From 5e25ba5003ee5de0ba2be56bfd54d16d4b1b028d Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 27 Aug 2013 05:46:32 -0700 Subject: tcp: TSO packets automatic sizing [ Upstream commits 6d36824e730f247b602c90e8715a792003e3c5a7, 02cf4ebd82ff0ac7254b88e466820a290ed8289a, and parts of 7eec4174ff29cd42f2acfae8112f51c228545d40 ] After hearing many people over past years complaining against TSO being bursty or even buggy, we are proud to present automatic sizing of TSO packets. One part of the problem is that tcp_tso_should_defer() uses an heuristic relying on upcoming ACKS instead of a timer, but more generally, having big TSO packets makes little sense for low rates, as it tends to create micro bursts on the network, and general consensus is to reduce the buffering amount. This patch introduces a per socket sk_pacing_rate, that approximates the current sending rate, and allows us to size the TSO packets so that we try to send one packet every ms. This field could be set by other transports. Patch has no impact for high speed flows, where having large TSO packets makes sense to reach line rate. For other flows, this helps better packet scheduling and ACK clocking. This patch increases performance of TCP flows in lossy environments. A new sysctl (tcp_min_tso_segs) is added, to specify the minimal size of a TSO packet (default being 2). A follow-up patch will provide a new packet scheduler (FQ), using sk_pacing_rate as an input to perform optional per flow pacing. This explains why we chose to set sk_pacing_rate to twice the current rate, allowing 'slow start' ramp up. sk_pacing_rate = 2 * cwnd * mss / srtt v2: Neal Cardwell reported a suspect deferring of last two segments on initial write of 10 MSS, I had to change tcp_tso_should_defer() to take into account tp->xmit_size_goal_segs Signed-off-by: Eric Dumazet Cc: Neal Cardwell Cc: Yuchung Cheng Cc: Van Jacobson Cc: Tom Herbert Acked-by: Yuchung Cheng Acked-by: Neal Cardwell Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- Documentation/networking/ip-sysctl.txt | 9 +++++++++ include/net/sock.h | 2 ++ include/net/tcp.h | 1 + net/core/sock.c | 1 + net/ipv4/sysctl_net_ipv4.c | 10 ++++++++++ net/ipv4/tcp.c | 28 +++++++++++++++++++++++----- net/ipv4/tcp_input.c | 34 +++++++++++++++++++++++++++++++++- net/ipv4/tcp_output.c | 2 +- 8 files changed, 80 insertions(+), 7 deletions(-) diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index 3458d6343e01..3994f0bbeeb6 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -478,6 +478,15 @@ tcp_syn_retries - INTEGER tcp_timestamps - BOOLEAN Enable timestamps as defined in RFC1323. +tcp_min_tso_segs - INTEGER + Minimal number of segments per TSO frame. + Since linux-3.12, TCP does an automatic sizing of TSO frames, + depending on flow rate, instead of filling 64Kbytes packets. + For specific usages, it's possible to force TCP to build big + TSO frames. Note that TCP stack might split too big TSO packets + if available window is too small. + Default: 2 + tcp_tso_win_divisor - INTEGER This allows control over what percentage of the congestion window can be consumed by a single TSO frame. diff --git a/include/net/sock.h b/include/net/sock.h index 66772cf8c3c5..cec4c723db9a 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -230,6 +230,7 @@ struct cg_proto; * @sk_wmem_queued: persistent queue size * @sk_forward_alloc: space allocated forward * @sk_allocation: allocation mode + * @sk_pacing_rate: Pacing rate (if supported by transport/packet scheduler) * @sk_sndbuf: size of send buffer in bytes * @sk_flags: %SO_LINGER (l_onoff), %SO_BROADCAST, %SO_KEEPALIVE, * %SO_OOBINLINE settings, %SO_TIMESTAMPING settings @@ -355,6 +356,7 @@ struct sock { kmemcheck_bitfield_end(flags); int sk_wmem_queued; gfp_t sk_allocation; + u32 sk_pacing_rate; /* bytes per second */ netdev_features_t sk_route_caps; netdev_features_t sk_route_nocaps; int sk_gso_type; diff --git a/include/net/tcp.h b/include/net/tcp.h index 5bba80fbd1d9..3fc77e90624a 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -287,6 +287,7 @@ extern int sysctl_tcp_thin_dupack; extern int sysctl_tcp_early_retrans; extern int sysctl_tcp_limit_output_bytes; extern int sysctl_tcp_challenge_ack_limit; +extern int sysctl_tcp_min_tso_segs; extern atomic_long_t tcp_memory_allocated; extern struct percpu_counter tcp_sockets_allocated; diff --git a/net/core/sock.c b/net/core/sock.c index d6d024cfaaaf..6565431b0e6d 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -2271,6 +2271,7 @@ void sock_init_data(struct socket *sock, struct sock *sk) sk->sk_stamp = ktime_set(-1L, 0); + sk->sk_pacing_rate = ~0U; /* * Before updating sk_refcnt, we must commit prior changes to memory * (Documentation/RCU/rculist_nulls.txt for details) diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index 3f25e75ae692..90b26beb84d4 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -29,6 +29,7 @@ static int zero; static int one = 1; static int four = 4; +static int gso_max_segs = GSO_MAX_SEGS; static int tcp_retr1_max = 255; static int ip_local_port_range_min[] = { 1, 1 }; static int ip_local_port_range_max[] = { 65535, 65535 }; @@ -752,6 +753,15 @@ static struct ctl_table ipv4_table[] = { .extra1 = &zero, .extra2 = &four, }, + { + .procname = "tcp_min_tso_segs", + .data = &sysctl_tcp_min_tso_segs, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, + .extra1 = &zero, + .extra2 = &gso_max_segs, + }, { .procname = "udp_mem", .data = &sysctl_udp_mem, diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 2b1b57f213b2..c888abf5a728 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -282,6 +282,8 @@ int sysctl_tcp_fin_timeout __read_mostly = TCP_FIN_TIMEOUT; +int sysctl_tcp_min_tso_segs __read_mostly = 2; + struct percpu_counter tcp_orphan_count; EXPORT_SYMBOL_GPL(tcp_orphan_count); @@ -786,12 +788,28 @@ static unsigned int tcp_xmit_size_goal(struct sock *sk, u32 mss_now, xmit_size_goal = mss_now; if (large_allowed && sk_can_gso(sk)) { - xmit_size_goal = ((sk->sk_gso_max_size - 1) - - inet_csk(sk)->icsk_af_ops->net_header_len - - inet_csk(sk)->icsk_ext_hdr_len - - tp->tcp_header_len); + u32 gso_size, hlen; + + /* Maybe we should/could use sk->sk_prot->max_header here ? */ + hlen = inet_csk(sk)->icsk_af_ops->net_header_len + + inet_csk(sk)->icsk_ext_hdr_len + + tp->tcp_header_len; + + /* Goal is to send at least one packet per ms, + * not one big TSO packet every 100 ms. + * This preserves ACK clocking and is consistent + * with tcp_tso_should_defer() heuristic. + */ + gso_size = sk->sk_pacing_rate / (2 * MSEC_PER_SEC); + gso_size = max_t(u32, gso_size, + sysctl_tcp_min_tso_segs * mss_now); + + xmit_size_goal = min_t(u32, gso_size, + sk->sk_gso_max_size - 1 - hlen); - /* TSQ : try to have two TSO segments in flight */ + /* TSQ : try to have at least two segments in flight + * (one in NIC TX ring, another in Qdisc) + */ xmit_size_goal = min_t(u32, xmit_size_goal, sysctl_tcp_limit_output_bytes >> 1); diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 4b75aad14b04..70883b87bc5d 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -699,6 +699,34 @@ static void tcp_rtt_estimator(struct sock *sk, const __u32 mrtt) } } +/* Set the sk_pacing_rate to allow proper sizing of TSO packets. + * Note: TCP stack does not yet implement pacing. + * FQ packet scheduler can be used to implement cheap but effective + * TCP pacing, to smooth the burst on large writes when packets + * in flight is significantly lower than cwnd (or rwin) + */ +static void tcp_update_pacing_rate(struct sock *sk) +{ + const struct tcp_sock *tp = tcp_sk(sk); + u64 rate; + + /* set sk_pacing_rate to 200 % of current rate (mss * cwnd / srtt) */ + rate = (u64)tp->mss_cache * 2 * (HZ << 3); + + rate *= max(tp->snd_cwnd, tp->packets_out); + + /* Correction for small srtt : minimum srtt being 8 (1 jiffy << 3), + * be conservative and assume srtt = 1 (125 us instead of 1.25 ms) + * We probably need usec resolution in the future. + * Note: This also takes care of possible srtt=0 case, + * when tcp_rtt_estimator() was not yet called. + */ + if (tp->srtt > 8 + 2) + do_div(rate, tp->srtt); + + sk->sk_pacing_rate = min_t(u64, rate, ~0U); +} + /* Calculate rto without backoff. This is the second half of Van Jacobson's * routine referred to above. */ @@ -3330,7 +3358,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) u32 ack_seq = TCP_SKB_CB(skb)->seq; u32 ack = TCP_SKB_CB(skb)->ack_seq; bool is_dupack = false; - u32 prior_in_flight; + u32 prior_in_flight, prior_cwnd = tp->snd_cwnd, prior_rtt = tp->srtt; u32 prior_fackets; int prior_packets = tp->packets_out; int prior_sacked = tp->sacked_out; @@ -3438,6 +3466,8 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) if (icsk->icsk_pending == ICSK_TIME_RETRANS) tcp_schedule_loss_probe(sk); + if (tp->srtt != prior_rtt || tp->snd_cwnd != prior_cwnd) + tcp_update_pacing_rate(sk); return 1; no_queue: @@ -5736,6 +5766,8 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, } else tcp_init_metrics(sk); + tcp_update_pacing_rate(sk); + /* Prevent spurious tcp_cwnd_restart() on * first data packet. */ diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 0145ce7e6098..400b811f5c06 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -1623,7 +1623,7 @@ static bool tcp_tso_should_defer(struct sock *sk, struct sk_buff *skb) /* If a full-sized TSO skb can be sent, do it. */ if (limit >= min_t(unsigned int, sk->sk_gso_max_size, - sk->sk_gso_max_segs * tp->mss_cache)) + tp->xmit_size_goal_segs * tp->mss_cache)) goto send_now; /* Middle in queue won't get any more data, full sendable already? */ -- cgit v1.2.3 From 0ae5f47eff2e543c3b94eec51c740f38a5071432 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 27 Sep 2013 03:28:54 -0700 Subject: tcp: TSQ can use a dynamic limit [ Upstream commit c9eeec26e32e087359160406f96e0949b3cc6f10 ] When TCP Small Queues was added, we used a sysctl to limit amount of packets queues on Qdisc/device queues for a given TCP flow. Problem is this limit is either too big for low rates, or too small for high rates. Now TCP stack has rate estimation in sk->sk_pacing_rate, and TSO auto sizing, it can better control number of packets in Qdisc/device queues. New limit is two packets or at least 1 to 2 ms worth of packets. Low rates flows benefit from this patch by having even smaller number of packets in queues, allowing for faster recovery, better RTT estimations. High rates flows benefit from this patch by allowing more than 2 packets in flight as we had reports this was a limiting factor to reach line rate. [ In particular if TX completion is delayed because of coalescing parameters ] Example for a single flow on 10Gbp link controlled by FQ/pacing 14 packets in flight instead of 2 $ tc -s -d qd qdisc fq 8001: dev eth0 root refcnt 32 limit 10000p flow_limit 100p buckets 1024 quantum 3028 initial_quantum 15140 Sent 1168459366606 bytes 771822841 pkt (dropped 0, overlimits 0 requeues 6822476) rate 9346Mbit 771713pps backlog 953820b 14p requeues 6822476 2047 flow, 2046 inactive, 1 throttled, delay 15673 ns 2372 gc, 0 highprio, 0 retrans, 9739249 throttled, 0 flows_plimit Note that sk_pacing_rate is currently set to twice the actual rate, but this might be refined in the future when a flow is in congestion avoidance. Additional change : skb->destructor should be set to tcp_wfree(). A future patch (for linux 3.13+) might remove tcp_limit_output_bytes Signed-off-by: Eric Dumazet Cc: Wei Liu Cc: Cong Wang Cc: Yuchung Cheng Cc: Neal Cardwell Acked-by: Neal Cardwell Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/tcp_output.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 400b811f5c06..3bb2f8c5e619 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -887,8 +887,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, skb_orphan(skb); skb->sk = sk; - skb->destructor = (sysctl_tcp_limit_output_bytes > 0) ? - tcp_wfree : sock_wfree; + skb->destructor = tcp_wfree; atomic_add(skb->truesize, &sk->sk_wmem_alloc); /* Build TCP header and checksum it. */ @@ -1832,7 +1831,6 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle, while ((skb = tcp_send_head(sk))) { unsigned int limit; - tso_segs = tcp_init_tso_segs(sk, skb, mss_now); BUG_ON(!tso_segs); @@ -1861,13 +1859,20 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle, break; } - /* TSQ : sk_wmem_alloc accounts skb truesize, - * including skb overhead. But thats OK. + /* TCP Small Queues : + * Control number of packets in qdisc/devices to two packets / or ~1 ms. + * This allows for : + * - better RTT estimation and ACK scheduling + * - faster recovery + * - high rates */ - if (atomic_read(&sk->sk_wmem_alloc) >= sysctl_tcp_limit_output_bytes) { + limit = max(skb->truesize, sk->sk_pacing_rate >> 10); + + if (atomic_read(&sk->sk_wmem_alloc) > limit) { set_bit(TSQ_THROTTLED, &tp->tsq_flags); break; } + limit = mss_now; if (tso_segs > 1 && !tcp_urg_mode(tp)) limit = tcp_mss_split_point(sk, skb, mss_now, -- cgit v1.2.3 From b81908e15f548e385598beaf17376cd101f36bc8 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 15 Oct 2013 11:54:30 -0700 Subject: tcp: must unclone packets before mangling them [ Upstream commit c52e2421f7368fd36cbe330d2cf41b10452e39a9 ] TCP stack should make sure it owns skbs before mangling them. We had various crashes using bnx2x, and it turned out gso_size was cleared right before bnx2x driver was populating TC descriptor of the _previous_ packet send. TCP stack can sometime retransmit packets that are still in Qdisc. Of course we could make bnx2x driver more robust (using ACCESS_ONCE(shinfo->gso_size) for example), but the bug is TCP stack. We have identified two points where skb_unclone() was needed. This patch adds a WARN_ON_ONCE() to warn us if we missed another fix of this kind. Kudos to Neal for finding the root cause of this bug. Its visible using small MSS. Signed-off-by: Eric Dumazet Signed-off-by: Neal Cardwell Cc: Yuchung Cheng Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/tcp_output.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 3bb2f8c5e619..cd16eb06bebf 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -976,6 +976,9 @@ static void tcp_queue_skb(struct sock *sk, struct sk_buff *skb) static void tcp_set_skb_tso_segs(const struct sock *sk, struct sk_buff *skb, unsigned int mss_now) { + /* Make sure we own this skb before messing gso_size/gso_segs */ + WARN_ON_ONCE(skb_cloned(skb)); + if (skb->len <= mss_now || !sk_can_gso(sk) || skb->ip_summed == CHECKSUM_NONE) { /* Avoid the costly divide in the normal @@ -1057,9 +1060,7 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, if (nsize < 0) nsize = 0; - if (skb_cloned(skb) && - skb_is_nonlinear(skb) && - pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) + if (skb_unclone(skb, GFP_ATOMIC)) return -ENOMEM; /* Get a new skb... force flag on. */ @@ -2334,6 +2335,8 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) int oldpcount = tcp_skb_pcount(skb); if (unlikely(oldpcount > 1)) { + if (skb_unclone(skb, GFP_ATOMIC)) + return -ENOMEM; tcp_init_tso_segs(sk, skb, cur_mss); tcp_adjust_pcount(sk, skb, oldpcount - tcp_skb_pcount(skb)); } -- cgit v1.2.3 From a50b0399e6899e39e6f74431aaddf12ee92db854 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 4 Oct 2013 10:31:41 -0700 Subject: tcp: do not forget FIN in tcp_shifted_skb() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 5e8a402f831dbe7ee831340a91439e46f0d38acd ] Yuchung found following problem : There are bugs in the SACK processing code, merging part in tcp_shift_skb_data(), that incorrectly resets or ignores the sacked skbs FIN flag. When a receiver first SACK the FIN sequence, and later throw away ofo queue (e.g., sack-reneging), the sender will stop retransmitting the FIN flag, and hangs forever. Following packetdrill test can be used to reproduce the bug. $ cat sack-merge-bug.pkt `sysctl -q net.ipv4.tcp_fack=0` // Establish a connection and send 10 MSS. 0.000 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3 +.000 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 +.000 bind(3, ..., ...) = 0 +.000 listen(3, 1) = 0 +.050 < S 0:0(0) win 32792 +.000 > S. 0:0(0) ack 1 +.001 < . 1:1(0) ack 1 win 1024 +.000 accept(3, ..., ...) = 4 +.100 write(4, ..., 12000) = 12000 +.000 shutdown(4, SHUT_WR) = 0 +.000 > . 1:10001(10000) ack 1 +.050 < . 1:1(0) ack 2001 win 257 +.000 > FP. 10001:12001(2000) ack 1 +.050 < . 1:1(0) ack 2001 win 257 +.050 < . 1:1(0) ack 2001 win 257 // SACK reneg +.050 < . 1:1(0) ack 12001 win 257 +0 %{ print "unacked: ",tcpi_unacked }% +5 %{ print "" }% First, a typo inverted left/right of one OR operation, then code forgot to advance end_seq if the merged skb carried FIN. Bug was added in 2.6.29 by commit 832d11c5cd076ab ("tcp: Try to restore large SKBs while SACK processing") Signed-off-by: Eric Dumazet Signed-off-by: Yuchung Cheng Acked-by: Neal Cardwell Cc: Ilpo Järvinen Acked-by: Ilpo Järvinen Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/tcp_input.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 70883b87bc5d..0ae7da7ff505 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -1292,7 +1292,10 @@ static bool tcp_shifted_skb(struct sock *sk, struct sk_buff *skb, tp->lost_cnt_hint -= tcp_skb_pcount(prev); } - TCP_SKB_CB(skb)->tcp_flags |= TCP_SKB_CB(prev)->tcp_flags; + TCP_SKB_CB(prev)->tcp_flags |= TCP_SKB_CB(skb)->tcp_flags; + if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN) + TCP_SKB_CB(prev)->end_seq++; + if (skb == tcp_highest_sack(sk)) tcp_advance_highest_sack(sk, skb); -- cgit v1.2.3 From d8ac0f178f98d4e7c23cf9526d789d4869ec6e4c Mon Sep 17 00:00:00 2001 From: Yuchung Cheng Date: Sat, 12 Oct 2013 10:16:27 -0700 Subject: tcp: fix incorrect ca_state in tail loss probe [ Upstream commit 031afe4990a7c9dbff41a3a742c44d3e740ea0a1 ] On receiving an ACK that covers the loss probe sequence, TLP immediately sets the congestion state to Open, even though some packets are not recovered and retransmisssion are on the way. The later ACks may trigger a WARN_ON check in step D of tcp_fastretrans_alert(), e.g., https://bugzilla.redhat.com/show_bug.cgi?id=989251 The fix is to follow the similar procedure in recovery by calling tcp_try_keep_open(). The sender switches to Open state if no packets are retransmissted. Otherwise it goes to Disorder and let subsequent ACKs move the state to Recovery or Open. Reported-By: Michael Sterrett Tested-By: Dormando Signed-off-by: Yuchung Cheng Acked-by: Neal Cardwell Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/tcp_input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 0ae7da7ff505..e15d330919af 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -3345,7 +3345,7 @@ static void tcp_process_tlp_ack(struct sock *sk, u32 ack, int flag) tcp_init_cwnd_reduction(sk, true); tcp_set_ca_state(sk, TCP_CA_CWR); tcp_end_cwnd_reduction(sk); - tcp_set_ca_state(sk, TCP_CA_Open); + tcp_try_keep_open(sk); NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPLOSSPROBERECOVERY); } -- cgit v1.2.3 From 53d384ae6a01eadb8d362afaca6a9c0ba72c1126 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 1 Oct 2013 21:04:11 -0700 Subject: net: do not call sock_put() on TIMEWAIT sockets [ Upstream commit 80ad1d61e72d626e30ebe8529a0455e660ca4693 ] commit 3ab5aee7fe84 ("net: Convert TCP & DCCP hash tables to use RCU / hlist_nulls") incorrectly used sock_put() on TIMEWAIT sockets. We should instead use inet_twsk_put() Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/inet_hashtables.c | 2 +- net/ipv6/inet6_hashtables.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index 6af375afeeef..c95848d00039 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c @@ -287,7 +287,7 @@ begintw: if (unlikely(!INET_TW_MATCH(sk, net, acookie, saddr, daddr, ports, dif))) { - sock_put(sk); + inet_twsk_put(inet_twsk(sk)); goto begintw; } goto out; diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c index 32b4a1675d82..066640e0ba8e 100644 --- a/net/ipv6/inet6_hashtables.c +++ b/net/ipv6/inet6_hashtables.c @@ -116,7 +116,7 @@ begintw: } if (unlikely(!INET6_TW_MATCH(sk, net, saddr, daddr, ports, dif))) { - sock_put(sk); + inet_twsk_put(inet_twsk(sk)); goto begintw; } goto out; -- cgit v1.2.3 From bd83cd77073e5c54a88f976d6d6c785a1a80b0c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20CACHEREUL?= Date: Wed, 2 Oct 2013 10:16:02 +0200 Subject: l2tp: fix kernel panic when using IPv4-mapped IPv6 addresses MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit e18503f41f9b12132c95d7c31ca6ee5155e44e5c ] IPv4 mapped addresses cause kernel panic. The patch juste check whether the IPv6 address is an IPv4 mapped address. If so, use IPv4 API instead of IPv6. [ 940.026915] general protection fault: 0000 [#1] [ 940.026915] Modules linked in: l2tp_ppp l2tp_netlink l2tp_core pppox ppp_generic slhc loop psmouse [ 940.026915] CPU: 0 PID: 3184 Comm: memcheck-amd64- Not tainted 3.11.0+ #1 [ 940.026915] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2007 [ 940.026915] task: ffff880007130e20 ti: ffff88000737e000 task.ti: ffff88000737e000 [ 940.026915] RIP: 0010:[] [] ip6_xmit+0x276/0x326 [ 940.026915] RSP: 0018:ffff88000737fd28 EFLAGS: 00010286 [ 940.026915] RAX: c748521a75ceff48 RBX: ffff880000c30800 RCX: 0000000000000000 [ 940.026915] RDX: ffff88000075cc4e RSI: 0000000000000028 RDI: ffff8800060e5a40 [ 940.026915] RBP: ffff8800060e5a40 R08: 0000000000000000 R09: ffff88000075cc90 [ 940.026915] R10: 0000000000000000 R11: 0000000000000000 R12: ffff88000737fda0 [ 940.026915] R13: 0000000000000000 R14: 0000000000002000 R15: ffff880005d3b580 [ 940.026915] FS: 00007f163dc5e800(0000) GS:ffffffff81623000(0000) knlGS:0000000000000000 [ 940.026915] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 940.026915] CR2: 00000004032dc940 CR3: 0000000005c25000 CR4: 00000000000006f0 [ 940.026915] Stack: [ 940.026915] ffff88000075cc4e ffffffff81694e90 ffff880000c30b38 0000000000000020 [ 940.026915] 11000000523c4bac ffff88000737fdb4 0000000000000000 ffff880000c30800 [ 940.026915] ffff880005d3b580 ffff880000c30b38 ffff8800060e5a40 0000000000000020 [ 940.026915] Call Trace: [ 940.026915] [] ? inet6_csk_xmit+0xa4/0xc4 [ 940.026915] [] ? l2tp_xmit_skb+0x503/0x55a [l2tp_core] [ 940.026915] [] ? pskb_expand_head+0x161/0x214 [ 940.026915] [] ? pppol2tp_xmit+0xf2/0x143 [l2tp_ppp] [ 940.026915] [] ? ppp_channel_push+0x36/0x8b [ppp_generic] [ 940.026915] [] ? ppp_write+0xaf/0xc5 [ppp_generic] [ 940.026915] [] ? vfs_write+0xa2/0x106 [ 940.026915] [] ? SyS_write+0x56/0x8a [ 940.026915] [] ? system_call_fastpath+0x16/0x1b [ 940.026915] Code: 00 49 8b 8f d8 00 00 00 66 83 7c 11 02 00 74 60 49 8b 47 58 48 83 e0 fe 48 8b 80 18 01 00 00 48 85 c0 74 13 48 8b 80 78 02 00 00 <48> ff 40 28 41 8b 57 68 48 01 50 30 48 8b 54 24 08 49 c7 c1 51 [ 940.026915] RIP [] ip6_xmit+0x276/0x326 [ 940.026915] RSP [ 940.057945] ---[ end trace be8aba9a61c8b7f3 ]--- [ 940.058583] Kernel panic - not syncing: Fatal exception in interrupt Signed-off-by: François CACHEREUL Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/l2tp/l2tp_core.c | 27 +++++++++++++++++++++++---- net/l2tp/l2tp_core.h | 3 +++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index 6984c3a353cd..522a5c4c77fe 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c @@ -499,6 +499,7 @@ out: static inline int l2tp_verify_udp_checksum(struct sock *sk, struct sk_buff *skb) { + struct l2tp_tunnel *tunnel = (struct l2tp_tunnel *)sk->sk_user_data; struct udphdr *uh = udp_hdr(skb); u16 ulen = ntohs(uh->len); __wsum psum; @@ -507,7 +508,7 @@ static inline int l2tp_verify_udp_checksum(struct sock *sk, return 0; #if IS_ENABLED(CONFIG_IPV6) - if (sk->sk_family == PF_INET6) { + if (sk->sk_family == PF_INET6 && !tunnel->v4mapped) { if (!uh->check) { LIMIT_NETDEBUG(KERN_INFO "L2TP: IPv6: checksum is 0\n"); return 1; @@ -1071,7 +1072,7 @@ static int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb, /* Queue the packet to IP for output */ skb->local_df = 1; #if IS_ENABLED(CONFIG_IPV6) - if (skb->sk->sk_family == PF_INET6) + if (skb->sk->sk_family == PF_INET6 && !tunnel->v4mapped) error = inet6_csk_xmit(skb, NULL); else #endif @@ -1198,7 +1199,7 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len /* Calculate UDP checksum if configured to do so */ #if IS_ENABLED(CONFIG_IPV6) - if (sk->sk_family == PF_INET6) + if (sk->sk_family == PF_INET6 && !tunnel->v4mapped) l2tp_xmit_ipv6_csum(sk, skb, udp_len); else #endif @@ -1647,6 +1648,24 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32 if (cfg != NULL) tunnel->debug = cfg->debug; +#if IS_ENABLED(CONFIG_IPV6) + if (sk->sk_family == PF_INET6) { + struct ipv6_pinfo *np = inet6_sk(sk); + + if (ipv6_addr_v4mapped(&np->saddr) && + ipv6_addr_v4mapped(&np->daddr)) { + struct inet_sock *inet = inet_sk(sk); + + tunnel->v4mapped = true; + inet->inet_saddr = np->saddr.s6_addr32[3]; + inet->inet_rcv_saddr = np->rcv_saddr.s6_addr32[3]; + inet->inet_daddr = np->daddr.s6_addr32[3]; + } else { + tunnel->v4mapped = false; + } + } +#endif + /* Mark socket as an encapsulation socket. See net/ipv4/udp.c */ tunnel->encap = encap; if (encap == L2TP_ENCAPTYPE_UDP) { @@ -1655,7 +1674,7 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32 udp_sk(sk)->encap_rcv = l2tp_udp_encap_recv; udp_sk(sk)->encap_destroy = l2tp_udp_encap_destroy; #if IS_ENABLED(CONFIG_IPV6) - if (sk->sk_family == PF_INET6) + if (sk->sk_family == PF_INET6 && !tunnel->v4mapped) udpv6_encap_enable(); else #endif diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h index 485a490fd990..2f89d43877d7 100644 --- a/net/l2tp/l2tp_core.h +++ b/net/l2tp/l2tp_core.h @@ -189,6 +189,9 @@ struct l2tp_tunnel { struct sock *sock; /* Parent socket */ int fd; /* Parent fd, if tunnel socket * was created by userspace */ +#if IS_ENABLED(CONFIG_IPV6) + bool v4mapped; +#endif struct work_struct del_work; -- cgit v1.2.3 From d980ed627b35d4685a4a27561dc3fc7a09226dab Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 8 Oct 2013 15:44:26 -0400 Subject: l2tp: Fix build warning with ipv6 disabled. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 8d8a51e26a6d415e1470759f2cf5f3ee3ee86196 ] net/l2tp/l2tp_core.c: In function ‘l2tp_verify_udp_checksum’: net/l2tp/l2tp_core.c:499:22: warning: unused variable ‘tunnel’ [-Wunused-variable] Create a helper "l2tp_tunnel()" to facilitate this, and as a side effect get rid of a bunch of unnecessary void pointer casts. Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/l2tp/l2tp_core.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index 522a5c4c77fe..8c27de2b4d5a 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c @@ -115,6 +115,11 @@ struct l2tp_net { static void l2tp_session_set_header_len(struct l2tp_session *session, int version); static void l2tp_tunnel_free(struct l2tp_tunnel *tunnel); +static inline struct l2tp_tunnel *l2tp_tunnel(struct sock *sk) +{ + return sk->sk_user_data; +} + static inline struct l2tp_net *l2tp_pernet(struct net *net) { BUG_ON(!net); @@ -499,7 +504,6 @@ out: static inline int l2tp_verify_udp_checksum(struct sock *sk, struct sk_buff *skb) { - struct l2tp_tunnel *tunnel = (struct l2tp_tunnel *)sk->sk_user_data; struct udphdr *uh = udp_hdr(skb); u16 ulen = ntohs(uh->len); __wsum psum; @@ -508,7 +512,7 @@ static inline int l2tp_verify_udp_checksum(struct sock *sk, return 0; #if IS_ENABLED(CONFIG_IPV6) - if (sk->sk_family == PF_INET6 && !tunnel->v4mapped) { + if (sk->sk_family == PF_INET6 && !l2tp_tunnel(sk)->v4mapped) { if (!uh->check) { LIMIT_NETDEBUG(KERN_INFO "L2TP: IPv6: checksum is 0\n"); return 1; @@ -1248,10 +1252,9 @@ EXPORT_SYMBOL_GPL(l2tp_xmit_skb); */ static void l2tp_tunnel_destruct(struct sock *sk) { - struct l2tp_tunnel *tunnel; + struct l2tp_tunnel *tunnel = l2tp_tunnel(sk); struct l2tp_net *pn; - tunnel = sk->sk_user_data; if (tunnel == NULL) goto end; @@ -1619,7 +1622,7 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32 } /* Check if this socket has already been prepped */ - tunnel = (struct l2tp_tunnel *)sk->sk_user_data; + tunnel = l2tp_tunnel(sk); if (tunnel != NULL) { /* This socket has already been prepped */ err = -EBUSY; -- cgit v1.2.3 From 85cd02136ded01747a7959567aa1626627f1877e Mon Sep 17 00:00:00 2001 From: Sebastian Hesselbarth Date: Wed, 2 Oct 2013 12:57:20 +0200 Subject: net: mv643xx_eth: update statistics timer from timer context only [ Upstream commit 041b4ddb84989f06ff1df0ca869b950f1ee3cb1c ] Each port driver installs a periodic timer to update port statistics by calling mib_counters_update. As mib_counters_update is also called from non-timer context, we should not reschedule the timer there but rather move it to timer-only context. Signed-off-by: Sebastian Hesselbarth Acked-by: Jason Cooper Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/marvell/mv643xx_eth.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c index d1cbfb12c1ca..199a738bb28c 100644 --- a/drivers/net/ethernet/marvell/mv643xx_eth.c +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c @@ -1125,15 +1125,13 @@ static void mib_counters_update(struct mv643xx_eth_private *mp) p->rx_discard += rdlp(mp, RX_DISCARD_FRAME_CNT); p->rx_overrun += rdlp(mp, RX_OVERRUN_FRAME_CNT); spin_unlock_bh(&mp->mib_counters_lock); - - mod_timer(&mp->mib_counters_timer, jiffies + 30 * HZ); } static void mib_counters_timer_wrapper(unsigned long _mp) { struct mv643xx_eth_private *mp = (void *)_mp; - mib_counters_update(mp); + mod_timer(&mp->mib_counters_timer, jiffies + 30 * HZ); } -- cgit v1.2.3 From b24b4a82fc96f74d848275c8f1b33df66cbef061 Mon Sep 17 00:00:00 2001 From: Sebastian Hesselbarth Date: Wed, 2 Oct 2013 12:57:21 +0200 Subject: net: mv643xx_eth: fix orphaned statistics timer crash [ Upstream commit f564412c935111c583b787bcc18157377b208e2e ] The periodic statistics timer gets started at port _probe() time, but is stopped on _stop() only. In a modular environment, this can cause the timer to access already deallocated memory, if the module is unloaded without starting the eth device. To fix this, we add the timer right before the port is started, instead of at _probe() time. Signed-off-by: Sebastian Hesselbarth Acked-by: Jason Cooper Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/marvell/mv643xx_eth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c index 199a738bb28c..4be11ff516a0 100644 --- a/drivers/net/ethernet/marvell/mv643xx_eth.c +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c @@ -2229,6 +2229,7 @@ static int mv643xx_eth_open(struct net_device *dev) mp->int_mask |= INT_TX_END_0 << i; } + add_timer(&mp->mib_counters_timer); port_start(mp); wrlp(mp, INT_MASK_EXT, INT_EXT_LINK_PHY | INT_EXT_TX); @@ -2737,7 +2738,6 @@ static int mv643xx_eth_probe(struct platform_device *pdev) mp->mib_counters_timer.data = (unsigned long)mp; mp->mib_counters_timer.function = mib_counters_timer_wrapper; mp->mib_counters_timer.expires = jiffies + 30 * HZ; - add_timer(&mp->mib_counters_timer); spin_lock_init(&mp->mib_counters_lock); -- cgit v1.2.3 From 2e8d97ab1f1236d08a8576d5c4b25d3180ff01f6 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 3 Oct 2013 00:27:20 +0300 Subject: net: heap overflow in __audit_sockaddr() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 1661bf364ae9c506bc8795fef70d1532931be1e8 ] We need to cap ->msg_namelen or it leads to a buffer overflow when we to the memcpy() in __audit_sockaddr(). It requires CAP_AUDIT_CONTROL to exploit this bug. The call tree is: ___sys_recvmsg() move_addr_to_user() audit_sockaddr() __audit_sockaddr() Reported-by: Jüri Aedla Signed-off-by: Dan Carpenter Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/compat.c | 2 ++ net/socket.c | 24 ++++++++++++++++++++---- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/net/compat.c b/net/compat.c index f0a1ba6c8086..89032580bd1d 100644 --- a/net/compat.c +++ b/net/compat.c @@ -71,6 +71,8 @@ int get_compat_msghdr(struct msghdr *kmsg, struct compat_msghdr __user *umsg) __get_user(kmsg->msg_controllen, &umsg->msg_controllen) || __get_user(kmsg->msg_flags, &umsg->msg_flags)) return -EFAULT; + if (kmsg->msg_namelen > sizeof(struct sockaddr_storage)) + return -EINVAL; kmsg->msg_name = compat_ptr(tmp1); kmsg->msg_iov = compat_ptr(tmp2); kmsg->msg_control = compat_ptr(tmp3); diff --git a/net/socket.c b/net/socket.c index 4ca1526db756..9c467b2afc84 100644 --- a/net/socket.c +++ b/net/socket.c @@ -1956,6 +1956,16 @@ struct used_address { unsigned int name_len; }; +static int copy_msghdr_from_user(struct msghdr *kmsg, + struct msghdr __user *umsg) +{ + if (copy_from_user(kmsg, umsg, sizeof(struct msghdr))) + return -EFAULT; + if (kmsg->msg_namelen > sizeof(struct sockaddr_storage)) + return -EINVAL; + return 0; +} + static int ___sys_sendmsg(struct socket *sock, struct msghdr __user *msg, struct msghdr *msg_sys, unsigned int flags, struct used_address *used_address) @@ -1974,8 +1984,11 @@ static int ___sys_sendmsg(struct socket *sock, struct msghdr __user *msg, if (MSG_CMSG_COMPAT & flags) { if (get_compat_msghdr(msg_sys, msg_compat)) return -EFAULT; - } else if (copy_from_user(msg_sys, msg, sizeof(struct msghdr))) - return -EFAULT; + } else { + err = copy_msghdr_from_user(msg_sys, msg); + if (err) + return err; + } if (msg_sys->msg_iovlen > UIO_FASTIOV) { err = -EMSGSIZE; @@ -2183,8 +2196,11 @@ static int ___sys_recvmsg(struct socket *sock, struct msghdr __user *msg, if (MSG_CMSG_COMPAT & flags) { if (get_compat_msghdr(msg_sys, msg_compat)) return -EFAULT; - } else if (copy_from_user(msg_sys, msg, sizeof(struct msghdr))) - return -EFAULT; + } else { + err = copy_msghdr_from_user(msg_sys, msg); + if (err) + return err; + } if (msg_sys->msg_iovlen > UIO_FASTIOV) { err = -EMSGSIZE; -- cgit v1.2.3 From df6ae0dc3145f5d3c0b04a59e64cd647469881e4 Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Mon, 30 Sep 2013 22:03:06 +0200 Subject: proc connector: fix info leaks [ Upstream commit e727ca82e0e9616ab4844301e6bae60ca7327682 ] Initialize event_data for all possible message types to prevent leaking kernel stack contents to userland (up to 20 bytes). Also set the flags member of the connector message to 0 to prevent leaking two more stack bytes this way. Signed-off-by: Mathias Krause Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/connector/cn_proc.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c index 08ae128cce9b..c73fc2b74de2 100644 --- a/drivers/connector/cn_proc.c +++ b/drivers/connector/cn_proc.c @@ -65,6 +65,7 @@ void proc_fork_connector(struct task_struct *task) msg = (struct cn_msg *)buffer; ev = (struct proc_event *)msg->data; + memset(&ev->event_data, 0, sizeof(ev->event_data)); get_seq(&msg->seq, &ev->cpu); ktime_get_ts(&ts); /* get high res monotonic timestamp */ put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); @@ -80,6 +81,7 @@ void proc_fork_connector(struct task_struct *task) memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); msg->ack = 0; /* not used */ msg->len = sizeof(*ev); + msg->flags = 0; /* not used */ /* If cn_netlink_send() failed, the data is not sent */ cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); } @@ -96,6 +98,7 @@ void proc_exec_connector(struct task_struct *task) msg = (struct cn_msg *)buffer; ev = (struct proc_event *)msg->data; + memset(&ev->event_data, 0, sizeof(ev->event_data)); get_seq(&msg->seq, &ev->cpu); ktime_get_ts(&ts); /* get high res monotonic timestamp */ put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); @@ -106,6 +109,7 @@ void proc_exec_connector(struct task_struct *task) memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); msg->ack = 0; /* not used */ msg->len = sizeof(*ev); + msg->flags = 0; /* not used */ cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); } @@ -122,6 +126,7 @@ void proc_id_connector(struct task_struct *task, int which_id) msg = (struct cn_msg *)buffer; ev = (struct proc_event *)msg->data; + memset(&ev->event_data, 0, sizeof(ev->event_data)); ev->what = which_id; ev->event_data.id.process_pid = task->pid; ev->event_data.id.process_tgid = task->tgid; @@ -145,6 +150,7 @@ void proc_id_connector(struct task_struct *task, int which_id) memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); msg->ack = 0; /* not used */ msg->len = sizeof(*ev); + msg->flags = 0; /* not used */ cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); } @@ -160,6 +166,7 @@ void proc_sid_connector(struct task_struct *task) msg = (struct cn_msg *)buffer; ev = (struct proc_event *)msg->data; + memset(&ev->event_data, 0, sizeof(ev->event_data)); get_seq(&msg->seq, &ev->cpu); ktime_get_ts(&ts); /* get high res monotonic timestamp */ put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); @@ -170,6 +177,7 @@ void proc_sid_connector(struct task_struct *task) memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); msg->ack = 0; /* not used */ msg->len = sizeof(*ev); + msg->flags = 0; /* not used */ cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); } @@ -185,6 +193,7 @@ void proc_ptrace_connector(struct task_struct *task, int ptrace_id) msg = (struct cn_msg *)buffer; ev = (struct proc_event *)msg->data; + memset(&ev->event_data, 0, sizeof(ev->event_data)); get_seq(&msg->seq, &ev->cpu); ktime_get_ts(&ts); /* get high res monotonic timestamp */ put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); @@ -203,6 +212,7 @@ void proc_ptrace_connector(struct task_struct *task, int ptrace_id) memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); msg->ack = 0; /* not used */ msg->len = sizeof(*ev); + msg->flags = 0; /* not used */ cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); } @@ -218,6 +228,7 @@ void proc_comm_connector(struct task_struct *task) msg = (struct cn_msg *)buffer; ev = (struct proc_event *)msg->data; + memset(&ev->event_data, 0, sizeof(ev->event_data)); get_seq(&msg->seq, &ev->cpu); ktime_get_ts(&ts); /* get high res monotonic timestamp */ put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); @@ -229,6 +240,7 @@ void proc_comm_connector(struct task_struct *task) memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); msg->ack = 0; /* not used */ msg->len = sizeof(*ev); + msg->flags = 0; /* not used */ cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); } @@ -244,6 +256,7 @@ void proc_coredump_connector(struct task_struct *task) msg = (struct cn_msg *)buffer; ev = (struct proc_event *)msg->data; + memset(&ev->event_data, 0, sizeof(ev->event_data)); get_seq(&msg->seq, &ev->cpu); ktime_get_ts(&ts); /* get high res monotonic timestamp */ put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); @@ -254,6 +267,7 @@ void proc_coredump_connector(struct task_struct *task) memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); msg->ack = 0; /* not used */ msg->len = sizeof(*ev); + msg->flags = 0; /* not used */ cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); } @@ -269,6 +283,7 @@ void proc_exit_connector(struct task_struct *task) msg = (struct cn_msg *)buffer; ev = (struct proc_event *)msg->data; + memset(&ev->event_data, 0, sizeof(ev->event_data)); get_seq(&msg->seq, &ev->cpu); ktime_get_ts(&ts); /* get high res monotonic timestamp */ put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); @@ -281,6 +296,7 @@ void proc_exit_connector(struct task_struct *task) memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); msg->ack = 0; /* not used */ msg->len = sizeof(*ev); + msg->flags = 0; /* not used */ cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); } @@ -304,6 +320,7 @@ static void cn_proc_ack(int err, int rcvd_seq, int rcvd_ack) msg = (struct cn_msg *)buffer; ev = (struct proc_event *)msg->data; + memset(&ev->event_data, 0, sizeof(ev->event_data)); msg->seq = rcvd_seq; ktime_get_ts(&ts); /* get high res monotonic timestamp */ put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); @@ -313,6 +330,7 @@ static void cn_proc_ack(int err, int rcvd_seq, int rcvd_ack) memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); msg->ack = rcvd_ack + 1; msg->len = sizeof(*ev); + msg->flags = 0; /* not used */ cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); } -- cgit v1.2.3 From b15e22da6eb11f54ef53bec9b9e9adbc4fba1609 Mon Sep 17 00:00:00 2001 From: Jiri Benc Date: Fri, 4 Oct 2013 17:04:48 +0200 Subject: ipv4: fix ineffective source address selection [ Upstream commit 0a7e22609067ff524fc7bbd45c6951dd08561667 ] When sending out multicast messages, the source address in inet->mc_addr is ignored and rewritten by an autoselected one. This is caused by a typo in commit 813b3b5db831 ("ipv4: Use caller's on-stack flowi as-is in output route lookups"). Signed-off-by: Jiri Benc Acked-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/route.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index d35bbf0cf404..d11e73ce9365 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -2020,7 +2020,7 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4) RT_SCOPE_LINK); goto make_route; } - if (fl4->saddr) { + if (!fl4->saddr) { if (ipv4_is_multicast(fl4->daddr)) fl4->saddr = inet_select_addr(dev_out, 0, fl4->flowi4_scope); -- cgit v1.2.3 From 42fc155b9fe58a8885b76136ebdb7b5e376740b6 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Sat, 5 Oct 2013 21:25:17 +0200 Subject: can: dev: fix nlmsg size calculation in can_get_size() [ Upstream commit fe119a05f8ca481623a8d02efcc984332e612528 ] This patch fixes the calculation of the nlmsg size, by adding the missing nla_total_size(). Signed-off-by: Marc Kleine-Budde Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/can/dev.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c index f9cba4123c66..1870c4731a57 100644 --- a/drivers/net/can/dev.c +++ b/drivers/net/can/dev.c @@ -705,14 +705,14 @@ static size_t can_get_size(const struct net_device *dev) size_t size; size = nla_total_size(sizeof(u32)); /* IFLA_CAN_STATE */ - size += sizeof(struct can_ctrlmode); /* IFLA_CAN_CTRLMODE */ + size += nla_total_size(sizeof(struct can_ctrlmode)); /* IFLA_CAN_CTRLMODE */ size += nla_total_size(sizeof(u32)); /* IFLA_CAN_RESTART_MS */ - size += sizeof(struct can_bittiming); /* IFLA_CAN_BITTIMING */ - size += sizeof(struct can_clock); /* IFLA_CAN_CLOCK */ + size += nla_total_size(sizeof(struct can_bittiming)); /* IFLA_CAN_BITTIMING */ + size += nla_total_size(sizeof(struct can_clock)); /* IFLA_CAN_CLOCK */ if (priv->do_get_berr_counter) /* IFLA_CAN_BERR_COUNTER */ - size += sizeof(struct can_berr_counter); + size += nla_total_size(sizeof(struct can_berr_counter)); if (priv->bittiming_const) /* IFLA_CAN_BITTIMING_CONST */ - size += sizeof(struct can_bittiming_const); + size += nla_total_size(sizeof(struct can_bittiming_const)); return size; } -- cgit v1.2.3 From b9396c4c9e7f499b1dd8080e901c88705f2efa99 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Sat, 5 Oct 2013 17:56:59 -0300 Subject: net: secure_seq: Fix warning when CONFIG_IPV6 and CONFIG_INET are not selected [ Upstream commit cb03db9d0e964568407fb08ea46cc2b6b7f67587 ] net_secret() is only used when CONFIG_IPV6 or CONFIG_INET are selected. Building a defconfig with both of these symbols unselected (Using the ARM at91sam9rl_defconfig, for example) leads to the following build warning: $ make at91sam9rl_defconfig # # configuration written to .config # $ make net/core/secure_seq.o scripts/kconfig/conf --silentoldconfig Kconfig CHK include/config/kernel.release CHK include/generated/uapi/linux/version.h CHK include/generated/utsrelease.h make[1]: `include/generated/mach-types.h' is up to date. CALL scripts/checksyscalls.sh CC net/core/secure_seq.o net/core/secure_seq.c:17:13: warning: 'net_secret_init' defined but not used [-Wunused-function] Fix this warning by protecting the definition of net_secret() with these symbols. Reported-by: Olof Johansson Signed-off-by: Fabio Estevam Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/secure_seq.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/core/secure_seq.c b/net/core/secure_seq.c index 3f1ec1586ae1..8d9d05edd2eb 100644 --- a/net/core/secure_seq.c +++ b/net/core/secure_seq.c @@ -10,6 +10,7 @@ #include +#if IS_ENABLED(CONFIG_IPV6) || IS_ENABLED(CONFIG_INET) #define NET_SECRET_SIZE (MD5_MESSAGE_BYTES / 4) static u32 net_secret[NET_SECRET_SIZE] ____cacheline_aligned; @@ -29,6 +30,7 @@ static void net_secret_init(void) cmpxchg(&net_secret[--i], 0, tmp); } } +#endif #ifdef CONFIG_INET static u32 seq_scale(u32 seq) -- cgit v1.2.3 From f495ddc46f97dd0054ff2d5d3c7493d59f7511fb Mon Sep 17 00:00:00 2001 From: Paul Durrant Date: Tue, 8 Oct 2013 14:22:56 +0100 Subject: xen-netback: Don't destroy the netdev until the vif is shut down [ upstream commit id: 279f438e36c0a70b23b86d2090aeec50155034a9 ] Without this patch, if a frontend cycles through states Closing and Closed (which Windows frontends need to do) then the netdev will be destroyed and requires re-invocation of hotplug scripts to restore state before the frontend can move to Connected. Thus when udev is not in use the backend gets stuck in InitWait. With this patch, the netdev is left alone whilst the backend is still online and is only de-registered and freed just prior to destroying the vif (which is also nicely symmetrical with the netdev allocation and registration being done during probe) so no re-invocation of hotplug scripts is required. Signed-off-by: Paul Durrant Cc: David Vrabel Cc: Wei Liu Cc: Ian Campbell Signed-off-by: Greg Kroah-Hartman --- drivers/net/xen-netback/common.h | 1 + drivers/net/xen-netback/interface.c | 12 ++++++++++-- drivers/net/xen-netback/xenbus.c | 17 ++++++++++++----- 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h index 9d7f1723dd8f..1a285083d24a 100644 --- a/drivers/net/xen-netback/common.h +++ b/drivers/net/xen-netback/common.h @@ -115,6 +115,7 @@ struct xenvif *xenvif_alloc(struct device *parent, int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref, unsigned long rx_ring_ref, unsigned int evtchn); void xenvif_disconnect(struct xenvif *vif); +void xenvif_free(struct xenvif *vif); void xenvif_get(struct xenvif *vif); void xenvif_put(struct xenvif *vif); diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index d98414168485..3a294c2528d5 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@ -304,6 +304,9 @@ struct xenvif *xenvif_alloc(struct device *parent, domid_t domid, } netdev_dbg(dev, "Successfully created xenvif\n"); + + __module_get(THIS_MODULE); + return vif; } @@ -369,9 +372,14 @@ void xenvif_disconnect(struct xenvif *vif) if (vif->irq) unbind_from_irqhandler(vif->irq, vif); - unregister_netdev(vif->dev); - xen_netbk_unmap_frontend_rings(vif); +} + +void xenvif_free(struct xenvif *vif) +{ + unregister_netdev(vif->dev); free_netdev(vif->dev); + + module_put(THIS_MODULE); } diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c index 410018c4c528..abe24ff000f0 100644 --- a/drivers/net/xen-netback/xenbus.c +++ b/drivers/net/xen-netback/xenbus.c @@ -42,7 +42,7 @@ static int netback_remove(struct xenbus_device *dev) if (be->vif) { kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE); xenbus_rm(XBT_NIL, dev->nodename, "hotplug-status"); - xenvif_disconnect(be->vif); + xenvif_free(be->vif); be->vif = NULL; } kfree(be); @@ -203,9 +203,18 @@ static void disconnect_backend(struct xenbus_device *dev) { struct backend_info *be = dev_get_drvdata(&dev->dev); + if (be->vif) + xenvif_disconnect(be->vif); +} + +static void destroy_backend(struct xenbus_device *dev) +{ + struct backend_info *be = dev_get_drvdata(&dev->dev); + if (be->vif) { + kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE); xenbus_rm(XBT_NIL, dev->nodename, "hotplug-status"); - xenvif_disconnect(be->vif); + xenvif_free(be->vif); be->vif = NULL; } } @@ -237,14 +246,11 @@ static void frontend_changed(struct xenbus_device *dev, case XenbusStateConnected: if (dev->state == XenbusStateConnected) break; - backend_create_xenvif(be); if (be->vif) connect(be); break; case XenbusStateClosing: - if (be->vif) - kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE); disconnect_backend(dev); xenbus_switch_state(dev, XenbusStateClosing); break; @@ -253,6 +259,7 @@ static void frontend_changed(struct xenbus_device *dev, xenbus_switch_state(dev, XenbusStateClosed); if (xenbus_dev_is_online(dev)) break; + destroy_backend(dev); /* fall through if not online */ case XenbusStateUnknown: device_unregister(&dev->dev); -- cgit v1.2.3 From 4c1f32d2d776b7d87962e902d62f8b6b2b2e1025 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Mon, 7 Oct 2013 23:19:58 +0200 Subject: net: vlan: fix nlmsg size calculation in vlan_get_size() [ Upstream commit c33a39c575068c2ea9bffb22fd6de2df19c74b89 ] This patch fixes the calculation of the nlmsg size, by adding the missing nla_total_size(). Cc: Patrick McHardy Signed-off-by: Marc Kleine-Budde Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/8021q/vlan_netlink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/8021q/vlan_netlink.c b/net/8021q/vlan_netlink.c index 309129732285..c7e634af8516 100644 --- a/net/8021q/vlan_netlink.c +++ b/net/8021q/vlan_netlink.c @@ -171,7 +171,7 @@ static size_t vlan_get_size(const struct net_device *dev) return nla_total_size(2) + /* IFLA_VLAN_PROTOCOL */ nla_total_size(2) + /* IFLA_VLAN_ID */ - sizeof(struct ifla_vlan_flags) + /* IFLA_VLAN_FLAGS */ + nla_total_size(sizeof(struct ifla_vlan_flags)) + /* IFLA_VLAN_FLAGS */ vlan_qos_map_size(vlan->nr_ingress_mappings) + vlan_qos_map_size(vlan->nr_egress_mappings); } -- cgit v1.2.3 From a77db44038f976c2734fb3d2b1ed0cb9c3afde75 Mon Sep 17 00:00:00 2001 From: Christophe Gouault Date: Tue, 8 Oct 2013 17:21:22 +0200 Subject: vti: get rid of nf mark rule in prerouting [ Upstream commit 7263a5187f9e9de45fcb51349cf0e031142c19a1 ] This patch fixes and improves the use of vti interfaces (while lightly changing the way of configuring them). Currently: - it is necessary to identify and mark inbound IPsec packets destined to each vti interface, via netfilter rules in the mangle table at prerouting hook. - the vti module cannot retrieve the right tunnel in input since commit b9959fd3: vti tunnels all have an i_key, but the tunnel lookup is done with flag TUNNEL_NO_KEY, so there no chance to retrieve them. - the i_key is used by the outbound processing as a mark to lookup for the right SP and SA bundle. This patch uses the o_key to store the vti mark (instead of i_key) and enables: - to avoid the need for previously marking the inbound skbuffs via a netfilter rule. - to properly retrieve the right tunnel in input, only based on the IPsec packet outer addresses. - to properly perform an inbound policy check (using the tunnel o_key as a mark). - to properly perform an outbound SPD and SAD lookup (using the tunnel o_key as a mark). - to keep the current mark of the skbuff. The skbuff mark is neither used nor changed by the vti interface. Only the vti interface o_key is used. SAs have a wildcard mark. SPs have a mark equal to the vti interface o_key. The vti interface must be created as follows (i_key = 0, o_key = mark): ip link add vti1 mode vti local 1.1.1.1 remote 2.2.2.2 okey 1 The SPs attached to vti1 must be created as follows (mark = vti1 o_key): ip xfrm policy add dir out mark 1 tmpl src 1.1.1.1 dst 2.2.2.2 \ proto esp mode tunnel ip xfrm policy add dir in mark 1 tmpl src 2.2.2.2 dst 1.1.1.1 \ proto esp mode tunnel The SAs are created with the default wildcard mark. There is no distinction between global vs. vti SAs. Just their addresses will possibly link them to a vti interface: ip xfrm state add src 1.1.1.1 dst 2.2.2.2 proto esp spi 1000 mode tunnel \ enc "cbc(aes)" "azertyuiopqsdfgh" ip xfrm state add src 2.2.2.2 dst 1.1.1.1 proto esp spi 2000 mode tunnel \ enc "cbc(aes)" "sqbdhgqsdjqjsdfh" To avoid matching "global" (not vti) SPs in vti interfaces, global SPs should no use the default wildcard mark, but explicitly match mark 0. To avoid a double SPD lookup in input and output (in global and vti SPDs), the NOPOLICY and NOXFRM options should be set on the vti interfaces: echo 1 > /proc/sys/net/ipv4/conf/vti1/disable_policy echo 1 > /proc/sys/net/ipv4/conf/vti1/disable_xfrm The outgoing traffic is steered to vti1 by a route via the vti interface: ip route add 192.168.0.0/16 dev vti1 The incoming IPsec traffic is steered to vti1 because its outer addresses match the vti1 tunnel configuration. Signed-off-by: Christophe Gouault Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/ip_vti.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c index 17cc0ffa8c0d..065604127418 100644 --- a/net/ipv4/ip_vti.c +++ b/net/ipv4/ip_vti.c @@ -285,8 +285,17 @@ static int vti_rcv(struct sk_buff *skb) tunnel = vti_tunnel_lookup(dev_net(skb->dev), iph->saddr, iph->daddr); if (tunnel != NULL) { struct pcpu_tstats *tstats; + u32 oldmark = skb->mark; + int ret; - if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) + + /* temporarily mark the skb with the tunnel o_key, to + * only match policies with this mark. + */ + skb->mark = be32_to_cpu(tunnel->parms.o_key); + ret = xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb); + skb->mark = oldmark; + if (!ret) return -1; tstats = this_cpu_ptr(tunnel->dev->tstats); @@ -295,7 +304,6 @@ static int vti_rcv(struct sk_buff *skb) tstats->rx_bytes += skb->len; u64_stats_update_end(&tstats->syncp); - skb->mark = 0; secpath_reset(skb); skb->dev = tunnel->dev; return 1; @@ -327,7 +335,7 @@ static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) memset(&fl4, 0, sizeof(fl4)); flowi4_init_output(&fl4, tunnel->parms.link, - be32_to_cpu(tunnel->parms.i_key), RT_TOS(tos), + be32_to_cpu(tunnel->parms.o_key), RT_TOS(tos), RT_SCOPE_UNIVERSE, IPPROTO_IPIP, 0, dst, tiph->saddr, 0, 0); -- cgit v1.2.3 From a41536775e712e7b438400f73e927ffe4b21149c Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 10 Oct 2013 06:30:09 -0700 Subject: l2tp: must disable bh before calling l2tp_xmit_skb() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 455cc32bf128e114455d11ad919321ab89a2c312 ] François Cachereul made a very nice bug report and suspected the bh_lock_sock() / bh_unlok_sock() pair used in l2tp_xmit_skb() from process context was not good. This problem was added by commit 6af88da14ee284aaad6e4326da09a89191ab6165 ("l2tp: Fix locking in l2tp_core.c"). l2tp_eth_dev_xmit() runs from BH context, so we must disable BH from other l2tp_xmit_skb() users. [ 452.060011] BUG: soft lockup - CPU#1 stuck for 23s! [accel-pppd:6662] [ 452.061757] Modules linked in: l2tp_ppp l2tp_netlink l2tp_core pppoe pppox ppp_generic slhc ipv6 ext3 mbcache jbd virtio_balloon xfs exportfs dm_mod virtio_blk ata_generic virtio_net floppy ata_piix libata virtio_pci virtio_ring virtio [last unloaded: scsi_wait_scan] [ 452.064012] CPU 1 [ 452.080015] BUG: soft lockup - CPU#2 stuck for 23s! [accel-pppd:6643] [ 452.080015] CPU 2 [ 452.080015] [ 452.080015] Pid: 6643, comm: accel-pppd Not tainted 3.2.46.mini #1 Bochs Bochs [ 452.080015] RIP: 0010:[] [] do_raw_spin_lock+0x17/0x1f [ 452.080015] RSP: 0018:ffff88007125fc18 EFLAGS: 00000293 [ 452.080015] RAX: 000000000000aba9 RBX: ffffffff811d0703 RCX: 0000000000000000 [ 452.080015] RDX: 00000000000000ab RSI: ffff8800711f6896 RDI: ffff8800745c8110 [ 452.080015] RBP: ffff88007125fc18 R08: 0000000000000020 R09: 0000000000000000 [ 452.080015] R10: 0000000000000000 R11: 0000000000000280 R12: 0000000000000286 [ 452.080015] R13: 0000000000000020 R14: 0000000000000240 R15: 0000000000000000 [ 452.080015] FS: 00007fdc0cc24700(0000) GS:ffff8800b6f00000(0000) knlGS:0000000000000000 [ 452.080015] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 452.080015] CR2: 00007fdb054899b8 CR3: 0000000074404000 CR4: 00000000000006a0 [ 452.080015] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 452.080015] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 [ 452.080015] Process accel-pppd (pid: 6643, threadinfo ffff88007125e000, task ffff8800b27e6dd0) [ 452.080015] Stack: [ 452.080015] ffff88007125fc28 ffffffff81256559 ffff88007125fc98 ffffffffa01b2bd1 [ 452.080015] ffff88007125fc58 000000000000000c 00000000029490d0 0000009c71dbe25e [ 452.080015] 000000000000005c 000000080000000e 0000000000000000 ffff880071170600 [ 452.080015] Call Trace: [ 452.080015] [] _raw_spin_lock+0xe/0x10 [ 452.080015] [] l2tp_xmit_skb+0x189/0x4ac [l2tp_core] [ 452.080015] [] pppol2tp_sendmsg+0x15e/0x19c [l2tp_ppp] [ 452.080015] [] __sock_sendmsg_nosec+0x22/0x24 [ 452.080015] [] sock_sendmsg+0xa1/0xb6 [ 452.080015] [] ? __schedule+0x5c1/0x616 [ 452.080015] [] ? __dequeue_signal+0xb7/0x10c [ 452.080015] [] ? fget_light+0x75/0x89 [ 452.080015] [] ? sockfd_lookup_light+0x20/0x56 [ 452.080015] [] sys_sendto+0x10c/0x13b [ 452.080015] [] system_call_fastpath+0x16/0x1b [ 452.080015] Code: 81 48 89 e5 72 0c 31 c0 48 81 ff 45 66 25 81 0f 92 c0 5d c3 55 b8 00 01 00 00 48 89 e5 f0 66 0f c1 07 0f b6 d4 38 d0 74 06 f3 90 <8a> 07 eb f6 5d c3 90 90 55 48 89 e5 9c 58 0f 1f 44 00 00 5d c3 [ 452.080015] Call Trace: [ 452.080015] [] _raw_spin_lock+0xe/0x10 [ 452.080015] [] l2tp_xmit_skb+0x189/0x4ac [l2tp_core] [ 452.080015] [] pppol2tp_sendmsg+0x15e/0x19c [l2tp_ppp] [ 452.080015] [] __sock_sendmsg_nosec+0x22/0x24 [ 452.080015] [] sock_sendmsg+0xa1/0xb6 [ 452.080015] [] ? __schedule+0x5c1/0x616 [ 452.080015] [] ? __dequeue_signal+0xb7/0x10c [ 452.080015] [] ? fget_light+0x75/0x89 [ 452.080015] [] ? sockfd_lookup_light+0x20/0x56 [ 452.080015] [] sys_sendto+0x10c/0x13b [ 452.080015] [] system_call_fastpath+0x16/0x1b [ 452.064012] [ 452.064012] Pid: 6662, comm: accel-pppd Not tainted 3.2.46.mini #1 Bochs Bochs [ 452.064012] RIP: 0010:[] [] do_raw_spin_lock+0x19/0x1f [ 452.064012] RSP: 0018:ffff8800b6e83ba0 EFLAGS: 00000297 [ 452.064012] RAX: 000000000000aaa9 RBX: ffff8800b6e83b40 RCX: 0000000000000002 [ 452.064012] RDX: 00000000000000aa RSI: 000000000000000a RDI: ffff8800745c8110 [ 452.064012] RBP: ffff8800b6e83ba0 R08: 000000000000c802 R09: 000000000000001c [ 452.064012] R10: ffff880071096c4e R11: 0000000000000006 R12: ffff8800b6e83b18 [ 452.064012] R13: ffffffff8125d51e R14: ffff8800b6e83ba0 R15: ffff880072a589c0 [ 452.064012] FS: 00007fdc0b81e700(0000) GS:ffff8800b6e80000(0000) knlGS:0000000000000000 [ 452.064012] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 452.064012] CR2: 0000000000625208 CR3: 0000000074404000 CR4: 00000000000006a0 [ 452.064012] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 452.064012] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 [ 452.064012] Process accel-pppd (pid: 6662, threadinfo ffff88007129a000, task ffff8800744f7410) [ 452.064012] Stack: [ 452.064012] ffff8800b6e83bb0 ffffffff81256559 ffff8800b6e83bc0 ffffffff8121c64a [ 452.064012] ffff8800b6e83bf0 ffffffff8121ec7a ffff880072a589c0 ffff880071096c62 [ 452.064012] 0000000000000011 ffffffff81430024 ffff8800b6e83c80 ffffffff8121f276 [ 452.064012] Call Trace: [ 452.064012] [ 452.064012] [] _raw_spin_lock+0xe/0x10 [ 452.064012] [] spin_lock+0x9/0xb [ 452.064012] [] udp_queue_rcv_skb+0x186/0x269 [ 452.064012] [] __udp4_lib_rcv+0x297/0x4ae [ 452.064012] [] ? raw_rcv+0xe9/0xf0 [ 452.064012] [] udp_rcv+0x1a/0x1c [ 452.064012] [] ip_local_deliver_finish+0x12b/0x1a5 [ 452.064012] [] ip_local_deliver+0x53/0x84 [ 452.064012] [] ip_rcv_finish+0x2bc/0x2f3 [ 452.064012] [] ip_rcv+0x210/0x269 [ 452.064012] [] ? kvm_clock_get_cycles+0x9/0xb [ 452.064012] [] __netif_receive_skb+0x3a5/0x3f7 [ 452.064012] [] netif_receive_skb+0x57/0x5e [ 452.064012] [] ? __netdev_alloc_skb+0x1f/0x3b [ 452.064012] [] virtnet_poll+0x4ba/0x5a4 [virtio_net] [ 452.064012] [] net_rx_action+0x73/0x184 [ 452.064012] [] ? l2tp_xmit_skb+0x27a/0x4ac [l2tp_core] [ 452.064012] [] __do_softirq+0xc3/0x1a8 [ 452.064012] [] ? ack_APIC_irq+0x10/0x12 [ 452.064012] [] ? _raw_spin_lock+0xe/0x10 [ 452.064012] [] call_softirq+0x1c/0x26 [ 452.064012] [] do_softirq+0x45/0x82 [ 452.064012] [] irq_exit+0x42/0x9c [ 452.064012] [] do_IRQ+0x8e/0xa5 [ 452.064012] [] common_interrupt+0x6e/0x6e [ 452.064012] [ 452.064012] [] ? kfree+0x8a/0xa3 [ 452.064012] [] ? l2tp_xmit_skb+0x27a/0x4ac [l2tp_core] [ 452.064012] [] ? l2tp_xmit_skb+0x1dd/0x4ac [l2tp_core] [ 452.064012] [] pppol2tp_sendmsg+0x15e/0x19c [l2tp_ppp] [ 452.064012] [] __sock_sendmsg_nosec+0x22/0x24 [ 452.064012] [] sock_sendmsg+0xa1/0xb6 [ 452.064012] [] ? __schedule+0x5c1/0x616 [ 452.064012] [] ? __dequeue_signal+0xb7/0x10c [ 452.064012] [] ? fget_light+0x75/0x89 [ 452.064012] [] ? sockfd_lookup_light+0x20/0x56 [ 452.064012] [] sys_sendto+0x10c/0x13b [ 452.064012] [] system_call_fastpath+0x16/0x1b [ 452.064012] Code: 89 e5 72 0c 31 c0 48 81 ff 45 66 25 81 0f 92 c0 5d c3 55 b8 00 01 00 00 48 89 e5 f0 66 0f c1 07 0f b6 d4 38 d0 74 06 f3 90 8a 07 f6 5d c3 90 90 55 48 89 e5 9c 58 0f 1f 44 00 00 5d c3 55 48 [ 452.064012] Call Trace: [ 452.064012] [] _raw_spin_lock+0xe/0x10 [ 452.064012] [] spin_lock+0x9/0xb [ 452.064012] [] udp_queue_rcv_skb+0x186/0x269 [ 452.064012] [] __udp4_lib_rcv+0x297/0x4ae [ 452.064012] [] ? raw_rcv+0xe9/0xf0 [ 452.064012] [] udp_rcv+0x1a/0x1c [ 452.064012] [] ip_local_deliver_finish+0x12b/0x1a5 [ 452.064012] [] ip_local_deliver+0x53/0x84 [ 452.064012] [] ip_rcv_finish+0x2bc/0x2f3 [ 452.064012] [] ip_rcv+0x210/0x269 [ 452.064012] [] ? kvm_clock_get_cycles+0x9/0xb [ 452.064012] [] __netif_receive_skb+0x3a5/0x3f7 [ 452.064012] [] netif_receive_skb+0x57/0x5e [ 452.064012] [] ? __netdev_alloc_skb+0x1f/0x3b [ 452.064012] [] virtnet_poll+0x4ba/0x5a4 [virtio_net] [ 452.064012] [] net_rx_action+0x73/0x184 [ 452.064012] [] ? l2tp_xmit_skb+0x27a/0x4ac [l2tp_core] [ 452.064012] [] __do_softirq+0xc3/0x1a8 [ 452.064012] [] ? ack_APIC_irq+0x10/0x12 [ 452.064012] [] ? _raw_spin_lock+0xe/0x10 [ 452.064012] [] call_softirq+0x1c/0x26 [ 452.064012] [] do_softirq+0x45/0x82 [ 452.064012] [] irq_exit+0x42/0x9c [ 452.064012] [] do_IRQ+0x8e/0xa5 [ 452.064012] [] common_interrupt+0x6e/0x6e [ 452.064012] [] ? kfree+0x8a/0xa3 [ 452.064012] [] ? l2tp_xmit_skb+0x27a/0x4ac [l2tp_core] [ 452.064012] [] ? l2tp_xmit_skb+0x1dd/0x4ac [l2tp_core] [ 452.064012] [] pppol2tp_sendmsg+0x15e/0x19c [l2tp_ppp] [ 452.064012] [] __sock_sendmsg_nosec+0x22/0x24 [ 452.064012] [] sock_sendmsg+0xa1/0xb6 [ 452.064012] [] ? __schedule+0x5c1/0x616 [ 452.064012] [] ? __dequeue_signal+0xb7/0x10c [ 452.064012] [] ? fget_light+0x75/0x89 [ 452.064012] [] ? sockfd_lookup_light+0x20/0x56 [ 452.064012] [] sys_sendto+0x10c/0x13b [ 452.064012] [] system_call_fastpath+0x16/0x1b Reported-by: François Cachereul Tested-by: François Cachereul Signed-off-by: Eric Dumazet Cc: James Chapman Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/l2tp/l2tp_ppp.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c index 5ebee2ded9e9..8c46b271064a 100644 --- a/net/l2tp/l2tp_ppp.c +++ b/net/l2tp/l2tp_ppp.c @@ -353,7 +353,9 @@ static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msgh goto error_put_sess_tun; } + local_bh_disable(); l2tp_xmit_skb(session, skb, session->hdr_len); + local_bh_enable(); sock_put(ps->tunnel_sock); sock_put(sk); @@ -422,7 +424,9 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb) skb->data[0] = ppph[0]; skb->data[1] = ppph[1]; + local_bh_disable(); l2tp_xmit_skb(session, skb, session->hdr_len); + local_bh_enable(); sock_put(sk_tun); sock_put(sk); -- cgit v1.2.3 From 3a26736015acfc8745db623efa7f57bc982ed516 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Salva=20Peir=C3=B3?= Date: Fri, 11 Oct 2013 12:50:03 +0300 Subject: farsync: fix info leak in ioctl [ Upstream commit 96b340406724d87e4621284ebac5e059d67b2194 ] The fst_get_iface() code fails to initialize the two padding bytes of struct sync_serial_settings after the ->loopback member. Add an explicit memset(0) before filling the structure to avoid the info leak. Signed-off-by: Dan Carpenter Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/wan/farsync.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c index 3f0c4f268751..bcfff0d62de4 100644 --- a/drivers/net/wan/farsync.c +++ b/drivers/net/wan/farsync.c @@ -1972,6 +1972,7 @@ fst_get_iface(struct fst_card_info *card, struct fst_port_info *port, } i = port->index; + memset(&sync, 0, sizeof(sync)); sync.clock_rate = FST_RDL(card, portConfig[i].lineSpeed); /* Lucky card and linux use same encoding here */ sync.clock_type = FST_RDB(card, portConfig[i].internalClock) == -- cgit v1.2.3 From 39283085a92262f9446b95d36df9724902b7579a Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Mon, 30 Sep 2013 22:05:40 +0200 Subject: unix_diag: fix info leak [ Upstream commit 6865d1e834be84ddd5808d93d5035b492346c64a ] When filling the netlink message we miss to wipe the pad field, therefore leak one byte of heap memory to userland. Fix this by setting pad to 0. Signed-off-by: Mathias Krause Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/unix/diag.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/unix/diag.c b/net/unix/diag.c index d591091603bf..86fa0f3b2caf 100644 --- a/net/unix/diag.c +++ b/net/unix/diag.c @@ -124,6 +124,7 @@ static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, struct unix_diag_r rep->udiag_family = AF_UNIX; rep->udiag_type = sk->sk_type; rep->udiag_state = sk->sk_state; + rep->pad = 0; rep->udiag_ino = sk_ino; sock_diag_save_cookie(sk, rep->udiag_cookie); -- cgit v1.2.3 From 69b9c5ea567e5c9b202b3e5bcac3c2eb72270e0b Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Mon, 30 Sep 2013 22:03:07 +0200 Subject: connector: use nlmsg_len() to check message length [ Upstream commit 162b2bedc084d2d908a04c93383ba02348b648b0 ] The current code tests the length of the whole netlink message to be at least as long to fit a cn_msg. This is wrong as nlmsg_len includes the length of the netlink message header. Use nlmsg_len() instead to fix this "off-by-NLMSG_HDRLEN" size check. Signed-off-by: Mathias Krause Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/connector/connector.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c index 6ecfa758942c..0daa11e418b1 100644 --- a/drivers/connector/connector.c +++ b/drivers/connector/connector.c @@ -157,17 +157,18 @@ static int cn_call_callback(struct sk_buff *skb) static void cn_rx_skb(struct sk_buff *__skb) { struct nlmsghdr *nlh; - int err; struct sk_buff *skb; + int len, err; skb = skb_get(__skb); if (skb->len >= NLMSG_HDRLEN) { nlh = nlmsg_hdr(skb); + len = nlmsg_len(nlh); - if (nlh->nlmsg_len < sizeof(struct cn_msg) || + if (len < (int)sizeof(struct cn_msg) || skb->len < nlh->nlmsg_len || - nlh->nlmsg_len > CONNECTOR_MAX_MSG_SIZE) { + len > CONNECTOR_MAX_MSG_SIZE) { kfree_skb(skb); return; } -- cgit v1.2.3 From 608be70366c3abaa402ba9d6a8427b1b979633cf Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sat, 12 Oct 2013 14:08:34 -0700 Subject: bnx2x: record rx queue for LRO packets [ Upstream commit 60e66fee56b2256dcb1dc2ea1b2ddcb6e273857d ] RPS support is kind of broken on bnx2x, because only non LRO packets get proper rx queue information. This triggers reorders, as it seems bnx2x like to generate a non LRO packet for segment including TCP PUSH flag : (this might be pure coincidence, but all the reorders I've seen involve segments with a PUSH) 11:13:34.335847 IP A > B: . 415808:447136(31328) ack 1 win 457 11:13:34.335992 IP A > B: . 447136:448560(1424) ack 1 win 457 11:13:34.336391 IP A > B: . 448560:479888(31328) ack 1 win 457 11:13:34.336425 IP A > B: P 511216:512640(1424) ack 1 win 457 11:13:34.336423 IP A > B: . 479888:511216(31328) ack 1 win 457 11:13:34.336924 IP A > B: . 512640:543968(31328) ack 1 win 457 11:13:34.336963 IP A > B: . 543968:575296(31328) ack 1 win 457 We must call skb_record_rx_queue() to properly give to RPS (and more generally for TX queue selection on forward path) the receive queue information. Similar fix is needed for skb_mark_napi_id(), but will be handled in a separate patch to ease stable backports. Signed-off-by: Eric Dumazet Cc: Willem de Bruijn Cc: Eilon Greenstein Acked-by: Dmitry Kravkov Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index 638e55435b04..8c4babc0efbd 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -670,6 +670,7 @@ static void bnx2x_gro_receive(struct bnx2x *bp, struct bnx2x_fastpath *fp, } } #endif + skb_record_rx_queue(skb, fp->rx_queue); napi_gro_receive(&fp->napi, skb); } -- cgit v1.2.3 From f02721718c7dcd4cb949fb0c0689e19a66c8c6ef Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Tue, 15 Oct 2013 11:18:58 +0800 Subject: virtio-net: don't respond to cpu hotplug notifier if we're not ready [ Upstream commit 3ab098df35f8b98b6553edc2e40234af512ba877 ] We're trying to re-configure the affinity unconditionally in cpu hotplug callback. This may lead the issue during resuming from s3/s4 since - virt queues haven't been allocated at that time. - it's unnecessary since thaw method will re-configure the affinity. Fix this issue by checking the config_enable and do nothing is we're not ready. The bug were introduced by commit 8de4b2f3ae90c8fc0f17eeaab87d5a951b66ee17 (virtio-net: reset virtqueue affinity when doing cpu hotplug). Acked-by: Michael S. Tsirkin Cc: Rusty Russell Cc: Michael S. Tsirkin Cc: Wanlong Gao Reviewed-by: Wanlong Gao Signed-off-by: Jason Wang Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/virtio_net.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 42d670a468f8..542c3f2d8400 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -1097,6 +1097,11 @@ static int virtnet_cpu_callback(struct notifier_block *nfb, { struct virtnet_info *vi = container_of(nfb, struct virtnet_info, nb); + mutex_lock(&vi->config_lock); + + if (!vi->config_enable) + goto done; + switch(action & ~CPU_TASKS_FROZEN) { case CPU_ONLINE: case CPU_DOWN_FAILED: @@ -1109,6 +1114,9 @@ static int virtnet_cpu_callback(struct notifier_block *nfb, default: break; } + +done: + mutex_unlock(&vi->config_lock); return NOTIFY_OK; } -- cgit v1.2.3 From 413054e740f1efb2cb765323bc73ad01f986c4e1 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Thu, 4 Jul 2013 11:22:57 +0930 Subject: virtio-net: fix the race between channels setting and refill [ Upstream commit 9b9cd8024a2882e896c65222aa421d461354e3f2 ] Commit 55257d72bd1c51f25106350f4983ec19f62ed1fa (virtio-net: fill only rx queues which are being used) tries to refill on demand when changing the number of channels by call try_refill_recv() directly, this may race: - the refill work who may do the refill in the same time - the try_refill_recv() called in bh since napi was not disabled Which may led guest complain during setting channels: virtio_net virtio0: input.1:id 0 is not a head! Solve this issue by scheduling a refill work which can guarantee the serialization of refill. Signed-off-by: Jason Wang Cc: Sasha Levin Cc: Rusty Russell Cc: Michael S. Tsirkin Signed-off-by: Rusty Russell Signed-off-by: Greg Kroah-Hartman --- drivers/net/virtio_net.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 542c3f2d8400..43a71d911b1c 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -902,7 +902,6 @@ static int virtnet_set_queues(struct virtnet_info *vi, u16 queue_pairs) struct scatterlist sg; struct virtio_net_ctrl_mq s; struct net_device *dev = vi->dev; - int i; if (!vi->has_cvq || !virtio_has_feature(vi->vdev, VIRTIO_NET_F_MQ)) return 0; @@ -916,10 +915,8 @@ static int virtnet_set_queues(struct virtnet_info *vi, u16 queue_pairs) queue_pairs); return -EINVAL; } else { - for (i = vi->curr_queue_pairs; i < queue_pairs; i++) - if (!try_fill_recv(&vi->rq[i], GFP_KERNEL)) - schedule_delayed_work(&vi->refill, 0); vi->curr_queue_pairs = queue_pairs; + schedule_delayed_work(&vi->refill, 0); } return 0; -- cgit v1.2.3 From 30983d3c66572348f078fe2e2d55638d73c3e486 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Tue, 15 Oct 2013 11:18:59 +0800 Subject: virtio-net: refill only when device is up during setting queues [ Upstream commit 35ed159bfd96a7547ec277ed8b550c7cbd9841b6 ] We used to schedule the refill work unconditionally after changing the number of queues. This may lead an issue if the device is not up. Since we only try to cancel the work in ndo_stop(), this may cause the refill work still work after removing the device. Fix this by only schedule the work when device is up. The bug were introduce by commit 9b9cd8024a2882e896c65222aa421d461354e3f2. (virtio-net: fix the race between channels setting and refill) Signed-off-by: Jason Wang Cc: Rusty Russell Cc: Michael S. Tsirkin Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/virtio_net.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 43a71d911b1c..1d01534c2020 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -916,7 +916,9 @@ static int virtnet_set_queues(struct virtnet_info *vi, u16 queue_pairs) return -EINVAL; } else { vi->curr_queue_pairs = queue_pairs; - schedule_delayed_work(&vi->refill, 0); + /* virtnet_open() will refill when device is going to up. */ + if (dev->flags & IFF_UP) + schedule_delayed_work(&vi->refill, 0); } return 0; @@ -1714,7 +1716,9 @@ static int virtnet_restore(struct virtio_device *vdev) vi->config_enable = true; mutex_unlock(&vi->config_lock); + rtnl_lock(); virtnet_set_queues(vi, vi->curr_queue_pairs); + rtnl_unlock(); return 0; } -- cgit v1.2.3 From d14db2327635ac00aa7332bf26759d13ff39e2a5 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Tue, 15 Oct 2013 14:57:45 -0400 Subject: bridge: Correctly clamp MAX forward_delay when enabling STP [ Upstream commit 4b6c7879d84ad06a2ac5b964808ed599187a188d ] Commit be4f154d5ef0ca147ab6bcd38857a774133f5450 bridge: Clamp forward_delay when enabling STP had a typo when attempting to clamp maximum forward delay. It is possible to set bridge_forward_delay to be higher then permitted maximum when STP is off. When turning STP on, the higher then allowed delay has to be clamed down to max value. Signed-off-by: Vlad Yasevich CC: Herbert Xu CC: Stephen Hemminger Reviewed-by: Veaceslav Falico Acked-by: Herbert Xu Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/bridge/br_stp_if.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c index 108084a04671..656a6f3e40de 100644 --- a/net/bridge/br_stp_if.c +++ b/net/bridge/br_stp_if.c @@ -134,7 +134,7 @@ static void br_stp_start(struct net_bridge *br) if (br->bridge_forward_delay < BR_MIN_FORWARD_DELAY) __br_set_forward_delay(br, BR_MIN_FORWARD_DELAY); - else if (br->bridge_forward_delay < BR_MAX_FORWARD_DELAY) + else if (br->bridge_forward_delay > BR_MAX_FORWARD_DELAY) __br_set_forward_delay(br, BR_MAX_FORWARD_DELAY); if (r == 0) { -- cgit v1.2.3 From c9446ff691aca0ca902f31f7a9830ac725841759 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Tue, 15 Oct 2013 22:01:29 -0400 Subject: net: dst: provide accessor function to dst->xfrm [ Upstream commit e87b3998d795123b4139bc3f25490dd236f68212 ] dst->xfrm is conditionally defined. Provide accessor funtion that is always available. Signed-off-by: Vlad Yasevich Acked-by: Neil Horman Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/net/dst.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/include/net/dst.h b/include/net/dst.h index 1f8fd109e225..e0c97f5a57cf 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -477,10 +477,22 @@ static inline struct dst_entry *xfrm_lookup(struct net *net, { return dst_orig; } + +static inline struct xfrm_state *dst_xfrm(const struct dst_entry *dst) +{ + return NULL; +} + #else extern struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig, const struct flowi *fl, struct sock *sk, int flags); + +/* skb attached with this dst needs transformation if dst->xfrm is valid */ +static inline struct xfrm_state *dst_xfrm(const struct dst_entry *dst) +{ + return dst->xfrm; +} #endif #endif /* _NET_DST_H */ -- cgit v1.2.3 From 935be1dc2cafe04f1421e236f75d17878920631b Mon Sep 17 00:00:00 2001 From: Fan Du Date: Tue, 15 Oct 2013 22:01:30 -0400 Subject: sctp: Use software crc32 checksum when xfrm transform will happen. [ Upstream commit 27127a82561a2a3ed955ce207048e1b066a80a2a ] igb/ixgbe have hardware sctp checksum support, when this feature is enabled and also IPsec is armed to protect sctp traffic, ugly things happened as xfrm_output checks CHECKSUM_PARTIAL to do checksum operation(sum every thing up and pack the 16bits result in the checksum field). The result is fail establishment of sctp communication. Signed-off-by: Fan Du Cc: Neil Horman Cc: Steffen Klassert Signed-off-by: Vlad Yasevich Acked-by: Neil Horman Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/sctp/output.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/sctp/output.c b/net/sctp/output.c index bbef4a7a9b56..a1884399c042 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c @@ -547,7 +547,8 @@ int sctp_packet_transmit(struct sctp_packet *packet) * by CRC32-C as described in . */ if (!sctp_checksum_disable) { - if (!(dst->dev->features & NETIF_F_SCTP_CSUM)) { + if (!(dst->dev->features & NETIF_F_SCTP_CSUM) || + (dst_xfrm(dst) != NULL)) { __u32 crc32 = sctp_start_cksum((__u8 *)sh, cksum_buf_len); /* 3) Put the resultant value into the checksum field in the -- cgit v1.2.3 From c69ee66768490b30127bc496921a3603c9366a10 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Tue, 15 Oct 2013 22:01:31 -0400 Subject: sctp: Perform software checksum if packet has to be fragmented. [ Upstream commit d2dbbba77e95dff4b4f901fee236fef6d9552072 ] IP/IPv6 fragmentation knows how to compute only TCP/UDP checksum. This causes problems if SCTP packets has to be fragmented and ipsummed has been set to PARTIAL due to checksum offload support. This condition can happen when retransmitting after MTU discover, or when INIT or other control chunks are larger then MTU. Check for the rare fragmentation condition in SCTP and use software checksum calculation in this case. CC: Fan Du Signed-off-by: Vlad Yasevich Acked-by: Neil Horman Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/sctp/output.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sctp/output.c b/net/sctp/output.c index a1884399c042..0beb2f9c8a7c 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c @@ -548,7 +548,7 @@ int sctp_packet_transmit(struct sctp_packet *packet) */ if (!sctp_checksum_disable) { if (!(dst->dev->features & NETIF_F_SCTP_CSUM) || - (dst_xfrm(dst) != NULL)) { + (dst_xfrm(dst) != NULL) || packet->ipfragok) { __u32 crc32 = sctp_start_cksum((__u8 *)sh, cksum_buf_len); /* 3) Put the resultant value into the checksum field in the -- cgit v1.2.3 From 8ffb77d881734108a750acb7fb2625643f924bc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Salva=20Peir=C3=B3?= Date: Wed, 16 Oct 2013 12:46:50 +0200 Subject: wanxl: fix info leak in ioctl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 2b13d06c9584b4eb773f1e80bbaedab9a1c344e1 ] The wanxl_ioctl() code fails to initialize the two padding bytes of struct sync_serial_settings after the ->loopback member. Add an explicit memset(0) before filling the structure to avoid the info leak. Signed-off-by: Salva Peiró Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/wan/wanxl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c index 6a24a5a70cc7..4c0a69779b89 100644 --- a/drivers/net/wan/wanxl.c +++ b/drivers/net/wan/wanxl.c @@ -355,6 +355,7 @@ static int wanxl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ifr->ifr_settings.size = size; /* data size wanted */ return -ENOBUFS; } + memset(&line, 0, sizeof(line)); line.clock_type = get_status(port)->clocking; line.clock_rate = 0; line.loopback = 0; -- cgit v1.2.3 From a8410b48a2d992411a8befbab05de5e886b4ac3e Mon Sep 17 00:00:00 2001 From: Vasundhara Volam Date: Thu, 17 Oct 2013 11:47:14 +0530 Subject: be2net: pass if_id for v1 and V2 versions of TX_CREATE cmd [ Upstream commit 0fb88d61bc60779dde88b0fc268da17eb81d0412 ] It is a required field for all TX_CREATE cmd versions > 0. This fixes a driver initialization failure, caused by recent SH-R Firmwares (versions > 10.0.639.0) failing the TX_CREATE cmd when if_id field is not passed. Signed-off-by: Sathya Perla Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/emulex/benet/be_cmds.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c index 1db2df61b8af..696674edbdc4 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/drivers/net/ethernet/emulex/benet/be_cmds.c @@ -1150,7 +1150,6 @@ int be_cmd_txq_create(struct be_adapter *adapter, struct be_tx_obj *txo) if (lancer_chip(adapter)) { req->hdr.version = 1; - req->if_id = cpu_to_le16(adapter->if_handle); } else if (BEx_chip(adapter)) { if (adapter->function_caps & BE_FUNCTION_CAPS_SUPER_NIC) req->hdr.version = 2; @@ -1158,6 +1157,8 @@ int be_cmd_txq_create(struct be_adapter *adapter, struct be_tx_obj *txo) req->hdr.version = 2; } + if (req->hdr.version > 0) + req->if_id = cpu_to_le16(adapter->if_handle); req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size); req->ulp_num = BE_ULP1_NUM; req->type = BE_ETH_TX_RING_TYPE_STANDARD; -- cgit v1.2.3 From a769ad65ce0dea53fdf907008e5f6c93fe06168f Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Thu, 17 Oct 2013 22:51:31 +0200 Subject: net: unix: inherit SOCK_PASS{CRED, SEC} flags from socket to fix race [ Upstream commit 90c6bd34f884cd9cee21f1d152baf6c18bcac949 ] In the case of credentials passing in unix stream sockets (dgram sockets seem not affected), we get a rather sparse race after commit 16e5726 ("af_unix: dont send SCM_CREDENTIALS by default"). We have a stream server on receiver side that requests credential passing from senders (e.g. nc -U). Since we need to set SO_PASSCRED on each spawned/accepted socket on server side to 1 first (as it's not inherited), it can happen that in the time between accept() and setsockopt() we get interrupted, the sender is being scheduled and continues with passing data to our receiver. At that time SO_PASSCRED is neither set on sender nor receiver side, hence in cmsg's SCM_CREDENTIALS we get eventually pid:0, uid:65534, gid:65534 (== overflow{u,g}id) instead of what we actually would like to see. On the sender side, here nc -U, the tests in maybe_add_creds() invoked through unix_stream_sendmsg() would fail, as at that exact time, as mentioned, the sender has neither SO_PASSCRED on his side nor sees it on the server side, and we have a valid 'other' socket in place. Thus, sender believes it would just look like a normal connection, not needing/requesting SO_PASSCRED at that time. As reverting 16e5726 would not be an option due to the significant performance regression reported when having creds always passed, one way/trade-off to prevent that would be to set SO_PASSCRED on the listener socket and allow inheriting these flags to the spawned socket on server side in accept(). It seems also logical to do so if we'd tell the listener socket to pass those flags onwards, and would fix the race. Before, strace: recvmsg(4, {msg_name(0)=NULL, msg_iov(1)=[{"blub\n", 4096}], msg_controllen=32, {cmsg_len=28, cmsg_level=SOL_SOCKET, cmsg_type=SCM_CREDENTIALS{pid=0, uid=65534, gid=65534}}, msg_flags=0}, 0) = 5 After, strace: recvmsg(4, {msg_name(0)=NULL, msg_iov(1)=[{"blub\n", 4096}], msg_controllen=32, {cmsg_len=28, cmsg_level=SOL_SOCKET, cmsg_type=SCM_CREDENTIALS{pid=11580, uid=1000, gid=1000}}, msg_flags=0}, 0) = 5 Signed-off-by: Daniel Borkmann Cc: Eric Dumazet Cc: Eric W. Biederman Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/unix/af_unix.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 826e09938bff..0258072a518f 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -1245,6 +1245,15 @@ static int unix_socketpair(struct socket *socka, struct socket *sockb) return 0; } +static void unix_sock_inherit_flags(const struct socket *old, + struct socket *new) +{ + if (test_bit(SOCK_PASSCRED, &old->flags)) + set_bit(SOCK_PASSCRED, &new->flags); + if (test_bit(SOCK_PASSSEC, &old->flags)) + set_bit(SOCK_PASSSEC, &new->flags); +} + static int unix_accept(struct socket *sock, struct socket *newsock, int flags) { struct sock *sk = sock->sk; @@ -1279,6 +1288,7 @@ static int unix_accept(struct socket *sock, struct socket *newsock, int flags) /* attach accepted sock to socket */ unix_state_lock(tsk); newsock->state = SS_CONNECTED; + unix_sock_inherit_flags(sock, newsock); sock_graft(tsk, newsock); unix_state_unlock(tsk); return 0; -- cgit v1.2.3 From 872095cb74f0acd64d89e578a65df877870f198d Mon Sep 17 00:00:00 2001 From: Seif Mazareeb Date: Thu, 17 Oct 2013 20:33:21 -0700 Subject: net: fix cipso packet validation when !NETLABEL [ Upstream commit f2e5ddcc0d12f9c4c7b254358ad245c9dddce13b ] When CONFIG_NETLABEL is disabled, the cipso_v4_validate() function could loop forever in the main loop if opt[opt_iter +1] == 0, this will causing a kernel crash in an SMP system, since the CPU executing this function will stall /not respond to IPIs. This problem can be reproduced by running the IP Stack Integrity Checker (http://isic.sourceforge.net) using the following command on a Linux machine connected to DUT: "icmpsic -s rand -d -r 123456" wait (1-2 min) Signed-off-by: Seif Mazareeb Acked-by: Paul Moore Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/net/cipso_ipv4.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/net/cipso_ipv4.h b/include/net/cipso_ipv4.h index a7a683e30b64..a8c2ef6d3b93 100644 --- a/include/net/cipso_ipv4.h +++ b/include/net/cipso_ipv4.h @@ -290,6 +290,7 @@ static inline int cipso_v4_validate(const struct sk_buff *skb, unsigned char err_offset = 0; u8 opt_len = opt[1]; u8 opt_iter; + u8 tag_len; if (opt_len < 8) { err_offset = 1; @@ -302,11 +303,12 @@ static inline int cipso_v4_validate(const struct sk_buff *skb, } for (opt_iter = 6; opt_iter < opt_len;) { - if (opt[opt_iter + 1] > (opt_len - opt_iter)) { + tag_len = opt[opt_iter + 1]; + if ((tag_len == 0) || (opt[opt_iter + 1] > (opt_len - opt_iter))) { err_offset = opt_iter + 1; goto out; } - opt_iter += opt[opt_iter + 1]; + opt_iter += tag_len; } out: -- cgit v1.2.3 From b90cd7b9d0baab2e8176d9cca5f18a592ef16063 Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Tue, 22 Oct 2013 00:07:47 +0200 Subject: inet: fix possible memory corruption with UDP_CORK and UFO [ This is a simplified -stable version of a set of upstream commits. ] This is a replacement patch only for stable which does fix the problems handled by the following two commits in -net: "ip_output: do skb ufo init for peeked non ufo skb as well" (e93b7d748be887cd7639b113ba7d7ef792a7efb9) "ip6_output: do skb ufo init for peeked non ufo skb as well" (c547dbf55d5f8cf615ccc0e7265e98db27d3fb8b) Three frames are written on a corked udp socket for which the output netdevice has UFO enabled. If the first and third frame are smaller than the mtu and the second one is bigger, we enqueue the second frame with skb_append_datato_frags without initializing the gso fields. This leads to the third frame appended regulary and thus constructing an invalid skb. This fixes the problem by always using skb_append_datato_frags as soon as the first frag got enqueued to the skb without marking the packet as SKB_GSO_UDP. The problem with only two frames for ipv6 was fixed by "ipv6: udp packets following an UFO enqueued packet need also be handled by UFO" (2811ebac2521ceac84f2bdae402455baa6a7fb47). Signed-off-by: Hannes Frederic Sowa Cc: Jiri Pirko Cc: Eric Dumazet Cc: David Miller Signed-off-by: Greg Kroah-Hartman --- include/linux/skbuff.h | 5 +++++ net/ipv4/ip_output.c | 2 +- net/ipv6/ip6_output.c | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index dec1748cd002..eaf602781635 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -1308,6 +1308,11 @@ static inline int skb_pagelen(const struct sk_buff *skb) return len + skb_headlen(skb); } +static inline bool skb_has_frags(const struct sk_buff *skb) +{ + return skb_shinfo(skb)->nr_frags; +} + /** * __skb_fill_page_desc - initialise a paged fragment in an skb * @skb: buffer containing fragment to be initialised diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index ec2d430a6a55..6ca5873d6175 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -844,7 +844,7 @@ static int __ip_append_data(struct sock *sk, csummode = CHECKSUM_PARTIAL; cork->length += length; - if (((length > mtu) || (skb && skb_is_gso(skb))) && + if (((length > mtu) || (skb && skb_has_frags(skb))) && (sk->sk_protocol == IPPROTO_UDP) && (rt->dst.dev->features & NETIF_F_UFO) && !rt->dst.header_len) { err = ip_ufo_append_data(sk, queue, getfrag, from, length, diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 44ffdb99a62e..12ef531b64ec 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -1250,7 +1250,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, skb = skb_peek_tail(&sk->sk_write_queue); cork->length += length; if (((length > mtu) || - (skb && skb_is_gso(skb))) && + (skb && skb_has_frags(skb))) && (sk->sk_protocol == IPPROTO_UDP) && (rt->dst.dev->features & NETIF_F_UFO)) { err = ip6_ufo_append_data(sk, getfrag, from, length, -- cgit v1.2.3 From 208a6152b633a33722cc53bca47c46b79e88a2ad Mon Sep 17 00:00:00 2001 From: Julian Anastasov Date: Sun, 20 Oct 2013 15:43:03 +0300 Subject: ipv6: always prefer rt6i_gateway if present [ Upstream commit 96dc809514fb2328605198a0602b67554d8cce7b ] In v3.9 6fd6ce2056de2709 ("ipv6: Do not depend on rt->n in ip6_finish_output2()." changed the behaviour of ip6_finish_output2() such that the recently introduced rt6_nexthop() is used instead of an assigned neighbor. As rt6_nexthop() prefers rt6i_gateway only for gatewayed routes this causes a problem for users like IPVS, xt_TEE and RAW(hdrincl) if they want to use different address for routing compared to the destination address. Another case is when redirect can create RTF_DYNAMIC route without RTF_GATEWAY flag, we ignore the rt6i_gateway in rt6_nexthop(). Fix the above problems by considering the rt6i_gateway if present, so that traffic routed to address on local subnet is not wrongly diverted to the destination address. Thanks to Simon Horman and Phil Oester for spotting the problematic commit. Thanks to Hannes Frederic Sowa for his review and help in testing. Reported-by: Phil Oester Reported-by: Mark Brooks Signed-off-by: Julian Anastasov Acked-by: Hannes Frederic Sowa Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/net/ip6_route.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h index 260f83f16bcf..5cba2302a7a6 100644 --- a/include/net/ip6_route.h +++ b/include/net/ip6_route.h @@ -196,7 +196,7 @@ static inline int ip6_skb_dst_mtu(struct sk_buff *skb) static inline struct in6_addr *rt6_nexthop(struct rt6_info *rt, struct in6_addr *dest) { - if (rt->rt6i_flags & RTF_GATEWAY) + if (rt->rt6i_flags & RTF_GATEWAY || !ipv6_addr_any(&rt->rt6i_gateway)) return &rt->rt6i_gateway; return dest; } -- cgit v1.2.3 From 044d6efb797bfa1131bfb510102505ba41bfec52 Mon Sep 17 00:00:00 2001 From: Julian Anastasov Date: Sun, 20 Oct 2013 15:43:04 +0300 Subject: ipv6: fill rt6i_gateway with nexthop address [ Upstream commit 550bab42f83308c9d6ab04a980cc4333cef1c8fa ] Make sure rt6i_gateway contains nexthop information in all routes returned from lookup or when routes are directly attached to skb for generated ICMP packets. The effect of this patch should be a faster version of rt6_nexthop() and the consideration of local addresses as nexthop. Signed-off-by: Julian Anastasov Acked-by: Hannes Frederic Sowa Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/net/ip6_route.h | 6 ++---- net/ipv6/ip6_output.c | 4 ++-- net/ipv6/route.c | 8 ++++++-- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h index 5cba2302a7a6..b906f4a131a4 100644 --- a/include/net/ip6_route.h +++ b/include/net/ip6_route.h @@ -194,11 +194,9 @@ static inline int ip6_skb_dst_mtu(struct sk_buff *skb) skb_dst(skb)->dev->mtu : dst_mtu(skb_dst(skb)); } -static inline struct in6_addr *rt6_nexthop(struct rt6_info *rt, struct in6_addr *dest) +static inline struct in6_addr *rt6_nexthop(struct rt6_info *rt) { - if (rt->rt6i_flags & RTF_GATEWAY || !ipv6_addr_any(&rt->rt6i_gateway)) - return &rt->rt6i_gateway; - return dest; + return &rt->rt6i_gateway; } #endif diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 12ef531b64ec..878f8027ebf6 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -130,7 +130,7 @@ static int ip6_finish_output2(struct sk_buff *skb) } rcu_read_lock_bh(); - nexthop = rt6_nexthop((struct rt6_info *)dst, &ipv6_hdr(skb)->daddr); + nexthop = rt6_nexthop((struct rt6_info *)dst); neigh = __ipv6_neigh_lookup_noref(dst->dev, nexthop); if (unlikely(!neigh)) neigh = __neigh_create(&nd_tbl, nexthop, dst->dev, false); @@ -898,7 +898,7 @@ static int ip6_dst_lookup_tail(struct sock *sk, */ rt = (struct rt6_info *) *dst; rcu_read_lock_bh(); - n = __ipv6_neigh_lookup_noref(rt->dst.dev, rt6_nexthop(rt, &fl6->daddr)); + n = __ipv6_neigh_lookup_noref(rt->dst.dev, rt6_nexthop(rt)); err = n && !(n->nud_state & NUD_VALID) ? -EINVAL : 0; rcu_read_unlock_bh(); diff --git a/net/ipv6/route.c b/net/ipv6/route.c index bacce6c08644..225de3ec8351 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -848,7 +848,6 @@ static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, if (ort->rt6i_dst.plen != 128 && ipv6_addr_equal(&ort->rt6i_dst.addr, daddr)) rt->rt6i_flags |= RTF_ANYCAST; - rt->rt6i_gateway = *daddr; } rt->rt6i_flags |= RTF_CACHE; @@ -1245,6 +1244,7 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, rt->dst.flags |= DST_HOST; rt->dst.output = ip6_output; atomic_set(&rt->dst.__refcnt, 1); + rt->rt6i_gateway = fl6->daddr; rt->rt6i_dst.addr = fl6->daddr; rt->rt6i_dst.plen = 128; rt->rt6i_idev = idev; @@ -1801,7 +1801,10 @@ static struct rt6_info *ip6_rt_copy(struct rt6_info *ort, in6_dev_hold(rt->rt6i_idev); rt->dst.lastuse = jiffies; - rt->rt6i_gateway = ort->rt6i_gateway; + if (ort->rt6i_flags & RTF_GATEWAY) + rt->rt6i_gateway = ort->rt6i_gateway; + else + rt->rt6i_gateway = *dest; rt->rt6i_flags = ort->rt6i_flags; if ((ort->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) == (RTF_DEFAULT | RTF_ADDRCONF)) @@ -2088,6 +2091,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, else rt->rt6i_flags |= RTF_LOCAL; + rt->rt6i_gateway = *addr; rt->rt6i_dst.addr = *addr; rt->rt6i_dst.plen = 128; rt->rt6i_table = fib6_get_table(net, RT6_TABLE_LOCAL); -- cgit v1.2.3 From 2332d212926aaa92d4164482f6f7583c0f796647 Mon Sep 17 00:00:00 2001 From: Julian Anastasov Date: Sun, 20 Oct 2013 15:43:05 +0300 Subject: netfilter: nf_conntrack: fix rt6i_gateway checks for H.323 helper [ Upstream commit 56e42441ed54b092d6c7411138ce60d049e7c731 ] Now when rt6_nexthop() can return nexthop address we can use it for proper nexthop comparison of directly connected destinations. For more information refer to commit bbb5823cf742a7 ("netfilter: nf_conntrack: fix rt_gateway checks for H.323 helper"). Signed-off-by: Julian Anastasov Acked-by: Hannes Frederic Sowa Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/netfilter/nf_conntrack_h323_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c index bdebd03bc8cd..70866d192efc 100644 --- a/net/netfilter/nf_conntrack_h323_main.c +++ b/net/netfilter/nf_conntrack_h323_main.c @@ -778,8 +778,8 @@ static int callforward_do_filter(const union nf_inet_addr *src, flowi6_to_flowi(&fl1), false)) { if (!afinfo->route(&init_net, (struct dst_entry **)&rt2, flowi6_to_flowi(&fl2), false)) { - if (!memcmp(&rt1->rt6i_gateway, &rt2->rt6i_gateway, - sizeof(rt1->rt6i_gateway)) && + if (ipv6_addr_equal(rt6_nexthop(rt1), + rt6_nexthop(rt2)) && rt1->dst.dev == rt2->dst.dev) ret = 1; dst_release(&rt2->dst); -- cgit v1.2.3 From 8df627daa0bde7de4236ab68ef2dded12ab624c8 Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Mon, 21 Oct 2013 06:17:15 +0200 Subject: ipv6: probe routes asynchronous in rt6_probe [ Upstream commit c2f17e827b419918c856131f592df9521e1a38e3 ] Routes need to be probed asynchronous otherwise the call stack gets exhausted when the kernel attemps to deliver another skb inline, like e.g. xt_TEE does, and we probe at the same time. We update neigh->updated still at once, otherwise we would send to many probes. Cc: Julian Anastasov Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv6/route.c | 38 +++++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 225de3ec8351..3c1f493ccc63 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -473,6 +473,24 @@ out: } #ifdef CONFIG_IPV6_ROUTER_PREF +struct __rt6_probe_work { + struct work_struct work; + struct in6_addr target; + struct net_device *dev; +}; + +static void rt6_probe_deferred(struct work_struct *w) +{ + struct in6_addr mcaddr; + struct __rt6_probe_work *work = + container_of(w, struct __rt6_probe_work, work); + + addrconf_addr_solict_mult(&work->target, &mcaddr); + ndisc_send_ns(work->dev, NULL, &work->target, &mcaddr, NULL); + dev_put(work->dev); + kfree(w); +} + static void rt6_probe(struct rt6_info *rt) { struct neighbour *neigh; @@ -496,17 +514,23 @@ static void rt6_probe(struct rt6_info *rt) if (!neigh || time_after(jiffies, neigh->updated + rt->rt6i_idev->cnf.rtr_probe_interval)) { - struct in6_addr mcaddr; - struct in6_addr *target; + struct __rt6_probe_work *work; + + work = kmalloc(sizeof(*work), GFP_ATOMIC); - if (neigh) { + if (neigh && work) neigh->updated = jiffies; + + if (neigh) write_unlock(&neigh->lock); - } - target = (struct in6_addr *)&rt->rt6i_gateway; - addrconf_addr_solict_mult(target, &mcaddr); - ndisc_send_ns(rt->dst.dev, NULL, target, &mcaddr, NULL); + if (work) { + INIT_WORK(&work->work, rt6_probe_deferred); + work->target = rt->rt6i_gateway; + dev_hold(rt->dst.dev); + work->dev = rt->dst.dev; + schedule_work(&work->work); + } } else { out: write_unlock(&neigh->lock); -- cgit v1.2.3 From 9babd8ab0192070535fe1bab8b86d1c7b1e71943 Mon Sep 17 00:00:00 2001 From: Mariusz Ceier Date: Mon, 21 Oct 2013 19:45:04 +0200 Subject: davinci_emac.c: Fix IFF_ALLMULTI setup [ Upstream commit d69e0f7ea95fef8059251325a79c004bac01f018 ] When IFF_ALLMULTI flag is set on interface and IFF_PROMISC isn't, emac_dev_mcast_set should only enable RX of multicasts and reset MACHASH registers. It does this, but afterwards it either sets up multicast MACs filtering or disables RX of multicasts and resets MACHASH registers again, rendering IFF_ALLMULTI flag useless. This patch fixes emac_dev_mcast_set, so that multicast MACs filtering and disabling of RX of multicasts are skipped when IFF_ALLMULTI flag is set. Tested with kernel 2.6.37. Signed-off-by: Mariusz Ceier Acked-by: Mugunthan V N Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/ti/davinci_emac.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c index 860e15ddfbcb..7233610164cd 100644 --- a/drivers/net/ethernet/ti/davinci_emac.c +++ b/drivers/net/ethernet/ti/davinci_emac.c @@ -876,8 +876,7 @@ static void emac_dev_mcast_set(struct net_device *ndev) netdev_mc_count(ndev) > EMAC_DEF_MAX_MULTICAST_ADDRESSES) { mbp_enable = (mbp_enable | EMAC_MBP_RXMCAST); emac_add_mcast(priv, EMAC_ALL_MULTI_SET, NULL); - } - if (!netdev_mc_empty(ndev)) { + } else if (!netdev_mc_empty(ndev)) { struct netdev_hw_addr *ha; mbp_enable = (mbp_enable | EMAC_MBP_RXMCAST); -- cgit v1.2.3 From 4a402463a7a4a4243c9c66600fd01ae800f959e3 Mon Sep 17 00:00:00 2001 From: AKASHI Takahiro Date: Wed, 9 Oct 2013 15:58:29 +0100 Subject: ARM: 7851/1: check for number of arguments in syscall_get/set_arguments() commit 3c1532df5c1b54b5f6246cdef94eeb73a39fe43a upstream. In ftrace_syscall_enter(), syscall_get_arguments(..., 0, n, ...) if (i == 0) { ...; n--;} memcpy(..., n * sizeof(args[0])); If 'number of arguments(n)' is zero and 'argument index(i)' is also zero in syscall_get_arguments(), none of arguments should be copied by memcpy(). Otherwise 'n--' can be a big positive number and unexpected amount of data will be copied. Tracing system calls which take no argument, say sync(void), may hit this case and eventually make the system corrupted. This patch fixes the issue both in syscall_get_arguments() and syscall_set_arguments(). Acked-by: Will Deacon Signed-off-by: AKASHI Takahiro Signed-off-by: Will Deacon Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/include/asm/syscall.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/include/asm/syscall.h b/arch/arm/include/asm/syscall.h index f1d96d4e8092..73ddd7239b33 100644 --- a/arch/arm/include/asm/syscall.h +++ b/arch/arm/include/asm/syscall.h @@ -57,6 +57,9 @@ static inline void syscall_get_arguments(struct task_struct *task, unsigned int i, unsigned int n, unsigned long *args) { + if (n == 0) + return; + if (i + n > SYSCALL_MAX_ARGS) { unsigned long *args_bad = args + SYSCALL_MAX_ARGS - i; unsigned int n_bad = n + i - SYSCALL_MAX_ARGS; @@ -81,6 +84,9 @@ static inline void syscall_set_arguments(struct task_struct *task, unsigned int i, unsigned int n, const unsigned long *args) { + if (n == 0) + return; + if (i + n > SYSCALL_MAX_ARGS) { pr_warning("%s called with max args %d, handling only %d\n", __func__, i + n, SYSCALL_MAX_ARGS); -- cgit v1.2.3 From 77fc96c899a5c926dd8ba6f340f1e04933e7bfd2 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 7 Oct 2013 15:19:53 +0200 Subject: ARM: integrator: deactivate timer0 on the Integrator/CP commit 29114fd7db2fc82a34da8340d29b8fa413e03dca upstream. This fixes a long-standing Integrator/CP regression from commit 870e2928cf3368ca9b06bc925d0027b0a56bcd8e "ARM: integrator-cp: convert use CLKSRC_OF for timer init" When this code was introduced, the both aliases pointing the system to use timer1 as primary (clocksource) and timer2 as secondary (clockevent) was ignored, and the system would simply use the first two timers found as clocksource and clockevent. However this made the system timeline accelerate by a factor x25, as it turns out that the way the clocking actually works (totally undocumented and found after some trial-and-error) is that timer0 runs @ 25MHz and timer1 and timer2 runs @ 1MHz. Presumably this divider setting is a boot-on default and configurable albeit the way to configure it is not documented. So as a quick fix to the problem, let's mark timer0 as disabled, so the code will chose timer1 and timer2 as it used to. This also deletes the two aliases for the primary and secondary timer as they have been superceded by the auto-selection Cc: Rob Herring Cc: Russell King Signed-off-by: Linus Walleij Signed-off-by: Olof Johansson Signed-off-by: Greg Kroah-Hartman --- arch/arm/boot/dts/integratorcp.dts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/arch/arm/boot/dts/integratorcp.dts b/arch/arm/boot/dts/integratorcp.dts index ff1aea0ee043..72693a69f830 100644 --- a/arch/arm/boot/dts/integratorcp.dts +++ b/arch/arm/boot/dts/integratorcp.dts @@ -9,11 +9,6 @@ model = "ARM Integrator/CP"; compatible = "arm,integrator-cp"; - aliases { - arm,timer-primary = &timer2; - arm,timer-secondary = &timer1; - }; - chosen { bootargs = "root=/dev/ram0 console=ttyAMA0,38400n8 earlyprintk"; }; @@ -24,14 +19,18 @@ }; timer0: timer@13000000 { + /* TIMER0 runs @ 25MHz */ compatible = "arm,integrator-cp-timer"; + status = "disabled"; }; timer1: timer@13000100 { + /* TIMER1 runs @ 1MHz */ compatible = "arm,integrator-cp-timer"; }; timer2: timer@13000200 { + /* TIMER2 runs @ 1MHz */ compatible = "arm,integrator-cp-timer"; }; -- cgit v1.2.3 From 5e2672132dbdb79a7d70711ca5c4bd1fa770b7bd Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Tue, 1 Oct 2013 17:35:43 +0300 Subject: gpio/lynxpoint: check if the interrupt is enabled in IRQ handler commit 03d152d5582abc8a1c19cb107164c3724bbd4be4 upstream. Checking LP_INT_STAT is not enough in the interrupt handler because its contents get updated regardless of whether the pin has interrupt enabled or not. This causes the driver to loop forever for GPIOs that are pulled up. Fix this by checking the interrupt enable bit for the pin as well. Signed-off-by: Mika Westerberg Acked-by: Mathias Nyman Signed-off-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman --- drivers/gpio/gpio-lynxpoint.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-lynxpoint.c b/drivers/gpio/gpio-lynxpoint.c index 86c17de87692..71d86143aec5 100644 --- a/drivers/gpio/gpio-lynxpoint.c +++ b/drivers/gpio/gpio-lynxpoint.c @@ -248,14 +248,15 @@ static void lp_gpio_irq_handler(unsigned irq, struct irq_desc *desc) struct lp_gpio *lg = irq_data_get_irq_handler_data(data); struct irq_chip *chip = irq_data_get_irq_chip(data); u32 base, pin, mask; - unsigned long reg, pending; + unsigned long reg, ena, pending; unsigned virq; /* check from GPIO controller which pin triggered the interrupt */ for (base = 0; base < lg->chip.ngpio; base += 32) { reg = lp_gpio_reg(&lg->chip, base, LP_INT_STAT); + ena = lp_gpio_reg(&lg->chip, base, LP_INT_ENABLE); - while ((pending = inl(reg))) { + while ((pending = (inl(reg) & inl(ena)))) { pin = __ffs(pending); mask = BIT(pin); /* Clear before handling so we don't lose an edge */ -- cgit v1.2.3 From 2d99b6dd66b5778d92fc411b48037084528e1ae2 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Wed, 16 Oct 2013 03:17:47 +0100 Subject: dm snapshot: fix data corruption commit e9c6a182649f4259db704ae15a91ac820e63b0ca upstream. This patch fixes a particular type of data corruption that has been encountered when loading a snapshot's metadata from disk. When we allocate a new chunk in persistent_prepare, we increment ps->next_free and we make sure that it doesn't point to a metadata area by further incrementing it if necessary. When we load metadata from disk on device activation, ps->next_free is positioned after the last used data chunk. However, if this last used data chunk is followed by a metadata area, ps->next_free is positioned erroneously to the metadata area. A newly-allocated chunk is placed at the same location as the metadata area, resulting in data or metadata corruption. This patch changes the code so that ps->next_free skips the metadata area when metadata are loaded in function read_exceptions. The patch also moves a piece of code from persistent_prepare_exception to a separate function skip_metadata to avoid code duplication. CVE-2013-4299 Signed-off-by: Mikulas Patocka Cc: Mike Snitzer Signed-off-by: Alasdair G Kergon Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-snap-persistent.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/md/dm-snap-persistent.c b/drivers/md/dm-snap-persistent.c index 4caa8e6d59d7..2d2b1b7588d7 100644 --- a/drivers/md/dm-snap-persistent.c +++ b/drivers/md/dm-snap-persistent.c @@ -269,6 +269,14 @@ static chunk_t area_location(struct pstore *ps, chunk_t area) return NUM_SNAPSHOT_HDR_CHUNKS + ((ps->exceptions_per_area + 1) * area); } +static void skip_metadata(struct pstore *ps) +{ + uint32_t stride = ps->exceptions_per_area + 1; + chunk_t next_free = ps->next_free; + if (sector_div(next_free, stride) == NUM_SNAPSHOT_HDR_CHUNKS) + ps->next_free++; +} + /* * Read or write a metadata area. Remembering to skip the first * chunk which holds the header. @@ -502,6 +510,8 @@ static int read_exceptions(struct pstore *ps, ps->current_area--; + skip_metadata(ps); + return 0; } @@ -616,8 +626,6 @@ static int persistent_prepare_exception(struct dm_exception_store *store, struct dm_exception *e) { struct pstore *ps = get_info(store); - uint32_t stride; - chunk_t next_free; sector_t size = get_dev_size(dm_snap_cow(store->snap)->bdev); /* Is there enough room ? */ @@ -630,10 +638,8 @@ static int persistent_prepare_exception(struct dm_exception_store *store, * Move onto the next free pending, making sure to take * into account the location of the metadata chunks. */ - stride = (ps->exceptions_per_area + 1); - next_free = ++ps->next_free; - if (sector_div(next_free, stride) == 1) - ps->next_free++; + ps->next_free++; + skip_metadata(ps); atomic_inc(&ps->pending_count); return 0; -- cgit v1.2.3 From fe0051d83cb951fbeab6712633ca2e31de22ee11 Mon Sep 17 00:00:00 2001 From: James Ralston Date: Tue, 24 Sep 2013 16:47:55 -0700 Subject: i2c: ismt: initialize DMA buffer commit bf4169100c909667ede6af67668b3ecce6928343 upstream. This patch adds code to initialize the DMA buffer to compensate for possible hardware data corruption. Signed-off-by: James Ralston [wsa: changed to use 'sizeof'] Signed-off-by: Wolfram Sang Cc: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/busses/i2c-ismt.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/i2c/busses/i2c-ismt.c b/drivers/i2c/busses/i2c-ismt.c index cd82eb44e4c4..7c9f053556f2 100644 --- a/drivers/i2c/busses/i2c-ismt.c +++ b/drivers/i2c/busses/i2c-ismt.c @@ -393,6 +393,9 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr, desc = &priv->hw[priv->head]; + /* Initialize the DMA buffer */ + memset(priv->dma_buffer, 0, sizeof(priv->dma_buffer)); + /* Initialize the descriptor */ memset(desc, 0, sizeof(struct ismt_desc)); desc->tgtaddr_rw = ISMT_DESC_ADDR_RW(addr, read_write); -- cgit v1.2.3 From 7ed008638ee15991b79d8867d382e141fee89a69 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Wed, 16 Oct 2013 13:47:08 -0700 Subject: mm: fix BUG in __split_huge_page_pmd commit 750e8165f5e87b6a142be953640eabb13a9d350a upstream. Occasionally we hit the BUG_ON(pmd_trans_huge(*pmd)) at the end of __split_huge_page_pmd(): seen when doing madvise(,,MADV_DONTNEED). It's invalid: we don't always have down_write of mmap_sem there: a racing do_huge_pmd_wp_page() might have copied-on-write to another huge page before our split_huge_page() got the anon_vma lock. Forget the BUG_ON, just go back and try again if this happens. Signed-off-by: Hugh Dickins Acked-by: Kirill A. Shutemov Cc: Andrea Arcangeli Cc: Naoya Horiguchi Cc: David Rientjes Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/huge_memory.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/mm/huge_memory.c b/mm/huge_memory.c index b92d0ce428b1..0164b09c1e99 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -2699,6 +2699,7 @@ void __split_huge_page_pmd(struct vm_area_struct *vma, unsigned long address, mmun_start = haddr; mmun_end = haddr + HPAGE_PMD_SIZE; +again: mmu_notifier_invalidate_range_start(mm, mmun_start, mmun_end); spin_lock(&mm->page_table_lock); if (unlikely(!pmd_trans_huge(*pmd))) { @@ -2721,7 +2722,14 @@ void __split_huge_page_pmd(struct vm_area_struct *vma, unsigned long address, split_huge_page(page); put_page(page); - BUG_ON(pmd_trans_huge(*pmd)); + + /* + * We don't always have down_write of mmap_sem here: a racing + * do_huge_pmd_wp_page() might have copied-on-write to another + * huge page before our split_huge_page() got the anon_vma lock. + */ + if (unlikely(pmd_trans_huge(*pmd))) + goto again; } void split_huge_page_pmd_mm(struct mm_struct *mm, unsigned long address, -- cgit v1.2.3 From 1f931f65de9d04daf024eeb4dd6a8fe93b7a8e91 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 14 Oct 2013 16:02:15 +0200 Subject: ALSA: us122l: Fix pcm_usb_stream mmapping regression commit ac536a848a1643e4b87e8fbd376a63091afc2ccc upstream. The pcm_usb_stream plugin requires the mremap explicitly for the read buffer, as it expands itself once after reading the required size. But the commit [314e51b9: mm: kill vma flag VM_RESERVED and mm->reserved_vm counter] converted blindly to a combination of VM_DONTEXPAND | VM_DONTDUMP like other normal drivers, and this resulted in the failure of mremap(). For fixing this regression, we need to remove VM_DONTEXPAND for the read-buffer mmap. Reported-and-tested-by: James Miller Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/usb/usx2y/us122l.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/usb/usx2y/us122l.c b/sound/usb/usx2y/us122l.c index d0323a693ba2..999550bbad40 100644 --- a/sound/usb/usx2y/us122l.c +++ b/sound/usb/usx2y/us122l.c @@ -262,7 +262,9 @@ static int usb_stream_hwdep_mmap(struct snd_hwdep *hw, } area->vm_ops = &usb_stream_hwdep_vm_ops; - area->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP; + area->vm_flags |= VM_DONTDUMP; + if (!read) + area->vm_flags |= VM_DONTEXPAND; area->vm_private_data = us122l; atomic_inc(&us122l->mmap_count); out: -- cgit v1.2.3 From 1c4bd2b14d14f524c51839c64aa3f79a81622562 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Mon, 14 Oct 2013 10:16:22 +0200 Subject: ALSA: hda - Fix inverted internal mic not indicated on some machines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit ccb041571b73888785ef7828a276e380125891a4 upstream. The create_bind_cap_vol_ctl does not create any control indicating that an inverted dmic is present. Therefore, create multiple capture volumes in this scenario, so we always have some indication that the internal mic is inverted. This happens on the Lenovo Ideapad U310 as well as the Lenovo Yoga 13 (both are based on the CX20590 codec), but the fix is generic and could be needed for other codecs/machines too. Thanks to Szymon Acedański for the pointer and a draft patch. BugLink: https://bugs.launchpad.net/bugs/1239392 BugLink: https://bugs.launchpad.net/bugs/1227491 Reported-by: Szymon Acedański Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/hda_generic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index ad22decad02b..2519f9d03c0f 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c @@ -3474,7 +3474,7 @@ static int create_capture_mixers(struct hda_codec *codec) if (!multi) err = create_single_cap_vol_ctl(codec, n, vol, sw, inv_dmic); - else if (!multi_cap_vol) + else if (!multi_cap_vol && !inv_dmic) err = create_bind_cap_vol_ctl(codec, n, vol, sw); else err = create_multi_cap_vol_ctl(codec); -- cgit v1.2.3 From 71c908a0e5c0bbc2e8ad5f9578b9529a1e6ec8aa Mon Sep 17 00:00:00 2001 From: Fengguang Wu Date: Wed, 16 Oct 2013 13:47:03 -0700 Subject: writeback: fix negative bdi max pause MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit e3b6c655b91e01a1dade056cfa358581b47a5351 upstream. Toralf runs trinity on UML/i386. After some time it hangs and the last message line is BUG: soft lockup - CPU#0 stuck for 22s! [trinity-child0:1521] It's found that pages_dirtied becomes very large. More than 1000000000 pages in this case: period = HZ * pages_dirtied / task_ratelimit; BUG_ON(pages_dirtied > 2000000000); BUG_ON(pages_dirtied > 1000000000); <--------- UML debug printf shows that we got negative pause here: ick: pause : -984 ick: pages_dirtied : 0 ick: task_ratelimit: 0 pause: + if (pause < 0) { + extern int printf(char *, ...); + printf("ick : pause : %li\n", pause); + printf("ick: pages_dirtied : %lu\n", pages_dirtied); + printf("ick: task_ratelimit: %lu\n", task_ratelimit); + BUG_ON(1); + } trace_balance_dirty_pages(bdi, Since pause is bounded by [min_pause, max_pause] where min_pause is also bounded by max_pause. It's suspected and demonstrated that the max_pause calculation goes wrong: ick: pause : -717 ick: min_pause : -177 ick: max_pause : -717 ick: pages_dirtied : 14 ick: task_ratelimit: 0 The problem lies in the two "long = unsigned long" assignments in bdi_max_pause() which might go negative if the highest bit is 1, and the min_t(long, ...) check failed to protect it falling under 0. Fix all of them by using "unsigned long" throughout the function. Signed-off-by: Fengguang Wu Reported-by: Toralf Förster Tested-by: Toralf Förster Reviewed-by: Jan Kara Cc: Richard Weinberger Cc: Geert Uytterhoeven Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/page-writeback.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 4514ad7415c3..aca4364275b5 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -1104,11 +1104,11 @@ static unsigned long dirty_poll_interval(unsigned long dirty, return 1; } -static long bdi_max_pause(struct backing_dev_info *bdi, - unsigned long bdi_dirty) +static unsigned long bdi_max_pause(struct backing_dev_info *bdi, + unsigned long bdi_dirty) { - long bw = bdi->avg_write_bandwidth; - long t; + unsigned long bw = bdi->avg_write_bandwidth; + unsigned long t; /* * Limit pause time for small memory systems. If sleeping for too long @@ -1120,7 +1120,7 @@ static long bdi_max_pause(struct backing_dev_info *bdi, t = bdi_dirty / (1 + bw / roundup_pow_of_two(1 + HZ / 8)); t++; - return min_t(long, t, MAX_PAUSE); + return min_t(unsigned long, t, MAX_PAUSE); } static long bdi_min_pause(struct backing_dev_info *bdi, -- cgit v1.2.3 From add8ec07b2a000af11be64a89b99afc8c90797e5 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 11 Oct 2013 14:47:05 +0200 Subject: wireless: radiotap: fix parsing buffer overrun commit f5563318ff1bde15b10e736e97ffce13be08bc1a upstream. When parsing an invalid radiotap header, the parser can overrun the buffer that is passed in because it doesn't correctly check 1) the minimum radiotap header size 2) the space for extended bitmaps The first issue doesn't affect any in-kernel user as they all check the minimum size before calling the radiotap function. The second issue could potentially affect the kernel if an skb is passed in that consists only of the radiotap header with a lot of extended bitmaps that extend past the SKB. In that case a read-only buffer overrun by at most 4 bytes is possible. Fix this by adding the appropriate checks to the parser. Reported-by: Evan Huus Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/wireless/radiotap.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/net/wireless/radiotap.c b/net/wireless/radiotap.c index 7d604c06c3dc..a271c27fac77 100644 --- a/net/wireless/radiotap.c +++ b/net/wireless/radiotap.c @@ -97,6 +97,10 @@ int ieee80211_radiotap_iterator_init( struct ieee80211_radiotap_header *radiotap_header, int max_length, const struct ieee80211_radiotap_vendor_namespaces *vns) { + /* check the radiotap header can actually be present */ + if (max_length < sizeof(struct ieee80211_radiotap_header)) + return -EINVAL; + /* Linux only supports version 0 radiotap format */ if (radiotap_header->it_version) return -EINVAL; @@ -131,7 +135,8 @@ int ieee80211_radiotap_iterator_init( */ if ((unsigned long)iterator->_arg - - (unsigned long)iterator->_rtheader > + (unsigned long)iterator->_rtheader + + sizeof(uint32_t) > (unsigned long)iterator->_max_length) return -EINVAL; } -- cgit v1.2.3 From bfddde1b4056f5b7d0d365606000df3442b82cd0 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Mon, 14 Oct 2013 23:21:15 +0200 Subject: serial: vt8500: add missing braces commit d969de8d83401683420638c8107dcfedb2146f37 upstream. Due to missing braces on an if statement, in presence of a device_node a port was always assigned -1, regardless of any alias entries in the device tree. Conversely, if device_node was NULL, an unitialized port ended up being used. This patch adds the missing braces, fixing the issues. Signed-off-by: Roel Kluin Acked-by: Tony Prisk Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/vt8500_serial.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/tty/serial/vt8500_serial.c b/drivers/tty/serial/vt8500_serial.c index 1a8bc2275ea4..f72b43fbbef9 100644 --- a/drivers/tty/serial/vt8500_serial.c +++ b/drivers/tty/serial/vt8500_serial.c @@ -559,12 +559,13 @@ static int vt8500_serial_probe(struct platform_device *pdev) if (!mmres || !irqres) return -ENODEV; - if (np) + if (np) { port = of_alias_get_id(np, "serial"); if (port >= VT8500_MAX_PORTS) port = -1; - else + } else { port = -1; + } if (port < 0) { /* calculate the port id */ -- cgit v1.2.3 From e81e74f12005c5303cc26558b1b5c4294a0be4e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Elio=20Petten=C3=B2?= Date: Tue, 8 Oct 2013 20:03:37 +0100 Subject: USB: serial: ti_usb_3410_5052: add Abbott strip port ID to combined table as well. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit c9d09dc7ad106492c17c587b6eeb99fe3f43e522 upstream. Without this change, the USB cable for Freestyle Option and compatible glucometers will not be detected by the driver. Signed-off-by: Diego Elio Pettenò Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ti_usb_3410_5052.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 32bdd5eac59b..4cc84c0c990d 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -203,6 +203,7 @@ static struct usb_device_id ti_id_table_combined[19+2*TI_EXTRA_VID_PID_COUNT+1] { USB_DEVICE(IBM_VENDOR_ID, IBM_454B_PRODUCT_ID) }, { USB_DEVICE(IBM_VENDOR_ID, IBM_454C_PRODUCT_ID) }, { USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_PRODUCT_ID) }, + { USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_STRIP_PORT_ID) }, { USB_DEVICE(TI_VENDOR_ID, FRI2_PRODUCT_ID) }, { } }; -- cgit v1.2.3 From 961e551e0f2e2acf2adc7465544ef25c5852a0ac Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 5 Oct 2013 18:14:18 -0700 Subject: USB: serial: option: add support for Inovia SEW858 device commit f4c19b8e165cff1a6607c21f8809441d61cab7ec upstream. This patch adds the device id for the Inovia SEW858 device to the option driver. Reported-by: Pavel Parkhomenko Tested-by: Pavel Parkhomenko Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 80a7104d5ddb..c57dac7acaa7 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -451,6 +451,10 @@ static void option_instat_callback(struct urb *urb); #define CHANGHONG_VENDOR_ID 0x2077 #define CHANGHONG_PRODUCT_CH690 0x7001 +/* Inovia */ +#define INOVIA_VENDOR_ID 0x20a6 +#define INOVIA_SEW858 0x1105 + /* some devices interfaces need special handling due to a number of reasons */ enum option_blacklist_reason { OPTION_BLACKLIST_NONE = 0, @@ -1345,6 +1349,7 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d03, 0xff, 0x00, 0x00) }, { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e01, 0xff, 0xff, 0xff) }, /* D-Link DWM-152/C1 */ { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e02, 0xff, 0xff, 0xff) }, /* D-Link DWM-156/C1 */ + { USB_DEVICE(INOVIA_VENDOR_ID, INOVIA_SEW858) }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, option_ids); -- cgit v1.2.3 From adc6b15872611b75ae523d6784074d2ed84b1c4e Mon Sep 17 00:00:00 2001 From: Enrico Mioso Date: Tue, 15 Oct 2013 15:06:47 +0200 Subject: usb: serial: option: blacklist Olivetti Olicard200 commit fd8573f5828873343903215f203f14dc82de397c upstream. Interface 6 of this device speaks QMI as per tests done by us. Credits go to Antonella for providing the hardware. Signed-off-by: Enrico Mioso Signed-off-by: Antonella Pellizzari Tested-by: Dan Williams Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index c57dac7acaa7..f1507c052a2e 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -1261,7 +1261,9 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100) }, { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD145) }, - { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD200) }, + { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD200), + .driver_info = (kernel_ulong_t)&net_intf6_blacklist + }, { USB_DEVICE(CELOT_VENDOR_ID, CELOT_PRODUCT_CT680M) }, /* CT-650 CDMA 450 1xEVDO modem */ { USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_GT_B3730, USB_CLASS_CDC_DATA, 0x00, 0x00) }, /* Samsung GT-B3730 LTE USB modem.*/ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEM600) }, -- cgit v1.2.3 From 4e77f7f1261f65cff06918bc5e66d02a418fc842 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 4 Nov 2013 04:31:29 -0800 Subject: Linux 3.10.18 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 5c7d3d63d376..5fb14e503fe3 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 10 -SUBLEVEL = 17 +SUBLEVEL = 18 EXTRAVERSION = NAME = TOSSUG Baby Fish -- cgit v1.2.3 From b910ef250be4f872e383c62d1dfc40641b6f1c5b Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Mon, 14 Oct 2013 15:24:55 +0200 Subject: usb-storage: add quirk for mandatory READ_CAPACITY_16 commit 32c37fc30c52508711ea6a108cfd5855b8a07176 upstream. Some USB drive enclosures do not correctly report an overflow condition if they hold a drive with a capacity over 2TB and are confronted with a READ_CAPACITY_10. They answer with their capacity modulo 2TB. The generic layer cannot cope with that. It must be told to use READ_CAPACITY_16 from the beginning. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/scsiglue.c | 5 ++++- drivers/usb/storage/unusual_devs.h | 7 +++++++ include/linux/usb_usual.h | 4 +++- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index 92b05d95ec5e..5db153260827 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c @@ -211,8 +211,11 @@ static int slave_configure(struct scsi_device *sdev) /* * Many devices do not respond properly to READ_CAPACITY_16. * Tell the SCSI layer to try READ_CAPACITY_10 first. + * However some USB 3.0 drive enclosures return capacity + * modulo 2TB. Those must use READ_CAPACITY_16 */ - sdev->try_rc_10_first = 1; + if (!(us->fflags & US_FL_NEEDS_CAP16)) + sdev->try_rc_10_first = 1; /* assume SPC3 or latter devices support sense size > 18 */ if (sdev->scsi_level > SCSI_SPC_2) diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index c015f2c16729..de32cfa5bfa6 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1925,6 +1925,13 @@ UNUSUAL_DEV( 0x1652, 0x6600, 0x0201, 0x0201, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), +/* Reported by Oliver Neukum */ +UNUSUAL_DEV( 0x174c, 0x55aa, 0x0100, 0x0100, + "ASMedia", + "AS2105", + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_NEEDS_CAP16), + /* Reported by Jesse Feddema */ UNUSUAL_DEV( 0x177f, 0x0400, 0x0000, 0x0000, "Yarvik", diff --git a/include/linux/usb_usual.h b/include/linux/usb_usual.h index bf99cd01be20..630356866030 100644 --- a/include/linux/usb_usual.h +++ b/include/linux/usb_usual.h @@ -66,7 +66,9 @@ US_FLAG(INITIAL_READ10, 0x00100000) \ /* Initial READ(10) (and others) must be retried */ \ US_FLAG(WRITE_CACHE, 0x00200000) \ - /* Write Cache status is not available */ + /* Write Cache status is not available */ \ + US_FLAG(NEEDS_CAP16, 0x00400000) + /* cannot handle READ_CAPACITY_10 */ #define US_FLAG(name, value) US_FL_##name = value , enum { US_DO_ALL_FLAGS }; -- cgit v1.2.3 From 75094c77c2e413cf85ca797f9f352ecc4c3533ad Mon Sep 17 00:00:00 2001 From: "Fangxiaozhi (Franko)" Date: Fri, 11 Oct 2013 03:48:21 +0000 Subject: USB: support new huawei devices in option.c commit d544db293a44a2a3b09feab7dbd59668b692de71 upstream. Add new supporting declarations to option.c, to support Huawei new devices with new bInterfaceSubClass value. Signed-off-by: fangxiaozhi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 216 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 216 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index f1507c052a2e..acaee066b99a 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -693,6 +693,222 @@ static const struct usb_device_id option_ids[] = { { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x7A) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x7B) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x7C) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x01) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x02) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x03) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x04) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x05) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x06) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x0A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x0B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x0D) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x0E) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x0F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x10) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x12) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x13) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x14) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x15) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x17) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x18) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x19) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x1A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x1B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x1C) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x31) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x32) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x33) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x34) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x35) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x36) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x3A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x3B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x3D) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x3E) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x3F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x48) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x49) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x4A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x4B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x4C) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x61) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x62) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x63) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x64) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x65) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x66) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x6A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x6B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x6D) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x6E) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x6F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x78) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x79) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x7A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x7B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x7C) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x01) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x02) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x03) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x04) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x05) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x06) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x0A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x0B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x0D) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x0E) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x0F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x10) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x12) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x13) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x14) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x15) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x17) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x18) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x19) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x1A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x1B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x1C) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x31) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x32) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x33) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x34) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x35) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x36) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x3A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x3B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x3D) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x3E) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x3F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x48) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x49) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x4A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x4B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x4C) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x61) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x62) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x63) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x64) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x65) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x66) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x6A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x6B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x6D) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x6E) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x6F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x78) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x79) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x7A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x7B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x7C) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x01) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x02) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x03) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x04) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x05) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x06) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x0A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x0B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x0D) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x0E) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x0F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x10) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x12) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x13) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x14) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x15) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x17) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x18) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x19) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x1A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x1B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x1C) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x31) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x32) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x33) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x34) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x35) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x36) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x3A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x3B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x3D) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x3E) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x3F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x48) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x49) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x4A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x4B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x4C) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x61) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x62) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x63) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x64) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x65) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x66) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x6A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x6B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x6D) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x6E) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x6F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x78) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x79) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x7A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x7B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x7C) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x01) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x02) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x03) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x04) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x05) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x06) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x0A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x0B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x0D) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x0E) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x0F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x10) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x12) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x13) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x14) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x15) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x17) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x18) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x19) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x1A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x1B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x1C) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x31) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x32) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x33) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x34) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x35) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x36) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x3A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x3B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x3D) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x3E) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x3F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x48) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x49) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x4A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x4B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x4C) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x61) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x62) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x63) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x64) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x65) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x66) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x6A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x6B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x6D) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x6E) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x6F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x78) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x79) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x7A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x7B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x7C) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) }, -- cgit v1.2.3 From ac1acaf7b6cb48562f6466e4f793d0f24a5726d8 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Mon, 14 Oct 2013 16:22:40 +0200 Subject: USB: quirks.c: add one device that cannot deal with suspension commit 4294bca7b423d1a5aa24307e3d112a04075e3763 upstream. The device is not responsive when resumed, unless it is reset. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/quirks.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index 5b44cd47da5b..b23f71f669a9 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -130,6 +130,9 @@ static const struct usb_device_id usb_quirk_list[] = { /* Broadcom BCM92035DGROM BT dongle */ { USB_DEVICE(0x0a5c, 0x2021), .driver_info = USB_QUIRK_RESET_RESUME }, + /* MAYA44USB sound device */ + { USB_DEVICE(0x0a92, 0x0091), .driver_info = USB_QUIRK_RESET_RESUME }, + /* Action Semiconductor flash disk */ { USB_DEVICE(0x10d6, 0x2200), .driver_info = USB_QUIRK_STRING_FETCH_255 }, -- cgit v1.2.3 From 59fa93ea76e2de29910bab0a49dbb14f56b79aea Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Wed, 16 Oct 2013 12:26:07 +0200 Subject: USB: quirks: add touchscreen that is dazzeled by remote wakeup commit 614ced91fc6fbb5a1cdd12f0f1b6c9197d9f1350 upstream. The device descriptors are messed up after remote wakeup Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/quirks.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index b23f71f669a9..01fe36273f3b 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -97,6 +97,9 @@ static const struct usb_device_id usb_quirk_list[] = { /* Alcor Micro Corp. Hub */ { USB_DEVICE(0x058f, 0x9254), .driver_info = USB_QUIRK_RESET_RESUME }, + /* MicroTouch Systems touchscreen */ + { USB_DEVICE(0x0596, 0x051e), .driver_info = USB_QUIRK_RESET_RESUME }, + /* appletouch */ { USB_DEVICE(0x05ac, 0x021a), .driver_info = USB_QUIRK_RESET_RESUME }, -- cgit v1.2.3 From a73e47ff525d2a69d61767a5928ba00937f77e1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B5=D0=B9=20=D0=9A=D1=80?= =?UTF-8?q?=D0=B0=D0=BC=D0=B0=D1=80=D0=B5=D0=BD=D0=BA=D0=BE?= Date: Fri, 1 Nov 2013 17:26:38 +0400 Subject: USB: serial: ftdi_sio: add id for Z3X Box device commit e1466ad5b1aeda303f9282463d55798d2eda218c upstream. Custom VID/PID for Z3X Box device, popular tool for cellphone flashing. Signed-off-by: Alexey E. Kramarenko Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 1 + drivers/usb/serial/ftdi_sio_ids.h | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index b65e657c641d..aa3aed5458a6 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -906,6 +906,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_LUMEL_PD12_PID) }, /* Crucible Devices */ { USB_DEVICE(FTDI_VID, FTDI_CT_COMET_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_Z3X_PID) }, { }, /* Optional parameter entry */ { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 1b8af461b522..a7019d1e3058 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -1307,3 +1307,9 @@ * Manufacturer: Crucible Technologies */ #define FTDI_CT_COMET_PID 0x8e08 + +/* + * Product: Z3X Box + * Manufacturer: Smart GSM Team + */ +#define FTDI_Z3X_PID 0x0011 -- cgit v1.2.3 From 40f3a9e5aea1753ececbcbbfe483b0c05788b001 Mon Sep 17 00:00:00 2001 From: Russ Anderson Date: Mon, 14 Oct 2013 11:17:34 -0500 Subject: x86: Update UV3 hub revision ID commit dd3c9c4b603c664fedc12facf180db0f1794aafe upstream. The UV3 hub revision ID is different than expected. The first revision was supposed to start at 1 but instead will start at 0. Signed-off-by: Russ Anderson Link: http://lkml.kernel.org/r/20131014161733.GA6274@sgi.com Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/apic/x2apic_uv_x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c index 794f6eb54cd3..b32dbb411a9a 100644 --- a/arch/x86/kernel/apic/x2apic_uv_x.c +++ b/arch/x86/kernel/apic/x2apic_uv_x.c @@ -98,7 +98,7 @@ static int __init early_get_pnodeid(void) break; case UV3_HUB_PART_NUMBER: case UV3_HUB_PART_NUMBER_X: - uv_min_hub_revision_id += UV3_HUB_REVISION_BASE - 1; + uv_min_hub_revision_id += UV3_HUB_REVISION_BASE; break; } -- cgit v1.2.3 From f606b358df6e174cd57f0509e5f5299bd4a73854 Mon Sep 17 00:00:00 2001 From: Dirk Brandewie Date: Tue, 15 Oct 2013 11:06:14 -0700 Subject: cpufreq / intel_pstate: Fix max_perf_pct on resume commit 52e0a509e5d6f902ec26bc2a8bb02b137dc453be upstream. If the system is suspended while max_perf_pct is less than 100 percent or no_turbo set policy->{min,max} will be set incorrectly with scaled values which turn the scaled values into hard limits. References: https://bugzilla.kernel.org/show_bug.cgi?id=61241 Reported-by: Patrick Bartels Signed-off-by: Dirk Brandewie Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- drivers/cpufreq/intel_pstate.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 6d6a0b48eb75..9520e3b90bde 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -629,8 +629,8 @@ static int __cpuinit intel_pstate_cpu_exit(struct cpufreq_policy *policy) static int __cpuinit intel_pstate_cpu_init(struct cpufreq_policy *policy) { - int rc, min_pstate, max_pstate; struct cpudata *cpu; + int rc; rc = intel_pstate_init_cpu(policy->cpu); if (rc) @@ -644,9 +644,8 @@ static int __cpuinit intel_pstate_cpu_init(struct cpufreq_policy *policy) else policy->policy = CPUFREQ_POLICY_POWERSAVE; - intel_pstate_get_min_max(cpu, &min_pstate, &max_pstate); - policy->min = min_pstate * 100000; - policy->max = max_pstate * 100000; + policy->min = cpu->pstate.min_pstate * 100000; + policy->max = cpu->pstate.turbo_pstate * 100000; /* cpuinfo and default policy values */ policy->cpuinfo.min_freq = cpu->pstate.min_pstate * 100000; -- cgit v1.2.3 From 955a23e181561a792d6e4c1572848b7ba306499f Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Tue, 22 Oct 2013 15:35:50 -0700 Subject: bcache: Fixed incorrect order of arguments to bio_alloc_bioset() commit d4eddd42f592a0cf06818fae694a3d271f842e4d upstream. Signed-off-by: Kent Overstreet Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/md/bcache/request.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c index cbcf8b301edc..a30a0f8a41c0 100644 --- a/drivers/md/bcache/request.c +++ b/drivers/md/bcache/request.c @@ -1059,7 +1059,7 @@ static void request_write(struct cached_dev *dc, struct search *s) if (bio->bi_rw & REQ_FLUSH) { /* Also need to send a flush to the backing device */ - struct bio *flush = bio_alloc_bioset(0, GFP_NOIO, + struct bio *flush = bio_alloc_bioset(GFP_NOIO, 0, dc->disk.bio_split); flush->bi_rw = WRITE_FLUSH; -- cgit v1.2.3 From 5be794dc4bb66266acc91eb589ace48e82a6c77e Mon Sep 17 00:00:00 2001 From: Anjana V Kumar Date: Sat, 12 Oct 2013 10:59:17 +0800 Subject: cgroup: fix to break the while loop in cgroup_attach_task() correctly commit ea84753c98a7ac6b74e530b64c444a912b3835ca upstream. Both Anjana and Eunki reported a stall in the while_each_thread loop in cgroup_attach_task(). It's because, when we attach a single thread to a cgroup, if the cgroup is exiting or is already in that cgroup, we won't break the loop. If the task is already in the cgroup, the bug can lead to another thread being attached to the cgroup unexpectedly: # echo 5207 > tasks # cat tasks 5207 # echo 5207 > tasks # cat tasks 5207 5215 What's worse, if the task to be attached isn't the leader of the thread group, we might never exit the loop, hence cpu stall. Thanks for Oleg's analysis. This bug was introduced by commit 081aa458c38ba576bdd4265fc807fa95b48b9e79 ("cgroup: consolidate cgroup_attach_task() and cgroup_attach_proc()") [ lizf: - fixed the first continue, pointed out by Oleg, - rewrote changelog. ] Reported-by: Eunki Kim Reported-by: Anjana V Kumar Signed-off-by: Anjana V Kumar Signed-off-by: Li Zefan Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- kernel/cgroup.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 2e9b387971d1..b6b26faf1740 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -1995,7 +1995,7 @@ static int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk, /* @tsk either already exited or can't exit until the end */ if (tsk->flags & PF_EXITING) - continue; + goto next; /* as per above, nr_threads may decrease, but not increase. */ BUG_ON(i >= group_size); @@ -2003,7 +2003,7 @@ static int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk, ent.cgrp = task_cgroup_from_root(tsk, root); /* nothing to do if this task is already in the cgroup */ if (ent.cgrp == cgrp) - continue; + goto next; /* * saying GFP_ATOMIC has no effect here because we did prealloc * earlier, but it's good form to communicate our expectations. @@ -2011,7 +2011,7 @@ static int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk, retval = flex_array_put(group, i, &ent, GFP_ATOMIC); BUG_ON(retval != 0); i++; - + next: if (!threadgroup) break; } while_each_thread(leader, tsk); -- cgit v1.2.3 From 715a606d73f63e94259e6251565e6e12e3271d0f Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Mon, 16 Sep 2013 11:12:07 +0300 Subject: mac80211: correctly close cancelled scans commit a754055a1296fcbe6f32de3a5eaca6efb2fd1865 upstream. __ieee80211_scan_completed is called from a worker. This means that the following flow is possible. * driver calls ieee80211_scan_completed * mac80211 cancels the scan (that is already complete) * __ieee80211_scan_completed runs When scan_work will finally run, it will see that the scan hasn't been aborted and might even trigger another scan on another band. This leads to a situation where cfg80211's scan is not done and no further scan can be issued. Fix this by setting a new flag when a HW scan is being cancelled so that no other scan will be triggered. Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/mac80211/ieee80211_i.h | 3 +++ net/mac80211/scan.c | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 9ca8e3278cc0..92ef04c72c51 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -842,6 +842,8 @@ struct tpt_led_trigger { * that the scan completed. * @SCAN_ABORTED: Set for our scan work function when the driver reported * a scan complete for an aborted scan. + * @SCAN_HW_CANCELLED: Set for our scan work function when the scan is being + * cancelled. */ enum { SCAN_SW_SCANNING, @@ -849,6 +851,7 @@ enum { SCAN_ONCHANNEL_SCANNING, SCAN_COMPLETED, SCAN_ABORTED, + SCAN_HW_CANCELLED, }; /** diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 99b103921a4b..eb03337b6545 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -202,6 +202,9 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local) enum ieee80211_band band; int i, ielen, n_chans; + if (test_bit(SCAN_HW_CANCELLED, &local->scanning)) + return false; + do { if (local->hw_scan_band == IEEE80211_NUM_BANDS) return false; @@ -878,7 +881,23 @@ void ieee80211_scan_cancel(struct ieee80211_local *local) if (!local->scan_req) goto out; + /* + * We have a scan running and the driver already reported completion, + * but the worker hasn't run yet or is stuck on the mutex - mark it as + * cancelled. + */ + if (test_bit(SCAN_HW_SCANNING, &local->scanning) && + test_bit(SCAN_COMPLETED, &local->scanning)) { + set_bit(SCAN_HW_CANCELLED, &local->scanning); + goto out; + } + if (test_bit(SCAN_HW_SCANNING, &local->scanning)) { + /* + * Make sure that __ieee80211_scan_completed doesn't trigger a + * scan on another band. + */ + set_bit(SCAN_HW_CANCELLED, &local->scanning); if (local->ops->cancel_hw_scan) drv_cancel_hw_scan(local, rcu_dereference_protected(local->scan_sdata, -- cgit v1.2.3 From d7da0fc72d073181e65970edad0a9461542e02c6 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 17 Sep 2013 11:15:43 +0200 Subject: mac80211: drop spoofed packets in ad-hoc mode commit 6329b8d917adc077caa60c2447385554130853a3 upstream. If an Ad-Hoc node receives packets with the Cell ID or its own MAC address as source address, it hits a WARN_ON in sta_info_insert_check() With many packets, this can massively spam the logs. One way that this can easily happen is through having Cisco APs in the area with rouge AP detection and countermeasures enabled. Such Cisco APs will regularly send fake beacons, disassoc and deauth packets that trigger these warnings. To fix this issue, drop such spoofed packets early in the rx path. Reported-by: Thomas Huehn Signed-off-by: Felix Fietkau Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/mac80211/rx.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 83f6d29202aa..ec09bcba9bae 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -3002,6 +3002,9 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx, case NL80211_IFTYPE_ADHOC: if (!bssid) return 0; + if (ether_addr_equal(sdata->vif.addr, hdr->addr2) || + ether_addr_equal(sdata->u.ibss.bssid, hdr->addr2)) + return 0; if (ieee80211_is_beacon(hdr->frame_control)) { return 1; } else if (!ieee80211_bssid_match(bssid, sdata->u.ibss.bssid)) { -- cgit v1.2.3 From 8d4f150d4e8d52a761e424f9f640c57cd118105f Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 29 Sep 2013 21:39:33 +0200 Subject: mac80211: use sta_info_get_bss() for nl80211 tx and client probing commit 03bb7f42765ce596604f03d179f3137d7df05bba upstream. This allows calls for clients in AP_VLANs (e.g. for 4-addr) to succeed Signed-off-by: Felix Fietkau Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/mac80211/cfg.c | 2 +- net/mac80211/tx.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index ae36f8e11ae4..5ab17b82605d 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -3315,7 +3315,7 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev, return -EINVAL; } band = chanctx_conf->def.chan->band; - sta = sta_info_get(sdata, peer); + sta = sta_info_get_bss(sdata, peer); if (sta) { qos = test_sta_flag(sta, WLAN_STA_WME); } else { diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 9972e07a2f96..e9d18c30071f 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1100,7 +1100,8 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, tx->sta = rcu_dereference(sdata->u.vlan.sta); if (!tx->sta && sdata->dev->ieee80211_ptr->use_4addr) return TX_DROP; - } else if (info->flags & IEEE80211_TX_CTL_INJECTED || + } else if (info->flags & (IEEE80211_TX_CTL_INJECTED | + IEEE80211_TX_INTFL_NL80211_FRAME_TX) || tx->sdata->control_port_protocol == tx->skb->protocol) { tx->sta = sta_info_get_bss(sdata, hdr->addr1); } -- cgit v1.2.3 From 31da12cec6d7882acb2bd968566b1cfbbcae695a Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 29 Sep 2013 21:39:34 +0200 Subject: mac80211: update sta->last_rx on acked tx frames commit 0c5b93290b2f3c7a376567c03ae8d385b0e99851 upstream. When clients are idle for too long, hostapd sends nullfunc frames for probing. When those are acked by the client, the idle time needs to be updated. To make this work (and to avoid unnecessary probing), update sta->last_rx whenever an ACK was received for a tx packet. Only do this if the flag IEEE80211_HW_REPORTS_TX_ACK_STATUS is set. Signed-off-by: Felix Fietkau Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/mac80211/status.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 43439203f4e4..9e78206bd9bb 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -180,6 +180,9 @@ static void ieee80211_frame_acked(struct sta_info *sta, struct sk_buff *skb) struct ieee80211_local *local = sta->local; struct ieee80211_sub_if_data *sdata = sta->sdata; + if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) + sta->last_rx = jiffies; + if (ieee80211_is_data_qos(mgmt->frame_control)) { struct ieee80211_hdr *hdr = (void *) skb->data; u8 *qc = ieee80211_get_qos_ctl(hdr); -- cgit v1.2.3 From 0b1621f62382e9b6f97b35861e9ade1a979b95b8 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 11 Oct 2013 15:47:06 +0200 Subject: mac80211: fix crash if bitrate calculation goes wrong commit d86aa4f8ca58898ec6a94c0635da20b948171ed7 upstream. If a frame's timestamp is calculated, and the bitrate calculation goes wrong and returns zero, the system will attempt to divide by zero and crash. Catch this case and print the rate information that the driver reported when this happens. Reported-by: Thomas Lindroth Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/mac80211/util.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 72e6292955bb..5db8eb5d56cf 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -2174,6 +2174,10 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local, } rate = cfg80211_calculate_bitrate(&ri); + if (WARN_ONCE(!rate, + "Invalid bitrate: flags=0x%x, idx=%d, vht_nss=%d\n", + status->flag, status->rate_idx, status->vht_nss)) + return 0; /* rewind from end of MPDU */ if (status->flag & RX_FLAG_MACTIME_END) -- cgit v1.2.3 From fc756d89ff073a9c7fb8e4788fa63705d3d8f2a2 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 5 Oct 2013 14:09:30 +0200 Subject: ath9k: fix tx queue scheduling after channel changes commit ec30326ea773900da210c495e14cfeb532550ba2 upstream. Otherwise, if queues are full during a scan, tx scheduling does not resume after switching back to the home channel. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/main.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index e33a659e224b..a8fee08479ef 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -209,6 +209,7 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start) struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); unsigned long flags; + int i; if (ath_startrecv(sc) != 0) { ath_err(common, "Unable to restart recv logic\n"); @@ -236,6 +237,15 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start) } work: ath_restart_work(sc); + + for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { + if (!ATH_TXQ_SETUP(sc, i)) + continue; + + spin_lock_bh(&sc->tx.txq[i].axq_lock); + ath_txq_schedule(sc, &sc->tx.txq[i]); + spin_unlock_bh(&sc->tx.txq[i].axq_lock); + } } if ((ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) && sc->ant_rx != 3) @@ -543,21 +553,10 @@ chip_reset: static int ath_reset(struct ath_softc *sc) { - int i, r; + int r; ath9k_ps_wakeup(sc); - r = ath_reset_internal(sc, NULL); - - for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { - if (!ATH_TXQ_SETUP(sc, i)) - continue; - - spin_lock_bh(&sc->tx.txq[i].axq_lock); - ath_txq_schedule(sc, &sc->tx.txq[i]); - spin_unlock_bh(&sc->tx.txq[i].axq_lock); - } - ath9k_ps_restore(sc); return r; -- cgit v1.2.3 From e83301f88258e3f204392cf59b0ffd706a051a26 Mon Sep 17 00:00:00 2001 From: Bruno Randolf Date: Thu, 26 Sep 2013 16:55:28 +0100 Subject: cfg80211: fix warning when using WEXT for IBSS commit f478f33a93f9353dcd1fe55445343d76b1c3f84a upstream. Fix kernel warning when using WEXT for configuring ad-hoc mode, e.g. "iwconfig wlan0 essid test channel 1" WARNING: at net/wireless/chan.c:373 cfg80211_chandef_usable+0x50/0x21c [cfg80211]() The warning is caused by an uninitialized variable center_freq1. Signed-off-by: Bruno Randolf Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/wireless/ibss.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c index d80e47194d49..e62c1ad4e4c9 100644 --- a/net/wireless/ibss.c +++ b/net/wireless/ibss.c @@ -269,6 +269,8 @@ int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev, if (chan->flags & IEEE80211_CHAN_DISABLED) continue; wdev->wext.ibss.chandef.chan = chan; + wdev->wext.ibss.chandef.center_freq1 = + chan->center_freq; break; } @@ -353,6 +355,7 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev, if (chan) { wdev->wext.ibss.chandef.chan = chan; wdev->wext.ibss.chandef.width = NL80211_CHAN_WIDTH_20_NOHT; + wdev->wext.ibss.chandef.center_freq1 = freq; wdev->wext.ibss.channel_fixed = true; } else { /* cfg80211_ibss_wext_join will pick one if needed */ -- cgit v1.2.3 From 6f2c0ed7835fd30d6c137198cf1dc964f061f132 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Fri, 27 Sep 2013 10:55:38 -0700 Subject: mwifiex: fix SDIO interrupt lost issue commit 453b0c3f6910672f79da354077af728d92f95c5b upstream. 601216e "mwifiex: process RX packets in SDIO IRQ thread directly" introduced a command timeout issue which can be reproduced easily on an AM33xx platform using a test application written by Daniel Mack: https://gist.github.com/zonque/6579314 mwifiex_main_process() is called from both the SDIO handler and the workqueue. In case an interrupt occurs right after the int_status check, but before updating the mwifiex_processing flag, this interrupt gets lost, resulting in a command timeout and consequently a card reset. Let main_proc_lock protect both int_status and mwifiex_processing flag. This fixes the interrupt lost issue. Reported-by: Sven Neumann Reported-by: Andreas Fenkart Tested-by: Daniel Mack Reviewed-by: Dylan Reid Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: Paul Stewart Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/mwifiex/main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index 8fc44992b5c3..fc3fe8ddcf62 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c @@ -270,10 +270,12 @@ process_start: } } while (true); - if ((adapter->int_status) || IS_CARD_RX_RCVD(adapter)) + spin_lock_irqsave(&adapter->main_proc_lock, flags); + if ((adapter->int_status) || IS_CARD_RX_RCVD(adapter)) { + spin_unlock_irqrestore(&adapter->main_proc_lock, flags); goto process_start; + } - spin_lock_irqsave(&adapter->main_proc_lock, flags); adapter->mwifiex_processing = false; spin_unlock_irqrestore(&adapter->main_proc_lock, flags); -- cgit v1.2.3 From 3af669ca9923d504d5476bcfe04eaf4bbde03515 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Tue, 8 Oct 2013 10:18:20 -0500 Subject: rtlwifi: rtl8192cu: Fix error in pointer arithmetic commit 9473ca6e920a3b9ca902753ce52833657f9221cc upstream. An error in calculating the offset in an skb causes the driver to read essential device info from the wrong locations. The main effect is that automatic gain calculations are nonsense. Signed-off-by: Mark Cave-Ayland Signed-off-by: Larry Finger Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/rtlwifi/rtl8192cu/trx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c index 763cf1defab5..5a060e537fbe 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c @@ -343,7 +343,8 @@ bool rtl92cu_rx_query_desc(struct ieee80211_hw *hw, (bool)GET_RX_DESC_PAGGR(pdesc)); rx_status->mactime = GET_RX_DESC_TSFL(pdesc); if (phystatus) { - p_drvinfo = (struct rx_fwinfo_92c *)(pdesc + RTL_RX_DESC_SIZE); + p_drvinfo = (struct rx_fwinfo_92c *)(skb->data + + stats->rx_bufshift); rtl92c_translate_rx_signal_stuff(hw, skb, stats, pdesc, p_drvinfo); } -- cgit v1.2.3 From fa2025dc177d9bef300b48289b689a5d667f5ae9 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Tue, 24 Sep 2013 19:34:26 +0300 Subject: iwlwifi: pcie: add SKUs for 6000, 6005 and 6235 series commit 08a5dd3842f2ac61c6d69661d2d96022df8ae359 upstream. Add some new PCI IDs to the table for 6000, 6005 and 6235 series. Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/iwlwifi/iwl-6000.c | 6 ++++++ drivers/net/wireless/iwlwifi/iwl-config.h | 1 + drivers/net/wireless/iwlwifi/pcie/drv.c | 10 ++++++++++ 3 files changed, 17 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index b5ab8d1bcac0..5282088d6c14 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -268,6 +268,12 @@ const struct iwl_cfg iwl6035_2agn_cfg = { .ht_params = &iwl6000_ht_params, }; +const struct iwl_cfg iwl6035_2agn_sff_cfg = { + .name = "Intel(R) Centrino(R) Ultimate-N 6235 AGN", + IWL_DEVICE_6035, + .ht_params = &iwl6000_ht_params, +}; + const struct iwl_cfg iwl1030_bgn_cfg = { .name = "Intel(R) Centrino(R) Wireless-N 1030 BGN", IWL_DEVICE_6030, diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h index c38aa8f77554..c67e29655b2d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/iwlwifi/iwl-config.h @@ -316,6 +316,7 @@ extern const struct iwl_cfg iwl2000_2bgn_cfg; extern const struct iwl_cfg iwl2000_2bgn_d_cfg; extern const struct iwl_cfg iwl2030_2bgn_cfg; extern const struct iwl_cfg iwl6035_2agn_cfg; +extern const struct iwl_cfg iwl6035_2agn_sff_cfg; extern const struct iwl_cfg iwl105_bgn_cfg; extern const struct iwl_cfg iwl105_bgn_d_cfg; extern const struct iwl_cfg iwl135_bgn_cfg; diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c index 5283b5552e6f..b7858a595973 100644 --- a/drivers/net/wireless/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/iwlwifi/pcie/drv.c @@ -138,13 +138,16 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { /* 6x00 Series */ {IWL_PCI_DEVICE(0x422B, 0x1101, iwl6000_3agn_cfg)}, + {IWL_PCI_DEVICE(0x422B, 0x1108, iwl6000_3agn_cfg)}, {IWL_PCI_DEVICE(0x422B, 0x1121, iwl6000_3agn_cfg)}, + {IWL_PCI_DEVICE(0x422B, 0x1128, iwl6000_3agn_cfg)}, {IWL_PCI_DEVICE(0x422C, 0x1301, iwl6000i_2agn_cfg)}, {IWL_PCI_DEVICE(0x422C, 0x1306, iwl6000i_2abg_cfg)}, {IWL_PCI_DEVICE(0x422C, 0x1307, iwl6000i_2bg_cfg)}, {IWL_PCI_DEVICE(0x422C, 0x1321, iwl6000i_2agn_cfg)}, {IWL_PCI_DEVICE(0x422C, 0x1326, iwl6000i_2abg_cfg)}, {IWL_PCI_DEVICE(0x4238, 0x1111, iwl6000_3agn_cfg)}, + {IWL_PCI_DEVICE(0x4238, 0x1118, iwl6000_3agn_cfg)}, {IWL_PCI_DEVICE(0x4239, 0x1311, iwl6000i_2agn_cfg)}, {IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)}, @@ -152,12 +155,16 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { {IWL_PCI_DEVICE(0x0082, 0x1301, iwl6005_2agn_cfg)}, {IWL_PCI_DEVICE(0x0082, 0x1306, iwl6005_2abg_cfg)}, {IWL_PCI_DEVICE(0x0082, 0x1307, iwl6005_2bg_cfg)}, + {IWL_PCI_DEVICE(0x0082, 0x1308, iwl6005_2agn_cfg)}, {IWL_PCI_DEVICE(0x0082, 0x1321, iwl6005_2agn_cfg)}, {IWL_PCI_DEVICE(0x0082, 0x1326, iwl6005_2abg_cfg)}, + {IWL_PCI_DEVICE(0x0082, 0x1328, iwl6005_2agn_cfg)}, {IWL_PCI_DEVICE(0x0085, 0x1311, iwl6005_2agn_cfg)}, + {IWL_PCI_DEVICE(0x0085, 0x1318, iwl6005_2agn_cfg)}, {IWL_PCI_DEVICE(0x0085, 0x1316, iwl6005_2abg_cfg)}, {IWL_PCI_DEVICE(0x0082, 0xC020, iwl6005_2agn_sff_cfg)}, {IWL_PCI_DEVICE(0x0085, 0xC220, iwl6005_2agn_sff_cfg)}, + {IWL_PCI_DEVICE(0x0085, 0xC228, iwl6005_2agn_sff_cfg)}, {IWL_PCI_DEVICE(0x0082, 0x4820, iwl6005_2agn_d_cfg)}, {IWL_PCI_DEVICE(0x0082, 0x1304, iwl6005_2agn_mow1_cfg)},/* low 5GHz active */ {IWL_PCI_DEVICE(0x0082, 0x1305, iwl6005_2agn_mow2_cfg)},/* high 5GHz active */ @@ -239,8 +246,11 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { /* 6x35 Series */ {IWL_PCI_DEVICE(0x088E, 0x4060, iwl6035_2agn_cfg)}, + {IWL_PCI_DEVICE(0x088E, 0x406A, iwl6035_2agn_sff_cfg)}, {IWL_PCI_DEVICE(0x088F, 0x4260, iwl6035_2agn_cfg)}, + {IWL_PCI_DEVICE(0x088F, 0x426A, iwl6035_2agn_sff_cfg)}, {IWL_PCI_DEVICE(0x088E, 0x4460, iwl6035_2agn_cfg)}, + {IWL_PCI_DEVICE(0x088E, 0x446A, iwl6035_2agn_sff_cfg)}, {IWL_PCI_DEVICE(0x088E, 0x4860, iwl6035_2agn_cfg)}, {IWL_PCI_DEVICE(0x088F, 0x5260, iwl6035_2agn_cfg)}, -- cgit v1.2.3 From 4ac4eb6520aa52f77be36780bbe5b17ca3bce983 Mon Sep 17 00:00:00 2001 From: Dave Kleikamp Date: Fri, 6 Sep 2013 21:49:56 -0500 Subject: jfs: fix error path in ialloc commit 8660998608cfa1077e560034db81885af8e1e885 upstream. If insert_inode_locked() fails, we shouldn't be calling unlock_new_inode(). Signed-off-by: Dave Kleikamp Tested-by: Michael L. Semon Signed-off-by: Greg Kroah-Hartman --- fs/jfs/jfs_inode.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fs/jfs/jfs_inode.c b/fs/jfs/jfs_inode.c index c1a3e603279c..7f464c513ba0 100644 --- a/fs/jfs/jfs_inode.c +++ b/fs/jfs/jfs_inode.c @@ -95,7 +95,7 @@ struct inode *ialloc(struct inode *parent, umode_t mode) if (insert_inode_locked(inode) < 0) { rc = -EINVAL; - goto fail_unlock; + goto fail_put; } inode_init_owner(inode, parent, mode); @@ -156,7 +156,6 @@ struct inode *ialloc(struct inode *parent, umode_t mode) fail_drop: dquot_drop(inode); inode->i_flags |= S_NOQUOTA; -fail_unlock: clear_nlink(inode); unlock_new_inode(inode); fail_put: -- cgit v1.2.3 From 1a64b62db0883ba42db1c3860a8aa25aa398e020 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Wed, 9 Oct 2013 12:19:19 +0200 Subject: can: at91-can: fix device to driver data mapping for platform devices commit 5abbeea553c8260ed4e2ac4aae962aff800b6c6d upstream. In commit: 3078cde7 can: at91_can: add dt support device tree support was added to the at91_can driver. In this commit the mapping of device to driver data was mixed up. This results in the sam9x5 parameters being used for the sam9263 and the workaround for the broken mailbox 0 on the sam9263 not being activated. This patch fixes the broken platform_device_id table. Cc: Ludovic Desroches Signed-off-by: Marc Kleine-Budde Signed-off-by: Greg Kroah-Hartman --- drivers/net/can/at91_can.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c index db52f4414def..535d5dd8d816 100644 --- a/drivers/net/can/at91_can.c +++ b/drivers/net/can/at91_can.c @@ -1409,10 +1409,10 @@ static int at91_can_remove(struct platform_device *pdev) static const struct platform_device_id at91_can_id_table[] = { { - .name = "at91_can", + .name = "at91sam9x5_can", .driver_data = (kernel_ulong_t)&at91_at91sam9x5_data, }, { - .name = "at91sam9x5_can", + .name = "at91_can", .driver_data = (kernel_ulong_t)&at91_at91sam9263_data, }, { /* sentinel */ -- cgit v1.2.3 From e350ff50bcd46d650d56015a1416c622d057ec90 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Thu, 3 Oct 2013 23:51:55 +0200 Subject: can: flexcan: fix mx28 detection by rearanging OF match table commit e358784297992b012e8071764d996191dd2b1a54 upstream. The current implemetation of of_match_device() relies that the of_device_id table in the driver is sorted from most specific to least specific compatible. Without this patch the mx28 is detected as the less specific p1010. This leads to a p1010 specific workaround is activated on the mx28, which is not needed. Signed-off-by: Marc Kleine-Budde Signed-off-by: Greg Kroah-Hartman --- drivers/net/can/flexcan.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 769d29ed106d..261d1ee64473 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -983,9 +983,9 @@ static void unregister_flexcandev(struct net_device *dev) } static const struct of_device_id flexcan_of_match[] = { - { .compatible = "fsl,p1010-flexcan", .data = &fsl_p1010_devtype_data, }, - { .compatible = "fsl,imx28-flexcan", .data = &fsl_imx28_devtype_data, }, { .compatible = "fsl,imx6q-flexcan", .data = &fsl_imx6q_devtype_data, }, + { .compatible = "fsl,imx28-flexcan", .data = &fsl_imx28_devtype_data, }, + { .compatible = "fsl,p1010-flexcan", .data = &fsl_p1010_devtype_data, }, { /* sentinel */ }, }; MODULE_DEVICE_TABLE(of, flexcan_of_match); -- cgit v1.2.3 From d60241f65bdc363f1be2b099bd98ff13a96c1f0d Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Fri, 4 Oct 2013 10:52:36 +0200 Subject: can: flexcan: flexcan_chip_start: fix regression, mark one MB for TX and abort pending TX MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit d5a7b406c529e4595ce03dc8f6dcf7fa36f106fa upstream. In patch 0d1862e can: flexcan: fix flexcan_chip_start() on imx6 the loop in flexcan_chip_start() that iterates over all mailboxes after the soft reset of the CAN core was removed. This loop put all mailboxes (even the ones marked as reserved 1...7) into EMPTY/INACTIVE mode. On mailboxes 8...63, this aborts any pending TX messages. After a cold boot there is random garbage in the mailboxes, which leads to spontaneous transmit of CAN frames during first activation. Further if the interface was disabled with a pending message (usually due to an error condition on the CAN bus), this message is retransmitted after enabling the interface again. This patch fixes the regression by: 1) Limiting the maximum number of used mailboxes to 8, 0...7 are used by the RX FIFO, 8 is used by TX. 2) Marking the TX mailbox as EMPTY/INACTIVE, so that any pending TX of that mailbox is aborted. Cc: Lothar Waßmann Signed-off-by: Marc Kleine-Budde Signed-off-by: Greg Kroah-Hartman --- drivers/net/can/flexcan.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 261d1ee64473..a8f33a525dd6 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -63,7 +63,7 @@ #define FLEXCAN_MCR_BCC BIT(16) #define FLEXCAN_MCR_LPRIO_EN BIT(13) #define FLEXCAN_MCR_AEN BIT(12) -#define FLEXCAN_MCR_MAXMB(x) ((x) & 0xf) +#define FLEXCAN_MCR_MAXMB(x) ((x) & 0x1f) #define FLEXCAN_MCR_IDAM_A (0 << 8) #define FLEXCAN_MCR_IDAM_B (1 << 8) #define FLEXCAN_MCR_IDAM_C (2 << 8) @@ -745,9 +745,11 @@ static int flexcan_chip_start(struct net_device *dev) * */ reg_mcr = flexcan_read(®s->mcr); + reg_mcr &= ~FLEXCAN_MCR_MAXMB(0xff); reg_mcr |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_FEN | FLEXCAN_MCR_HALT | FLEXCAN_MCR_SUPV | FLEXCAN_MCR_WRN_EN | - FLEXCAN_MCR_IDAM_C | FLEXCAN_MCR_SRX_DIS; + FLEXCAN_MCR_IDAM_C | FLEXCAN_MCR_SRX_DIS | + FLEXCAN_MCR_MAXMB(FLEXCAN_TX_BUF_ID); netdev_dbg(dev, "%s: writing mcr=0x%08x", __func__, reg_mcr); flexcan_write(reg_mcr, ®s->mcr); @@ -792,6 +794,10 @@ static int flexcan_chip_start(struct net_device *dev) ®s->cantxfg[i].can_ctrl); } + /* Abort any pending TX, mark Mailbox as INACTIVE */ + flexcan_write(FLEXCAN_MB_CNT_CODE(0x4), + ®s->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl); + /* acceptance mask/acceptance code (accept everything) */ flexcan_write(0x0, ®s->rxgmask); flexcan_write(0x0, ®s->rx14mask); -- cgit v1.2.3 From da0d4136d107d926273c227fdeaf805159044f66 Mon Sep 17 00:00:00 2001 From: Aaron Lu Date: Thu, 10 Oct 2013 13:22:36 +0800 Subject: SCSI: sd: call blk_pm_runtime_init before add_disk commit 10c580e4239df5c3344ca00322eca86ab2de880b upstream. Sujit has found a race condition that would make q->nr_pending unbalanced, it occurs as Sujit explained: " sd_probe_async() -> add_disk() -> disk_add_event() -> schedule(disk_events_workfn) sd_revalidate_disk() blk_pm_runtime_init() return; Let's say the disk_events_workfn() calls sd_check_events() which tries to send test_unit_ready() and because of sd_revalidate_disk() trying to send another commands the test_unit_ready() might be re-queued as the tagged command queuing is disabled. So the race condition is - Thread 1 | Thread 2 sd_revalidate_disk() | sd_check_events() ...nr_pending = 0 as q->dev = NULL| scsi_queue_insert() blk_runtime_pm_init() | blk_pm_requeue_request() -> | nr_pending = -1 since | q->dev != NULL " The problem is, the test_unit_ready request doesn't get counted the first time it is queued, so the later decrement of q->nr_pending in blk_pm_requeue_request makes it unbalanced. Fix this by calling blk_pm_runtime_init before add_disk so that all requests initiated there will all be counted. Signed-off-by: Aaron Lu Reported-and-tested-by: Sujit Reddy Thumma Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/sd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index c39863441337..734a29a70f63 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -2843,6 +2843,7 @@ static void sd_probe_async(void *data, async_cookie_t cookie) gd->events |= DISK_EVENT_MEDIA_CHANGE; } + blk_pm_runtime_init(sdp->request_queue, dev); add_disk(gd); if (sdkp->capacity) sd_dif_config_host(sdkp); @@ -2851,7 +2852,6 @@ static void sd_probe_async(void *data, async_cookie_t cookie) sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n", sdp->removable ? "removable " : ""); - blk_pm_runtime_init(sdp->request_queue, dev); scsi_autopm_put_device(sdp); put_device(&sdkp->dev); } -- cgit v1.2.3 From 4053771449476d9c323bd00c0c87bbd390588e55 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Fri, 11 Oct 2013 16:49:16 -0300 Subject: ecryptfs: Fix memory leakage in keystore.c commit 3edc8376c06133e3386265a824869cad03a4efd4 upstream. In 'decrypt_pki_encrypted_session_key' function: Initializes 'payload' pointer and releases it on exit. Signed-off-by: Geyslan G. Bem Signed-off-by: Tyler Hicks Signed-off-by: Greg Kroah-Hartman --- fs/ecryptfs/keystore.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c index 7d52806c2119..4725a07f003c 100644 --- a/fs/ecryptfs/keystore.c +++ b/fs/ecryptfs/keystore.c @@ -1149,7 +1149,7 @@ decrypt_pki_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok, struct ecryptfs_msg_ctx *msg_ctx; struct ecryptfs_message *msg = NULL; char *auth_tok_sig; - char *payload; + char *payload = NULL; size_t payload_len = 0; int rc; @@ -1203,6 +1203,7 @@ decrypt_pki_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok, } out: kfree(msg); + kfree(payload); return rc; } -- cgit v1.2.3 From 7e44a92662ce582268c4f35e68aad1f632ada8f8 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Sat, 19 Oct 2013 14:50:28 +0800 Subject: raid5: set bio bi_vcnt 0 for discard request commit 37c61ff31e9b5e3fcf3cc6579f5c68f6ad40c4b1 upstream. SCSI layer will add new payload for discard request. If two bios are merged to one, the second bio has bi_vcnt 1 which is set in raid5. This will confuse SCSI and cause oops. Suitable for backport to 3.7+ Reported-by: Jes Sorensen Signed-off-by: Shaohua Li Signed-off-by: NeilBrown Acked-by: Martin K. Petersen Signed-off-by: Greg Kroah-Hartman --- drivers/md/raid5.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index a35b846af4f8..279dd99bd4c8 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -668,6 +668,12 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s) bi->bi_io_vec[0].bv_len = STRIPE_SIZE; bi->bi_io_vec[0].bv_offset = 0; bi->bi_size = STRIPE_SIZE; + /* + * If this is discard request, set bi_vcnt 0. We don't + * want to confuse SCSI because SCSI will replace payload + */ + if (rw & REQ_DISCARD) + bi->bi_vcnt = 0; if (rrdev) set_bit(R5_DOUBLE_LOCKED, &sh->dev[i].flags); @@ -706,6 +712,12 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s) rbi->bi_io_vec[0].bv_len = STRIPE_SIZE; rbi->bi_io_vec[0].bv_offset = 0; rbi->bi_size = STRIPE_SIZE; + /* + * If this is discard request, set bi_vcnt 0. We don't + * want to confuse SCSI because SCSI will replace payload + */ + if (rw & REQ_DISCARD) + rbi->bi_vcnt = 0; if (conf->mddev->gendisk) trace_block_bio_remap(bdev_get_queue(rbi->bi_bdev), rbi, disk_devt(conf->mddev->gendisk), -- cgit v1.2.3 From 01e608d7276508fcafb76f2092db89885e62ef66 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Sat, 19 Oct 2013 14:51:42 +0800 Subject: raid5: avoid finding "discard" stripe commit d47648fcf0611812286f68131b40251c6fa54f5e upstream. SCSI discard will damage discard stripe bio setting, eg, some fields are changed. If the stripe is reused very soon, we have wrong bios setting. We remove discard stripe from hash list, so next time the strip will be fully initialized. Suitable for backport to 3.7+. Signed-off-by: Shaohua Li Signed-off-by: NeilBrown Signed-off-by: Greg Kroah-Hartman --- drivers/md/raid5.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 279dd99bd4c8..4bed5454b8dc 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -2812,6 +2812,14 @@ static void handle_stripe_clean_event(struct r5conf *conf, } /* now that discard is done we can proceed with any sync */ clear_bit(STRIPE_DISCARD, &sh->state); + /* + * SCSI discard will change some bio fields and the stripe has + * no updated data, so remove it from hash list and the stripe + * will be reinitialized + */ + spin_lock_irq(&conf->device_lock); + remove_hash(sh); + spin_unlock_irq(&conf->device_lock); if (test_bit(STRIPE_SYNC_REQUESTED, &sh->state)) set_bit(STRIPE_HANDLE, &sh->state); -- cgit v1.2.3 From 1946436e87d13b44bbf69a37cb7fe07477bb5117 Mon Sep 17 00:00:00 2001 From: Gwendal Grignou Date: Fri, 7 Aug 2009 16:17:49 -0700 Subject: libata: make ata_eh_qc_retry() bump scmd->allowed on bogus failures commit f13e220161e738c2710b9904dcb3cf8bb0bcce61 upstream. libata EH decrements scmd->retries when the command failed for reasons unrelated to the command itself so that, for example, commands aborted due to suspend / resume cycle don't get penalized; however, decrementing scmd->retries isn't enough for ATA passthrough commands. Without this fix, ATA passthrough commands are not resend to the drive, and no error is signalled to the caller because: - allowed retry count is 1 - ata_eh_qc_complete fill the sense data, so result is valid - sense data is filled with untouched ATA registers. Signed-off-by: Gwendal Grignou Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- drivers/ata/libata-eh.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index c69fcce505c0..370462fa8e01 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -1322,14 +1322,14 @@ void ata_eh_qc_complete(struct ata_queued_cmd *qc) * should be retried. To be used from EH. * * SCSI midlayer limits the number of retries to scmd->allowed. - * scmd->retries is decremented for commands which get retried + * scmd->allowed is incremented for commands which get retried * due to unrelated failures (qc->err_mask is zero). */ void ata_eh_qc_retry(struct ata_queued_cmd *qc) { struct scsi_cmnd *scmd = qc->scsicmd; - if (!qc->err_mask && scmd->retries) - scmd->retries--; + if (!qc->err_mask) + scmd->allowed++; __ata_eh_qc_complete(qc); } -- cgit v1.2.3 From 0465496671f4769e0f4f00481ce5bc5598c5caa2 Mon Sep 17 00:00:00 2001 From: Bian Yu Date: Sat, 12 Oct 2013 01:10:03 -0400 Subject: md: avoid deadlock when md_set_badblocks. commit 905b0297a9533d7a6ee00a01a990456636877dd6 upstream. When operate harddisk and hit errors, md_set_badblocks is called after scsi_restart_operations which already disabled the irq. but md_set_badblocks will call write_sequnlock_irq and enable irq. so softirq can preempt the current thread and that may cause a deadlock. I think this situation should use write_sequnlock_irqsave/irqrestore instead. I met the situation and the call trace is below: [ 638.919974] BUG: spinlock recursion on CPU#0, scsi_eh_13/1010 [ 638.921923] lock: 0xffff8800d4d51fc8, .magic: dead4ead, .owner: scsi_eh_13/1010, .owner_cpu: 0 [ 638.923890] CPU: 0 PID: 1010 Comm: scsi_eh_13 Not tainted 3.12.0-rc5+ #37 [ 638.925844] Hardware name: To be filled by O.E.M. To be filled by O.E.M./MAHOBAY, BIOS 4.6.5 03/05/2013 [ 638.927816] ffff880037ad4640 ffff880118c03d50 ffffffff8172ff85 0000000000000007 [ 638.929829] ffff8800d4d51fc8 ffff880118c03d70 ffffffff81730030 ffff8800d4d51fc8 [ 638.931848] ffffffff81a72eb0 ffff880118c03d90 ffffffff81730056 ffff8800d4d51fc8 [ 638.933884] Call Trace: [ 638.935867] [] dump_stack+0x55/0x76 [ 638.937878] [] spin_dump+0x8a/0x8f [ 638.939861] [] spin_bug+0x21/0x26 [ 638.941836] [] do_raw_spin_lock+0xa4/0xc0 [ 638.943801] [] _raw_spin_lock+0x66/0x80 [ 638.945747] [] ? scsi_device_unbusy+0x9d/0xd0 [ 638.947672] [] ? _raw_spin_unlock+0x2b/0x50 [ 638.949595] [] scsi_device_unbusy+0x9d/0xd0 [ 638.951504] [] scsi_finish_command+0x37/0xe0 [ 638.953388] [] scsi_softirq_done+0xa8/0x140 [ 638.955248] [] blk_done_softirq+0x7b/0x90 [ 638.957116] [] __do_softirq+0xfd/0x330 [ 638.958987] [] ? __lock_release+0x6f/0x100 [ 638.960861] [] call_softirq+0x1c/0x30 [ 638.962724] [] do_softirq+0x8d/0xc0 [ 638.964565] [] irq_exit+0x10e/0x150 [ 638.966390] [] smp_apic_timer_interrupt+0x4a/0x60 [ 638.968223] [] apic_timer_interrupt+0x6f/0x80 [ 638.970079] [] ? __lock_release+0x6f/0x100 [ 638.971899] [] ? _raw_spin_unlock_irq+0x3a/0x50 [ 638.973691] [] ? _raw_spin_unlock_irq+0x30/0x50 [ 638.975475] [] md_set_badblocks+0x1f3/0x4a0 [ 638.977243] [] rdev_set_badblocks+0x27/0x80 [ 638.978988] [] raid5_end_read_request+0x36b/0x4e0 [raid456] [ 638.980723] [] bio_endio+0x1d/0x40 [ 638.982463] [] req_bio_endio.isra.65+0x83/0xa0 [ 638.984214] [] blk_update_request+0x7f/0x350 [ 638.985967] [] blk_update_bidi_request+0x31/0x90 [ 638.987710] [] __blk_end_bidi_request+0x20/0x50 [ 638.989439] [] __blk_end_request_all+0x1f/0x30 [ 638.991149] [] blk_peek_request+0x106/0x250 [ 638.992861] [] ? scsi_kill_request.isra.32+0xe9/0x130 [ 638.994561] [] scsi_request_fn+0x4a/0x3d0 [ 638.996251] [] __blk_run_queue+0x37/0x50 [ 638.997900] [] blk_run_queue+0x2f/0x50 [ 638.999553] [] scsi_run_queue+0xe0/0x1c0 [ 639.001185] [] scsi_run_host_queues+0x21/0x40 [ 639.002798] [] scsi_restart_operations+0x177/0x200 [ 639.004391] [] scsi_error_handler+0xc9/0xe0 [ 639.005996] [] ? scsi_unjam_host+0xd0/0xd0 [ 639.007600] [] kthread+0xdb/0xe0 [ 639.009205] [] ? flush_kthread_worker+0x170/0x170 [ 639.010821] [] ret_from_fork+0x7c/0xb0 [ 639.012437] [] ? flush_kthread_worker+0x170/0x170 This bug was introduce in commit 2e8ac30312973dd20e68073653 (the first time rdev_set_badblock was call from interrupt context), so this patch is appropriate for 3.5 and subsequent kernels. Signed-off-by: Bian Yu Reviewed-by: Jianpeng Ma Signed-off-by: NeilBrown Signed-off-by: Greg Kroah-Hartman --- drivers/md/md.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index 51f0345a4ba4..d78f1fffab01 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -8072,6 +8072,7 @@ static int md_set_badblocks(struct badblocks *bb, sector_t s, int sectors, u64 *p; int lo, hi; int rv = 1; + unsigned long flags; if (bb->shift < 0) /* badblocks are disabled */ @@ -8086,7 +8087,7 @@ static int md_set_badblocks(struct badblocks *bb, sector_t s, int sectors, sectors = next - s; } - write_seqlock_irq(&bb->lock); + write_seqlock_irqsave(&bb->lock, flags); p = bb->page; lo = 0; @@ -8202,7 +8203,7 @@ static int md_set_badblocks(struct badblocks *bb, sector_t s, int sectors, bb->changed = 1; if (!acknowledged) bb->unacked_exist = 1; - write_sequnlock_irq(&bb->lock); + write_sequnlock_irqrestore(&bb->lock, flags); return rv; } -- cgit v1.2.3 From ed840bec21c6f2f99ca34e974a5905e4f2116c1b Mon Sep 17 00:00:00 2001 From: Lukasz Dorau Date: Thu, 24 Oct 2013 12:55:17 +1100 Subject: md: Fix skipping recovery for read-only arrays. commit 61e4947c99c4494336254ec540c50186d186150b upstream. Since: commit 7ceb17e87bde79d285a8b988cfed9eaeebe60b86 md: Allow devices to be re-added to a read-only array. spares are activated on a read-only array. In case of raid1 and raid10 personalities it causes that not-in-sync devices are marked in-sync without checking if recovery has been finished. If a read-only array is degraded and one of its devices is not in-sync (because the array has been only partially recovered) recovery will be skipped. This patch adds checking if recovery has been finished before marking a device in-sync for raid1 and raid10 personalities. In case of raid5 personality such condition is already present (at raid5.c:6029). Bug was introduced in 3.10 and causes data corruption. Signed-off-by: Pawel Baldysiak Signed-off-by: Lukasz Dorau Signed-off-by: NeilBrown Signed-off-by: Greg Kroah-Hartman --- drivers/md/raid1.c | 1 + drivers/md/raid10.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 6f4824426e86..afaa5d425e9a 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -1479,6 +1479,7 @@ static int raid1_spare_active(struct mddev *mddev) } } if (rdev + && rdev->recovery_offset == MaxSector && !test_bit(Faulty, &rdev->flags) && !test_and_set_bit(In_sync, &rdev->flags)) { count++; diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 081bb3345353..0add86821755 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -1762,6 +1762,7 @@ static int raid10_spare_active(struct mddev *mddev) } sysfs_notify_dirent_safe(tmp->replacement->sysfs_state); } else if (tmp->rdev + && tmp->rdev->recovery_offset == MaxSector && !test_bit(Faulty, &tmp->rdev->flags) && !test_and_set_bit(In_sync, &tmp->rdev->flags)) { count++; -- cgit v1.2.3 From f21abb623ac78e2e9248057282d0de4e9b82e616 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Fri, 25 Oct 2013 21:53:33 +0800 Subject: target/pscsi: fix return value check commit 58932e96e438cd78f75e765d7b87ef39d3533d15 upstream. In case of error, the function scsi_host_lookup() returns NULL pointer not ERR_PTR(). The IS_ERR() test in the return value check should be replaced with NULL test. Signed-off-by: Wei Yongjun Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman --- drivers/target/target_core_pscsi.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c index e992b27aa090..3250ba2594e0 100644 --- a/drivers/target/target_core_pscsi.c +++ b/drivers/target/target_core_pscsi.c @@ -134,10 +134,10 @@ static int pscsi_pmode_enable_hba(struct se_hba *hba, unsigned long mode_flag) * pSCSI Host ID and enable for phba mode */ sh = scsi_host_lookup(phv->phv_host_id); - if (IS_ERR(sh)) { + if (!sh) { pr_err("pSCSI: Unable to locate SCSI Host for" " phv_host_id: %d\n", phv->phv_host_id); - return PTR_ERR(sh); + return -EINVAL; } phv->phv_lld_host = sh; @@ -515,10 +515,10 @@ static int pscsi_configure_device(struct se_device *dev) sh = phv->phv_lld_host; } else { sh = scsi_host_lookup(pdv->pdv_host_id); - if (IS_ERR(sh)) { + if (!sh) { pr_err("pSCSI: Unable to locate" " pdv_host_id: %d\n", pdv->pdv_host_id); - return PTR_ERR(sh); + return -EINVAL; } } } else { -- cgit v1.2.3 From 722b78bc8a42b6910c291266e87abe2e63dc750f Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Fri, 25 Oct 2013 10:44:15 -0700 Subject: vhost/scsi: Fix incorrect usage of get_user_pages_fast write parameter commit 60a01f558af9c48b0bb31f303c479e32721add3f upstream. This patch addresses a long-standing bug where the get_user_pages_fast() write parameter used for setting the underlying page table entry permission bits was incorrectly set to write=1 for data_direction=DMA_TO_DEVICE, and passed into get_user_pages_fast() via vhost_scsi_map_iov_to_sgl(). However, this parameter is intended to signal WRITEs to pinned userspace PTEs for the virtio-scsi DMA_FROM_DEVICE -> READ payload case, and *not* for the virtio-scsi DMA_TO_DEVICE -> WRITE payload case. This bug would manifest itself as random process segmentation faults on KVM host after repeated vhost starts + stops and/or with lots of vhost endpoints + LUNs. Cc: Stefan Hajnoczi Cc: Michael S. Tsirkin Cc: Asias He Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman --- drivers/vhost/scsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c index 701420297225..962c7e3c3baa 100644 --- a/drivers/vhost/scsi.c +++ b/drivers/vhost/scsi.c @@ -1017,7 +1017,7 @@ static void vhost_scsi_handle_vq(struct vhost_scsi *vs, if (data_direction != DMA_NONE) { ret = vhost_scsi_map_iov_to_sgl(tv_cmd, &vq->iov[data_first], data_num, - data_direction == DMA_TO_DEVICE); + data_direction == DMA_FROM_DEVICE); if (unlikely(ret)) { vq_err(vq, "Failed to map iov to sgl\n"); goto err_free; -- cgit v1.2.3 From b5b02b140665d016236918cb88b88f6249050605 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 24 Sep 2013 21:50:23 +0200 Subject: clockevents: Sanitize ticks to nsec conversion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 97b9410643475d6557d2517c2aff9fd2221141a9 upstream. Marc Kleine-Budde pointed out, that commit 77cc982 "clocksource: use clockevents_config_and_register() where possible" caused a regression for some of the converted subarchs. The reason is, that the clockevents core code converts the minimal hardware tick delta to a nanosecond value for core internal usage. This conversion is affected by integer math rounding loss, so the backwards conversion to hardware ticks will likely result in a value which is less than the configured hardware limitation. The affected subarchs used their own workaround (SIGH!) which got lost in the conversion. The solution for the issue at hand is simple: adding evt->mult - 1 to the shifted value before the integer divison in the core conversion function takes care of it. But this only works for the case where for the scaled math mult/shift pair "mult <= 1 << shift" is true. For the case where "mult > 1 << shift" we can apply the rounding add only for the minimum delta value to make sure that the backward conversion is not less than the given hardware limit. For the upper bound we need to omit the rounding add, because the backwards conversion is always larger than the original latch value. That would violate the upper bound of the hardware device. Though looking closer at the details of that function reveals another bogosity: The upper bounds check is broken as well. Checking for a resulting "clc" value greater than KTIME_MAX after the conversion is pointless. The conversion does: u64 clc = (latch << evt->shift) / evt->mult; So there is no sanity check for (latch << evt->shift) exceeding the 64bit boundary. The latch argument is "unsigned long", so on a 64bit arch the handed in argument could easily lead to an unnoticed shift overflow. With the above rounding fix applied the calculation before the divison is: u64 clc = (latch << evt->shift) + evt->mult - 1; So we need to make sure, that neither the shift nor the rounding add is overflowing the u64 boundary. [ukl: move assignment to rnd after eventually changing mult, fix build issue and correct comment with the right math] Signed-off-by: Thomas Gleixner Cc: Russell King - ARM Linux Cc: Marc Kleine-Budde Cc: nicolas.ferre@atmel.com Cc: Marc Pignat Cc: john.stultz@linaro.org Cc: kernel@pengutronix.de Cc: Ronald Wahl Cc: LAK Cc: Ludovic Desroches Link: http://lkml.kernel.org/r/1380052223-24139-1-git-send-email-u.kleine-koenig@pengutronix.de Signed-off-by: Uwe Kleine-König Signed-off-by: Greg Kroah-Hartman --- kernel/time/clockevents.c | 65 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 50 insertions(+), 15 deletions(-) diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c index c6d6400ee137..6a23c6c556c3 100644 --- a/kernel/time/clockevents.c +++ b/kernel/time/clockevents.c @@ -30,29 +30,64 @@ static RAW_NOTIFIER_HEAD(clockevents_chain); /* Protection for the above */ static DEFINE_RAW_SPINLOCK(clockevents_lock); -/** - * clockevents_delta2ns - Convert a latch value (device ticks) to nanoseconds - * @latch: value to convert - * @evt: pointer to clock event device descriptor - * - * Math helper, returns latch value converted to nanoseconds (bound checked) - */ -u64 clockevent_delta2ns(unsigned long latch, struct clock_event_device *evt) +static u64 cev_delta2ns(unsigned long latch, struct clock_event_device *evt, + bool ismax) { u64 clc = (u64) latch << evt->shift; + u64 rnd; if (unlikely(!evt->mult)) { evt->mult = 1; WARN_ON(1); } + rnd = (u64) evt->mult - 1; + + /* + * Upper bound sanity check. If the backwards conversion is + * not equal latch, we know that the above shift overflowed. + */ + if ((clc >> evt->shift) != (u64)latch) + clc = ~0ULL; + + /* + * Scaled math oddities: + * + * For mult <= (1 << shift) we can safely add mult - 1 to + * prevent integer rounding loss. So the backwards conversion + * from nsec to device ticks will be correct. + * + * For mult > (1 << shift), i.e. device frequency is > 1GHz we + * need to be careful. Adding mult - 1 will result in a value + * which when converted back to device ticks can be larger + * than latch by up to (mult - 1) >> shift. For the min_delta + * calculation we still want to apply this in order to stay + * above the minimum device ticks limit. For the upper limit + * we would end up with a latch value larger than the upper + * limit of the device, so we omit the add to stay below the + * device upper boundary. + * + * Also omit the add if it would overflow the u64 boundary. + */ + if ((~0ULL - clc > rnd) && + (!ismax || evt->mult <= (1U << evt->shift))) + clc += rnd; do_div(clc, evt->mult); - if (clc < 1000) - clc = 1000; - if (clc > KTIME_MAX) - clc = KTIME_MAX; - return clc; + /* Deltas less than 1usec are pointless noise */ + return clc > 1000 ? clc : 1000; +} + +/** + * clockevents_delta2ns - Convert a latch value (device ticks) to nanoseconds + * @latch: value to convert + * @evt: pointer to clock event device descriptor + * + * Math helper, returns latch value converted to nanoseconds (bound checked) + */ +u64 clockevent_delta2ns(unsigned long latch, struct clock_event_device *evt) +{ + return cev_delta2ns(latch, evt, false); } EXPORT_SYMBOL_GPL(clockevent_delta2ns); @@ -317,8 +352,8 @@ void clockevents_config(struct clock_event_device *dev, u32 freq) sec = 600; clockevents_calc_mult_shift(dev, freq, sec); - dev->min_delta_ns = clockevent_delta2ns(dev->min_delta_ticks, dev); - dev->max_delta_ns = clockevent_delta2ns(dev->max_delta_ticks, dev); + dev->min_delta_ns = cev_delta2ns(dev->min_delta_ticks, dev, false); + dev->max_delta_ns = cev_delta2ns(dev->max_delta_ticks, dev, true); } /** -- cgit v1.2.3 From daa73ffb82d3e6135de12ca879c373bbd5a9f41b Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sat, 26 Oct 2013 23:19:25 +0200 Subject: parisc: Do not crash 64bit SMP kernels on machines with >= 4GB RAM commit 54e181e073fc1415e41917d725ebdbd7de956455 upstream. Since the beginning of the parisc-linux port, sometimes 64bit SMP kernels were not able to bring up other CPUs than the monarch CPU and instead crashed the kernel. The reason was unclear, esp. since it involved various machines (e.g. J5600, J6750 and SuperDome). Testing showed, that those crashes didn't happened when less than 4GB were installed, or if a 32bit Linux kernel was booted. In the end, the fix for those SMP problems is trivial: During the early phase of the initialization of the CPUs, including the monarch CPU, the PDC_PSW firmware function to enable WIDE (=64bit) mode is called. It's documented that this firmware function may clobber various registers, and one one of those possibly clobbered registers is %cr30 which holds the task thread info pointer. Now, if %cr30 would always have been clobbered, then this bug would have been detected much earlier. But lots of testing finally showed, that - at least for %cr30 - on some machines only the upper 32bits of the 64bit register suddenly turned zero after the firmware call. So, after finding the root cause, the explanation for the various crashes became clear: - On 32bit SMP Linux kernels all upper 32bit were zero, so we didn't faced this problem. - Monarch CPUs in 64bit mode always booted sucessfully, because the inital task thread info pointer was below 4GB. - Secondary CPUs booted sucessfully on machines with less than 4GB RAM because the upper 32bit were zero anyay. - Secondary CPus failed to boot if we had more than 4GB RAM and the task thread info pointer was located above the 4GB boundary. Finally, the patch to fix this problem is trivial by saving the %cr30 register before the firmware call and restoring it afterwards. Signed-off-by: Helge Deller Signed-off-by: John David Anglin Signed-off-by: Helge Deller Signed-off-by: Greg Kroah-Hartman --- arch/parisc/kernel/head.S | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/parisc/kernel/head.S b/arch/parisc/kernel/head.S index 37aabd772fbb..d2d58258aea6 100644 --- a/arch/parisc/kernel/head.S +++ b/arch/parisc/kernel/head.S @@ -195,6 +195,8 @@ common_stext: ldw MEM_PDC_HI(%r0),%r6 depd %r6, 31, 32, %r3 /* move to upper word */ + mfctl %cr30,%r6 /* PCX-W2 firmware bug */ + ldo PDC_PSW(%r0),%arg0 /* 21 */ ldo PDC_PSW_SET_DEFAULTS(%r0),%arg1 /* 2 */ ldo PDC_PSW_WIDE_BIT(%r0),%arg2 /* 2 */ @@ -203,6 +205,8 @@ common_stext: copy %r0,%arg3 stext_pdc_ret: + mtctl %r6,%cr30 /* restore task thread info */ + /* restore rfi target address*/ ldd TI_TASK-THREAD_SZ_ALGN(%sp), %r10 tophys_r1 %r10 -- cgit v1.2.3 From 27b840ea211f8a36fadabaa07ef94fb1b45730c3 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Sat, 2 Nov 2013 09:11:33 +1030 Subject: scripts/kallsyms: filter symbols not in kernel address space commit f6537f2f0eba4eba3354e48dbe3047db6d8b6254 upstream. This patch uses CONFIG_PAGE_OFFSET to filter symbols which are not in kernel address space because these symbols are generally for generating code purpose and can't be run at kernel mode, so we needn't keep them in /proc/kallsyms. For example, on ARM there are some symbols which may be linked in relocatable code section, then perf can't parse symbols any more from /proc/kallsyms, this patch fixes the problem (introduced b9b32bf70f2fb710b07c94e13afbc729afe221da) Cc: Russell King Cc: linux-arm-kernel@lists.infradead.org Cc: Michal Marek Signed-off-by: Ming Lei Signed-off-by: Rusty Russell Signed-off-by: Greg Kroah-Hartman --- scripts/kallsyms.c | 12 +++++++++++- scripts/link-vmlinux.sh | 2 ++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c index 487ac6f37ca2..9a11f9f799f4 100644 --- a/scripts/kallsyms.c +++ b/scripts/kallsyms.c @@ -55,6 +55,7 @@ static struct sym_entry *table; static unsigned int table_size, table_cnt; static int all_symbols = 0; static char symbol_prefix_char = '\0'; +static unsigned long long kernel_start_addr = 0; int token_profit[0x10000]; @@ -65,7 +66,10 @@ unsigned char best_table_len[256]; static void usage(void) { - fprintf(stderr, "Usage: kallsyms [--all-symbols] [--symbol-prefix=] < in.map > out.S\n"); + fprintf(stderr, "Usage: kallsyms [--all-symbols] " + "[--symbol-prefix=] " + "[--page-offset=] " + "< in.map > out.S\n"); exit(1); } @@ -194,6 +198,9 @@ static int symbol_valid(struct sym_entry *s) int i; int offset = 1; + if (s->addr < kernel_start_addr) + return 0; + /* skip prefix char */ if (symbol_prefix_char && *(s->sym + 1) == symbol_prefix_char) offset++; @@ -646,6 +653,9 @@ int main(int argc, char **argv) if ((*p == '"' && *(p+2) == '"') || (*p == '\'' && *(p+2) == '\'')) p++; symbol_prefix_char = *p; + } else if (strncmp(argv[i], "--page-offset=", 14) == 0) { + const char *p = &argv[i][14]; + kernel_start_addr = strtoull(p, NULL, 16); } else usage(); } diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index 014994936b1c..32b10f53d0b4 100644 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@ -82,6 +82,8 @@ kallsyms() kallsymopt="${kallsymopt} --all-symbols" fi + kallsymopt="${kallsymopt} --page-offset=$CONFIG_PAGE_OFFSET" + local aflags="${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL} \ ${NOSTDINC_FLAGS} ${LINUXINCLUDE} ${KBUILD_CPPFLAGS}" -- cgit v1.2.3 From 40a894023d9a4c58379eb4f2ac12e40a2fe014d3 Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Sat, 2 Nov 2013 17:47:49 +0530 Subject: ARC: Incorrect mm reference used in vmalloc fault handler commit 9c41f4eeb9d51f3ece20428d35a3ea32cf3b5622 upstream. A vmalloc fault needs to sync up PGD/PTE entry from init_mm to current task's "active_mm". ARC vmalloc fault handler however was using mm. A vmalloc fault for non user task context (actually pre-userland, from init thread's open for /dev/console) caused the handler to deref NULL mm (for mm->pgd) The reasons it worked so far is amazing: 1. By default (!SMP), vmalloc fault handler uses a cached value of PGD. In SMP that MMU register is repurposed hence need for mm pointer deref. 2. In pre-3.12 SMP kernel, the problem triggering vmalloc didn't exist in pre-userland code path - it was introduced with commit 20bafb3d23d108bc "n_tty: Move buffers into n_tty_data" Signed-off-by: Vineet Gupta Cc: Gilad Ben-Yossef Cc: Noam Camus Cc: Peter Hurley Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- arch/arc/mm/fault.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arc/mm/fault.c b/arch/arc/mm/fault.c index 689ffd86d5e9..331a0846628e 100644 --- a/arch/arc/mm/fault.c +++ b/arch/arc/mm/fault.c @@ -16,7 +16,7 @@ #include #include -static int handle_vmalloc_fault(struct mm_struct *mm, unsigned long address) +static int handle_vmalloc_fault(unsigned long address) { /* * Synchronize this task's top level page-table @@ -26,7 +26,7 @@ static int handle_vmalloc_fault(struct mm_struct *mm, unsigned long address) pud_t *pud, *pud_k; pmd_t *pmd, *pmd_k; - pgd = pgd_offset_fast(mm, address); + pgd = pgd_offset_fast(current->active_mm, address); pgd_k = pgd_offset_k(address); if (!pgd_present(*pgd_k)) @@ -72,7 +72,7 @@ void do_page_fault(struct pt_regs *regs, int write, unsigned long address, * nothing more. */ if (address >= VMALLOC_START && address <= VMALLOC_END) { - ret = handle_vmalloc_fault(mm, address); + ret = handle_vmalloc_fault(address); if (unlikely(ret)) goto bad_area_nosemaphore; else -- cgit v1.2.3 From 8fde18bd74c8f30094bc47edf2c9ed19478661de Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 25 Oct 2013 23:43:10 +0200 Subject: ALSA: hda - Add missing initial vmaster hook at build_controls callback commit b63eae0a6c84839275a4638a7baa391be965cd0e upstream. The generic parser has a support of vmaster hook, but this is initialized only in the init callback with the check of the presence of the corresponding kctl. However, since kctl is NULL at the very first init callback that is called before build_controls callback, the vmaster hook sync is skipped there. Eventually this leads to the uninitialized state depending on the hook implementation. This patch adds a simple workaround, just calling the sync function explicitly at build_controls callback. Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/hda_generic.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 2519f9d03c0f..d0cc796f778a 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c @@ -4383,9 +4383,11 @@ int snd_hda_gen_build_controls(struct hda_codec *codec) true, &spec->vmaster_mute.sw_kctl); if (err < 0) return err; - if (spec->vmaster_mute.hook) + if (spec->vmaster_mute.hook) { snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute, spec->vmaster_mute_enum); + snd_hda_sync_vmaster_hook(&spec->vmaster_mute); + } } free_kctls(spec); /* no longer needed */ -- cgit v1.2.3 From c9e32ffdbe042276914daac9cdc737b8896eace6 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 24 Oct 2013 01:20:24 +0200 Subject: ALSA: hda - Fix unbalanced runtime PM refcount after S3/S4 commit e6bbe666673ab044a3d39ddb74e4d9a401cf1d6f upstream. When a machine goes to S3/S4 after power-save is enabled, the runtime PM refcount might be incorrectly decreased because the power-down triggered soon after resume assumes that the controller was already powered up, and issues the pm_notify down. This patch fixes the incorrect pm_notify call simply by checking the current value properly. Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/hda_codec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 55108b5fb291..31461ba32d3c 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -4789,8 +4789,8 @@ static void hda_power_work(struct work_struct *work) spin_unlock(&codec->power_lock); state = hda_call_codec_suspend(codec, true); - codec->pm_down_notified = 0; - if (!bus->power_keep_link_on && (state & AC_PWRST_CLK_STOP_OK)) { + if (!codec->pm_down_notified && + !bus->power_keep_link_on && (state & AC_PWRST_CLK_STOP_OK)) { codec->pm_down_notified = 1; hda_call_pm_notify(bus, false); } -- cgit v1.2.3 From f08830dbf7af3b9c551d3112425a2d1b3c2757df Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 30 Oct 2013 12:29:40 +0100 Subject: ALSA: hda - Add a fixup for ASUS N76VZ commit 6fc16e58adf50c0f1e4478538983fb5ff6f453d4 upstream. ASUS N76VZ needs the same fixup as N56VZ for supporting the boost speaker. Bugzilla: https://bugzilla.novell.com/show_bug.cgi?id=846529 Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 21b6649c128e..4496e0ab693d 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4253,6 +4253,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { SND_PCI_QUIRK(0x1028, 0x05db, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800), SND_PCI_QUIRK(0x1043, 0x1477, "ASUS N56VZ", ALC662_FIXUP_ASUS_MODE4), + SND_PCI_QUIRK(0x1043, 0x1bf3, "ASUS N76VZ", ALC662_FIXUP_ASUS_MODE4), SND_PCI_QUIRK(0x1043, 0x8469, "ASUS mobo", ALC662_FIXUP_NO_JACK_DETECT), SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_FIXUP_ASUS_MODE2), SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD), -- cgit v1.2.3 From 58dc7706bb9becb535e8861c7b8f33d604381710 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 31 Oct 2013 15:01:37 +0000 Subject: ALSA: fix oops in snd_pcm_info() caused by ASoC DPCM commit a4461f41b94cb52e0141af717dcf4ef6558c8e2e upstream. Unable to handle kernel NULL pointer dereference at virtual address 00000008 pgd = d5300000 [00000008] *pgd=0d265831, *pte=00000000, *ppte=00000000 Internal error: Oops: 17 [#1] PREEMPT ARM CPU: 0 PID: 2295 Comm: vlc Not tainted 3.11.0+ #755 task: dee74800 ti: e213c000 task.ti: e213c000 PC is at snd_pcm_info+0xc8/0xd8 LR is at 0x30232065 pc : [] lr : [<30232065>] psr: a0070013 sp : e213dea8 ip : d81cb0d0 fp : c05f7678 r10: c05f7770 r9 : fffffdfd r8 : 00000000 r7 : d8a968a8 r6 : d8a96800 r5 : d8a96200 r4 : d81cb000 r3 : 00000000 r2 : d81cb000 r1 : 00000001 r0 : d8a96200 Flags: NzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user Control: 10c5387d Table: 15300019 DAC: 00000015 Process vlc (pid: 2295, stack limit = 0xe213c248) [] (snd_pcm_info) from [] (snd_pcm_info_user+0x34/0x9c) [] (snd_pcm_info_user) from [] (snd_pcm_control_ioctl+0x274/0x280) [] (snd_pcm_control_ioctl) from [] (snd_ctl_ioctl+0xc0/0x55c) [] (snd_ctl_ioctl) from [] (do_vfs_ioctl+0x80/0x31c) [] (do_vfs_ioctl) from [] (SyS_ioctl+0x3c/0x60) [] (SyS_ioctl) from [] (ret_fast_syscall+0x0/0x48) Code: e1a00005 e59530dc e3a01001 e1a02004 (e5933008) ---[ end trace cb3d9bdb8dfefb3c ]--- This is provoked when the ASoC front end is open along with its backend, (which causes the backend to have a runtime assigned to it) and then the SNDRV_CTL_IOCTL_PCM_INFO is requested for the (visible) backend device. Resolve this by ensuring that ASoC internal backend devices are not visible to userspace, just as the commentry for snd_pcm_new_internal() says it should be. Signed-off-by: Russell King Acked-by: Mark Brown Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/core/pcm.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 17f45e8aa89c..e1e9e0c999fe 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -49,6 +49,8 @@ static struct snd_pcm *snd_pcm_get(struct snd_card *card, int device) struct snd_pcm *pcm; list_for_each_entry(pcm, &snd_pcm_devices, list) { + if (pcm->internal) + continue; if (pcm->card == card && pcm->device == device) return pcm; } @@ -60,6 +62,8 @@ static int snd_pcm_next(struct snd_card *card, int device) struct snd_pcm *pcm; list_for_each_entry(pcm, &snd_pcm_devices, list) { + if (pcm->internal) + continue; if (pcm->card == card && pcm->device > device) return pcm->device; else if (pcm->card->number > card->number) -- cgit v1.2.3 From 0492665d67bb7bdff10f3027a26b9c145fe73ddb Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 30 Oct 2013 08:35:02 +0100 Subject: ASoC: wm_hubs: Add missing break in hp_supply_event() commit 268ff14525edba31da29a12a9dd693cdd6a7872e upstream. Spotted by coverity CID 115170. Signed-off-by: Takashi Iwai Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/wm_hubs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index f5d81b948759..7a0466eb7ede 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c @@ -530,6 +530,7 @@ static int hp_supply_event(struct snd_soc_dapm_widget *w, hubs->hp_startup_mode); break; } + break; case SND_SOC_DAPM_PRE_PMD: snd_soc_update_bits(codec, WM8993_CHARGE_PUMP_1, -- cgit v1.2.3 From 2ca317899d45d60805b0b5dc9b6f879a8f93f7c6 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 28 Oct 2013 14:21:49 +0100 Subject: ASoC: dapm: Fix source list debugfs outputs commit ff18620c2157671a8ee21ebb8e6a3520ea209b1f upstream. ... due to a copy & paste error. Spotted by coverity CID 710923. Signed-off-by: Takashi Iwai Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/soc-dapm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 360638362e98..c2ecb4e01597 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -1797,7 +1797,7 @@ static ssize_t dapm_widget_power_read_file(struct file *file, w->active ? "active" : "inactive"); list_for_each_entry(p, &w->sources, list_sink) { - if (p->connected && !p->connected(w, p->sink)) + if (p->connected && !p->connected(w, p->source)) continue; if (p->connect) -- cgit v1.2.3 From a2f8eb6acf8b40793f3b798b0a63800f38707444 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 29 Oct 2013 22:07:47 +0300 Subject: staging: ozwpan: prevent overflow in oz_cdev_write() commit c2c65cd2e14ada6de44cb527e7f1990bede24e15 upstream. We need to check "count" so we don't overflow the ei->data buffer. Reported-by: Nico Golde Reported-by: Fabian Yamaguchi Signed-off-by: Dan Carpenter Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ozwpan/ozcdev.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/staging/ozwpan/ozcdev.c b/drivers/staging/ozwpan/ozcdev.c index 27d06666c81a..224ccff75d4f 100644 --- a/drivers/staging/ozwpan/ozcdev.c +++ b/drivers/staging/ozwpan/ozcdev.c @@ -153,6 +153,9 @@ static ssize_t oz_cdev_write(struct file *filp, const char __user *buf, struct oz_app_hdr *app_hdr; struct oz_serial_ctx *ctx; + if (count > sizeof(ei->data) - sizeof(*elt) - sizeof(*app_hdr)) + return -EINVAL; + spin_lock_bh(&g_cdev.lock); pd = g_cdev.active_pd; if (pd) -- cgit v1.2.3 From 421a5dcd03c36833cfe3923b6943e999c3770973 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 29 Oct 2013 23:01:11 +0300 Subject: Staging: bcm: info leak in ioctl commit 8d1e72250c847fa96498ec029891de4dc638a5ba upstream. The DevInfo.u32Reserved[] array isn't initialized so it leaks kernel information to user space. Reported-by: Nico Golde Reported-by: Fabian Yamaguchi Signed-off-by: Dan Carpenter Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/Bcmchar.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/bcm/Bcmchar.c b/drivers/staging/bcm/Bcmchar.c index 35641e529396..8fa64d964b16 100644 --- a/drivers/staging/bcm/Bcmchar.c +++ b/drivers/staging/bcm/Bcmchar.c @@ -1960,6 +1960,7 @@ cntrlEnd: BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Called IOCTL_BCM_GET_DEVICE_DRIVER_INFO\n"); + memset(&DevInfo, 0, sizeof(DevInfo)); DevInfo.MaxRDMBufferSize = BUFFER_4K; DevInfo.u32DSDStartOffset = EEPROM_CALPARAM_START; DevInfo.u32RxAlignmentCorrection = 0; -- cgit v1.2.3 From 2958a1199ee79b5ad4cb80a4bf8da95ac602d796 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 29 Oct 2013 23:01:43 +0300 Subject: Staging: sb105x: info leak in mp_get_count() commit a8b33654b1e3b0c74d4a1fed041c9aae50b3c427 upstream. The icount.reserved[] array isn't initialized so it leaks stack information to userspace. Reported-by: Nico Golde Reported-by: Fabian Yamaguchi Signed-off-by: Dan Carpenter Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sb105x/sb_pci_mp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/sb105x/sb_pci_mp.c b/drivers/staging/sb105x/sb_pci_mp.c index cd94f6c27723..b90e96b7ca01 100644 --- a/drivers/staging/sb105x/sb_pci_mp.c +++ b/drivers/staging/sb105x/sb_pci_mp.c @@ -1063,7 +1063,7 @@ static int mp_wait_modem_status(struct sb_uart_state *state, unsigned long arg) static int mp_get_count(struct sb_uart_state *state, struct serial_icounter_struct *icnt) { - struct serial_icounter_struct icount; + struct serial_icounter_struct icount = {}; struct sb_uart_icount cnow; struct sb_uart_port *port = state->port; -- cgit v1.2.3 From e668dd8e47c2bc39c7bc31529dbe21c6169290bf Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 29 Oct 2013 23:00:15 +0300 Subject: staging: wlags49_h2: buffer overflow setting station name commit b5e2f339865fb443107e5b10603e53bbc92dc054 upstream. We need to check the length parameter before doing the memcpy(). I've actually changed it to strlcpy() as well so that it's NUL terminated. You need CAP_NET_ADMIN to trigger these so it's not the end of the world. Reported-by: Nico Golde Reported-by: Fabian Yamaguchi Signed-off-by: Dan Carpenter Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlags49_h2/wl_priv.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wlags49_h2/wl_priv.c b/drivers/staging/wlags49_h2/wl_priv.c index c97e0e154d28..7e10dcdc3090 100644 --- a/drivers/staging/wlags49_h2/wl_priv.c +++ b/drivers/staging/wlags49_h2/wl_priv.c @@ -570,6 +570,7 @@ int wvlan_uil_put_info(struct uilreq *urq, struct wl_private *lp) ltv_t *pLtv; bool_t ltvAllocated = FALSE; ENCSTRCT sEncryption; + size_t len; #ifdef USE_WDS hcf_16 hcfPort = HCF_PORT_0; @@ -686,7 +687,8 @@ int wvlan_uil_put_info(struct uilreq *urq, struct wl_private *lp) break; case CFG_CNF_OWN_NAME: memset(lp->StationName, 0, sizeof(lp->StationName)); - memcpy((void *)lp->StationName, (void *)&pLtv->u.u8[2], (size_t)pLtv->u.u16[0]); + len = min_t(size_t, pLtv->u.u16[0], sizeof(lp->StationName)); + strlcpy(lp->StationName, &pLtv->u.u8[2], len); pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]); break; case CFG_CNF_LOAD_BALANCING: @@ -1783,6 +1785,7 @@ int wvlan_set_station_nickname(struct net_device *dev, { struct wl_private *lp = wl_priv(dev); unsigned long flags; + size_t len; int ret = 0; /*------------------------------------------------------------------------*/ @@ -1793,8 +1796,8 @@ int wvlan_set_station_nickname(struct net_device *dev, wl_lock(lp, &flags); memset(lp->StationName, 0, sizeof(lp->StationName)); - - memcpy(lp->StationName, extra, wrqu->data.length); + len = min_t(size_t, wrqu->data.length, sizeof(lp->StationName)); + strlcpy(lp->StationName, extra, len); /* Commit the adapter parameters */ wl_apply(lp); -- cgit v1.2.3 From 079584656265347f310c75fac6f863a6280a17e4 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 29 Oct 2013 22:06:04 +0300 Subject: uml: check length in exitcode_proc_write() commit 201f99f170df14ba52ea4c52847779042b7a623b upstream. We don't cap the size of buffer from the user so we could write past the end of the array here. Only root can write to this file. Reported-by: Nico Golde Reported-by: Fabian Yamaguchi Signed-off-by: Dan Carpenter Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- arch/um/kernel/exitcode.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/um/kernel/exitcode.c b/arch/um/kernel/exitcode.c index 829df49dee99..41ebbfebb333 100644 --- a/arch/um/kernel/exitcode.c +++ b/arch/um/kernel/exitcode.c @@ -40,9 +40,11 @@ static ssize_t exitcode_proc_write(struct file *file, const char __user *buffer, size_t count, loff_t *pos) { char *end, buf[sizeof("nnnnn\0")]; + size_t size; int tmp; - if (copy_from_user(buf, buffer, count)) + size = min(count, sizeof(buf)); + if (copy_from_user(buf, buffer, size)) return -EFAULT; tmp = simple_strtol(buf, &end, 0); -- cgit v1.2.3 From 54a702cb065e49976f61d2130c16f585bfba6c44 Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Tue, 15 Oct 2013 02:22:43 +0400 Subject: xtensa: don't use alternate signal stack on threads commit cba9a90053e3b7973eff4f1946f33032e98eeed5 upstream. According to create_thread(3): "The new thread does not inherit the creating thread's alternate signal stack". Since commit f9a3879a (Fix sigaltstack corruption among cloned threads), current->sas_ss_size is set to 0 for cloned processes sharing VM with their parent. Don't use the (nonexistent) alternate signal stack in this case. This has been broken since commit 29c4dfd9 ([XTENSA] Remove non-rt signal handling). Fixes the SA_ONSTACK part of the nptl/tst-cancel20 test from uClibc. Signed-off-by: Baruch Siach Signed-off-by: Max Filippov Signed-off-by: Chris Zankel Signed-off-by: Greg Kroah-Hartman --- arch/xtensa/kernel/signal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/xtensa/kernel/signal.c b/arch/xtensa/kernel/signal.c index 718eca1850bd..98b67d5f1514 100644 --- a/arch/xtensa/kernel/signal.c +++ b/arch/xtensa/kernel/signal.c @@ -341,7 +341,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info, sp = regs->areg[1]; - if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp)) { + if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && sas_ss_flags(sp) == 0) { sp = current->sas_ss_sp + current->sas_ss_size; } -- cgit v1.2.3 From f80d1c35d87072b46bf47f323f8051c4a5073fb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 7 Aug 2013 13:02:52 +0200 Subject: mm: make generic_access_phys available for modules MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 5a73633ef01cd8772defa6a3c34a588376a1df4c upstream. In the next commit this function will be used in the uio subsystem Signed-off-by: Uwe Kleine-König Signed-off-by: Greg Kroah-Hartman --- mm/memory.c | 1 + 1 file changed, 1 insertion(+) diff --git a/mm/memory.c b/mm/memory.c index 5a35443c01ad..0a6f3d16747d 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -4074,6 +4074,7 @@ int generic_access_phys(struct vm_area_struct *vma, unsigned long addr, return len; } +EXPORT_SYMBOL_GPL(generic_access_phys); #endif /* -- cgit v1.2.3 From 5fa25ee0bde3ad47e99e9877313a36a9ace95b72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 7 Aug 2013 13:02:53 +0200 Subject: uio: provide vm access to UIO_MEM_PHYS maps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 7294151d0592e0ff48c61fca9fd7c93d613134da upstream. This makes it possible to let gdb access mappings of the process that is being debugged. uio_mmap_logical was moved and uio_vm_ops renamed to group related code and differentiate to new stuff. Signed-off-by: Uwe Kleine-König Signed-off-by: Greg Kroah-Hartman --- drivers/uio/uio.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c index b645c47501b4..bcdcb4c2132c 100644 --- a/drivers/uio/uio.c +++ b/drivers/uio/uio.c @@ -630,12 +630,26 @@ static int uio_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf) return 0; } -static const struct vm_operations_struct uio_vm_ops = { +static const struct vm_operations_struct uio_logical_vm_ops = { .open = uio_vma_open, .close = uio_vma_close, .fault = uio_vma_fault, }; +static int uio_mmap_logical(struct vm_area_struct *vma) +{ + vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP; + vma->vm_ops = &uio_logical_vm_ops; + uio_vma_open(vma); + return 0; +} + +static const struct vm_operations_struct uio_physical_vm_ops = { +#ifdef CONFIG_HAVE_IOREMAP_PROT + .access = generic_access_phys, +#endif +}; + static int uio_mmap_physical(struct vm_area_struct *vma) { struct uio_device *idev = vma->vm_private_data; @@ -643,6 +657,8 @@ static int uio_mmap_physical(struct vm_area_struct *vma) if (mi < 0) return -EINVAL; + vma->vm_ops = &uio_physical_vm_ops; + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); return remap_pfn_range(vma, @@ -652,14 +668,6 @@ static int uio_mmap_physical(struct vm_area_struct *vma) vma->vm_page_prot); } -static int uio_mmap_logical(struct vm_area_struct *vma) -{ - vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP; - vma->vm_ops = &uio_vm_ops; - uio_vma_open(vma); - return 0; -} - static int uio_mmap(struct file *filep, struct vm_area_struct *vma) { struct uio_listener *listener = filep->private_data; -- cgit v1.2.3 From a4c8ae2e72bdb85f6dfdfad82bec0df1e2749ac5 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 11 May 2013 12:38:38 -0400 Subject: au1100fb: VM_IO is set by io_remap_pfn_range() commit c607f450f6e49f5794f27617bedc638b51044d2e upstream. Signed-off-by: Al Viro Signed-off-by: Greg Kroah-Hartman --- drivers/video/au1100fb.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c index 700cac067b46..ebeb9715f061 100644 --- a/drivers/video/au1100fb.c +++ b/drivers/video/au1100fb.c @@ -385,8 +385,6 @@ int au1100fb_fb_mmap(struct fb_info *fbi, struct vm_area_struct *vma) vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); pgprot_val(vma->vm_page_prot) |= (6 << 9); //CCA=6 - vma->vm_flags |= VM_IO; - if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, vma->vm_end - vma->vm_start, vma->vm_page_prot)) { -- cgit v1.2.3 From f1e65e494c7914220ac6d87caa126114f46ac462 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 11 May 2013 12:37:38 -0400 Subject: au1200fb: io_remap_pfn_range() sets VM_IO commit 1fca06fafb235a88c4fa91294aa1726c0e22855b upstream. ... and single return is quite sufficient to get out of function, TYVM Signed-off-by: Al Viro Signed-off-by: Greg Kroah-Hartman --- drivers/video/au1200fb.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/video/au1200fb.c b/drivers/video/au1200fb.c index 1b59054fc6a4..301224ecc950 100644 --- a/drivers/video/au1200fb.c +++ b/drivers/video/au1200fb.c @@ -1258,13 +1258,9 @@ static int au1200fb_fb_mmap(struct fb_info *info, struct vm_area_struct *vma) vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); pgprot_val(vma->vm_page_prot) |= _CACHE_MASK; /* CCA=7 */ - vma->vm_flags |= VM_IO; - return io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, vma->vm_end - vma->vm_start, vma->vm_page_prot); - - return 0; } static void set_global(u_int cmd, struct au1200_lcd_global_regs_t *pdata) -- cgit v1.2.3 From c79c7ad9d1398787f907f85afc44cf7d6623027d Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 29 Oct 2013 10:21:34 -0700 Subject: Fix a few incorrectly checked [io_]remap_pfn_range() calls commit 7314e613d5ff9f0934f7a0f74ed7973b903315d1 upstream. Nico Golde reports a few straggling uses of [io_]remap_pfn_range() that really should use the vm_iomap_memory() helper. This trivially converts two of them to the helper, and comments about why the third one really needs to continue to use remap_pfn_range(), and adds the missing size check. Reported-by: Nico Golde Signed-off-by: Linus Torvalds --- drivers/uio/uio.c | 17 +++++++++++++++-- drivers/video/au1100fb.c | 26 +------------------------- drivers/video/au1200fb.c | 23 +---------------------- 3 files changed, 17 insertions(+), 49 deletions(-) diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c index bcdcb4c2132c..2d57a00dc173 100644 --- a/drivers/uio/uio.c +++ b/drivers/uio/uio.c @@ -654,16 +654,29 @@ static int uio_mmap_physical(struct vm_area_struct *vma) { struct uio_device *idev = vma->vm_private_data; int mi = uio_find_mem_index(vma); + struct uio_mem *mem; if (mi < 0) return -EINVAL; + mem = idev->info->mem + mi; - vma->vm_ops = &uio_physical_vm_ops; + if (vma->vm_end - vma->vm_start > mem->size) + return -EINVAL; + vma->vm_ops = &uio_physical_vm_ops; vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + /* + * We cannot use the vm_iomap_memory() helper here, + * because vma->vm_pgoff is the map index we looked + * up above in uio_find_mem_index(), rather than an + * actual page offset into the mmap. + * + * So we just do the physical mmap without a page + * offset. + */ return remap_pfn_range(vma, vma->vm_start, - idev->info->mem[mi].addr >> PAGE_SHIFT, + mem->addr >> PAGE_SHIFT, vma->vm_end - vma->vm_start, vma->vm_page_prot); } diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c index ebeb9715f061..bdc515f5e979 100644 --- a/drivers/video/au1100fb.c +++ b/drivers/video/au1100fb.c @@ -361,37 +361,13 @@ void au1100fb_fb_rotate(struct fb_info *fbi, int angle) int au1100fb_fb_mmap(struct fb_info *fbi, struct vm_area_struct *vma) { struct au1100fb_device *fbdev; - unsigned int len; - unsigned long start=0, off; fbdev = to_au1100fb_device(fbi); - if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) { - return -EINVAL; - } - - start = fbdev->fb_phys & PAGE_MASK; - len = PAGE_ALIGN((start & ~PAGE_MASK) + fbdev->fb_len); - - off = vma->vm_pgoff << PAGE_SHIFT; - - if ((vma->vm_end - vma->vm_start + off) > len) { - return -EINVAL; - } - - off += start; - vma->vm_pgoff = off >> PAGE_SHIFT; - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); pgprot_val(vma->vm_page_prot) |= (6 << 9); //CCA=6 - if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, - vma->vm_end - vma->vm_start, - vma->vm_page_prot)) { - return -EAGAIN; - } - - return 0; + return vm_iomap_memory(vma, fbdev->fb_phys, fbdev->fb_len); } static struct fb_ops au1100fb_ops = diff --git a/drivers/video/au1200fb.c b/drivers/video/au1200fb.c index 301224ecc950..1d02897d17f2 100644 --- a/drivers/video/au1200fb.c +++ b/drivers/video/au1200fb.c @@ -1233,34 +1233,13 @@ static int au1200fb_fb_blank(int blank_mode, struct fb_info *fbi) * method mainly to allow the use of the TLB streaming flag (CCA=6) */ static int au1200fb_fb_mmap(struct fb_info *info, struct vm_area_struct *vma) - { - unsigned int len; - unsigned long start=0, off; struct au1200fb_device *fbdev = info->par; - if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) { - return -EINVAL; - } - - start = fbdev->fb_phys & PAGE_MASK; - len = PAGE_ALIGN((start & ~PAGE_MASK) + fbdev->fb_len); - - off = vma->vm_pgoff << PAGE_SHIFT; - - if ((vma->vm_end - vma->vm_start + off) > len) { - return -EINVAL; - } - - off += start; - vma->vm_pgoff = off >> PAGE_SHIFT; - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); pgprot_val(vma->vm_page_prot) |= _CACHE_MASK; /* CCA=7 */ - return io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, - vma->vm_end - vma->vm_start, - vma->vm_page_prot); + return vm_iomap_memory(vma, fbdev->fb_phys, fbdev->fb_len); } static void set_global(u_int cmd, struct au1200_lcd_global_regs_t *pdata) -- cgit v1.2.3 From e14594cd658f655ae3384fcc3ec8c345b36cd4d0 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Thu, 31 Oct 2013 16:34:17 -0700 Subject: lib/scatterlist.c: don't flush_kernel_dcache_page on slab page commit 3d77b50c5874b7e923be946ba793644f82336b75 upstream. Commit b1adaf65ba03 ("[SCSI] block: add sg buffer copy helper functions") introduces two sg buffer copy helpers, and calls flush_kernel_dcache_page() on pages in SG list after these pages are written to. Unfortunately, the commit may introduce a potential bug: - Before sending some SCSI commands, kmalloc() buffer may be passed to block layper, so flush_kernel_dcache_page() can see a slab page finally - According to cachetlb.txt, flush_kernel_dcache_page() is only called on "a user page", which surely can't be a slab page. - ARCH's implementation of flush_kernel_dcache_page() may use page mapping information to do optimization so page_mapping() will see the slab page, then VM_BUG_ON() is triggered. Aaro Koskinen reported the bug on ARM/kirkwood when DEBUG_VM is enabled, and this patch fixes the bug by adding test of '!PageSlab(miter->page)' before calling flush_kernel_dcache_page(). Signed-off-by: Ming Lei Reported-by: Aaro Koskinen Tested-by: Simon Baatz Cc: Russell King - ARM Linux Cc: Will Deacon Cc: Aaro Koskinen Acked-by: Catalin Marinas Cc: FUJITA Tomonori Cc: Tejun Heo Cc: "James E.J. Bottomley" Cc: Jens Axboe Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- lib/scatterlist.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/scatterlist.c b/lib/scatterlist.c index a1cf8cae60e7..3e7df38067ae 100644 --- a/lib/scatterlist.c +++ b/lib/scatterlist.c @@ -529,7 +529,8 @@ void sg_miter_stop(struct sg_mapping_iter *miter) miter->__offset += miter->consumed; miter->__remaining -= miter->consumed; - if (miter->__flags & SG_MITER_TO_SG) + if ((miter->__flags & SG_MITER_TO_SG) && + !PageSlab(miter->page)) flush_kernel_dcache_page(miter->page); if (miter->__flags & SG_MITER_ATOMIC) { -- cgit v1.2.3 From a33ed3974e7b75af36553589e7810da9d8b22382 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 29 Oct 2013 22:11:06 +0300 Subject: aacraid: missing capable() check in compat ioctl commit f856567b930dfcdbc3323261bf77240ccdde01f5 upstream. In commit d496f94d22d1 ('[SCSI] aacraid: fix security weakness') we added a check on CAP_SYS_RAWIO to the ioctl. The compat ioctls need the check as well. Signed-off-by: Dan Carpenter Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/aacraid/linit.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 408a42ef787a..f0d432c139d0 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -771,6 +771,8 @@ static long aac_compat_do_ioctl(struct aac_dev *dev, unsigned cmd, unsigned long static int aac_compat_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) { struct aac_dev *dev = (struct aac_dev *)sdev->host->hostdata; + if (!capable(CAP_SYS_RAWIO)) + return -EPERM; return aac_compat_do_ioctl(dev, cmd, (unsigned long)arg); } -- cgit v1.2.3 From 165b4f8bf37ba929924e9099bd9a1ee5031cf4e7 Mon Sep 17 00:00:00 2001 From: Jonathan Austin Date: Tue, 23 Jul 2013 16:42:18 +0100 Subject: clk: fixup argument order when setting VCO parameters commit 2f9f64bc5aa31836810cd25301aa4772ad73ebab upstream. The order of arguments in the call to vco_set() for the ICST clocks appears to have been switched in error, which results in the VCO not being initialised correctly. This in turn stops the integrated LCD on things like Integrator/CP from working correctly. This patch fixes the order and restores the expected functionality. Reviewed-by: Linus Walleij Signed-off-by: Jonathan Austin Signed-off-by: Mike Turquette Signed-off-by: Greg Kroah-Hartman --- drivers/clk/versatile/clk-icst.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/versatile/clk-icst.c b/drivers/clk/versatile/clk-icst.c index 67ccf4aa7277..f5e4c21b301f 100644 --- a/drivers/clk/versatile/clk-icst.c +++ b/drivers/clk/versatile/clk-icst.c @@ -107,7 +107,7 @@ static int icst_set_rate(struct clk_hw *hw, unsigned long rate, vco = icst_hz_to_vco(icst->params, rate); icst->rate = icst_hz(icst->params, vco); - vco_set(icst->vcoreg, icst->lockreg, vco); + vco_set(icst->lockreg, icst->vcoreg, vco); return 0; } -- cgit v1.2.3 From 699ba929e88a0c2b172e7beebf10fd37ef120142 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Mon, 7 Oct 2013 11:28:42 +0100 Subject: mm: numa: Do not account for a hinting fault if we raced commit 1dd49bfa3465756b3ce72214b58a33e4afb67aa3 upstream. If another task handled a hinting fault in parallel then do not double account for it. Signed-off-by: Mel Gorman Reviewed-by: Rik van Riel Cc: Andrea Arcangeli Cc: Johannes Weiner Cc: Srikar Dronamraju Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1381141781-10992-5-git-send-email-mgorman@suse.de Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- mm/huge_memory.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 0164b09c1e99..7b09fe75799c 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -1335,8 +1335,11 @@ int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma, check_same: spin_lock(&mm->page_table_lock); - if (unlikely(!pmd_same(pmd, *pmdp))) + if (unlikely(!pmd_same(pmd, *pmdp))) { + /* Someone else took our fault */ + current_nid = -1; goto out_unlock; + } clear_pmdnuma: pmd = pmd_mknonnuma(pmd); set_pmd_at(mm, haddr, pmdp, pmd); -- cgit v1.2.3 From 2e39395e03fe936171a8b45894cbf75ccfae0375 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Mon, 7 Oct 2013 11:28:43 +0100 Subject: mm: Wait for THP migrations to complete during NUMA hinting faults commit 42836f5f8baa33085f547098b74aa98991ee9216 upstream. The locking for migrating THP is unusual. While normal page migration prevents parallel accesses using a migration PTE, THP migration relies on a combination of the page_table_lock, the page lock and the existance of the NUMA hinting PTE to guarantee safety but there is a bug in the scheme. If a THP page is currently being migrated and another thread traps a fault on the same page it checks if the page is misplaced. If it is not, then pmd_numa is cleared. The problem is that it checks if the page is misplaced without holding the page lock meaning that the racing thread can be migrating the THP when the second thread clears the NUMA bit and faults a stale page. This patch checks if the page is potentially being migrated and stalls using the lock_page if it is potentially being migrated before checking if the page is misplaced or not. Signed-off-by: Mel Gorman Reviewed-by: Rik van Riel Cc: Andrea Arcangeli Cc: Johannes Weiner Cc: Srikar Dronamraju Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1381141781-10992-6-git-send-email-mgorman@suse.de Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- mm/huge_memory.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 7b09fe75799c..0ad946974df4 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -1305,13 +1305,14 @@ int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma, if (current_nid == numa_node_id()) count_vm_numa_event(NUMA_HINT_FAULTS_LOCAL); - target_nid = mpol_misplaced(page, vma, haddr); - if (target_nid == -1) { - put_page(page); - goto clear_pmdnuma; - } + /* + * Acquire the page lock to serialise THP migrations but avoid dropping + * page_table_lock if at all possible + */ + if (trylock_page(page)) + goto got_lock; - /* Acquire the page lock to serialise THP migrations */ + /* Serialise against migrationa and check placement check placement */ spin_unlock(&mm->page_table_lock); lock_page(page); @@ -1322,9 +1323,17 @@ int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma, put_page(page); goto out_unlock; } - spin_unlock(&mm->page_table_lock); + +got_lock: + target_nid = mpol_misplaced(page, vma, haddr); + if (target_nid == -1) { + unlock_page(page); + put_page(page); + goto clear_pmdnuma; + } /* Migrate the THP to the requested node */ + spin_unlock(&mm->page_table_lock); migrated = migrate_misplaced_transhuge_page(mm, vma, pmdp, pmd, addr, page, target_nid); if (!migrated) -- cgit v1.2.3 From 299723f2297726ca4c0a9d8ef3548ece5466431d Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Mon, 7 Oct 2013 11:28:44 +0100 Subject: mm: Prevent parallel splits during THP migration commit 587fe586f44a48f9691001ba6c45b86c8e4ba21f upstream. THP migrations are serialised by the page lock but on its own that does not prevent THP splits. If the page is split during THP migration then the pmd_same checks will prevent page table corruption but the unlock page and other fix-ups potentially will cause corruption. This patch takes the anon_vma lock to prevent parallel splits during migration. Signed-off-by: Mel Gorman Reviewed-by: Rik van Riel Cc: Andrea Arcangeli Cc: Johannes Weiner Cc: Srikar Dronamraju Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1381141781-10992-7-git-send-email-mgorman@suse.de Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- mm/huge_memory.c | 44 ++++++++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 0ad946974df4..64f8aadb0595 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -1288,18 +1288,18 @@ out: int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long addr, pmd_t pmd, pmd_t *pmdp) { + struct anon_vma *anon_vma = NULL; struct page *page; unsigned long haddr = addr & HPAGE_PMD_MASK; int target_nid; int current_nid = -1; - bool migrated; + bool migrated, page_locked; spin_lock(&mm->page_table_lock); if (unlikely(!pmd_same(pmd, *pmdp))) goto out_unlock; page = pmd_page(pmd); - get_page(page); current_nid = page_to_nid(page); count_vm_numa_event(NUMA_HINT_FAULTS); if (current_nid == numa_node_id()) @@ -1309,12 +1309,29 @@ int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma, * Acquire the page lock to serialise THP migrations but avoid dropping * page_table_lock if at all possible */ - if (trylock_page(page)) - goto got_lock; + page_locked = trylock_page(page); + target_nid = mpol_misplaced(page, vma, haddr); + if (target_nid == -1) { + /* If the page was locked, there are no parallel migrations */ + if (page_locked) { + unlock_page(page); + goto clear_pmdnuma; + } - /* Serialise against migrationa and check placement check placement */ + /* Otherwise wait for potential migrations and retry fault */ + spin_unlock(&mm->page_table_lock); + wait_on_page_locked(page); + goto out; + } + + /* Page is misplaced, serialise migrations and parallel THP splits */ + get_page(page); spin_unlock(&mm->page_table_lock); - lock_page(page); + if (!page_locked) { + lock_page(page); + page_locked = true; + } + anon_vma = page_lock_anon_vma_read(page); /* Confirm the PTE did not while locked */ spin_lock(&mm->page_table_lock); @@ -1324,14 +1341,6 @@ int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma, goto out_unlock; } -got_lock: - target_nid = mpol_misplaced(page, vma, haddr); - if (target_nid == -1) { - unlock_page(page); - put_page(page); - goto clear_pmdnuma; - } - /* Migrate the THP to the requested node */ spin_unlock(&mm->page_table_lock); migrated = migrate_misplaced_transhuge_page(mm, vma, @@ -1340,6 +1349,8 @@ got_lock: goto check_same; task_numa_fault(target_nid, HPAGE_PMD_NR, true); + if (anon_vma) + page_unlock_anon_vma_read(anon_vma); return 0; check_same: @@ -1356,6 +1367,11 @@ clear_pmdnuma: update_mmu_cache_pmd(vma, addr, pmdp); out_unlock: spin_unlock(&mm->page_table_lock); + +out: + if (anon_vma) + page_unlock_anon_vma_read(anon_vma); + if (current_nid != -1) task_numa_fault(current_nid, HPAGE_PMD_NR, false); return 0; -- cgit v1.2.3 From 174dfa40d63b2250e299d5376937d200e4662b7c Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Mon, 7 Oct 2013 11:28:45 +0100 Subject: mm: numa: Sanitize task_numa_fault() callsites commit c61109e34f60f6e85bb43c5a1cd51c0e3db40847 upstream. There are three callers of task_numa_fault(): - do_huge_pmd_numa_page(): Accounts against the current node, not the node where the page resides, unless we migrated, in which case it accounts against the node we migrated to. - do_numa_page(): Accounts against the current node, not the node where the page resides, unless we migrated, in which case it accounts against the node we migrated to. - do_pmd_numa_page(): Accounts not at all when the page isn't migrated, otherwise accounts against the node we migrated towards. This seems wrong to me; all three sites should have the same sementaics, furthermore we should accounts against where the page really is, we already know where the task is. So modify all three sites to always account; we did after all receive the fault; and always account to where the page is after migration, regardless of success. They all still differ on when they clear the PTE/PMD; ideally that would get sorted too. Signed-off-by: Mel Gorman Reviewed-by: Rik van Riel Cc: Andrea Arcangeli Cc: Johannes Weiner Cc: Srikar Dronamraju Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1381141781-10992-8-git-send-email-mgorman@suse.de Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- mm/huge_memory.c | 25 +++++++++++++------------ mm/memory.c | 53 +++++++++++++++++++++-------------------------------- 2 files changed, 34 insertions(+), 44 deletions(-) diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 64f8aadb0595..f276efe68c82 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -1291,18 +1291,19 @@ int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma, struct anon_vma *anon_vma = NULL; struct page *page; unsigned long haddr = addr & HPAGE_PMD_MASK; + int page_nid = -1, this_nid = numa_node_id(); int target_nid; - int current_nid = -1; - bool migrated, page_locked; + bool page_locked; + bool migrated = false; spin_lock(&mm->page_table_lock); if (unlikely(!pmd_same(pmd, *pmdp))) goto out_unlock; page = pmd_page(pmd); - current_nid = page_to_nid(page); + page_nid = page_to_nid(page); count_vm_numa_event(NUMA_HINT_FAULTS); - if (current_nid == numa_node_id()) + if (page_nid == this_nid) count_vm_numa_event(NUMA_HINT_FAULTS_LOCAL); /* @@ -1345,19 +1346,18 @@ int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma, spin_unlock(&mm->page_table_lock); migrated = migrate_misplaced_transhuge_page(mm, vma, pmdp, pmd, addr, page, target_nid); - if (!migrated) + if (migrated) + page_nid = target_nid; + else goto check_same; - task_numa_fault(target_nid, HPAGE_PMD_NR, true); - if (anon_vma) - page_unlock_anon_vma_read(anon_vma); - return 0; + goto out; check_same: spin_lock(&mm->page_table_lock); if (unlikely(!pmd_same(pmd, *pmdp))) { /* Someone else took our fault */ - current_nid = -1; + page_nid = -1; goto out_unlock; } clear_pmdnuma: @@ -1372,8 +1372,9 @@ out: if (anon_vma) page_unlock_anon_vma_read(anon_vma); - if (current_nid != -1) - task_numa_fault(current_nid, HPAGE_PMD_NR, false); + if (page_nid != -1) + task_numa_fault(page_nid, HPAGE_PMD_NR, migrated); + return 0; } diff --git a/mm/memory.c b/mm/memory.c index 0a6f3d16747d..4b60011907d7 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -3525,12 +3525,12 @@ static int do_nonlinear_fault(struct mm_struct *mm, struct vm_area_struct *vma, } int numa_migrate_prep(struct page *page, struct vm_area_struct *vma, - unsigned long addr, int current_nid) + unsigned long addr, int page_nid) { get_page(page); count_vm_numa_event(NUMA_HINT_FAULTS); - if (current_nid == numa_node_id()) + if (page_nid == numa_node_id()) count_vm_numa_event(NUMA_HINT_FAULTS_LOCAL); return mpol_misplaced(page, vma, addr); @@ -3541,7 +3541,7 @@ int do_numa_page(struct mm_struct *mm, struct vm_area_struct *vma, { struct page *page = NULL; spinlock_t *ptl; - int current_nid = -1; + int page_nid = -1; int target_nid; bool migrated = false; @@ -3571,15 +3571,10 @@ int do_numa_page(struct mm_struct *mm, struct vm_area_struct *vma, return 0; } - current_nid = page_to_nid(page); - target_nid = numa_migrate_prep(page, vma, addr, current_nid); + page_nid = page_to_nid(page); + target_nid = numa_migrate_prep(page, vma, addr, page_nid); pte_unmap_unlock(ptep, ptl); if (target_nid == -1) { - /* - * Account for the fault against the current node if it not - * being replaced regardless of where the page is located. - */ - current_nid = numa_node_id(); put_page(page); goto out; } @@ -3587,11 +3582,11 @@ int do_numa_page(struct mm_struct *mm, struct vm_area_struct *vma, /* Migrate to the requested node */ migrated = migrate_misplaced_page(page, target_nid); if (migrated) - current_nid = target_nid; + page_nid = target_nid; out: - if (current_nid != -1) - task_numa_fault(current_nid, 1, migrated); + if (page_nid != -1) + task_numa_fault(page_nid, 1, migrated); return 0; } @@ -3606,7 +3601,6 @@ static int do_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long offset; spinlock_t *ptl; bool numa = false; - int local_nid = numa_node_id(); spin_lock(&mm->page_table_lock); pmd = *pmdp; @@ -3629,9 +3623,10 @@ static int do_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma, for (addr = _addr + offset; addr < _addr + PMD_SIZE; pte++, addr += PAGE_SIZE) { pte_t pteval = *pte; struct page *page; - int curr_nid = local_nid; + int page_nid = -1; int target_nid; - bool migrated; + bool migrated = false; + if (!pte_present(pteval)) continue; if (!pte_numa(pteval)) @@ -3653,25 +3648,19 @@ static int do_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma, if (unlikely(page_mapcount(page) != 1)) continue; - /* - * Note that the NUMA fault is later accounted to either - * the node that is currently running or where the page is - * migrated to. - */ - curr_nid = local_nid; - target_nid = numa_migrate_prep(page, vma, addr, - page_to_nid(page)); - if (target_nid == -1) { + page_nid = page_to_nid(page); + target_nid = numa_migrate_prep(page, vma, addr, page_nid); + pte_unmap_unlock(pte, ptl); + if (target_nid != -1) { + migrated = migrate_misplaced_page(page, target_nid); + if (migrated) + page_nid = target_nid; + } else { put_page(page); - continue; } - /* Migrate to the requested node */ - pte_unmap_unlock(pte, ptl); - migrated = migrate_misplaced_page(page, target_nid); - if (migrated) - curr_nid = target_nid; - task_numa_fault(curr_nid, 1, migrated); + if (page_nid != -1) + task_numa_fault(page_nid, 1, migrated); pte = pte_offset_map_lock(mm, pmdp, addr, &ptl); } -- cgit v1.2.3 From a490bb33b51d0fc625c87ed5fff1edfd3a2afeb0 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Mon, 7 Oct 2013 11:28:46 +0100 Subject: mm: Close races between THP migration and PMD numa clearing commit 3f926ab945b60a5824369d21add7710622a2eac0 upstream. THP migration uses the page lock to guard against parallel allocations but there are cases like this still open Task A Task B --------------------- --------------------- do_huge_pmd_numa_page do_huge_pmd_numa_page lock_page mpol_misplaced == -1 unlock_page goto clear_pmdnuma lock_page mpol_misplaced == 2 migrate_misplaced_transhuge pmd = pmd_mknonnuma set_pmd_at During hours of testing, one crashed with weird errors and while I have no direct evidence, I suspect something like the race above happened. This patch extends the page lock to being held until the pmd_numa is cleared to prevent migration starting in parallel while the pmd_numa is being cleared. It also flushes the old pmd entry and orders pagetable insertion before rmap insertion. Signed-off-by: Mel Gorman Reviewed-by: Rik van Riel Cc: Andrea Arcangeli Cc: Johannes Weiner Cc: Srikar Dronamraju Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1381141781-10992-9-git-send-email-mgorman@suse.de Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- mm/huge_memory.c | 33 +++++++++++++++------------------ mm/migrate.c | 19 +++++++++++-------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/mm/huge_memory.c b/mm/huge_memory.c index f276efe68c82..c403a74e4bee 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -1314,24 +1314,25 @@ int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma, target_nid = mpol_misplaced(page, vma, haddr); if (target_nid == -1) { /* If the page was locked, there are no parallel migrations */ - if (page_locked) { - unlock_page(page); + if (page_locked) goto clear_pmdnuma; - } - /* Otherwise wait for potential migrations and retry fault */ + /* + * Otherwise wait for potential migrations and retry. We do + * relock and check_same as the page may no longer be mapped. + * As the fault is being retried, do not account for it. + */ spin_unlock(&mm->page_table_lock); wait_on_page_locked(page); + page_nid = -1; goto out; } /* Page is misplaced, serialise migrations and parallel THP splits */ get_page(page); spin_unlock(&mm->page_table_lock); - if (!page_locked) { + if (!page_locked) lock_page(page); - page_locked = true; - } anon_vma = page_lock_anon_vma_read(page); /* Confirm the PTE did not while locked */ @@ -1339,32 +1340,28 @@ int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma, if (unlikely(!pmd_same(pmd, *pmdp))) { unlock_page(page); put_page(page); + page_nid = -1; goto out_unlock; } - /* Migrate the THP to the requested node */ + /* + * Migrate the THP to the requested node, returns with page unlocked + * and pmd_numa cleared. + */ spin_unlock(&mm->page_table_lock); migrated = migrate_misplaced_transhuge_page(mm, vma, pmdp, pmd, addr, page, target_nid); if (migrated) page_nid = target_nid; - else - goto check_same; goto out; - -check_same: - spin_lock(&mm->page_table_lock); - if (unlikely(!pmd_same(pmd, *pmdp))) { - /* Someone else took our fault */ - page_nid = -1; - goto out_unlock; - } clear_pmdnuma: + BUG_ON(!PageLocked(page)); pmd = pmd_mknonnuma(pmd); set_pmd_at(mm, haddr, pmdp, pmd); VM_BUG_ON(pmd_numa(*pmdp)); update_mmu_cache_pmd(vma, addr, pmdp); + unlock_page(page); out_unlock: spin_unlock(&mm->page_table_lock); diff --git a/mm/migrate.c b/mm/migrate.c index 25ca7caf9092..bf436c15f055 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -1710,12 +1710,12 @@ int migrate_misplaced_transhuge_page(struct mm_struct *mm, unlock_page(new_page); put_page(new_page); /* Free it */ - unlock_page(page); + /* Retake the callers reference and putback on LRU */ + get_page(page); putback_lru_page(page); - - count_vm_events(PGMIGRATE_FAIL, HPAGE_PMD_NR); - isolated = 0; - goto out; + mod_zone_page_state(page_zone(page), + NR_ISOLATED_ANON + page_lru, -HPAGE_PMD_NR); + goto out_fail; } /* @@ -1732,9 +1732,9 @@ int migrate_misplaced_transhuge_page(struct mm_struct *mm, entry = maybe_pmd_mkwrite(pmd_mkdirty(entry), vma); entry = pmd_mkhuge(entry); - page_add_new_anon_rmap(new_page, vma, haddr); - + pmdp_clear_flush(vma, haddr, pmd); set_pmd_at(mm, haddr, pmd, entry); + page_add_new_anon_rmap(new_page, vma, haddr); update_mmu_cache_pmd(vma, address, &entry); page_remove_rmap(page); /* @@ -1753,7 +1753,6 @@ int migrate_misplaced_transhuge_page(struct mm_struct *mm, count_vm_events(PGMIGRATE_SUCCESS, HPAGE_PMD_NR); count_vm_numa_events(NUMA_PAGE_MIGRATE, HPAGE_PMD_NR); -out: mod_zone_page_state(page_zone(page), NR_ISOLATED_ANON + page_lru, -HPAGE_PMD_NR); @@ -1762,6 +1761,10 @@ out: out_fail: count_vm_events(PGMIGRATE_FAIL, HPAGE_PMD_NR); out_dropref: + entry = pmd_mknonnuma(entry); + set_pmd_at(mm, haddr, pmd, entry); + update_mmu_cache_pmd(vma, address, &entry); + unlock_page(page); put_page(page); return 0; -- cgit v1.2.3 From e86100b54cd487c13956f09f2c38955f1a1a0909 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Mon, 7 Oct 2013 11:28:47 +0100 Subject: mm: Account for a THP NUMA hinting update as one PTE update commit 0255d491848032f6c601b6410c3b8ebded3a37b1 upstream. A THP PMD update is accounted for as 512 pages updated in vmstat. This is large difference when estimating the cost of automatic NUMA balancing and can be misleading when comparing results that had collapsed versus split THP. This patch addresses the accounting issue. Signed-off-by: Mel Gorman Reviewed-by: Rik van Riel Cc: Andrea Arcangeli Cc: Johannes Weiner Cc: Srikar Dronamraju Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1381141781-10992-10-git-send-email-mgorman@suse.de Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- mm/mprotect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/mprotect.c b/mm/mprotect.c index 94722a4d6b43..2bbb648ea73f 100644 --- a/mm/mprotect.c +++ b/mm/mprotect.c @@ -145,7 +145,7 @@ static inline unsigned long change_pmd_range(struct vm_area_struct *vma, split_huge_page_pmd(vma, addr, pmd); else if (change_huge_pmd(vma, pmd, addr, newprot, prot_numa)) { - pages += HPAGE_PMD_NR; + pages++; continue; } /* fall through */ -- cgit v1.2.3 From 18b683a2334848c003fe89e3002244ca298544f4 Mon Sep 17 00:00:00 2001 From: Chen LinX Date: Wed, 30 Oct 2013 13:56:18 -0700 Subject: mm/pagewalk.c: fix walk_page_range() access of wrong PTEs commit 3017f079efd6af199b0852b5c425364513db460e upstream. When walk_page_range walk a memory map's page tables, it'll skip VM_PFNMAP area, then variable 'next' will to assign to vma->vm_end, it maybe larger than 'end'. In next loop, 'addr' will be larger than 'next'. Then in /proc/XXXX/pagemap file reading procedure, the 'addr' will growing forever in pagemap_pte_range, pte_to_pagemap_entry will access the wrong pte. BUG: Bad page map in process procrank pte:8437526f pmd:785de067 addr:9108d000 vm_flags:00200073 anon_vma:f0d99020 mapping: (null) index:9108d CPU: 1 PID: 4974 Comm: procrank Tainted: G B W O 3.10.1+ #1 Call Trace: dump_stack+0x16/0x18 print_bad_pte+0x114/0x1b0 vm_normal_page+0x56/0x60 pagemap_pte_range+0x17a/0x1d0 walk_page_range+0x19e/0x2c0 pagemap_read+0x16e/0x200 vfs_read+0x84/0x150 SyS_read+0x4a/0x80 syscall_call+0x7/0xb Signed-off-by: Liu ShuoX Signed-off-by: Chen LinX Acked-by: Kirill A. Shutemov Reviewed-by: Naoya Horiguchi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/pagewalk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/pagewalk.c b/mm/pagewalk.c index 5da2cbcfdbb5..2beeabf502c5 100644 --- a/mm/pagewalk.c +++ b/mm/pagewalk.c @@ -242,7 +242,7 @@ int walk_page_range(unsigned long addr, unsigned long end, if (err) break; pgd++; - } while (addr = next, addr != end); + } while (addr = next, addr < end); return err; } -- cgit v1.2.3 From 7bff7accd427da171501b558457ef8fa81ee2767 Mon Sep 17 00:00:00 2001 From: Zhang Yanfei Date: Mon, 8 Jul 2013 16:00:19 -0700 Subject: mm/vmalloc.c: fix an overflow bug in alloc_vmap_area() commit bcb615a81b1765864c71c50afb56631e7a1e5283 upstream. When searching a vmap area in the vmalloc space, we use (addr + size - 1) to check if the value is less than addr, which is an overflow. But we assign (addr + size) to vmap_area->va_end. So if we come across the below case: (addr + size - 1) : not overflow (addr + size) : overflow we will assign an overflow value (e.g 0) to vmap_area->va_end, And this will trigger BUG in __insert_vmap_area, causing system panic. So using (addr + size) to check the overflow should be the correct behaviour, not (addr + size - 1). Signed-off-by: Zhang Yanfei Reported-by: Ghennadi Procopciuc Tested-by: Daniel Baluta Cc: David Rientjes Cc: Minchan Kim Cc: KOSAKI Motohiro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Cc: Anatoly Muliarski Signed-off-by: Greg Kroah-Hartman --- mm/vmalloc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mm/vmalloc.c b/mm/vmalloc.c index d365724feb05..d4565606cc96 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -388,12 +388,12 @@ nocache: addr = ALIGN(first->va_end, align); if (addr < vstart) goto nocache; - if (addr + size - 1 < addr) + if (addr + size < addr) goto overflow; } else { addr = ALIGN(vstart, align); - if (addr + size - 1 < addr) + if (addr + size < addr) goto overflow; n = vmap_area_root.rb_node; @@ -420,7 +420,7 @@ nocache: if (addr + cached_hole_size < first->va_start) cached_hole_size = first->va_start - addr; addr = ALIGN(first->va_end, align); - if (addr + size - 1 < addr) + if (addr + size < addr) goto overflow; if (list_is_last(&first->list, &vmap_area_list)) -- cgit v1.2.3 From 0d6d09974ba93877afa53f5ce5ce89f20b3dfe20 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 9 Oct 2013 01:42:50 -0700 Subject: drm/vmwgfx: Don't put resources with invalid id's on lru list commit 26682480c202e7360cbcdc3bc9e962bf749c6b8d upstream. The evict code may try to swap them out causing a BUG in the destroy function. Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c index bc784254e78e..407d7f9fe8a8 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c @@ -970,7 +970,7 @@ void vmw_resource_unreserve(struct vmw_resource *res, if (new_backup) res->backup_offset = new_backup_offset; - if (!res->func->may_evict) + if (!res->func->may_evict || res->id == -1) return; write_lock(&dev_priv->resource_lock); -- cgit v1.2.3 From 09c2c79ce6e82b226262e667971db7f4a666e430 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 9 Oct 2013 01:42:51 -0700 Subject: drm/vmwgfx: Don't kill clients on VT switch commit c4249855ac5b2a383704d31e040d3831d6a25c6f upstream. DRI clients that tried to grab the TTM lock when the master (X server) was switched away during a VT switch were sent the SIGTERM signal by the kernel. Fix this so that they are only sent that signal when the master has exited. Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 07dfd823cc30..6c44c69a5ba4 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -740,9 +740,17 @@ static void vmw_postclose(struct drm_device *dev, struct vmw_fpriv *vmw_fp; vmw_fp = vmw_fpriv(file_priv); - ttm_object_file_release(&vmw_fp->tfile); - if (vmw_fp->locked_master) + + if (vmw_fp->locked_master) { + struct vmw_master *vmaster = + vmw_master(vmw_fp->locked_master); + + ttm_lock_set_kill(&vmaster->lock, true, SIGTERM); + ttm_vt_unlock(&vmaster->lock); drm_master_put(&vmw_fp->locked_master); + } + + ttm_object_file_release(&vmw_fp->tfile); kfree(vmw_fp); } @@ -942,14 +950,13 @@ static void vmw_master_drop(struct drm_device *dev, vmw_fp->locked_master = drm_master_get(file_priv->master); ret = ttm_vt_lock(&vmaster->lock, false, vmw_fp->tfile); - vmw_execbuf_release_pinned_bo(dev_priv); - if (unlikely((ret != 0))) { DRM_ERROR("Unable to lock TTM at VT switch.\n"); drm_master_put(&vmw_fp->locked_master); } - ttm_lock_set_kill(&vmaster->lock, true, SIGTERM); + ttm_lock_set_kill(&vmaster->lock, false, SIGTERM); + vmw_execbuf_release_pinned_bo(dev_priv); if (!dev_priv->enable_fb) { ret = ttm_bo_evict_mm(&dev_priv->bdev, TTM_PL_VRAM); -- cgit v1.2.3 From 45da934f7431181cd1ccc33b4d138dc41c2cd1ba Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 16 Oct 2013 11:22:44 +0100 Subject: drm: Prevent overwriting from userspace underallocating core ioctl structs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit b062672e305ce071f21eb9e18b102c2a430e0999 upstream. Apply the protections from commit 1b2f1489633888d4a06028315dc19d65768a1c05 Author: Dave Airlie Date: Sat Aug 14 20:20:34 2010 +1000 drm: block userspace under allocating buffer and having drivers overwrite it (v2) to the core ioctl structs as well, for we found one instance where there is a 32-/64-bit size mismatch and were guilty of writing beyond the end of the user's buffer. Signed-off-by: Chris Wilson Cc: Dave Airlie Reviewed-by: Ville Syrjälä Cc: dri-devel@lists.freedesktop.org Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/drm_drv.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 9cc247f55502..2ab782cb38a2 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -406,9 +406,16 @@ long drm_ioctl(struct file *filp, cmd = ioctl->cmd_drv; } else if ((nr >= DRM_COMMAND_END) || (nr < DRM_COMMAND_BASE)) { + u32 drv_size; + ioctl = &drm_ioctls[nr]; - cmd = ioctl->cmd; + + drv_size = _IOC_SIZE(ioctl->cmd); usize = asize = _IOC_SIZE(cmd); + if (drv_size > asize) + asize = drv_size; + + cmd = ioctl->cmd; } else goto err_i1; -- cgit v1.2.3 From 9c1aab0da00ed04f096fabc4136241cb45f92cc1 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 16 Oct 2013 09:49:02 +0100 Subject: drm: Pad drm_mode_get_connector to 64-bit boundary commit bc5bd37ce48c66e9192ad2e7231e9678880f6f8e upstream. Pavel Roskin reported that DRM_IOCTL_MODE_GETCONNECTOR was overwritting the 4 bytes beyond the end of its structure with a 32-bit userspace running on a 64-bit kernel. This is due to the padding gcc inserts as the drm_mode_get_connector struct includes a u64 and its size is not a natural multiple of u64s. 64-bit kernel: sizeof(drm_mode_get_connector)=80, alignof=8 sizeof(drm_mode_get_encoder)=20, alignof=4 sizeof(drm_mode_modeinfo)=68, alignof=4 32-bit userspace: sizeof(drm_mode_get_connector)=76, alignof=4 sizeof(drm_mode_get_encoder)=20, alignof=4 sizeof(drm_mode_modeinfo)=68, alignof=4 Fortuituously we can insert explicit padding to the tail of our structures without breaking ABI. Reported-by: Pavel Roskin Signed-off-by: Chris Wilson Cc: Dave Airlie Cc: dri-devel@lists.freedesktop.org Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- include/uapi/drm/drm_mode.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index 090e5331ab7e..cc2e00eac2f1 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -223,6 +223,8 @@ struct drm_mode_get_connector { __u32 connection; __u32 mm_width, mm_height; /**< HxW in millimeters */ __u32 subpixel; + + __u32 pad; }; #define DRM_MODE_PROP_PENDING (1<<0) -- cgit v1.2.3 From 2233b4db914786e69960d717a3019c87ba3bb5a5 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 10 Oct 2013 16:45:27 -0400 Subject: drm/radeon/atom: workaround vbios bug in transmitter table on rs780 commit c23632d4e57c0dd20bf50eca08fa0eb8ad3ff680 upstream. Some rs780 asics seem to be affected as well. See: http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=91f3a6aaf280294b07c05dfe606e6c27b7ba3c72 Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=60791 Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/atombios_encoders.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index c272d8832605..4c81e9faa635 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c @@ -1641,7 +1641,7 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode) * does the same thing and more. */ if ((rdev->family != CHIP_RV710) && (rdev->family != CHIP_RV730) && - (rdev->family != CHIP_RS880)) + (rdev->family != CHIP_RS780) && (rdev->family != CHIP_RS880)) atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); } if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) { -- cgit v1.2.3 From dad483b78d280665a110591fd418535e0f9791dc Mon Sep 17 00:00:00 2001 From: Gu Zheng Date: Fri, 25 Oct 2013 18:15:06 +0800 Subject: seq_file: always update file->f_pos in seq_lseek() commit 05e16745c0c471bba313961b605b6da3b21a853d upstream. This issue was first pointed out by Jiaxing Wang several months ago, but no further comments: https://lkml.org/lkml/2013/6/29/41 As we know pread() does not change f_pos, so after pread(), file->f_pos and m->read_pos become different. And seq_lseek() does not update file->f_pos if offset equals to m->read_pos, so after pread() and seq_lseek()(lseek to m->read_pos), then a subsequent read may read from a wrong position, the following program produces the problem: char str1[32] = { 0 }; char str2[32] = { 0 }; int poffset = 10; int count = 20; /*open any seq file*/ int fd = open("/proc/modules", O_RDONLY); pread(fd, str1, count, poffset); printf("pread:%s\n", str1); /*seek to where m->read_pos is*/ lseek(fd, poffset+count, SEEK_SET); /*supposed to read from poffset+count, but this read from position 0*/ read(fd, str2, count); printf("read:%s\n", str2); out put: pread: ck_netbios_ns 12665 read: nf_conntrack_netbios /proc/modules: nf_conntrack_netbios_ns 12665 0 - Live 0xffffffffa038b000 nf_conntrack_broadcast 12589 1 nf_conntrack_netbios_ns, Live 0xffffffffa0386000 So we always update file->f_pos to offset in seq_lseek() to fix this issue. Signed-off-by: Jiaxing Wang Signed-off-by: Gu Zheng Signed-off-by: Al Viro Cc: Jonghwan Choi Signed-off-by: Greg Kroah-Hartman --- fs/seq_file.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/seq_file.c b/fs/seq_file.c index 774c1eb7f1c9..3dd44db1465e 100644 --- a/fs/seq_file.c +++ b/fs/seq_file.c @@ -328,6 +328,8 @@ loff_t seq_lseek(struct file *file, loff_t offset, int whence) m->read_pos = offset; retval = file->f_pos = offset; } + } else { + file->f_pos = offset; } } file->f_version = m->version; -- cgit v1.2.3 From 21720562911f038d7406654e7ea0c171cfac47b8 Mon Sep 17 00:00:00 2001 From: Jon Mason Date: Mon, 15 Jul 2013 13:23:47 -0700 Subject: NTB: Add Error Handling in ntb_device_setup commit 3b12a0d15bd1559e72ad21d9d807fd2a6706f0ab upstream. If an error is encountered in ntb_device_setup, it is possible that the spci_cmd isn't populated. Writes to the offset can result in a NULL pointer dereference. This issue is easily encountered by running in NTB-RP mode, as it currently is not supported and will generate an error. To get around this issue, return if an error is encountered prior to attempting to write to the spci_cmd offset. Signed-off-by: Jon Mason Signed-off-by: Greg Kroah-Hartman --- drivers/ntb/ntb_hw.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/ntb/ntb_hw.c b/drivers/ntb/ntb_hw.c index 2dacd19e1b8a..515099ee12fe 100644 --- a/drivers/ntb/ntb_hw.c +++ b/drivers/ntb/ntb_hw.c @@ -644,10 +644,13 @@ static int ntb_device_setup(struct ntb_device *ndev) rc = -ENODEV; } + if (rc) + return rc; + /* Enable Bus Master and Memory Space on the secondary side */ writew(PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER, ndev->reg_ofs.spci_cmd); - return rc; + return 0; } static void ntb_device_free(struct ntb_device *ndev) -- cgit v1.2.3 From 576db18cb68483e6e54f18dfda4b9c24f7e07dfe Mon Sep 17 00:00:00 2001 From: Jon Mason Date: Mon, 15 Jul 2013 15:26:14 -0700 Subject: NTB: Correct Number of Scratch Pad Registers commit 87034511519815259e37336f52edf06d114d43b6 upstream. The NTB Xeon hardware has 16 scratch pad registers and 16 back-to-back scratch pad registers. Correct the #define to represent this and update the variable names to reflect their usage. Signed-off-by: Jon Mason Signed-off-by: Greg Kroah-Hartman --- drivers/ntb/ntb_hw.c | 2 +- drivers/ntb/ntb_regs.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/ntb/ntb_hw.c b/drivers/ntb/ntb_hw.c index 515099ee12fe..3b0ab50e2d5c 100644 --- a/drivers/ntb/ntb_hw.c +++ b/drivers/ntb/ntb_hw.c @@ -547,7 +547,7 @@ static int ntb_xeon_setup(struct ntb_device *ndev) if (ndev->conn_type == NTB_CONN_B2B) { ndev->reg_ofs.sdb = ndev->reg_base + SNB_B2B_DOORBELL_OFFSET; ndev->reg_ofs.spad_write = ndev->reg_base + SNB_B2B_SPAD_OFFSET; - ndev->limits.max_spads = SNB_MAX_SPADS; + ndev->limits.max_spads = SNB_MAX_B2B_SPADS; } else { ndev->reg_ofs.sdb = ndev->reg_base + SNB_SDOORBELL_OFFSET; ndev->reg_ofs.spad_write = ndev->reg_base + SNB_SPAD_OFFSET; diff --git a/drivers/ntb/ntb_regs.h b/drivers/ntb/ntb_regs.h index 5bfa8c06c059..96209b4abc22 100644 --- a/drivers/ntb/ntb_regs.h +++ b/drivers/ntb/ntb_regs.h @@ -53,8 +53,8 @@ #define NTB_LINK_WIDTH_MASK 0x03f0 #define SNB_MSIX_CNT 4 -#define SNB_MAX_SPADS 16 -#define SNB_MAX_COMPAT_SPADS 8 +#define SNB_MAX_B2B_SPADS 16 +#define SNB_MAX_COMPAT_SPADS 16 /* Reserve the uppermost bit for link interrupt */ #define SNB_MAX_DB_BITS 15 #define SNB_DB_BITS_PER_VEC 5 -- cgit v1.2.3 From 8293fc2416f0eb13ff81501b31f0206c5331b9cb Mon Sep 17 00:00:00 2001 From: Jon Mason Date: Fri, 31 May 2013 14:05:53 -0700 Subject: NTB: Correct USD/DSD Identification commit b6750cfe0710a14fd147ba27fddbecae8ba88c77 upstream. Due to ambiguous documentation, the USD/DSD identification is backward when compared to the setting in BIOS. Correct the bits to match the BIOS setting. Signed-off-by: Jon Mason Signed-off-by: Greg Kroah-Hartman --- drivers/ntb/ntb_hw.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/ntb/ntb_hw.c b/drivers/ntb/ntb_hw.c index 3b0ab50e2d5c..26b808b4d3a0 100644 --- a/drivers/ntb/ntb_hw.c +++ b/drivers/ntb/ntb_hw.c @@ -531,9 +531,9 @@ static int ntb_xeon_setup(struct ntb_device *ndev) } if (val & SNB_PPD_DEV_TYPE) - ndev->dev_type = NTB_DEV_DSD; - else ndev->dev_type = NTB_DEV_USD; + else + ndev->dev_type = NTB_DEV_DSD; ndev->reg_ofs.pdb = ndev->reg_base + SNB_PDOORBELL_OFFSET; ndev->reg_ofs.pdb_mask = ndev->reg_base + SNB_PDBMSK_OFFSET; @@ -647,6 +647,9 @@ static int ntb_device_setup(struct ntb_device *ndev) if (rc) return rc; + dev_info(&ndev->pdev->dev, "Device Type = %s\n", + ndev->dev_type == NTB_DEV_USD ? "USD/DSP" : "DSD/USP"); + /* Enable Bus Master and Memory Space on the secondary side */ writew(PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER, ndev->reg_ofs.spci_cmd); -- cgit v1.2.3 From cfa234b144de51eb96e877ee0bee47a3420e8bed Mon Sep 17 00:00:00 2001 From: Jon Mason Date: Tue, 30 Jul 2013 15:58:49 -0700 Subject: NTB: Correct debugfs to work with more than 1 NTB Device commit 1517a3f21a1dd321f16bcf44204bddff9d21abd0 upstream. Debugfs was setup in NTB to only have a single debugfs directory. This resulted in the leaking of debugfs directories and files when multiple NTB devices were present, due to each device stomping on the variables containing the previous device's values (thus preventing them from being freed on cleanup). Correct this by creating a secondary directory of the PCI BDF for each device present, and nesting the previously existing information in those directories. Signed-off-by: Jon Mason Signed-off-by: Greg Kroah-Hartman --- drivers/ntb/ntb_hw.c | 27 +++++++++++++++++++++++++++ drivers/ntb/ntb_hw.h | 16 ++++++++++++++++ drivers/ntb/ntb_transport.c | 17 +++++------------ 3 files changed, 48 insertions(+), 12 deletions(-) diff --git a/drivers/ntb/ntb_hw.c b/drivers/ntb/ntb_hw.c index 26b808b4d3a0..b9bf8b551e3c 100644 --- a/drivers/ntb/ntb_hw.c +++ b/drivers/ntb/ntb_hw.c @@ -78,6 +78,8 @@ enum { BWD_HW, }; +static struct dentry *debugfs_dir; + /* Translate memory window 0,1 to BAR 2,4 */ #define MW_TO_BAR(mw) (mw * 2 + 2) @@ -998,6 +1000,28 @@ static void ntb_free_callbacks(struct ntb_device *ndev) kfree(ndev->db_cb); } +static void ntb_setup_debugfs(struct ntb_device *ndev) +{ + if (!debugfs_initialized()) + return; + + if (!debugfs_dir) + debugfs_dir = debugfs_create_dir(KBUILD_MODNAME, NULL); + + ndev->debugfs_dir = debugfs_create_dir(pci_name(ndev->pdev), + debugfs_dir); +} + +static void ntb_free_debugfs(struct ntb_device *ndev) +{ + debugfs_remove_recursive(ndev->debugfs_dir); + + if (debugfs_dir && simple_empty(debugfs_dir)) { + debugfs_remove_recursive(debugfs_dir); + debugfs_dir = NULL; + } +} + static int ntb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct ntb_device *ndev; @@ -1010,6 +1034,7 @@ static int ntb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) ndev->pdev = pdev; ndev->link_status = NTB_LINK_DOWN; pci_set_drvdata(pdev, ndev); + ntb_setup_debugfs(ndev); rc = pci_enable_device(pdev); if (rc) @@ -1106,6 +1131,7 @@ err2: err1: pci_disable_device(pdev); err: + ntb_free_debugfs(ndev); kfree(ndev); dev_err(&pdev->dev, "Error loading %s module\n", KBUILD_MODNAME); @@ -1135,6 +1161,7 @@ static void ntb_pci_remove(struct pci_dev *pdev) iounmap(ndev->reg_base); pci_release_selected_regions(pdev, NTB_BAR_MASK); pci_disable_device(pdev); + ntb_free_debugfs(ndev); kfree(ndev); } diff --git a/drivers/ntb/ntb_hw.h b/drivers/ntb/ntb_hw.h index 3a3038ca83e6..6a4f56f564ee 100644 --- a/drivers/ntb/ntb_hw.h +++ b/drivers/ntb/ntb_hw.h @@ -127,6 +127,8 @@ struct ntb_device { unsigned char link_status; struct delayed_work hb_timer; unsigned long last_ts; + + struct dentry *debugfs_dir; }; /** @@ -155,6 +157,20 @@ static inline struct pci_dev *ntb_query_pdev(struct ntb_device *ndev) return ndev->pdev; } +/** + * ntb_query_debugfs() - return the debugfs pointer + * @ndev: pointer to ntb_device instance + * + * Given the ntb pointer, return the debugfs directory pointer for the NTB + * hardware device + * + * RETURNS: a pointer to the debugfs directory + */ +static inline struct dentry *ntb_query_debugfs(struct ntb_device *ndev) +{ + return ndev->debugfs_dir; +} + struct ntb_device *ntb_register_transport(struct pci_dev *pdev, void *transport); void ntb_unregister_transport(struct ntb_device *ndev); diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c index f8d7081ee301..c3089151aa49 100644 --- a/drivers/ntb/ntb_transport.c +++ b/drivers/ntb/ntb_transport.c @@ -157,7 +157,6 @@ struct ntb_transport { bool transport_link; struct delayed_work link_work; struct work_struct link_cleanup; - struct dentry *debugfs_dir; }; enum { @@ -824,12 +823,12 @@ static void ntb_transport_init_queue(struct ntb_transport *nt, qp->tx_max_frame = min(transport_mtu, tx_size / 2); qp->tx_max_entry = tx_size / qp->tx_max_frame; - if (nt->debugfs_dir) { + if (ntb_query_debugfs(nt->ndev)) { char debugfs_name[4]; snprintf(debugfs_name, 4, "qp%d", qp_num); qp->debugfs_dir = debugfs_create_dir(debugfs_name, - nt->debugfs_dir); + ntb_query_debugfs(nt->ndev)); qp->debugfs_stats = debugfs_create_file("stats", S_IRUSR, qp->debugfs_dir, qp, @@ -857,11 +856,6 @@ int ntb_transport_init(struct pci_dev *pdev) if (!nt) return -ENOMEM; - if (debugfs_initialized()) - nt->debugfs_dir = debugfs_create_dir(KBUILD_MODNAME, NULL); - else - nt->debugfs_dir = NULL; - nt->ndev = ntb_register_transport(pdev, nt); if (!nt->ndev) { rc = -EIO; @@ -907,7 +901,6 @@ err2: err1: ntb_unregister_transport(nt->ndev); err: - debugfs_remove_recursive(nt->debugfs_dir); kfree(nt); return rc; } @@ -921,16 +914,16 @@ void ntb_transport_free(void *transport) nt->transport_link = NTB_LINK_DOWN; /* verify that all the qp's are freed */ - for (i = 0; i < nt->max_qps; i++) + for (i = 0; i < nt->max_qps; i++) { if (!test_bit(i, &nt->qp_bitmap)) ntb_transport_free_queue(&nt->qps[i]); + debugfs_remove_recursive(nt->qps[i].debugfs_dir); + } ntb_bus_remove(nt); cancel_delayed_work_sync(&nt->link_work); - debugfs_remove_recursive(nt->debugfs_dir); - ntb_unregister_event_callback(nt->ndev); pdev = ntb_query_pdev(nt->ndev); -- cgit v1.2.3 From 3729ed7c6aa8c5b9eee8f832e4a246b8fa1d56b5 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 13 Nov 2013 12:05:59 +0900 Subject: Linux 3.10.19 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 5fb14e503fe3..83a02f5b2c00 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 10 -SUBLEVEL = 18 +SUBLEVEL = 19 EXTRAVERSION = NAME = TOSSUG Baby Fish -- cgit v1.2.3 From b9099fea22395af057dec42c678f47cf746cc998 Mon Sep 17 00:00:00 2001 From: Pravin B Shelar Date: Mon, 28 Oct 2013 10:38:55 -0700 Subject: ip_gre: Fix WCCPv2 header parsing. [ No applicable upstream commit, the upstream implementation is now completely different and doesn't have this bug. ] In case of WCCPv2 GRE header has extra four bytes. Following patch pull those extra four bytes so that skb offsets are set correctly. CC: Eric Dumazet Reported-by: Peter Schmitt Tested-by: Peter Schmitt Signed-off-by: Pravin B Shelar Signed-off-by: Greg Kroah-Hartman --- include/net/ip_tunnels.h | 2 +- net/ipv4/ip_gre.c | 2 +- net/ipv4/ip_tunnel.c | 4 ++-- net/ipv4/ipip.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h index a9942e1faefb..7ac7f91f0242 100644 --- a/include/net/ip_tunnels.h +++ b/include/net/ip_tunnels.h @@ -113,7 +113,7 @@ struct ip_tunnel *ip_tunnel_lookup(struct ip_tunnel_net *itn, __be32 key); int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb, - const struct tnl_ptk_info *tpi, bool log_ecn_error); + const struct tnl_ptk_info *tpi, int hdr_len, bool log_ecn_error); int ip_tunnel_changelink(struct net_device *dev, struct nlattr *tb[], struct ip_tunnel_parm *p); int ip_tunnel_newlink(struct net_device *dev, struct nlattr *tb[], diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index c52fee0976da..64e4e98c8786 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -335,7 +335,7 @@ static int ipgre_rcv(struct sk_buff *skb) iph->saddr, iph->daddr, tpi.key); if (tunnel) { - ip_tunnel_rcv(tunnel, skb, &tpi, log_ecn_error); + ip_tunnel_rcv(tunnel, skb, &tpi, hdr_len, log_ecn_error); return 0; } icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index 92d2f0f5d7bf..46dcf32c012e 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c @@ -402,7 +402,7 @@ static struct ip_tunnel *ip_tunnel_create(struct net *net, } int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb, - const struct tnl_ptk_info *tpi, bool log_ecn_error) + const struct tnl_ptk_info *tpi, int hdr_len, bool log_ecn_error) { struct pcpu_tstats *tstats; const struct iphdr *iph = ip_hdr(skb); @@ -413,7 +413,7 @@ int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb, skb->protocol = tpi->proto; skb->mac_header = skb->network_header; - __pskb_pull(skb, tunnel->hlen); + __pskb_pull(skb, hdr_len); skb_postpull_rcsum(skb, skb_transport_header(skb), tunnel->hlen); #ifdef CONFIG_NET_IPGRE_BROADCAST if (ipv4_is_multicast(iph->daddr)) { diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index 7cfc45624b6d..f5cc7b331511 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -195,7 +195,7 @@ static int ipip_rcv(struct sk_buff *skb) if (tunnel) { if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) goto drop; - return ip_tunnel_rcv(tunnel, skb, &tpi, log_ecn_error); + return ip_tunnel_rcv(tunnel, skb, &tpi, 0, log_ecn_error); } return -1; -- cgit v1.2.3 From 8ffff756458db53555ca36a97766f1731f6719cc Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Thu, 24 Oct 2013 07:48:24 +0200 Subject: ipv6: ip6_dst_check needs to check for expired dst_entries [ Upstream commit e3bc10bd95d7fcc3f2ac690c6ff22833ea6781d6 ] On receiving a packet too big icmp error we check if our current cached dst_entry in the socket is still valid. This validation check did not care about the expiration of the (cached) route. The error path I traced down: The socket receives a packet too big mtu notification. It still has a valid dst_entry and thus issues the ip6_rt_pmtu_update on this dst_entry, setting RTF_EXPIRE and updates the dst.expiration value (which could fail because of not up-to-date expiration values, see previous patch). In some seldom cases we race with a) the ip6_fib gc or b) another routing lookup which would result in a recreation of the cached rt6_info from its parent non-cached rt6_info. While copying the rt6_info we reinitialize the metrics store by copying it over from the parent thus invalidating the just installed pmtu update (both dsts use the same key to the inetpeer storage). The dst_entry with the just invalidated metrics data would just get its RTF_EXPIRES flag cleared and would continue to stay valid for the socket. We should have not issued the pmtu update on the already expired dst_entry in the first placed. By checking the expiration on the dst entry and doing a relookup in case it is out of date we close the race because we would install a new rt6_info into the fib before we issue the pmtu update, thus closing this race. Not reliably updating the dst.expire value was fixed by the patch "ipv6: reset dst.expires value when clearing expire flag". Reported-by: Steinar H. Gunderson Reported-by: Valentijn Sessink Cc: YOSHIFUJI Hideaki Signed-off-by: Hannes Frederic Sowa Reviewed-by: Eric Dumazet Tested-by: Valentijn Sessink Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv6/route.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 3c1f493ccc63..548a1f7c1a29 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -1084,10 +1084,13 @@ static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie) if (rt->rt6i_genid != rt_genid(dev_net(rt->dst.dev))) return NULL; - if (rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie)) - return dst; + if (!rt->rt6i_node || (rt->rt6i_node->fn_sernum != cookie)) + return NULL; - return NULL; + if (rt6_check_expired(rt)) + return NULL; + + return dst; } static struct dst_entry *ip6_negative_advice(struct dst_entry *dst) -- cgit v1.2.3 From 262eb452f9a806b1d115fffba520a496f62374b6 Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Thu, 24 Oct 2013 10:14:27 +0200 Subject: ipv6: reset dst.expires value when clearing expire flag [ Upstream commit 01ba16d6ec85a1ec4669c75513a76b61ec53ee50 ] On receiving a packet too big icmp error we update the expire value by calling rt6_update_expires. This function uses dst_set_expires which is implemented that it can only reduce the expiration value of the dst entry. If we insert new routing non-expiry information into the ipv6 fib where we already have a matching rt6_info we only clear the RTF_EXPIRES flag in rt6i_flags and leave the dst.expires value as is. When new mtu information arrives for that cached dst_entry we again call dst_set_expires. This time it won't update the dst.expire value because we left the dst.expire value intact from the last update. So dst_set_expires won't touch dst.expires. Fix this by resetting dst.expires when clearing the RTF_EXPIRE flag. dst_set_expires checks for a zero expiration and updates the dst.expires. In the past this (not updating dst.expires) was necessary because dst.expire was placed in a union with the dst_entry *from reference and rt6_clean_expires did assign NULL to it. This split happend in ecd9883724b78cc72ed92c98bcb1a46c764fff21 ("ipv6: fix race condition regarding dst->expires and dst->from"). Reported-by: Steinar H. Gunderson Reported-by: Valentijn Sessink Cc: YOSHIFUJI Hideaki Acked-by: Eric Dumazet Tested-by: Valentijn Sessink Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/net/ip6_fib.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h index 2a601e7da1bf..665e0cee59bd 100644 --- a/include/net/ip6_fib.h +++ b/include/net/ip6_fib.h @@ -165,6 +165,7 @@ static inline struct inet6_dev *ip6_dst_idev(struct dst_entry *dst) static inline void rt6_clean_expires(struct rt6_info *rt) { rt->rt6i_flags &= ~RTF_EXPIRES; + rt->dst.expires = 0; } static inline void rt6_set_expires(struct rt6_info *rt, unsigned long expires) -- cgit v1.2.3 From 0b5be4967ce4d66e2f23103aa114e8170546578e Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sun, 27 Oct 2013 21:02:39 +0000 Subject: cxgb3: Fix length calculation in write_ofld_wr() on 32-bit architectures [ Upstream commit 262e827fe745642589450ae241b7afd3912c3f25 ] The length calculation here is now invalid on 32-bit architectures, since sk_buff::tail is a pointer and sk_buff::transport_header is an integer offset: drivers/net/ethernet/chelsio/cxgb3/sge.c: In function 'write_ofld_wr': drivers/net/ethernet/chelsio/cxgb3/sge.c:1603:9: warning: passing argument 4 of 'make_sgl' makes integer from pointer without a cast [enabled by default] adap->pdev); ^ drivers/net/ethernet/chelsio/cxgb3/sge.c:964:28: note: expected 'unsigned int' but argument is of type 'sk_buff_data_t' static inline unsigned int make_sgl(const struct sk_buff *skb, ^ Use the appropriate skb accessor functions. Compile-tested only. Signed-off-by: Ben Hutchings Fixes: 1a37e412a022 ('net: Use 16bits for *_headers fields of struct skbuff') Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/chelsio/cxgb3/sge.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/chelsio/cxgb3/sge.c b/drivers/net/ethernet/chelsio/cxgb3/sge.c index f12e6b85a653..f057a189d975 100644 --- a/drivers/net/ethernet/chelsio/cxgb3/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb3/sge.c @@ -1600,7 +1600,8 @@ static void write_ofld_wr(struct adapter *adap, struct sk_buff *skb, flits = skb_transport_offset(skb) / 8; sgp = ndesc == 1 ? (struct sg_ent *)&d->flit[flits] : sgl; sgl_flits = make_sgl(skb, sgp, skb_transport_header(skb), - skb->tail - skb->transport_header, + skb_tail_pointer(skb) - + skb_transport_header(skb), adap->pdev); if (need_skb_unmap()) { setup_deferred_unmapping(skb, adap->pdev, sgp, sgl_flits); -- cgit v1.2.3 From fb1494fa72c8f40f63c56b0f0e77ea40db586448 Mon Sep 17 00:00:00 2001 From: Wei Liu Date: Mon, 28 Oct 2013 12:07:57 +0000 Subject: xen-netback: use jiffies_64 value to calculate credit timeout [ Upstream commit 059dfa6a93b779516321e5112db9d7621b1367ba ] time_after_eq() only works if the delta is < MAX_ULONG/2. For a 32bit Dom0, if netfront sends packets at a very low rate, the time between subsequent calls to tx_credit_exceeded() may exceed MAX_ULONG/2 and the test for timer_after_eq() will be incorrect. Credit will not be replenished and the guest may become unable to send packets (e.g., if prior to the long gap, all credit was exhausted). Use jiffies_64 variant to mitigate this problem for 32bit Dom0. Suggested-by: Jan Beulich Signed-off-by: Wei Liu Reviewed-by: David Vrabel Cc: Ian Campbell Cc: Jason Luan Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/xen-netback/common.h | 1 + drivers/net/xen-netback/interface.c | 3 +-- drivers/net/xen-netback/netback.c | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h index 1a285083d24a..f2faa779e3fe 100644 --- a/drivers/net/xen-netback/common.h +++ b/drivers/net/xen-netback/common.h @@ -88,6 +88,7 @@ struct xenvif { unsigned long credit_usec; unsigned long remaining_credit; struct timer_list credit_timeout; + u64 credit_window_start; /* Statistics */ unsigned long rx_gso_checksum_fixup; diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index 3a294c2528d5..c4a2eb2cd8a0 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@ -275,8 +275,7 @@ struct xenvif *xenvif_alloc(struct device *parent, domid_t domid, vif->credit_bytes = vif->remaining_credit = ~0UL; vif->credit_usec = 0UL; init_timer(&vif->credit_timeout); - /* Initialize 'expires' now: it's used to track the credit window. */ - vif->credit_timeout.expires = jiffies; + vif->credit_window_start = get_jiffies_64(); dev->netdev_ops = &xenvif_netdev_ops; dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO; diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index 0071f211a08a..36efb418c26f 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -1423,9 +1423,8 @@ out: static bool tx_credit_exceeded(struct xenvif *vif, unsigned size) { - unsigned long now = jiffies; - unsigned long next_credit = - vif->credit_timeout.expires + + u64 now = get_jiffies_64(); + u64 next_credit = vif->credit_window_start + msecs_to_jiffies(vif->credit_usec / 1000); /* Timer could already be pending in rare cases. */ @@ -1433,8 +1432,8 @@ static bool tx_credit_exceeded(struct xenvif *vif, unsigned size) return true; /* Passed the point where we can replenish credit? */ - if (time_after_eq(now, next_credit)) { - vif->credit_timeout.expires = now; + if (time_after_eq64(now, next_credit)) { + vif->credit_window_start = now; tx_add_credit(vif); } @@ -1446,6 +1445,7 @@ static bool tx_credit_exceeded(struct xenvif *vif, unsigned size) tx_credit_callback; mod_timer(&vif->credit_timeout, next_credit); + vif->credit_window_start = next_credit; return true; } -- cgit v1.2.3 From 69ce0106d07262f819a0ad41d64bb7e713d620bc Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Tue, 29 Oct 2013 15:11:07 +0800 Subject: virtio-net: correctly handle cpu hotplug notifier during resuming [ Upstream commit ec9debbd9a88d8ea86c488d6ffcac419ee7d46d9 ] commit 3ab098df35f8b98b6553edc2e40234af512ba877 (virtio-net: don't respond to cpu hotplug notifier if we're not ready) tries to bypass the cpu hotplug notifier by checking the config_enable and does nothing is it was false. So it need to try to hold the config_lock mutex which may happen in atomic environment which leads the following warnings: [ 622.944441] CPU0 attaching NULL sched-domain. [ 622.944446] CPU1 attaching NULL sched-domain. [ 622.944485] CPU0 attaching NULL sched-domain. [ 622.950795] BUG: sleeping function called from invalid context at kernel/mutex.c:616 [ 622.950796] in_atomic(): 1, irqs_disabled(): 1, pid: 10, name: migration/1 [ 622.950796] no locks held by migration/1/10. [ 622.950798] CPU: 1 PID: 10 Comm: migration/1 Not tainted 3.12.0-rc5-wl-01249-gb91e82d #317 [ 622.950799] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011 [ 622.950802] 0000000000000000 ffff88001d42dba0 ffffffff81a32f22 ffff88001bfb9c70 [ 622.950803] ffff88001d42dbb0 ffffffff810edb02 ffff88001d42dc38 ffffffff81a396ed [ 622.950805] 0000000000000046 ffff88001d42dbe8 ffffffff810e861d 0000000000000000 [ 622.950805] Call Trace: [ 622.950810] [] dump_stack+0x54/0x74 [ 622.950815] [] __might_sleep+0x112/0x114 [ 622.950817] [] mutex_lock_nested+0x3c/0x3c6 [ 622.950818] [] ? up+0x39/0x3e [ 622.950821] [] ? acpi_os_signal_semaphore+0x21/0x2d [ 622.950824] [] ? acpi_ut_release_mutex+0x5e/0x62 [ 622.950828] [] virtnet_cpu_callback+0x33/0x87 [ 622.950830] [] notifier_call_chain+0x3c/0x5e [ 622.950832] [] __raw_notifier_call_chain+0xe/0x10 [ 622.950835] [] __cpu_notify+0x20/0x37 [ 622.950836] [] cpu_notify+0x13/0x15 [ 622.950838] [] take_cpu_down+0x27/0x3a [ 622.950841] [] stop_machine_cpu_stop+0x93/0xf1 [ 622.950842] [] cpu_stopper_thread+0xa0/0x12f [ 622.950844] [] ? cpu_stopper_thread+0x12f/0x12f [ 622.950847] [] ? lock_release_holdtime.part.7+0xa3/0xa8 [ 622.950848] [] ? cpu_stop_should_run+0x3f/0x47 [ 622.950850] [] smpboot_thread_fn+0x1c5/0x1e3 [ 622.950852] [] ? lg_global_unlock+0x67/0x67 [ 622.950854] [] kthread+0xd8/0xe0 [ 622.950857] [] ? wait_for_common+0x12f/0x164 [ 622.950859] [] ? kthread_create_on_node+0x124/0x124 [ 622.950861] [] ret_from_fork+0x7c/0xb0 [ 622.950862] [] ? kthread_create_on_node+0x124/0x124 [ 622.950876] smpboot: CPU 1 is now offline [ 623.194556] SMP alternatives: lockdep: fixing up alternatives [ 623.194559] smpboot: Booting Node 0 Processor 1 APIC 0x1 ... A correct fix is to unregister the hotcpu notifier during restore and register a new one in resume. Reported-by: Fengguang Wu Tested-by: Fengguang Wu Cc: Wanlong Gao Cc: Rusty Russell Cc: Michael S. Tsirkin Signed-off-by: Jason Wang Acked-by: Michael S. Tsirkin Reviewed-by: Wanlong Gao Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/virtio_net.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 1d01534c2020..64cf70247048 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -1096,11 +1096,6 @@ static int virtnet_cpu_callback(struct notifier_block *nfb, { struct virtnet_info *vi = container_of(nfb, struct virtnet_info, nb); - mutex_lock(&vi->config_lock); - - if (!vi->config_enable) - goto done; - switch(action & ~CPU_TASKS_FROZEN) { case CPU_ONLINE: case CPU_DOWN_FAILED: @@ -1114,8 +1109,6 @@ static int virtnet_cpu_callback(struct notifier_block *nfb, break; } -done: - mutex_unlock(&vi->config_lock); return NOTIFY_OK; } @@ -1672,6 +1665,8 @@ static int virtnet_freeze(struct virtio_device *vdev) struct virtnet_info *vi = vdev->priv; int i; + unregister_hotcpu_notifier(&vi->nb); + /* Prevent config work handler from accessing the device */ mutex_lock(&vi->config_lock); vi->config_enable = false; @@ -1720,6 +1715,10 @@ static int virtnet_restore(struct virtio_device *vdev) virtnet_set_queues(vi, vi->curr_queue_pairs); rtnl_unlock(); + err = register_hotcpu_notifier(&vi->nb); + if (err) + return err; + return 0; } #endif -- cgit v1.2.3 From 666a76c79fc23fef31fb870193053464148ba488 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Fri, 1 Nov 2013 15:01:10 +0800 Subject: net: flow_dissector: fail on evil iph->ihl [ Upstream commit 6f092343855a71e03b8d209815d8c45bf3a27fcd ] We don't validate iph->ihl which may lead a dead loop if we meet a IPIP skb whose iph->ihl is zero. Fix this by failing immediately when iph->ihl is evil (less than 5). This issue were introduced by commit ec5efe7946280d1e84603389a1030ccec0a767ae (rps: support IPIP encapsulation). Signed-off-by: Jason Wang Cc: Eric Dumazet Cc: Petr Matousek Cc: Michael S. Tsirkin Cc: Daniel Borkmann Acked-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/flow_dissector.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index 44db78ae6a65..f97101b4d373 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c @@ -40,7 +40,7 @@ again: struct iphdr _iph; ip: iph = skb_header_pointer(skb, nhoff, sizeof(_iph), &_iph); - if (!iph) + if (!iph || iph->ihl < 5) return false; if (ip_is_fragment(iph)) -- cgit v1.2.3 From 5bf906573cbe62fb4b4bb61db5086e62c62d9b2a Mon Sep 17 00:00:00 2001 From: Jack Morgenstein Date: Sun, 3 Nov 2013 10:04:07 +0200 Subject: net/mlx4_core: Fix call to __mlx4_unregister_mac [ Upstream commit c32b7dfbb1dfb3f0a68f250deff65103c8bb704a ] In function mlx4_master_deactivate_admin_state() __mlx4_unregister_mac was called using the MAC index. It should be called with the value of the MAC itself. Signed-off-by: Jack Morgenstein Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/mellanox/mlx4/cmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c index 0e572a527154..28d706bd12eb 100644 --- a/drivers/net/ethernet/mellanox/mlx4/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c @@ -1544,7 +1544,7 @@ static void mlx4_master_deactivate_admin_state(struct mlx4_priv *priv, int slave vp_oper->vlan_idx = NO_INDX; } if (NO_INDX != vp_oper->mac_idx) { - __mlx4_unregister_mac(&priv->dev, port, vp_oper->mac_idx); + __mlx4_unregister_mac(&priv->dev, port, vp_oper->state.mac); vp_oper->mac_idx = NO_INDX; } } -- cgit v1.2.3 From 7ab12337112dce7669c2481f6077b1ebfb048ddc Mon Sep 17 00:00:00 2001 From: Paul Durrant Date: Thu, 26 Sep 2013 12:09:52 +0100 Subject: xen-netback: Handle backend state transitions in a more robust way [ Upstream commit ea732dff5cfa10789007bf4a5b935388a0bb2a8f ] When the frontend state changes netback now specifies its desired state to a new function, set_backend_state(), which transitions through any necessary intermediate states. This fixes an issue observed with some old Windows frontend drivers where they failed to transition through the Closing state and netback would not behave correctly. Signed-off-by: Paul Durrant Cc: Ian Campbell Cc: Wei Liu Cc: David Vrabel Acked-by: Ian Campbell Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/xen-netback/xenbus.c | 149 +++++++++++++++++++++++++++++++-------- 1 file changed, 118 insertions(+), 31 deletions(-) diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c index abe24ff000f0..805a0a328391 100644 --- a/drivers/net/xen-netback/xenbus.c +++ b/drivers/net/xen-netback/xenbus.c @@ -24,6 +24,12 @@ struct backend_info { struct xenbus_device *dev; struct xenvif *vif; + + /* This is the state that will be reflected in xenstore when any + * active hotplug script completes. + */ + enum xenbus_state state; + enum xenbus_state frontend_state; struct xenbus_watch hotplug_status_watch; u8 have_hotplug_status_watch:1; @@ -126,6 +132,8 @@ static int netback_probe(struct xenbus_device *dev, if (err) goto fail; + be->state = XenbusStateInitWait; + /* This kicks hotplug scripts, so do it immediately. */ backend_create_xenvif(be); @@ -198,24 +206,113 @@ static void backend_create_xenvif(struct backend_info *be) kobject_uevent(&dev->dev.kobj, KOBJ_ONLINE); } - -static void disconnect_backend(struct xenbus_device *dev) +static void backend_disconnect(struct backend_info *be) { - struct backend_info *be = dev_get_drvdata(&dev->dev); - if (be->vif) xenvif_disconnect(be->vif); } -static void destroy_backend(struct xenbus_device *dev) +static void backend_connect(struct backend_info *be) { - struct backend_info *be = dev_get_drvdata(&dev->dev); + if (be->vif) + connect(be); +} - if (be->vif) { - kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE); - xenbus_rm(XBT_NIL, dev->nodename, "hotplug-status"); - xenvif_free(be->vif); - be->vif = NULL; +static inline void backend_switch_state(struct backend_info *be, + enum xenbus_state state) +{ + struct xenbus_device *dev = be->dev; + + pr_debug("%s -> %s\n", dev->nodename, xenbus_strstate(state)); + be->state = state; + + /* If we are waiting for a hotplug script then defer the + * actual xenbus state change. + */ + if (!be->have_hotplug_status_watch) + xenbus_switch_state(dev, state); +} + +/* Handle backend state transitions: + * + * The backend state starts in InitWait and the following transitions are + * allowed. + * + * InitWait -> Connected + * + * ^ \ | + * | \ | + * | \ | + * | \ | + * | \ | + * | \ | + * | V V + * + * Closed <-> Closing + * + * The state argument specifies the eventual state of the backend and the + * function transitions to that state via the shortest path. + */ +static void set_backend_state(struct backend_info *be, + enum xenbus_state state) +{ + while (be->state != state) { + switch (be->state) { + case XenbusStateClosed: + switch (state) { + case XenbusStateInitWait: + case XenbusStateConnected: + pr_info("%s: prepare for reconnect\n", + be->dev->nodename); + backend_switch_state(be, XenbusStateInitWait); + break; + case XenbusStateClosing: + backend_switch_state(be, XenbusStateClosing); + break; + default: + BUG(); + } + break; + case XenbusStateInitWait: + switch (state) { + case XenbusStateConnected: + backend_connect(be); + backend_switch_state(be, XenbusStateConnected); + break; + case XenbusStateClosing: + case XenbusStateClosed: + backend_switch_state(be, XenbusStateClosing); + break; + default: + BUG(); + } + break; + case XenbusStateConnected: + switch (state) { + case XenbusStateInitWait: + case XenbusStateClosing: + case XenbusStateClosed: + backend_disconnect(be); + backend_switch_state(be, XenbusStateClosing); + break; + default: + BUG(); + } + break; + case XenbusStateClosing: + switch (state) { + case XenbusStateInitWait: + case XenbusStateConnected: + case XenbusStateClosed: + backend_switch_state(be, XenbusStateClosed); + break; + default: + BUG(); + } + break; + default: + BUG(); + } } } @@ -227,41 +324,33 @@ static void frontend_changed(struct xenbus_device *dev, { struct backend_info *be = dev_get_drvdata(&dev->dev); - pr_debug("frontend state %s", xenbus_strstate(frontend_state)); + pr_debug("%s -> %s\n", dev->otherend, xenbus_strstate(frontend_state)); be->frontend_state = frontend_state; switch (frontend_state) { case XenbusStateInitialising: - if (dev->state == XenbusStateClosed) { - printk(KERN_INFO "%s: %s: prepare for reconnect\n", - __func__, dev->nodename); - xenbus_switch_state(dev, XenbusStateInitWait); - } + set_backend_state(be, XenbusStateInitWait); break; case XenbusStateInitialised: break; case XenbusStateConnected: - if (dev->state == XenbusStateConnected) - break; - if (be->vif) - connect(be); + set_backend_state(be, XenbusStateConnected); break; case XenbusStateClosing: - disconnect_backend(dev); - xenbus_switch_state(dev, XenbusStateClosing); + set_backend_state(be, XenbusStateClosing); break; case XenbusStateClosed: - xenbus_switch_state(dev, XenbusStateClosed); + set_backend_state(be, XenbusStateClosed); if (xenbus_dev_is_online(dev)) break; - destroy_backend(dev); /* fall through if not online */ case XenbusStateUnknown: + set_backend_state(be, XenbusStateClosed); device_unregister(&dev->dev); break; @@ -354,7 +443,9 @@ static void hotplug_status_changed(struct xenbus_watch *watch, if (IS_ERR(str)) return; if (len == sizeof("connected")-1 && !memcmp(str, "connected", len)) { - xenbus_switch_state(be->dev, XenbusStateConnected); + /* Complete any pending state change */ + xenbus_switch_state(be->dev, be->state); + /* Not interested in this watch anymore. */ unregister_hotplug_status_watch(be); } @@ -384,12 +475,8 @@ static void connect(struct backend_info *be) err = xenbus_watch_pathfmt(dev, &be->hotplug_status_watch, hotplug_status_changed, "%s/%s", dev->nodename, "hotplug-status"); - if (err) { - /* Switch now, since we can't do a watch. */ - xenbus_switch_state(dev, XenbusStateConnected); - } else { + if (!err) be->have_hotplug_status_watch = 1; - } netif_wake_queue(be->vif->dev); } -- cgit v1.2.3 From 7e19d6db7caebd7b8ffe29ff687cc399b59790bc Mon Sep 17 00:00:00 2001 From: David Vrabel Date: Mon, 7 Oct 2013 13:55:19 +0100 Subject: xen-netback: transition to CLOSED when removing a VIF [ Upstream commit dc62ccaccfb139d9b04bbc5a2688a4402adbfab3 ] If a guest is destroyed without transitioning its frontend to CLOSED, the domain becomes a zombie as netback was not grant unmapping the shared rings. When removing a VIF, transition the backend to CLOSED so the VIF is disconnected if necessary (which will unmap the shared rings etc). This fixes a regression introduced by 279f438e36c0a70b23b86d2090aeec50155034a9 (xen-netback: Don't destroy the netdev until the vif is shut down). Signed-off-by: David Vrabel Cc: Ian Campbell Cc: Wei Liu Cc: Paul Durrant Acked-by: Wei Liu Reviewed-by: Paul Durrant Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/xen-netback/xenbus.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c index 805a0a328391..8a9e8750703f 100644 --- a/drivers/net/xen-netback/xenbus.c +++ b/drivers/net/xen-netback/xenbus.c @@ -39,11 +39,15 @@ static int connect_rings(struct backend_info *); static void connect(struct backend_info *); static void backend_create_xenvif(struct backend_info *be); static void unregister_hotplug_status_watch(struct backend_info *be); +static void set_backend_state(struct backend_info *be, + enum xenbus_state state); static int netback_remove(struct xenbus_device *dev) { struct backend_info *be = dev_get_drvdata(&dev->dev); + set_backend_state(be, XenbusStateClosed); + unregister_hotplug_status_watch(be); if (be->vif) { kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE); -- cgit v1.2.3 From b44cfec16dac9c2aba3581c57488bad1989778f7 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Fri, 27 Sep 2013 18:03:39 +0200 Subject: batman-adv: set up network coding packet handlers during module init commit 6c519bad7b19a2c14a075b400edabaa630330123 upstream. batman-adv saves its table of packet handlers as a global state, so handlers must be set up only once (and setting them up a second time will fail). The recently-added network coding support tries to set up its handler each time a new softif is registered, which obviously fails when more that one softif is used (and in consequence, the softif creation fails). Fix this by splitting up batadv_nc_init into batadv_nc_init (which is called only once) and batadv_nc_mesh_init (which is called for each softif); in addition batadv_nc_free is renamed to batadv_nc_mesh_free to keep naming consistent. Signed-off-by: Matthias Schiffer Signed-off-by: Marek Lindner Signed-off-by: Antonio Quartulli Cc: David Miller Signed-off-by: Greg Kroah-Hartman --- net/batman-adv/main.c | 5 +++-- net/batman-adv/network-coding.c | 28 ++++++++++++++++++---------- net/batman-adv/network-coding.h | 14 ++++++++++---- 3 files changed, 31 insertions(+), 16 deletions(-) diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c index 51aafd669cbb..f1cb1f56cda9 100644 --- a/net/batman-adv/main.c +++ b/net/batman-adv/main.c @@ -61,6 +61,7 @@ static int __init batadv_init(void) batadv_recv_handler_init(); batadv_iv_init(); + batadv_nc_init(); batadv_event_workqueue = create_singlethread_workqueue("bat_events"); @@ -138,7 +139,7 @@ int batadv_mesh_init(struct net_device *soft_iface) if (ret < 0) goto err; - ret = batadv_nc_init(bat_priv); + ret = batadv_nc_mesh_init(bat_priv); if (ret < 0) goto err; @@ -163,7 +164,7 @@ void batadv_mesh_free(struct net_device *soft_iface) batadv_vis_quit(bat_priv); batadv_gw_node_purge(bat_priv); - batadv_nc_free(bat_priv); + batadv_nc_mesh_free(bat_priv); batadv_dat_free(bat_priv); batadv_bla_free(bat_priv); diff --git a/net/batman-adv/network-coding.c b/net/batman-adv/network-coding.c index e84629ece9b7..f97aeee2201c 100644 --- a/net/batman-adv/network-coding.c +++ b/net/batman-adv/network-coding.c @@ -34,6 +34,20 @@ static void batadv_nc_worker(struct work_struct *work); static int batadv_nc_recv_coded_packet(struct sk_buff *skb, struct batadv_hard_iface *recv_if); +/** + * batadv_nc_init - one-time initialization for network coding + */ +int __init batadv_nc_init(void) +{ + int ret; + + /* Register our packet type */ + ret = batadv_recv_handler_register(BATADV_CODED, + batadv_nc_recv_coded_packet); + + return ret; +} + /** * batadv_nc_start_timer - initialise the nc periodic worker * @bat_priv: the bat priv with all the soft interface information @@ -45,10 +59,10 @@ static void batadv_nc_start_timer(struct batadv_priv *bat_priv) } /** - * batadv_nc_init - initialise coding hash table and start house keeping + * batadv_nc_mesh_init - initialise coding hash table and start house keeping * @bat_priv: the bat priv with all the soft interface information */ -int batadv_nc_init(struct batadv_priv *bat_priv) +int batadv_nc_mesh_init(struct batadv_priv *bat_priv) { bat_priv->nc.timestamp_fwd_flush = jiffies; bat_priv->nc.timestamp_sniffed_purge = jiffies; @@ -70,11 +84,6 @@ int batadv_nc_init(struct batadv_priv *bat_priv) batadv_hash_set_lock_class(bat_priv->nc.coding_hash, &batadv_nc_decoding_hash_lock_class_key); - /* Register our packet type */ - if (batadv_recv_handler_register(BATADV_CODED, - batadv_nc_recv_coded_packet) < 0) - goto err; - INIT_DELAYED_WORK(&bat_priv->nc.work, batadv_nc_worker); batadv_nc_start_timer(bat_priv); @@ -1722,12 +1731,11 @@ free_nc_packet: } /** - * batadv_nc_free - clean up network coding memory + * batadv_nc_mesh_free - clean up network coding memory * @bat_priv: the bat priv with all the soft interface information */ -void batadv_nc_free(struct batadv_priv *bat_priv) +void batadv_nc_mesh_free(struct batadv_priv *bat_priv) { - batadv_recv_handler_unregister(BATADV_CODED); cancel_delayed_work_sync(&bat_priv->nc.work); batadv_nc_purge_paths(bat_priv, bat_priv->nc.coding_hash, NULL); diff --git a/net/batman-adv/network-coding.h b/net/batman-adv/network-coding.h index 4fa6d0caddbd..bd4295fb960f 100644 --- a/net/batman-adv/network-coding.h +++ b/net/batman-adv/network-coding.h @@ -22,8 +22,9 @@ #ifdef CONFIG_BATMAN_ADV_NC -int batadv_nc_init(struct batadv_priv *bat_priv); -void batadv_nc_free(struct batadv_priv *bat_priv); +int batadv_nc_init(void); +int batadv_nc_mesh_init(struct batadv_priv *bat_priv); +void batadv_nc_mesh_free(struct batadv_priv *bat_priv); void batadv_nc_update_nc_node(struct batadv_priv *bat_priv, struct batadv_orig_node *orig_node, struct batadv_orig_node *orig_neigh_node, @@ -47,12 +48,17 @@ int batadv_nc_init_debugfs(struct batadv_priv *bat_priv); #else /* ifdef CONFIG_BATMAN_ADV_NC */ -static inline int batadv_nc_init(struct batadv_priv *bat_priv) +static inline int batadv_nc_init(void) { return 0; } -static inline void batadv_nc_free(struct batadv_priv *bat_priv) +static inline int batadv_nc_mesh_init(struct batadv_priv *bat_priv) +{ + return 0; +} + +static inline void batadv_nc_mesh_free(struct batadv_priv *bat_priv) { return; } -- cgit v1.2.3 From 41bb9b0ef41b4abb1dadef28d0aa7c568add7f85 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 2 Oct 2013 13:55:10 +0200 Subject: hyperv-fb: add pci stub commit 7ad9684721606efbfb9b347346816e1e6baff8bb upstream. This patch adds a pci stub driver to hyper-fb. The hyperv framebuffer driver will bind to the pci device then, so linux kernel and userspace know there is a proper kernel driver for the device active. lspci shows this for example: [root@dhcp231 ~]# lspci -vs8 00:08.0 VGA compatible controller: Microsoft Corporation Hyper-V virtual VGA (prog-if 00 [VGA controller]) Flags: bus master, fast devsel, latency 0, IRQ 11 Memory at f8000000 (32-bit, non-prefetchable) [size=64M] Expansion ROM at [disabled] Kernel driver in use: hyperv_fb Another effect is that the xorg vesa driver will not attach to the device and thus the Xorg server will automatically use the fbdev driver instead. Signed-off-by: Gerd Hoffmann Acked-by: Haiyang Zhang Signed-off-by: Tomi Valkeinen Signed-off-by: Greg Kroah-Hartman --- drivers/video/hyperv_fb.c | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/drivers/video/hyperv_fb.c b/drivers/video/hyperv_fb.c index d4d2c5fe2488..0f3b33cf13ef 100644 --- a/drivers/video/hyperv_fb.c +++ b/drivers/video/hyperv_fb.c @@ -795,12 +795,21 @@ static int hvfb_remove(struct hv_device *hdev) } +static DEFINE_PCI_DEVICE_TABLE(pci_stub_id_table) = { + { + .vendor = PCI_VENDOR_ID_MICROSOFT, + .device = PCI_DEVICE_ID_HYPERV_VIDEO, + }, + { /* end of list */ } +}; + static const struct hv_vmbus_device_id id_table[] = { /* Synthetic Video Device GUID */ {HV_SYNTHVID_GUID}, {} }; +MODULE_DEVICE_TABLE(pci, pci_stub_id_table); MODULE_DEVICE_TABLE(vmbus, id_table); static struct hv_driver hvfb_drv = { @@ -810,14 +819,43 @@ static struct hv_driver hvfb_drv = { .remove = hvfb_remove, }; +static int hvfb_pci_stub_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + return 0; +} + +static void hvfb_pci_stub_remove(struct pci_dev *pdev) +{ +} + +static struct pci_driver hvfb_pci_stub_driver = { + .name = KBUILD_MODNAME, + .id_table = pci_stub_id_table, + .probe = hvfb_pci_stub_probe, + .remove = hvfb_pci_stub_remove, +}; static int __init hvfb_drv_init(void) { - return vmbus_driver_register(&hvfb_drv); + int ret; + + ret = vmbus_driver_register(&hvfb_drv); + if (ret != 0) + return ret; + + ret = pci_register_driver(&hvfb_pci_stub_driver); + if (ret != 0) { + vmbus_driver_unregister(&hvfb_drv); + return ret; + } + + return 0; } static void __exit hvfb_drv_exit(void) { + pci_unregister_driver(&hvfb_pci_stub_driver); vmbus_driver_unregister(&hvfb_drv); } -- cgit v1.2.3 From e70bfcc02cc2a5192528134ab32599cccac4920c Mon Sep 17 00:00:00 2001 From: Rui li Date: Fri, 25 Oct 2013 10:57:21 +0800 Subject: USB: add new zte 3g-dongle's pid to option.c commit 0636fc507a976cdc40f21bdbcce6f0b98ff1dfe9 upstream. Signed-off-by: Rui li Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index acaee066b99a..c3d94853b4ab 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -1376,6 +1376,23 @@ static const struct usb_device_id option_ids[] = { .driver_info = (kernel_ulong_t)&net_intf2_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1426, 0xff, 0xff, 0xff), /* ZTE MF91 */ .driver_info = (kernel_ulong_t)&net_intf2_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1533, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1534, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1535, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1545, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1546, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1547, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1565, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1566, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1567, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1589, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1590, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1591, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1592, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1594, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1596, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1598, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1600, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&zte_k3765_z_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) }, -- cgit v1.2.3 From 1c645a14a672c2a1affd2ad1f7add118394b925a Mon Sep 17 00:00:00 2001 From: Anssi Hannula Date: Sat, 5 Oct 2013 02:25:38 +0300 Subject: ALSA: hda - hdmi: Fix reported channel map on common default layouts commit 56cac413dd6d43af8355f5d1f90a199b540f73fc upstream. hdmi_setup_fake_chmap() is supposed to set the reported channel map when the channel map is not specified by the user. However, the function indexes channel_allocations[] with a wrong value and extracts the wrong nibble from hdmi_channel_mapping[], causing wrong channel maps to be shown. Fix those issues. Tested on Intel HDMI to correctly generate various channel maps, for example 3,4,14,15,7,8,5,6 (instead of incorrect 3,4,8,7,5,6,14,0) for standard 7.1 channel audio. (Note that the side and rear channels are reported as RL/RR and RLC/RRC, respectively, as per the CEA-861 standard, instead of the more traditional SL/SR and RL/RR.) Note that this only fixes the layouts that only contain traditional 7.1 speakers (2.0, 2.1, 4.0, 5.1, 7.1, etc.). E.g. the rear center of 6.1 is still being shown wrongly due to an issue with from_cea_slot() which will be fixed in a later patch. Signed-off-by: Anssi Hannula Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_hdmi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index aecf088f40af..b93799201578 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -738,9 +738,10 @@ static int hdmi_manual_setup_channel_mapping(struct hda_codec *codec, static void hdmi_setup_fake_chmap(unsigned char *map, int ca) { int i; + int ordered_ca = get_channel_allocation_order(ca); for (i = 0; i < 8; i++) { - if (i < channel_allocations[ca].channels) - map[i] = from_cea_slot((hdmi_channel_mapping[ca][i] >> 4) & 0x0f); + if (i < channel_allocations[ordered_ca].channels) + map[i] = from_cea_slot(hdmi_channel_mapping[ca][i] & 0x0f); else map[i] = 0; } -- cgit v1.2.3 From 8430063608b2a95a75cdf3ddd3fbd7dac88c151f Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Wed, 9 Oct 2013 22:23:23 -0400 Subject: tracing: Fix potential out-of-bounds in trace_get_user() commit 057db8488b53d5e4faa0cedb2f39d4ae75dfbdbb upstream. Andrey reported the following report: ERROR: AddressSanitizer: heap-buffer-overflow on address ffff8800359c99f3 ffff8800359c99f3 is located 0 bytes to the right of 243-byte region [ffff8800359c9900, ffff8800359c99f3) Accessed by thread T13003: #0 ffffffff810dd2da (asan_report_error+0x32a/0x440) #1 ffffffff810dc6b0 (asan_check_region+0x30/0x40) #2 ffffffff810dd4d3 (__tsan_write1+0x13/0x20) #3 ffffffff811cd19e (ftrace_regex_release+0x1be/0x260) #4 ffffffff812a1065 (__fput+0x155/0x360) #5 ffffffff812a12de (____fput+0x1e/0x30) #6 ffffffff8111708d (task_work_run+0x10d/0x140) #7 ffffffff810ea043 (do_exit+0x433/0x11f0) #8 ffffffff810eaee4 (do_group_exit+0x84/0x130) #9 ffffffff810eafb1 (SyS_exit_group+0x21/0x30) #10 ffffffff81928782 (system_call_fastpath+0x16/0x1b) Allocated by thread T5167: #0 ffffffff810dc778 (asan_slab_alloc+0x48/0xc0) #1 ffffffff8128337c (__kmalloc+0xbc/0x500) #2 ffffffff811d9d54 (trace_parser_get_init+0x34/0x90) #3 ffffffff811cd7b3 (ftrace_regex_open+0x83/0x2e0) #4 ffffffff811cda7d (ftrace_filter_open+0x2d/0x40) #5 ffffffff8129b4ff (do_dentry_open+0x32f/0x430) #6 ffffffff8129b668 (finish_open+0x68/0xa0) #7 ffffffff812b66ac (do_last+0xb8c/0x1710) #8 ffffffff812b7350 (path_openat+0x120/0xb50) #9 ffffffff812b8884 (do_filp_open+0x54/0xb0) #10 ffffffff8129d36c (do_sys_open+0x1ac/0x2c0) #11 ffffffff8129d4b7 (SyS_open+0x37/0x50) #12 ffffffff81928782 (system_call_fastpath+0x16/0x1b) Shadow bytes around the buggy address: ffff8800359c9700: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd ffff8800359c9780: fd fd fd fd fd fd fd fd fa fa fa fa fa fa fa fa ffff8800359c9800: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa ffff8800359c9880: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa ffff8800359c9900: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 =>ffff8800359c9980: 00 00 00 00 00 00 00 00 00 00 00 00 00 00[03]fb ffff8800359c9a00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa ffff8800359c9a80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa ffff8800359c9b00: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00 ffff8800359c9b80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ffff8800359c9c00: 00 00 00 00 00 00 00 00 fa fa fa fa fa fa fa fa Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap redzone: fa Heap kmalloc redzone: fb Freed heap region: fd Shadow gap: fe The out-of-bounds access happens on 'parser->buffer[parser->idx] = 0;' Although the crash happened in ftrace_regex_open() the real bug occurred in trace_get_user() where there's an incrementation to parser->idx without a check against the size. The way it is triggered is if userspace sends in 128 characters (EVENT_BUF_SIZE + 1), the loop that reads the last character stores it and then breaks out because there is no more characters. Then the last character is read to determine what to do next, and the index is incremented without checking size. Then the caller of trace_get_user() usually nulls out the last character with a zero, but since the index is equal to the size, it writes a nul character after the allocated space, which can corrupt memory. Luckily, only root user has write access to this file. Link: http://lkml.kernel.org/r/20131009222323.04fd1a0d@gandalf.local.home Reported-by: Andrey Konovalov Signed-off-by: Steven Rostedt Signed-off-by: Greg Kroah-Hartman --- kernel/trace/trace.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 0582a01a81e3..5546ae9c84f9 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -826,9 +826,12 @@ int trace_get_user(struct trace_parser *parser, const char __user *ubuf, if (isspace(ch)) { parser->buffer[parser->idx] = 0; parser->cont = false; - } else { + } else if (parser->idx < parser->size - 1) { parser->cont = true; parser->buffer[parser->idx++] = ch; + } else { + ret = -EINVAL; + goto out; } *ppos += read; -- cgit v1.2.3 From 0fb024c4377701319ae29af1b23b647885d7c808 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 28 Oct 2013 13:55:29 +0100 Subject: perf: Fix perf ring buffer memory ordering commit bf378d341e4873ed928dc3c636252e6895a21f50 upstream. The PPC64 people noticed a missing memory barrier and crufty old comments in the perf ring buffer code. So update all the comments and add the missing barrier. When the architecture implements local_t using atomic_long_t there will be double barriers issued; but short of introducing more conditional barrier primitives this is the best we can do. Reported-by: Victor Kaplansky Tested-by: Victor Kaplansky Signed-off-by: Peter Zijlstra Cc: Mathieu Desnoyers Cc: michael@ellerman.id.au Cc: Paul McKenney Cc: Michael Neuling Cc: Frederic Weisbecker Cc: anton@samba.org Cc: benh@kernel.crashing.org Link: http://lkml.kernel.org/r/20131025173749.GG19466@laptop.lan Signed-off-by: Ingo Molnar Cc: Michael Neuling Signed-off-by: Greg Kroah-Hartman --- include/uapi/linux/perf_event.h | 12 +++++++----- kernel/events/ring_buffer.c | 31 +++++++++++++++++++++++++++---- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h index fb104e51496e..9e59950f55cf 100644 --- a/include/uapi/linux/perf_event.h +++ b/include/uapi/linux/perf_event.h @@ -425,13 +425,15 @@ struct perf_event_mmap_page { /* * Control data for the mmap() data buffer. * - * User-space reading the @data_head value should issue an rmb(), on - * SMP capable platforms, after reading this value -- see - * perf_event_wakeup(). + * User-space reading the @data_head value should issue an smp_rmb(), + * after reading this value. * * When the mapping is PROT_WRITE the @data_tail value should be - * written by userspace to reflect the last read data. In this case - * the kernel will not over-write unread data. + * written by userspace to reflect the last read data, after issueing + * an smp_mb() to separate the data read from the ->data_tail store. + * In this case the kernel will not over-write unread data. + * + * See perf_output_put_handle() for the data ordering. */ __u64 data_head; /* head in the data section */ __u64 data_tail; /* user-space written tail */ diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c index cd55144270b5..9c2ddfbf4525 100644 --- a/kernel/events/ring_buffer.c +++ b/kernel/events/ring_buffer.c @@ -87,10 +87,31 @@ again: goto out; /* - * Publish the known good head. Rely on the full barrier implied - * by atomic_dec_and_test() order the rb->head read and this - * write. + * Since the mmap() consumer (userspace) can run on a different CPU: + * + * kernel user + * + * READ ->data_tail READ ->data_head + * smp_mb() (A) smp_rmb() (C) + * WRITE $data READ $data + * smp_wmb() (B) smp_mb() (D) + * STORE ->data_head WRITE ->data_tail + * + * Where A pairs with D, and B pairs with C. + * + * I don't think A needs to be a full barrier because we won't in fact + * write data until we see the store from userspace. So we simply don't + * issue the data WRITE until we observe it. Be conservative for now. + * + * OTOH, D needs to be a full barrier since it separates the data READ + * from the tail WRITE. + * + * For B a WMB is sufficient since it separates two WRITEs, and for C + * an RMB is sufficient since it separates two READs. + * + * See perf_output_begin(). */ + smp_wmb(); rb->user_page->data_head = head; /* @@ -154,9 +175,11 @@ int perf_output_begin(struct perf_output_handle *handle, * Userspace could choose to issue a mb() before updating the * tail pointer. So that all reads will be completed before the * write is issued. + * + * See perf_output_put_handle(). */ tail = ACCESS_ONCE(rb->user_page->data_tail); - smp_rmb(); + smp_mb(); offset = head = local_read(&rb->head); head += size; if (unlikely(!perf_output_space(rb, tail, offset, head))) -- cgit v1.2.3 From fa97ca4fc69f9f3a0f862184505ce87b05e0199b Mon Sep 17 00:00:00 2001 From: Oren Givon Date: Tue, 23 Apr 2013 18:19:11 +0300 Subject: iwlwifi: add new 7260 and 3160 series device IDs commit 93fc64114b994f9ef6901697f9b0de00762680e9 upstream. Add new device IDs and configurations to support all the devices. Signed-off-by: Oren Givon Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/iwlwifi/iwl-7000.c | 42 ++++++++++++++++++++++++-- drivers/net/wireless/iwlwifi/iwl-config.h | 6 +++- drivers/net/wireless/iwlwifi/pcie/drv.c | 50 +++++++++++++++++++++++++++++-- 3 files changed, 91 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-7000.c b/drivers/net/wireless/iwlwifi/iwl-7000.c index dc94d44d95cd..822443c5a3b5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-7000.c +++ b/drivers/net/wireless/iwlwifi/iwl-7000.c @@ -125,7 +125,7 @@ static const struct iwl_ht_params iwl7000_ht_params = { const struct iwl_cfg iwl7260_2ac_cfg = { - .name = "Intel(R) Dual Band Wireless AC7260", + .name = "Intel(R) Dual Band Wireless AC 7260", .fw_name_pre = IWL7260_FW_PRE, IWL_DEVICE_7000, .ht_params = &iwl7000_ht_params, @@ -133,8 +133,44 @@ const struct iwl_cfg iwl7260_2ac_cfg = { .nvm_calib_ver = IWL7260_TX_POWER_VERSION, }; -const struct iwl_cfg iwl3160_ac_cfg = { - .name = "Intel(R) Dual Band Wireless AC3160", +const struct iwl_cfg iwl7260_2n_cfg = { + .name = "Intel(R) Dual Band Wireless N 7260", + .fw_name_pre = IWL7260_FW_PRE, + IWL_DEVICE_7000, + .ht_params = &iwl7000_ht_params, + .nvm_ver = IWL7260_NVM_VERSION, + .nvm_calib_ver = IWL7260_TX_POWER_VERSION, +}; + +const struct iwl_cfg iwl7260_n_cfg = { + .name = "Intel(R) Wireless N 7260", + .fw_name_pre = IWL7260_FW_PRE, + IWL_DEVICE_7000, + .ht_params = &iwl7000_ht_params, + .nvm_ver = IWL7260_NVM_VERSION, + .nvm_calib_ver = IWL7260_TX_POWER_VERSION, +}; + +const struct iwl_cfg iwl3160_2ac_cfg = { + .name = "Intel(R) Dual Band Wireless AC 3160", + .fw_name_pre = IWL3160_FW_PRE, + IWL_DEVICE_7000, + .ht_params = &iwl7000_ht_params, + .nvm_ver = IWL3160_NVM_VERSION, + .nvm_calib_ver = IWL3160_TX_POWER_VERSION, +}; + +const struct iwl_cfg iwl3160_2n_cfg = { + .name = "Intel(R) Dual Band Wireless N 3160", + .fw_name_pre = IWL3160_FW_PRE, + IWL_DEVICE_7000, + .ht_params = &iwl7000_ht_params, + .nvm_ver = IWL3160_NVM_VERSION, + .nvm_calib_ver = IWL3160_TX_POWER_VERSION, +}; + +const struct iwl_cfg iwl3160_n_cfg = { + .name = "Intel(R) Wireless N 3160", .fw_name_pre = IWL3160_FW_PRE, IWL_DEVICE_7000, .ht_params = &iwl7000_ht_params, diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h index c67e29655b2d..44e3370ce343 100644 --- a/drivers/net/wireless/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/iwlwifi/iwl-config.h @@ -321,6 +321,10 @@ extern const struct iwl_cfg iwl105_bgn_cfg; extern const struct iwl_cfg iwl105_bgn_d_cfg; extern const struct iwl_cfg iwl135_bgn_cfg; extern const struct iwl_cfg iwl7260_2ac_cfg; -extern const struct iwl_cfg iwl3160_ac_cfg; +extern const struct iwl_cfg iwl7260_2n_cfg; +extern const struct iwl_cfg iwl7260_n_cfg; +extern const struct iwl_cfg iwl3160_2ac_cfg; +extern const struct iwl_cfg iwl3160_2n_cfg; +extern const struct iwl_cfg iwl3160_n_cfg; #endif /* __IWL_CONFIG_H__ */ diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c index b7858a595973..d92d15723a9f 100644 --- a/drivers/net/wireless/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/iwlwifi/pcie/drv.c @@ -267,10 +267,54 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { /* 7000 Series */ {IWL_PCI_DEVICE(0x08B1, 0x4070, iwl7260_2ac_cfg)}, - {IWL_PCI_DEVICE(0x08B1, 0x4062, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x4170, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x4060, iwl7260_2n_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x4160, iwl7260_2n_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x4062, iwl7260_n_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x4162, iwl7260_n_cfg)}, + {IWL_PCI_DEVICE(0x08B2, 0x4270, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B2, 0x4260, iwl7260_2n_cfg)}, + {IWL_PCI_DEVICE(0x08B2, 0x4262, iwl7260_n_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x4470, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x4460, iwl7260_2n_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x4462, iwl7260_n_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x4870, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x486E, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x4A70, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x4A6E, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x4A6C, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x4020, iwl7260_2n_cfg)}, + {IWL_PCI_DEVICE(0x08B2, 0x4220, iwl7260_2n_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x4420, iwl7260_2n_cfg)}, {IWL_PCI_DEVICE(0x08B1, 0xC070, iwl7260_2ac_cfg)}, - {IWL_PCI_DEVICE(0x08B3, 0x0070, iwl3160_ac_cfg)}, - {IWL_PCI_DEVICE(0x08B3, 0x8070, iwl3160_ac_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0xC170, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0xC060, iwl7260_2n_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0xC160, iwl7260_2n_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0xC062, iwl7260_n_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0xC162, iwl7260_n_cfg)}, + {IWL_PCI_DEVICE(0x08B2, 0xC270, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B2, 0xC260, iwl7260_2n_cfg)}, + {IWL_PCI_DEVICE(0x08B2, 0xC262, iwl7260_n_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0xC470, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0xC460, iwl7260_2n_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0xC462, iwl7260_n_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0xC020, iwl7260_2n_cfg)}, + {IWL_PCI_DEVICE(0x08B2, 0xC220, iwl7260_2n_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0xC420, iwl7260_2n_cfg)}, + +/* 3160 Series */ + {IWL_PCI_DEVICE(0x08B3, 0x0070, iwl3160_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B3, 0x0170, iwl3160_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B3, 0x0060, iwl3160_2n_cfg)}, + {IWL_PCI_DEVICE(0x08B3, 0x0062, iwl3160_n_cfg)}, + {IWL_PCI_DEVICE(0x08B4, 0x0270, iwl3160_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B3, 0x0470, iwl3160_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B3, 0x8070, iwl3160_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B3, 0x8170, iwl3160_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B3, 0x8060, iwl3160_2n_cfg)}, + {IWL_PCI_DEVICE(0x08B3, 0x8062, iwl3160_n_cfg)}, + {IWL_PCI_DEVICE(0x08B4, 0x8270, iwl3160_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B3, 0x8470, iwl3160_2ac_cfg)}, {0} }; -- cgit v1.2.3 From dfd6a61d259ea14fb87a3c0e7980b2e77261ff90 Mon Sep 17 00:00:00 2001 From: Matti Gottlieb Date: Sun, 22 Sep 2013 08:23:23 +0300 Subject: iwlwifi: pcie: add new SKUs for 7000 & 3160 NIC series commit b49926629fb5c324bb1ed3960fb0d7905a4a8562 upstream. Add some new PCI IDs to the table for 7000 & 3160 series Signed-off-by: Matti Gottlieb Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg Signed-off-by: Emmanuel Grumbach Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/iwlwifi/pcie/drv.c | 35 ++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c index d92d15723a9f..b53e5c3f403b 100644 --- a/drivers/net/wireless/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/iwlwifi/pcie/drv.c @@ -267,54 +267,83 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { /* 7000 Series */ {IWL_PCI_DEVICE(0x08B1, 0x4070, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x4072, iwl7260_2ac_cfg)}, {IWL_PCI_DEVICE(0x08B1, 0x4170, iwl7260_2ac_cfg)}, {IWL_PCI_DEVICE(0x08B1, 0x4060, iwl7260_2n_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x406A, iwl7260_2n_cfg)}, {IWL_PCI_DEVICE(0x08B1, 0x4160, iwl7260_2n_cfg)}, {IWL_PCI_DEVICE(0x08B1, 0x4062, iwl7260_n_cfg)}, {IWL_PCI_DEVICE(0x08B1, 0x4162, iwl7260_n_cfg)}, {IWL_PCI_DEVICE(0x08B2, 0x4270, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B2, 0x4272, iwl7260_2ac_cfg)}, {IWL_PCI_DEVICE(0x08B2, 0x4260, iwl7260_2n_cfg)}, + {IWL_PCI_DEVICE(0x08B2, 0x426A, iwl7260_2n_cfg)}, {IWL_PCI_DEVICE(0x08B2, 0x4262, iwl7260_n_cfg)}, {IWL_PCI_DEVICE(0x08B1, 0x4470, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x4472, iwl7260_2ac_cfg)}, {IWL_PCI_DEVICE(0x08B1, 0x4460, iwl7260_2n_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x446A, iwl7260_2n_cfg)}, {IWL_PCI_DEVICE(0x08B1, 0x4462, iwl7260_n_cfg)}, {IWL_PCI_DEVICE(0x08B1, 0x4870, iwl7260_2ac_cfg)}, {IWL_PCI_DEVICE(0x08B1, 0x486E, iwl7260_2ac_cfg)}, - {IWL_PCI_DEVICE(0x08B1, 0x4A70, iwl7260_2ac_cfg)}, - {IWL_PCI_DEVICE(0x08B1, 0x4A6E, iwl7260_2ac_cfg)}, - {IWL_PCI_DEVICE(0x08B1, 0x4A6C, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x4570, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x4560, iwl7260_2n_cfg)}, + {IWL_PCI_DEVICE(0x08B2, 0x4370, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B2, 0x4360, iwl7260_2n_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x5070, iwl7260_2ac_cfg)}, {IWL_PCI_DEVICE(0x08B1, 0x4020, iwl7260_2n_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x402A, iwl7260_2n_cfg)}, {IWL_PCI_DEVICE(0x08B2, 0x4220, iwl7260_2n_cfg)}, {IWL_PCI_DEVICE(0x08B1, 0x4420, iwl7260_2n_cfg)}, {IWL_PCI_DEVICE(0x08B1, 0xC070, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0xC072, iwl7260_2ac_cfg)}, {IWL_PCI_DEVICE(0x08B1, 0xC170, iwl7260_2ac_cfg)}, {IWL_PCI_DEVICE(0x08B1, 0xC060, iwl7260_2n_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0xC06A, iwl7260_2n_cfg)}, {IWL_PCI_DEVICE(0x08B1, 0xC160, iwl7260_2n_cfg)}, {IWL_PCI_DEVICE(0x08B1, 0xC062, iwl7260_n_cfg)}, {IWL_PCI_DEVICE(0x08B1, 0xC162, iwl7260_n_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0xC770, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0xC760, iwl7260_2n_cfg)}, {IWL_PCI_DEVICE(0x08B2, 0xC270, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B2, 0xC272, iwl7260_2ac_cfg)}, {IWL_PCI_DEVICE(0x08B2, 0xC260, iwl7260_2n_cfg)}, + {IWL_PCI_DEVICE(0x08B2, 0xC26A, iwl7260_n_cfg)}, {IWL_PCI_DEVICE(0x08B2, 0xC262, iwl7260_n_cfg)}, {IWL_PCI_DEVICE(0x08B1, 0xC470, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0xC472, iwl7260_2ac_cfg)}, {IWL_PCI_DEVICE(0x08B1, 0xC460, iwl7260_2n_cfg)}, {IWL_PCI_DEVICE(0x08B1, 0xC462, iwl7260_n_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0xC570, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0xC560, iwl7260_2n_cfg)}, + {IWL_PCI_DEVICE(0x08B2, 0xC370, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0xC360, iwl7260_2n_cfg)}, {IWL_PCI_DEVICE(0x08B1, 0xC020, iwl7260_2n_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0xC02A, iwl7260_2n_cfg)}, {IWL_PCI_DEVICE(0x08B2, 0xC220, iwl7260_2n_cfg)}, {IWL_PCI_DEVICE(0x08B1, 0xC420, iwl7260_2n_cfg)}, /* 3160 Series */ {IWL_PCI_DEVICE(0x08B3, 0x0070, iwl3160_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B3, 0x0072, iwl3160_2ac_cfg)}, {IWL_PCI_DEVICE(0x08B3, 0x0170, iwl3160_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B3, 0x0172, iwl3160_2ac_cfg)}, {IWL_PCI_DEVICE(0x08B3, 0x0060, iwl3160_2n_cfg)}, {IWL_PCI_DEVICE(0x08B3, 0x0062, iwl3160_n_cfg)}, {IWL_PCI_DEVICE(0x08B4, 0x0270, iwl3160_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B4, 0x0272, iwl3160_2ac_cfg)}, {IWL_PCI_DEVICE(0x08B3, 0x0470, iwl3160_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B3, 0x0472, iwl3160_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B4, 0x0370, iwl3160_2ac_cfg)}, {IWL_PCI_DEVICE(0x08B3, 0x8070, iwl3160_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B3, 0x8072, iwl3160_2ac_cfg)}, {IWL_PCI_DEVICE(0x08B3, 0x8170, iwl3160_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B3, 0x8172, iwl3160_2ac_cfg)}, {IWL_PCI_DEVICE(0x08B3, 0x8060, iwl3160_2n_cfg)}, {IWL_PCI_DEVICE(0x08B3, 0x8062, iwl3160_n_cfg)}, {IWL_PCI_DEVICE(0x08B4, 0x8270, iwl3160_2ac_cfg)}, {IWL_PCI_DEVICE(0x08B3, 0x8470, iwl3160_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B3, 0x8570, iwl3160_2ac_cfg)}, {0} }; -- cgit v1.2.3 From ccd24ec4c98c1aa76e73d4fa80bf8146b5e62175 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 22 Oct 2013 18:32:39 +0200 Subject: misc: atmel_pwm: add deferred-probing support commit 5c6d6fd1564138ad048564e48639f842714a90c6 upstream. Two drivers (atmel-pwm-bl and leds-atmel-pwm) currently depend on the atmel_pwm driver to have bound to any pwm-device before their devices are probed. Support deferred probing of such devices by making sure to return -EPROBE_DEFER from pwm_channel_alloc when no pwm-device has yet been bound. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/misc/atmel_pwm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/misc/atmel_pwm.c b/drivers/misc/atmel_pwm.c index 494d0500bda6..a6dc56e1bc58 100644 --- a/drivers/misc/atmel_pwm.c +++ b/drivers/misc/atmel_pwm.c @@ -90,8 +90,10 @@ int pwm_channel_alloc(int index, struct pwm_channel *ch) unsigned long flags; int status = 0; - /* insist on PWM init, with this signal pinned out */ - if (!pwm || !(pwm->mask & 1 << index)) + if (!pwm) + return -EPROBE_DEFER; + + if (!(pwm->mask & 1 << index)) return -ENODEV; if (index < 0 || index >= PWM_NCHAN || !ch) -- cgit v1.2.3 From 4790536896fd1e76949e58530dac2ba82354bd28 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 23 Sep 2013 16:27:32 +0200 Subject: backlight: atmel-pwm-bl: fix deferred probe from __init commit 9d3fde86b15303decea632c929fbf1f3ae4501f2 upstream. Move probe out of __init section and don't use platform_driver_probe which cannot be used with deferred probing. Since commit e9354576 ("gpiolib: Defer failed gpio requests by default") this driver might return -EPROBE_DEFER if a gpio_request fails. Cc: Richard Purdie Cc: Jingoo Han Cc: Jean-Christophe Plagniol-Villard Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/video/backlight/atmel-pwm-bl.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/video/backlight/atmel-pwm-bl.c b/drivers/video/backlight/atmel-pwm-bl.c index a60d6afca97c..30e4ed52d701 100644 --- a/drivers/video/backlight/atmel-pwm-bl.c +++ b/drivers/video/backlight/atmel-pwm-bl.c @@ -118,7 +118,7 @@ static const struct backlight_ops atmel_pwm_bl_ops = { .update_status = atmel_pwm_bl_set_intensity, }; -static int __init atmel_pwm_bl_probe(struct platform_device *pdev) +static int atmel_pwm_bl_probe(struct platform_device *pdev) { struct backlight_properties props; const struct atmel_pwm_bl_platform_data *pdata; @@ -203,7 +203,7 @@ err_free_mem: return retval; } -static int __exit atmel_pwm_bl_remove(struct platform_device *pdev) +static int atmel_pwm_bl_remove(struct platform_device *pdev) { struct atmel_pwm_bl *pwmbl = platform_get_drvdata(pdev); @@ -222,10 +222,11 @@ static struct platform_driver atmel_pwm_bl_driver = { .name = "atmel-pwm-bl", }, /* REVISIT add suspend() and resume() */ - .remove = __exit_p(atmel_pwm_bl_remove), + .probe = atmel_pwm_bl_probe, + .remove = atmel_pwm_bl_remove, }; -module_platform_driver_probe(atmel_pwm_bl_driver, atmel_pwm_bl_probe); +module_platform_driver(atmel_pwm_bl_driver); MODULE_AUTHOR("Hans-Christian egtvedt "); MODULE_DESCRIPTION("Atmel PWM backlight driver"); -- cgit v1.2.3 From 734268997d0e68caa9149787d8dd70875bd6aaf2 Mon Sep 17 00:00:00 2001 From: Krzysztof Mazur Date: Thu, 22 Aug 2013 14:49:38 +0200 Subject: usb: fix cleanup after failure in hub_configure() commit d0308d4b6b02597f39fc31a9bddf7bb3faad5622 upstream. If the hub_configure() fails after setting the hdev->maxchild the hub->ports might be NULL or point to uninitialized kzallocated memory causing NULL pointer dereference in hub_quiesce() during cleanup. Now after such error the hdev->maxchild is set to 0 to avoid cleanup of uninitialized ports. Signed-off-by: Krzysztof Mazur Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 6cf2ae0aa1f7..a7515d165390 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1568,6 +1568,7 @@ static int hub_configure(struct usb_hub *hub, return 0; fail: + hdev->maxchild = 0; dev_err (hub_dev, "config failed, %s (err %d)\n", message, ret); /* hub_disconnect() frees urb and descriptor */ -- cgit v1.2.3 From 386f000abc920c7de7c06a89fc11566fc70ce4ad Mon Sep 17 00:00:00 2001 From: Krzysztof Mazur Date: Thu, 22 Aug 2013 14:49:39 +0200 Subject: usb: fail on usb_hub_create_port_device() errors commit e58547eb9561a8a72d46e2d411090a614d33ac0e upstream. Ignoring usb_hub_create_port_device() errors cause later NULL pointer deference when uninitialized hub->ports[i] entries are dereferenced after port memory allocation error. Signed-off-by: Krzysztof Mazur Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index a7515d165390..896532d3fc2d 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1557,10 +1557,15 @@ static int hub_configure(struct usb_hub *hub, if (hub->has_indicators && blinkenlights) hub->indicator [0] = INDICATOR_CYCLE; - for (i = 0; i < hdev->maxchild; i++) - if (usb_hub_create_port_device(hub, i + 1) < 0) + for (i = 0; i < hdev->maxchild; i++) { + ret = usb_hub_create_port_device(hub, i + 1); + if (ret < 0) { dev_err(hub->intfdev, "couldn't create port%d device.\n", i + 1); + hdev->maxchild = i; + goto fail_keep_maxchild; + } + } usb_hub_adjust_deviceremovable(hdev, hub->descriptor); @@ -1569,6 +1574,7 @@ static int hub_configure(struct usb_hub *hub, fail: hdev->maxchild = 0; +fail_keep_maxchild: dev_err (hub_dev, "config failed, %s (err %d)\n", message, ret); /* hub_disconnect() frees urb and descriptor */ -- cgit v1.2.3 From a5ca6f06feb5eafb05ac825b900923f06a2a6c1f Mon Sep 17 00:00:00 2001 From: Xenia Ragiadakou Date: Sat, 31 Aug 2013 18:09:12 +0300 Subject: usbcore: set lpm_capable field for LPM capable root hubs commit 9df89d85b407690afa46ddfbccc80bec6869971d upstream. This patch sets the lpm_capable field for root hubs with LPM capabilities. Signed-off-by: Xenia Ragiadakou Reported-by: Martin MOKREJS Suggested-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd.c | 1 + drivers/usb/core/hub.c | 7 ++++++- drivers/usb/core/usb.h | 1 + 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index d53547d2e4c7..d3aa353908aa 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1010,6 +1010,7 @@ static int register_root_hub(struct usb_hcd *hcd) dev_name(&usb_dev->dev), retval); return retval; } + usb_dev->lpm_capable = usb_device_supports_lpm(usb_dev); } retval = usb_new_device (usb_dev); diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 896532d3fc2d..c8b9fa0e9275 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -135,7 +135,7 @@ struct usb_hub *usb_hub_to_struct_hub(struct usb_device *hdev) return usb_get_intfdata(hdev->actconfig->interface[0]); } -static int usb_device_supports_lpm(struct usb_device *udev) +int usb_device_supports_lpm(struct usb_device *udev) { /* USB 2.1 (and greater) devices indicate LPM support through * their USB 2.0 Extended Capabilities BOS descriptor. @@ -156,6 +156,11 @@ static int usb_device_supports_lpm(struct usb_device *udev) "Power management will be impacted.\n"); return 0; } + + /* udev is root hub */ + if (!udev->parent) + return 1; + if (udev->parent->lpm_capable) return 1; diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 823857767a16..c49383669cd8 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -35,6 +35,7 @@ extern int usb_get_device_descriptor(struct usb_device *dev, unsigned int size); extern int usb_get_bos_descriptor(struct usb_device *dev); extern void usb_release_bos_descriptor(struct usb_device *dev); +extern int usb_device_supports_lpm(struct usb_device *udev); extern char *usb_cache_string(struct usb_device *udev, int index); extern int usb_set_configuration(struct usb_device *dev, int configuration); extern int usb_choose_configuration(struct usb_device *udev); -- cgit v1.2.3 From 8212db5775902438ae8875e223738fc931325ce4 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 23 Aug 2013 06:54:44 -0300 Subject: media: sh_vou: almost forever loop in sh_vou_try_fmt_vid_out() commit 47c32ec9392a1fc7dec9d7cfde084e1432fcee82 upstream. The "i < " part of the "i < ARRAY_SIZE()" condition was missing. Signed-off-by: Dan Carpenter [g.liakhovetski@gmx.de: remove unrelated superfluous braces] Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/platform/sh_vou.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/sh_vou.c b/drivers/media/platform/sh_vou.c index 7d0235069c87..5d538e7cd1bb 100644 --- a/drivers/media/platform/sh_vou.c +++ b/drivers/media/platform/sh_vou.c @@ -776,7 +776,7 @@ static int sh_vou_try_fmt_vid_out(struct file *file, void *priv, v4l_bound_align_image(&pix->width, 0, VOU_MAX_IMAGE_WIDTH, 1, &pix->height, 0, VOU_MAX_IMAGE_HEIGHT, 1, 0); - for (i = 0; ARRAY_SIZE(vou_fmt); i++) + for (i = 0; i < ARRAY_SIZE(vou_fmt); i++) if (vou_fmt[i].pfmt == pix->pixelformat) return 0; -- cgit v1.2.3 From a4c01ca3b76b28c41fb3b07a1eb1389dae24bf4a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 20 Nov 2013 12:28:01 -0800 Subject: Linux 3.10.20 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 83a02f5b2c00..ba784b7b0f51 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 10 -SUBLEVEL = 19 +SUBLEVEL = 20 EXTRAVERSION = NAME = TOSSUG Baby Fish -- cgit v1.2.3 From 82eb7924131196deccf9f09fd29d96960bc48200 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 8 Aug 2013 15:29:32 +0800 Subject: ACPICA: DeRefOf operator: Update to fully resolve FieldUnit and BufferField refs. commit 63660e05ec719613b518547b40a1c501c10f0bc4 upstream. Previously, references to these objects were resolved only to the actual FieldUnit or BufferField object. The correct behavior is to resolve these references to an actual value. The problem is that DerefOf did not resolve these objects to actual values. An "Integer" object is simple, return the value. But a field in an operation region will require a read operation. For a BufferField, the appropriate data must be extracted from the parent buffer. NOTE: It appears that this issues is present in Windows7 but not Windows8. Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/acpica/exoparg1.c | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/drivers/acpi/acpica/exoparg1.c b/drivers/acpi/acpica/exoparg1.c index b60c877f5906..eaa0fcd9644b 100644 --- a/drivers/acpi/acpica/exoparg1.c +++ b/drivers/acpi/acpica/exoparg1.c @@ -991,11 +991,40 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) acpi_namespace_node *) return_desc); - } + if (!return_desc) { + break; + } + + /* + * June 2013: + * buffer_fields/field_units require additional resolution + */ + switch (return_desc->common.type) { + case ACPI_TYPE_BUFFER_FIELD: + case ACPI_TYPE_LOCAL_REGION_FIELD: + case ACPI_TYPE_LOCAL_BANK_FIELD: + case ACPI_TYPE_LOCAL_INDEX_FIELD: + + status = + acpi_ex_read_data_from_field + (walk_state, return_desc, + &temp_desc); + if (ACPI_FAILURE(status)) { + goto cleanup; + } - /* Add another reference to the object! */ + return_desc = temp_desc; + break; - acpi_ut_add_reference(return_desc); + default: + + /* Add another reference to the object */ + + acpi_ut_add_reference + (return_desc); + break; + } + } break; default: -- cgit v1.2.3 From cdd9192be79055a0595092c2abea69399e4d951d Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 30 Oct 2013 20:12:51 +0300 Subject: libertas: potential oops in debugfs commit a497e47d4aec37aaf8f13509f3ef3d1f6a717d88 upstream. If we do a zero size allocation then it will oops. Also we can't be sure the user passes us a NUL terminated string so I've added a terminator. This code can only be triggered by root. Reported-by: Nico Golde Reported-by: Fabian Yamaguchi Signed-off-by: Dan Carpenter Acked-by: Dan Williams Signed-off-by: John W. Linville Cc: Kees Cook Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/libertas/debugfs.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c index 668dd27616a0..cc6a0a586f0b 100644 --- a/drivers/net/wireless/libertas/debugfs.c +++ b/drivers/net/wireless/libertas/debugfs.c @@ -913,7 +913,10 @@ static ssize_t lbs_debugfs_write(struct file *f, const char __user *buf, char *p2; struct debug_data *d = f->private_data; - pdata = kmalloc(cnt, GFP_KERNEL); + if (cnt == 0) + return 0; + + pdata = kmalloc(cnt + 1, GFP_KERNEL); if (pdata == NULL) return 0; @@ -922,6 +925,7 @@ static ssize_t lbs_debugfs_write(struct file *f, const char __user *buf, kfree(pdata); return 0; } + pdata[cnt] = '\0'; p0 = pdata; for (i = 0; i < num_of_items; i++) { -- cgit v1.2.3 From 0417642d6541b4583cdebbb031f8c020029400e7 Mon Sep 17 00:00:00 2001 From: Mahesh Rajashekhara Date: Thu, 31 Oct 2013 14:01:02 +0530 Subject: aacraid: prevent invalid pointer dereference commit b4789b8e6be3151a955ade74872822f30e8cd914 upstream. It appears that driver runs into a problem here if fibsize is too small because we allocate user_srbcmd with fibsize size only but later we access it until user_srbcmd->sg.count to copy it over to srbcmd. It is not correct to test (fibsize < sizeof(*user_srbcmd)) because this structure already includes one sg element and this is not needed for commands without data. So, we would recommend to add the following (instead of test for fibsize == 0). Signed-off-by: Mahesh Rajashekhara Reported-by: Nico Golde Reported-by: Fabian Yamaguchi Signed-off-by: Linus Torvalds Cc: Kees Cook Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/aacraid/commctrl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c index 1ef041bc60c8..ee6caddd978c 100644 --- a/drivers/scsi/aacraid/commctrl.c +++ b/drivers/scsi/aacraid/commctrl.c @@ -510,7 +510,8 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) goto cleanup; } - if (fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr))) { + if ((fibsize < (sizeof(struct user_aac_srb) - sizeof(struct user_sgentry))) || + (fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr)))) { rcode = -EINVAL; goto cleanup; } -- cgit v1.2.3 From 97020dadef81be7b3f1af758406a97d02c1cfa6b Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 8 Aug 2013 15:29:58 +0800 Subject: ACPICA: Return error if DerefOf resolves to a null package element. commit a50abf4842dd7d603a2ad6dcc7f1467fd2a66f03 upstream. Disallow the dereference of a reference (via index) to an uninitialized package element. Provides compatibility with other ACPI implementations. ACPICA BZ 1003. References: https://bugs.acpica.org/show_bug.cgi?id=431 Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki Signed-off-by: Lv Zheng Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/acpica/exoparg1.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/acpi/acpica/exoparg1.c b/drivers/acpi/acpica/exoparg1.c index eaa0fcd9644b..c3241b188434 100644 --- a/drivers/acpi/acpica/exoparg1.c +++ b/drivers/acpi/acpica/exoparg1.c @@ -963,10 +963,17 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) */ return_desc = *(operand[0]->reference.where); - if (return_desc) { - acpi_ut_add_reference - (return_desc); + if (!return_desc) { + /* + * Element is NULL, do not allow the dereference. + * This provides compatibility with other ACPI + * implementations. + */ + return_ACPI_STATUS + (AE_AML_UNINITIALIZED_ELEMENT); } + + acpi_ut_add_reference(return_desc); break; default: -- cgit v1.2.3 From 217e7268258cf7a23196093dc828a0d0736aeb13 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Fri, 6 Sep 2013 14:27:15 +0800 Subject: ACPICA: Fix for a Store->ArgX when ArgX contains a reference to a field. commit 4be4be8fee2ee99a52f94f90d03d2f287ee1db86 upstream. This change fixes a problem where a Store operation to an ArgX object that contained a reference to a field object did not complete the automatic dereference and then write to the actual field object. Instead, the object type of the field object was inadvertently changed to match the type of the source operand. The new behavior will actually write to the field object (buffer field or field unit), thus matching the correct ACPI-defined behavior. Signed-off-by: Bob Moore Signed-off-by: Rafael J. Wysocki Signed-off-by: Lv Zheng Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/acpica/exstore.c | 166 ++++++++++++++++++++++++++---------------- 1 file changed, 102 insertions(+), 64 deletions(-) diff --git a/drivers/acpi/acpica/exstore.c b/drivers/acpi/acpica/exstore.c index 93c6049c2d75..b1ad39443cb6 100644 --- a/drivers/acpi/acpica/exstore.c +++ b/drivers/acpi/acpica/exstore.c @@ -57,6 +57,11 @@ acpi_ex_store_object_to_index(union acpi_operand_object *val_desc, union acpi_operand_object *dest_desc, struct acpi_walk_state *walk_state); +static acpi_status +acpi_ex_store_direct_to_node(union acpi_operand_object *source_desc, + struct acpi_namespace_node *node, + struct acpi_walk_state *walk_state); + /******************************************************************************* * * FUNCTION: acpi_ex_store @@ -376,7 +381,11 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc, * When storing into an object the data is converted to the * target object type then stored in the object. This means * that the target object type (for an initialized target) will - * not be changed by a store operation. + * not be changed by a store operation. A copy_object can change + * the target type, however. + * + * The implicit_conversion flag is set to NO/FALSE only when + * storing to an arg_x -- as per the rules of the ACPI spec. * * Assumes parameters are already validated. * @@ -400,7 +409,7 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc, target_type = acpi_ns_get_type(node); target_desc = acpi_ns_get_attached_object(node); - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Storing %p(%s) into node %p(%s)\n", + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Storing %p (%s) to node %p (%s)\n", source_desc, acpi_ut_get_object_type_name(source_desc), node, acpi_ut_get_type_name(target_type))); @@ -414,46 +423,31 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc, return_ACPI_STATUS(status); } - /* If no implicit conversion, drop into the default case below */ - - if ((!implicit_conversion) || - ((walk_state->opcode == AML_COPY_OP) && - (target_type != ACPI_TYPE_LOCAL_REGION_FIELD) && - (target_type != ACPI_TYPE_LOCAL_BANK_FIELD) && - (target_type != ACPI_TYPE_LOCAL_INDEX_FIELD))) { - /* - * Force execution of default (no implicit conversion). Note: - * copy_object does not perform an implicit conversion, as per the ACPI - * spec -- except in case of region/bank/index fields -- because these - * objects must retain their original type permanently. - */ - target_type = ACPI_TYPE_ANY; - } - /* Do the actual store operation */ switch (target_type) { - case ACPI_TYPE_BUFFER_FIELD: - case ACPI_TYPE_LOCAL_REGION_FIELD: - case ACPI_TYPE_LOCAL_BANK_FIELD: - case ACPI_TYPE_LOCAL_INDEX_FIELD: - - /* For fields, copy the source data to the target field. */ - - status = acpi_ex_write_data_to_field(source_desc, target_desc, - &walk_state->result_obj); - break; - case ACPI_TYPE_INTEGER: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: /* - * These target types are all of type Integer/String/Buffer, and - * therefore support implicit conversion before the store. - * - * Copy and/or convert the source object to a new target object + * The simple data types all support implicit source operand + * conversion before the store. */ + + if ((walk_state->opcode == AML_COPY_OP) || !implicit_conversion) { + /* + * However, copy_object and Stores to arg_x do not perform + * an implicit conversion, as per the ACPI specification. + * A direct store is performed instead. + */ + status = acpi_ex_store_direct_to_node(source_desc, node, + walk_state); + break; + } + + /* Store with implicit source operand conversion support */ + status = acpi_ex_store_object_to_object(source_desc, target_desc, &new_desc, walk_state); @@ -467,13 +461,12 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc, * the Name's type to that of the value being stored in it. * source_desc reference count is incremented by attach_object. * - * Note: This may change the type of the node if an explicit store - * has been performed such that the node/object type has been - * changed. + * Note: This may change the type of the node if an explicit + * store has been performed such that the node/object type + * has been changed. */ - status = - acpi_ns_attach_object(node, new_desc, - new_desc->common.type); + status = acpi_ns_attach_object(node, new_desc, + new_desc->common.type); ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Store %s into %s via Convert/Attach\n", @@ -484,38 +477,83 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc, } break; - default: - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Storing [%s] (%p) directly into node [%s] (%p)" - " with no implicit conversion\n", - acpi_ut_get_object_type_name(source_desc), - source_desc, - acpi_ut_get_object_type_name(target_desc), - node)); + case ACPI_TYPE_BUFFER_FIELD: + case ACPI_TYPE_LOCAL_REGION_FIELD: + case ACPI_TYPE_LOCAL_BANK_FIELD: + case ACPI_TYPE_LOCAL_INDEX_FIELD: + /* + * For all fields, always write the source data to the target + * field. Any required implicit source operand conversion is + * performed in the function below as necessary. Note, field + * objects must retain their original type permanently. + */ + status = acpi_ex_write_data_to_field(source_desc, target_desc, + &walk_state->result_obj); + break; + default: /* * No conversions for all other types. Directly store a copy of - * the source object. NOTE: This is a departure from the ACPI - * spec, which states "If conversion is impossible, abort the - * running control method". + * the source object. This is the ACPI spec-defined behavior for + * the copy_object operator. * - * This code implements "If conversion is impossible, treat the - * Store operation as a CopyObject". + * NOTE: For the Store operator, this is a departure from the + * ACPI spec, which states "If conversion is impossible, abort + * the running control method". Instead, this code implements + * "If conversion is impossible, treat the Store operation as + * a CopyObject". */ - status = - acpi_ut_copy_iobject_to_iobject(source_desc, &new_desc, - walk_state); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - status = - acpi_ns_attach_object(node, new_desc, - new_desc->common.type); - acpi_ut_remove_reference(new_desc); + status = acpi_ex_store_direct_to_node(source_desc, node, + walk_state); break; } return_ACPI_STATUS(status); } + +/******************************************************************************* + * + * FUNCTION: acpi_ex_store_direct_to_node + * + * PARAMETERS: source_desc - Value to be stored + * node - Named object to receive the value + * walk_state - Current walk state + * + * RETURN: Status + * + * DESCRIPTION: "Store" an object directly to a node. This involves a copy + * and an attach. + * + ******************************************************************************/ + +static acpi_status +acpi_ex_store_direct_to_node(union acpi_operand_object *source_desc, + struct acpi_namespace_node *node, + struct acpi_walk_state *walk_state) +{ + acpi_status status; + union acpi_operand_object *new_desc; + + ACPI_FUNCTION_TRACE(ex_store_direct_to_node); + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Storing [%s] (%p) directly into node [%s] (%p)" + " with no implicit conversion\n", + acpi_ut_get_object_type_name(source_desc), + source_desc, acpi_ut_get_type_name(node->type), + node)); + + /* Copy the source object to a new object */ + + status = + acpi_ut_copy_iobject_to_iobject(source_desc, &new_desc, walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Attach the new object to the node */ + + status = acpi_ns_attach_object(node, new_desc, new_desc->common.type); + acpi_ut_remove_reference(new_desc); + return_ACPI_STATUS(status); +} -- cgit v1.2.3 From 7471b5f424c444727014ec6a72b6008e62fafef4 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 9 Oct 2013 17:01:09 +0200 Subject: USB: mos7840: fix tiocmget error handling commit a91ccd26e75235d86248d018fe3779732bcafd8d upstream. Make sure to return errors from tiocmget rather than rely on uninitialised stack data. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mos7840.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 2c1749da1f7e..8b3d0abe7e14 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -1593,7 +1593,11 @@ static int mos7840_tiocmget(struct tty_struct *tty) return -ENODEV; status = mos7840_get_uart_reg(port, MODEM_STATUS_REGISTER, &msr); + if (status != 1) + return -EIO; status = mos7840_get_uart_reg(port, MODEM_CONTROL_REGISTER, &mcr); + if (status != 1) + return -EIO; result = ((mcr & MCR_DTR) ? TIOCM_DTR : 0) | ((mcr & MCR_RTS) ? TIOCM_RTS : 0) | ((mcr & MCR_LOOPBACK) ? TIOCM_LOOP : 0) -- cgit v1.2.3 From 4e467973ad083f10d5eee5c08429c63f2b5fd671 Mon Sep 17 00:00:00 2001 From: Olivier Sobrie Date: Sun, 27 Oct 2013 22:07:53 +0100 Subject: can: kvaser_usb: fix usb endpoints detection commit 896e23bd04ea50a146dffd342e2f96180f0812a5 upstream. Some devices, like the Kvaser Memorator Professional, have several bulk in endpoints. Only the first one found must be used by the driver. The same holds for the bulk out endpoint. The official Kvaser driver (leaf) was used as reference for this patch. Signed-off-by: Olivier Sobrie Signed-off-by: Marc Kleine-Budde Signed-off-by: Greg Kroah-Hartman --- drivers/net/can/usb/kvaser_usb.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/net/can/usb/kvaser_usb.c b/drivers/net/can/usb/kvaser_usb.c index 3b9546588240..4b2d5ed62b11 100644 --- a/drivers/net/can/usb/kvaser_usb.c +++ b/drivers/net/can/usb/kvaser_usb.c @@ -1544,9 +1544,9 @@ static int kvaser_usb_init_one(struct usb_interface *intf, return 0; } -static void kvaser_usb_get_endpoints(const struct usb_interface *intf, - struct usb_endpoint_descriptor **in, - struct usb_endpoint_descriptor **out) +static int kvaser_usb_get_endpoints(const struct usb_interface *intf, + struct usb_endpoint_descriptor **in, + struct usb_endpoint_descriptor **out) { const struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; @@ -1557,12 +1557,18 @@ static void kvaser_usb_get_endpoints(const struct usb_interface *intf, for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { endpoint = &iface_desc->endpoint[i].desc; - if (usb_endpoint_is_bulk_in(endpoint)) + if (!*in && usb_endpoint_is_bulk_in(endpoint)) *in = endpoint; - if (usb_endpoint_is_bulk_out(endpoint)) + if (!*out && usb_endpoint_is_bulk_out(endpoint)) *out = endpoint; + + /* use first bulk endpoint for in and out */ + if (*in && *out) + return 0; } + + return -ENODEV; } static int kvaser_usb_probe(struct usb_interface *intf, @@ -1576,8 +1582,8 @@ static int kvaser_usb_probe(struct usb_interface *intf, if (!dev) return -ENOMEM; - kvaser_usb_get_endpoints(intf, &dev->bulk_in, &dev->bulk_out); - if (!dev->bulk_in || !dev->bulk_out) { + err = kvaser_usb_get_endpoints(intf, &dev->bulk_in, &dev->bulk_out); + if (err) { dev_err(&intf->dev, "Cannot get usb endpoint(s)"); return err; } -- cgit v1.2.3 From d8a7dd7122d411662e7ccf9986070fbe2ac2aeb2 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Tue, 17 Sep 2013 08:33:11 -0400 Subject: crypto: ansi_cprng - Fix off by one error in non-block size request commit 714b33d15130cbb5ab426456d4e3de842d6c5b8a upstream. Stephan Mueller reported to me recently a error in random number generation in the ansi cprng. If several small requests are made that are less than the instances block size, the remainder for loop code doesn't increment rand_data_valid in the last iteration, meaning that the last bytes in the rand_data buffer gets reused on the subsequent smaller-than-a-block request for random data. The fix is pretty easy, just re-code the for loop to make sure that rand_data_valid gets incremented appropriately Signed-off-by: Neil Horman Reported-by: Stephan Mueller CC: Stephan Mueller CC: Petr Matousek CC: Herbert Xu CC: "David S. Miller" Signed-off-by: Herbert Xu Cc: Luis Henriques Signed-off-by: Greg Kroah-Hartman --- crypto/ansi_cprng.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crypto/ansi_cprng.c b/crypto/ansi_cprng.c index c0bb3778f1ae..666f1962a160 100644 --- a/crypto/ansi_cprng.c +++ b/crypto/ansi_cprng.c @@ -230,11 +230,11 @@ remainder: */ if (byte_count < DEFAULT_BLK_SZ) { empty_rbuf: - for (; ctx->rand_data_valid < DEFAULT_BLK_SZ; - ctx->rand_data_valid++) { + while (ctx->rand_data_valid < DEFAULT_BLK_SZ) { *ptr = ctx->rand_data[ctx->rand_data_valid]; ptr++; byte_count--; + ctx->rand_data_valid++; if (byte_count == 0) goto done; } -- cgit v1.2.3 From 4821fd9dea0feb827b9d0ecda3463227ada05d52 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Tue, 5 Nov 2013 19:36:27 +0800 Subject: crypto: s390 - Fix aes-cbc IV corruption commit f262f0f5cad0c9eca61d1d383e3b67b57dcbe5ea upstream. The cbc-aes-s390 algorithm incorrectly places the IV in the tfm data structure. As the tfm is shared between multiple threads, this introduces a possibility of data corruption. This patch fixes this by moving the parameter block containing the IV and key onto the stack (the block is 48 bytes long). The same bug exists elsewhere in the s390 crypto system and they will be fixed in subsequent patches. Signed-off-by: Herbert Xu Signed-off-by: Greg Kroah-Hartman --- arch/s390/crypto/aes_s390.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/arch/s390/crypto/aes_s390.c b/arch/s390/crypto/aes_s390.c index b4dbade8ca24..2e4b5be31a1b 100644 --- a/arch/s390/crypto/aes_s390.c +++ b/arch/s390/crypto/aes_s390.c @@ -35,7 +35,6 @@ static u8 *ctrblk; static char keylen_flag; struct s390_aes_ctx { - u8 iv[AES_BLOCK_SIZE]; u8 key[AES_MAX_KEY_SIZE]; long enc; long dec; @@ -441,30 +440,36 @@ static int cbc_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, return aes_set_key(tfm, in_key, key_len); } -static int cbc_aes_crypt(struct blkcipher_desc *desc, long func, void *param, +static int cbc_aes_crypt(struct blkcipher_desc *desc, long func, struct blkcipher_walk *walk) { + struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm); int ret = blkcipher_walk_virt(desc, walk); unsigned int nbytes = walk->nbytes; + struct { + u8 iv[AES_BLOCK_SIZE]; + u8 key[AES_MAX_KEY_SIZE]; + } param; if (!nbytes) goto out; - memcpy(param, walk->iv, AES_BLOCK_SIZE); + memcpy(param.iv, walk->iv, AES_BLOCK_SIZE); + memcpy(param.key, sctx->key, sctx->key_len); do { /* only use complete blocks */ unsigned int n = nbytes & ~(AES_BLOCK_SIZE - 1); u8 *out = walk->dst.virt.addr; u8 *in = walk->src.virt.addr; - ret = crypt_s390_kmc(func, param, out, in, n); + ret = crypt_s390_kmc(func, ¶m, out, in, n); if (ret < 0 || ret != n) return -EIO; nbytes &= AES_BLOCK_SIZE - 1; ret = blkcipher_walk_done(desc, walk, nbytes); } while ((nbytes = walk->nbytes)); - memcpy(walk->iv, param, AES_BLOCK_SIZE); + memcpy(walk->iv, param.iv, AES_BLOCK_SIZE); out: return ret; @@ -481,7 +486,7 @@ static int cbc_aes_encrypt(struct blkcipher_desc *desc, return fallback_blk_enc(desc, dst, src, nbytes); blkcipher_walk_init(&walk, dst, src, nbytes); - return cbc_aes_crypt(desc, sctx->enc, sctx->iv, &walk); + return cbc_aes_crypt(desc, sctx->enc, &walk); } static int cbc_aes_decrypt(struct blkcipher_desc *desc, @@ -495,7 +500,7 @@ static int cbc_aes_decrypt(struct blkcipher_desc *desc, return fallback_blk_dec(desc, dst, src, nbytes); blkcipher_walk_init(&walk, dst, src, nbytes); - return cbc_aes_crypt(desc, sctx->dec, sctx->iv, &walk); + return cbc_aes_crypt(desc, sctx->dec, &walk); } static struct crypto_alg cbc_aes_alg = { -- cgit v1.2.3 From ef1c63283fc95d0e60904937f5a428cc2c9236bd Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Mon, 28 Oct 2013 09:54:40 +0100 Subject: can: c_can: Fix RX message handling, handle lost message before EOB commit 5d0f801a2ccec3b1fdabc3392c8d99ed0413d216 upstream. If we handle end of block messages with higher priority than a lost message, we can run into an endless interrupt loop. This is reproducable with a am335x processor and "cansequence -r" at 1Mbit. As soon as we loose a packet we can't escape from an interrupt loop. This patch fixes the problem by handling lost packets before EOB packets. Signed-off-by: Markus Pargmann Signed-off-by: Marc Kleine-Budde Signed-off-by: Greg Kroah-Hartman --- drivers/net/can/c_can/c_can.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c index a668cd491cb3..e3fc07cf2f62 100644 --- a/drivers/net/can/c_can/c_can.c +++ b/drivers/net/can/c_can/c_can.c @@ -814,9 +814,6 @@ static int c_can_do_rx_poll(struct net_device *dev, int quota) msg_ctrl_save = priv->read_reg(priv, C_CAN_IFACE(MSGCTRL_REG, 0)); - if (msg_ctrl_save & IF_MCONT_EOB) - return num_rx_pkts; - if (msg_ctrl_save & IF_MCONT_MSGLST) { c_can_handle_lost_msg_obj(dev, 0, msg_obj); num_rx_pkts++; @@ -824,6 +821,9 @@ static int c_can_do_rx_poll(struct net_device *dev, int quota) continue; } + if (msg_ctrl_save & IF_MCONT_EOB) + return num_rx_pkts; + if (!(msg_ctrl_save & IF_MCONT_NEWDAT)) continue; -- cgit v1.2.3 From c6cac65e0d07f9a4c57b68702db945db6e0321f7 Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Thu, 21 Nov 2013 14:32:08 -0800 Subject: ipc,shm: correct error return value in shmctl (SHM_UNLOCK) commit 3a72660b07d86d60457ca32080b1ce8c2b628ee2 upstream. Commit 2caacaa82a51 ("ipc,shm: shorten critical region for shmctl") restructured the ipc shm to shorten critical region, but introduced a path where the return value could be -EPERM, even if the operation actually was performed. Before the commit, the err return value was reset by the return value from security_shm_shmctl() after the if (!ns_capable(...)) statement. Now, we still exit the if statement with err set to -EPERM, and in the case of SHM_UNLOCK, it is not reset at all, and used as the return value from shmctl. To fix this, we only set err when errors occur, leaving the fallthrough case alone. Signed-off-by: Jesper Nilsson Cc: Davidlohr Bueso Cc: Rik van Riel Cc: Michel Lespinasse Cc: Al Viro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- ipc/shm.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/ipc/shm.c b/ipc/shm.c index 7b87bea5245b..8ffae5807317 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -974,12 +974,15 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf) ipc_lock_object(&shp->shm_perm); if (!ns_capable(ns->user_ns, CAP_IPC_LOCK)) { kuid_t euid = current_euid(); - err = -EPERM; if (!uid_eq(euid, shp->shm_perm.uid) && - !uid_eq(euid, shp->shm_perm.cuid)) + !uid_eq(euid, shp->shm_perm.cuid)) { + err = -EPERM; goto out_unlock0; - if (cmd == SHM_LOCK && !rlimit(RLIMIT_MEMLOCK)) + } + if (cmd == SHM_LOCK && !rlimit(RLIMIT_MEMLOCK)) { + err = -EPERM; goto out_unlock0; + } } shm_file = shp->shm_file; -- cgit v1.2.3 From b444df2f5791fb1ddf7d6b771ee32e30cc29dad9 Mon Sep 17 00:00:00 2001 From: Greg Thelen Date: Thu, 21 Nov 2013 14:32:00 -0800 Subject: ipc,shm: fix shm_file deletion races commit a399b29dfbaaaf91162b2dc5a5875dd51bbfa2a1 upstream. When IPC_RMID races with other shm operations there's potential for use-after-free of the shm object's associated file (shm_file). Here's the race before this patch: TASK 1 TASK 2 ------ ------ shm_rmid() ipc_lock_object() shmctl() shp = shm_obtain_object_check() shm_destroy() shum_unlock() fput(shp->shm_file) ipc_lock_object() shmem_lock(shp->shm_file) The oops is caused because shm_destroy() calls fput() after dropping the ipc_lock. fput() clears the file's f_inode, f_path.dentry, and f_path.mnt, which causes various NULL pointer references in task 2. I reliably see the oops in task 2 if with shmlock, shmu This patch fixes the races by: 1) set shm_file=NULL in shm_destroy() while holding ipc_object_lock(). 2) modify at risk operations to check shm_file while holding ipc_object_lock(). Example workloads, which each trigger oops... Workload 1: while true; do id=$(shmget 1 4096) shm_rmid $id & shmlock $id & wait done The oops stack shows accessing NULL f_inode due to racing fput: _raw_spin_lock shmem_lock SyS_shmctl Workload 2: while true; do id=$(shmget 1 4096) shmat $id 4096 & shm_rmid $id & wait done The oops stack is similar to workload 1 due to NULL f_inode: touch_atime shmem_mmap shm_mmap mmap_region do_mmap_pgoff do_shmat SyS_shmat Workload 3: while true; do id=$(shmget 1 4096) shmlock $id shm_rmid $id & shmunlock $id & wait done The oops stack shows second fput tripping on an NULL f_inode. The first fput() completed via from shm_destroy(), but a racing thread did a get_file() and queued this fput(): locks_remove_flock __fput ____fput task_work_run do_notify_resume int_signal Fixes: c2c737a0461e ("ipc,shm: shorten critical region for shmat") Fixes: 2caacaa82a51 ("ipc,shm: shorten critical region for shmctl") Signed-off-by: Greg Thelen Cc: Davidlohr Bueso Cc: Rik van Riel Cc: Manfred Spraul Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- ipc/shm.c | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/ipc/shm.c b/ipc/shm.c index 8ffae5807317..6dc55af8a29b 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -208,15 +208,18 @@ static void shm_open(struct vm_area_struct *vma) */ static void shm_destroy(struct ipc_namespace *ns, struct shmid_kernel *shp) { + struct file *shm_file; + + shm_file = shp->shm_file; + shp->shm_file = NULL; ns->shm_tot -= (shp->shm_segsz + PAGE_SIZE - 1) >> PAGE_SHIFT; shm_rmid(ns, shp); shm_unlock(shp); - if (!is_file_hugepages(shp->shm_file)) - shmem_lock(shp->shm_file, 0, shp->mlock_user); + if (!is_file_hugepages(shm_file)) + shmem_lock(shm_file, 0, shp->mlock_user); else if (shp->mlock_user) - user_shm_unlock(file_inode(shp->shm_file)->i_size, - shp->mlock_user); - fput (shp->shm_file); + user_shm_unlock(file_inode(shm_file)->i_size, shp->mlock_user); + fput(shm_file); ipc_rcu_putref(shp, shm_rcu_free); } @@ -986,6 +989,13 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf) } shm_file = shp->shm_file; + + /* check if shm_destroy() is tearing down shp */ + if (shm_file == NULL) { + err = -EIDRM; + goto out_unlock0; + } + if (is_file_hugepages(shm_file)) goto out_unlock0; @@ -1104,6 +1114,14 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr, goto out_unlock; ipc_lock_object(&shp->shm_perm); + + /* check if shm_destroy() is tearing down shp */ + if (shp->shm_file == NULL) { + ipc_unlock_object(&shp->shm_perm); + err = -EIDRM; + goto out_unlock; + } + path = shp->shm_file->f_path; path_get(&path); shp->shm_nattch++; -- cgit v1.2.3 From fdfe8f670850dc576d108424ed47208a422e62d3 Mon Sep 17 00:00:00 2001 From: Emil Velikov Date: Sun, 28 Jul 2013 21:00:23 +0100 Subject: drm/nv50-/disp: remove dcb_outp_match call, and related variables commit 9a7046d55f319b2dde5d2536cc2adb01ebdbe09e upstream. Unused and irrelavant since the code move of DP training/linkcontrol interrupt Signed-off-by: Emil Velikov Signed-off-by: Ben Skeggs Cc: Ilia Mirkin Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c index ab1e918469a8..526b75242899 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c @@ -47,14 +47,8 @@ int nv50_sor_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size) { struct nv50_disp_priv *priv = (void *)object->engine; - struct nouveau_bios *bios = nouveau_bios(priv); - const u16 type = (mthd & NV50_DISP_SOR_MTHD_TYPE) >> 12; const u8 head = (mthd & NV50_DISP_SOR_MTHD_HEAD) >> 3; - const u8 link = (mthd & NV50_DISP_SOR_MTHD_LINK) >> 2; const u8 or = (mthd & NV50_DISP_SOR_MTHD_OR); - const u16 mask = (0x0100 << head) | (0x0040 << link) | (0x0001 << or); - struct dcb_output outp; - u8 ver, hdr; u32 data; int ret = -EINVAL; @@ -62,8 +56,6 @@ nv50_sor_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size) return -EINVAL; data = *(u32 *)args; - if (type && !dcb_outp_match(bios, type, mask, &ver, &hdr, &outp)) - return -ENODEV; switch (mthd & ~0x3f) { case NV50_DISP_SOR_PWR: -- cgit v1.2.3 From bcb97394c1d36ec62de59963f5e08cfff61b9c81 Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Sun, 28 Jul 2013 22:30:57 -0400 Subject: drm/nva3-/disp: fix hda eld writing, needs to be padded commit 02d69294a174d7cb6a76080b6d16971ca08728d4 upstream. Commits 0a9e2b959 (drm/nvd0/disp: move HDA codec setup to core) and a4feaf4ea (drm/nva3/disp: move hda codec handling to core) moved code around but neglected to fill data up to 0x60 as before. This caused /proc/asound/cardN/eld#3.0 to show eld_valid as 0. With this patch, that file is again populated with the correct data. See https://bugs.freedesktop.org/show_bug.cgi?id=67051 Reported-and-tested-by: Alex Signed-off-by: Ilia Mirkin Signed-off-by: Ben Skeggs Cc: Ilia Mirkin Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/nouveau/core/engine/disp/hdanva3.c | 2 ++ drivers/gpu/drm/nouveau/core/engine/disp/hdanvd0.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/hdanva3.c b/drivers/gpu/drm/nouveau/core/engine/disp/hdanva3.c index 373dbcc523b2..a19e7d79b847 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/hdanva3.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/hdanva3.c @@ -36,6 +36,8 @@ nva3_hda_eld(struct nv50_disp_priv *priv, int or, u8 *data, u32 size) if (data && data[0]) { for (i = 0; i < size; i++) nv_wr32(priv, 0x61c440 + soff, (i << 8) | data[i]); + for (; i < 0x60; i++) + nv_wr32(priv, 0x61c440 + soff, (i << 8)); nv_mask(priv, 0x61c448 + soff, 0x80000003, 0x80000003); } else if (data) { diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/hdanvd0.c b/drivers/gpu/drm/nouveau/core/engine/disp/hdanvd0.c index dc57e24fc1df..717639386ced 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/hdanvd0.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/hdanvd0.c @@ -41,6 +41,8 @@ nvd0_hda_eld(struct nv50_disp_priv *priv, int or, u8 *data, u32 size) if (data && data[0]) { for (i = 0; i < size; i++) nv_wr32(priv, 0x10ec00 + soff, (i << 8) | data[i]); + for (; i < 0x60; i++) + nv_wr32(priv, 0x10ec00 + soff, (i << 8)); nv_mask(priv, 0x10ec10 + soff, 0x80000003, 0x80000003); } else if (data) { -- cgit v1.2.3 From 5bad04d7bc7fe12a89b716f8b63d32b5735f6dd2 Mon Sep 17 00:00:00 2001 From: Andy Adamson Date: Wed, 14 Aug 2013 11:59:13 -0400 Subject: SUNRPC: don't map EKEYEXPIRED to EACCES in call_refreshresult commit f1ff0c27fd9987c59d707cd1a6b6c1fc3ae0a250 upstream. The NFS layer needs to know when a key has expired. This change also returns -EKEYEXPIRED to the application, and the informative "Key has expired" error message is displayed. The user then knows that credential renewal is required. Signed-off-by: Andy Adamson Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- net/sunrpc/clnt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 426f8fcc4c6c..5b1bf7b530f1 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -1407,9 +1407,9 @@ call_refreshresult(struct rpc_task *task) return; case -ETIMEDOUT: rpc_delay(task, 3*HZ); - case -EKEYEXPIRED: case -EAGAIN: status = -EACCES; + case -EKEYEXPIRED: if (!task->tk_cred_retry) break; task->tk_cred_retry--; -- cgit v1.2.3 From e895dad0a5b1db5475346d9c2ae4a92e6fefa58d Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 11 Sep 2013 12:43:13 +0200 Subject: sched, idle: Fix the idle polling state logic commit ea8117478918a4734586d35ff530721b682425be upstream. Mike reported that commit 7d1a9417 ("x86: Use generic idle loop") regressed several workloads and caused excessive reschedule interrupts. The patch in question failed to notice that the x86 code had an inverted sense of the polling state versus the new generic code (x86: default polling, generic: default !polling). Fix the two prominent x86 mwait based idle drivers and introduce a few new generic polling helpers (fixing the wrong smp_mb__after_clear_bit usage). Also switch the idle routines to using tif_need_resched() which is an immediate TIF_NEED_RESCHED test as opposed to need_resched which will end up being slightly different. Reported-by: Mike Galbraith Signed-off-by: Peter Zijlstra Cc: lenb@kernel.org Cc: tglx@linutronix.de Link: http://lkml.kernel.org/n/tip-nc03imb0etuefmzybzj7sprf@git.kernel.org Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/process.c | 6 ++-- drivers/acpi/processor_idle.c | 46 ++++++------------------- drivers/idle/intel_idle.c | 2 +- include/linux/sched.h | 78 +++++++++++++++++++++++++++++++++++++++---- include/linux/thread_info.h | 2 ++ kernel/cpu/idle.c | 9 +++-- 6 files changed, 91 insertions(+), 52 deletions(-) diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 81a5f5e8f142..59b90379cb6a 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -391,9 +391,9 @@ static void amd_e400_idle(void) * The switch back from broadcast mode needs to be * called with interrupts disabled. */ - local_irq_disable(); - clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu); - local_irq_enable(); + local_irq_disable(); + clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu); + local_irq_enable(); } else default_idle(); } diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index eb133c77aadb..4056d3175178 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -121,17 +121,10 @@ static struct dmi_system_id __cpuinitdata processor_power_dmi_table[] = { */ static void acpi_safe_halt(void) { - current_thread_info()->status &= ~TS_POLLING; - /* - * TS_POLLING-cleared state must be visible before we - * test NEED_RESCHED: - */ - smp_mb(); - if (!need_resched()) { + if (!tif_need_resched()) { safe_halt(); local_irq_disable(); } - current_thread_info()->status |= TS_POLLING; } #ifdef ARCH_APICTIMER_STOPS_ON_C3 @@ -739,6 +732,11 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev, if (unlikely(!pr)) return -EINVAL; + if (cx->entry_method == ACPI_CSTATE_FFH) { + if (current_set_polling_and_test()) + return -EINVAL; + } + lapic_timer_state_broadcast(pr, cx, 1); acpi_idle_do_entry(cx); @@ -792,18 +790,9 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, if (unlikely(!pr)) return -EINVAL; - if (cx->entry_method != ACPI_CSTATE_FFH) { - current_thread_info()->status &= ~TS_POLLING; - /* - * TS_POLLING-cleared state must be visible before we test - * NEED_RESCHED: - */ - smp_mb(); - - if (unlikely(need_resched())) { - current_thread_info()->status |= TS_POLLING; + if (cx->entry_method == ACPI_CSTATE_FFH) { + if (current_set_polling_and_test()) return -EINVAL; - } } /* @@ -821,9 +810,6 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, sched_clock_idle_wakeup_event(0); - if (cx->entry_method != ACPI_CSTATE_FFH) - current_thread_info()->status |= TS_POLLING; - lapic_timer_state_broadcast(pr, cx, 0); return index; } @@ -860,18 +846,9 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, } } - if (cx->entry_method != ACPI_CSTATE_FFH) { - current_thread_info()->status &= ~TS_POLLING; - /* - * TS_POLLING-cleared state must be visible before we test - * NEED_RESCHED: - */ - smp_mb(); - - if (unlikely(need_resched())) { - current_thread_info()->status |= TS_POLLING; + if (cx->entry_method == ACPI_CSTATE_FFH) { + if (current_set_polling_and_test()) return -EINVAL; - } } acpi_unlazy_tlb(smp_processor_id()); @@ -917,9 +894,6 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, sched_clock_idle_wakeup_event(0); - if (cx->entry_method != ACPI_CSTATE_FFH) - current_thread_info()->status |= TS_POLLING; - lapic_timer_state_broadcast(pr, cx, 0); return index; } diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index fa6964d8681a..f116d664b473 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -359,7 +359,7 @@ static int intel_idle(struct cpuidle_device *dev, if (!(lapic_timer_reliable_states & (1 << (cstate)))) clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu); - if (!need_resched()) { + if (!current_set_polling_and_test()) { __monitor((void *)¤t_thread_info()->flags, 0, 0); smp_mb(); diff --git a/include/linux/sched.h b/include/linux/sched.h index 178a8d909f14..7b64cd4e3e56 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -2469,34 +2469,98 @@ static inline int tsk_is_polling(struct task_struct *p) { return task_thread_info(p)->status & TS_POLLING; } -static inline void current_set_polling(void) +static inline void __current_set_polling(void) { current_thread_info()->status |= TS_POLLING; } -static inline void current_clr_polling(void) +static inline bool __must_check current_set_polling_and_test(void) +{ + __current_set_polling(); + + /* + * Polling state must be visible before we test NEED_RESCHED, + * paired by resched_task() + */ + smp_mb(); + + return unlikely(tif_need_resched()); +} + +static inline void __current_clr_polling(void) { current_thread_info()->status &= ~TS_POLLING; - smp_mb__after_clear_bit(); +} + +static inline bool __must_check current_clr_polling_and_test(void) +{ + __current_clr_polling(); + + /* + * Polling state must be visible before we test NEED_RESCHED, + * paired by resched_task() + */ + smp_mb(); + + return unlikely(tif_need_resched()); } #elif defined(TIF_POLLING_NRFLAG) static inline int tsk_is_polling(struct task_struct *p) { return test_tsk_thread_flag(p, TIF_POLLING_NRFLAG); } -static inline void current_set_polling(void) + +static inline void __current_set_polling(void) { set_thread_flag(TIF_POLLING_NRFLAG); } -static inline void current_clr_polling(void) +static inline bool __must_check current_set_polling_and_test(void) +{ + __current_set_polling(); + + /* + * Polling state must be visible before we test NEED_RESCHED, + * paired by resched_task() + * + * XXX: assumes set/clear bit are identical barrier wise. + */ + smp_mb__after_clear_bit(); + + return unlikely(tif_need_resched()); +} + +static inline void __current_clr_polling(void) { clear_thread_flag(TIF_POLLING_NRFLAG); } + +static inline bool __must_check current_clr_polling_and_test(void) +{ + __current_clr_polling(); + + /* + * Polling state must be visible before we test NEED_RESCHED, + * paired by resched_task() + */ + smp_mb__after_clear_bit(); + + return unlikely(tif_need_resched()); +} + #else static inline int tsk_is_polling(struct task_struct *p) { return 0; } -static inline void current_set_polling(void) { } -static inline void current_clr_polling(void) { } +static inline void __current_set_polling(void) { } +static inline void __current_clr_polling(void) { } + +static inline bool __must_check current_set_polling_and_test(void) +{ + return unlikely(tif_need_resched()); +} +static inline bool __must_check current_clr_polling_and_test(void) +{ + return unlikely(tif_need_resched()); +} #endif /* diff --git a/include/linux/thread_info.h b/include/linux/thread_info.h index e7e04736802f..4ae6f32c8033 100644 --- a/include/linux/thread_info.h +++ b/include/linux/thread_info.h @@ -107,6 +107,8 @@ static inline int test_ti_thread_flag(struct thread_info *ti, int flag) #define set_need_resched() set_thread_flag(TIF_NEED_RESCHED) #define clear_need_resched() clear_thread_flag(TIF_NEED_RESCHED) +#define tif_need_resched() test_thread_flag(TIF_NEED_RESCHED) + #if defined TIF_RESTORE_SIGMASK && !defined HAVE_SET_RESTORE_SIGMASK /* * An arch can define its own version of set_restore_sigmask() to get the diff --git a/kernel/cpu/idle.c b/kernel/cpu/idle.c index e695c0a0bcb5..c261409500e4 100644 --- a/kernel/cpu/idle.c +++ b/kernel/cpu/idle.c @@ -44,7 +44,7 @@ static inline int cpu_idle_poll(void) rcu_idle_enter(); trace_cpu_idle_rcuidle(0, smp_processor_id()); local_irq_enable(); - while (!need_resched()) + while (!tif_need_resched()) cpu_relax(); trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, smp_processor_id()); rcu_idle_exit(); @@ -92,8 +92,7 @@ static void cpu_idle_loop(void) if (cpu_idle_force_poll || tick_check_broadcast_expired()) { cpu_idle_poll(); } else { - current_clr_polling(); - if (!need_resched()) { + if (!current_clr_polling_and_test()) { stop_critical_timings(); rcu_idle_enter(); arch_cpu_idle(); @@ -103,7 +102,7 @@ static void cpu_idle_loop(void) } else { local_irq_enable(); } - current_set_polling(); + __current_set_polling(); } arch_cpu_idle_exit(); } @@ -129,7 +128,7 @@ void cpu_startup_entry(enum cpuhp_state state) */ boot_init_stack_canary(); #endif - current_set_polling(); + __current_set_polling(); arch_cpu_idle_prepare(); cpu_idle_loop(); } -- cgit v1.2.3 From b72a3a06c698143d5b315a2882c3ecb4c947ac5f Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 27 Aug 2013 09:54:40 -0600 Subject: PCI: Allow PCIe Capability link-related register access for switches commit d3694d4fa3f44f6a295f8ab064937c8a1549d174 upstream. Every PCIe device has a link, except Root Complex Integrated Endpoints and Root Complex Event Collectors. Previously we didn't give access to PCIe capability link-related registers for Upstream Ports, Downstream Ports, and Bridges, so attempts to read PCI_EXP_LNKCTL incorrectly returned zero. See PCIe spec r3.0, sec 7.8 and 1.3.2.3. Reference: http://lkml.kernel.org/r/979A8436335E3744ADCD3A9F2A2B68A52AD136BE@SJEXCHMB10.corp.ad.broadcom.com Reported-by: Yuval Mintz Signed-off-by: Bjorn Helgaas Reviewed-By: Jiang Liu Signed-off-by: Greg Kroah-Hartman --- drivers/pci/access.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/pci/access.c b/drivers/pci/access.c index 1cc23661f79b..e26c3bd9aca4 100644 --- a/drivers/pci/access.c +++ b/drivers/pci/access.c @@ -485,9 +485,13 @@ static inline bool pcie_cap_has_lnkctl(const struct pci_dev *dev) int type = pci_pcie_type(dev); return pcie_cap_version(dev) > 1 || - type == PCI_EXP_TYPE_ROOT_PORT || type == PCI_EXP_TYPE_ENDPOINT || - type == PCI_EXP_TYPE_LEG_END; + type == PCI_EXP_TYPE_LEG_END || + type == PCI_EXP_TYPE_ROOT_PORT || + type == PCI_EXP_TYPE_UPSTREAM || + type == PCI_EXP_TYPE_DOWNSTREAM || + type == PCI_EXP_TYPE_PCI_BRIDGE || + type == PCI_EXP_TYPE_PCIE_BRIDGE; } static inline bool pcie_cap_has_sltctl(const struct pci_dev *dev) -- cgit v1.2.3 From 6c944bc629b3080bb850e9a2d5797d5b602ce648 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 28 Aug 2013 11:33:53 -0600 Subject: PCI: Remove PCIe Capability version checks commit c8b303d0206b28c4ff3aecada47108d1655ae00f upstream. Previously we relied on the PCIe r3.0, sec 7.8, spec language that says "For Functions that do not implement the [Link, Slot, Root] registers, these spaces must be hardwired to 0b," which means that for v2 PCIe capabilities, we don't need to check the device type at all. But it's simpler if we don't need to check the capability version at all, and I think the spec is explicit enough about which registers are required for which types that we can remove the version checks. Signed-off-by: Bjorn Helgaas Reviewed-By: Jiang Liu Acked-by: Myron Stowe Signed-off-by: Greg Kroah-Hartman --- drivers/pci/access.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/pci/access.c b/drivers/pci/access.c index e26c3bd9aca4..9a46fa9135d9 100644 --- a/drivers/pci/access.c +++ b/drivers/pci/access.c @@ -484,8 +484,7 @@ static inline bool pcie_cap_has_lnkctl(const struct pci_dev *dev) { int type = pci_pcie_type(dev); - return pcie_cap_version(dev) > 1 || - type == PCI_EXP_TYPE_ENDPOINT || + return type == PCI_EXP_TYPE_ENDPOINT || type == PCI_EXP_TYPE_LEG_END || type == PCI_EXP_TYPE_ROOT_PORT || type == PCI_EXP_TYPE_UPSTREAM || @@ -498,8 +497,7 @@ static inline bool pcie_cap_has_sltctl(const struct pci_dev *dev) { int type = pci_pcie_type(dev); - return pcie_cap_version(dev) > 1 || - type == PCI_EXP_TYPE_ROOT_PORT || + return type == PCI_EXP_TYPE_ROOT_PORT || (type == PCI_EXP_TYPE_DOWNSTREAM && pcie_caps_reg(dev) & PCI_EXP_FLAGS_SLOT); } @@ -508,8 +506,7 @@ static inline bool pcie_cap_has_rtctl(const struct pci_dev *dev) { int type = pci_pcie_type(dev); - return pcie_cap_version(dev) > 1 || - type == PCI_EXP_TYPE_ROOT_PORT || + return type == PCI_EXP_TYPE_ROOT_PORT || type == PCI_EXP_TYPE_RC_EC; } -- cgit v1.2.3 From 1b81dc5b7eead5d1112c4042a41339493f71ddeb Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 28 Aug 2013 12:01:03 -0600 Subject: PCI: Support PCIe Capability Slot registers only for ports with slots commit 6d3a1741f1e648cfbd5a0cc94477a0d5004c6f5e upstream. Previously we allowed callers to access Slot Capabilities, Status, and Control for Root Ports even if the Root Port did not implement a slot. This seems dubious because the spec only requires these registers if a slot is implemented. It's true that even Root Ports without slots must have *space* for these slot registers, because the Root Capabilities, Status, and Control registers are after the slot registers in the capability. However, for a v1 PCIe Capability, the *semantics* of the slot registers are undefined unless a slot is implemented. Signed-off-by: Bjorn Helgaas Reviewed-By: Jiang Liu Acked-by: Myron Stowe Signed-off-by: Greg Kroah-Hartman --- drivers/pci/access.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/pci/access.c b/drivers/pci/access.c index 9a46fa9135d9..061da8c3ab4b 100644 --- a/drivers/pci/access.c +++ b/drivers/pci/access.c @@ -497,9 +497,9 @@ static inline bool pcie_cap_has_sltctl(const struct pci_dev *dev) { int type = pci_pcie_type(dev); - return type == PCI_EXP_TYPE_ROOT_PORT || - (type == PCI_EXP_TYPE_DOWNSTREAM && - pcie_caps_reg(dev) & PCI_EXP_FLAGS_SLOT); + return (type == PCI_EXP_TYPE_ROOT_PORT || + type == PCI_EXP_TYPE_DOWNSTREAM) && + pcie_caps_reg(dev) & PCI_EXP_FLAGS_SLOT; } static inline bool pcie_cap_has_rtctl(const struct pci_dev *dev) -- cgit v1.2.3 From 65b4037862eeec836fef612bbcd558ea10efe1a8 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Tue, 5 Nov 2013 12:51:11 -0500 Subject: perf/ftrace: Fix paranoid level for enabling function tracer commit 12ae030d54ef250706da5642fc7697cc60ad0df7 upstream. The current default perf paranoid level is "1" which has "perf_paranoid_kernel()" return false, and giving any operations that use it, access to normal users. Unfortunately, this includes function tracing and normal users should not be allowed to enable function tracing by default. The proper level is defined at "-1" (full perf access), which "perf_paranoid_tracepoint_raw()" will only give access to. Use that check instead for enabling function tracing. Reported-by: Dave Jones Reported-by: Vince Weaver Tested-by: Vince Weaver Cc: Peter Zijlstra Cc: Ingo Molnar Cc: Jiri Olsa Cc: Frederic Weisbecker CVE: CVE-2013-2930 Fixes: ced39002f5ea ("ftrace, perf: Add support to use function tracepoint in perf") Signed-off-by: Steven Rostedt Signed-off-by: Greg Kroah-Hartman --- kernel/trace/trace_event_perf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c index 84b1e045faba..8354dc81ae64 100644 --- a/kernel/trace/trace_event_perf.c +++ b/kernel/trace/trace_event_perf.c @@ -26,7 +26,7 @@ static int perf_trace_event_perm(struct ftrace_event_call *tp_event, { /* The ftrace function trace is allowed only for root. */ if (ftrace_event_is_function(tp_event) && - perf_paranoid_kernel() && !capable(CAP_SYS_ADMIN)) + perf_paranoid_tracepoint_raw() && !capable(CAP_SYS_ADMIN)) return -EPERM; /* No tracing, just counting, so no obvious leak */ -- cgit v1.2.3 From 968f56ccc37ae686e226fbd2cec9b826c4b6f7c4 Mon Sep 17 00:00:00 2001 From: Puneet Kumar Date: Fri, 15 Nov 2013 11:41:29 -0800 Subject: ACPI / EC: Ensure lock is acquired before accessing ec struct members commit 36b15875a7819a2ec4cb5748ff7096ad7bd86cbb upstream. A bug was introduced by commit b76b51ba0cef ('ACPI / EC: Add more debug info and trivial code cleanup') that erroneously caused the struct member to be accessed before acquiring the required lock. This change fixes it by ensuring the lock acquisition is done first. Found by Aaron Durbin Fixes: b76b51ba0cef ('ACPI / EC: Add more debug info and trivial code cleanup') References: http://crbug.com/319019 Signed-off-by: Puneet Kumar Reviewed-by: Aaron Durbin [olof: Commit message reworded a bit] Signed-off-by: Olof Johansson Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/ec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 45af90a1ec1b..1ad5a4f9e0c3 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -175,9 +175,10 @@ static void start_transaction(struct acpi_ec *ec) static void advance_transaction(struct acpi_ec *ec, u8 status) { unsigned long flags; - struct transaction *t = ec->curr; + struct transaction *t; spin_lock_irqsave(&ec->lock, flags); + t = ec->curr; if (!t) goto unlock; if (t->wlen > t->wi) { -- cgit v1.2.3 From 602b910bb0b18c5d7887df7a05e256fac780cf49 Mon Sep 17 00:00:00 2001 From: Aaron Lu Date: Wed, 6 Nov 2013 09:07:10 +0800 Subject: ACPI / video: Quirk initial backlight level 0 commit 2c62333a408f5badd2d2ffd7177f95deeccc5ca4 upstream. Some firmware doesn't initialize initial backlight level to a proper value and _BQC will return 0 on first time evaluation. We used to be able to detect such incorrect value with our code logic, as value 0 normally isn't a valid value in _BCL. But with the introduction of Win8, firmware begins to fill _BCL with values from 0 to 100, now 0 becomes a valid value but that value will make user's screen black. This patch test initial _BQC for value 0, if such a value is returned, do not use it. References: https://bugzilla.kernel.org/show_bug.cgi?id=64031 References: https://bugzilla.kernel.org/show_bug.cgi?id=61231 References: https://bugzilla.kernel.org/show_bug.cgi?id=63111 Reported-by: Qingshuai Tian Tested-by: Aaron Lu # on "Idealpad u330p" Reported-and-tested-by: # on "Acer Aspire V5-573G" Reported-and-tested-by: Kirill Tkhai # on "HP 250 G1" Signed-off-by: Aaron Lu Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 0e4b96b62c75..055dfdfd7348 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -846,7 +846,7 @@ acpi_video_init_brightness(struct acpi_video_device *device) for (i = 2; i < br->count; i++) if (level_old == br->levels[i]) break; - if (i == br->count) + if (i == br->count || !level) level = max_level; } -- cgit v1.2.3 From e02d0a0455b7c701586595975894539a18c9a2ba Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 7 Nov 2013 01:41:27 +0100 Subject: ACPI / hotplug: Fix handle_root_bridge_removal() commit 2441191a19039002b2c454a261fb45986df15184 upstream. It is required to do get_device() on the struct acpi_device in question before passing it to acpi_bus_hot_remove_device() through acpi_os_hotplug_execute(), because acpi_bus_hot_remove_device() calls acpi_scan_hot_remove() that does put_device() on that object. The ACPI PCI root removal routine, handle_root_bridge_removal(), doesn't do that, which may lead to premature freeing of the device object or to executing put_device() on an object that has been freed already. Fix this problem by making handle_root_bridge_removal() use get_device() as appropriate. Signed-off-by: Rafael J. Wysocki Acked-by: Toshi Kani Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/pci_root.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index e427dc516c76..e36842b9e1fa 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -614,9 +614,12 @@ static void handle_root_bridge_removal(struct acpi_device *device) ej_event->device = device; ej_event->event = ACPI_NOTIFY_EJECT_REQUEST; + get_device(&device->dev); status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, ej_event); - if (ACPI_FAILURE(status)) + if (ACPI_FAILURE(status)) { + put_device(&device->dev); kfree(ej_event); + } } static void _handle_hotplug_event_root(struct work_struct *work) -- cgit v1.2.3 From 55c00c5afd3e9adfb5f7ea556b652b3aab0f3871 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 7 Nov 2013 01:42:17 +0100 Subject: ACPI / hotplug: Do not execute "insert in progress" _OST commit 176a88d79d6b5aebabaff16734e8b3107efcaaad upstream. According to the ACPI spec (5.0, Section 6.3.5), the "Device insertion in progress (pending)" (0x80) _OST status code is reserved for the "Insertion Processing" (0x200) source event which is "a result of an OSPM action". Specifically, it is not a notification, so that status code should not be used during notification processing, which unfortunately is done by acpi_scan_bus_device_check(). For this reason, drop the ACPI_OST_SC_INSERT_IN_PROGRESS _OST status evaluation from there (it was a mistake to put it in there in the first place). Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/scan.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index af658b2ff279..362f0c2aa1ea 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -244,8 +244,6 @@ static void acpi_scan_bus_device_check(acpi_handle handle, u32 ost_source) goto out; } } - acpi_evaluate_hotplug_ost(handle, ost_source, - ACPI_OST_SC_INSERT_IN_PROGRESS, NULL); error = acpi_bus_scan(handle); if (error) { acpi_handle_warn(handle, "Namespace scan failure\n"); -- cgit v1.2.3 From 1f44b29361e380645b2fc43f760fc0c7032e5c05 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 14 Nov 2013 21:33:15 +0100 Subject: rt2x00: fix a crash bug in the HT descriptor handling fix commit b4089d6d8e71a7293e2192025dfa507a04f661c4 upstream. Commit "rt2x00: fix HT TX descriptor settings regression" assumes that the control parameter to rt2x00mac_tx is always non-NULL. There is an internal call in rt2x00lib_bc_buffer_iter where NULL is passed. Fix the resulting crash by adding an initialized dummy on-stack ieee80211_tx_control struct. Signed-off-by: Felix Fietkau Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/rt2x00/rt2x00dev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 90dc14336980..a2889d1cfe37 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -181,6 +181,7 @@ static void rt2x00lib_autowakeup(struct work_struct *work) static void rt2x00lib_bc_buffer_iter(void *data, u8 *mac, struct ieee80211_vif *vif) { + struct ieee80211_tx_control control = {}; struct rt2x00_dev *rt2x00dev = data; struct sk_buff *skb; @@ -195,7 +196,7 @@ static void rt2x00lib_bc_buffer_iter(void *data, u8 *mac, */ skb = ieee80211_get_buffered_bc(rt2x00dev->hw, vif); while (skb) { - rt2x00mac_tx(rt2x00dev->hw, NULL, skb); + rt2x00mac_tx(rt2x00dev->hw, &control, skb); skb = ieee80211_get_buffered_bc(rt2x00dev->hw, vif); } } -- cgit v1.2.3 From c3e4f5f80f95f69e98624e97eaf2b9c2a6238288 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Tue, 15 Oct 2013 14:31:12 +0200 Subject: rt2x00: check if device is still available on rt2x00mac_flush() commit 5671ab05cf2a579218985ef56595387932d78ee4 upstream. Fix random kernel panic with below messages when remove dongle. [ 2212.355447] BUG: unable to handle kernel NULL pointer dereference at 0000000000000250 [ 2212.355527] IP: [] rt2x00usb_kick_tx_entry+0x12/0x160 [rt2x00usb] [ 2212.355599] PGD 0 [ 2212.355626] Oops: 0000 [#1] SMP [ 2212.355664] Modules linked in: rt2800usb rt2x00usb rt2800lib crc_ccitt rt2x00lib mac80211 cfg80211 tun arc4 fuse rfcomm bnep snd_hda_codec_realtek snd_hda_intel snd_hda_codec btusb uvcvideo bluetooth snd_hwdep x86_pkg_temp_thermal snd_seq coretemp aesni_intel aes_x86_64 snd_seq_device glue_helper snd_pcm ablk_helper videobuf2_vmalloc sdhci_pci videobuf2_memops videobuf2_core sdhci videodev mmc_core serio_raw snd_page_alloc microcode i2c_i801 snd_timer hid_multitouch thinkpad_acpi lpc_ich mfd_core snd tpm_tis wmi tpm tpm_bios soundcore acpi_cpufreq i915 i2c_algo_bit drm_kms_helper drm i2c_core video [last unloaded: cfg80211] [ 2212.356224] CPU: 0 PID: 34 Comm: khubd Not tainted 3.12.0-rc3-wl+ #3 [ 2212.356268] Hardware name: LENOVO 3444CUU/3444CUU, BIOS G6ET93WW (2.53 ) 02/04/2013 [ 2212.356319] task: ffff880212f687c0 ti: ffff880212f66000 task.ti: ffff880212f66000 [ 2212.356392] RIP: 0010:[] [] rt2x00usb_kick_tx_entry+0x12/0x160 [rt2x00usb] [ 2212.356481] RSP: 0018:ffff880212f67750 EFLAGS: 00010202 [ 2212.356519] RAX: 000000000000000c RBX: 000000000000000c RCX: 0000000000000293 [ 2212.356568] RDX: ffff8801f4dc219a RSI: 0000000000000000 RDI: 0000000000000240 [ 2212.356617] RBP: ffff880212f67778 R08: ffffffffa02667e0 R09: 0000000000000002 [ 2212.356665] R10: 0001f95254ab4b40 R11: ffff880212f675be R12: ffff8801f4dc2150 [ 2212.356712] R13: 0000000000000000 R14: ffffffffa02667e0 R15: 000000000000000d [ 2212.356761] FS: 0000000000000000(0000) GS:ffff88021e200000(0000) knlGS:0000000000000000 [ 2212.356813] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 2212.356852] CR2: 0000000000000250 CR3: 0000000001a0c000 CR4: 00000000001407f0 [ 2212.356899] Stack: [ 2212.356917] 000000000000000c ffff8801f4dc2150 0000000000000000 ffffffffa02667e0 [ 2212.356980] 000000000000000d ffff880212f677b8 ffffffffa03a31ad ffff8801f4dc219a [ 2212.357038] ffff8801f4dc2150 0000000000000000 ffff8800b93217a0 ffff8801f49bc800 [ 2212.357099] Call Trace: [ 2212.357122] [] ? rt2x00usb_interrupt_txdone+0x90/0x90 [rt2x00usb] [ 2212.357174] [] rt2x00queue_for_each_entry+0xed/0x170 [rt2x00lib] [ 2212.357244] [] rt2x00usb_kick_queue+0x5c/0x60 [rt2x00usb] [ 2212.357314] [] rt2x00queue_flush_queue+0x62/0xa0 [rt2x00lib] [ 2212.357386] [] rt2x00mac_flush+0x30/0x70 [rt2x00lib] [ 2212.357470] [] ieee80211_flush_queues+0xbd/0x140 [mac80211] [ 2212.357555] [] ieee80211_set_disassoc+0x2d2/0x3d0 [mac80211] [ 2212.357645] [] ieee80211_mgd_deauth+0x1d3/0x240 [mac80211] [ 2212.357718] [] ? try_to_wake_up+0xec/0x290 [ 2212.357788] [] ieee80211_deauth+0x18/0x20 [mac80211] [ 2212.357872] [] cfg80211_mlme_deauth+0x9c/0x140 [cfg80211] [ 2212.357913] [] cfg80211_mlme_down+0x5c/0x60 [cfg80211] [ 2212.357962] [] cfg80211_disconnect+0x188/0x1a0 [cfg80211] [ 2212.358014] [] ? __cfg80211_stop_sched_scan+0x1c/0x130 [cfg80211] [ 2212.358067] [] cfg80211_leave+0xc4/0xe0 [cfg80211] [ 2212.358124] [] cfg80211_netdev_notifier_call+0x3ab/0x5e0 [cfg80211] [ 2212.358177] [] ? inetdev_event+0x38/0x510 [ 2212.358217] [] ? __wake_up+0x44/0x50 [ 2212.358254] [] notifier_call_chain+0x4c/0x70 [ 2212.358293] [] raw_notifier_call_chain+0x16/0x20 [ 2212.358361] [] call_netdevice_notifiers_info+0x35/0x60 [ 2212.358429] [] __dev_close_many+0x49/0xd0 [ 2212.358487] [] dev_close_many+0x88/0x100 [ 2212.358546] [] rollback_registered_many+0xb0/0x220 [ 2212.358612] [] unregister_netdevice_many+0x19/0x60 [ 2212.358694] [] ieee80211_remove_interfaces+0x112/0x190 [mac80211] [ 2212.358791] [] ieee80211_unregister_hw+0x4f/0x100 [mac80211] [ 2212.361994] [] rt2x00lib_remove_dev+0x161/0x1a0 [rt2x00lib] [ 2212.365240] [] rt2x00usb_disconnect+0x2e/0x70 [rt2x00usb] [ 2212.368470] [] usb_unbind_interface+0x64/0x1c0 [ 2212.371734] [] __device_release_driver+0x7f/0xf0 [ 2212.374999] [] device_release_driver+0x23/0x30 [ 2212.378131] [] bus_remove_device+0x108/0x180 [ 2212.381358] [] device_del+0x135/0x1d0 [ 2212.384454] [] usb_disable_device+0xb0/0x270 [ 2212.387451] [] usb_disconnect+0xad/0x1d0 [ 2212.390294] [] hub_thread+0x63d/0x1660 [ 2212.393034] [] ? wake_up_atomic_t+0x30/0x30 [ 2212.395728] [] ? hub_port_debounce+0x130/0x130 [ 2212.398412] [] kthread+0xc0/0xd0 [ 2212.401058] [] ? insert_kthread_work+0x40/0x40 [ 2212.403639] [] ret_from_fork+0x7c/0xb0 [ 2212.406193] [] ? insert_kthread_work+0x40/0x40 [ 2212.408732] Code: 24 58 08 00 00 bf 80 00 00 00 e8 3a c3 e0 e0 5b 41 5c 5d c3 0f 1f 44 00 00 0f 1f 44 00 00 55 48 89 e5 41 57 41 56 41 55 41 54 53 <48> 8b 47 10 48 89 fb 4c 8b 6f 28 4c 8b 20 49 8b 04 24 4c 8b 30 [ 2212.414671] RIP [] rt2x00usb_kick_tx_entry+0x12/0x160 [rt2x00usb] [ 2212.417646] RSP [ 2212.420547] CR2: 0000000000000250 [ 2212.441024] ---[ end trace 5442918f33832bce ]--- Signed-off-by: Stanislaw Gruszka Acked-by: Helmut Schaa Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/rt2x00/rt2x00mac.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index f883802f3505..ba1de865c892 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -754,6 +754,9 @@ void rt2x00mac_flush(struct ieee80211_hw *hw, u32 queues, bool drop) struct rt2x00_dev *rt2x00dev = hw->priv; struct data_queue *queue; + if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) + return; + tx_queue_for_each(rt2x00dev, queue) rt2x00queue_flush_queue(queue, drop); } -- cgit v1.2.3 From 0e11a27ff570fbebd37fcca1a329966194b46879 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Thu, 3 Oct 2013 20:00:40 +0200 Subject: rt2x00: rt2800lib: fix VGC adjustment for RT5592 commit 0beb1bbf19c72f17809e42b8f33522a55c2cc18c upstream. In commit 3d81535ea5940446510a8a5cee1c6ad23c90c753 (rt2800: 5592: add chip specific vgc calculations) the rt2800_link_tuner function has been modified to adjust VGC level for the RT5592 chipset. On the RT5592 chipset, the VGC level must be adjusted only if rssi is greater than -65. However the current code adjusts the VGC value by 0x10 regardless of the actual chipset if the rssi value is between -80 and -65. Fix the broken behaviour by reordering the if-else statements. Signed-off-by: Gabor Juhos Acked-by: Stanislaw Gruszka Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/rt2x00/rt2800lib.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index f281971919f5..12652d204f7e 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -3400,10 +3400,13 @@ void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual, vgc = rt2800_get_default_vgc(rt2x00dev); - if (rt2x00_rt(rt2x00dev, RT5592) && qual->rssi > -65) - vgc += 0x20; - else if (qual->rssi > -80) - vgc += 0x10; + if (rt2x00_rt(rt2x00dev, RT5592)) { + if (qual->rssi > -65) + vgc += 0x20; + } else { + if (qual->rssi > -80) + vgc += 0x10; + } rt2800_set_vgc(rt2x00dev, qual, vgc); } -- cgit v1.2.3 From ac600ac47b4b44af06c3518f6754f91bc4e89a47 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Thu, 31 Oct 2013 11:23:57 +0100 Subject: rt2x00: fix HT TX descriptor settings regression commit 3d8bfe141be8e5c21261fc63da8e7964d44f2645 upstream. Since: commit 36323f817af0376c78612cfdab714b0feb05fea5 Author: Thomas Huehn Date: Mon Jul 23 21:33:42 2012 +0200 mac80211: move TX station pointer and restructure TX we do not pass sta pointer to rt2x00queue_create_tx_descriptor_ht(), hence we do not correctly set station WCID and AMPDU density parameters. Signed-off-by: Stanislaw Gruszka Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/rt2x00/rt2x00lib.h | 2 +- drivers/net/wireless/rt2x00/rt2x00mac.c | 4 ++-- drivers/net/wireless/rt2x00/rt2x00queue.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index a0935987fa3a..7f40ab8e1bd8 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -146,7 +146,7 @@ void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int header_length); * @local: frame is not from mac80211 */ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb, - bool local); + struct ieee80211_sta *sta, bool local); /** * rt2x00queue_update_beacon - Send new beacon from mac80211 diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index ba1de865c892..f8cff1f0b6b7 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -90,7 +90,7 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev, frag_skb->data, data_length, tx_info, (struct ieee80211_rts *)(skb->data)); - retval = rt2x00queue_write_tx_frame(queue, skb, true); + retval = rt2x00queue_write_tx_frame(queue, skb, NULL, true); if (retval) { dev_kfree_skb_any(skb); rt2x00_warn(rt2x00dev, "Failed to send RTS/CTS frame\n"); @@ -151,7 +151,7 @@ void rt2x00mac_tx(struct ieee80211_hw *hw, goto exit_fail; } - if (unlikely(rt2x00queue_write_tx_frame(queue, skb, false))) + if (unlikely(rt2x00queue_write_tx_frame(queue, skb, control->sta, false))) goto exit_fail; /* diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index d955741e48ff..1f17f5b64625 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -635,7 +635,7 @@ static void rt2x00queue_bar_check(struct queue_entry *entry) } int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb, - bool local) + struct ieee80211_sta *sta, bool local) { struct ieee80211_tx_info *tx_info; struct queue_entry *entry; @@ -649,7 +649,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb, * after that we are free to use the skb->cb array * for our information. */ - rt2x00queue_create_tx_descriptor(queue->rt2x00dev, skb, &txdesc, NULL); + rt2x00queue_create_tx_descriptor(queue->rt2x00dev, skb, &txdesc, sta); /* * All information is retrieved from the skb->cb array, -- cgit v1.2.3 From 8bcee197d648d07ad81a9322ea93de85ab1719eb Mon Sep 17 00:00:00 2001 From: Mimi Zohar Date: Thu, 17 Oct 2013 07:34:02 -0400 Subject: Revert "ima: policy for RAMFS" commit 08de59eb144d7c41351a467442f898d720f0f15f upstream. This reverts commit 4c2c392763a682354fac65b6a569adec4e4b5387. Everything in the initramfs should be measured and appraised, but until the initramfs has extended attribute support, at least measured. Signed-off-by: Mimi Zohar Signed-off-by: Greg Kroah-Hartman --- security/integrity/ima/ima_policy.c | 1 - 1 file changed, 1 deletion(-) diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 399433ad614e..a9c3d3cd1990 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -73,7 +73,6 @@ static struct ima_rule_entry default_rules[] = { {.action = DONT_MEASURE,.fsmagic = SYSFS_MAGIC,.flags = IMA_FSMAGIC}, {.action = DONT_MEASURE,.fsmagic = DEBUGFS_MAGIC,.flags = IMA_FSMAGIC}, {.action = DONT_MEASURE,.fsmagic = TMPFS_MAGIC,.flags = IMA_FSMAGIC}, - {.action = DONT_MEASURE,.fsmagic = RAMFS_MAGIC,.flags = IMA_FSMAGIC}, {.action = DONT_MEASURE,.fsmagic = DEVPTS_SUPER_MAGIC,.flags = IMA_FSMAGIC}, {.action = DONT_MEASURE,.fsmagic = BINFMTFS_MAGIC,.flags = IMA_FSMAGIC}, {.action = DONT_MEASURE,.fsmagic = SECURITYFS_MAGIC,.flags = IMA_FSMAGIC}, -- cgit v1.2.3 From d389d610b143d487e50fe898e0ee9d329c279a1b Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 12 Nov 2013 15:11:17 -0800 Subject: exec/ptrace: fix get_dumpable() incorrect tests commit d049f74f2dbe71354d43d393ac3a188947811348 upstream. The get_dumpable() return value is not boolean. Most users of the function actually want to be testing for non-SUID_DUMP_USER(1) rather than SUID_DUMP_DISABLE(0). The SUID_DUMP_ROOT(2) is also considered a protected state. Almost all places did this correctly, excepting the two places fixed in this patch. Wrong logic: if (dumpable == SUID_DUMP_DISABLE) { /* be protective */ } or if (dumpable == 0) { /* be protective */ } or if (!dumpable) { /* be protective */ } Correct logic: if (dumpable != SUID_DUMP_USER) { /* be protective */ } or if (dumpable != 1) { /* be protective */ } Without this patch, if the system had set the sysctl fs/suid_dumpable=2, a user was able to ptrace attach to processes that had dropped privileges to that user. (This may have been partially mitigated if Yama was enabled.) The macros have been moved into the file that declares get/set_dumpable(), which means things like the ia64 code can see them too. CVE-2013-2929 Reported-by: Vasily Kulikov Signed-off-by: Kees Cook Cc: "Luck, Tony" Cc: Oleg Nesterov Cc: "Eric W. Biederman" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- arch/ia64/include/asm/processor.h | 2 +- fs/exec.c | 6 ++++++ include/linux/binfmts.h | 3 --- include/linux/sched.h | 4 ++++ kernel/ptrace.c | 3 ++- 5 files changed, 13 insertions(+), 5 deletions(-) diff --git a/arch/ia64/include/asm/processor.h b/arch/ia64/include/asm/processor.h index e0a899a1a8a6..5a84b3a50741 100644 --- a/arch/ia64/include/asm/processor.h +++ b/arch/ia64/include/asm/processor.h @@ -319,7 +319,7 @@ struct thread_struct { regs->loadrs = 0; \ regs->r8 = get_dumpable(current->mm); /* set "don't zap registers" flag */ \ regs->r12 = new_sp - 16; /* allocate 16 byte scratch area */ \ - if (unlikely(!get_dumpable(current->mm))) { \ + if (unlikely(get_dumpable(current->mm) != SUID_DUMP_USER)) { \ /* \ * Zap scratch regs to avoid leaking bits between processes with different \ * uid/privileges. \ diff --git a/fs/exec.c b/fs/exec.c index 1f446705636b..bb60cda5ee30 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1669,6 +1669,12 @@ int __get_dumpable(unsigned long mm_flags) return (ret > SUID_DUMP_USER) ? SUID_DUMP_ROOT : ret; } +/* + * This returns the actual value of the suid_dumpable flag. For things + * that are using this for checking for privilege transitions, it must + * test against SUID_DUMP_USER rather than treating it as a boolean + * value. + */ int get_dumpable(struct mm_struct *mm) { return __get_dumpable(mm->flags); diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h index 70cf138690e9..df97ca4aae52 100644 --- a/include/linux/binfmts.h +++ b/include/linux/binfmts.h @@ -99,9 +99,6 @@ extern void setup_new_exec(struct linux_binprm * bprm); extern void would_dump(struct linux_binprm *, struct file *); extern int suid_dumpable; -#define SUID_DUMP_DISABLE 0 /* No setuid dumping */ -#define SUID_DUMP_USER 1 /* Dump as user of process */ -#define SUID_DUMP_ROOT 2 /* Dump as root */ /* Stack area protections */ #define EXSTACK_DEFAULT 0 /* Whatever the arch defaults to */ diff --git a/include/linux/sched.h b/include/linux/sched.h index 7b64cd4e3e56..597c8ab005a0 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -332,6 +332,10 @@ static inline void arch_pick_mmap_layout(struct mm_struct *mm) {} extern void set_dumpable(struct mm_struct *mm, int value); extern int get_dumpable(struct mm_struct *mm); +#define SUID_DUMP_DISABLE 0 /* No setuid dumping */ +#define SUID_DUMP_USER 1 /* Dump as user of process */ +#define SUID_DUMP_ROOT 2 /* Dump as root */ + /* mm flags */ /* dumpable bits */ #define MMF_DUMPABLE 0 /* core dump is permitted */ diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 335a7ae697f5..afadcf7b4a22 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -257,7 +257,8 @@ ok: if (task->mm) dumpable = get_dumpable(task->mm); rcu_read_lock(); - if (!dumpable && !ptrace_has_cap(__task_cred(task)->user_ns, mode)) { + if (dumpable != SUID_DUMP_USER && + !ptrace_has_cap(__task_cred(task)->user_ns, mode)) { rcu_read_unlock(); return -EPERM; } -- cgit v1.2.3 From 75dab4710ba28b127cd5587b44ea5668fcde9a61 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 28 Oct 2013 11:24:23 +0100 Subject: ALSA: 6fire: Fix probe of multiple cards commit 9b389a8a022110b4bc055a19b888283544d9eba6 upstream. The probe code of snd-usb-6fire driver overrides the devices[] pointer wrongly without checking whether it's already occupied or not. This would screw up the device disconnection later. Spotted by coverity CID 141423. Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/usb/6fire/chip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/usb/6fire/chip.c b/sound/usb/6fire/chip.c index 4394ae796356..0716ba691398 100644 --- a/sound/usb/6fire/chip.c +++ b/sound/usb/6fire/chip.c @@ -101,7 +101,7 @@ static int usb6fire_chip_probe(struct usb_interface *intf, usb_set_intfdata(intf, chips[i]); mutex_unlock(®ister_mutex); return 0; - } else if (regidx < 0) + } else if (!devices[i] && regidx < 0) regidx = i; } if (regidx < 0) { -- cgit v1.2.3 From 16442d4ff3014c84008266feee1e36befd84c8c3 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Thu, 24 Oct 2013 16:37:31 +0530 Subject: ALSA: compress: fix drain calls blocking other compress functions commit 917f4b5cba78980a527098a910d94139d3e82c8d upstream. The drain and drain_notify callback were blocked by low level driver untill the draining was complete. Due to this being invoked with big fat mutex held, others ops like reading timestamp, calling pause, drop were blocked. So to fix this we add a new snd_compr_drain_notify() API. This would be required to be invoked by low level driver when drain or partial drain has been completed by the DSP. Thus we make the drain and partial_drain callback as non blocking and driver returns immediately after notifying DSP. The waiting is done while relasing the lock so that other ops can go ahead. Signed-off-by: Vinod Koul Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- include/sound/compress_driver.h | 12 ++++++++++++ sound/core/compress_offload.c | 41 ++++++++++++++++++++++++++++++++++++++--- 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/include/sound/compress_driver.h b/include/sound/compress_driver.h index 9031a26249b5..175ab3237b58 100644 --- a/include/sound/compress_driver.h +++ b/include/sound/compress_driver.h @@ -48,6 +48,8 @@ struct snd_compr_ops; * the ring buffer * @total_bytes_transferred: cumulative bytes transferred by offload DSP * @sleep: poll sleep + * @wait: drain wait queue + * @drain_wake: condition for drain wake */ struct snd_compr_runtime { snd_pcm_state_t state; @@ -59,6 +61,8 @@ struct snd_compr_runtime { u64 total_bytes_available; u64 total_bytes_transferred; wait_queue_head_t sleep; + wait_queue_head_t wait; + unsigned int drain_wake; void *private_data; }; @@ -171,4 +175,12 @@ static inline void snd_compr_fragment_elapsed(struct snd_compr_stream *stream) wake_up(&stream->runtime->sleep); } +static inline void snd_compr_drain_notify(struct snd_compr_stream *stream) +{ + snd_BUG_ON(!stream); + + stream->runtime->drain_wake = 1; + wake_up(&stream->runtime->wait); +} + #endif diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index 5863ba6dd12b..68d3ffcac78b 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c @@ -123,6 +123,7 @@ static int snd_compr_open(struct inode *inode, struct file *f) } runtime->state = SNDRV_PCM_STATE_OPEN; init_waitqueue_head(&runtime->sleep); + init_waitqueue_head(&runtime->wait); data->stream.runtime = runtime; f->private_data = (void *)data; mutex_lock(&compr->lock); @@ -670,12 +671,34 @@ static int snd_compr_stop(struct snd_compr_stream *stream) if (!retval) { stream->runtime->state = SNDRV_PCM_STATE_SETUP; wake_up(&stream->runtime->sleep); + snd_compr_drain_notify(stream); stream->runtime->total_bytes_available = 0; stream->runtime->total_bytes_transferred = 0; } return retval; } +static int snd_compress_wait_for_drain(struct snd_compr_stream *stream) +{ + /* + * We are called with lock held. So drop the lock while we wait for + * drain complete notfication from the driver + * + * It is expected that driver will notify the drain completion and then + * stream will be moved to SETUP state, even if draining resulted in an + * error. We can trigger next track after this. + */ + stream->runtime->state = SNDRV_PCM_STATE_DRAINING; + mutex_unlock(&stream->device->lock); + + wait_event(stream->runtime->wait, stream->runtime->drain_wake); + + wake_up(&stream->runtime->sleep); + mutex_lock(&stream->device->lock); + + return 0; +} + static int snd_compr_drain(struct snd_compr_stream *stream) { int retval; @@ -683,11 +706,17 @@ static int snd_compr_drain(struct snd_compr_stream *stream) if (stream->runtime->state == SNDRV_PCM_STATE_PREPARED || stream->runtime->state == SNDRV_PCM_STATE_SETUP) return -EPERM; + + stream->runtime->drain_wake = 0; retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_DRAIN); - if (!retval) { - stream->runtime->state = SNDRV_PCM_STATE_DRAINING; + if (retval) { + pr_err("SND_COMPR_TRIGGER_DRAIN failed %d\n", retval); wake_up(&stream->runtime->sleep); + return retval; } + + retval = snd_compress_wait_for_drain(stream); + stream->runtime->state = SNDRV_PCM_STATE_SETUP; return retval; } @@ -723,10 +752,16 @@ static int snd_compr_partial_drain(struct snd_compr_stream *stream) if (stream->next_track == false) return -EPERM; + stream->runtime->drain_wake = 0; retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_PARTIAL_DRAIN); + if (retval) { + pr_err("Partial drain returned failure\n"); + wake_up(&stream->runtime->sleep); + return retval; + } stream->next_track = false; - return retval; + return snd_compress_wait_for_drain(stream); } static long snd_compr_ioctl(struct file *f, unsigned int cmd, unsigned long arg) -- cgit v1.2.3 From 86e6de789cfeb2bb6c532281e16a478d797f3598 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Thu, 7 Nov 2013 10:08:22 +0100 Subject: ALSA: compress: fix drain calls blocking other compress functions (v6) commit f44f2a5417b2968a8724b352cc0b2545a6bcb1f4 upstream. The drain and drain_notify callback were blocked by low level driver until the draining was complete. Due to this being invoked with big fat mutex held, others ops like reading timestamp, calling pause, drop were blocked. So to fix this we add a new snd_compr_drain_notify() API. This would be required to be invoked by low level driver when drain or partial drain has been completed by the DSP. Thus we make the drain and partial_drain callback as non blocking and driver returns immediately after notifying DSP. The waiting is done while releasing the lock so that other ops can go ahead. [ The commit 917f4b5cba78 was wrongly applied from the preliminary patch. This commit corrects to the final version. Sorry for inconvenience! -- tiwai ] Signed-off-by: Vinod Koul Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- include/sound/compress_driver.h | 11 ++++------- sound/core/compress_offload.c | 31 +++++++++++++++++++------------ 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/include/sound/compress_driver.h b/include/sound/compress_driver.h index 175ab3237b58..ae6c3b8ed2f5 100644 --- a/include/sound/compress_driver.h +++ b/include/sound/compress_driver.h @@ -48,8 +48,6 @@ struct snd_compr_ops; * the ring buffer * @total_bytes_transferred: cumulative bytes transferred by offload DSP * @sleep: poll sleep - * @wait: drain wait queue - * @drain_wake: condition for drain wake */ struct snd_compr_runtime { snd_pcm_state_t state; @@ -61,8 +59,6 @@ struct snd_compr_runtime { u64 total_bytes_available; u64 total_bytes_transferred; wait_queue_head_t sleep; - wait_queue_head_t wait; - unsigned int drain_wake; void *private_data; }; @@ -177,10 +173,11 @@ static inline void snd_compr_fragment_elapsed(struct snd_compr_stream *stream) static inline void snd_compr_drain_notify(struct snd_compr_stream *stream) { - snd_BUG_ON(!stream); + if (snd_BUG_ON(!stream)) + return; - stream->runtime->drain_wake = 1; - wake_up(&stream->runtime->wait); + stream->runtime->state = SNDRV_PCM_STATE_SETUP; + wake_up(&stream->runtime->sleep); } #endif diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index 68d3ffcac78b..19799931c51d 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c @@ -123,7 +123,6 @@ static int snd_compr_open(struct inode *inode, struct file *f) } runtime->state = SNDRV_PCM_STATE_OPEN; init_waitqueue_head(&runtime->sleep); - init_waitqueue_head(&runtime->wait); data->stream.runtime = runtime; f->private_data = (void *)data; mutex_lock(&compr->lock); @@ -669,8 +668,6 @@ static int snd_compr_stop(struct snd_compr_stream *stream) return -EPERM; retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_STOP); if (!retval) { - stream->runtime->state = SNDRV_PCM_STATE_SETUP; - wake_up(&stream->runtime->sleep); snd_compr_drain_notify(stream); stream->runtime->total_bytes_available = 0; stream->runtime->total_bytes_transferred = 0; @@ -680,6 +677,8 @@ static int snd_compr_stop(struct snd_compr_stream *stream) static int snd_compress_wait_for_drain(struct snd_compr_stream *stream) { + int ret; + /* * We are called with lock held. So drop the lock while we wait for * drain complete notfication from the driver @@ -691,12 +690,24 @@ static int snd_compress_wait_for_drain(struct snd_compr_stream *stream) stream->runtime->state = SNDRV_PCM_STATE_DRAINING; mutex_unlock(&stream->device->lock); - wait_event(stream->runtime->wait, stream->runtime->drain_wake); + /* we wait for drain to complete here, drain can return when + * interruption occurred, wait returned error or success. + * For the first two cases we don't do anything different here and + * return after waking up + */ + + ret = wait_event_interruptible(stream->runtime->sleep, + (stream->runtime->state != SNDRV_PCM_STATE_DRAINING)); + if (ret == -ERESTARTSYS) + pr_debug("wait aborted by a signal"); + else if (ret) + pr_debug("wait for drain failed with %d\n", ret); + wake_up(&stream->runtime->sleep); mutex_lock(&stream->device->lock); - return 0; + return ret; } static int snd_compr_drain(struct snd_compr_stream *stream) @@ -707,17 +718,14 @@ static int snd_compr_drain(struct snd_compr_stream *stream) stream->runtime->state == SNDRV_PCM_STATE_SETUP) return -EPERM; - stream->runtime->drain_wake = 0; retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_DRAIN); if (retval) { - pr_err("SND_COMPR_TRIGGER_DRAIN failed %d\n", retval); + pr_debug("SND_COMPR_TRIGGER_DRAIN failed %d\n", retval); wake_up(&stream->runtime->sleep); return retval; } - retval = snd_compress_wait_for_drain(stream); - stream->runtime->state = SNDRV_PCM_STATE_SETUP; - return retval; + return snd_compress_wait_for_drain(stream); } static int snd_compr_next_track(struct snd_compr_stream *stream) @@ -752,10 +760,9 @@ static int snd_compr_partial_drain(struct snd_compr_stream *stream) if (stream->next_track == false) return -EPERM; - stream->runtime->drain_wake = 0; retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_PARTIAL_DRAIN); if (retval) { - pr_err("Partial drain returned failure\n"); + pr_debug("Partial drain returned failure\n"); wake_up(&stream->runtime->sleep); return retval; } -- cgit v1.2.3 From 737d967e6b6c5f812e0c141e8ecb1207e5fd8b38 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 12 Nov 2013 08:06:20 +0100 Subject: ALSA: msnd: Avoid duplicated driver name commit 092f9cd16aac7d054af1755c945f37c1b33399e6 upstream. msnd_pinnacle.c is used for both snd-msnd-pinnacle and snd-msnd-classic drivers, and both should have different driver names. Using the same driver name results in the sysfs warning for duplicated entries like kobject: 'msnd-pinnacle.7' (cec33408): kobject_release, parent (null) (delayed) kobject: 'msnd-pinnacle' (cecd4980): kobject_release, parent cf3ad9b0 (delayed) ------------[ cut here ]------------ WARNING: CPU: 0 PID: 1 at fs/sysfs/dir.c:486 sysfs_warn_dup+0x7d/0xa0() sysfs: cannot create duplicate filename '/bus/isa/drivers/msnd-pinnacle' ...... Reported-by: Fengguang Wu Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/isa/msnd/msnd_pinnacle.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/isa/msnd/msnd_pinnacle.c b/sound/isa/msnd/msnd_pinnacle.c index ddabb406b14c..3a7946ebbe23 100644 --- a/sound/isa/msnd/msnd_pinnacle.c +++ b/sound/isa/msnd/msnd_pinnacle.c @@ -73,9 +73,11 @@ #ifdef MSND_CLASSIC # include "msnd_classic.h" # define LOGNAME "msnd_classic" +# define DEV_NAME "msnd-classic" #else # include "msnd_pinnacle.h" # define LOGNAME "snd_msnd_pinnacle" +# define DEV_NAME "msnd-pinnacle" #endif static void set_default_audio_parameters(struct snd_msnd *chip) @@ -1068,8 +1070,6 @@ static int snd_msnd_isa_remove(struct device *pdev, unsigned int dev) return 0; } -#define DEV_NAME "msnd-pinnacle" - static struct isa_driver snd_msnd_driver = { .match = snd_msnd_isa_match, .probe = snd_msnd_isa_probe, -- cgit v1.2.3 From 51f7512087067c0ba31bd5ad4bad5258fbd9b44c Mon Sep 17 00:00:00 2001 From: Kailang Yang Date: Thu, 24 Oct 2013 11:35:18 +0200 Subject: ALSA: hda - Add support of ALC255 codecs commit 1d04c9de5c76df113e4af7120feb53c628b5efcc upstream. It's just another variant of ALC269 & co. Signed-off-by: Kailang Yang Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 4496e0ab693d..0f4bfe9f60d5 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -2531,6 +2531,7 @@ enum { ALC269_TYPE_ALC282, ALC269_TYPE_ALC284, ALC269_TYPE_ALC286, + ALC269_TYPE_ALC255, }; /* @@ -2555,6 +2556,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec) case ALC269_TYPE_ALC269VD: case ALC269_TYPE_ALC282: case ALC269_TYPE_ALC286: + case ALC269_TYPE_ALC255: ssids = alc269_ssids; break; default: @@ -3765,6 +3767,9 @@ static int patch_alc269(struct hda_codec *codec) case 0x10ec0286: spec->codec_variant = ALC269_TYPE_ALC286; break; + case 0x10ec0255: + spec->codec_variant = ALC269_TYPE_ALC255; + break; } /* automatic parse from the BIOS config */ @@ -4472,6 +4477,7 @@ static int patch_alc680(struct hda_codec *codec) static const struct hda_codec_preset snd_hda_preset_realtek[] = { { .id = 0x10ec0221, .name = "ALC221", .patch = patch_alc269 }, { .id = 0x10ec0233, .name = "ALC233", .patch = patch_alc269 }, + { .id = 0x10ec0255, .name = "ALC255", .patch = patch_alc269 }, { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 }, { .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 }, { .id = 0x10ec0267, .name = "ALC267", .patch = patch_alc268 }, -- cgit v1.2.3 From 0009160a1b27a03d11ba007c542474aaba0b5380 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 4 Nov 2013 18:21:08 +0100 Subject: ALSA: hda - Enable SPDIF for Acer TravelMate 6293 commit 24eff328f65c8ef352c90b6adb7c2f39eb94205d upstream. BIOS on Acer TravelMate 6293 doesn't set up the SPDIF output pin correctly as default, so enable it via a fixup entry. Reported-and-tested-by: Hagen Heiduck Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 0f4bfe9f60d5..ca945d63af50 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -2380,6 +2380,7 @@ static const struct hda_verb alc268_beep_init_verbs[] = { enum { ALC268_FIXUP_INV_DMIC, ALC268_FIXUP_HP_EAPD, + ALC268_FIXUP_SPDIF, }; static const struct hda_fixup alc268_fixups[] = { @@ -2394,6 +2395,13 @@ static const struct hda_fixup alc268_fixups[] = { {} } }, + [ALC268_FIXUP_SPDIF] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { + { 0x1e, 0x014b1180 }, /* enable SPDIF out */ + {} + } + }, }; static const struct hda_model_fixup alc268_fixup_models[] = { @@ -2403,6 +2411,7 @@ static const struct hda_model_fixup alc268_fixup_models[] = { }; static const struct snd_pci_quirk alc268_fixup_tbl[] = { + SND_PCI_QUIRK(0x1025, 0x0139, "Acer TravelMate 6293", ALC268_FIXUP_SPDIF), SND_PCI_QUIRK(0x1025, 0x015b, "Acer AOA 150 (ZG5)", ALC268_FIXUP_INV_DMIC), /* below is codec SSID since multiple Toshiba laptops have the * same PCI SSID 1179:ff00 -- cgit v1.2.3 From ca4c12c0cf1d0efb5e7ffecf31cb17f95e1e77df Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Wed, 6 Nov 2013 10:50:44 +0100 Subject: ALSA: hda - Make sure mute LEDs stay on during runtime suspend (Realtek) commit d5b6b65e75ce607c2734227524e11574317a1c1a upstream. Some HP machines with Realtek codecs have mute LEDs connected to VREF pins. However when these go into runtime suspend, the pin powers down and its pin control is disabled, thus disabling the LED too. This patch fixes that issue by making sure that the pin stays in D0 with correct pin control. BugLink: https://bugs.launchpad.net/bugs/1248465 Tested-by: Franz Hsieh Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index ca945d63af50..3f8f4e4e519f 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -2765,6 +2765,23 @@ static void alc269_fixup_mic_mute_hook(void *private_data, int enabled) snd_hda_set_pin_ctl_cache(codec, spec->mute_led_nid, pinval); } +/* Make sure the led works even in runtime suspend */ +static unsigned int led_power_filter(struct hda_codec *codec, + hda_nid_t nid, + unsigned int power_state) +{ + struct alc_spec *spec = codec->spec; + + if (power_state != AC_PWRST_D3 || nid != spec->mute_led_nid) + return power_state; + + /* Set pin ctl again, it might have just been set to 0 */ + snd_hda_set_pin_ctl(codec, nid, + snd_hda_codec_get_pin_target(codec, nid)); + + return AC_PWRST_D0; +} + static void alc269_fixup_hp_mute_led(struct hda_codec *codec, const struct hda_fixup *fix, int action) { @@ -2784,6 +2801,7 @@ static void alc269_fixup_hp_mute_led(struct hda_codec *codec, spec->mute_led_nid = pin - 0x0a + 0x18; spec->gen.vmaster_mute.hook = alc269_fixup_mic_mute_hook; spec->gen.vmaster_mute_enum = 1; + codec->power_filter = led_power_filter; snd_printd("Detected mute LED for %x:%d\n", spec->mute_led_nid, spec->mute_led_polarity); break; @@ -2799,6 +2817,7 @@ static void alc269_fixup_hp_mute_led_mic1(struct hda_codec *codec, spec->mute_led_nid = 0x18; spec->gen.vmaster_mute.hook = alc269_fixup_mic_mute_hook; spec->gen.vmaster_mute_enum = 1; + codec->power_filter = led_power_filter; } } @@ -2811,6 +2830,7 @@ static void alc269_fixup_hp_mute_led_mic2(struct hda_codec *codec, spec->mute_led_nid = 0x19; spec->gen.vmaster_mute.hook = alc269_fixup_mic_mute_hook; spec->gen.vmaster_mute_enum = 1; + codec->power_filter = led_power_filter; } } -- cgit v1.2.3 From dc788a78ccf8e4a4862e9dd7f1faa4150583a91b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 6 Nov 2013 18:47:42 +0100 Subject: ALSA: hda - Add support for CX20952 commit 8f42d7698751a45cd9f7134a5da49bc5b6206179 upstream. It's a superset of the existing CX2075x codecs, so we can reuse the existing parser code. Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_conexant.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index c96e1945059d..1868d3a6e310 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -3491,6 +3491,8 @@ static const struct hda_codec_preset snd_hda_preset_conexant[] = { .patch = patch_conexant_auto }, { .id = 0x14f15115, .name = "CX20757", .patch = patch_conexant_auto }, + { .id = 0x14f151d7, .name = "CX20952", + .patch = patch_conexant_auto }, {} /* terminator */ }; @@ -3517,6 +3519,7 @@ MODULE_ALIAS("snd-hda-codec-id:14f15111"); MODULE_ALIAS("snd-hda-codec-id:14f15113"); MODULE_ALIAS("snd-hda-codec-id:14f15114"); MODULE_ALIAS("snd-hda-codec-id:14f15115"); +MODULE_ALIAS("snd-hda-codec-id:14f151d7"); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Conexant HD-audio codec"); -- cgit v1.2.3 From 705f5ab4855df0dee9abd526b170cb43632add72 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 7 Nov 2013 07:29:30 +0100 Subject: ALSA: hda - Add pincfg fixup for ASUS W5A commit 487a588d09db0d6508261867df208d8bdc718251 upstream. BIOS on ASUS W5A laptop with ALC880 codec doesn't provide any pin configurations, so we have to set up all pins manually. Reported-and-tested-by: nb Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 3f8f4e4e519f..48aa3cd7d0b2 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -1037,6 +1037,7 @@ enum { ALC880_FIXUP_UNIWILL, ALC880_FIXUP_UNIWILL_DIG, ALC880_FIXUP_Z71V, + ALC880_FIXUP_ASUS_W5A, ALC880_FIXUP_3ST_BASE, ALC880_FIXUP_3ST, ALC880_FIXUP_3ST_DIG, @@ -1207,6 +1208,26 @@ static const struct hda_fixup alc880_fixups[] = { { } } }, + [ALC880_FIXUP_ASUS_W5A] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { + /* set up the whole pins as BIOS is utterly broken */ + { 0x14, 0x0121411f }, /* HP */ + { 0x15, 0x411111f0 }, /* N/A */ + { 0x16, 0x411111f0 }, /* N/A */ + { 0x17, 0x411111f0 }, /* N/A */ + { 0x18, 0x90a60160 }, /* mic */ + { 0x19, 0x411111f0 }, /* N/A */ + { 0x1a, 0x411111f0 }, /* N/A */ + { 0x1b, 0x411111f0 }, /* N/A */ + { 0x1c, 0x411111f0 }, /* N/A */ + { 0x1d, 0x411111f0 }, /* N/A */ + { 0x1e, 0xb743111e }, /* SPDIF out */ + { } + }, + .chained = true, + .chain_id = ALC880_FIXUP_GPIO1, + }, [ALC880_FIXUP_3ST_BASE] = { .type = HDA_FIXUP_PINS, .v.pins = (const struct hda_pintbl[]) { @@ -1328,6 +1349,7 @@ static const struct hda_fixup alc880_fixups[] = { static const struct snd_pci_quirk alc880_fixup_tbl[] = { SND_PCI_QUIRK(0x1019, 0x0f69, "Coeus G610P", ALC880_FIXUP_W810), + SND_PCI_QUIRK(0x1043, 0x10c3, "ASUS W5A", ALC880_FIXUP_ASUS_W5A), SND_PCI_QUIRK(0x1043, 0x1964, "ASUS Z71V", ALC880_FIXUP_Z71V), SND_PCI_QUIRK_VENDOR(0x1043, "ASUS", ALC880_FIXUP_GPIO1), SND_PCI_QUIRK(0x1558, 0x5401, "Clevo GPIO2", ALC880_FIXUP_GPIO2), -- cgit v1.2.3 From c6ebcc4a440d9d8243ce33ed6c95235125fe1a80 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Tue, 12 Nov 2013 11:10:57 +0100 Subject: ALSA: hda - Fix Line Out automute on Realtek multifunction jacks commit 5959a6bc1124211a359525d209005abc07b0197b upstream. In case there is both a multifunction headset jack and a Line Out jack, automuting was not working properly from the Line Out jack. This patch fixes that issue. BugLink: https://bugs.launchpad.net/bugs/1250377 Tested-by: Cyrus Lien Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 48aa3cd7d0b2..3a9bd60aa3e4 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -3093,8 +3093,10 @@ static void alc_update_headset_mode(struct hda_codec *codec) else new_headset_mode = ALC_HEADSET_MODE_HEADPHONE; - if (new_headset_mode == spec->current_headset_mode) + if (new_headset_mode == spec->current_headset_mode) { + snd_hda_gen_update_outputs(codec); return; + } switch (new_headset_mode) { case ALC_HEADSET_MODE_UNPLUGGED: -- cgit v1.2.3 From 320f9078dbc4f9f71c79084d77cfe4c03aaaf328 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 12 Nov 2013 11:36:00 +0100 Subject: ALSA: hda - Check keep_eapd_on before inv_eapd commit 468ac413045af1e0e4d1272291bed6878f248a69 upstream. We don't change the EAPD bit in set_pin_eapd() if keep_eapd_on flag is set by the codec driver and enable is false. But, we also apply the flipping of enable value according to inv_eapd flag in the same function, and this confused the former check, handled as if it's turned ON. The inverted EAPD check must be applied after keep_eapd_on check, instead. Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/hda_generic.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index d0cc796f778a..26ed56f00b7c 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c @@ -786,10 +786,10 @@ static void set_pin_eapd(struct hda_codec *codec, hda_nid_t pin, bool enable) if (spec->own_eapd_ctl || !(snd_hda_query_pin_caps(codec, pin) & AC_PINCAP_EAPD)) return; - if (codec->inv_eapd) - enable = !enable; if (spec->keep_eapd_on && !enable) return; + if (codec->inv_eapd) + enable = !enable; snd_hda_codec_update_cache(codec, pin, 0, AC_VERB_SET_EAPD_BTLENABLE, enable ? 0x02 : 0x00); -- cgit v1.2.3 From b5c32fe75ce821a7a0ae1dd3f89c97f50a8a0304 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 13 Nov 2013 09:39:08 +0100 Subject: ALSA: hda - Don't turn off EAPD for headphone on Lenovo N100 commit 7a3e6107f94344e65c35bfe62de6c096a7b48965 upstream. The only EAPD on AD1986A is on NID 0x1b where usually the speaker. But this doesn't control only the speaker amp but may influence on all outputs, e.g. Lenovo N100 laptop seems to have this issue. Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_analog.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index d97f0d61a15b..e17b55a95bc5 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -1197,8 +1197,12 @@ static int alloc_ad_spec(struct hda_codec *codec) static void ad_fixup_inv_jack_detect(struct hda_codec *codec, const struct hda_fixup *fix, int action) { - if (action == HDA_FIXUP_ACT_PRE_PROBE) + struct ad198x_spec *spec = codec->spec; + + if (action == HDA_FIXUP_ACT_PRE_PROBE) { codec->inv_jack_detect = 1; + spec->gen.keep_eapd_on = 1; + } } enum { -- cgit v1.2.3 From 7088cd2da7489d71a6b5d569899f8af3f85247c4 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 13 Nov 2013 16:58:10 +0100 Subject: ALSA: hda - Don't clear the power state at snd_hda_codec_reset() commit d183b4fc463489b6bbe05c99afa0257a6fe578eb upstream. snd_hda_codec_reset() is called either in resetting the whole setup at error paths or hwdep clear/reconfig sysfs triggers. But all of these don't assume that the power has to be off, rather they want to keep the power state unchanged (e.g. reconfig_codec() calls the power up/down by itself). Thus, unconditionally clearing the power state in snd_hda_codec_reset() leads to the inconsistency, confuses the further operation. This patch gets rid of the lines doing that bad thing. Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/hda_codec.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 31461ba32d3c..5b3d6614e66e 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -2517,9 +2517,6 @@ int snd_hda_codec_reset(struct hda_codec *codec) cancel_delayed_work_sync(&codec->jackpoll_work); #ifdef CONFIG_PM cancel_delayed_work_sync(&codec->power_work); - codec->power_on = 0; - codec->power_transition = 0; - codec->power_jiffies = jiffies; flush_workqueue(bus->workq); #endif snd_hda_ctls_clear(codec); -- cgit v1.2.3 From c3bd14e68a1d4eaabbac84a3a28288a3bf13f9f6 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 20 Nov 2013 12:15:07 +0100 Subject: ALSA: hda - Fix unbalanced runtime PM notification at resume commit 0fc28fc030a85aa3d6d14e9e9fca0c8237c9ffb5 upstream. When a codec is resumed, it keeps the power on while the resuming phase via hda_keep_power_on(), then turns down via snd_hda_power_down(). At that point, snd_hda_power_down() notifies the power down to the controller, and this may confuse the refcount if the codec was already powered up before the resume. In the end result, the controller goes to runtime suspend even before the codec is kicked off to the power save, and the communication stalls happens. The fix is to add the power-up notification together with hda_keep_power_on(), and clears the flag appropriately. Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/hda_codec.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 5b3d6614e66e..aeefec74a061 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -3924,6 +3924,10 @@ static void hda_call_codec_resume(struct hda_codec *codec) * in the resume / power-save sequence */ hda_keep_power_on(codec); + if (codec->pm_down_notified) { + codec->pm_down_notified = 0; + hda_call_pm_notify(codec->bus, true); + } hda_set_power_state(codec, AC_PWRST_D0); restore_shutup_pins(codec); hda_exec_init_verbs(codec); -- cgit v1.2.3 From a020c697a1bd12ed3c1ea1f9435955174da879b2 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 21 Nov 2013 09:12:52 +0100 Subject: ALSA: hda - Fix the headphone jack detection on Sony VAIO TX commit 0f5a5b8515472a0219768423226b58228001e3d5 upstream. BIOS sets MISC_NO_PRESENCE bit wrongly to the pin config on NID 0x0f. Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 3a9bd60aa3e4..6541f4081706 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -1643,6 +1643,7 @@ static const struct snd_pci_quirk alc260_fixup_tbl[] = { SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_FIXUP_GPIO1), SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", ALC260_FIXUP_HP_DC5750), SND_PCI_QUIRK(0x103c, 0x30ba, "HP Presario B1900", ALC260_FIXUP_HP_B1900), + SND_PCI_QUIRK(0x104d, 0x81e2, "Sony VAIO TX", ALC260_FIXUP_HP_PIN_0F), SND_PCI_QUIRK(0x10cf, 0x1326, "FSC LifeBook S7020", ALC260_FIXUP_FSC_S7020), SND_PCI_QUIRK(0x1509, 0x4540, "Favorit 100XS", ALC260_FIXUP_GPIO1), SND_PCI_QUIRK(0x152d, 0x0729, "Quanta KN1", ALC260_FIXUP_KN1), -- cgit v1.2.3 From 55b13703da85a79c38b3fe986f777838846d1623 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Thu, 21 Nov 2013 14:12:59 +0100 Subject: ALSA: hda - Add headset quirk for Dell Inspiron 3135 commit b8362e70cbbb397db50939bc4c7c78dc3246c3eb upstream. BugLink: https://bugs.launchpad.net/bugs/1253636 Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 6541f4081706..1b354572ead1 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -3601,6 +3601,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1028, 0x0608, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x0609, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x0613, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1028, 0x0614, "Dell Inspiron 3135", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x0616, "Dell Vostro 5470", ALC290_FIXUP_MONO_SPEAKERS), SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2), SND_PCI_QUIRK(0x103c, 0x18e6, "HP", ALC269_FIXUP_HP_GPIO_LED), -- cgit v1.2.3 From 5bc7e35d3470bf24c7640984bbfe20afd804afdb Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 22 Nov 2013 08:06:36 +0100 Subject: ALSA: hda - Provide missing pin configs for VAIO with ALC260 commit d08c5ef2a039393eaf2ab2152db5f07790fa0f40 upstream. Some models (or maybe depending on BIOS version) of Sony VAIO with ALC260 give no proper pin configurations as default, resulting in the non-working speaker, etc. Just provide the whole pin configurations via a fixup. Reported-by: Matthew Markus Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 1b354572ead1..8bce044583ed 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -1495,6 +1495,7 @@ enum { ALC260_FIXUP_KN1, ALC260_FIXUP_FSC_S7020, ALC260_FIXUP_FSC_S7020_JWSE, + ALC260_FIXUP_VAIO_PINS, }; static void alc260_gpio1_automute(struct hda_codec *codec) @@ -1635,6 +1636,24 @@ static const struct hda_fixup alc260_fixups[] = { .chained = true, .chain_id = ALC260_FIXUP_FSC_S7020, }, + [ALC260_FIXUP_VAIO_PINS] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { + /* Pin configs are missing completely on some VAIOs */ + { 0x0f, 0x01211020 }, + { 0x10, 0x0001003f }, + { 0x11, 0x411111f0 }, + { 0x12, 0x01a15930 }, + { 0x13, 0x411111f0 }, + { 0x14, 0x411111f0 }, + { 0x15, 0x411111f0 }, + { 0x16, 0x411111f0 }, + { 0x17, 0x411111f0 }, + { 0x18, 0x411111f0 }, + { 0x19, 0x411111f0 }, + { } + } + }, }; static const struct snd_pci_quirk alc260_fixup_tbl[] = { @@ -1643,6 +1662,7 @@ static const struct snd_pci_quirk alc260_fixup_tbl[] = { SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_FIXUP_GPIO1), SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", ALC260_FIXUP_HP_DC5750), SND_PCI_QUIRK(0x103c, 0x30ba, "HP Presario B1900", ALC260_FIXUP_HP_B1900), + SND_PCI_QUIRK(0x104d, 0x81bb, "Sony VAIO", ALC260_FIXUP_VAIO_PINS), SND_PCI_QUIRK(0x104d, 0x81e2, "Sony VAIO TX", ALC260_FIXUP_HP_PIN_0F), SND_PCI_QUIRK(0x10cf, 0x1326, "FSC LifeBook S7020", ALC260_FIXUP_FSC_S7020), SND_PCI_QUIRK(0x1509, 0x4540, "Favorit 100XS", ALC260_FIXUP_GPIO1), -- cgit v1.2.3 From 55fce163b8367ce78c163f0f63a8326ea266c09f Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 1 Oct 2013 14:24:58 -0400 Subject: NFSv4: Fix a use-after-free situation in _nfs4_proc_getlk() commit a6f951ddbdfb7bd87d31a44f61abe202ed6ce57f upstream. In nfs4_proc_getlk(), when some error causes a retry of the call to _nfs4_proc_getlk(), we can end up with Oopses of the form BUG: unable to handle kernel NULL pointer dereference at 0000000000000134 IP: [] _raw_spin_lock+0xe/0x30 Call Trace: [] _atomic_dec_and_lock+0x4d/0x70 [] nfs4_put_lock_state+0x32/0xb0 [nfsv4] [] nfs4_fl_release_lock+0x15/0x20 [nfsv4] [] _nfs4_proc_getlk.isra.40+0x146/0x170 [nfsv4] [] nfs4_proc_lock+0x399/0x5a0 [nfsv4] The problem is that we don't clear the request->fl_ops after the first try and so when we retry, nfs4_set_lock_state() exits early without setting the lock stateid. Regression introduced by commit 70cc6487a4e08b8698c0e2ec935fb48d10490162 (locks: make ->lock release private data before returning in GETLK case) Reported-by: Weston Andros Adamson Reported-by: Jorge Mora Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/nfs4proc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index d7ba5616989c..3bafe0859999 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -4572,6 +4572,7 @@ static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock status = 0; } request->fl_ops->fl_release_private(request); + request->fl_ops = NULL; out: return status; } -- cgit v1.2.3 From 84febe04c528ef627da6962169e7ae324a0a2b99 Mon Sep 17 00:00:00 2001 From: Weston Andros Adamson Date: Mon, 21 Oct 2013 13:10:10 -0400 Subject: NFSv4: fix NULL dereference in open recover commit f494a6071d31e3294a3b51ad7a3684f983953f9f upstream. _nfs4_opendata_reclaim_to_nfs4_state doesn't expect to see a cached open CLAIM_PREVIOUS, but this can happen. An example is when there are RDWR openers and RDONLY openers on a delegation stateid. The recovery path will first try an open CLAIM_PREVIOUS for the RDWR openers, this marks the delegation as not needing RECLAIM anymore, so the open CLAIM_PREVIOUS for the RDONLY openers will not actually send an rpc. The NULL dereference is due to _nfs4_opendata_reclaim_to_nfs4_state returning PTR_ERR(rpc_status) when !rpc_done. When the open is cached, rpc_done == 0 and rpc_status == 0, thus _nfs4_opendata_reclaim_to_nfs4_state returns NULL - this is unexpected by callers of nfs4_opendata_to_nfs4_state(). This can be reproduced easily by opening the same file two times on an NFSv4.0 mount with delegations enabled, once as RDWR and once as RDONLY then sleeping for a long time. While the files are held open, kick off state recovery and this NULL dereference will be hit every time. An example OOPS: [ 65.003602] BUG: unable to handle kernel NULL pointer dereference at 00000000 00000030 [ 65.005312] IP: [] __nfs4_close+0x1e/0x160 [nfsv4] [ 65.006820] PGD 7b0ea067 PUD 791ff067 PMD 0 [ 65.008075] Oops: 0000 [#1] SMP [ 65.008802] Modules linked in: rpcsec_gss_krb5 nfsv4 dns_resolver nfs fscache snd_ens1371 gameport nfsd snd_rawmidi snd_ac97_codec ac97_bus btusb snd_seq snd _seq_device snd_pcm ppdev bluetooth auth_rpcgss coretemp snd_page_alloc crc32_pc lmul crc32c_intel ghash_clmulni_intel microcode rfkill nfs_acl vmw_balloon serio _raw snd_timer lockd parport_pc e1000 snd soundcore parport i2c_piix4 shpchp vmw _vmci sunrpc ata_generic mperf pata_acpi mptspi vmwgfx ttm scsi_transport_spi dr m mptscsih mptbase i2c_core [ 65.018684] CPU: 0 PID: 473 Comm: 192.168.10.85-m Not tainted 3.11.2-201.fc19 .x86_64 #1 [ 65.020113] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 07/31/2013 [ 65.022012] task: ffff88003707e320 ti: ffff88007b906000 task.ti: ffff88007b906000 [ 65.023414] RIP: 0010:[] [] __nfs4_close+0x1e/0x160 [nfsv4] [ 65.025079] RSP: 0018:ffff88007b907d10 EFLAGS: 00010246 [ 65.026042] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000 [ 65.027321] RDX: 0000000000000050 RSI: 0000000000000001 RDI: 0000000000000000 [ 65.028691] RBP: ffff88007b907d38 R08: 0000000000016f60 R09: 0000000000000000 [ 65.029990] R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000001 [ 65.031295] R13: 0000000000000050 R14: 0000000000000000 R15: 0000000000000001 [ 65.032527] FS: 0000000000000000(0000) GS:ffff88007f600000(0000) knlGS:0000000000000000 [ 65.033981] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 65.035177] CR2: 0000000000000030 CR3: 000000007b27f000 CR4: 00000000000407f0 [ 65.036568] Stack: [ 65.037011] 0000000000000000 0000000000000001 ffff88007b907d90 ffff88007a880220 [ 65.038472] ffff88007b768de8 ffff88007b907d48 ffffffffa037e4a5 ffff88007b907d80 [ 65.039935] ffffffffa036a6c8 ffff880037020e40 ffff88007a880000 ffff880037020e40 [ 65.041468] Call Trace: [ 65.042050] [] nfs4_close_state+0x15/0x20 [nfsv4] [ 65.043209] [] nfs4_open_recover_helper+0x148/0x1f0 [nfsv4] [ 65.044529] [] nfs4_open_recover+0x116/0x150 [nfsv4] [ 65.045730] [] nfs4_open_reclaim+0xad/0x150 [nfsv4] [ 65.046905] [] nfs4_do_reclaim+0x149/0x5f0 [nfsv4] [ 65.048071] [] nfs4_run_state_manager+0x3bc/0x670 [nfsv4] [ 65.049436] [] ? nfs4_do_reclaim+0x5f0/0x5f0 [nfsv4] [ 65.050686] [] ? nfs4_do_reclaim+0x5f0/0x5f0 [nfsv4] [ 65.051943] [] kthread+0xc0/0xd0 [ 65.052831] [] ? insert_kthread_work+0x40/0x40 [ 65.054697] [] ret_from_fork+0x7c/0xb0 [ 65.056396] [] ? insert_kthread_work+0x40/0x40 [ 65.058208] Code: 5c 41 5d 5d c3 0f 1f 84 00 00 00 00 00 66 66 66 66 90 55 48 89 e5 41 57 41 89 f7 41 56 41 89 ce 41 55 41 89 d5 41 54 53 48 89 fb <4c> 8b 67 30 f0 41 ff 44 24 44 49 8d 7c 24 40 e8 0e 0a 2d e1 44 [ 65.065225] RIP [] __nfs4_close+0x1e/0x160 [nfsv4] [ 65.067175] RSP [ 65.068570] CR2: 0000000000000030 [ 65.070098] ---[ end trace 0d1fe4f5c7dd6f8b ]--- Signed-off-by: Weston Andros Adamson Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/nfs4proc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 3bafe0859999..6af08f36bd8a 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -1159,7 +1159,8 @@ _nfs4_opendata_reclaim_to_nfs4_state(struct nfs4_opendata *data) struct nfs4_state *state = data->state; int ret; - if (!data->rpc_done) { + /* allow cached opens (!rpc_done && !rpc_status) */ + if (!data->rpc_done && data->rpc_status) { ret = data->rpc_status; goto err; } -- cgit v1.2.3 From a5178adbeda8c532361fd22a6dff3bf699ab8b13 Mon Sep 17 00:00:00 2001 From: Weston Andros Adamson Date: Mon, 21 Oct 2013 13:10:11 -0400 Subject: NFSv4: don't fail on missing fattr in open recover commit a43ec98b72aae3e330f0673438f58316c3769b84 upstream. This is an unneeded check that could cause the client to fail to recover opens. Signed-off-by: Weston Andros Adamson Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/nfs4proc.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 6af08f36bd8a..2e230830ff2b 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -1165,12 +1165,6 @@ _nfs4_opendata_reclaim_to_nfs4_state(struct nfs4_opendata *data) goto err; } - ret = -ESTALE; - if (!(data->f_attr.valid & NFS_ATTR_FATTR_TYPE) || - !(data->f_attr.valid & NFS_ATTR_FATTR_FILEID) || - !(data->f_attr.valid & NFS_ATTR_FATTR_CHANGE)) - goto err; - ret = -ENOMEM; state = nfs4_get_open_state(inode, data->owner); if (state == NULL) -- cgit v1.2.3 From 231817ee68a9640d91ef34ce12c4d67b38f17ed8 Mon Sep 17 00:00:00 2001 From: Weston Andros Adamson Date: Mon, 21 Oct 2013 13:10:13 -0400 Subject: NFSv4: don't reprocess cached open CLAIM_PREVIOUS commit d2bfda2e7aa036f90ccea610a657064b1e267913 upstream. Cached opens have already been handled by _nfs4_opendata_reclaim_to_nfs4_state and can safely skip being reprocessed, but must still call update_open_stateid to make sure that all active fmodes are recovered. Signed-off-by: Weston Andros Adamson Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/nfs4proc.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 2e230830ff2b..d097233cd33b 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -1159,10 +1159,13 @@ _nfs4_opendata_reclaim_to_nfs4_state(struct nfs4_opendata *data) struct nfs4_state *state = data->state; int ret; - /* allow cached opens (!rpc_done && !rpc_status) */ - if (!data->rpc_done && data->rpc_status) { - ret = data->rpc_status; - goto err; + if (!data->rpc_done) { + if (data->rpc_status) { + ret = data->rpc_status; + goto err; + } + /* cached opens have already been processed */ + goto update; } ret = -ENOMEM; @@ -1176,6 +1179,7 @@ _nfs4_opendata_reclaim_to_nfs4_state(struct nfs4_opendata *data) if (data->o_res.delegation_type != 0) nfs4_opendata_check_deleg(data, state); +update: update_open_stateid(state, &data->o_res.stateid, NULL, data->o_arg.fmode); -- cgit v1.2.3 From 1311157d8407d16b8543c2286f0e95251ca04fe8 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Mon, 28 Oct 2013 14:57:12 -0400 Subject: NFSv4: Fix state reference counting in _nfs4_opendata_reclaim_to_nfs4_state commit d49f042aeec99c5f87160bb52dd52088b1051311 upstream. Currently, if the call to nfs_refresh_inode fails, then we end up leaking a reference count, due to the call to nfs4_get_open_state. While we're at it, replace nfs4_get_open_state with a simple call to atomic_inc(); there is no need to do a full lookup of the struct nfs_state since it is passed as an argument in the struct nfs4_opendata, and is already assigned to the variable 'state'. Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/nfs4proc.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index d097233cd33b..e78b8c2656ee 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -1168,11 +1168,6 @@ _nfs4_opendata_reclaim_to_nfs4_state(struct nfs4_opendata *data) goto update; } - ret = -ENOMEM; - state = nfs4_get_open_state(inode, data->owner); - if (state == NULL) - goto err; - ret = nfs_refresh_inode(inode, &data->f_attr); if (ret) goto err; @@ -1182,6 +1177,7 @@ _nfs4_opendata_reclaim_to_nfs4_state(struct nfs4_opendata *data) update: update_open_stateid(state, &data->o_res.stateid, NULL, data->o_arg.fmode); + atomic_inc(&state->count); return state; err: -- cgit v1.2.3 From 8b7330f9057949e8c5df82df8a76068d0129e778 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Fri, 13 Sep 2013 11:08:45 -0400 Subject: nfsd: return better errors to exportfs commit 427d6c6646d868fbd3094e7e2e1644d480cd9204 upstream. Someone noticed exportfs happily accepted exports that would later be rejected when mountd tried to give them to the kernel. Fix this. This is a regression from 4c1e1b34d5c800ad3ac9a7e2805b0bea70ad2278 "nfsd: Store ex_anon_uid and ex_anon_gid as kuids and kgids". Cc: "Eric W. Biederman" Reported-by: Yin.JianHong Signed-off-by: J. Bruce Fields Signed-off-by: Greg Kroah-Hartman --- fs/nfsd/export.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index 5f38ea36e266..af51cf9bf2e3 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c @@ -536,16 +536,12 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) if (err) goto out3; exp.ex_anon_uid= make_kuid(&init_user_ns, an_int); - if (!uid_valid(exp.ex_anon_uid)) - goto out3; /* anon gid */ err = get_int(&mesg, &an_int); if (err) goto out3; exp.ex_anon_gid= make_kgid(&init_user_ns, an_int); - if (!gid_valid(exp.ex_anon_gid)) - goto out3; /* fsid */ err = get_int(&mesg, &an_int); @@ -583,6 +579,17 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) exp.ex_uuid); if (err) goto out4; + /* + * For some reason exportfs has been passing down an + * invalid (-1) uid & gid on the "dummy" export which it + * uses to test export support. To make sure exportfs + * sees errors from check_export we therefore need to + * delay these checks till after check_export: + */ + if (!uid_valid(exp.ex_anon_uid)) + goto out4; + if (!gid_valid(exp.ex_anon_gid)) + goto out4; } expp = svc_export_lookup(&exp); -- cgit v1.2.3 From b26be14b8e496c6fa14b53ba3390b56a5988df8a Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 18 Nov 2013 05:07:30 -0800 Subject: nfsd: split up nfsd_setattr commit 818e5a22e907fbae75e9c1fd78233baec9fa64b6 upstream. Split out two helpers to make the code more readable and easier to verify for correctness. Signed-off-by: Christoph Hellwig Signed-off-by: J. Bruce Fields Signed-off-by: Greg Kroah-Hartman --- fs/nfsd/vfs.c | 144 ++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 84 insertions(+), 60 deletions(-) diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index baf149a85263..56b71a9e6271 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -297,41 +297,12 @@ commit_metadata(struct svc_fh *fhp) } /* - * Set various file attributes. - * N.B. After this call fhp needs an fh_put + * Go over the attributes and take care of the small differences between + * NFS semantics and what Linux expects. */ -__be32 -nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, - int check_guard, time_t guardtime) +static void +nfsd_sanitize_attrs(struct inode *inode, struct iattr *iap) { - struct dentry *dentry; - struct inode *inode; - int accmode = NFSD_MAY_SATTR; - umode_t ftype = 0; - __be32 err; - int host_err; - int size_change = 0; - - if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME | ATTR_SIZE)) - accmode |= NFSD_MAY_WRITE|NFSD_MAY_OWNER_OVERRIDE; - if (iap->ia_valid & ATTR_SIZE) - ftype = S_IFREG; - - /* Get inode */ - err = fh_verify(rqstp, fhp, ftype, accmode); - if (err) - goto out; - - dentry = fhp->fh_dentry; - inode = dentry->d_inode; - - /* Ignore any mode updates on symlinks */ - if (S_ISLNK(inode->i_mode)) - iap->ia_valid &= ~ATTR_MODE; - - if (!iap->ia_valid) - goto out; - /* * NFSv2 does not differentiate between "set-[ac]time-to-now" * which only requires access, and "set-[ac]time-to-X" which @@ -341,8 +312,7 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, * convert to "set to now" instead of "set to explicit time" * * We only call inode_change_ok as the last test as technically - * it is not an interface that we should be using. It is only - * valid if the filesystem does not define it's own i_op->setattr. + * it is not an interface that we should be using. */ #define BOTH_TIME_SET (ATTR_ATIME_SET | ATTR_MTIME_SET) #define MAX_TOUCH_TIME_ERROR (30*60) @@ -368,30 +338,6 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, iap->ia_valid &= ~BOTH_TIME_SET; } } - - /* - * The size case is special. - * It changes the file as well as the attributes. - */ - if (iap->ia_valid & ATTR_SIZE) { - if (iap->ia_size < inode->i_size) { - err = nfsd_permission(rqstp, fhp->fh_export, dentry, - NFSD_MAY_TRUNC|NFSD_MAY_OWNER_OVERRIDE); - if (err) - goto out; - } - - host_err = get_write_access(inode); - if (host_err) - goto out_nfserr; - - size_change = 1; - host_err = locks_verify_truncate(inode, NULL, iap->ia_size); - if (host_err) { - put_write_access(inode); - goto out_nfserr; - } - } /* sanitize the mode change */ if (iap->ia_valid & ATTR_MODE) { @@ -414,8 +360,86 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, iap->ia_valid |= (ATTR_KILL_SUID | ATTR_KILL_SGID); } } +} - /* Change the attributes. */ +static __be32 +nfsd_get_write_access(struct svc_rqst *rqstp, struct svc_fh *fhp, + struct iattr *iap) +{ + struct inode *inode = fhp->fh_dentry->d_inode; + int host_err; + + if (iap->ia_size < inode->i_size) { + __be32 err; + + err = nfsd_permission(rqstp, fhp->fh_export, fhp->fh_dentry, + NFSD_MAY_TRUNC | NFSD_MAY_OWNER_OVERRIDE); + if (err) + return err; + } + + host_err = get_write_access(inode); + if (host_err) + goto out_nfserrno; + + host_err = locks_verify_truncate(inode, NULL, iap->ia_size); + if (host_err) + goto out_put_write_access; + return 0; + +out_put_write_access: + put_write_access(inode); +out_nfserrno: + return nfserrno(host_err); +} + +/* + * Set various file attributes. After this call fhp needs an fh_put. + */ +__be32 +nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, + int check_guard, time_t guardtime) +{ + struct dentry *dentry; + struct inode *inode; + int accmode = NFSD_MAY_SATTR; + umode_t ftype = 0; + __be32 err; + int host_err; + int size_change = 0; + + if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME | ATTR_SIZE)) + accmode |= NFSD_MAY_WRITE|NFSD_MAY_OWNER_OVERRIDE; + if (iap->ia_valid & ATTR_SIZE) + ftype = S_IFREG; + + /* Get inode */ + err = fh_verify(rqstp, fhp, ftype, accmode); + if (err) + goto out; + + dentry = fhp->fh_dentry; + inode = dentry->d_inode; + + /* Ignore any mode updates on symlinks */ + if (S_ISLNK(inode->i_mode)) + iap->ia_valid &= ~ATTR_MODE; + + if (!iap->ia_valid) + goto out; + + nfsd_sanitize_attrs(inode, iap); + + /* + * The size case is special, it changes the file in addition to the + * attributes. + */ + if (iap->ia_valid & ATTR_SIZE) { + err = nfsd_get_write_access(rqstp, fhp, iap); + if (err) + goto out; + size_change = 1; + } iap->ia_valid |= ATTR_CTIME; -- cgit v1.2.3 From e7c1ad19d74ccb254332c7b7d667998f1c26b64b Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 18 Nov 2013 05:07:47 -0800 Subject: nfsd: make sure to balance get/put_write_access commit 987da4791052fa298b7cfcde4dea9f6f2bbc786b upstream. Use a straight goto error label style in nfsd_setattr to make sure we always do the put_write_access call after we got it earlier. Note that the we have been failing to do that in the case nfsd_break_lease() returns an error, a bug introduced into 2.6.38 with 6a76bebefe15d9a08864f824d7f8d5beaf37c997 "nfsd4: break lease on nfsd setattr". Signed-off-by: Christoph Hellwig Signed-off-by: J. Bruce Fields Signed-off-by: Greg Kroah-Hartman --- fs/nfsd/vfs.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 56b71a9e6271..62fd6616801d 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -443,27 +443,28 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, iap->ia_valid |= ATTR_CTIME; - err = nfserr_notsync; - if (!check_guard || guardtime == inode->i_ctime.tv_sec) { - host_err = nfsd_break_lease(inode); - if (host_err) - goto out_nfserr; - fh_lock(fhp); - - host_err = notify_change(dentry, iap); - err = nfserrno(host_err); - fh_unlock(fhp); + if (check_guard && guardtime != inode->i_ctime.tv_sec) { + err = nfserr_notsync; + goto out_put_write_access; } + + host_err = nfsd_break_lease(inode); + if (host_err) + goto out_put_write_access_nfserror; + + fh_lock(fhp); + host_err = notify_change(dentry, iap); + fh_unlock(fhp); + +out_put_write_access_nfserror: + err = nfserrno(host_err); +out_put_write_access: if (size_change) put_write_access(inode); if (!err) commit_metadata(fhp); out: return err; - -out_nfserr: - err = nfserrno(host_err); - goto out; } #if defined(CONFIG_NFSD_V2_ACL) || \ -- cgit v1.2.3 From b4673c4343e86c0b74d79e8b02eafa0da263989a Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Tue, 12 Nov 2013 17:39:43 +0100 Subject: x86/microcode/amd: Tone down printk(), don't treat a missing firmware file as an error commit 11f918d3e2d3861b6931e97b3aa778e4984935aa upstream. Do it the same way as done in microcode_intel.c: use pr_debug() for missing firmware files. There seem to be CPUs out there for which no microcode update has been submitted to kernel-firmware repo yet resulting in scary sounding error messages in dmesg: microcode: failed to load file amd-ucode/microcode_amd_fam16h.bin Signed-off-by: Thomas Renninger Acked-by: Borislav Petkov Link: http://lkml.kernel.org/r/1384274383-43510-1-git-send-email-trenn@suse.de Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/microcode_amd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c index efdec7cd8e01..b516dfb411ec 100644 --- a/arch/x86/kernel/microcode_amd.c +++ b/arch/x86/kernel/microcode_amd.c @@ -430,7 +430,7 @@ static enum ucode_state request_microcode_amd(int cpu, struct device *device, snprintf(fw_name, sizeof(fw_name), "amd-ucode/microcode_amd_fam%.2xh.bin", c->x86); if (request_firmware(&fw, (const char *)fw_name, device)) { - pr_err("failed to load file %s\n", fw_name); + pr_debug("failed to load file %s\n", fw_name); goto out; } -- cgit v1.2.3 From b5f92a134b69faeffa0e1a811f01a48d686a4e97 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 31 Oct 2013 23:05:24 +0100 Subject: KVM: x86: fix emulation of "movzbl %bpl, %eax" commit daf727225b8abfdfe424716abac3d15a3ac5626a upstream. When I was looking at RHEL5.9's failure to start with unrestricted_guest=0/emulate_invalid_guest_state=1, I got it working with a slightly older tree than kvm.git. I now debugged the remaining failure, which was introduced by commit 660696d1 (KVM: X86 emulator: fix source operand decoding for 8bit mov[zs]x instructions, 2013-04-24) introduced a similar mis-emulation to the one in commit 8acb4207 (KVM: fix sil/dil/bpl/spl in the mod/rm fields, 2013-05-30). The incorrect decoding occurs in 8-bit movzx/movsx instructions whose 8-bit operand is sil/dil/bpl/spl. Needless to say, "movzbl %bpl, %eax" does occur in RHEL5.9's decompression prolog, just a handful of instructions before finally giving control to the decompressed vmlinux and getting out of the invalid guest state. Because OpMem8 bypasses decode_modrm, the same handling of the REX prefix must be applied to OpMem8. Reported-by: Michele Baldessari Cc: Gleb Natapov Signed-off-by: Paolo Bonzini Signed-off-by: Gleb Natapov Signed-off-by: Greg Kroah-Hartman --- arch/x86/kvm/emulate.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 5953dcea752d..5484d54582ca 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -4207,7 +4207,10 @@ static int decode_operand(struct x86_emulate_ctxt *ctxt, struct operand *op, case OpMem8: ctxt->memop.bytes = 1; if (ctxt->memop.type == OP_REG) { - ctxt->memop.addr.reg = decode_register(ctxt, ctxt->modrm_rm, 1); + int highbyte_regs = ctxt->rex_prefix == 0; + + ctxt->memop.addr.reg = decode_register(ctxt, ctxt->modrm_rm, + highbyte_regs); fetch_register_operand(&ctxt->memop); } goto mem_common; -- cgit v1.2.3 From fe78c20faafde229631b0402ef9fdfbc75277903 Mon Sep 17 00:00:00 2001 From: Kevin Hao Date: Wed, 23 Oct 2013 20:58:16 +0800 Subject: ftrace/x86: skip over the breakpoint for ftrace caller commit ab4ead02ec235d706d0611d8741964628291237e upstream. In commit 8a4d0a687a59 "ftrace: Use breakpoint method to update ftrace caller", we choose to use breakpoint method to update the ftrace caller. But we also need to skip over the breakpoint in function ftrace_int3_handler() for them. Otherwise weird things would happen. Signed-off-by: Kevin Hao Signed-off-by: Steven Rostedt Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/ftrace.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c index 42a392a9fd02..d4bdd253fea7 100644 --- a/arch/x86/kernel/ftrace.c +++ b/arch/x86/kernel/ftrace.c @@ -248,6 +248,15 @@ int ftrace_update_ftrace_func(ftrace_func_t func) return ret; } +static int is_ftrace_caller(unsigned long ip) +{ + if (ip == (unsigned long)(&ftrace_call) || + ip == (unsigned long)(&ftrace_regs_call)) + return 1; + + return 0; +} + /* * A breakpoint was added to the code address we are about to * modify, and this is the handle that will just skip over it. @@ -257,10 +266,13 @@ int ftrace_update_ftrace_func(ftrace_func_t func) */ int ftrace_int3_handler(struct pt_regs *regs) { + unsigned long ip; + if (WARN_ON_ONCE(!regs)) return 0; - if (!ftrace_location(regs->ip - 1)) + ip = regs->ip - 1; + if (!ftrace_location(ip) && !is_ftrace_caller(ip)) return 0; regs->ip += MCOUNT_INSN_SIZE - 1; -- cgit v1.2.3 From ac18077a4150ab4ecddea135e466c55cc6c551ab Mon Sep 17 00:00:00 2001 From: Greg Edwards Date: Mon, 4 Nov 2013 09:08:12 -0700 Subject: KVM: IOMMU: hva align mapping page size commit 27ef63c7e97d1e5dddd85051c03f8d44cc887f34 upstream. When determining the page size we could use to map with the IOMMU, the page size should also be aligned with the hva, not just the gfn. The gfn may not reflect the real alignment within the hugetlbfs file. Most of the time, this works fine. However, if the hugetlbfs file is backed by non-contiguous huge pages, a multi-huge page memslot starts at an unaligned offset within the hugetlbfs file, and the gfn is aligned with respect to the huge page size, kvm_host_page_size() will return the huge page size and we will use that to map with the IOMMU. When we later unpin that same memslot, the IOMMU returns the unmap size as the huge page size, and we happily unpin that many pfns in monotonically increasing order, not realizing we are spanning non-contiguous huge pages and partially unpin the wrong huge page. Ensure the IOMMU mapping page size is aligned with the hva corresponding to the gfn, which does reflect the alignment within the hugetlbfs file. Reviewed-by: Marcelo Tosatti Signed-off-by: Greg Edwards Signed-off-by: Gleb Natapov Signed-off-by: Greg Kroah-Hartman --- virt/kvm/iommu.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/virt/kvm/iommu.c b/virt/kvm/iommu.c index 72a130bc448a..c329c8fc57f4 100644 --- a/virt/kvm/iommu.c +++ b/virt/kvm/iommu.c @@ -103,6 +103,10 @@ int kvm_iommu_map_pages(struct kvm *kvm, struct kvm_memory_slot *slot) while ((gfn << PAGE_SHIFT) & (page_size - 1)) page_size >>= 1; + /* Make sure hva is aligned to the page size we want to map */ + while (__gfn_to_hva_memslot(slot, gfn) & (page_size - 1)) + page_size >>= 1; + /* * Pin all pages we are about to map in memory. This is * important because we unmap and unpin in 4kb steps later. -- cgit v1.2.3 From 9cce2a8756944a83dee2b687800bcca369ecbbed Mon Sep 17 00:00:00 2001 From: Christoffer Dall Date: Fri, 15 Nov 2013 13:14:12 -0800 Subject: arm/arm64: KVM: Fix hyp mappings of vmalloc regions commit 40c2729bab48e2832b17c1fa8af9db60e776131b upstream. Using virt_to_phys on percpu mappings is horribly wrong as it may be backed by vmalloc. Introduce kvm_kaddr_to_phys which translates both types of valid kernel addresses to the corresponding physical address. At the same time resolves a typing issue where we were storing the physical address as a 32 bit unsigned long (on arm), truncating the physical address for addresses above the 4GB limit. This caused breakage on Keystone. Reported-by: Santosh Shilimkar Tested-by: Santosh Shilimkar Signed-off-by: Marc Zyngier Signed-off-by: Christoffer Dall Signed-off-by: Greg Kroah-Hartman --- arch/arm/kvm/mmu.c | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c index 84ba67b982c0..e04613906f1b 100644 --- a/arch/arm/kvm/mmu.c +++ b/arch/arm/kvm/mmu.c @@ -313,6 +313,17 @@ out: return err; } +static phys_addr_t kvm_kaddr_to_phys(void *kaddr) +{ + if (!is_vmalloc_addr(kaddr)) { + BUG_ON(!virt_addr_valid(kaddr)); + return __pa(kaddr); + } else { + return page_to_phys(vmalloc_to_page(kaddr)) + + offset_in_page(kaddr); + } +} + /** * create_hyp_mappings - duplicate a kernel virtual address range in Hyp mode * @from: The virtual kernel start address of the range @@ -324,16 +335,27 @@ out: */ int create_hyp_mappings(void *from, void *to) { - unsigned long phys_addr = virt_to_phys(from); + phys_addr_t phys_addr; + unsigned long virt_addr; unsigned long start = KERN_TO_HYP((unsigned long)from); unsigned long end = KERN_TO_HYP((unsigned long)to); - /* Check for a valid kernel memory mapping */ - if (!virt_addr_valid(from) || !virt_addr_valid(to - 1)) - return -EINVAL; + start = start & PAGE_MASK; + end = PAGE_ALIGN(end); - return __create_hyp_mappings(hyp_pgd, start, end, - __phys_to_pfn(phys_addr), PAGE_HYP); + for (virt_addr = start; virt_addr < end; virt_addr += PAGE_SIZE) { + int err; + + phys_addr = kvm_kaddr_to_phys(from + virt_addr - start); + err = __create_hyp_mappings(hyp_pgd, virt_addr, + virt_addr + PAGE_SIZE, + __phys_to_pfn(phys_addr), + PAGE_HYP); + if (err) + return err; + } + + return 0; } /** -- cgit v1.2.3 From 598f412c2f62635b20b110e46d5c4eba2fb96834 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Fri, 15 Nov 2013 10:40:38 +0100 Subject: hwmon: (lm90) Fix max6696 alarm handling commit e41fae2b1ed8c78283d73651cd65be0228c0dd1c upstream. Bit 2 of status register 2 on MAX6696 (external diode 2 open) sets ALERT; the bit thus has to be listed in alert_alarms. Also display a message in the alert handler if the condition is encountered. Even though not all overtemperature conditions cause ALERT to be set, we should not ignore them in the alert handler. Display messages for all out-of-range conditions. Reported-by: Jean Delvare Signed-off-by: Guenter Roeck Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/lm90.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c index 8eeb141c85ac..74813130d211 100644 --- a/drivers/hwmon/lm90.c +++ b/drivers/hwmon/lm90.c @@ -278,7 +278,7 @@ static const struct lm90_params lm90_params[] = { [max6696] = { .flags = LM90_HAVE_EMERGENCY | LM90_HAVE_EMERGENCY_ALARM | LM90_HAVE_TEMP3, - .alert_alarms = 0x187c, + .alert_alarms = 0x1c7c, .max_convrate = 6, .reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL, }, @@ -1500,19 +1500,22 @@ static void lm90_alert(struct i2c_client *client, unsigned int flag) if ((alarms & 0x7f) == 0 && (alarms2 & 0xfe) == 0) { dev_info(&client->dev, "Everything OK\n"); } else { - if (alarms & 0x61) + if ((alarms & 0x61) || (alarms2 & 0x80)) dev_warn(&client->dev, "temp%d out of range, please check!\n", 1); - if (alarms & 0x1a) + if ((alarms & 0x1a) || (alarms2 & 0x20)) dev_warn(&client->dev, "temp%d out of range, please check!\n", 2); if (alarms & 0x04) dev_warn(&client->dev, "temp%d diode open, please check!\n", 2); - if (alarms2 & 0x18) + if (alarms2 & 0x5a) dev_warn(&client->dev, "temp%d out of range, please check!\n", 3); + if (alarms2 & 0x04) + dev_warn(&client->dev, + "temp%d diode open, please check!\n", 3); /* * Disable ALERT# output, because these chips don't implement -- cgit v1.2.3 From 869d4e7f52ada7136161a9ac343ecc000a77f46d Mon Sep 17 00:00:00 2001 From: Jeff Moyer Date: Tue, 8 Oct 2013 14:36:41 -0400 Subject: block: fix race between request completion and timeout handling commit 4912aa6c11e6a5d910264deedbec2075c6f1bb73 upstream. crocode i2c_i801 i2c_core iTCO_wdt iTCO_vendor_support shpchp ioatdma dca be2net sg ses enclosure ext4 mbcache jbd2 sd_mod crc_t10dif ahci megaraid_sas(U) dm_mirror dm_region_hash dm_log dm_mod [last unloaded: scsi_wait_scan] Pid: 491, comm: scsi_eh_0 Tainted: G W ---------------- 2.6.32-220.13.1.el6.x86_64 #1 IBM -[8722PAX]-/00D1461 RIP: 0010:[] [] blk_requeue_request+0x94/0xa0 RSP: 0018:ffff881057eefd60 EFLAGS: 00010012 RAX: ffff881d99e3e8a8 RBX: ffff881d99e3e780 RCX: ffff881d99e3e8a8 RDX: ffff881d99e3e8a8 RSI: ffff881d99e3e780 RDI: ffff881d99e3e780 RBP: ffff881057eefd80 R08: ffff881057eefe90 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000000 R12: ffff881057f92338 R13: 0000000000000000 R14: ffff881057f92338 R15: ffff883058188000 FS: 0000000000000000(0000) GS:ffff880040200000(0000) knlGS:0000000000000000 CS: 0010 DS: 0018 ES: 0018 CR0: 000000008005003b CR2: 00000000006d3ec0 CR3: 000000302cd7d000 CR4: 00000000000406b0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process scsi_eh_0 (pid: 491, threadinfo ffff881057eee000, task ffff881057e29540) Stack: 0000000000001057 0000000000000286 ffff8810275efdc0 ffff881057f16000 <0> ffff881057eefdd0 ffffffff81362323 ffff881057eefe20 ffffffff8135f393 <0> ffff881057e29af8 ffff8810275efdc0 ffff881057eefe78 ffff881057eefe90 Call Trace: [] __scsi_queue_insert+0xa3/0x150 [] ? scsi_eh_ready_devs+0x5e3/0x850 [] scsi_queue_insert+0x13/0x20 [] scsi_eh_flush_done_q+0x104/0x160 [] scsi_error_handler+0x35b/0x660 [] ? scsi_error_handler+0x0/0x660 [] kthread+0x96/0xa0 [] child_rip+0xa/0x20 [] ? kthread+0x0/0xa0 [] ? child_rip+0x0/0x20 Code: 00 00 eb d1 4c 8b 2d 3c 8f 97 00 4d 85 ed 74 bf 49 8b 45 00 49 83 c5 08 48 89 de 4c 89 e7 ff d0 49 8b 45 00 48 85 c0 75 eb eb a4 <0f> 0b eb fe 0f 1f 84 00 00 00 00 00 55 48 89 e5 0f 1f 44 00 00 RIP [] blk_requeue_request+0x94/0xa0 RSP The RIP is this line: BUG_ON(blk_queued_rq(rq)); After digging through the code, I think there may be a race between the request completion and the timer handler running. A timer is started for each request put on the device's queue (see blk_start_request->blk_add_timer). If the request does not complete before the timer expires, the timer handler (blk_rq_timed_out_timer) will mark the request complete atomically: static inline int blk_mark_rq_complete(struct request *rq) { return test_and_set_bit(REQ_ATOM_COMPLETE, &rq->atomic_flags); } and then call blk_rq_timed_out. The latter function will call scsi_times_out, which will return one of BLK_EH_HANDLED, BLK_EH_RESET_TIMER or BLK_EH_NOT_HANDLED. If BLK_EH_RESET_TIMER is returned, blk_clear_rq_complete is called, and blk_add_timer is again called to simply wait longer for the request to complete. Now, if the request happens to complete while this is going on, what happens? Given that we know the completion handler will bail if it finds the REQ_ATOM_COMPLETE bit set, we need to focus on the completion handler running after that bit is cleared. So, from the above paragraph, after the call to blk_clear_rq_complete. If the completion sets REQ_ATOM_COMPLETE before the BUG_ON in blk_add_timer, we go boom there (I haven't seen this in the cores). Next, if we get the completion before the call to list_add_tail, then the timer will eventually fire for an old req, which may either be freed or reallocated (there is evidence that this might be the case). Finally, if the completion comes in *after* the addition to the timeout list, I think it's harmless. The request will be removed from the timeout list, req_atom_complete will be set, and all will be well. This will only actually explain the coredumps *IF* the request structure was freed, reallocated *and* queued before the error handler thread had a chance to process it. That is possible, but it may make sense to keep digging for another race. I think that if this is what was happening, we would see other instances of this problem showing up as null pointer or garbage pointer dereferences, for example when the request structure was not re-used. It looks like we actually do run into that situation in other reports. This patch moves the BUG_ON(test_bit(REQ_ATOM_COMPLETE, &req->atomic_flags)); from blk_add_timer to the only caller that could trip over it (blk_start_request). It then inverts the calls to blk_clear_rq_complete and blk_add_timer in blk_rq_timed_out to address the race. I've boot tested this patch, but nothing more. Signed-off-by: Jeff Moyer Acked-by: Hannes Reinecke Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- block/blk-core.c | 1 + block/blk-timeout.c | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index d5745b5833c9..45f3a51f6b56 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -2229,6 +2229,7 @@ void blk_start_request(struct request *req) if (unlikely(blk_bidi_rq(req))) req->next_rq->resid_len = blk_rq_bytes(req->next_rq); + BUG_ON(test_bit(REQ_ATOM_COMPLETE, &req->atomic_flags)); blk_add_timer(req); } EXPORT_SYMBOL(blk_start_request); diff --git a/block/blk-timeout.c b/block/blk-timeout.c index 6e4744cbfb56..5a6296ef9a81 100644 --- a/block/blk-timeout.c +++ b/block/blk-timeout.c @@ -90,8 +90,8 @@ static void blk_rq_timed_out(struct request *req) __blk_complete_request(req); break; case BLK_EH_RESET_TIMER: - blk_clear_rq_complete(req); blk_add_timer(req); + blk_clear_rq_complete(req); break; case BLK_EH_NOT_HANDLED: /* @@ -173,7 +173,6 @@ void blk_add_timer(struct request *req) return; BUG_ON(!list_empty(&req->timeout_list)); - BUG_ON(test_bit(REQ_ATOM_COMPLETE, &req->atomic_flags)); /* * Some LLDs, like scsi, peek at the timeout to prevent a -- cgit v1.2.3 From 12e6e9c2a578d3a2f0474d48d845f796361a90c0 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Mon, 14 Oct 2013 12:13:24 -0400 Subject: block: fix a probe argument to blk_register_region commit a207f5937630dd35bd2550620bef416937a1365e upstream. The probe function is supposed to return NULL on failure (as we can see in kobj_lookup: kobj = probe(dev, index, data); ... if (kobj) return kobj; However, in loop and brd, it returns negative error from ERR_PTR. This causes a crash if we simulate disk allocation failure and run less -f /dev/loop0 because the negative number is interpreted as a pointer: BUG: unable to handle kernel NULL pointer dereference at 00000000000002b4 IP: [] __blkdev_get+0x28/0x450 PGD 23c677067 PUD 23d6d1067 PMD 0 Oops: 0000 [#1] PREEMPT SMP Modules linked in: loop hpfs nvidia(PO) ip6table_filter ip6_tables uvesafb cfbcopyarea cfbimgblt cfbfillrect fbcon font bitblit fbcon_rotate fbcon_cw fbcon_ud fbcon_ccw softcursor fb fbdev msr ipt_MASQUERADE iptable_nat nf_nat_ipv4 nf_conntrack_ipv4 nf_defrag_ipv4 xt_state ipt_REJECT xt_tcpudp iptable_filter ip_tables x_tables bridge stp llc tun ipv6 cpufreq_stats cpufreq_ondemand cpufreq_userspace cpufreq_powersave cpufreq_conservative hid_generic spadfs usbhid hid fuse raid0 snd_usb_audio snd_pcm_oss snd_mixer_oss md_mod snd_pcm snd_timer snd_page_alloc snd_hwdep snd_usbmidi_lib dmi_sysfs snd_rawmidi nf_nat_ftp nf_nat nf_conntrack_ftp nf_conntrack snd soundcore lm85 hwmon_vid ohci_hcd ehci_pci ehci_hcd serverworks sata_svw libata acpi_cpufreq freq_table mperf ide_core usbcore kvm_amd kvm tg3 i2c_piix4 libphy microcode e100 usb_common ptp skge i2c_core pcspkr k10temp evdev floppy hwmon pps_core mii rtc_cmos button processor unix [last unloaded: nvidia] CPU: 1 PID: 6831 Comm: less Tainted: P W O 3.10.15-devel #18 Hardware name: empty empty/S3992-E, BIOS 'V1.06 ' 06/09/2009 task: ffff880203cc6bc0 ti: ffff88023e47c000 task.ti: ffff88023e47c000 RIP: 0010:[] [] __blkdev_get+0x28/0x450 RSP: 0018:ffff88023e47dbd8 EFLAGS: 00010286 RAX: ffffffffffffff74 RBX: ffffffffffffff74 RCX: 0000000000000000 RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000001 RBP: ffff88023e47dc18 R08: 0000000000000002 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000000 R12: ffff88023f519658 R13: ffffffff8118c300 R14: 0000000000000000 R15: ffff88023f519640 FS: 00007f2070bf7700(0000) GS:ffff880247400000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00000000000002b4 CR3: 000000023da1d000 CR4: 00000000000007e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Stack: 0000000000000002 0000001d00000000 000000003e47dc50 ffff88023f519640 ffff88043d5bb668 ffffffff8118c300 ffff88023d683550 ffff88023e47de60 ffff88023e47dc98 ffffffff8118c10d 0000001d81605698 0000000000000292 Call Trace: [] ? blkdev_get_by_dev+0x60/0x60 [] blkdev_get+0x1dd/0x370 [] ? blkdev_get_by_dev+0x60/0x60 [] ? _raw_spin_unlock+0x2c/0x50 [] ? blkdev_get_by_dev+0x60/0x60 [] blkdev_open+0x65/0x80 [] do_dentry_open.isra.18+0x23e/0x2f0 [] finish_open+0x34/0x50 [] do_last.isra.62+0x2d2/0xc50 [] path_openat.isra.63+0xb8/0x4d0 [] ? might_fault+0x4e/0xa0 [] do_filp_open+0x40/0x90 [] ? _raw_spin_unlock+0x2c/0x50 [] ? __alloc_fd+0xa5/0x1f0 [] do_sys_open+0xef/0x1d0 [] SyS_open+0x19/0x20 [] system_call_fastpath+0x1a/0x1f Code: 44 00 00 55 48 89 e5 41 57 49 89 ff 41 56 41 89 d6 41 55 41 54 4c 8d 67 18 53 48 83 ec 18 89 75 cc e9 f2 00 00 00 0f 1f 44 00 00 <48> 8b 80 40 03 00 00 48 89 df 4c 8b 68 58 e8 d5 a4 07 00 44 89 RIP [] __blkdev_get+0x28/0x450 RSP CR2: 00000000000002b4 ---[ end trace bb7f32dbf02398dc ]--- The brd change should be backported to stable kernels starting with 2.6.25. The loop change should be backported to stable kernels starting with 2.6.22. Signed-off-by: Mikulas Patocka Acked-by: Tejun Heo Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- drivers/block/brd.c | 2 +- drivers/block/loop.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/block/brd.c b/drivers/block/brd.c index 9bf4371755f2..d91f1a56e861 100644 --- a/drivers/block/brd.c +++ b/drivers/block/brd.c @@ -545,7 +545,7 @@ static struct kobject *brd_probe(dev_t dev, int *part, void *data) mutex_lock(&brd_devices_mutex); brd = brd_init_one(MINOR(dev) >> part_shift); - kobj = brd ? get_disk(brd->brd_disk) : ERR_PTR(-ENOMEM); + kobj = brd ? get_disk(brd->brd_disk) : NULL; mutex_unlock(&brd_devices_mutex); *part = 0; diff --git a/drivers/block/loop.c b/drivers/block/loop.c index d92d50fd84b7..00559736cee4 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -1741,7 +1741,7 @@ static struct kobject *loop_probe(dev_t dev, int *part, void *data) if (err < 0) err = loop_add(&lo, MINOR(dev) >> part_shift); if (err < 0) - kobj = ERR_PTR(err); + kobj = NULL; else kobj = get_disk(lo->lo_disk); mutex_unlock(&loop_index_mutex); -- cgit v1.2.3 From 0deb6f9cb87494f6646fb014f09b41d3ded76c63 Mon Sep 17 00:00:00 2001 From: Mike Snitzer Date: Fri, 18 Oct 2013 09:44:49 -0600 Subject: block: properly stack underlying max_segment_size to DM device commit d82ae52e68892338068e7559a0c0657193341ce4 upstream. Without this patch all DM devices will default to BLK_MAX_SEGMENT_SIZE (65536) even if the underlying device(s) have a larger value -- this is due to blk_stack_limits() using min_not_zero() when stacking the max_segment_size limit. 1073741824 before patch: 65536 after patch: 1073741824 Reported-by: Lukasz Flis Signed-off-by: Mike Snitzer Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- block/blk-settings.c | 1 + 1 file changed, 1 insertion(+) diff --git a/block/blk-settings.c b/block/blk-settings.c index c50ecf0ea3b1..53309333c2f0 100644 --- a/block/blk-settings.c +++ b/block/blk-settings.c @@ -144,6 +144,7 @@ void blk_set_stacking_limits(struct queue_limits *lim) lim->discard_zeroes_data = 1; lim->max_segments = USHRT_MAX; lim->max_hw_sectors = UINT_MAX; + lim->max_segment_size = UINT_MAX; lim->max_sectors = UINT_MAX; lim->max_write_same_sectors = UINT_MAX; } -- cgit v1.2.3 From ae4c6cbd0a56bcea14bf35168076b9ad5bd3203f Mon Sep 17 00:00:00 2001 From: Anatolij Gustschin Date: Wed, 16 Oct 2013 13:11:27 +0200 Subject: powerpc/52xx: fix build breakage for MPC5200 LPBFIFO module commit 2bf75084f6d9f9a91ba6e30a501ff070d8a1acf6 upstream. The MPC5200 LPBFIFO driver requires the bestcomm module to be enabled, otherwise building will fail. Fix it. Reported-by: Wolfgang Denk Signed-off-by: Anatolij Gustschin Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/platforms/52xx/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/platforms/52xx/Kconfig b/arch/powerpc/platforms/52xx/Kconfig index 90f4496017e4..af54174801f7 100644 --- a/arch/powerpc/platforms/52xx/Kconfig +++ b/arch/powerpc/platforms/52xx/Kconfig @@ -57,5 +57,5 @@ config PPC_MPC5200_BUGFIX config PPC_MPC5200_LPBFIFO tristate "MPC5200 LocalPlus bus FIFO driver" - depends on PPC_MPC52xx + depends on PPC_MPC52xx && PPC_BESTCOMM select PPC_BESTCOMM_GEN_BD -- cgit v1.2.3 From a2db1eb6794f761bc90ae128c0694874bf572579 Mon Sep 17 00:00:00 2001 From: Prarit Bhargava Date: Thu, 17 Oct 2013 08:00:11 -0400 Subject: powerpc/vio: use strcpy in modalias_show commit 411cabf79e684171669ad29a0628c400b4431e95 upstream. Commit e82b89a6f19bae73fb064d1b3dd91fcefbb478f4 used strcat instead of strcpy which can result in an overflow of newlines on the buffer. Signed-off-by: Prarit Bhargava Cc: benh@kernel.crashing.org Cc: ben@decadent.org.uk Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/kernel/vio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index 2d845d8199fc..56d2e72c85de 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c @@ -1530,12 +1530,12 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, dn = dev->of_node; if (!dn) { - strcat(buf, "\n"); + strcpy(buf, "\n"); return strlen(buf); } cp = of_get_property(dn, "compatible", NULL); if (!cp) { - strcat(buf, "\n"); + strcpy(buf, "\n"); return strlen(buf); } -- cgit v1.2.3 From 36cfdef6ffa08c5f3b1f812332eddd8aa4d91ed2 Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Mon, 4 Nov 2013 16:32:46 +0800 Subject: powerpc/powernv: Add PE to its own PELTV commit 631ad691b5818291d89af9be607d2fe40be0886e upstream. We need add PE to its own PELTV. Otherwise, the errors originated from the PE might contribute to other PEs. In the result, we can't clear up the error successfully even we're checking and clearing errors during access to PCI config space. Reported-by: kalshett@in.ibm.com Signed-off-by: Gavin Shan Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/platforms/powernv/pci-ioda.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 7816beff1db8..f75607c93e8a 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -151,13 +151,23 @@ static int pnv_ioda_configure_pe(struct pnv_phb *phb, struct pnv_ioda_pe *pe) rid_end = pe->rid + 1; } - /* Associate PE in PELT */ + /* + * Associate PE in PELT. We need add the PE into the + * corresponding PELT-V as well. Otherwise, the error + * originated from the PE might contribute to other + * PEs. + */ rc = opal_pci_set_pe(phb->opal_id, pe->pe_number, pe->rid, bcomp, dcomp, fcomp, OPAL_MAP_PE); if (rc) { pe_err(pe, "OPAL error %ld trying to setup PELT table\n", rc); return -ENXIO; } + + rc = opal_pci_set_peltv(phb->opal_id, pe->pe_number, + pe->pe_number, OPAL_ADD_PE_TO_DOMAIN); + if (rc) + pe_warn(pe, "OPAL error %d adding self to PELTV\n", rc); opal_pci_eeh_freeze_clear(phb->opal_id, pe->pe_number, OPAL_EEH_ACTION_CLEAR_FREEZE_ALL); -- cgit v1.2.3 From 3ee8b4e1d91204180081d04c964ee5e0c7387f27 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Mon, 18 Nov 2013 14:55:28 +1100 Subject: powerpc: ppc64 address space capped at 32TB, mmap randomisation disabled commit 5a049f14902982c26538250bdc8d54156d357252 upstream. Commit fba2369e6ceb (mm: use vm_unmapped_area() on powerpc architecture) has a bug in slice_scan_available() where we compare an unsigned long (high_slices) against a shifted int. As a result, comparisons against the top 32 bits of high_slices (representing the top 32TB) always returns 0 and the top of our mmap region is clamped at 32TB This also breaks mmap randomisation since the randomised address is always up near the top of the address space and it gets clamped down to 32TB. Signed-off-by: Anton Blanchard Acked-by: Michel Lespinasse Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/mm/slice.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/mm/slice.c b/arch/powerpc/mm/slice.c index 3e99c149271a..7ce9cf3b6988 100644 --- a/arch/powerpc/mm/slice.c +++ b/arch/powerpc/mm/slice.c @@ -258,7 +258,7 @@ static bool slice_scan_available(unsigned long addr, slice = GET_HIGH_SLICE_INDEX(addr); *boundary_addr = (slice + end) ? ((slice + end) << SLICE_HIGH_SHIFT) : SLICE_LOW_TOP; - return !!(available.high_slices & (1u << slice)); + return !!(available.high_slices & (1ul << slice)); } } -- cgit v1.2.3 From 826b7a8cc660c8412ae6c8c7bb258c875dd0dbc2 Mon Sep 17 00:00:00 2001 From: Michael Neuling Date: Wed, 20 Nov 2013 16:18:54 +1100 Subject: powerpc/signals: Mark VSX not saved with small contexts commit c13f20ac48328b05cd3b8c19e31ed6c132b44b42 upstream. The VSX MSR bit in the user context indicates if the context contains VSX state. Currently we set this when the process has touched VSX at any stage. Unfortunately, if the user has not provided enough space to save the VSX state, we can't save it but we currently still set the MSR VSX bit. This patch changes this to clear the MSR VSX bit when the user doesn't provide enough space. This indicates that there is no valid VSX state in the user context. This is needed to support get/set/make/swapcontext for applications that use VSX but only provide a small context. For example, getcontext in glibc provides a smaller context since the VSX registers don't need to be saved over the glibc function call. But since the program calling getcontext may have used VSX, the kernel currently says the VSX state is valid when it's not. If the returned context is then used in setcontext (ie. a small context without VSX but with MSR VSX set), the kernel will refuse the context. This situation has been reported by the glibc community. Based on patch from Carlos O'Donell. Tested-by: Haren Myneni Signed-off-by: Michael Neuling Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/kernel/signal_32.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index 0f83122e6676..323309963cd3 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c @@ -454,7 +454,15 @@ static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame, if (copy_vsx_to_user(&frame->mc_vsregs, current)) return 1; msr |= MSR_VSX; - } + } else if (!ctx_has_vsx_region) + /* + * With a small context structure we can't hold the VSX + * registers, hence clear the MSR value to indicate the state + * was not saved. + */ + msr &= ~MSR_VSX; + + #endif /* CONFIG_VSX */ #ifdef CONFIG_SPE /* save spe registers */ -- cgit v1.2.3 From fe76407da71233f8b172e2eabaf58a9d3dccf894 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Thu, 7 Nov 2013 16:29:15 +0000 Subject: slub: Handle NULL parameter in kmem_cache_flags commit c6f58d9b362b45c52afebe4342c9137d0dabe47f upstream. Andreas Herrmann writes: When I've used slub_debug kernel option (e.g. "slub_debug=,skbuff_fclone_cache" or similar) on a debug session I've seen a panic like: Highbank #setenv bootargs console=ttyAMA0 root=/dev/sda2 kgdboc.kgdboc=ttyAMA0,115200 slub_debug=,kmalloc-4096 earlyprintk=ttyAMA0 ... Unable to handle kernel NULL pointer dereference at virtual address 00000000 pgd = c0004000 [00000000] *pgd=00000000 Internal error: Oops: 5 [#1] SMP ARM Modules linked in: CPU: 0 PID: 0 Comm: swapper Tainted: G W 3.12.0-00048-gbe408cd #314 task: c0898360 ti: c088a000 task.ti: c088a000 PC is at strncmp+0x1c/0x84 LR is at kmem_cache_flags.isra.46.part.47+0x44/0x60 pc : [] lr : [] psr: 200001d3 sp : c088bea8 ip : c088beb8 fp : c088beb4 r10: 00000000 r9 : 413fc090 r8 : 00000001 r7 : 00000000 r6 : c2984a08 r5 : c0966e78 r4 : 00000000 r3 : 0000006b r2 : 0000000c r1 : 00000000 r0 : c2984a08 Flags: nzCv IRQs off FIQs off Mode SVC_32 ISA ARM Segment kernel Control: 10c5387d Table: 0000404a DAC: 00000015 Process swapper (pid: 0, stack limit = 0xc088a248) Stack: (0xc088bea8 to 0xc088c000) bea0: c088bed4 c088beb8 c0110a3c c02c6d90 c0966e78 00000040 bec0: ef001f00 00000040 c088bf14 c088bed8 c0112070 c0110a04 00000005 c010fac8 bee0: c088bf5c c088bef0 c010fac8 ef001f00 00000040 00000000 00000040 00000001 bf00: 413fc090 00000000 c088bf34 c088bf18 c0839190 c0112040 00000000 ef001f00 bf20: 00000000 00000000 c088bf54 c088bf38 c0839200 c083914c 00000006 c0961c4c bf40: c0961c28 00000000 c088bf7c c088bf58 c08392ac c08391c0 c08a2ed8 c0966e78 bf60: c086b874 c08a3f50 c0961c28 00000001 c088bfb4 c088bf80 c083b258 c0839248 bf80: 2f800000 0f000000 c08935b4 ffffffff c08cd400 ffffffff c08cd400 c0868408 bfa0: c29849c0 00000000 c088bff4 c088bfb8 c0824974 c083b1e4 ffffffff ffffffff bfc0: c08245c0 00000000 00000000 c0868408 00000000 10c5387d c0892bcc c0868404 bfe0: c0899440 0000406a 00000000 c088bff8 00008074 c0824824 00000000 00000000 [] (strncmp+0x1c/0x84) from [] (kmem_cache_flags.isra.46.part.47+0x44/0x60) [] (kmem_cache_flags.isra.46.part.47+0x44/0x60) from [] (__kmem_cache_create+0x3c/0x410) [] (__kmem_cache_create+0x3c/0x410) from [] (create_boot_cache+0x50/0x74) [] (create_boot_cache+0x50/0x74) from [] (create_kmalloc_cache+0x4c/0x88) [] (create_kmalloc_cache+0x4c/0x88) from [] (create_kmalloc_caches+0x70/0x114) [] (create_kmalloc_caches+0x70/0x114) from [] (kmem_cache_init+0x80/0xe0) [] (kmem_cache_init+0x80/0xe0) from [] (start_kernel+0x15c/0x318) [] (start_kernel+0x15c/0x318) from [<00008074>] (0x8074) Code: e3520000 01a00002 089da800 e5d03000 (e5d1c000) ---[ end trace 1b75b31a2719ed1d ]--- Kernel panic - not syncing: Fatal exception Problem is that slub_debug option is not parsed before create_boot_cache is called. Solve this by changing slub_debug to early_param. Kernels 3.11, 3.10 are also affected. I am not sure about older kernels. Christoph Lameter explains: kmem_cache_flags may be called with NULL parameter during early boot. Skip the test in that case. Reported-by: Andreas Herrmann Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg Signed-off-by: Greg Kroah-Hartman --- mm/slub.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mm/slub.c b/mm/slub.c index 57707f01bcfb..c34bd44e8be9 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -1201,8 +1201,8 @@ static unsigned long kmem_cache_flags(unsigned long object_size, /* * Enable debugging if selected on the kernel commandline. */ - if (slub_debug && (!slub_debug_slabs || - !strncmp(slub_debug_slabs, name, strlen(slub_debug_slabs)))) + if (slub_debug && (!slub_debug_slabs || (name && + !strncmp(slub_debug_slabs, name, strlen(slub_debug_slabs))))) flags |= slub_debug; return flags; -- cgit v1.2.3 From 7adb120526cf06bc2c0a8449194172ecfb62c730 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Fri, 8 Nov 2013 16:03:50 -0500 Subject: SUNRPC: Fix a data corruption issue when retransmitting RPC calls commit a6b31d18b02ff9d7915c5898c9b5ca41a798cd73 upstream. The following scenario can cause silent data corruption when doing NFS writes. It has mainly been observed when doing database writes using O_DIRECT. 1) The RPC client uses sendpage() to do zero-copy of the page data. 2) Due to networking issues, the reply from the server is delayed, and so the RPC client times out. 3) The client issues a second sendpage of the page data as part of an RPC call retransmission. 4) The reply to the first transmission arrives from the server _before_ the client hardware has emptied the TCP socket send buffer. 5) After processing the reply, the RPC state machine rules that the call to be done, and triggers the completion callbacks. 6) The application notices the RPC call is done, and reuses the pages to store something else (e.g. a new write). 7) The client NIC drains the TCP socket send buffer. Since the page data has now changed, it reads a corrupted version of the initial RPC call, and puts it on the wire. This patch fixes the problem in the following manner: The ordering guarantees of TCP ensure that when the server sends a reply, then we know that the _first_ transmission has completed. Using zero-copy in that situation is therefore safe. If a time out occurs, we then send the retransmission using sendmsg() (i.e. no zero-copy), We then know that the socket contains a full copy of the data, and so it will retransmit a faithful reproduction even if the RPC call completes, and the application reuses the O_DIRECT buffer in the meantime. Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- net/sunrpc/xprtsock.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index ffd50348a509..8a0e04d0928a 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -391,8 +391,10 @@ static int xs_send_kvec(struct socket *sock, struct sockaddr *addr, int addrlen, return kernel_sendmsg(sock, &msg, NULL, 0, 0); } -static int xs_send_pagedata(struct socket *sock, struct xdr_buf *xdr, unsigned int base, int more) +static int xs_send_pagedata(struct socket *sock, struct xdr_buf *xdr, unsigned int base, int more, bool zerocopy) { + ssize_t (*do_sendpage)(struct socket *sock, struct page *page, + int offset, size_t size, int flags); struct page **ppage; unsigned int remainder; int err, sent = 0; @@ -401,6 +403,9 @@ static int xs_send_pagedata(struct socket *sock, struct xdr_buf *xdr, unsigned i base += xdr->page_base; ppage = xdr->pages + (base >> PAGE_SHIFT); base &= ~PAGE_MASK; + do_sendpage = sock->ops->sendpage; + if (!zerocopy) + do_sendpage = sock_no_sendpage; for(;;) { unsigned int len = min_t(unsigned int, PAGE_SIZE - base, remainder); int flags = XS_SENDMSG_FLAGS; @@ -408,7 +413,7 @@ static int xs_send_pagedata(struct socket *sock, struct xdr_buf *xdr, unsigned i remainder -= len; if (remainder != 0 || more) flags |= MSG_MORE; - err = sock->ops->sendpage(sock, *ppage, base, len, flags); + err = do_sendpage(sock, *ppage, base, len, flags); if (remainder == 0 || err != len) break; sent += err; @@ -429,9 +434,10 @@ static int xs_send_pagedata(struct socket *sock, struct xdr_buf *xdr, unsigned i * @addrlen: UDP only -- length of destination address * @xdr: buffer containing this request * @base: starting position in the buffer + * @zerocopy: true if it is safe to use sendpage() * */ -static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base) +static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base, bool zerocopy) { unsigned int remainder = xdr->len - base; int err, sent = 0; @@ -459,7 +465,7 @@ static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, if (base < xdr->page_len) { unsigned int len = xdr->page_len - base; remainder -= len; - err = xs_send_pagedata(sock, xdr, base, remainder != 0); + err = xs_send_pagedata(sock, xdr, base, remainder != 0, zerocopy); if (remainder == 0 || err != len) goto out; sent += err; @@ -562,7 +568,7 @@ static int xs_local_send_request(struct rpc_task *task) req->rq_svec->iov_base, req->rq_svec->iov_len); status = xs_sendpages(transport->sock, NULL, 0, - xdr, req->rq_bytes_sent); + xdr, req->rq_bytes_sent, true); dprintk("RPC: %s(%u) = %d\n", __func__, xdr->len - req->rq_bytes_sent, status); if (likely(status >= 0)) { @@ -618,7 +624,7 @@ static int xs_udp_send_request(struct rpc_task *task) status = xs_sendpages(transport->sock, xs_addr(xprt), xprt->addrlen, xdr, - req->rq_bytes_sent); + req->rq_bytes_sent, true); dprintk("RPC: xs_udp_send_request(%u) = %d\n", xdr->len - req->rq_bytes_sent, status); @@ -689,6 +695,7 @@ static int xs_tcp_send_request(struct rpc_task *task) struct rpc_xprt *xprt = req->rq_xprt; struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); struct xdr_buf *xdr = &req->rq_snd_buf; + bool zerocopy = true; int status; xs_encode_stream_record_marker(&req->rq_snd_buf); @@ -696,13 +703,20 @@ static int xs_tcp_send_request(struct rpc_task *task) xs_pktdump("packet data:", req->rq_svec->iov_base, req->rq_svec->iov_len); + /* Don't use zero copy if this is a resend. If the RPC call + * completes while the socket holds a reference to the pages, + * then we may end up resending corrupted data. + */ + if (task->tk_flags & RPC_TASK_SENT) + zerocopy = false; /* Continue transmitting the packet/record. We must be careful * to cope with writespace callbacks arriving _after_ we have * called sendmsg(). */ while (1) { status = xs_sendpages(transport->sock, - NULL, 0, xdr, req->rq_bytes_sent); + NULL, 0, xdr, req->rq_bytes_sent, + zerocopy); dprintk("RPC: xs_tcp_send_request(%u) = %d\n", xdr->len - req->rq_bytes_sent, status); -- cgit v1.2.3 From bd7e08189efba225bfa173372b05682ac141af88 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Mon, 21 Oct 2013 22:05:38 +0300 Subject: mei: nfc: fix memory leak in error path commit 4bff7208f332b2b1d7cf1338e50527441283a198 upstream. The flow may reach the err label without freeing cl and cl_info cl and cl_info weren't assigned to ndev->cl and cl_info so they weren't freed in mei_nfc_free called on error path Cc: Samuel Ortiz Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/nfc.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/misc/mei/nfc.c b/drivers/misc/mei/nfc.c index d0c6907dfd92..994ca4aff1a3 100644 --- a/drivers/misc/mei/nfc.c +++ b/drivers/misc/mei/nfc.c @@ -485,8 +485,11 @@ int mei_nfc_host_init(struct mei_device *dev) if (ndev->cl_info) return 0; - cl_info = mei_cl_allocate(dev); - cl = mei_cl_allocate(dev); + ndev->cl_info = mei_cl_allocate(dev); + ndev->cl = mei_cl_allocate(dev); + + cl = ndev->cl; + cl_info = ndev->cl_info; if (!cl || !cl_info) { ret = -ENOMEM; @@ -527,10 +530,9 @@ int mei_nfc_host_init(struct mei_device *dev) cl->device_uuid = mei_nfc_guid; + list_add_tail(&cl->device_link, &dev->device_list); - ndev->cl_info = cl_info; - ndev->cl = cl; ndev->req_id = 1; INIT_WORK(&ndev->init_work, mei_nfc_init); -- cgit v1.2.3 From 1316580f10273f89629cc197f59cc7ad96d9605e Mon Sep 17 00:00:00 2001 From: Julius Werner Date: Tue, 15 Oct 2013 17:45:00 -0700 Subject: usb: hub: Clear Port Reset Change during init/resume commit e92aee330837e4911553761490a8fb843f2053a6 upstream. This patch adds the Port Reset Change flag to the set of bits that are preemptively cleared on init/resume of a hub. In theory this bit should never be set unexpectedly... in practice it can still happen if BIOS, SMM or ACPI code plays around with USB devices without cleaning up correctly. This is especially dangerous for XHCI root hubs, which don't generate any more Port Status Change Events until all change bits are cleared, so this is a good precaution to have (similar to how it's already done for the Warm Port Reset Change flag). Signed-off-by: Julius Werner Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index c8b9fa0e9275..1424a8988849 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1129,6 +1129,11 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) usb_clear_port_feature(hub->hdev, port1, USB_PORT_FEAT_C_ENABLE); } + if (portchange & USB_PORT_STAT_C_RESET) { + need_debounce_delay = true; + usb_clear_port_feature(hub->hdev, port1, + USB_PORT_FEAT_C_RESET); + } if ((portchange & USB_PORT_STAT_C_BH_RESET) && hub_is_superspeed(hub->hdev)) { need_debounce_delay = true; -- cgit v1.2.3 From f3170c7a91c9520eeb6d2c13d0897172ebd6c228 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 18 Oct 2013 11:36:54 +0200 Subject: rt2800usb: slow down TX status polling commit 36165fd5b00bf8163f89c21bb16a3e9834555b10 upstream. Polling TX statuses too frequently has two negative effects. First is randomly peek CPU usage, causing overall system functioning delays. Second bad effect is that device is not able to fill TX statuses in H/W register on some workloads and we get lot of timeouts like below: ieee80211 phy4: rt2800usb_entry_txstatus_timeout: Warning - TX status timeout for entry 7 in queue 2 ieee80211 phy4: rt2800usb_entry_txstatus_timeout: Warning - TX status timeout for entry 7 in queue 2 ieee80211 phy4: rt2800usb_txdone: Warning - Got TX status for an empty queue 2, dropping This not only cause flood of messages in dmesg, but also bad throughput, since rate scaling algorithm can not work optimally. In the future, we should probably make polling interval be adjusted automatically, but for now just increase values, this make mentioned problems gone. Resolve: https://bugzilla.kernel.org/show_bug.cgi?id=62781 Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/rt2x00/rt2800usb.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index ac854d75bd6c..9ef0711a5cc1 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -148,6 +148,8 @@ static bool rt2800usb_txstatus_timeout(struct rt2x00_dev *rt2x00dev) return false; } +#define TXSTATUS_READ_INTERVAL 1000000 + static bool rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev, int urb_status, u32 tx_status) { @@ -176,8 +178,9 @@ static bool rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev, queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work); if (rt2800usb_txstatus_pending(rt2x00dev)) { - /* Read register after 250 us */ - hrtimer_start(&rt2x00dev->txstatus_timer, ktime_set(0, 250000), + /* Read register after 1 ms */ + hrtimer_start(&rt2x00dev->txstatus_timer, + ktime_set(0, TXSTATUS_READ_INTERVAL), HRTIMER_MODE_REL); return false; } @@ -202,8 +205,9 @@ static void rt2800usb_async_read_tx_status(struct rt2x00_dev *rt2x00dev) if (test_and_set_bit(TX_STATUS_READING, &rt2x00dev->flags)) return; - /* Read TX_STA_FIFO register after 500 us */ - hrtimer_start(&rt2x00dev->txstatus_timer, ktime_set(0, 500000), + /* Read TX_STA_FIFO register after 2 ms */ + hrtimer_start(&rt2x00dev->txstatus_timer, + ktime_set(0, 2*TXSTATUS_READ_INTERVAL), HRTIMER_MODE_REL); } -- cgit v1.2.3 From d4f2a840c79ca283a453b9cd6329ccb530cb0f70 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Mon, 28 Oct 2013 12:15:32 +0100 Subject: s390/vtime: correct idle time calculation commit 4560e7c3317c7a2b370e36dadd3a3bac2ed70818 upstream. Use the ACCESS_ONCE macro for both accesses to idle->sequence in the loops to calculate the idle time. If only one access uses the macro, the compiler is free to cache the value for the second access which can cause endless loops. Signed-off-by: Martin Schwidefsky Signed-off-by: Greg Kroah-Hartman --- arch/s390/kernel/smp.c | 4 ++-- arch/s390/kernel/vtime.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 4f977d0d25c2..14647fe09d0c 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -933,7 +933,7 @@ static ssize_t show_idle_count(struct device *dev, idle_count = ACCESS_ONCE(idle->idle_count); if (ACCESS_ONCE(idle->clock_idle_enter)) idle_count++; - } while ((sequence & 1) || (idle->sequence != sequence)); + } while ((sequence & 1) || (ACCESS_ONCE(idle->sequence) != sequence)); return sprintf(buf, "%llu\n", idle_count); } static DEVICE_ATTR(idle_count, 0444, show_idle_count, NULL); @@ -951,7 +951,7 @@ static ssize_t show_idle_time(struct device *dev, idle_time = ACCESS_ONCE(idle->idle_time); idle_enter = ACCESS_ONCE(idle->clock_idle_enter); idle_exit = ACCESS_ONCE(idle->clock_idle_exit); - } while ((sequence & 1) || (idle->sequence != sequence)); + } while ((sequence & 1) || (ACCESS_ONCE(idle->sequence) != sequence)); idle_time += idle_enter ? ((idle_exit ? : now) - idle_enter) : 0; return sprintf(buf, "%llu\n", idle_time >> 12); } diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c index 3fb09359eda6..737d50caa4fe 100644 --- a/arch/s390/kernel/vtime.c +++ b/arch/s390/kernel/vtime.c @@ -190,7 +190,7 @@ cputime64_t s390_get_idle_time(int cpu) sequence = ACCESS_ONCE(idle->sequence); idle_enter = ACCESS_ONCE(idle->clock_idle_enter); idle_exit = ACCESS_ONCE(idle->clock_idle_exit); - } while ((sequence & 1) || (idle->sequence != sequence)); + } while ((sequence & 1) || (ACCESS_ONCE(idle->sequence) != sequence)); return idle_enter ? ((idle_exit ?: now) - idle_enter) : 0; } -- cgit v1.2.3 From 7a4ca2033fd051599a862ab1d05707677143a9ef Mon Sep 17 00:00:00 2001 From: Junxiao Bi Date: Thu, 21 Nov 2013 14:31:56 -0800 Subject: configfs: fix race between dentry put and lookup commit 76ae281f6307331aa063288edb6422ae99f435f0 upstream. A race window in configfs, it starts from one dentry is UNHASHED and end before configfs_d_iput is called. In this window, if a lookup happen, since the original dentry was UNHASHED, so a new dentry will be allocated, and then in configfs_attach_attr(), sd->s_dentry will be updated to the new dentry. Then in configfs_d_iput(), BUG_ON(sd->s_dentry != dentry) will be triggered and system panic. sys_open: sys_close: ... fput dput dentry_kill __d_drop <--- dentry unhashed here, but sd->dentry still point to this dentry. lookup_real configfs_lookup configfs_attach_attr---> update sd->s_dentry to new allocated dentry here. d_kill configfs_d_iput <--- BUG_ON(sd->s_dentry != dentry) triggered here. To fix it, change configfs_d_iput to not update sd->s_dentry if sd->s_count > 2, that means there are another dentry is using the sd beside the one that is going to be put. Use configfs_dirent_lock in configfs_attach_attr to sync with configfs_d_iput. With the following steps, you can reproduce the bug. 1. enable ocfs2, this will mount configfs at /sys/kernel/config and fill configure in it. 2. run the following script. while [ 1 ]; do cat /sys/kernel/config/cluster/$your_cluster_name/idle_timeout_ms > /dev/null; done & while [ 1 ]; do cat /sys/kernel/config/cluster/$your_cluster_name/idle_timeout_ms > /dev/null; done & Signed-off-by: Junxiao Bi Cc: Joel Becker Cc: Al Viro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/configfs/dir.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index 7aabc6ad4e9b..fa38d076697d 100644 --- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c @@ -56,10 +56,19 @@ static void configfs_d_iput(struct dentry * dentry, struct configfs_dirent *sd = dentry->d_fsdata; if (sd) { - BUG_ON(sd->s_dentry != dentry); /* Coordinate with configfs_readdir */ spin_lock(&configfs_dirent_lock); - sd->s_dentry = NULL; + /* Coordinate with configfs_attach_attr where will increase + * sd->s_count and update sd->s_dentry to new allocated one. + * Only set sd->dentry to null when this dentry is the only + * sd owner. + * If not do so, configfs_d_iput may run just after + * configfs_attach_attr and set sd->s_dentry to null + * even it's still in use. + */ + if (atomic_read(&sd->s_count) <= 2) + sd->s_dentry = NULL; + spin_unlock(&configfs_dirent_lock); configfs_put(sd); } @@ -426,8 +435,11 @@ static int configfs_attach_attr(struct configfs_dirent * sd, struct dentry * den struct configfs_attribute * attr = sd->s_element; int error; + spin_lock(&configfs_dirent_lock); dentry->d_fsdata = configfs_get(sd); sd->s_dentry = dentry; + spin_unlock(&configfs_dirent_lock); + error = configfs_create(dentry, (attr->ca_mode & S_IALLUGO) | S_IFREG, configfs_init_file); if (error) { -- cgit v1.2.3 From a8e25439e373f9e2ec3ad7db6ddf0e32429d9ec0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 12 Nov 2013 15:06:49 -0800 Subject: cris: media platform drivers: fix build commit 72a0c5571351f5184195754d23db3e14495b2080 upstream. On cris arch, the functions below aren't defined: drivers/media/platform/sh_veu.c: In function 'sh_veu_reg_read': drivers/media/platform/sh_veu.c:228:2: error: implicit declaration of function 'ioread32' [-Werror=implicit-function-declaration] drivers/media/platform/sh_veu.c: In function 'sh_veu_reg_write': drivers/media/platform/sh_veu.c:234:2: error: implicit declaration of function 'iowrite32' [-Werror=implicit-function-declaration] drivers/media/platform/vsp1/vsp1.h: In function 'vsp1_read': drivers/media/platform/vsp1/vsp1.h:66:2: error: implicit declaration of function 'ioread32' [-Werror=implicit-function-declaration] drivers/media/platform/vsp1/vsp1.h: In function 'vsp1_write': drivers/media/platform/vsp1/vsp1.h:71:2: error: implicit declaration of function 'iowrite32' [-Werror=implicit-function-declaration] drivers/media/platform/vsp1/vsp1.h: In function 'vsp1_read': drivers/media/platform/vsp1/vsp1.h:66:2: error: implicit declaration of function 'ioread32' [-Werror=implicit-function-declaration] drivers/media/platform/vsp1/vsp1.h: In function 'vsp1_write': drivers/media/platform/vsp1/vsp1.h:71:2: error: implicit declaration of function 'iowrite32' [-Werror=implicit-function-declaration] drivers/media/platform/soc_camera/rcar_vin.c: In function 'rcar_vin_setup': drivers/media/platform/soc_camera/rcar_vin.c:284:3: error: implicit declaration of function 'iowrite32' [-Werror=implicit-function-declaration] drivers/media/platform/soc_camera/rcar_vin.c: In function 'rcar_vin_request_capture_stop': drivers/media/platform/soc_camera/rcar_vin.c:353:2: error: implicit declaration of function 'ioread32' [-Werror=implicit-function-declaration] Yet, they're available, as CONFIG_GENERIC_IOMAP is defined. What happens is that asm/io.h was not including asm-generic/iomap.h. Suggested-by: Ben Hutchings Signed-off-by: Mauro Carvalho Chehab Cc: Mikael Starvik Cc: Jesper Nilsson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- arch/cris/include/asm/io.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/cris/include/asm/io.h b/arch/cris/include/asm/io.h index ac12ae2b9286..db9a16c704f3 100644 --- a/arch/cris/include/asm/io.h +++ b/arch/cris/include/asm/io.h @@ -3,6 +3,7 @@ #include /* for __va, __pa */ #include +#include #include struct cris_io_operations -- cgit v1.2.3 From e3e129e720552f0dbc8ad363f8e85120219dac94 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 3 Jul 2013 15:05:02 -0700 Subject: dmi: add support for exact DMI matches in addition to substring matching commit 5017b2851373ee15c7035151853bb1448800cae2 upstream. dmi_match() considers a substring match to be a successful match. This is not always sufficient to distinguish between DMI data for different systems. Add support for exact string matching using strcmp() in addition to the substring matching using strstr(). The specific use case in the i915 driver is to allow us to use an exact match for D510MO, without also incorrectly matching D510MOV: { .ident = "Intel D510MO", .matches = { DMI_MATCH(DMI_BOARD_VENDOR, "Intel"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "D510MO"), }, } Signed-off-by: Jani Nikula Cc: Cc: Chris Wilson Cc: Cornel Panceac Acked-by: Daniel Vetter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/firmware/dmi_scan.c | 12 +++++++++--- include/linux/mod_devicetable.h | 6 ++++-- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index b95159b33c39..eb760a218da4 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c @@ -551,9 +551,15 @@ static bool dmi_matches(const struct dmi_system_id *dmi) int s = dmi->matches[i].slot; if (s == DMI_NONE) break; - if (dmi_ident[s] - && strstr(dmi_ident[s], dmi->matches[i].substr)) - continue; + if (dmi_ident[s]) { + if (!dmi->matches[i].exact_match && + strstr(dmi_ident[s], dmi->matches[i].substr)) + continue; + else if (dmi->matches[i].exact_match && + !strcmp(dmi_ident[s], dmi->matches[i].substr)) + continue; + } + /* No match */ return false; } diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index b508016fb76d..b3bd7e737e8b 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h @@ -456,7 +456,8 @@ enum dmi_field { }; struct dmi_strmatch { - unsigned char slot; + unsigned char slot:7; + unsigned char exact_match:1; char substr[79]; }; @@ -474,7 +475,8 @@ struct dmi_system_id { */ #define dmi_device_id dmi_system_id -#define DMI_MATCH(a, b) { a, b } +#define DMI_MATCH(a, b) { .slot = a, .substr = b } +#define DMI_EXACT_MATCH(a, b) { .slot = a, .substr = b, .exact_match = 1 } #define PLATFORM_NAME_SIZE 20 #define PLATFORM_MODULE_PREFIX "platform:" -- cgit v1.2.3 From 2df22e6f70c2b4f9204f47d6d471fd2a6691e393 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 3 Jul 2013 15:05:03 -0700 Subject: drm/i915: quirk away phantom LVDS on Intel's D510MO mainboard commit e5614f0c2d0f4d7f0b8ef745d34593baf2c5dbf8 upstream. This replaceable mainboard only has a VGA-out, yet it claims to also have a connected LVDS header. Addresses https://bugs.freedesktop.org/show_bug.cgi?id=63860 [jani.nikula@intel.com: use DMI_EXACT_MATCH for board name.] Signed-off-by: Chris Wilson Signed-off-by: Jani Nikula Reported-by: Cc: Cornel Panceac Acked-by: Daniel Vetter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_lvds.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 29412cc89c7a..5716cf340539 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -869,6 +869,14 @@ static const struct dmi_system_id intel_no_lvds[] = { DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Q900"), }, }, + { + .callback = intel_no_lvds_dmi_callback, + .ident = "Intel D510MO", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Intel"), + DMI_EXACT_MATCH(DMI_BOARD_NAME, "D510MO"), + }, + }, { } /* terminating entry */ }; -- cgit v1.2.3 From 215948b12e93e724923ea0cac10ffbb5a36a0a5a Mon Sep 17 00:00:00 2001 From: Rob Pearce Date: Sun, 27 Oct 2013 16:13:42 +0000 Subject: drm/i915: No LVDS hardware on Intel D410PT and D425KT commit 645378d85ee524e429aa4cf52806047b56cdc596 upstream. The Intel D410PT(LW) and D425KT Mini-ITX desktop boards both show up as having LVDS but the hardware is not populated. This patch adds them to the list of such systems. Patch is against 3.11.4 v2: Patch revised to match the D425KT exactly as the D425KTW does have LVDS. According to Intel's documentation, the D410PTL and D410PLTW don't. Signed-off-by: Rob Pearce [danvet: Pimp commit message to my liking and add cc: stable.] Signed-off-by: Daniel Vetter Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_lvds.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 5716cf340539..f77d42f74427 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -869,6 +869,22 @@ static const struct dmi_system_id intel_no_lvds[] = { DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Q900"), }, }, + { + .callback = intel_no_lvds_dmi_callback, + .ident = "Intel D410PT", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Intel"), + DMI_MATCH(DMI_BOARD_NAME, "D410PT"), + }, + }, + { + .callback = intel_no_lvds_dmi_callback, + .ident = "Intel D425KT", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Intel"), + DMI_EXACT_MATCH(DMI_BOARD_NAME, "D425KT"), + }, + }, { .callback = intel_no_lvds_dmi_callback, .ident = "Intel D510MO", -- cgit v1.2.3 From 43d8b1ef8250705d07fadceefa44f91b32e08328 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 29 Nov 2013 11:12:03 -0800 Subject: Linux 3.10.21 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index ba784b7b0f51..c0635fbab87f 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 10 -SUBLEVEL = 20 +SUBLEVEL = 21 EXTRAVERSION = NAME = TOSSUG Baby Fish -- cgit v1.2.3 From c44d83ec7018dd23255c23897492b3c8d43785df Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Wed, 6 Nov 2013 23:38:59 +0100 Subject: parisc: sticon - unbreak on 64bit kernel commit 0219132fe7c26574371232b50db085573f6fbd3f upstream. STI text console (sticon) was broken on 64bit machines with more than 4GB RAM and this lead in some cases to a kernel crash. Since sticon uses the 32bit STI API it needs to keep pointers to memory below 4GB. But on a 64bit kernel some memory regions (e.g. the kernel stack) might be above 4GB which then may crash the kernel in the STI functions. Additionally sticon didn't selected the built-in framebuffer fonts by default. This is now fixed. On a side-note: Theoretically we could enhance the sticon driver to use the 64bit STI API. But - beside the fact that some machines don't provide a 64bit STI ROM - this would just add complexity. Signed-off-by: Helge Deller Signed-off-by: Greg Kroah-Hartman --- drivers/video/console/sticore.c | 166 +++++++++++++++++++++++++--------------- drivers/video/sticore.h | 62 ++++++++++++--- drivers/video/stifb.c | 10 +-- 3 files changed, 158 insertions(+), 80 deletions(-) diff --git a/drivers/video/console/sticore.c b/drivers/video/console/sticore.c index 35687fd56456..4ad24f2c6472 100644 --- a/drivers/video/console/sticore.c +++ b/drivers/video/console/sticore.c @@ -3,7 +3,7 @@ * core code for console driver using HP's STI firmware * * Copyright (C) 2000 Philipp Rumpf - * Copyright (C) 2001-2003 Helge Deller + * Copyright (C) 2001-2013 Helge Deller * Copyright (C) 2001-2002 Thomas Bogendoerfer * * TODO: @@ -30,7 +30,7 @@ #include "../sticore.h" -#define STI_DRIVERVERSION "Version 0.9a" +#define STI_DRIVERVERSION "Version 0.9b" static struct sti_struct *default_sti __read_mostly; @@ -73,28 +73,34 @@ static const struct sti_init_flags default_init_flags = { static int sti_init_graph(struct sti_struct *sti) { - struct sti_init_inptr_ext inptr_ext = { 0, }; - struct sti_init_inptr inptr = { - .text_planes = 3, /* # of text planes (max 3 for STI) */ - .ext_ptr = STI_PTR(&inptr_ext) - }; - struct sti_init_outptr outptr = { 0, }; + struct sti_init_inptr *inptr = &sti->sti_data->init_inptr; + struct sti_init_inptr_ext *inptr_ext = &sti->sti_data->init_inptr_ext; + struct sti_init_outptr *outptr = &sti->sti_data->init_outptr; unsigned long flags; - int ret; + int ret, err; spin_lock_irqsave(&sti->lock, flags); - ret = STI_CALL(sti->init_graph, &default_init_flags, &inptr, - &outptr, sti->glob_cfg); + memset(inptr, 0, sizeof(*inptr)); + inptr->text_planes = 3; /* # of text planes (max 3 for STI) */ + memset(inptr_ext, 0, sizeof(*inptr_ext)); + inptr->ext_ptr = STI_PTR(inptr_ext); + outptr->errno = 0; + + ret = sti_call(sti, sti->init_graph, &default_init_flags, inptr, + outptr, sti->glob_cfg); + + if (ret >= 0) + sti->text_planes = outptr->text_planes; + err = outptr->errno; spin_unlock_irqrestore(&sti->lock, flags); if (ret < 0) { - printk(KERN_ERR "STI init_graph failed (ret %d, errno %d)\n",ret,outptr.errno); + pr_err("STI init_graph failed (ret %d, errno %d)\n", ret, err); return -1; } - sti->text_planes = outptr.text_planes; return 0; } @@ -104,16 +110,18 @@ static const struct sti_conf_flags default_conf_flags = { static void sti_inq_conf(struct sti_struct *sti) { - struct sti_conf_inptr inptr = { 0, }; + struct sti_conf_inptr *inptr = &sti->sti_data->inq_inptr; + struct sti_conf_outptr *outptr = &sti->sti_data->inq_outptr; unsigned long flags; s32 ret; - sti->outptr.ext_ptr = STI_PTR(&sti->outptr_ext); + outptr->ext_ptr = STI_PTR(&sti->sti_data->inq_outptr_ext); do { spin_lock_irqsave(&sti->lock, flags); - ret = STI_CALL(sti->inq_conf, &default_conf_flags, - &inptr, &sti->outptr, sti->glob_cfg); + memset(inptr, 0, sizeof(*inptr)); + ret = sti_call(sti, sti->inq_conf, &default_conf_flags, + inptr, outptr, sti->glob_cfg); spin_unlock_irqrestore(&sti->lock, flags); } while (ret == 1); } @@ -126,7 +134,8 @@ static const struct sti_font_flags default_font_flags = { void sti_putc(struct sti_struct *sti, int c, int y, int x) { - struct sti_font_inptr inptr = { + struct sti_font_inptr *inptr = &sti->sti_data->font_inptr; + struct sti_font_inptr inptr_default = { .font_start_addr= STI_PTR(sti->font->raw), .index = c_index(sti, c), .fg_color = c_fg(sti, c), @@ -134,14 +143,15 @@ sti_putc(struct sti_struct *sti, int c, int y, int x) .dest_x = x * sti->font_width, .dest_y = y * sti->font_height, }; - struct sti_font_outptr outptr = { 0, }; + struct sti_font_outptr *outptr = &sti->sti_data->font_outptr; s32 ret; unsigned long flags; do { spin_lock_irqsave(&sti->lock, flags); - ret = STI_CALL(sti->font_unpmv, &default_font_flags, - &inptr, &outptr, sti->glob_cfg); + *inptr = inptr_default; + ret = sti_call(sti, sti->font_unpmv, &default_font_flags, + inptr, outptr, sti->glob_cfg); spin_unlock_irqrestore(&sti->lock, flags); } while (ret == 1); } @@ -156,7 +166,8 @@ void sti_set(struct sti_struct *sti, int src_y, int src_x, int height, int width, u8 color) { - struct sti_blkmv_inptr inptr = { + struct sti_blkmv_inptr *inptr = &sti->sti_data->blkmv_inptr; + struct sti_blkmv_inptr inptr_default = { .fg_color = color, .bg_color = color, .src_x = src_x, @@ -166,14 +177,15 @@ sti_set(struct sti_struct *sti, int src_y, int src_x, .width = width, .height = height, }; - struct sti_blkmv_outptr outptr = { 0, }; + struct sti_blkmv_outptr *outptr = &sti->sti_data->blkmv_outptr; s32 ret; unsigned long flags; do { spin_lock_irqsave(&sti->lock, flags); - ret = STI_CALL(sti->block_move, &clear_blkmv_flags, - &inptr, &outptr, sti->glob_cfg); + *inptr = inptr_default; + ret = sti_call(sti, sti->block_move, &clear_blkmv_flags, + inptr, outptr, sti->glob_cfg); spin_unlock_irqrestore(&sti->lock, flags); } while (ret == 1); } @@ -182,7 +194,8 @@ void sti_clear(struct sti_struct *sti, int src_y, int src_x, int height, int width, int c) { - struct sti_blkmv_inptr inptr = { + struct sti_blkmv_inptr *inptr = &sti->sti_data->blkmv_inptr; + struct sti_blkmv_inptr inptr_default = { .fg_color = c_fg(sti, c), .bg_color = c_bg(sti, c), .src_x = src_x * sti->font_width, @@ -192,14 +205,15 @@ sti_clear(struct sti_struct *sti, int src_y, int src_x, .width = width * sti->font_width, .height = height* sti->font_height, }; - struct sti_blkmv_outptr outptr = { 0, }; + struct sti_blkmv_outptr *outptr = &sti->sti_data->blkmv_outptr; s32 ret; unsigned long flags; do { spin_lock_irqsave(&sti->lock, flags); - ret = STI_CALL(sti->block_move, &clear_blkmv_flags, - &inptr, &outptr, sti->glob_cfg); + *inptr = inptr_default; + ret = sti_call(sti, sti->block_move, &clear_blkmv_flags, + inptr, outptr, sti->glob_cfg); spin_unlock_irqrestore(&sti->lock, flags); } while (ret == 1); } @@ -212,7 +226,8 @@ void sti_bmove(struct sti_struct *sti, int src_y, int src_x, int dst_y, int dst_x, int height, int width) { - struct sti_blkmv_inptr inptr = { + struct sti_blkmv_inptr *inptr = &sti->sti_data->blkmv_inptr; + struct sti_blkmv_inptr inptr_default = { .src_x = src_x * sti->font_width, .src_y = src_y * sti->font_height, .dest_x = dst_x * sti->font_width, @@ -220,14 +235,15 @@ sti_bmove(struct sti_struct *sti, int src_y, int src_x, .width = width * sti->font_width, .height = height* sti->font_height, }; - struct sti_blkmv_outptr outptr = { 0, }; + struct sti_blkmv_outptr *outptr = &sti->sti_data->blkmv_outptr; s32 ret; unsigned long flags; do { spin_lock_irqsave(&sti->lock, flags); - ret = STI_CALL(sti->block_move, &default_blkmv_flags, - &inptr, &outptr, sti->glob_cfg); + *inptr = inptr_default; + ret = sti_call(sti, sti->block_move, &default_blkmv_flags, + inptr, outptr, sti->glob_cfg); spin_unlock_irqrestore(&sti->lock, flags); } while (ret == 1); } @@ -284,7 +300,7 @@ __setup("sti=", sti_setup); -static char *font_name[MAX_STI_ROMS] = { "VGA8x16", }; +static char *font_name[MAX_STI_ROMS]; static int font_index[MAX_STI_ROMS], font_height[MAX_STI_ROMS], font_width[MAX_STI_ROMS]; @@ -389,10 +405,10 @@ static void sti_dump_outptr(struct sti_struct *sti) "%d used bits\n" "%d planes\n" "attributes %08x\n", - sti->outptr.bits_per_pixel, - sti->outptr.bits_used, - sti->outptr.planes, - sti->outptr.attributes)); + sti->sti_data->inq_outptr.bits_per_pixel, + sti->sti_data->inq_outptr.bits_used, + sti->sti_data->inq_outptr.planes, + sti->sti_data->inq_outptr.attributes)); } static int sti_init_glob_cfg(struct sti_struct *sti, unsigned long rom_address, @@ -402,24 +418,21 @@ static int sti_init_glob_cfg(struct sti_struct *sti, unsigned long rom_address, struct sti_glob_cfg_ext *glob_cfg_ext; void *save_addr; void *sti_mem_addr; - const int save_addr_size = 1024; /* XXX */ - int i; + int i, size; - if (!sti->sti_mem_request) + if (sti->sti_mem_request < 256) sti->sti_mem_request = 256; /* STI default */ - glob_cfg = kzalloc(sizeof(*sti->glob_cfg), GFP_KERNEL); - glob_cfg_ext = kzalloc(sizeof(*glob_cfg_ext), GFP_KERNEL); - save_addr = kzalloc(save_addr_size, GFP_KERNEL); - sti_mem_addr = kzalloc(sti->sti_mem_request, GFP_KERNEL); + size = sizeof(struct sti_all_data) + sti->sti_mem_request - 256; - if (!(glob_cfg && glob_cfg_ext && save_addr && sti_mem_addr)) { - kfree(glob_cfg); - kfree(glob_cfg_ext); - kfree(save_addr); - kfree(sti_mem_addr); + sti->sti_data = kzalloc(size, STI_LOWMEM); + if (!sti->sti_data) return -ENOMEM; - } + + glob_cfg = &sti->sti_data->glob_cfg; + glob_cfg_ext = &sti->sti_data->glob_cfg_ext; + save_addr = &sti->sti_data->save_addr; + sti_mem_addr = &sti->sti_data->sti_mem_addr; glob_cfg->ext_ptr = STI_PTR(glob_cfg_ext); glob_cfg->save_addr = STI_PTR(save_addr); @@ -475,32 +488,31 @@ static int sti_init_glob_cfg(struct sti_struct *sti, unsigned long rom_address, return 0; } -#ifdef CONFIG_FB +#ifdef CONFIG_FONTS static struct sti_cooked_font * sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name) { - const struct font_desc *fbfont; + const struct font_desc *fbfont = NULL; unsigned int size, bpc; void *dest; struct sti_rom_font *nf; struct sti_cooked_font *cooked_font; - if (!fbfont_name || !strlen(fbfont_name)) - return NULL; - fbfont = find_font(fbfont_name); + if (fbfont_name && strlen(fbfont_name)) + fbfont = find_font(fbfont_name); if (!fbfont) fbfont = get_default_font(1024,768, ~(u32)0, ~(u32)0); if (!fbfont) return NULL; - DPRINTK((KERN_DEBUG "selected %dx%d fb-font %s\n", - fbfont->width, fbfont->height, fbfont->name)); + pr_info("STI selected %dx%d framebuffer font %s for sticon\n", + fbfont->width, fbfont->height, fbfont->name); bpc = ((fbfont->width+7)/8) * fbfont->height; size = bpc * 256; size += sizeof(struct sti_rom_font); - nf = kzalloc(size, GFP_KERNEL); + nf = kzalloc(size, STI_LOWMEM); if (!nf) return NULL; @@ -637,7 +649,7 @@ static void *sti_bmode_font_raw(struct sti_cooked_font *f) unsigned char *n, *p, *q; int size = f->raw->bytes_per_char*256+sizeof(struct sti_rom_font); - n = kzalloc (4*size, GFP_KERNEL); + n = kzalloc(4*size, STI_LOWMEM); if (!n) return NULL; p = n + 3; @@ -673,7 +685,7 @@ static struct sti_rom *sti_get_bmode_rom (unsigned long address) sti_bmode_rom_copy(address + BMODE_LAST_ADDR_OFFS, sizeof(size), &size); size = (size+3) / 4; - raw = kmalloc(size, GFP_KERNEL); + raw = kmalloc(size, STI_LOWMEM); if (raw) { sti_bmode_rom_copy(address, size, raw); memmove (&raw->res004, &raw->type[0], 0x3c); @@ -707,7 +719,7 @@ static struct sti_rom *sti_get_wmode_rom(unsigned long address) /* read the ROM size directly from the struct in ROM */ size = gsc_readl(address + offsetof(struct sti_rom,last_addr)); - raw = kmalloc(size, GFP_KERNEL); + raw = kmalloc(size, STI_LOWMEM); if (raw) sti_rom_copy(address, size, raw); @@ -743,6 +755,10 @@ static int sti_read_rom(int wordmode, struct sti_struct *sti, address = (unsigned long) STI_PTR(raw); + pr_info("STI ROM supports 32 %sbit firmware functions.\n", + raw->alt_code_type == ALT_CODE_TYPE_PA_RISC_64 + ? "and 64 " : ""); + sti->font_unpmv = address + (raw->font_unpmv & 0x03ffffff); sti->block_move = address + (raw->block_move & 0x03ffffff); sti->init_graph = address + (raw->init_graph & 0x03ffffff); @@ -901,7 +917,8 @@ test_rom: sti_dump_globcfg(sti->glob_cfg, sti->sti_mem_request); sti_dump_outptr(sti); - printk(KERN_INFO " graphics card name: %s\n", sti->outptr.dev_name ); + pr_info(" graphics card name: %s\n", + sti->sti_data->inq_outptr.dev_name); sti_roms[num_sti_roms] = sti; num_sti_roms++; @@ -1073,6 +1090,29 @@ struct sti_struct * sti_get_rom(unsigned int index) } EXPORT_SYMBOL(sti_get_rom); + +int sti_call(const struct sti_struct *sti, unsigned long func, + const void *flags, void *inptr, void *outptr, + struct sti_glob_cfg *glob_cfg) +{ + unsigned long _flags = STI_PTR(flags); + unsigned long _inptr = STI_PTR(inptr); + unsigned long _outptr = STI_PTR(outptr); + unsigned long _glob_cfg = STI_PTR(glob_cfg); + int ret; + +#ifdef CONFIG_64BIT + /* Check for overflow when using 32bit STI on 64bit kernel. */ + if (WARN_ONCE(_flags>>32 || _inptr>>32 || _outptr>>32 || _glob_cfg>>32, + "Out of 32bit-range pointers!")) + return -1; +#endif + + ret = pdc_sti_call(func, _flags, _inptr, _outptr, _glob_cfg); + + return ret; +} + MODULE_AUTHOR("Philipp Rumpf, Helge Deller, Thomas Bogendoerfer"); MODULE_DESCRIPTION("Core STI driver for HP's NGLE series graphics cards in HP PARISC machines"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/video/sticore.h b/drivers/video/sticore.h index addf7b615ef8..af1619536ac8 100644 --- a/drivers/video/sticore.h +++ b/drivers/video/sticore.h @@ -18,6 +18,9 @@ #define STI_FONT_HPROMAN8 1 #define STI_FONT_KANA8 2 +#define ALT_CODE_TYPE_UNKNOWN 0x00 /* alt code type values */ +#define ALT_CODE_TYPE_PA_RISC_64 0x01 + /* The latency of the STI functions cannot really be reduced by setting * this to 0; STI doesn't seem to be designed to allow calling a different * function (or the same function with different arguments) after a @@ -40,14 +43,6 @@ #define STI_PTR(p) ( virt_to_phys(p) ) #define PTR_STI(p) ( phys_to_virt((unsigned long)p) ) -#define STI_CALL(func, flags, inptr, outptr, glob_cfg) \ - ({ \ - pdc_sti_call( func, STI_PTR(flags), \ - STI_PTR(inptr), \ - STI_PTR(outptr), \ - STI_PTR(glob_cfg)); \ - }) - #define sti_onscreen_x(sti) (sti->glob_cfg->onscreen_x) #define sti_onscreen_y(sti) (sti->glob_cfg->onscreen_y) @@ -56,6 +51,12 @@ #define sti_font_x(sti) (PTR_STI(sti->font)->width) #define sti_font_y(sti) (PTR_STI(sti->font)->height) +#ifdef CONFIG_64BIT +#define STI_LOWMEM (GFP_KERNEL | GFP_DMA) +#else +#define STI_LOWMEM (GFP_KERNEL) +#endif + /* STI function configuration structs */ @@ -306,6 +307,34 @@ struct sti_blkmv_outptr { }; +/* sti_all_data is an internal struct which needs to be allocated in + * low memory (< 4GB) if STI is used with 32bit STI on a 64bit kernel */ + +struct sti_all_data { + struct sti_glob_cfg glob_cfg; + struct sti_glob_cfg_ext glob_cfg_ext; + + struct sti_conf_inptr inq_inptr; + struct sti_conf_outptr inq_outptr; /* configuration */ + struct sti_conf_outptr_ext inq_outptr_ext; + + struct sti_init_inptr_ext init_inptr_ext; + struct sti_init_inptr init_inptr; + struct sti_init_outptr init_outptr; + + struct sti_blkmv_inptr blkmv_inptr; + struct sti_blkmv_outptr blkmv_outptr; + + struct sti_font_inptr font_inptr; + struct sti_font_outptr font_outptr; + + /* leave as last entries */ + unsigned long save_addr[1024 / sizeof(unsigned long)]; + /* min 256 bytes which is STI default, max sti->sti_mem_request */ + unsigned long sti_mem_addr[256 / sizeof(unsigned long)]; + /* do not add something below here ! */ +}; + /* internal generic STI struct */ struct sti_struct { @@ -330,11 +359,9 @@ struct sti_struct { region_t regions[STI_REGION_MAX]; unsigned long regions_phys[STI_REGION_MAX]; - struct sti_glob_cfg *glob_cfg; - struct sti_cooked_font *font; /* ptr to selected font (cooked) */ + struct sti_glob_cfg *glob_cfg; /* points into sti_all_data */ - struct sti_conf_outptr outptr; /* configuration */ - struct sti_conf_outptr_ext outptr_ext; + struct sti_cooked_font *font; /* ptr to selected font (cooked) */ struct pci_dev *pd; @@ -343,6 +370,9 @@ struct sti_struct { /* pointer to the fb_info where this STI device is used */ struct fb_info *info; + + /* pointer to all internal data */ + struct sti_all_data *sti_data; }; @@ -350,6 +380,14 @@ struct sti_struct { struct sti_struct *sti_get_rom(unsigned int index); /* 0: default sti */ + +/* sticore main function to call STI firmware */ + +int sti_call(const struct sti_struct *sti, unsigned long func, + const void *flags, void *inptr, void *outptr, + struct sti_glob_cfg *glob_cfg); + + /* functions to call the STI ROM directly */ void sti_putc(struct sti_struct *sti, int c, int y, int x); diff --git a/drivers/video/stifb.c b/drivers/video/stifb.c index 876648e15e9d..019a1feef995 100644 --- a/drivers/video/stifb.c +++ b/drivers/video/stifb.c @@ -1101,6 +1101,7 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref) var = &info->var; fb->sti = sti; + dev_name = sti->sti_data->inq_outptr.dev_name; /* store upper 32bits of the graphics id */ fb->id = fb->sti->graphics_id[0]; @@ -1114,11 +1115,11 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref) Since this driver only supports standard mode, we check if the device name contains the string "DX" and tell the user how to reconfigure the card. */ - if (strstr(sti->outptr.dev_name, "DX")) { + if (strstr(dev_name, "DX")) { printk(KERN_WARNING "WARNING: stifb framebuffer driver does not support '%s' in double-buffer mode.\n" "WARNING: Please disable the double-buffer mode in IPL menu (the PARISC-BIOS).\n", - sti->outptr.dev_name); + dev_name); goto out_err0; } /* fall though */ @@ -1130,7 +1131,7 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref) break; default: printk(KERN_WARNING "stifb: '%s' (id: 0x%08x) not supported.\n", - sti->outptr.dev_name, fb->id); + dev_name, fb->id); goto out_err0; } @@ -1154,7 +1155,6 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref) fb->id = S9000_ID_A1659A; break; case S9000_ID_TIMBER: /* HP9000/710 Any (may be a grayscale device) */ - dev_name = fb->sti->outptr.dev_name; if (strstr(dev_name, "GRAYSCALE") || strstr(dev_name, "Grayscale") || strstr(dev_name, "grayscale")) @@ -1290,7 +1290,7 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref) var->xres, var->yres, var->bits_per_pixel, - sti->outptr.dev_name, + dev_name, fb->id, fix->mmio_start); -- cgit v1.2.3 From 6ca235a5703b6d30df5d4c8d47d6f8d6695d46fd Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Thu, 17 Oct 2013 09:18:38 +0200 Subject: ARM: OMAP2+: irq, AM33XX add missing register check commit 0bebda684857f76548ea48c8886785198701d8d3 upstream. am33xx has a INTC_PENDING_IRQ3 register that is not checked for pending interrupts. This patch adds AM33XX to the ifdef of SOCs that have to check this register. Signed-off-by: Markus Pargmann Signed-off-by: Tony Lindgren Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-omap2/irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c index 3926f370448f..e022a869bff2 100644 --- a/arch/arm/mach-omap2/irq.c +++ b/arch/arm/mach-omap2/irq.c @@ -233,7 +233,7 @@ static inline void omap_intc_handle_irq(void __iomem *base_addr, struct pt_regs goto out; irqnr = readl_relaxed(base_addr + 0xd8); -#ifdef CONFIG_SOC_TI81XX +#if IS_ENABLED(CONFIG_SOC_TI81XX) || IS_ENABLED(CONFIG_SOC_AM33XX) if (irqnr) goto out; irqnr = readl_relaxed(base_addr + 0xf8); -- cgit v1.2.3 From 853e96428c8e8f2ac95e1b6a144114340694a244 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 16 Oct 2013 00:09:02 +0100 Subject: ARM: sa11x0/assabet: ensure CS2 is configured appropriately commit f3964fe1c9d9a887d65faf594669852e4dec46e0 upstream. The CS2 region contains the Assabet board configuration and status registers, which are 32-bit. Unfortunately, some boot loaders do not configure this region correctly, leaving it setup as a 16-bit region. Fix this. Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-sa1100/assabet.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c index e838ba27e443..c9808c684152 100644 --- a/arch/arm/mach-sa1100/assabet.c +++ b/arch/arm/mach-sa1100/assabet.c @@ -512,6 +512,9 @@ static void __init assabet_map_io(void) * Its called GPCLKR0 in my SA1110 manual. */ Ser1SDCR0 |= SDCR0_SUS; + MSC1 = (MSC1 & ~0xffff) | + MSC_NonBrst | MSC_32BitStMem | + MSC_RdAcc(2) | MSC_WrAcc(2) | MSC_Rec(0); if (!machine_has_neponset()) sa1100_register_uart_fns(&assabet_port_fns); -- cgit v1.2.3 From 45a8ae89ee0f4d4b33f75b2e619f4112810ff822 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Mon, 4 Nov 2013 11:42:29 +0100 Subject: ARM: 7876/1: clear Thumb-2 IT state on exception handling commit e16b31bf47738f4498d7ce632e12d7d2a6a2492a upstream. The exception handling code fails to clear the IT state, potentially leading to incorrect execution of the fixup if the size of the IT block is more than one. Let fixup_exception do the IT sanitizing if a fixup has been found, and restore CPSR from the stack when returning from a data abort. Cc: Will Deacon Reviewed-by: Catalin Marinas Signed-off-by: Marc Zyngier Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/kernel/entry-armv.S | 1 + arch/arm/mm/extable.c | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index d43c7e54ec6c..32640ae7750f 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -192,6 +192,7 @@ __dabt_svc: svc_entry mov r2, sp dabt_helper + THUMB( ldr r5, [sp, #S_PSR] ) @ potentially updated CPSR svc_exit r5 @ return from exception UNWIND(.fnend ) ENDPROC(__dabt_svc) diff --git a/arch/arm/mm/extable.c b/arch/arm/mm/extable.c index 9d285626bc7d..312e15e6d00b 100644 --- a/arch/arm/mm/extable.c +++ b/arch/arm/mm/extable.c @@ -9,8 +9,13 @@ int fixup_exception(struct pt_regs *regs) const struct exception_table_entry *fixup; fixup = search_exception_tables(instruction_pointer(regs)); - if (fixup) + if (fixup) { regs->ARM_pc = fixup->fixup; +#ifdef CONFIG_THUMB2_KERNEL + /* Clear the IT state to avoid nasty surprises in the fixup */ + regs->ARM_cpsr &= ~PSR_IT_MASK; +#endif + } return fixup != NULL; } -- cgit v1.2.3 From 208a11c4412dee65ccf76503fb980d7fb3c5c743 Mon Sep 17 00:00:00 2001 From: Jonathan Austin Date: Thu, 29 Aug 2013 18:41:11 +0100 Subject: ARM: integrator_cp: Set LCD{0,1} enable lines when turning on CLCD commit 30aeadd44deea3f3b0df45b9a70ee0fd5f8d6dc2 upstream. This turns on the internal integrator LCD display(s). It seems that the code to do this got lost in refactoring of the CLCD driver. Signed-off-by: Jonathan Austin Acked-by: Linus Walleij Signed-off-by: Olof Johansson Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-integrator/integrator_cp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c index 8c60fcb08a98..2f4c92486cfa 100644 --- a/arch/arm/mach-integrator/integrator_cp.c +++ b/arch/arm/mach-integrator/integrator_cp.c @@ -199,7 +199,8 @@ static struct mmci_platform_data mmc_data = { static void cp_clcd_enable(struct clcd_fb *fb) { struct fb_var_screeninfo *var = &fb->fb.var; - u32 val = CM_CTRL_STATIC1 | CM_CTRL_STATIC2; + u32 val = CM_CTRL_STATIC1 | CM_CTRL_STATIC2 + | CM_CTRL_LCDEN0 | CM_CTRL_LCDEN1; if (var->bits_per_pixel <= 8 || (var->bits_per_pixel == 16 && var->green.length == 5)) -- cgit v1.2.3 From 54f830b7337ed016b6708cf5a2ac297d4cee227d Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 16 Oct 2013 11:56:14 +0200 Subject: ARM: at91: fix hanged boot due to early rtc-interrupt commit 6de714c21a8ea315fffba6a93bbe537f4c1bf4f0 upstream. Make sure the RTC-interrupts are masked at boot by adding a new helper function to be used at SOC-init. This fixes hanged boot on all AT91 SOCs with an RTC (but RM9200), for example, after a reset during an RTC-update or if an RTC-alarm goes off after shutdown (e.g. when using RTC wakeup). The RTC and RTT-peripherals are powered by backup power (VDDBU) (on all AT91 SOCs but RM9200) and are not reset on wake-up, user, watchdog or software reset. This means that their interrupts may be enabled during early boot if, for example, they where not disabled during a previous shutdown (e.g. due to a buggy driver or a non-clean shutdown such as a user reset). Furthermore, an RTC or RTT-alarm may also be active. The RTC and RTT-interrupts use the shared system-interrupt line, which is also used by the PIT, and if an interrupt occurs before a handler (e.g. RTC-driver) has been installed this leads to the system interrupt being disabled and prevents the system from booting. Note that when boot hangs due to an early RTC or RTT-interrupt, the only way to get the system to start again is to remove the backup power (e.g. battery) or to disable the interrupt manually from the bootloader. In particular, a user reset is not sufficient. Signed-off-by: Johan Hovold Signed-off-by: Nicolas Ferre Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-at91/Makefile | 2 +- arch/arm/mach-at91/at91sam9g45.c | 2 ++ arch/arm/mach-at91/at91sam9n12.c | 6 ++++ arch/arm/mach-at91/at91sam9rl.c | 2 ++ arch/arm/mach-at91/at91sam9x5.c | 6 ++++ arch/arm/mach-at91/generic.h | 1 + arch/arm/mach-at91/include/mach/at91sam9n12.h | 5 +++ arch/arm/mach-at91/include/mach/at91sam9x5.h | 5 +++ arch/arm/mach-at91/include/mach/sama5d3.h | 5 +++ arch/arm/mach-at91/sama5d3.c | 6 ++++ arch/arm/mach-at91/sysirq_mask.c | 47 +++++++++++++++++++++++++++ 11 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-at91/sysirq_mask.c diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index 788562dccb43..c336efdf8f13 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile @@ -2,7 +2,7 @@ # Makefile for the linux kernel. # -obj-y := irq.o gpio.o setup.o +obj-y := irq.o gpio.o setup.o sysirq_mask.o obj-m := obj-n := obj- := diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c index 8b7fce067652..eebfe3818812 100644 --- a/arch/arm/mach-at91/at91sam9g45.c +++ b/arch/arm/mach-at91/at91sam9g45.c @@ -376,6 +376,8 @@ static void __init at91sam9g45_initialize(void) arm_pm_restart = at91sam9g45_restart; at91_extern_irq = (1 << AT91SAM9G45_ID_IRQ0); + at91_sysirq_mask_rtc(AT91SAM9G45_BASE_RTC); + /* Register GPIO subsystem */ at91_gpio_init(at91sam9g45_gpio, 5); } diff --git a/arch/arm/mach-at91/at91sam9n12.c b/arch/arm/mach-at91/at91sam9n12.c index c7d670d11802..4d6001c355f5 100644 --- a/arch/arm/mach-at91/at91sam9n12.c +++ b/arch/arm/mach-at91/at91sam9n12.c @@ -223,7 +223,13 @@ static void __init at91sam9n12_map_io(void) at91_init_sram(0, AT91SAM9N12_SRAM_BASE, AT91SAM9N12_SRAM_SIZE); } +static void __init at91sam9n12_initialize(void) +{ + at91_sysirq_mask_rtc(AT91SAM9N12_BASE_RTC); +} + AT91_SOC_START(at91sam9n12) .map_io = at91sam9n12_map_io, .register_clocks = at91sam9n12_register_clocks, + .init = at91sam9n12_initialize, AT91_SOC_END diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c index f77fae5591bc..297613944c93 100644 --- a/arch/arm/mach-at91/at91sam9rl.c +++ b/arch/arm/mach-at91/at91sam9rl.c @@ -295,6 +295,8 @@ static void __init at91sam9rl_initialize(void) arm_pm_restart = at91sam9_alt_restart; at91_extern_irq = (1 << AT91SAM9RL_ID_IRQ0); + at91_sysirq_mask_rtc(AT91SAM9RL_BASE_RTC); + /* Register GPIO subsystem */ at91_gpio_init(at91sam9rl_gpio, 4); } diff --git a/arch/arm/mach-at91/at91sam9x5.c b/arch/arm/mach-at91/at91sam9x5.c index e631fec040ce..7b4f848312eb 100644 --- a/arch/arm/mach-at91/at91sam9x5.c +++ b/arch/arm/mach-at91/at91sam9x5.c @@ -318,6 +318,11 @@ static void __init at91sam9x5_map_io(void) at91_init_sram(0, AT91SAM9X5_SRAM_BASE, AT91SAM9X5_SRAM_SIZE); } +static void __init at91sam9x5_initialize(void) +{ + at91_sysirq_mask_rtc(AT91SAM9X5_BASE_RTC); +} + /* -------------------------------------------------------------------- * Interrupt initialization * -------------------------------------------------------------------- */ @@ -325,4 +330,5 @@ static void __init at91sam9x5_map_io(void) AT91_SOC_START(at91sam9x5) .map_io = at91sam9x5_map_io, .register_clocks = at91sam9x5_register_clocks, + .init = at91sam9x5_initialize, AT91_SOC_END diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h index 78ab06548658..325a4d1fb736 100644 --- a/arch/arm/mach-at91/generic.h +++ b/arch/arm/mach-at91/generic.h @@ -33,6 +33,7 @@ extern int __init at91_aic_of_init(struct device_node *node, struct device_node *parent); extern int __init at91_aic5_of_init(struct device_node *node, struct device_node *parent); +extern void __init at91_sysirq_mask_rtc(u32 rtc_base); /* Timer */ diff --git a/arch/arm/mach-at91/include/mach/at91sam9n12.h b/arch/arm/mach-at91/include/mach/at91sam9n12.h index d374b87c0459..0151bcf6163c 100644 --- a/arch/arm/mach-at91/include/mach/at91sam9n12.h +++ b/arch/arm/mach-at91/include/mach/at91sam9n12.h @@ -48,6 +48,11 @@ #define AT91SAM9N12_BASE_USART2 0xf8024000 #define AT91SAM9N12_BASE_USART3 0xf8028000 +/* + * System Peripherals + */ +#define AT91SAM9N12_BASE_RTC 0xfffffeb0 + /* * Internal Memory. */ diff --git a/arch/arm/mach-at91/include/mach/at91sam9x5.h b/arch/arm/mach-at91/include/mach/at91sam9x5.h index c75ee19b58d3..2fc76c49e97c 100644 --- a/arch/arm/mach-at91/include/mach/at91sam9x5.h +++ b/arch/arm/mach-at91/include/mach/at91sam9x5.h @@ -54,6 +54,11 @@ #define AT91SAM9X5_BASE_USART1 0xf8020000 #define AT91SAM9X5_BASE_USART2 0xf8024000 +/* + * System Peripherals + */ +#define AT91SAM9X5_BASE_RTC 0xfffffeb0 + /* * Internal Memory. */ diff --git a/arch/arm/mach-at91/include/mach/sama5d3.h b/arch/arm/mach-at91/include/mach/sama5d3.h index 6dc81ee38048..3abbc4286875 100644 --- a/arch/arm/mach-at91/include/mach/sama5d3.h +++ b/arch/arm/mach-at91/include/mach/sama5d3.h @@ -64,6 +64,11 @@ #define SAMA5D3_ID_TRNG 45 /* True Random Generator Number */ #define SAMA5D3_ID_IRQ0 47 /* Advanced Interrupt Controller (IRQ0) */ +/* + * System Peripherals + */ +#define SAMA5D3_BASE_RTC 0xfffffeb0 + /* * Internal Memory */ diff --git a/arch/arm/mach-at91/sama5d3.c b/arch/arm/mach-at91/sama5d3.c index 401279715ab1..3ea86428ee09 100644 --- a/arch/arm/mach-at91/sama5d3.c +++ b/arch/arm/mach-at91/sama5d3.c @@ -371,7 +371,13 @@ static void __init sama5d3_map_io(void) at91_init_sram(0, SAMA5D3_SRAM_BASE, SAMA5D3_SRAM_SIZE); } +static void __init sama5d3_initialize(void) +{ + at91_sysirq_mask_rtc(SAMA5D3_BASE_RTC); +} + AT91_SOC_START(sama5d3) .map_io = sama5d3_map_io, .register_clocks = sama5d3_register_clocks, + .init = sama5d3_initialize, AT91_SOC_END diff --git a/arch/arm/mach-at91/sysirq_mask.c b/arch/arm/mach-at91/sysirq_mask.c new file mode 100644 index 000000000000..ee3e22c66ce8 --- /dev/null +++ b/arch/arm/mach-at91/sysirq_mask.c @@ -0,0 +1,47 @@ +/* + * sysirq_mask.c - System-interrupt masking + * + * Copyright (C) 2013 Johan Hovold + * + * Functions to disable system interrupts from backup-powered peripherals. + * + * The RTC and RTT-peripherals are generally powered by backup power (VDDBU) + * and are not reset on wake-up, user, watchdog or software reset. This means + * that their interrupts may be enabled during early boot (e.g. after a user + * reset). + * + * As the RTC and RTT share the system-interrupt line with the PIT, an + * interrupt occurring before a handler has been installed would lead to the + * system interrupt being disabled and prevent the system from booting. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +#include "generic.h" + +#define AT91_RTC_IDR 0x24 /* Interrupt Disable Register */ +#define AT91_RTC_IMR 0x28 /* Interrupt Mask Register */ + +void __init at91_sysirq_mask_rtc(u32 rtc_base) +{ + void __iomem *base; + u32 mask; + + base = ioremap(rtc_base, 64); + if (!base) + return; + + mask = readl_relaxed(base + AT91_RTC_IMR); + if (mask) { + pr_info("AT91: Disabling rtc irq\n"); + writel_relaxed(mask, base + AT91_RTC_IDR); + (void)readl_relaxed(base + AT91_RTC_IMR); /* flush */ + } + + iounmap(base); +} -- cgit v1.2.3 From 6ce3ee9af1ad697c71766067ffa1a35352dfdcfd Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 16 Oct 2013 11:56:15 +0200 Subject: ARM: at91: fix hanged boot due to early rtt-interrupt commit 94c4c79f2f1acca6e69a50bff5a7d9027509c16b upstream. Make sure the RTT-interrupts are masked at boot by adding a new helper function to be used at SOC-init. This fixes hanged boot on all AT91 SOCs with an RTT, for example, if an RTT-alarm goes off after a non-clean shutdown (e.g. when using RTC wakeup). The RTC and RTT-peripherals are powered by backup power (VDDBU) (on all AT91 SOCs but RM9200) and are not reset on wake-up, user, watchdog or software reset. This means that their interrupts may be enabled during early boot if, for example, they where not disabled during a previous shutdown (e.g. due to a buggy driver or a non-clean shutdown such as a user reset). Furthermore, an RTC or RTT-alarm may also be active. The RTC and RTT-interrupts use the shared system-interrupt line, which is also used by the PIT, and if an interrupt occurs before a handler (e.g. RTC-driver) has been installed this leads to the system interrupt being disabled and prevents the system from booting. Note that when boot hangs due to an early RTC or RTT-interrupt, the only way to get the system to start again is to remove the backup power (e.g. battery) or to disable the interrupt manually from the bootloader. In particular, a user reset is not sufficient. Signed-off-by: Johan Hovold Signed-off-by: Nicolas Ferre Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-at91/at91sam9260.c | 2 ++ arch/arm/mach-at91/at91sam9261.c | 2 ++ arch/arm/mach-at91/at91sam9263.c | 3 +++ arch/arm/mach-at91/at91sam9g45.c | 1 + arch/arm/mach-at91/at91sam9rl.c | 1 + arch/arm/mach-at91/generic.h | 1 + arch/arm/mach-at91/sysirq_mask.c | 24 ++++++++++++++++++++++++ 7 files changed, 34 insertions(+) diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c index a8ce24538da6..cdb1fb695edf 100644 --- a/arch/arm/mach-at91/at91sam9260.c +++ b/arch/arm/mach-at91/at91sam9260.c @@ -351,6 +351,8 @@ static void __init at91sam9260_initialize(void) at91_extern_irq = (1 << AT91SAM9260_ID_IRQ0) | (1 << AT91SAM9260_ID_IRQ1) | (1 << AT91SAM9260_ID_IRQ2); + at91_sysirq_mask_rtt(AT91SAM9260_BASE_RTT); + /* Register GPIO subsystem */ at91_gpio_init(at91sam9260_gpio, 3); } diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c index 25efb5ac30f1..7c9d2ea5bb88 100644 --- a/arch/arm/mach-at91/at91sam9261.c +++ b/arch/arm/mach-at91/at91sam9261.c @@ -293,6 +293,8 @@ static void __init at91sam9261_initialize(void) at91_extern_irq = (1 << AT91SAM9261_ID_IRQ0) | (1 << AT91SAM9261_ID_IRQ1) | (1 << AT91SAM9261_ID_IRQ2); + at91_sysirq_mask_rtt(AT91SAM9261_BASE_RTT); + /* Register GPIO subsystem */ at91_gpio_init(at91sam9261_gpio, 3); } diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c index f44ffd2105a7..c6b2f477c71f 100644 --- a/arch/arm/mach-at91/at91sam9263.c +++ b/arch/arm/mach-at91/at91sam9263.c @@ -329,6 +329,9 @@ static void __init at91sam9263_initialize(void) arm_pm_restart = at91sam9_alt_restart; at91_extern_irq = (1 << AT91SAM9263_ID_IRQ0) | (1 << AT91SAM9263_ID_IRQ1); + at91_sysirq_mask_rtt(AT91SAM9263_BASE_RTT0); + at91_sysirq_mask_rtt(AT91SAM9263_BASE_RTT1); + /* Register GPIO subsystem */ at91_gpio_init(at91sam9263_gpio, 5); } diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c index eebfe3818812..e381fa125011 100644 --- a/arch/arm/mach-at91/at91sam9g45.c +++ b/arch/arm/mach-at91/at91sam9g45.c @@ -377,6 +377,7 @@ static void __init at91sam9g45_initialize(void) at91_extern_irq = (1 << AT91SAM9G45_ID_IRQ0); at91_sysirq_mask_rtc(AT91SAM9G45_BASE_RTC); + at91_sysirq_mask_rtt(AT91SAM9G45_BASE_RTT); /* Register GPIO subsystem */ at91_gpio_init(at91sam9g45_gpio, 5); diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c index 297613944c93..5615d28a5b96 100644 --- a/arch/arm/mach-at91/at91sam9rl.c +++ b/arch/arm/mach-at91/at91sam9rl.c @@ -296,6 +296,7 @@ static void __init at91sam9rl_initialize(void) at91_extern_irq = (1 << AT91SAM9RL_ID_IRQ0); at91_sysirq_mask_rtc(AT91SAM9RL_BASE_RTC); + at91_sysirq_mask_rtt(AT91SAM9RL_BASE_RTT); /* Register GPIO subsystem */ at91_gpio_init(at91sam9rl_gpio, 4); diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h index 325a4d1fb736..d949ab4e26fa 100644 --- a/arch/arm/mach-at91/generic.h +++ b/arch/arm/mach-at91/generic.h @@ -34,6 +34,7 @@ extern int __init at91_aic_of_init(struct device_node *node, extern int __init at91_aic5_of_init(struct device_node *node, struct device_node *parent); extern void __init at91_sysirq_mask_rtc(u32 rtc_base); +extern void __init at91_sysirq_mask_rtt(u32 rtt_base); /* Timer */ diff --git a/arch/arm/mach-at91/sysirq_mask.c b/arch/arm/mach-at91/sysirq_mask.c index ee3e22c66ce8..2ba694f9626b 100644 --- a/arch/arm/mach-at91/sysirq_mask.c +++ b/arch/arm/mach-at91/sysirq_mask.c @@ -21,6 +21,7 @@ */ #include +#include #include "generic.h" @@ -45,3 +46,26 @@ void __init at91_sysirq_mask_rtc(u32 rtc_base) iounmap(base); } + +void __init at91_sysirq_mask_rtt(u32 rtt_base) +{ + void __iomem *base; + void __iomem *reg; + u32 mode; + + base = ioremap(rtt_base, 16); + if (!base) + return; + + reg = base + AT91_RTT_MR; + + mode = readl_relaxed(reg); + if (mode & (AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN)) { + pr_info("AT91: Disabling rtt irq\n"); + mode &= ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN); + writel_relaxed(mode, reg); + (void)readl_relaxed(reg); /* flush */ + } + + iounmap(base); +} -- cgit v1.2.3 From c51fe27dc3cc7b43ee09edfb192d01ae6fa1c0cf Mon Sep 17 00:00:00 2001 From: Jiada Wang Date: Wed, 30 Oct 2013 04:25:51 -0700 Subject: ARM: i.MX6q: fix the wrong parent of can_root clock commit 9b3d423707c3b1f6633be1be7e959623e10c596b upstream. instead of pll3_usb_otg the parent of can_root clock should be pll3_60m. Signed-off-by: Jiada Wang Signed-off-by: Shawn Guo Cc: Marc Kleine-Budde Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-imx/clk-imx6q.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c index 4e3148ce852d..0b9e437719bd 100644 --- a/arch/arm/mach-imx/clk-imx6q.c +++ b/arch/arm/mach-imx/clk-imx6q.c @@ -424,7 +424,7 @@ int __init mx6q_clocks_init(void) clk[asrc_podf] = imx_clk_divider("asrc_podf", "asrc_pred", base + 0x30, 9, 3); clk[spdif_pred] = imx_clk_divider("spdif_pred", "spdif_sel", base + 0x30, 25, 3); clk[spdif_podf] = imx_clk_divider("spdif_podf", "spdif_pred", base + 0x30, 22, 3); - clk[can_root] = imx_clk_divider("can_root", "pll3_usb_otg", base + 0x20, 2, 6); + clk[can_root] = imx_clk_divider("can_root", "pll3_60m", base + 0x20, 2, 6); clk[ecspi_root] = imx_clk_divider("ecspi_root", "pll3_60m", base + 0x38, 19, 6); clk[gpu2d_core_podf] = imx_clk_divider("gpu2d_core_podf", "gpu2d_core_sel", base + 0x18, 23, 3); clk[gpu3d_core_podf] = imx_clk_divider("gpu3d_core_podf", "gpu3d_core_sel", base + 0x18, 26, 3); -- cgit v1.2.3 From 51de4ecd7c25fae75eb8d0936a443119e13384f9 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 27 Nov 2013 09:32:49 -0800 Subject: Staging: tidspbridge: disable driver commit 930ba4a374b96560ef9fde2145cdc454a164ddcc upstream. There seems to be no active maintainer for the driver, and there is an unfixed security bug, so disable the driver for now. Hopefully someone steps up to be the maintainer, and works to get this out of staging, otherwise it will be deleted soon. Reported-by: Nico Golde Reported-by: Dan Carpenter Cc: Omar Ramirez Luna Cc: Omar Ramirez Luna Cc: Kanigeri, Hari Cc: Ameya Palande Cc: Guzman Lugo, Fernando Cc: Hebbar, Shivananda Cc: Ramos Falcon, Ernesto Cc: Felipe Contreras Cc: Anna, Suman Cc: Gupta, Ramesh Cc: Gomez Castellanos, Ivan Cc: Andy Shevchenko Cc: Armando Uribe De Leon Cc: Deepak Chitriki Cc: Menon, Nishanth Cc: Phil Carmody Cc: Ohad Ben-Cohen Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/staging/tidspbridge/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/tidspbridge/Kconfig b/drivers/staging/tidspbridge/Kconfig index 60848f198b48..f7deabcf8355 100644 --- a/drivers/staging/tidspbridge/Kconfig +++ b/drivers/staging/tidspbridge/Kconfig @@ -4,7 +4,7 @@ menuconfig TIDSPBRIDGE tristate "DSP Bridge driver" - depends on ARCH_OMAP3 && !ARCH_MULTIPLATFORM + depends on ARCH_OMAP3 && !ARCH_MULTIPLATFORM && BROKEN select OMAP_MBOX_FWK help DSP/BIOS Bridge is designed for platforms that contain a GPP and -- cgit v1.2.3 From 6871b98011fd07991f9259c9be339b1bde34d527 Mon Sep 17 00:00:00 2001 From: Olav Haugan Date: Fri, 22 Nov 2013 09:30:41 -0800 Subject: staging: zsmalloc: Ensure handle is never 0 on success commit 67296874eb1cc80317bf2a8fba22b494e21eb29b upstream. zsmalloc encodes a handle using the pfn and an object index. On hardware platforms with physical memory starting at 0x0 the pfn can be 0. This causes the encoded handle to be 0 and is incorrectly interpreted as an allocation failure. This issue affects all current and future SoCs with physical memory starting at 0x0. All MSM8974 SoCs which includes Google Nexus 5 devices are affected. To prevent this false error we ensure that the encoded handle will not be 0 when allocation succeeds. Signed-off-by: Olav Haugan Signed-off-by: Greg Kroah-Hartman --- drivers/staging/zsmalloc/zsmalloc-main.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/staging/zsmalloc/zsmalloc-main.c b/drivers/staging/zsmalloc/zsmalloc-main.c index f82f7e69c8a5..288f58252a18 100644 --- a/drivers/staging/zsmalloc/zsmalloc-main.c +++ b/drivers/staging/zsmalloc/zsmalloc-main.c @@ -430,7 +430,12 @@ static struct page *get_next_page(struct page *page) return next; } -/* Encode as a single handle value */ +/* + * Encode as a single handle value. + * On hardware platforms with physical memory starting at 0x0 the pfn + * could be 0 so we ensure that the handle will never be 0 by adjusting the + * encoded obj_idx value before encoding. + */ static void *obj_location_to_handle(struct page *page, unsigned long obj_idx) { unsigned long handle; @@ -441,17 +446,21 @@ static void *obj_location_to_handle(struct page *page, unsigned long obj_idx) } handle = page_to_pfn(page) << OBJ_INDEX_BITS; - handle |= (obj_idx & OBJ_INDEX_MASK); + handle |= ((obj_idx + 1) & OBJ_INDEX_MASK); return (void *)handle; } -/* Decode pair from the given object handle */ +/* + * Decode pair from the given object handle. We adjust the + * decoded obj_idx back to its original value since it was adjusted in + * obj_location_to_handle(). + */ static void obj_handle_to_location(unsigned long handle, struct page **page, unsigned long *obj_idx) { *page = pfn_to_page(handle >> OBJ_INDEX_BITS); - *obj_idx = handle & OBJ_INDEX_MASK; + *obj_idx = (handle & OBJ_INDEX_MASK) - 1; } static unsigned long obj_idx_to_offset(struct page *page, -- cgit v1.2.3 From 368289b373137db191a35ed9e6865e42ff7d0263 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Thu, 7 Nov 2013 21:49:04 +0000 Subject: staging: vt6656: [BUG] Fix for TX USB resets from vendors driver. commit 9df682927c2e3a92f43803d6b52095992e3b2ab8 upstream. This fixes resets on heavy TX data traffic. Vendor driver VT6656_Linux_src_v1.21.03_x86_11.04.zip http://www.viaembedded.com/servlet/downloadSvl?id=1890&download_file_id=14704 This is GPL-licensed code. original code BBbVT3184Init ... //2007-0725, RobertChang add, Enable Squelch detect reset option(SQ_RST_Opt), USB (register4, bit1) CONTROLnsRequestIn(pDevice, MESSAGE_TYPE_READ, (WORD)0x600+4, // USB's Reg4's bit1 MESSAGE_REQUEST_MEM, 1, (PBYTE) &byData); byData = byData|2 ; CONTROLnsRequestOut(pDevice, MESSAGE_TYPE_WRITE, (WORD)0x600+4, // USB's Reg4's bit1 MESSAGE_REQUEST_MEM, 1, (PBYTE) &byData); return TRUE;//ntStatus; .... A back port patch is needed for kernels less than 3.10. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/baseband.c | 11 +++++++++++ drivers/staging/vt6656/rndis.h | 2 ++ 2 files changed, 13 insertions(+) diff --git a/drivers/staging/vt6656/baseband.c b/drivers/staging/vt6656/baseband.c index 33fa76759bf1..3ff1126c9a53 100644 --- a/drivers/staging/vt6656/baseband.c +++ b/drivers/staging/vt6656/baseband.c @@ -941,6 +941,7 @@ int BBbVT3184Init(struct vnt_private *pDevice) u8 * pbyAgc; u16 wLengthAgc; u8 abyArray[256]; + u8 data; ntStatus = CONTROLnsRequestIn(pDevice, MESSAGE_TYPE_READ, @@ -1106,6 +1107,16 @@ else { ControlvWriteByte(pDevice,MESSAGE_REQUEST_BBREG,0x0D,0x01); RFbRFTableDownload(pDevice); + + /* Fix for TX USB resets from vendors driver */ + CONTROLnsRequestIn(pDevice, MESSAGE_TYPE_READ, USB_REG4, + MESSAGE_REQUEST_MEM, sizeof(data), &data); + + data |= 0x2; + + CONTROLnsRequestOut(pDevice, MESSAGE_TYPE_WRITE, USB_REG4, + MESSAGE_REQUEST_MEM, sizeof(data), &data); + return true;//ntStatus; } diff --git a/drivers/staging/vt6656/rndis.h b/drivers/staging/vt6656/rndis.h index 5e073062017a..5cf5e732a36f 100644 --- a/drivers/staging/vt6656/rndis.h +++ b/drivers/staging/vt6656/rndis.h @@ -66,6 +66,8 @@ #define VIAUSB20_PACKET_HEADER 0x04 +#define USB_REG4 0x604 + typedef struct _CMD_MESSAGE { u8 byData[256]; -- cgit v1.2.3 From fe619f64b93df39d3d6f4b60cd9fa3474e61ce5f Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 12 Nov 2013 15:09:39 -0800 Subject: backlight: atmel-pwm-bl: fix gpio polarity in remove commit ad5066d4c2b1d696749f8d7816357c23b648c4d3 upstream. Make sure to honour gpio polarity also at remove so that the backlight is actually disabled on boards with active-low enable pin. Signed-off-by: Johan Hovold Acked-by: Jingoo Han Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/video/backlight/atmel-pwm-bl.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/video/backlight/atmel-pwm-bl.c b/drivers/video/backlight/atmel-pwm-bl.c index 30e4ed52d701..6d2edeb85ac2 100644 --- a/drivers/video/backlight/atmel-pwm-bl.c +++ b/drivers/video/backlight/atmel-pwm-bl.c @@ -207,8 +207,10 @@ static int atmel_pwm_bl_remove(struct platform_device *pdev) { struct atmel_pwm_bl *pwmbl = platform_get_drvdata(pdev); - if (pwmbl->gpio_on != -1) - gpio_set_value(pwmbl->gpio_on, 0); + if (pwmbl->gpio_on != -1) { + gpio_set_value(pwmbl->gpio_on, + 0 ^ pwmbl->pdata->on_active_low); + } pwm_channel_disable(&pwmbl->pwmc); pwm_channel_free(&pwmbl->pwmc); backlight_device_unregister(pwmbl->bldev); -- cgit v1.2.3 From 06909ca39fbac8b66421dbf8397d029879e81cfa Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 12 Nov 2013 15:09:38 -0800 Subject: backlight: atmel-pwm-bl: fix reported brightness commit 185d91442550110db67a7dc794a32efcea455a36 upstream. The driver supports 16-bit brightness values, but the value returned from get_brightness was truncated to eight bits. Signed-off-by: Johan Hovold Cc: Jingoo Han Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/video/backlight/atmel-pwm-bl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/backlight/atmel-pwm-bl.c b/drivers/video/backlight/atmel-pwm-bl.c index 6d2edeb85ac2..27a14a05ff7a 100644 --- a/drivers/video/backlight/atmel-pwm-bl.c +++ b/drivers/video/backlight/atmel-pwm-bl.c @@ -70,7 +70,7 @@ static int atmel_pwm_bl_set_intensity(struct backlight_device *bd) static int atmel_pwm_bl_get_intensity(struct backlight_device *bd) { struct atmel_pwm_bl *pwmbl = bl_get_data(bd); - u8 intensity; + u32 intensity; if (pwmbl->pdata->pwm_active_low) { intensity = pwm_channel_readl(&pwmbl->pwmc, PWM_CDTY) - @@ -80,7 +80,7 @@ static int atmel_pwm_bl_get_intensity(struct backlight_device *bd) pwm_channel_readl(&pwmbl->pwmc, PWM_CDTY); } - return intensity; + return intensity & 0xffff; } static int atmel_pwm_bl_init_pwm(struct atmel_pwm_bl *pwmbl) -- cgit v1.2.3 From 2807631534a8356005fd965fa3927de95fa95004 Mon Sep 17 00:00:00 2001 From: Phil Edworthy Date: Thu, 31 Oct 2013 23:06:17 -0700 Subject: ASoC: ak4642: prevent un-necessary changes to SG_SL1 commit 7b5bfb82882b9b1c8423ce0ed6852ca3762d967a upstream. If you record the sound during playback, the playback sound becomes silent. Modify so that the codec driver does not clear SG_SL1::DACL bit which is controlled under widget Signed-off-by: Phil Edworthy Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/ak4642.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c index 2d0378709702..687565d08d9c 100644 --- a/sound/soc/codecs/ak4642.c +++ b/sound/soc/codecs/ak4642.c @@ -257,7 +257,7 @@ static int ak4642_dai_startup(struct snd_pcm_substream *substream, * This operation came from example code of * "ASAHI KASEI AK4642" (japanese) manual p94. */ - snd_soc_write(codec, SG_SL1, PMMP | MGAIN0); + snd_soc_update_bits(codec, SG_SL1, PMMP | MGAIN0, PMMP | MGAIN0); snd_soc_write(codec, TIMER, ZTM(0x3) | WTM(0x3)); snd_soc_write(codec, ALC_CTL1, ALC | LMTH0); snd_soc_update_bits(codec, PW_MGMT1, PMADL, PMADL); -- cgit v1.2.3 From 8559f25c6b72ebed12cf42ec60934b7ccdc96098 Mon Sep 17 00:00:00 2001 From: Brian Austin Date: Thu, 14 Nov 2013 11:46:12 -0600 Subject: ASoC: cs42l52: Correct MIC CTL mask commit 3d800c6d75b8c92fa928a0bcaf95cd7ac5fd1ce5 upstream. The mask for CS42L52_MIC_CTL_TYPE_MASK was wrong keeping the mic config from being set correctly. Signed-off-by: Brian Austin Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/cs42l52.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/cs42l52.h b/sound/soc/codecs/cs42l52.h index 4277012c4719..a935d7381af6 100644 --- a/sound/soc/codecs/cs42l52.h +++ b/sound/soc/codecs/cs42l52.h @@ -179,7 +179,7 @@ #define CS42L52_MICB_CTL 0x11 #define CS42L52_MIC_CTL_MIC_SEL_MASK 0xBF #define CS42L52_MIC_CTL_MIC_SEL_SHIFT 6 -#define CS42L52_MIC_CTL_TYPE_MASK 0xDF +#define CS42L52_MIC_CTL_TYPE_MASK 0x20 #define CS42L52_MIC_CTL_TYPE_SHIFT 5 -- cgit v1.2.3 From 59d5384899d0e8567dfd7875d4e174cce311de63 Mon Sep 17 00:00:00 2001 From: Nicolin Chen Date: Thu, 14 Nov 2013 11:59:21 +0800 Subject: ASoC: wm8962: Turn on regcache_cache_only before disabling regulator commit 50bfcf2df2fadf77e143d6099150e6fa7ef4d78c upstream. It's safer to turn on regcache_cache_only before disabling regulator since the driver will turn off the regcache_cache_only after enabling regulator. If we remain cache_only false, some command like 'amixer cset' would get failure if being run before wm8962_resume(). Signed-off-by: Nicolin Chen Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/wm8962.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 730dd0c0f0ab..e3cd86514cea 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -3686,6 +3686,8 @@ static int wm8962_i2c_probe(struct i2c_client *i2c, if (ret < 0) goto err_enable; + regcache_cache_only(wm8962->regmap, true); + /* The drivers should power up as needed */ regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), wm8962->supplies); -- cgit v1.2.3 From ddf2f8881b5a608c9a55f3944b6e39a3decc5e4b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 13 Nov 2013 17:15:00 +0100 Subject: ASoC: blackfin: Fix missing break commit afed4dbe3a043dbd833a53b6b4951e155708afd2 upstream. Fixes: 4b2ffc205cb9 ('ASoC: Blackfin I2S: add 8-bit sample support') Reported-by: David Binderman Signed-off-by: Takashi Iwai Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/blackfin/bf5xx-i2s.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/blackfin/bf5xx-i2s.c b/sound/soc/blackfin/bf5xx-i2s.c index dd0c2a4f83a3..e0869aaa1e93 100644 --- a/sound/soc/blackfin/bf5xx-i2s.c +++ b/sound/soc/blackfin/bf5xx-i2s.c @@ -111,6 +111,7 @@ static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream, bf5xx_i2s->tcr2 |= 7; bf5xx_i2s->rcr2 |= 7; sport_handle->wdsize = 1; + break; case SNDRV_PCM_FORMAT_S16_LE: bf5xx_i2s->tcr2 |= 15; bf5xx_i2s->rcr2 |= 15; -- cgit v1.2.3 From b63d5e491bbbab6f97cc4432334d3a2539cd4a1c Mon Sep 17 00:00:00 2001 From: Oskar Schirmer Date: Tue, 12 Nov 2013 15:46:38 +0000 Subject: ASoC: fsl: imx-pcm-fiq: omit fiq counter to avoid harm in unbalanced situations commit fc7dc61d9a87011aaf8a6eb3144ebf9552adf5d2 upstream. Unbalanced calls to snd_imx_pcm_trigger() may result in endless FIQ activity and thus provoke eternal sound. While on the first glance, the switch statement looks pretty symmetric, the SUSPEND/RESUME pair is not: the suspend case comes along snd_pcm_suspend_all(), which for fsl/imx-pcm-fiq is called only at snd_soc_suspend(), but the resume case originates straight from the SNDRV_PCM_IOCTL_RESUME. This way userland may provoke an unbalanced resume, which might cause the fiq_enable counter to increase and never return to zero again, so eventually imx_pcm_fiq is never disabled. Simply removing the fiq_enable will solve the problem, as long as one never goes play and capture game simultaneously, but beware trying both at once, the early TRIGGER_STOP will cut off the other activity prematurely. So now playing and capturing is scrutinized separately, instead of by counting. Signed-off-by: Oskar Schirmer Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/fsl/imx-pcm-fiq.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/sound/soc/fsl/imx-pcm-fiq.c b/sound/soc/fsl/imx-pcm-fiq.c index 670b96b0ce2f..dcfd0fae0b35 100644 --- a/sound/soc/fsl/imx-pcm-fiq.c +++ b/sound/soc/fsl/imx-pcm-fiq.c @@ -42,7 +42,8 @@ struct imx_pcm_runtime_data { struct hrtimer hrt; int poll_time_ns; struct snd_pcm_substream *substream; - atomic_t running; + atomic_t playing; + atomic_t capturing; }; static enum hrtimer_restart snd_hrtimer_callback(struct hrtimer *hrt) @@ -54,7 +55,7 @@ static enum hrtimer_restart snd_hrtimer_callback(struct hrtimer *hrt) struct pt_regs regs; unsigned long delta; - if (!atomic_read(&iprtd->running)) + if (!atomic_read(&iprtd->playing) && !atomic_read(&iprtd->capturing)) return HRTIMER_NORESTART; get_fiq_regs(®s); @@ -122,7 +123,6 @@ static int snd_imx_pcm_prepare(struct snd_pcm_substream *substream) return 0; } -static int fiq_enable; static int imx_pcm_fiq; static int snd_imx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) @@ -134,23 +134,27 @@ static int snd_imx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - atomic_set(&iprtd->running, 1); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + atomic_set(&iprtd->playing, 1); + else + atomic_set(&iprtd->capturing, 1); hrtimer_start(&iprtd->hrt, ns_to_ktime(iprtd->poll_time_ns), HRTIMER_MODE_REL); - if (++fiq_enable == 1) - enable_fiq(imx_pcm_fiq); - + enable_fiq(imx_pcm_fiq); break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - atomic_set(&iprtd->running, 0); - - if (--fiq_enable == 0) + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + atomic_set(&iprtd->playing, 0); + else + atomic_set(&iprtd->capturing, 0); + if (!atomic_read(&iprtd->playing) && + !atomic_read(&iprtd->capturing)) disable_fiq(imx_pcm_fiq); - break; + default: return -EINVAL; } @@ -198,7 +202,8 @@ static int snd_imx_open(struct snd_pcm_substream *substream) iprtd->substream = substream; - atomic_set(&iprtd->running, 0); + atomic_set(&iprtd->playing, 0); + atomic_set(&iprtd->capturing, 0); hrtimer_init(&iprtd->hrt, CLOCK_MONOTONIC, HRTIMER_MODE_REL); iprtd->hrt.function = snd_hrtimer_callback; -- cgit v1.2.3 From d2099a50522c4002a2888c70a39560aab20d0926 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Wed, 20 Nov 2013 14:37:09 +0000 Subject: ASoC: arizona: Set FLL to free-run before disabling commit 3e68ce1bc72e5d6615677ec5a8b0a9bcb6c7a490 upstream. The FLL must be placed into free-run mode before disabling to allow it to entirely shut down. Signed-off-by: Richard Fitzgerald Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/arizona.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 389f23253831..663a2a748626 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -1454,6 +1454,8 @@ static void arizona_enable_fll(struct arizona_fll *fll, /* Clear any pending completions */ try_wait_for_completion(&fll->ok); + regmap_update_bits(arizona->regmap, fll->base + 1, + ARIZONA_FLL1_FREERUN, 0); regmap_update_bits(arizona->regmap, fll->base + 1, ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA); if (fll->ref_src >= 0 && fll->sync_src >= 0 && @@ -1473,6 +1475,8 @@ static void arizona_disable_fll(struct arizona_fll *fll) struct arizona *arizona = fll->arizona; bool change; + regmap_update_bits(arizona->regmap, fll->base + 1, + ARIZONA_FLL1_FREERUN, ARIZONA_FLL1_FREERUN); regmap_update_bits_check(arizona->regmap, fll->base + 1, ARIZONA_FLL1_ENA, 0, &change); regmap_update_bits(arizona->regmap, fll->base + 0x11, -- cgit v1.2.3 From f9bdb31ae29c0cf60b35ed83c98e7a4043873336 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 19 Nov 2013 10:51:29 +0000 Subject: ASoC: wm5110: Add post SYSCLK register patch for rev D chip commit f69f86b1ba6493126a7f093a65a8952bcb183de2 upstream. Certain registers require patching after the SYSCLK has been brought up add support for this into the CODEC driver. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/wm5110.c | 43 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 88ad7db52dde..cd6ed88409d7 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -37,6 +37,47 @@ struct wm5110_priv { struct arizona_fll fll[2]; }; +static const struct reg_default wm5110_sysclk_revd_patch[] = { + { 0x3093, 0x1001 }, + { 0x30E3, 0x1301 }, + { 0x3133, 0x1201 }, + { 0x3183, 0x1501 }, + { 0x31D3, 0x1401 }, +}; + +static int wm5110_sysclk_ev(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = w->codec; + struct arizona *arizona = dev_get_drvdata(codec->dev->parent); + struct regmap *regmap = codec->control_data; + const struct reg_default *patch = NULL; + int i, patch_size; + + switch (arizona->rev) { + case 3: + patch = wm5110_sysclk_revd_patch; + patch_size = ARRAY_SIZE(wm5110_sysclk_revd_patch); + break; + default: + return 0; + } + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + if (patch) + for (i = 0; i < patch_size; i++) + regmap_write(regmap, patch[i].reg, + patch[i].def); + break; + + default: + break; + } + + return 0; +} + static DECLARE_TLV_DB_SCALE(ana_tlv, 0, 100, 0); static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0); @@ -386,7 +427,7 @@ static const struct snd_kcontrol_new wm5110_aec_loopback_mux = static const struct snd_soc_dapm_widget wm5110_dapm_widgets[] = { SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT, - 0, NULL, 0), + 0, wm5110_sysclk_ev, SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_SUPPLY("ASYNCCLK", ARIZONA_ASYNC_CLOCK_1, ARIZONA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0), SND_SOC_DAPM_SUPPLY("OPCLK", ARIZONA_OUTPUT_SYSTEM_CLOCK, -- cgit v1.2.3 From 9dfd005a3f4e1c648cb4aa1dc70604bb370c5e7b Mon Sep 17 00:00:00 2001 From: Michael Hudson-Doyle Date: Thu, 31 Oct 2013 16:47:45 -0700 Subject: perf tools: Remove cast of non-variadic function to variadic commit 53805eca3d89b095062c11a6798689bb0af09216 upstream. The 4fb71074a570 (perf ui/hist: Consolidate hpp helpers) cset introduced a cast of percent_color_snprintf to a function pointer type with varargs. Change percent_color_snprintf to be variadic and remove the cast. The symptom of this was all percentages being reported as 0.00% in perf report --stdio output on the armhf arch. Signed-off-by: Michael Hudson-Doyle Acked-by: Namhyung Kim Acked-by: Will Deacon Cc: Jean Pihet Cc: Jiri Olsa Cc: Will Deacon Link: http://lkml.kernel.org/r/87zjppvw7y.fsf@canonical.com Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: Greg Kroah-Hartman --- tools/perf/ui/hist.c | 2 +- tools/perf/util/color.c | 11 +++++++++-- tools/perf/util/color.h | 2 +- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index 4bf91b09d62d..794bb1a120be 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -113,7 +113,7 @@ static u64 he_get_##_field(struct hist_entry *he) \ static int hpp__color_##_type(struct perf_hpp *hpp, struct hist_entry *he) \ { \ return __hpp__fmt(hpp, he, he_get_##_field, " %6.2f%%", \ - (hpp_snprint_fn)percent_color_snprintf, true); \ + percent_color_snprintf, true); \ } #define __HPP_ENTRY_PERCENT_FN(_type, _field) \ diff --git a/tools/perf/util/color.c b/tools/perf/util/color.c index 11e46da17bbb..66e44a5019d5 100644 --- a/tools/perf/util/color.c +++ b/tools/perf/util/color.c @@ -318,8 +318,15 @@ int percent_color_fprintf(FILE *fp, const char *fmt, double percent) return r; } -int percent_color_snprintf(char *bf, size_t size, const char *fmt, double percent) +int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...) { - const char *color = get_percent_color(percent); + va_list args; + double percent; + const char *color; + + va_start(args, fmt); + percent = va_arg(args, double); + va_end(args); + color = get_percent_color(percent); return color_snprintf(bf, size, color, fmt, percent); } diff --git a/tools/perf/util/color.h b/tools/perf/util/color.h index dea082b79602..fced3840e99c 100644 --- a/tools/perf/util/color.h +++ b/tools/perf/util/color.h @@ -39,7 +39,7 @@ int color_fprintf(FILE *fp, const char *color, const char *fmt, ...); int color_snprintf(char *bf, size_t size, const char *color, const char *fmt, ...); int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...); int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf); -int percent_color_snprintf(char *bf, size_t size, const char *fmt, double percent); +int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...); int percent_color_fprintf(FILE *fp, const char *fmt, double percent); const char *get_percent_color(double percent); -- cgit v1.2.3 From 4501cfd0e3a1c06e5539c9f806866f8408232393 Mon Sep 17 00:00:00 2001 From: KOSAKI Motohiro Date: Mon, 14 Oct 2013 17:33:16 -0400 Subject: alarmtimer: return EINVAL instead of ENOTSUPP if rtcdev doesn't exist commit 98d6f4dd84a134d942827584a3c5f67ffd8ec35f upstream. Fedora Ruby maintainer reported latest Ruby doesn't work on Fedora Rawhide on ARM. (http://bugs.ruby-lang.org/issues/9008) Because of, commit 1c6b39ad3f (alarmtimers: Return -ENOTSUPP if no RTC device is present) intruduced to return ENOTSUPP when clock_get{time,res} can't find a RTC device. However this is incorrect. First, ENOTSUPP isn't exported to userland (ENOTSUP or EOPNOTSUP are the closest userland equivlents). Second, Posix and Linux man pages agree that clock_gettime and clock_getres should return EINVAL if clk_id argument is invalid. While the arugment that the clockid is valid, but just not supported on this hardware could be made, this is just a technicality that doesn't help userspace applicaitons, and only complicates error handling. Thus, this patch changes the code to use EINVAL. Cc: Thomas Gleixner Cc: Frederic Weisbecker Reported-by: Vit Ondruch Signed-off-by: KOSAKI Motohiro [jstultz: Tweaks to commit message to include full rational] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- kernel/time/alarmtimer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c index f11d83b12949..a8f5084dcde7 100644 --- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c @@ -445,7 +445,7 @@ static int alarm_clock_getres(const clockid_t which_clock, struct timespec *tp) clockid_t baseid = alarm_bases[clock2alarm(which_clock)].base_clockid; if (!alarmtimer_get_rtcdev()) - return -ENOTSUPP; + return -EINVAL; return hrtimer_get_res(baseid, tp); } @@ -462,7 +462,7 @@ static int alarm_clock_get(clockid_t which_clock, struct timespec *tp) struct alarm_base *base = &alarm_bases[clock2alarm(which_clock)]; if (!alarmtimer_get_rtcdev()) - return -ENOTSUPP; + return -EINVAL; *tp = ktime_to_timespec(base->gettime()); return 0; -- cgit v1.2.3 From 884181395dc053f31759ae0bd0c8ff88d143eb4e Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Mon, 14 Oct 2013 01:27:27 +0200 Subject: pinctrl: dove: unset twsi option3 for gconfig as well commit 6d0a4ed2b90a12e1403d3e7d9d8c2cc7fdc301b5 upstream. This fixes a typo which left twsi config3 option enabled. Signed-off-by: Roel Kluin Acked-by: Sebastian Hesselbarth Signed-off-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman --- drivers/pinctrl/mvebu/pinctrl-dove.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/mvebu/pinctrl-dove.c b/drivers/pinctrl/mvebu/pinctrl-dove.c index 428ea96a94d3..e29e6d831aeb 100644 --- a/drivers/pinctrl/mvebu/pinctrl-dove.c +++ b/drivers/pinctrl/mvebu/pinctrl-dove.c @@ -323,7 +323,7 @@ static int dove_twsi_ctrl_set(struct mvebu_mpp_ctrl *ctrl, unsigned long gcfg2 = readl(DOVE_GLOBAL_CONFIG_2); gcfg1 &= ~DOVE_TWSI_ENABLE_OPTION1; - gcfg2 &= ~(DOVE_TWSI_ENABLE_OPTION2 | DOVE_TWSI_ENABLE_OPTION2); + gcfg2 &= ~(DOVE_TWSI_ENABLE_OPTION2 | DOVE_TWSI_ENABLE_OPTION3); switch (config) { case 1: -- cgit v1.2.3 From cc447613b50aa83ff466878dd6245153b1cfb95c Mon Sep 17 00:00:00 2001 From: Ilija Hadzic Date: Tue, 12 Nov 2013 15:11:45 -0800 Subject: devpts: plug the memory leak in kill_sb commit 66da0e1f9034140ae2f571ef96e254a25083906c upstream. When devpts is unmounted, there may be a no-longer-used IDR tree hanging off the superblock we are about to kill. This needs to be cleaned up before destroying the SB. The leak is usually not a big deal because unmounting devpts is typically done when shutting down the whole machine. However, shutting down an LXC container instead of a physical machine exposes the problem (the garbage is detectable with kmemleak). Signed-off-by: Ilija Hadzic Cc: Sukadev Bhattiprolu Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/devpts/inode.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c index 073d30b9d1ac..a726b9f29cb7 100644 --- a/fs/devpts/inode.c +++ b/fs/devpts/inode.c @@ -498,6 +498,7 @@ static void devpts_kill_sb(struct super_block *sb) { struct pts_fs_info *fsi = DEVPTS_SB(sb); + ida_destroy(&fsi->allocated_ptys); kfree(fsi); kill_litter_super(sb); } -- cgit v1.2.3 From 8f7e823f18150b6767e5e03ede80a0896a4adf06 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Mon, 14 Oct 2013 21:04:13 +0200 Subject: parisc: break out SOCK_NONBLOCK define to own asm header file commit 38c7937379276a5ea8c54481205003af2f2b5694 upstream. Break SOCK_NONBLOCK out to its own asm-file as other arches do. This fixes build errors with auditd and probably other packages. Signed-off-by: Helge Deller Signed-off-by: Greg Kroah-Hartman --- arch/parisc/include/asm/socket.h | 11 +++++++++++ arch/parisc/include/uapi/asm/socket.h | 11 +++-------- 2 files changed, 14 insertions(+), 8 deletions(-) create mode 100644 arch/parisc/include/asm/socket.h diff --git a/arch/parisc/include/asm/socket.h b/arch/parisc/include/asm/socket.h new file mode 100644 index 000000000000..748016cb122d --- /dev/null +++ b/arch/parisc/include/asm/socket.h @@ -0,0 +1,11 @@ +#ifndef _ASM_SOCKET_H +#define _ASM_SOCKET_H + +#include + +/* O_NONBLOCK clashes with the bits used for socket types. Therefore we + * have to define SOCK_NONBLOCK to a different value here. + */ +#define SOCK_NONBLOCK 0x40000000 + +#endif /* _ASM_SOCKET_H */ diff --git a/arch/parisc/include/uapi/asm/socket.h b/arch/parisc/include/uapi/asm/socket.h index 70c512a386f7..4fecb26230e7 100644 --- a/arch/parisc/include/uapi/asm/socket.h +++ b/arch/parisc/include/uapi/asm/socket.h @@ -1,5 +1,5 @@ -#ifndef _ASM_SOCKET_H -#define _ASM_SOCKET_H +#ifndef _UAPI_ASM_SOCKET_H +#define _UAPI_ASM_SOCKET_H #include @@ -73,9 +73,4 @@ #define SO_SELECT_ERR_QUEUE 0x4026 -/* O_NONBLOCK clashes with the bits used for socket types. Therefore we - * have to define SOCK_NONBLOCK to a different value here. - */ -#define SOCK_NONBLOCK 0x40000000 - -#endif /* _ASM_SOCKET_H */ +#endif /* _UAPI_ASM_SOCKET_H */ -- cgit v1.2.3 From 2e3179de1d002a148f7e540e30f7227111992421 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Fri, 27 Sep 2013 12:15:05 +0200 Subject: can: flexcan: fix flexcan_chip_start() on imx6 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 0d1862ea1a5bb876cf05555a7307080cb75bf379 upstream. In the flexcan_chip_start() function first the flexcan core is going through the soft reset sequence, then the RX FIFO is enabled. With the hardware is put into FIFO mode, message buffers 1...7 are reserved by the FIFO engine. The remaining message buffers are in reset default values. This patch removes the bogus initialization of the message buffers, as it causes an imprecise external abort on imx6. Reported-by: Lothar Waßmann Tested-by: Lothar Waßmann [mkl: adjusted context for stable] Signed-off-by: Marc Kleine-Budde Signed-off-by: Greg Kroah-Hartman --- drivers/net/can/flexcan.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index a8f33a525dd6..f63169d6af26 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -711,7 +711,6 @@ static int flexcan_chip_start(struct net_device *dev) { struct flexcan_priv *priv = netdev_priv(dev); struct flexcan_regs __iomem *regs = priv->base; - unsigned int i; int err; u32 reg_mcr, reg_ctrl; @@ -783,17 +782,6 @@ static int flexcan_chip_start(struct net_device *dev) netdev_dbg(dev, "%s: writing ctrl=0x%08x", __func__, reg_ctrl); flexcan_write(reg_ctrl, ®s->ctrl); - for (i = 0; i < ARRAY_SIZE(regs->cantxfg); i++) { - flexcan_write(0, ®s->cantxfg[i].can_ctrl); - flexcan_write(0, ®s->cantxfg[i].can_id); - flexcan_write(0, ®s->cantxfg[i].data[0]); - flexcan_write(0, ®s->cantxfg[i].data[1]); - - /* put MB into rx queue */ - flexcan_write(FLEXCAN_MB_CNT_CODE(0x4), - ®s->cantxfg[i].can_ctrl); - } - /* Abort any pending TX, mark Mailbox as INACTIVE */ flexcan_write(FLEXCAN_MB_CNT_CODE(0x4), ®s->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl); -- cgit v1.2.3 From 12ea4499abf3cabc3dcea7efed13d15b99930405 Mon Sep 17 00:00:00 2001 From: Ionut Nicu Date: Fri, 11 Oct 2013 12:09:57 +0200 Subject: i2c: mux: gpio: use reg value for i2c_add_mux_adapter commit 8c0ec2500eeb89749341884a972860d7f9e56f9c upstream. The i2c-mux driver requires that the chan_id parameter passed to the i2c_add_mux_adapter() function is equal to the reg value for that adapter: for_each_child_of_node(mux_dev->of_node, child) { ret = of_property_read_u32(child, "reg", ®); if (ret) continue; if (chan_id == reg) { priv->adap.dev.of_node = child; break; } } The i2c-mux-gpio driver uses an internal logical index for chan_id when calling i2c_add_mux_adapter() instead of using the reg value. Because of this, there will problems in selecting the right adapter when the i2c-mux-gpio's index into mux->data.values doesn't match the reg value. An example of such a case: mux->data.values = { 1, 0 } For chan_id = 0, i2c-mux will bind the adapter to the of_node with reg = <0>, but when it will call the select() callback with chan_id set to 0, the i2c-mux-gpio will use it as an index into mux->data.values and it will actually select the bus with reg = <1>. Signed-off-by: Ionut Nicu Acked-by: Alexander Sverdlin Signed-off-by: Wolfram Sang Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/muxes/i2c-mux-gpio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/muxes/i2c-mux-gpio.c b/drivers/i2c/muxes/i2c-mux-gpio.c index 5a0ce0081dce..4879796dddc5 100644 --- a/drivers/i2c/muxes/i2c-mux-gpio.c +++ b/drivers/i2c/muxes/i2c-mux-gpio.c @@ -39,7 +39,7 @@ static int i2c_mux_gpio_select(struct i2c_adapter *adap, void *data, u32 chan) { struct gpiomux *mux = data; - i2c_mux_gpio_set(mux, mux->data.values[chan]); + i2c_mux_gpio_set(mux, chan); return 0; } @@ -223,7 +223,7 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev) unsigned int class = mux->data.classes ? mux->data.classes[i] : 0; mux->adap[i] = i2c_add_mux_adapter(parent, &pdev->dev, mux, nr, - i, class, + mux->data.values[i], class, i2c_mux_gpio_select, deselect); if (!mux->adap[i]) { ret = -ENODEV; -- cgit v1.2.3 From d9d317655d19d5cb583333e5643b0ada4ef5b48e Mon Sep 17 00:00:00 2001 From: Ionut Nicu Date: Fri, 11 Oct 2013 14:17:10 +0200 Subject: i2c: mux: gpio: use gpio_set_value_cansleep() commit 250ad590d6f12d93f4d85be305b0a598d609232e upstream. Some gpio chips may have get/set operations that can sleep. gpio_set_value() only works for chips which do not sleep, for the others we will get a kernel warning. Using gpio_set_value_cansleep() will work for both chips that do sleep and those who don't. Signed-off-by: Ionut Nicu Acked-by: Peter Korsgaard Signed-off-by: Wolfram Sang Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/muxes/i2c-mux-gpio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/muxes/i2c-mux-gpio.c b/drivers/i2c/muxes/i2c-mux-gpio.c index 4879796dddc5..bb4f69f75f3c 100644 --- a/drivers/i2c/muxes/i2c-mux-gpio.c +++ b/drivers/i2c/muxes/i2c-mux-gpio.c @@ -31,8 +31,8 @@ static void i2c_mux_gpio_set(const struct gpiomux *mux, unsigned val) int i; for (i = 0; i < mux->data.n_gpios; i++) - gpio_set_value(mux->gpio_base + mux->data.gpios[i], - val & (1 << i)); + gpio_set_value_cansleep(mux->gpio_base + mux->data.gpios[i], + val & (1 << i)); } static int i2c_mux_gpio_select(struct i2c_adapter *adap, void *data, u32 chan) -- cgit v1.2.3 From c1acc1db4649a44b38ded7d432a6d2fd24526b1b Mon Sep 17 00:00:00 2001 From: Doug Anderson Date: Wed, 23 Oct 2013 06:11:01 -0700 Subject: ARM: dts: Add max77686 RTC interrupt to cros5250-common commit c61248afa8190ae3f47ee67f46e3c9b584a73d31 upstream. Without the interrupt you'll get problems if you enable CONFIG_RTC_DRV_MAX77686. Setup the interrupt properly in the device tree. Signed-off-by: Doug Anderson Tested-by: Marc Zyngier Signed-off-by: Olof Johansson Signed-off-by: Greg Kroah-Hartman --- arch/arm/boot/dts/cros5250-common.dtsi | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm/boot/dts/cros5250-common.dtsi b/arch/arm/boot/dts/cros5250-common.dtsi index 3f0239ec1bc5..49d8da2779a6 100644 --- a/arch/arm/boot/dts/cros5250-common.dtsi +++ b/arch/arm/boot/dts/cros5250-common.dtsi @@ -27,6 +27,13 @@ i2c2_bus: i2c2-bus { samsung,pin-pud = <0>; }; + + max77686_irq: max77686-irq { + samsung,pins = "gpx3-2"; + samsung,pin-function = <0>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; }; i2c@12C60000 { @@ -35,6 +42,11 @@ max77686@09 { compatible = "maxim,max77686"; + interrupt-parent = <&gpx3>; + interrupts = <2 0>; + pinctrl-names = "default"; + pinctrl-0 = <&max77686_irq>; + wakeup-source; reg = <0x09>; voltage-regulators { -- cgit v1.2.3 From e7b2933095b228e2e668bd191b4fddeff4f21815 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Mon, 25 Nov 2013 20:35:42 -0700 Subject: ARM: bcm2835: add missing #xxx-cells to I2C nodes commit a31ab44ef5d07c6707df4a9ad2c8affd2d62ff4b upstream. The I2C controller node needs #address-cells and #size-cells properties, but these are currently missing. Add them. This allows child nodes to be parsed correctly. Signed-off-by: Stephen Warren Signed-off-by: Olof Johansson Signed-off-by: Greg Kroah-Hartman --- arch/arm/boot/dts/bcm2835.dtsi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/boot/dts/bcm2835.dtsi b/arch/arm/boot/dts/bcm2835.dtsi index 1e12aeff403b..aa537ed13f0a 100644 --- a/arch/arm/boot/dts/bcm2835.dtsi +++ b/arch/arm/boot/dts/bcm2835.dtsi @@ -85,6 +85,8 @@ reg = <0x7e205000 0x1000>; interrupts = <2 21>; clocks = <&clk_i2c>; + #address-cells = <1>; + #size-cells = <0>; status = "disabled"; }; @@ -93,6 +95,8 @@ reg = <0x7e804000 0x1000>; interrupts = <2 21>; clocks = <&clk_i2c>; + #address-cells = <1>; + #size-cells = <0>; status = "disabled"; }; -- cgit v1.2.3 From af8888ac768fbe9d2e526329e632700c1ff6b2fa Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 18 Nov 2013 15:22:49 -0800 Subject: gpio: twl4030: Fix regression for twl gpio output commit 0b2aa8bed3e13892fcac77e4f50ec6e80125469d upstream. Commit c111feabe2e2 (gpio: twl4030: Cache the direction and output states in private data) improved things in general, but caused a regression for setting the GPIO output direction. The change reorganized twl_direction_out() and twl_set() and swapped the function names around in the process. While doing that, a bug got introduced that's not obvious while reading the patch as it appears as no change to the code. The bug is we now call function twl4030_set_gpio_dataout() twice in both twl_direction_out() and twl_set(). Instead, we should first call twl_direction_out() in twl_direction_out() followed by twl4030_set_gpio_dataout() in twl_set(). This regression probably has gone unnoticed for a long time as the bootloader may have set the GPIO direction properly in many cases. This fixes at least the LCD panel not turning on omap3 LDP for example. Cc: linux-gpio@vger.kernel.org Reviewed-by: Peter Ujfalusi Acked-by: Linus Walleij Signed-off-by: Tony Lindgren Signed-off-by: Greg Kroah-Hartman --- drivers/gpio/gpio-twl4030.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-twl4030.c b/drivers/gpio/gpio-twl4030.c index 4d330e36da1d..ed1d10ae1999 100644 --- a/drivers/gpio/gpio-twl4030.c +++ b/drivers/gpio/gpio-twl4030.c @@ -354,17 +354,18 @@ static void twl_set(struct gpio_chip *chip, unsigned offset, int value) static int twl_direction_out(struct gpio_chip *chip, unsigned offset, int value) { struct gpio_twl4030_priv *priv = to_gpio_twl4030(chip); + int ret = -EINVAL; mutex_lock(&priv->mutex); if (offset < TWL4030_GPIO_MAX) - twl4030_set_gpio_dataout(offset, value); + ret = twl4030_set_gpio_direction(offset, 0); priv->direction |= BIT(offset); mutex_unlock(&priv->mutex); twl_set(chip, offset, value); - return 0; + return ret; } static int twl_to_irq(struct gpio_chip *chip, unsigned offset) -- cgit v1.2.3 From aeb94017f672ba2ca8592e7d91fbcc0c3ff63031 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 7 Nov 2013 10:50:19 +0300 Subject: gpio: mvebu: make mvchip->irqbase signed for error handling commit d535922691fc026479fcc03e78ac3d931a54e75a upstream. There is a bug in mvebu_gpio_probe() where we do: mvchip->irqbase = irq_alloc_descs(-1, 0, ngpios, -1); if (mvchip->irqbase < 0) { The problem is that mvchip->irqbase is unsigned so the error handling doesn't work. I have changed it to be a regular int. Signed-off-by: Dan Carpenter Signed-off-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman --- drivers/gpio/gpio-mvebu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index 3a4816adc137..5c27da6a2853 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c @@ -79,7 +79,7 @@ struct mvebu_gpio_chip { spinlock_t lock; void __iomem *membase; void __iomem *percpu_membase; - unsigned int irqbase; + int irqbase; struct irq_domain *domain; int soc_variant; }; -- cgit v1.2.3 From a878002b71bf238810b6e2a885455601222ac140 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 7 Nov 2013 10:56:51 +0300 Subject: gpio: rcar: NULL dereference on error in probe() commit 0c8aab8e65e450f2bfea494c1b6a86ded653f88c upstream. It's not obvious from the label name but "err1" tries to release "p->irq_domain" which leads to a NULL dereference. Fixes: 119f5e448d32 ('gpio: Renesas R-Car GPIO driver V3') Signed-off-by: Dan Carpenter Acked-by: Magnus Damm Signed-off-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman --- drivers/gpio/gpio-rcar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c index b4ca450947b8..c45ad478f462 100644 --- a/drivers/gpio/gpio-rcar.c +++ b/drivers/gpio/gpio-rcar.c @@ -329,7 +329,7 @@ static int gpio_rcar_probe(struct platform_device *pdev) if (!p->irq_domain) { ret = -ENXIO; dev_err(&pdev->dev, "cannot initialize irq domain\n"); - goto err1; + goto err0; } if (devm_request_irq(&pdev->dev, irq->start, -- cgit v1.2.3 From 929742b8d766876b34f92fd3e40aed8d189dade4 Mon Sep 17 00:00:00 2001 From: Gwendal Grignou Date: Fri, 25 Oct 2013 16:28:57 -0700 Subject: libata: Fix display of sata speed commit 3e85c3ecbc520751324a191d23bb94873ed01b10 upstream. 6.0 Gbps link speed was not decoded properly: speed was reported at 3.0 Gbps only. Tested: On a machine where libata reports 6.0 Gbps in /var/log/messages: ata1: SATA link up 6.0 Gbps (SStatus 133 SControl 300) Before: cat /sys/class/ata_link/link1/sata_spd 3.0 Gbps After: cat /sys/class/ata_link/link1/sata_spd 6.0 Gbps Signed-off-by: Gwendal Grignou Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- drivers/ata/libata-transport.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/ata/libata-transport.c b/drivers/ata/libata-transport.c index c04d393d20c1..08e67285645b 100644 --- a/drivers/ata/libata-transport.c +++ b/drivers/ata/libata-transport.c @@ -319,25 +319,25 @@ int ata_tport_add(struct device *parent, /* * ATA link attributes */ +static int noop(int x) { return x; } - -#define ata_link_show_linkspeed(field) \ +#define ata_link_show_linkspeed(field, format) \ static ssize_t \ show_ata_link_##field(struct device *dev, \ struct device_attribute *attr, char *buf) \ { \ struct ata_link *link = transport_class_to_link(dev); \ \ - return sprintf(buf,"%s\n", sata_spd_string(fls(link->field))); \ + return sprintf(buf, "%s\n", sata_spd_string(format(link->field))); \ } -#define ata_link_linkspeed_attr(field) \ - ata_link_show_linkspeed(field) \ +#define ata_link_linkspeed_attr(field, format) \ + ata_link_show_linkspeed(field, format) \ static DEVICE_ATTR(field, S_IRUGO, show_ata_link_##field, NULL) -ata_link_linkspeed_attr(hw_sata_spd_limit); -ata_link_linkspeed_attr(sata_spd_limit); -ata_link_linkspeed_attr(sata_spd); +ata_link_linkspeed_attr(hw_sata_spd_limit, fls); +ata_link_linkspeed_attr(sata_spd_limit, fls); +ata_link_linkspeed_attr(sata_spd, noop); static DECLARE_TRANSPORT_CLASS(ata_link_class, -- cgit v1.2.3 From 922b22ffb72220e659e58fec784e11dec9922ec4 Mon Sep 17 00:00:00 2001 From: Shan Hai Date: Mon, 28 Oct 2013 16:08:01 +0800 Subject: drivers/libata: Set max sector to 65535 for Slimtype DVD A DS8A9SH drive commit 0523f037f65dba10191b0fa9c51266f90ba64630 upstream. The "Slimtype DVD A DS8A9SH" drive locks up with following backtrace when the max sector is smaller than 65535 bytes, fix it by adding a quirk to set the max sector to 65535 bytes. INFO: task flush-11:0:663 blocked for more than 120 seconds. "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. flush-11:0 D 00000000ffff5ceb 0 663 2 0x00000000 ffff88026d3b1710 0000000000000046 0000000000000001 0000000000000000 ffff88026f2530c0 ffff88026d365860 ffff88026d3b16e0 ffffffff812ffd52 ffff88026d4fd3d0 0000000100000001 ffff88026d3b16f0 ffff88026d3b1fd8 Call Trace: [] ? cfq_may_queue+0x52/0xf0 [] schedule+0x18/0x30 [] io_schedule+0x42/0x60 [] get_request_wait+0xeb/0x1f0 [] ? autoremove_wake_function+0x0/0x40 [] ? elv_merge+0x42/0x210 [] __make_request+0x8e/0x4e0 [] generic_make_request+0x21e/0x5e0 [] submit_bio+0x5d/0xd0 [] submit_bh+0xf2/0x130 [] __block_write_full_page+0x1dc/0x3a0 [] ? end_buffer_async_write+0x0/0x120 [] ? blkdev_get_block+0x0/0x70 [] ? blkdev_get_block+0x0/0x70 [] ? end_buffer_async_write+0x0/0x120 [] block_write_full_page_endio+0xde/0x100 [] block_write_full_page+0x10/0x20 [] blkdev_writepage+0x13/0x20 [] __writepage+0x15/0x40 [] write_cache_pages+0x1cf/0x3e0 [] ? __writepage+0x0/0x40 [] generic_writepages+0x22/0x30 [] do_writepages+0x1f/0x40 [] writeback_single_inode+0xe7/0x3b0 [] writeback_sb_inodes+0x184/0x280 [] writeback_inodes_wb+0x6b/0x1a0 [] wb_writeback+0x23b/0x2a0 [] wb_do_writeback+0x17d/0x190 [] bdi_writeback_task+0x4b/0xe0 [] ? bdi_start_fn+0x0/0x100 [] bdi_start_fn+0x81/0x100 [] ? bdi_start_fn+0x0/0x100 [] kthread+0x8e/0xa0 [] ? finish_task_switch+0x54/0xc0 [] kernel_thread_helper+0x4/0x10 [] ? kthread+0x0/0xa0 [] ? kernel_thread_helper+0x0/0x10 The above trace was triggered by "dd if=/dev/zero of=/dev/sr0 bs=2048 count=32768" Signed-off-by: Shan Hai Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- drivers/ata/libata-core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index adf002a3c584..cd6aa28a8143 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4110,6 +4110,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { { "TORiSAN DVD-ROM DRD-N216", NULL, ATA_HORKAGE_MAX_SEC_128 }, { "QUANTUM DAT DAT72-000", NULL, ATA_HORKAGE_ATAPI_MOD16_DMA }, { "Slimtype DVD A DS8A8SH", NULL, ATA_HORKAGE_MAX_SEC_LBA48 }, + { "Slimtype DVD A DS8A9SH", NULL, ATA_HORKAGE_MAX_SEC_LBA48 }, /* Devices we expect to fail diagnostics */ -- cgit v1.2.3 From 7135a8a100fb1bc8d15f90a31e72faccdb4d7118 Mon Sep 17 00:00:00 2001 From: Ryan Mallon Date: Tue, 12 Nov 2013 15:08:51 -0800 Subject: vsprintf: check real user/group id for %pK commit 312b4e226951f707e120b95b118cbc14f3d162b2 upstream. Some setuid binaries will allow reading of files which have read permission by the real user id. This is problematic with files which use %pK because the file access permission is checked at open() time, but the kptr_restrict setting is checked at read() time. If a setuid binary opens a %pK file as an unprivileged user, and then elevates permissions before reading the file, then kernel pointer values may be leaked. This happens for example with the setuid pppd application on Ubuntu 12.04: $ head -1 /proc/kallsyms 00000000 T startup_32 $ pppd file /proc/kallsyms pppd: In file /proc/kallsyms: unrecognized option 'c1000000' This will only leak the pointer value from the first line, but other setuid binaries may leak more information. Fix this by adding a check that in addition to the current process having CAP_SYSLOG, that effective user and group ids are equal to the real ids. If a setuid binary reads the contents of a file which uses %pK then the pointer values will be printed as NULL if the real user is unprivileged. Update the sysctl documentation to reflect the changes, and also correct the documentation to state the kptr_restrict=0 is the default. This is a only temporary solution to the issue. The correct solution is to do the permission check at open() time on files, and to replace %pK with a function which checks the open() time permission. %pK uses in printk should be removed since no sane permission check can be done, and instead protected by using dmesg_restrict. Signed-off-by: Ryan Mallon Cc: Kees Cook Cc: Alexander Viro Cc: Joe Perches Cc: "Eric W. Biederman" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- Documentation/sysctl/kernel.txt | 25 ++++++++++++++++++------- lib/vsprintf.c | 33 ++++++++++++++++++++++++++++++--- 2 files changed, 48 insertions(+), 10 deletions(-) diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt index ccd42589e124..9b34b1685078 100644 --- a/Documentation/sysctl/kernel.txt +++ b/Documentation/sysctl/kernel.txt @@ -289,13 +289,24 @@ Default value is "/sbin/hotplug". kptr_restrict: This toggle indicates whether restrictions are placed on -exposing kernel addresses via /proc and other interfaces. When -kptr_restrict is set to (0), there are no restrictions. When -kptr_restrict is set to (1), the default, kernel pointers -printed using the %pK format specifier will be replaced with 0's -unless the user has CAP_SYSLOG. When kptr_restrict is set to -(2), kernel pointers printed using %pK will be replaced with 0's -regardless of privileges. +exposing kernel addresses via /proc and other interfaces. + +When kptr_restrict is set to (0), the default, there are no restrictions. + +When kptr_restrict is set to (1), kernel pointers printed using the %pK +format specifier will be replaced with 0's unless the user has CAP_SYSLOG +and effective user and group ids are equal to the real ids. This is +because %pK checks are done at read() time rather than open() time, so +if permissions are elevated between the open() and the read() (e.g via +a setuid binary) then %pK will not leak kernel pointers to unprivileged +users. Note, this is a temporary solution only. The correct long-term +solution is to do the permission checks at open() time. Consider removing +world read permissions from files that use %pK, and using dmesg_restrict +to protect against uses of %pK in dmesg(8) if leaking kernel pointer +values to unprivileged users is a concern. + +When kptr_restrict is set to (2), kernel pointers printed using +%pK will be replaced with 0's regardless of privileges. ============================================================== diff --git a/lib/vsprintf.c b/lib/vsprintf.c index e149c6416384..620fae4c11f6 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include /* for PAGE_SIZE */ @@ -1118,11 +1119,37 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, spec.field_width = default_width; return string(buf, end, "pK-error", spec); } - if (!((kptr_restrict == 0) || - (kptr_restrict == 1 && - has_capability_noaudit(current, CAP_SYSLOG)))) + + switch (kptr_restrict) { + case 0: + /* Always print %pK values */ + break; + case 1: { + /* + * Only print the real pointer value if the current + * process has CAP_SYSLOG and is running with the + * same credentials it started with. This is because + * access to files is checked at open() time, but %pK + * checks permission at read() time. We don't want to + * leak pointer values if a binary opens a file using + * %pK and then elevates privileges before reading it. + */ + const struct cred *cred = current_cred(); + + if (!has_capability_noaudit(current, CAP_SYSLOG) || + !uid_eq(cred->euid, cred->uid) || + !gid_eq(cred->egid, cred->gid)) + ptr = NULL; + break; + } + case 2: + default: + /* Always print 0's for %pK */ ptr = NULL; + break; + } break; + case 'N': switch (fmt[1]) { case 'F': -- cgit v1.2.3 From aaa3a8c7685d7ce2b779e89f25109e27e0c7c2a7 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Wed, 25 Sep 2013 12:57:48 -0500 Subject: rtlwifi: rtl8188ee: Fix smatch warning in rtl8188ee/hw.c commit dab3df5e88b979f8d09860f873ccfaa7a55758d2 upstream. Smatch lists the following: CHECK drivers/net/wireless/rtlwifi/rtl8188ee/hw.c drivers/net/wireless/rtlwifi/rtl8188ee/hw.c:149 _rtl88ee_set_fw_clock_on() info: ignoring unreachable code. drivers/net/wireless/rtlwifi/rtl8188ee/hw.c:149 _rtl88ee_set_fw_clock_on() info: ignoring unreachable code. This info message is the result of a real error due to a missing break statement in a "while (1)" loop. Signed-off-by: Larry Finger Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/rtlwifi/rtl8188ee/hw.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c b/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c index b68cae3024fc..e06971be7df7 100644 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c @@ -143,6 +143,7 @@ static void _rtl88ee_set_fw_clock_on(struct ieee80211_hw *hw, } else { rtlhal->fw_clk_change_in_progress = false; spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); + break; } } -- cgit v1.2.3 From dea4a8294ab66e105ed689e9ea3f2b2c0e0d4101 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Sat, 2 Nov 2013 14:28:35 -0500 Subject: rtlwifi: Fix endian error in extracting packet type commit 0c5d63f0ab6728f05ddefa25aff55e31297f95e6 upstream. All of the rtlwifi drivers have an error in the routine that tests if the data is "special". If it is, the subsequant transmission will be at the lowest rate to enhance reliability. The 16-bit quantity is big-endian, but was being extracted in native CPU mode. One of the effects of this bug is to inhibit association under some conditions as the TX rate is too high. Based on suggestions by Joe Perches, the entire routine is rewritten. One of the local headers contained duplicates of some of the ETH_P_XXX definitions. These are deleted. Signed-off-by: Larry Finger Cc: Mark Cave-Ayland Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/rtlwifi/base.c | 93 ++++++++++++++++--------------------- drivers/net/wireless/rtlwifi/wifi.h | 6 +-- 2 files changed, 42 insertions(+), 57 deletions(-) diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c index af59dd5718e1..3698028c910d 100644 --- a/drivers/net/wireless/rtlwifi/base.c +++ b/drivers/net/wireless/rtlwifi/base.c @@ -37,6 +37,7 @@ #include #include +#include /* *NOTICE!!!: This file will be very big, we should @@ -1066,64 +1067,52 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) if (!ieee80211_is_data(fc)) return false; + ip = (const struct iphdr *)(skb->data + mac_hdr_len + + SNAP_SIZE + PROTOC_TYPE_SIZE); + ether_type = be16_to_cpup((__be16 *) + (skb->data + mac_hdr_len + SNAP_SIZE)); - ip = (struct iphdr *)((u8 *) skb->data + mac_hdr_len + - SNAP_SIZE + PROTOC_TYPE_SIZE); - ether_type = *(u16 *) ((u8 *) skb->data + mac_hdr_len + SNAP_SIZE); - /* ether_type = ntohs(ether_type); */ - - if (ETH_P_IP == ether_type) { - if (IPPROTO_UDP == ip->protocol) { - struct udphdr *udp = (struct udphdr *)((u8 *) ip + - (ip->ihl << 2)); - if (((((u8 *) udp)[1] == 68) && - (((u8 *) udp)[3] == 67)) || - ((((u8 *) udp)[1] == 67) && - (((u8 *) udp)[3] == 68))) { - /* - * 68 : UDP BOOTP client - * 67 : UDP BOOTP server - */ - RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), - DBG_DMESG, "dhcp %s !!\n", - is_tx ? "Tx" : "Rx"); - - if (is_tx) { - rtlpriv->enter_ps = false; - schedule_work(&rtlpriv-> - works.lps_change_work); - ppsc->last_delaylps_stamp_jiffies = - jiffies; - } + switch (ether_type) { + case ETH_P_IP: { + struct udphdr *udp; + u16 src; + u16 dst; - return true; - } - } - } else if (ETH_P_ARP == ether_type) { - if (is_tx) { - rtlpriv->enter_ps = false; - schedule_work(&rtlpriv->works.lps_change_work); - ppsc->last_delaylps_stamp_jiffies = jiffies; - } + if (ip->protocol != IPPROTO_UDP) + return false; + udp = (struct udphdr *)((u8 *)ip + (ip->ihl << 2)); + src = be16_to_cpu(udp->source); + dst = be16_to_cpu(udp->dest); - return true; - } else if (ETH_P_PAE == ether_type) { + /* If this case involves port 68 (UDP BOOTP client) connecting + * with port 67 (UDP BOOTP server), then return true so that + * the lowest speed is used. + */ + if (!((src == 68 && dst == 67) || (src == 67 && dst == 68))) + return false; + + RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG, + "dhcp %s !!\n", is_tx ? "Tx" : "Rx"); + break; + } + case ETH_P_ARP: + break; + case ETH_P_PAE: RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG, "802.1X %s EAPOL pkt!!\n", is_tx ? "Tx" : "Rx"); - - if (is_tx) { - rtlpriv->enter_ps = false; - schedule_work(&rtlpriv->works.lps_change_work); - ppsc->last_delaylps_stamp_jiffies = jiffies; - } - - return true; - } else if (ETH_P_IPV6 == ether_type) { - /* IPv6 */ - return true; + break; + case ETH_P_IPV6: + /* TODO: Is this right? */ + return false; + default: + return false; } - - return false; + if (is_tx) { + rtlpriv->enter_ps = false; + schedule_work(&rtlpriv->works.lps_change_work); + ppsc->last_delaylps_stamp_jiffies = jiffies; + } + return true; } /********************************************************* diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h index 703258742d28..ad9c37a42709 100644 --- a/drivers/net/wireless/rtlwifi/wifi.h +++ b/drivers/net/wireless/rtlwifi/wifi.h @@ -77,11 +77,7 @@ #define RTL_SLOT_TIME_9 9 #define RTL_SLOT_TIME_20 20 -/*related with tcp/ip. */ -/*if_ehther.h*/ -#define ETH_P_PAE 0x888E /*Port Access Entity (IEEE 802.1X) */ -#define ETH_P_IP 0x0800 /*Internet Protocol packet */ -#define ETH_P_ARP 0x0806 /*Address Resolution packet */ +/*related to tcp/ip. */ #define SNAP_SIZE 6 #define PROTOC_TYPE_SIZE 2 -- cgit v1.2.3 From d6843050f97d777d843d113d3214cc04ca31bcca Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Fri, 18 Oct 2013 21:52:40 -0300 Subject: rtlwifi: rtl8192se: Fix wrong assignment commit 3aef7dde8dcf09e0124f0a2665845a507331972b upstream. There is a typo in the struct member name on assignment when checking rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40, the check uses pwrgroup_ht40 for bound limit and uses pwrgroup_ht20 when assigning instead. Signed-off-by: Felipe Pena Acked-by: Larry Finger Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/rtlwifi/rtl8192se/rf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/rf.c b/drivers/net/wireless/rtlwifi/rtl8192se/rf.c index 5061f1db3f02..92d38ab3c60e 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/rf.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/rf.c @@ -265,7 +265,7 @@ static void _rtl92s_get_txpower_writeval_byregulatory(struct ieee80211_hw *hw, rtlefuse->pwrgroup_ht40 [RF90_PATH_A][chnl - 1]) { pwrdiff_limit[i] = - rtlefuse->pwrgroup_ht20 + rtlefuse->pwrgroup_ht40 [RF90_PATH_A][chnl - 1]; } } else { -- cgit v1.2.3 From bfe84321327047afc355bcfc4c0bd30c25fddccc Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Sun, 10 Nov 2013 22:11:16 -0600 Subject: rtlwifi: rtl8192cu: Fix more pointer arithmetic errors commit eafbdde9c5629bea58df07275c5917eb42afbbe7 upstream. This driver uses a number of macros to get and set various fields in the RX and TX descriptors. To work correctly, a u8 pointer to the descriptor must be used; however, in some cases a descriptor structure pointer is used instead. In addition, a duplicated statement is removed. Signed-off-by: Larry Finger Reported-by: Mark Cave-Ayland Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/rtlwifi/rtl8192cu/mac.c | 6 +++--- drivers/net/wireless/rtlwifi/rtl8192cu/trx.c | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c index da4f587199ee..2c68c138912f 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c @@ -778,7 +778,7 @@ static long _rtl92c_signal_scale_mapping(struct ieee80211_hw *hw, static void _rtl92c_query_rxphystatus(struct ieee80211_hw *hw, struct rtl_stats *pstats, - struct rx_desc_92c *pdesc, + struct rx_desc_92c *p_desc, struct rx_fwinfo_92c *p_drvinfo, bool packet_match_bssid, bool packet_toself, @@ -793,11 +793,11 @@ static void _rtl92c_query_rxphystatus(struct ieee80211_hw *hw, u32 rssi, total_rssi = 0; bool in_powersavemode = false; bool is_cck_rate; + u8 *pdesc = (u8 *)p_desc; - is_cck_rate = RX_HAL_IS_CCK_RATE(pdesc); + is_cck_rate = RX_HAL_IS_CCK_RATE(p_desc); pstats->packet_matchbssid = packet_match_bssid; pstats->packet_toself = packet_toself; - pstats->is_cck = is_cck_rate; pstats->packet_beacon = packet_beacon; pstats->is_cck = is_cck_rate; pstats->RX_SIGQ[0] = -1; diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c index 5a060e537fbe..5dfe7e2513ae 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c @@ -303,10 +303,10 @@ out: bool rtl92cu_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats, struct ieee80211_rx_status *rx_status, - u8 *p_desc, struct sk_buff *skb) + u8 *pdesc, struct sk_buff *skb) { struct rx_fwinfo_92c *p_drvinfo; - struct rx_desc_92c *pdesc = (struct rx_desc_92c *)p_desc; + struct rx_desc_92c *p_desc = (struct rx_desc_92c *)pdesc; u32 phystatus = GET_RX_DESC_PHY_STATUS(pdesc); stats->length = (u16) GET_RX_DESC_PKT_LEN(pdesc); @@ -345,7 +345,7 @@ bool rtl92cu_rx_query_desc(struct ieee80211_hw *hw, if (phystatus) { p_drvinfo = (struct rx_fwinfo_92c *)(skb->data + stats->rx_bufshift); - rtl92c_translate_rx_signal_stuff(hw, skb, stats, pdesc, + rtl92c_translate_rx_signal_stuff(hw, skb, stats, p_desc, p_drvinfo); } /*rx_status->qual = stats->signal; */ -- cgit v1.2.3 From 4b825b95aaa48c706d24c804f7edff228bd6af70 Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Tue, 12 Nov 2013 15:11:47 -0800 Subject: ipc, msg: fix message length check for negative values commit 4e9b45a19241354daec281d7a785739829b52359 upstream. On 64 bit systems the test for negative message sizes is bogus as the size, which may be positive when evaluated as a long, will get truncated to an int when passed to load_msg(). So a long might very well contain a positive value but when truncated to an int it would become negative. That in combination with a small negative value of msg_ctlmax (which will be promoted to an unsigned type for the comparison against msgsz, making it a big positive value and therefore make it pass the check) will lead to two problems: 1/ The kmalloc() call in alloc_msg() will allocate a too small buffer as the addition of alen is effectively a subtraction. 2/ The copy_from_user() call in load_msg() will first overflow the buffer with userland data and then, when the userland access generates an access violation, the fixup handler copy_user_handle_tail() will try to fill the remainder with zeros -- roughly 4GB. That almost instantly results in a system crash or reset. ,-[ Reproducer (needs to be run as root) ]-- | #include | #include | #include | #include | | int main(void) { | long msg = 1; | int fd; | | fd = open("/proc/sys/kernel/msgmax", O_WRONLY); | write(fd, "-1", 2); | close(fd); | | msgsnd(0, &msg, 0xfffffff0, IPC_NOWAIT); | | return 0; | } '--- Fix the issue by preventing msgsz from getting truncated by consistently using size_t for the message length. This way the size checks in do_msgsnd() could still be passed with a negative value for msg_ctlmax but we would fail on the buffer allocation in that case and error out. Also change the type of m_ts from int to size_t to avoid similar nastiness in other code paths -- it is used in similar constructs, i.e. signed vs. unsigned checks. It should never become negative under normal circumstances, though. Setting msg_ctlmax to a negative value is an odd configuration and should be prevented. As that might break existing userland, it will be handled in a separate commit so it could easily be reverted and reworked without reintroducing the above described bug. Hardening mechanisms for user copy operations would have catched that bug early -- e.g. checking slab object sizes on user copy operations as the usercopy feature of the PaX patch does. Or, for that matter, detect the long vs. int sign change due to truncation, as the size overflow plugin of the very same patch does. [akpm@linux-foundation.org: fix i386 min() warnings] Signed-off-by: Mathias Krause Cc: Pax Team Cc: Davidlohr Bueso Cc: Brad Spengler Cc: Manfred Spraul Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- include/linux/msg.h | 6 +++--- ipc/msgutil.c | 20 ++++++++++---------- ipc/util.h | 4 ++-- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/include/linux/msg.h b/include/linux/msg.h index 391af8d11cce..e21f9d44307f 100644 --- a/include/linux/msg.h +++ b/include/linux/msg.h @@ -6,9 +6,9 @@ /* one msg_msg structure for each message */ struct msg_msg { - struct list_head m_list; - long m_type; - int m_ts; /* message text size */ + struct list_head m_list; + long m_type; + size_t m_ts; /* message text size */ struct msg_msgseg* next; void *security; /* the actual message follows immediately */ diff --git a/ipc/msgutil.c b/ipc/msgutil.c index 491e71f2a1b8..7e7095974d54 100644 --- a/ipc/msgutil.c +++ b/ipc/msgutil.c @@ -41,15 +41,15 @@ struct msg_msgseg { /* the next part of the message follows immediately */ }; -#define DATALEN_MSG (int)(PAGE_SIZE-sizeof(struct msg_msg)) -#define DATALEN_SEG (int)(PAGE_SIZE-sizeof(struct msg_msgseg)) +#define DATALEN_MSG ((size_t)PAGE_SIZE-sizeof(struct msg_msg)) +#define DATALEN_SEG ((size_t)PAGE_SIZE-sizeof(struct msg_msgseg)) -static struct msg_msg *alloc_msg(int len) +static struct msg_msg *alloc_msg(size_t len) { struct msg_msg *msg; struct msg_msgseg **pseg; - int alen; + size_t alen; alen = min(len, DATALEN_MSG); msg = kmalloc(sizeof(*msg) + alen, GFP_KERNEL); @@ -80,12 +80,12 @@ out_err: return NULL; } -struct msg_msg *load_msg(const void __user *src, int len) +struct msg_msg *load_msg(const void __user *src, size_t len) { struct msg_msg *msg; struct msg_msgseg *seg; int err = -EFAULT; - int alen; + size_t alen; msg = alloc_msg(len); if (msg == NULL) @@ -117,8 +117,8 @@ out_err: struct msg_msg *copy_msg(struct msg_msg *src, struct msg_msg *dst) { struct msg_msgseg *dst_pseg, *src_pseg; - int len = src->m_ts; - int alen; + size_t len = src->m_ts; + size_t alen; BUG_ON(dst == NULL); if (src->m_ts > dst->m_ts) @@ -147,9 +147,9 @@ struct msg_msg *copy_msg(struct msg_msg *src, struct msg_msg *dst) return ERR_PTR(-ENOSYS); } #endif -int store_msg(void __user *dest, struct msg_msg *msg, int len) +int store_msg(void __user *dest, struct msg_msg *msg, size_t len) { - int alen; + size_t alen; struct msg_msgseg *seg; alen = min(len, DATALEN_MSG); diff --git a/ipc/util.h b/ipc/util.h index f2f5036f2eed..59d78aa94987 100644 --- a/ipc/util.h +++ b/ipc/util.h @@ -148,9 +148,9 @@ int ipc_parse_version (int *cmd); #endif extern void free_msg(struct msg_msg *msg); -extern struct msg_msg *load_msg(const void __user *src, int len); +extern struct msg_msg *load_msg(const void __user *src, size_t len); extern struct msg_msg *copy_msg(struct msg_msg *src, struct msg_msg *dst); -extern int store_msg(void __user *dest, struct msg_msg *msg, int len); +extern int store_msg(void __user *dest, struct msg_msg *msg, size_t len); extern void recompute_msgmni(struct ipc_namespace *); -- cgit v1.2.3 From a12503f53b7555a639869527d47eef61ff33cd00 Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Sun, 3 Nov 2013 12:36:28 +0100 Subject: ipc, msg: forbid negative values for "msg{max,mnb,mni}" commit 9bf76ca325d5e9208eb343f7bd4cc666f703ed30 upstream. Negative message lengths make no sense -- so don't do negative queue lenghts or identifier counts. Prevent them from getting negative. Also change the underlying data types to be unsigned to avoid hairy surprises with sign extensions in cases where those variables get evaluated in unsigned expressions with bigger data types, e.g size_t. In case a user still wants to have "unlimited" sizes she could just use INT_MAX instead. Signed-off-by: Mathias Krause Cc: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- include/linux/ipc_namespace.h | 6 +++--- ipc/ipc_sysctl.c | 20 ++++++++++++-------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/include/linux/ipc_namespace.h b/include/linux/ipc_namespace.h index 19c19a5eee29..f6c82de12541 100644 --- a/include/linux/ipc_namespace.h +++ b/include/linux/ipc_namespace.h @@ -34,9 +34,9 @@ struct ipc_namespace { int sem_ctls[4]; int used_sems; - int msg_ctlmax; - int msg_ctlmnb; - int msg_ctlmni; + unsigned int msg_ctlmax; + unsigned int msg_ctlmnb; + unsigned int msg_ctlmni; atomic_t msg_bytes; atomic_t msg_hdrs; int auto_msgmni; diff --git a/ipc/ipc_sysctl.c b/ipc/ipc_sysctl.c index 130dfece27ac..b0e99deb6d05 100644 --- a/ipc/ipc_sysctl.c +++ b/ipc/ipc_sysctl.c @@ -62,7 +62,7 @@ static int proc_ipc_dointvec_minmax_orphans(ctl_table *table, int write, return err; } -static int proc_ipc_callback_dointvec(ctl_table *table, int write, +static int proc_ipc_callback_dointvec_minmax(ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { struct ctl_table ipc_table; @@ -72,7 +72,7 @@ static int proc_ipc_callback_dointvec(ctl_table *table, int write, memcpy(&ipc_table, table, sizeof(ipc_table)); ipc_table.data = get_ipc(table); - rc = proc_dointvec(&ipc_table, write, buffer, lenp, ppos); + rc = proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos); if (write && !rc && lenp_bef == *lenp) /* @@ -152,15 +152,13 @@ static int proc_ipcauto_dointvec_minmax(ctl_table *table, int write, #define proc_ipc_dointvec NULL #define proc_ipc_dointvec_minmax NULL #define proc_ipc_dointvec_minmax_orphans NULL -#define proc_ipc_callback_dointvec NULL +#define proc_ipc_callback_dointvec_minmax NULL #define proc_ipcauto_dointvec_minmax NULL #endif static int zero; static int one = 1; -#ifdef CONFIG_CHECKPOINT_RESTORE static int int_max = INT_MAX; -#endif static struct ctl_table ipc_kern_table[] = { { @@ -198,21 +196,27 @@ static struct ctl_table ipc_kern_table[] = { .data = &init_ipc_ns.msg_ctlmax, .maxlen = sizeof (init_ipc_ns.msg_ctlmax), .mode = 0644, - .proc_handler = proc_ipc_dointvec, + .proc_handler = proc_ipc_dointvec_minmax, + .extra1 = &zero, + .extra2 = &int_max, }, { .procname = "msgmni", .data = &init_ipc_ns.msg_ctlmni, .maxlen = sizeof (init_ipc_ns.msg_ctlmni), .mode = 0644, - .proc_handler = proc_ipc_callback_dointvec, + .proc_handler = proc_ipc_callback_dointvec_minmax, + .extra1 = &zero, + .extra2 = &int_max, }, { .procname = "msgmnb", .data = &init_ipc_ns.msg_ctlmnb, .maxlen = sizeof (init_ipc_ns.msg_ctlmnb), .mode = 0644, - .proc_handler = proc_ipc_dointvec, + .proc_handler = proc_ipc_dointvec_minmax, + .extra1 = &zero, + .extra2 = &int_max, }, { .procname = "sem", -- cgit v1.2.3 From 3f47cff85a8737780a5eba628cae112cd07496de Mon Sep 17 00:00:00 2001 From: Davidlohr Bueso Date: Wed, 16 Oct 2013 13:46:45 -0700 Subject: ipc: update locking scheme comments commit 18ccee263c7e250a57f01c9434658f11f4118a64 upstream. The initial documentation was a bit incomplete, update accordingly. [akpm@linux-foundation.org: make it more readable in 80 columns] Signed-off-by: Davidlohr Bueso Acked-by: Manfred Spraul Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- ipc/util.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/ipc/util.c b/ipc/util.c index fdb8ae740775..7684f41bce76 100644 --- a/ipc/util.c +++ b/ipc/util.c @@ -17,12 +17,27 @@ * Pavel Emelianov * * General sysv ipc locking scheme: - * when doing ipc id lookups, take the ids->rwsem - * rcu_read_lock() - * obtain the ipc object (kern_ipc_perm) - * perform security, capabilities, auditing and permission checks, etc. - * acquire the ipc lock (kern_ipc_perm.lock) throught ipc_lock_object() - * perform data updates (ie: SET, RMID, LOCK/UNLOCK commands) + * rcu_read_lock() + * obtain the ipc object (kern_ipc_perm) by looking up the id in an idr + * tree. + * - perform initial checks (capabilities, auditing and permission, + * etc). + * - perform read-only operations, such as STAT, INFO commands. + * acquire the ipc lock (kern_ipc_perm.lock) through + * ipc_lock_object() + * - perform data updates, such as SET, RMID commands and + * mechanism-specific operations (semop/semtimedop, + * msgsnd/msgrcv, shmat/shmdt). + * drop the ipc lock, through ipc_unlock_object(). + * rcu_read_unlock() + * + * The ids->rwsem must be taken when: + * - creating, removing and iterating the existing entries in ipc + * identifier sets. + * - iterating through files under /proc/sysvipc/ + * + * Note that sems have a special fast path that avoids kern_ipc_perm.lock - + * see sem_lock(). */ #include -- cgit v1.2.3 From 873be93b1af2d62b6541b053f99a46771f5d9234 Mon Sep 17 00:00:00 2001 From: Manfred Spraul Date: Wed, 16 Oct 2013 13:46:45 -0700 Subject: ipc/sem.c: synchronize semop and semctl with IPC_RMID commit 6e224f94597842c5eb17f1fc2208d20b6f7f7d49 upstream. After acquiring the semlock spinlock, operations must test that the array is still valid. - semctl() and exit_sem() would walk stale linked lists (ugly, but should be ok: all lists are empty) - semtimedop() would sleep forever - and if woken up due to a signal - access memory after free. The patch also: - standardizes the tests for .deleted, so that all tests in one function leave the function with the same approach. - unconditionally tests for .deleted immediately after every call to sem_lock - even it it means that for semctl(GETALL), .deleted will be tested twice. Both changes make the review simpler: After every sem_lock, there must be a test of .deleted, followed by a goto to the cleanup code (if the function uses "goto cleanup"). The only exception is semctl_down(): If sem_ids().rwsem is locked, then the presence in ids->ipcs_idr is equivalent to !.deleted, thus no additional test is required. Signed-off-by: Manfred Spraul Cc: Mike Galbraith Acked-by: Davidlohr Bueso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- ipc/sem.c | 42 +++++++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/ipc/sem.c b/ipc/sem.c index 8c4f59b0204a..db9d241af133 100644 --- a/ipc/sem.c +++ b/ipc/sem.c @@ -1282,6 +1282,12 @@ static int semctl_setval(struct ipc_namespace *ns, int semid, int semnum, sem_lock(sma, NULL, -1); + if (sma->sem_perm.deleted) { + sem_unlock(sma, -1); + rcu_read_unlock(); + return -EIDRM; + } + curr = &sma->sem_base[semnum]; ipc_assert_locked_object(&sma->sem_perm); @@ -1336,12 +1342,14 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum, int i; sem_lock(sma, NULL, -1); + if (sma->sem_perm.deleted) { + err = -EIDRM; + goto out_unlock; + } if(nsems > SEMMSL_FAST) { if (!ipc_rcu_getref(sma)) { - sem_unlock(sma, -1); - rcu_read_unlock(); err = -EIDRM; - goto out_free; + goto out_unlock; } sem_unlock(sma, -1); rcu_read_unlock(); @@ -1354,10 +1362,8 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum, rcu_read_lock(); sem_lock_and_putref(sma); if (sma->sem_perm.deleted) { - sem_unlock(sma, -1); - rcu_read_unlock(); err = -EIDRM; - goto out_free; + goto out_unlock; } } for (i = 0; i < sma->sem_nsems; i++) @@ -1375,8 +1381,8 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum, struct sem_undo *un; if (!ipc_rcu_getref(sma)) { - rcu_read_unlock(); - return -EIDRM; + err = -EIDRM; + goto out_rcu_wakeup; } rcu_read_unlock(); @@ -1404,10 +1410,8 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum, rcu_read_lock(); sem_lock_and_putref(sma); if (sma->sem_perm.deleted) { - sem_unlock(sma, -1); - rcu_read_unlock(); err = -EIDRM; - goto out_free; + goto out_unlock; } for (i = 0; i < nsems; i++) @@ -1431,6 +1435,10 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum, goto out_rcu_wakeup; sem_lock(sma, NULL, -1); + if (sma->sem_perm.deleted) { + err = -EIDRM; + goto out_unlock; + } curr = &sma->sem_base[semnum]; switch (cmd) { @@ -1836,6 +1844,10 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops, if (error) goto out_rcu_wakeup; + error = -EIDRM; + locknum = sem_lock(sma, sops, nsops); + if (sma->sem_perm.deleted) + goto out_unlock_free; /* * semid identifiers are not unique - find_alloc_undo may have * allocated an undo structure, it was invalidated by an RMID @@ -1843,8 +1855,6 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops, * This case can be detected checking un->semid. The existence of * "un" itself is guaranteed by rcu. */ - error = -EIDRM; - locknum = sem_lock(sma, sops, nsops); if (un && un->semid == -1) goto out_unlock_free; @@ -2057,6 +2067,12 @@ void exit_sem(struct task_struct *tsk) } sem_lock(sma, NULL, -1); + /* exit_sem raced with IPC_RMID, nothing to do */ + if (sma->sem_perm.deleted) { + sem_unlock(sma, -1); + rcu_read_unlock(); + continue; + } un = __lookup_undo(ulp, semid); if (un == NULL) { /* exit_sem raced with IPC_RMID+semget() that created -- cgit v1.2.3 From 296cfdecbe6cf01b12f6073a521694db2073af5e Mon Sep 17 00:00:00 2001 From: James Ralston Date: Mon, 4 Nov 2013 09:24:58 -0800 Subject: ahci: Add Device IDs for Intel Wildcat Point-LP commit 9f961a5f6efc87a79571d7166257b36af28ffcfe upstream. This patch adds the AHCI-mode SATA Device IDs for the Intel Wildcat Point-LP PCH. Signed-off-by: James Ralston Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- drivers/ata/ahci.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index b112625482ca..84bd54ca73b5 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -292,6 +292,10 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(INTEL, 0x8d66), board_ahci }, /* Wellsburg RAID */ { PCI_VDEVICE(INTEL, 0x8d6e), board_ahci }, /* Wellsburg RAID */ { PCI_VDEVICE(INTEL, 0x23a3), board_ahci }, /* Coleto Creek AHCI */ + { PCI_VDEVICE(INTEL, 0x9c83), board_ahci }, /* Wildcat Point-LP AHCI */ + { PCI_VDEVICE(INTEL, 0x9c85), board_ahci }, /* Wildcat Point-LP RAID */ + { PCI_VDEVICE(INTEL, 0x9c87), board_ahci }, /* Wildcat Point-LP RAID */ + { PCI_VDEVICE(INTEL, 0x9c8f), board_ahci }, /* Wildcat Point-LP RAID */ /* JMicron 360/1/3/5/6, match class to avoid IDE function */ { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, -- cgit v1.2.3 From 420df0f5c514a3d6f44829c2dacfcb44964f6517 Mon Sep 17 00:00:00 2001 From: xiangliang yu Date: Sun, 27 Oct 2013 08:03:04 -0400 Subject: ahci: disabled FBS prior to issuing software reset commit 89dafa20f3daab5b3e0c13d0068a28e8e64e2102 upstream. Tested with Marvell 88se9125, attached with one port mulitplier(5 ports) and one disk, we will get following boot log messages if using current code: ata8: SATA link up 6.0 Gbps (SStatus 133 SControl 330) ata8.15: Port Multiplier 1.2, 0x1b4b:0x9715 r160, 5 ports, feat 0x1/0x1f ahci 0000:03:00.0: FBS is enabled ata8.00: hard resetting link ata8.00: SATA link down (SStatus 0 SControl 330) ata8.01: hard resetting link ata8.01: SATA link down (SStatus 0 SControl 330) ata8.02: hard resetting link ata8.02: SATA link down (SStatus 0 SControl 330) ata8.03: hard resetting link ata8.03: SATA link up 6.0 Gbps (SStatus 133 SControl 133) ata8.04: hard resetting link ata8.04: failed to resume link (SControl 133) ata8.04: failed to read SCR 0 (Emask=0x40) ata8.04: failed to read SCR 0 (Emask=0x40) ata8.04: failed to read SCR 1 (Emask=0x40) ata8.04: failed to read SCR 0 (Emask=0x40) ata8.03: native sectors (2) is smaller than sectors (976773168) ata8.03: ATA-8: ST3500413AS, JC4B, max UDMA/133 ata8.03: 976773168 sectors, multi 0: LBA48 NCQ (depth 31/32) ata8.03: configured for UDMA/133 ata8.04: failed to IDENTIFY (I/O error, err_mask=0x100) ata8.15: hard resetting link ata8.15: SATA link up 6.0 Gbps (SStatus 133 SControl 330) ata8.15: Port Multiplier vendor mismatch '0x1b4b' != '0x133' ata8.15: PMP revalidation failed (errno=-19) ata8.15: hard resetting link ata8.15: SATA link up 6.0 Gbps (SStatus 133 SControl 330) ata8.15: Port Multiplier vendor mismatch '0x1b4b' != '0x133' ata8.15: PMP revalidation failed (errno=-19) ata8.15: limiting SATA link speed to 3.0 Gbps ata8.15: hard resetting link ata8.15: SATA link up 3.0 Gbps (SStatus 123 SControl 320) ata8.15: Port Multiplier vendor mismatch '0x1b4b' != '0x133' ata8.15: PMP revalidation failed (errno=-19) ata8.15: failed to recover PMP after 5 tries, giving up ata8.15: Port Multiplier detaching ata8.03: disabled ata8.00: disabled ata8: EH complete The reason is that current detection code doesn't follow AHCI spec: First,the port multiplier detection process look like this: ahci_hardreset(link, class, deadline) if (class == ATA_DEV_PMP) { sata_pmp_attach(dev) /* will enable FBS */ sata_pmp_init_links(ap, nr_ports); ata_for_each_link(link, ap, EDGE) { sata_std_hardreset(link, class, deadline); if (link_is_online) /* do soft reset */ ahci_softreset(link, class, deadline); } } But, according to chapter 9.3.9 in AHCI spec: Prior to issuing software reset, software shall clear PxCMD.ST to '0' and then clear PxFBS.EN to '0'. The patch test ok with kernel 3.11.1. tj: Patch white space contaminated, applied manually with trivial updates. Signed-off-by: Xiangliang Yu Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- drivers/ata/libahci.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index 7b9bdd822c62..8905e03a53a2 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -1266,9 +1266,11 @@ int ahci_do_softreset(struct ata_link *link, unsigned int *class, { struct ata_port *ap = link->ap; struct ahci_host_priv *hpriv = ap->host->private_data; + struct ahci_port_priv *pp = ap->private_data; const char *reason = NULL; unsigned long now, msecs; struct ata_taskfile tf; + bool fbs_disabled = false; int rc; DPRINTK("ENTER\n"); @@ -1278,6 +1280,16 @@ int ahci_do_softreset(struct ata_link *link, unsigned int *class, if (rc && rc != -EOPNOTSUPP) ata_link_warn(link, "failed to reset engine (errno=%d)\n", rc); + /* + * According to AHCI-1.2 9.3.9: if FBS is enable, software shall + * clear PxFBS.EN to '0' prior to issuing software reset to devices + * that is attached to port multiplier. + */ + if (!ata_is_host_link(link) && pp->fbs_enabled) { + ahci_disable_fbs(ap); + fbs_disabled = true; + } + ata_tf_init(link->device, &tf); /* issue the first D2H Register FIS */ @@ -1318,6 +1330,10 @@ int ahci_do_softreset(struct ata_link *link, unsigned int *class, } else *class = ahci_dev_classify(ap); + /* re-enable FBS if disabled before */ + if (fbs_disabled) + ahci_enable_fbs(ap); + DPRINTK("EXIT, class=%u\n", *class); return 0; -- cgit v1.2.3 From 61688ba3da37952114be1bef89e2f4a3b0217624 Mon Sep 17 00:00:00 2001 From: Samir Benmendil Date: Sun, 17 Nov 2013 23:56:17 +0100 Subject: ahci: add Marvell 9230 to the AHCI PCI device list commit 6d5278a68a75891db1df5ae1ecf83d288fc58c65 upstream. Tested with a DAWICONTROL DC-624e on 3.10.10 Signed-off-by: Samir Benmendil Signed-off-by: Tejun Heo Reviewed-by: Levente Kurusa Signed-off-by: Greg Kroah-Hartman --- drivers/ata/ahci.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 84bd54ca73b5..3d67f76407c1 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -435,6 +435,8 @@ static const struct pci_device_id ahci_pci_tbl[] = { .driver_data = board_ahci_yes_fbs }, /* 88se9172 on some Gigabyte */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a3), .driver_data = board_ahci_yes_fbs }, + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9230), + .driver_data = board_ahci_yes_fbs }, /* Promise */ { PCI_VDEVICE(PROMISE, 0x3f20), board_ahci }, /* PDC42819 */ -- cgit v1.2.3 From cf516effc76c78f948e6eb7cc46d4515003b423d Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Tue, 12 Nov 2013 17:54:56 -0800 Subject: iscsi-target: Fix mutex_trylock usage in iscsit_increment_maxcmdsn commit 5e8e6b4b3adebf01a9d97056cbbfd8c44330df99 upstream. This patch fixes a >= v3.10 regression bug with mutex_trylock() usage within iscsit_increment_maxcmdsn(), that was originally added to allow for a special case where ->cmdsn_mutex was already held from the iscsit_execute_cmd() exception path for ib_isert. When !mutex_trylock() was occuring under contention during normal RX/TX process context codepaths, the bug was manifesting itself as the following protocol error: Received CmdSN: 0x000fcbb7 is greater than MaxCmdSN: 0x000fcbb6, protocol error. Received CmdSN: 0x000fcbb8 is greater than MaxCmdSN: 0x000fcbb6, protocol error. This patch simply avoids the direct ib_isert callback in lio_queue_status() for the special iscsi_execute_cmd() exception cases, that allows the problematic mutex_trylock() usage in iscsit_increment_maxcmdsn() to go away. Reported-by: Moussa Ba Tested-by: Moussa Ba Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman --- drivers/target/iscsi/iscsi_target_configfs.c | 5 +++++ drivers/target/iscsi/iscsi_target_device.c | 6 +----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c index 421344da8b51..c45b3365d63d 100644 --- a/drivers/target/iscsi/iscsi_target_configfs.c +++ b/drivers/target/iscsi/iscsi_target_configfs.c @@ -1650,6 +1650,11 @@ static int lio_queue_status(struct se_cmd *se_cmd) struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd); cmd->i_state = ISTATE_SEND_STATUS; + + if (cmd->se_cmd.scsi_status || cmd->sense_reason) { + iscsit_add_cmd_to_response_queue(cmd, cmd->conn, cmd->i_state); + return 0; + } cmd->conn->conn_transport->iscsit_queue_status(cmd->conn, cmd); return 0; diff --git a/drivers/target/iscsi/iscsi_target_device.c b/drivers/target/iscsi/iscsi_target_device.c index 1b74033510a0..4edcc47c0634 100644 --- a/drivers/target/iscsi/iscsi_target_device.c +++ b/drivers/target/iscsi/iscsi_target_device.c @@ -60,11 +60,7 @@ void iscsit_increment_maxcmdsn(struct iscsi_cmd *cmd, struct iscsi_session *sess cmd->maxcmdsn_inc = 1; - if (!mutex_trylock(&sess->cmdsn_mutex)) { - sess->max_cmd_sn += 1; - pr_debug("Updated MaxCmdSN to 0x%08x\n", sess->max_cmd_sn); - return; - } + mutex_lock(&sess->cmdsn_mutex); sess->max_cmd_sn += 1; pr_debug("Updated MaxCmdSN to 0x%08x\n", sess->max_cmd_sn); mutex_unlock(&sess->cmdsn_mutex); -- cgit v1.2.3 From e97f132f0e66893138f64b681cddff2d2ff37b53 Mon Sep 17 00:00:00 2001 From: Eric Seppanen Date: Wed, 20 Nov 2013 14:19:51 -0800 Subject: iscsi-target: fix extract_param to handle buffer length corner case commit 369653e4fb511928511b0ce81f41c812ff1f28b6 upstream. extract_param() is called with max_length set to the total size of the output buffer. It's not safe to allow a parameter length equal to the buffer size as the terminating null would be written one byte past the end of the output buffer. Signed-off-by: Eric Seppanen Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman --- drivers/target/iscsi/iscsi_target_nego.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/target/iscsi/iscsi_target_nego.c b/drivers/target/iscsi/iscsi_target_nego.c index cd5018ff9cd7..72d9dec991c0 100644 --- a/drivers/target/iscsi/iscsi_target_nego.c +++ b/drivers/target/iscsi/iscsi_target_nego.c @@ -90,7 +90,7 @@ int extract_param( if (len < 0) return -1; - if (len > max_length) { + if (len >= max_length) { pr_err("Length of input: %d exceeds max_length:" " %d\n", len, max_length); return -1; -- cgit v1.2.3 From 6aec95b47deb9e3dad4cb2e6db87f3b03544224d Mon Sep 17 00:00:00 2001 From: Eric Seppanen Date: Wed, 20 Nov 2013 14:19:52 -0800 Subject: iscsi-target: chap auth shouldn't match username with trailing garbage commit 86784c6bdeeef78eed94d298be7a8879f6a97ee2 upstream. In iSCSI negotiations with initiator CHAP enabled, usernames with trailing garbage are permitted, because the string comparison only checks the strlen of the configured username. e.g. "usernameXXXXX" will be permitted to match "username". Just check one more byte so the trailing null char is also matched. Signed-off-by: Eric Seppanen Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman --- drivers/target/iscsi/iscsi_target_auth.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/target/iscsi/iscsi_target_auth.c b/drivers/target/iscsi/iscsi_target_auth.c index cee17543278c..130a1e4f96a1 100644 --- a/drivers/target/iscsi/iscsi_target_auth.c +++ b/drivers/target/iscsi/iscsi_target_auth.c @@ -148,6 +148,7 @@ static int chap_server_compute_md5( unsigned char client_digest[MD5_SIGNATURE_SIZE]; unsigned char server_digest[MD5_SIGNATURE_SIZE]; unsigned char chap_n[MAX_CHAP_N_SIZE], chap_r[MAX_RESPONSE_LENGTH]; + size_t compare_len; struct iscsi_chap *chap = conn->auth_protocol; struct crypto_hash *tfm; struct hash_desc desc; @@ -186,7 +187,9 @@ static int chap_server_compute_md5( goto out; } - if (memcmp(chap_n, auth->userid, strlen(auth->userid)) != 0) { + /* Include the terminating NULL in the compare */ + compare_len = strlen(auth->userid) + 1; + if (strncmp(chap_n, auth->userid, compare_len) != 0) { pr_err("CHAP_N values do not match!\n"); goto out; } -- cgit v1.2.3 From eef5ed304aa7b49b8f58720855dd299163329db2 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Fri, 4 Oct 2013 09:29:06 -0400 Subject: IB/ipath: Convert ipath_user_sdma_pin_pages() to use get_user_pages_fast() commit 4adcf7fb6783e354aab38824d803fa8c4f8e8a27 upstream. ipath_user_sdma_queue_pkts() gets called with mmap_sem held for writing. Except for get_user_pages() deep down in ipath_user_sdma_pin_pages() we don't seem to need mmap_sem at all. Even more interestingly the function ipath_user_sdma_queue_pkts() (and also ipath_user_sdma_coalesce() called somewhat later) call copy_from_user() which can hit a page fault and we deadlock on trying to get mmap_sem when handling that fault. So just make ipath_user_sdma_pin_pages() use get_user_pages_fast() and leave mmap_sem locking for mm. This deadlock has actually been observed in the wild when the node is under memory pressure. Signed-off-by: Jan Kara Signed-off-by: Mike Marciniszyn [ Merged in fix for call to get_user_pages_fast from Tetsuo Handa . - Roland ] Signed-off-by: Roland Dreier Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/hw/ipath/ipath_user_sdma.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/infiniband/hw/ipath/ipath_user_sdma.c b/drivers/infiniband/hw/ipath/ipath_user_sdma.c index f5cb13b21445..cc04b7ba3488 100644 --- a/drivers/infiniband/hw/ipath/ipath_user_sdma.c +++ b/drivers/infiniband/hw/ipath/ipath_user_sdma.c @@ -280,9 +280,7 @@ static int ipath_user_sdma_pin_pages(const struct ipath_devdata *dd, int j; int ret; - ret = get_user_pages(current, current->mm, addr, - npages, 0, 1, pages, NULL); - + ret = get_user_pages_fast(addr, npages, 0, pages); if (ret != npages) { int i; @@ -811,10 +809,7 @@ int ipath_user_sdma_writev(struct ipath_devdata *dd, while (dim) { const int mxp = 8; - down_write(¤t->mm->mmap_sem); ret = ipath_user_sdma_queue_pkts(dd, pq, &list, iov, dim, mxp); - up_write(¤t->mm->mmap_sem); - if (ret <= 0) goto done_unlock; else { -- cgit v1.2.3 From 71d7bd9b865fb91fb39501260fafd88c791d9dc5 Mon Sep 17 00:00:00 2001 From: Mike Marciniszyn Date: Fri, 25 Oct 2013 11:17:59 -0400 Subject: IB/qib: Fix txselect regression commit 2fadd83184d58701f1116ca578465b5a75f9417c upstream. Commit 7fac33014f54("IB/qib: checkpatch fixes") was overzealous in removing a simple_strtoul for a parse routine, setup_txselect(). That routine is required to handle a multi-value string. Unwind that aspect of the fix. Signed-off-by: Mike Marciniszyn Signed-off-by: Roland Dreier Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/hw/qib/qib_iba7322.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c index 3f6b21e9dc11..bd8cb0f89ef1 100644 --- a/drivers/infiniband/hw/qib/qib_iba7322.c +++ b/drivers/infiniband/hw/qib/qib_iba7322.c @@ -5853,21 +5853,20 @@ static int setup_txselect(const char *str, struct kernel_param *kp) { struct qib_devdata *dd; unsigned long val; - int ret; - + char *n; if (strlen(str) >= MAX_ATTEN_LEN) { pr_info("txselect_values string too long\n"); return -ENOSPC; } - ret = kstrtoul(str, 0, &val); - if (ret || val >= (TXDDS_TABLE_SZ + TXDDS_EXTRA_SZ + + val = simple_strtoul(str, &n, 0); + if (n == str || val >= (TXDDS_TABLE_SZ + TXDDS_EXTRA_SZ + TXDDS_MFG_SZ)) { pr_info("txselect_values must start with a number < %d\n", TXDDS_TABLE_SZ + TXDDS_EXTRA_SZ + TXDDS_MFG_SZ); - return ret ? ret : -EINVAL; + return -EINVAL; } - strcpy(txselect_list, str); + list_for_each_entry(dd, &qib_dev_list, list) if (dd->deviceid == PCI_DEVICE_ID_QLOGIC_IB_7322) set_no_qsfp_atten(dd, 1); -- cgit v1.2.3 From c0be79254f31d3e19fa584bb2e7ca8d152074bbc Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 10 Oct 2013 13:53:25 +0200 Subject: IB/srp: Report receive errors correctly commit cd4e38542a5c2cab94e5410fb17c1cc004a60792 upstream. The IB spec does not guarantee that the opcode is available in error completions. Hence do not rely on it. See also commit 948d1e889e5b ("IB/srp: Introduce srp_handle_qp_err()"). Signed-off-by: Bart Van Assche Signed-off-by: Roland Dreier Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/ulp/srp/ib_srp.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 7ccf3284dda3..793ac5dcee71 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -1300,14 +1300,13 @@ static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc) PFX "Recv failed with error code %d\n", res); } -static void srp_handle_qp_err(enum ib_wc_status wc_status, - enum ib_wc_opcode wc_opcode, +static void srp_handle_qp_err(enum ib_wc_status wc_status, bool send_err, struct srp_target_port *target) { if (target->connected && !target->qp_in_error) { shost_printk(KERN_ERR, target->scsi_host, PFX "failed %s status %d\n", - wc_opcode & IB_WC_RECV ? "receive" : "send", + send_err ? "send" : "receive", wc_status); } target->qp_in_error = true; @@ -1323,7 +1322,7 @@ static void srp_recv_completion(struct ib_cq *cq, void *target_ptr) if (likely(wc.status == IB_WC_SUCCESS)) { srp_handle_recv(target, &wc); } else { - srp_handle_qp_err(wc.status, wc.opcode, target); + srp_handle_qp_err(wc.status, false, target); } } } @@ -1339,7 +1338,7 @@ static void srp_send_completion(struct ib_cq *cq, void *target_ptr) iu = (struct srp_iu *) (uintptr_t) wc.wr_id; list_add(&iu->list, &target->free_tx); } else { - srp_handle_qp_err(wc.status, wc.opcode, target); + srp_handle_qp_err(wc.status, true, target); } } } -- cgit v1.2.3 From 6be5caa68ad7d194173eafd35c9f8aeba00adb00 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Mon, 14 Oct 2013 12:12:24 -0400 Subject: loop: fix crash if blk_alloc_queue fails commit 3ec981e30fae1f3c8728a05c730acaa1f627bcfb upstream. loop: fix crash if blk_alloc_queue fails If blk_alloc_queue fails, loop_add cleans up, but it doesn't clean up the identifier allocated with idr_alloc. That causes crash on module unload in idr_for_each(&loop_index_idr, &loop_exit_cb, NULL); where we attempt to remove non-existed device with that id. BUG: unable to handle kernel NULL pointer dereference at 0000000000000380 IP: [] del_gendisk+0x19/0x2d0 PGD 43d399067 PUD 43d0ad067 PMD 0 Oops: 0000 [#1] PREEMPT SMP Modules linked in: loop(-) dm_snapshot dm_zero dm_mirror dm_region_hash dm_log dm_loop dm_mod ip6table_filter ip6_tables uvesafb cfbcopyarea cfbimgblt cfbfillrect fbcon font bitblit fbcon_rotate fbcon_cw fbcon_ud fbcon_ccw softcursor fb fbdev msr ipt_MASQUERADE iptable_nat nf_nat_ipv4 nf_conntrack_ipv4 nf_defrag_ipv4 xt_state ipt_REJECT xt_tcpudp iptable_filter ip_tables x_tables bridge stp llc tun ipv6 cpufreq_userspace cpufreq_stats cpufreq_ondemand cpufreq_conservative cpufreq_powersave spadfs fuse hid_generic usbhid hid raid0 md_mod dmi_sysfs nf_nat_ftp nf_nat nf_conntrack_ftp nf_conntrack snd_usb_audio snd_pcm_oss snd_mixer_oss snd_pcm snd_timer snd_page_alloc lm85 hwmon_vid snd_hwdep snd_usbmidi_lib snd_rawmidi snd soundcore acpi_cpufreq ohci_hcd freq_table tg3 ehci_pci mperf ehci_hcd kvm_amd kvm sata_svw serverworks libphy libata ide_core k10temp usbcore hwmon microcode ptp pcspkr pps_core e100 skge mii usb_common i2c_piix4 floppy evdev rtc_cmos i2c_core processor but! ton unix CPU: 7 PID: 2735 Comm: rmmod Tainted: G W 3.10.15-devel #15 Hardware name: empty empty/S3992-E, BIOS 'V1.06 ' 06/09/2009 task: ffff88043d38e780 ti: ffff88043d21e000 task.ti: ffff88043d21e000 RIP: 0010:[] [] del_gendisk+0x19/0x2d0 RSP: 0018:ffff88043d21fe10 EFLAGS: 00010282 RAX: ffffffffa05102e0 RBX: 0000000000000000 RCX: 0000000000000000 RDX: 0000000000000000 RSI: ffff88043ea82800 RDI: 0000000000000000 RBP: ffff88043d21fe48 R08: 0000000000000000 R09: 0000000000000001 R10: 0000000000000001 R11: 0000000000000000 R12: 00000000000000ff R13: 0000000000000080 R14: 0000000000000000 R15: ffff88043ea82800 FS: 00007ff646534700(0000) GS:ffff880447000000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b CR2: 0000000000000380 CR3: 000000043e9bf000 CR4: 00000000000007e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Stack: ffffffff8100aba4 0000000000000092 ffff88043d21fe48 ffff88043ea82800 00000000000000ff ffff88043d21fe98 0000000000000000 ffff88043d21fe60 ffffffffa05102b4 0000000000000000 ffff88043d21fe70 ffffffffa05102ec Call Trace: [] ? native_sched_clock+0x24/0x80 [] loop_remove+0x14/0x40 [loop] [] loop_exit_cb+0xc/0x10 [loop] [] idr_for_each+0x104/0x190 [] ? loop_remove+0x40/0x40 [loop] [] ? trace_hardirqs_on_caller+0x105/0x1d0 [] loop_exit+0x34/0xa58 [loop] [] SyS_delete_module+0x13a/0x260 [] ? trace_hardirqs_on_thunk+0x3a/0x3f [] system_call_fastpath+0x1a/0x1f Code: f0 4c 8b 6d f8 c9 c3 66 66 2e 0f 1f 84 00 00 00 00 00 55 48 89 e5 41 56 41 55 4c 8d af 80 00 00 00 41 54 53 48 89 fb 48 83 ec 18 <48> 83 bf 80 03 00 00 00 74 4d e8 98 fe ff ff 31 f6 48 c7 c7 20 RIP [] del_gendisk+0x19/0x2d0 RSP CR2: 0000000000000380 ---[ end trace 64ec069ec70f1309 ]--- Signed-off-by: Mikulas Patocka Acked-by: Tejun Heo Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- drivers/block/loop.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 00559736cee4..9430f1ceeef8 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -1633,7 +1633,7 @@ static int loop_add(struct loop_device **l, int i) err = -ENOMEM; lo->lo_queue = blk_alloc_queue(GFP_KERNEL); if (!lo->lo_queue) - goto out_free_dev; + goto out_free_idr; disk = lo->lo_disk = alloc_disk(1 << part_shift); if (!disk) @@ -1678,6 +1678,8 @@ static int loop_add(struct loop_device **l, int i) out_free_queue: blk_cleanup_queue(lo->lo_queue); +out_free_idr: + idr_remove(&loop_index_idr, i); out_free_dev: kfree(lo); out: -- cgit v1.2.3 From ff236289a23351c72359f4507071d3639e3b7e6d Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Tue, 15 Oct 2013 14:14:38 -0600 Subject: loop: fix crash when using unassigned loop device commit ef7e7c82e02b602f29c2b87f42dcd6143a6777da upstream. When the loop module is loaded, it creates 8 loop devices /dev/loop[0-7]. The devices have no request routine and thus, when they are used without being assigned, a crash happens. For example, these commands cause crash (assuming there are no used loop devices): Kernel Fault: Code=26 regs=000000007f420980 (Addr=0000000000000010) CPU: 1 PID: 50 Comm: kworker/1:1 Not tainted 3.11.0 #1 Workqueue: ksnaphd do_metadata [dm_snapshot] task: 000000007fcf4078 ti: 000000007f420000 task.ti: 000000007f420000 [ 116.319988] YZrvWESTHLNXBCVMcbcbcbcbOGFRQPDI PSW: 00001000000001001111111100001111 Not tainted r00-03 000000ff0804ff0f 00000000408bf5d0 00000000402d8204 000000007b7ff6c0 r04-07 00000000408a95d0 000000007f420950 000000007b7ff6c0 000000007d06c930 r08-11 000000007f4205c0 0000000000000001 000000007f4205c0 000000007f4204b8 r12-15 0000000000000010 0000000000000000 0000000000000000 0000000000000000 r16-19 000000001108dd48 000000004061cd7c 000000007d859800 000000000800000f r20-23 0000000000000000 0000000000000008 0000000000000000 0000000000000000 r24-27 00000000ffffffff 000000007b7ff6c0 000000007d859800 00000000408a95d0 r28-31 0000000000000000 000000007f420950 000000007f420980 000000007f4208e8 sr00-03 0000000000000000 0000000000000000 0000000000000000 0000000000303000 sr04-07 0000000000000000 0000000000000000 0000000000000000 0000000000000000 [ 117.549988] IASQ: 0000000000000000 0000000000000000 IAOQ: 00000000402d82fc 00000000402d8300 IIR: 53820020 ISR: 0000000000000000 IOR: 0000000000000010 CPU: 1 CR30: 000000007f420000 CR31: ffffffffffffffff ORIG_R28: 0000000000000001 IAOQ[0]: generic_make_request+0x11c/0x1a0 IAOQ[1]: generic_make_request+0x120/0x1a0 RP(r2): generic_make_request+0x24/0x1a0 Backtrace: [<00000000402d83f0>] submit_bio+0x70/0x140 [<0000000011087c4c>] dispatch_io+0x234/0x478 [dm_mod] [<0000000011087f44>] sync_io+0xb4/0x190 [dm_mod] [<00000000110883bc>] dm_io+0x2c4/0x310 [dm_mod] [<00000000110bfcd0>] do_metadata+0x28/0xb0 [dm_snapshot] [<00000000401591d8>] process_one_work+0x160/0x460 [<0000000040159bc0>] worker_thread+0x300/0x478 [<0000000040161a70>] kthread+0x118/0x128 [<0000000040104020>] end_fault_vector+0x20/0x28 [<0000000040177220>] task_tick_fair+0x420/0x4d0 [<00000000401aa048>] invoke_rcu_core+0x50/0x60 [<00000000401ad5b8>] rcu_check_callbacks+0x210/0x8d8 [<000000004014aaa0>] update_process_times+0xa8/0xc0 [<00000000401ab86c>] rcu_process_callbacks+0x4b4/0x598 [<0000000040142408>] __do_softirq+0x250/0x2c0 [<00000000401789d0>] find_busiest_group+0x3c0/0xc70 [ 119.379988] Kernel panic - not syncing: Kernel Fault Rebooting in 1 seconds.. Signed-off-by: Mikulas Patocka Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- drivers/block/loop.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 9430f1ceeef8..4a8116547873 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -894,13 +894,6 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode, bio_list_init(&lo->lo_bio_list); - /* - * set queue make_request_fn, and add limits based on lower level - * device - */ - blk_queue_make_request(lo->lo_queue, loop_make_request); - lo->lo_queue->queuedata = lo; - if (!(lo_flags & LO_FLAGS_READ_ONLY) && file->f_op->fsync) blk_queue_flush(lo->lo_queue, REQ_FLUSH); @@ -1618,6 +1611,8 @@ static int loop_add(struct loop_device **l, int i) if (!lo) goto out; + lo->lo_state = Lo_unbound; + /* allocate id, if @id >= 0, we're requesting that specific id */ if (i >= 0) { err = idr_alloc(&loop_index_idr, lo, i, i + 1, GFP_KERNEL); @@ -1635,6 +1630,12 @@ static int loop_add(struct loop_device **l, int i) if (!lo->lo_queue) goto out_free_idr; + /* + * set queue make_request_fn + */ + blk_queue_make_request(lo->lo_queue, loop_make_request); + lo->lo_queue->queuedata = lo; + disk = lo->lo_disk = alloc_disk(1 << part_shift); if (!disk) goto out_free_queue; -- cgit v1.2.3 From 017beeafb0bd8a13118b71d568ed0912b6bf9f69 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Tue, 27 Aug 2013 18:45:10 -0700 Subject: mtd: nand: hack ONFI for non-power-of-2 dimensions commit 4355b70cf48363c50a9de450b01178c83aba8f6a upstream. Some bright specification writers decided to write this in the ONFI spec (from ONFI 3.0, Section 3.1): "The number of blocks and number of pages per block is not required to be a power of two. In the case where one of these values is not a power of two, the corresponding address shall be rounded to an integral number of bits such that it addresses a range up to the subsequent power of two value. The host shall not access upper addresses in a range that is shown as not supported." This breaks every assumption MTD makes about NAND block/chip-size dimensions -- they *must* be a power of two! And of course, an enterprising manufacturer has made use of this lovely freedom. Exhibit A: Micron MT29F32G08CBADAWP "- Plane size: 2 planes x 1064 blocks per plane - Device size: 32Gb: 2128 blockss [sic]" This quickly hits a BUG() in nand_base.c, since the extra dimensions overflow so we think it's a second chip (on my single-chip setup): ONFI param page 0 valid ONFI flash detected NAND device: Manufacturer ID: 0x2c, Chip ID: 0x44 (Micron MT29F32G08CBADAWP), 4256MiB, page size: 8192, OOB size: 744 ------------[ cut here ]------------ kernel BUG at drivers/mtd/nand/nand_base.c:203! Internal error: Oops - BUG: 0 [#1] SMP ARM [... trim ...] [] (nand_select_chip+0x18/0x2c) from [] (nand_do_read_ops+0x90/0x424) [] (nand_do_read_ops+0x90/0x424) from [] (nand_read+0x54/0x78) [] (nand_read+0x54/0x78) from [] (mtd_read+0x84/0xbc) [] (mtd_read+0x84/0xbc) from [] (scan_read.clone.4+0x4c/0x64) [] (scan_read.clone.4+0x4c/0x64) from [] (search_bbt+0x148/0x290) [] (search_bbt+0x148/0x290) from [] (nand_scan_bbt+0xd4/0x5c0) [... trim ...] ---[ end trace 0c9363860d865ff2 ]--- So to fix this, just truncate these dimensions down to the greatest power-of-2 dimension that is less than or equal to the specified dimension. Signed-off-by: Brian Norris Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/nand/nand_base.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index fb8c4deaac27..633db8830c13 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -2904,10 +2904,21 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, sanitize_string(p->model, sizeof(p->model)); if (!mtd->name) mtd->name = p->model; + mtd->writesize = le32_to_cpu(p->byte_per_page); - mtd->erasesize = le32_to_cpu(p->pages_per_block) * mtd->writesize; + + /* + * pages_per_block and blocks_per_lun may not be a power-of-2 size + * (don't ask me who thought of this...). MTD assumes that these + * dimensions will be power-of-2, so just truncate the remaining area. + */ + mtd->erasesize = 1 << (fls(le32_to_cpu(p->pages_per_block)) - 1); + mtd->erasesize *= mtd->writesize; + mtd->oobsize = le16_to_cpu(p->spare_bytes_per_page); - chip->chipsize = le32_to_cpu(p->blocks_per_lun); + + /* See erasesize comment */ + chip->chipsize = 1 << (fls(le32_to_cpu(p->blocks_per_lun)) - 1); chip->chipsize *= (uint64_t)mtd->erasesize * p->lun_count; *busw = 0; if (le16_to_cpu(p->features) & 1) -- cgit v1.2.3 From 1da42d7c5ff4dbee6b7c60cbcba9035422a7a1f8 Mon Sep 17 00:00:00 2001 From: Wang Haitao Date: Thu, 22 Aug 2013 19:32:38 +0800 Subject: mtd: map: fixed bug in 64-bit systems commit a4d62babf988fe5dfde24437fa135ef147bc7aa0 upstream. Hardware: CPU: XLP832,the 64-bit OS NOR Flash:S29GL128S 128M Software: Kernel:2.6.32.41 Filesystem:JFFS2 When writing files, errors appear: Write len 182 but return retlen 180 Write of 182 bytes at 0x072c815c failed. returned -5, retlen 180 Write len 186 but return retlen 184 Write of 186 bytes at 0x072caff4 failed. returned -5, retlen 184 These errors exist only in 64-bit systems,not in 32-bit systems. After analysis, we found that the left shift operation is wrong in map_word_load_partial. For instance: unsigned char buf[3] ={0x9e,0x3a,0xea}; map_bankwidth(map) is 4; for (i=0; i < 3; i++) { int bitpos; bitpos = (map_bankwidth(map)-1-i)*8; orig.x[0] &= ~(0xff << bitpos); orig.x[0] |= buf[i] << bitpos; } The value of orig.x[0] is expected to be 0x9e3aeaff, but in this situation(64-bit System) we'll get the wrong value of 0xffffffff9e3aeaff due to the 64-bit sign extension: buf[i] is defined as "unsigned char" and the left-shift operation will convert it to the type of "signed int", so when left-shift buf[i] by 24 bits, the final result will get the wrong value: 0xffffffff9e3aeaff. If the left-shift bits are less than 24, then sign extension will not occur. Whereas the bankwidth of the nor flash we used is 4, therefore this BUG emerges. Signed-off-by: Pang Xunlei Signed-off-by: Zhang Yi Signed-off-by: Lu Zhongjun Signed-off-by: Brian Norris Signed-off-by: Greg Kroah-Hartman --- include/linux/mtd/map.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/mtd/map.h b/include/linux/mtd/map.h index 4b02512e421c..5f487d776411 100644 --- a/include/linux/mtd/map.h +++ b/include/linux/mtd/map.h @@ -365,7 +365,7 @@ static inline map_word map_word_load_partial(struct map_info *map, map_word orig bitpos = (map_bankwidth(map)-1-i)*8; #endif orig.x[0] &= ~(0xff << bitpos); - orig.x[0] |= buf[i-start] << bitpos; + orig.x[0] |= (unsigned long)buf[i-start] << bitpos; } } return orig; @@ -384,7 +384,7 @@ static inline map_word map_word_ff(struct map_info *map) if (map_bankwidth(map) < MAP_FF_LIMIT) { int bw = 8 * map_bankwidth(map); - r.x[0] = (1 << bw) - 1; + r.x[0] = (1UL << bw) - 1; } else { for (i=0; i Date: Mon, 11 Nov 2013 12:13:45 +0800 Subject: mtd: gpmi: fix kernel BUG due to racing DMA operations commit 7b3d2fb92067bcb29f0f085a9fa9fa64920a6646 upstream. [1] The gpmi uses the nand_command_lp to issue the commands to NAND chips. The gpmi issues a DMA operation with gpmi_cmd_ctrl when it handles a NAND_CMD_NONE control command. So when we read a page(NAND_CMD_READ0) from the NAND, we may send two DMA operations back-to-back. If we do not serialize the two DMA operations, we will meet a bug when 1.1) we enable CONFIG_DMA_API_DEBUG, CONFIG_DMADEVICES_DEBUG, and CONFIG_DEBUG_SG. 1.2) Use the following commands in an UART console and a SSH console: cmd 1: while true;do dd if=/dev/mtd0 of=/dev/null;done cmd 1: while true;do dd if=/dev/mmcblk0 of=/dev/null;done The kernel log shows below: ----------------------------------------------------------------- kernel BUG at lib/scatterlist.c:28! Unable to handle kernel NULL pointer dereference at virtual address 00000000 ......................... [<80044a0c>] (__bug+0x18/0x24) from [<80249b74>] (sg_next+0x48/0x4c) [<80249b74>] (sg_next+0x48/0x4c) from [<80255398>] (debug_dma_unmap_sg+0x170/0x1a4) [<80255398>] (debug_dma_unmap_sg+0x170/0x1a4) from [<8004af58>] (dma_unmap_sg+0x14/0x6c) [<8004af58>] (dma_unmap_sg+0x14/0x6c) from [<8027e594>] (mxs_dma_tasklet+0x18/0x1c) [<8027e594>] (mxs_dma_tasklet+0x18/0x1c) from [<8007d444>] (tasklet_action+0x114/0x164) ----------------------------------------------------------------- 1.3) Assume the two DMA operations is X (first) and Y (second). The root cause of the bug: Assume process P issues DMA X, and sleep on the completion @this->dma_done. X's tasklet callback is dma_irq_callback. It firstly wake up the process sleeping on the completion @this->dma_done, and then trid to unmap the scatterlist S. The waked process P will issue Y in another ARM core. Y initializes S->sg_magic to zero with sg_init_one(), while dma_irq_callback is unmapping S at the same time. See the diagram: ARM core 0 | ARM core 1 ------------------------------------------------------------- (P issues DMA X, then sleep) --> | | (X's tasklet wakes P) --> | | | <-- (P begin to issue DMA Y) | (X's tasklet unmap the | scatterlist S with dma_unmap_sg) --> | <-- (Y calls sg_init_one() to init | scatterlist S) | [2] This patch serialize both the X and Y in the following way: Unmap the DMA scatterlist S firstly, and wake up the process at the end of the DMA callback, in such a way, Y will be executed after X. After this patch: ARM core 0 | ARM core 1 ------------------------------------------------------------- (P issues DMA X, then sleep) --> | | (X's tasklet unmap the | scatterlist S with dma_unmap_sg) --> | | (X's tasklet wakes P) --> | | | <-- (P begin to issue DMA Y) | | <-- (Y calls sg_init_one() to init | scatterlist S) | Signed-off-by: Huang Shijie Signed-off-by: Brian Norris Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/nand/gpmi-nand/gpmi-nand.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c index 25ecfa1822a8..ab6581f1bc28 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c @@ -264,8 +264,6 @@ static void dma_irq_callback(void *param) struct gpmi_nand_data *this = param; struct completion *dma_c = &this->dma_done; - complete(dma_c); - switch (this->dma_type) { case DMA_FOR_COMMAND: dma_unmap_sg(this->dev, &this->cmd_sgl, 1, DMA_TO_DEVICE); @@ -290,6 +288,8 @@ static void dma_irq_callback(void *param) default: pr_err("in wrong DMA operation.\n"); } + + complete(dma_c); } int start_dma_without_bch_irq(struct gpmi_nand_data *this, -- cgit v1.2.3 From ef0d74867fc7e440b0e945e7fe47a862dbc9c9ef Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Thu, 31 Oct 2013 23:00:24 -0400 Subject: ext4: avoid bh leak in retry path of ext4_expand_extra_isize_ea() commit dcb9917ba041866686fe152850364826c4622a36 upstream. Reported-by: Dave Jones Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/xattr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index 03e9bebba198..1423c4816a47 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c @@ -1352,6 +1352,7 @@ retry: new_extra_isize = s_min_extra_isize; kfree(is); is = NULL; kfree(bs); bs = NULL; + brelse(bh); goto retry; } error = -1; -- cgit v1.2.3 From d0ac18ce1a3d607ad650fd4b9d371be75a5c8e3a Mon Sep 17 00:00:00 2001 From: Vegard Nossum Date: Thu, 5 Sep 2013 13:00:14 +0200 Subject: xen/blkback: fix reference counting commit ea5ec76d76da9279d12027c1828544c5ccbe7932 upstream. If the permission check fails, we drop a reference to the blkif without having taken it in the first place. The bug was introduced in commit 604c499cbbcc3d5fe5fb8d53306aa0fae1990109 (xen/blkback: Check device permissions before allowing OP_DISCARD). Cc: Jan Beulich Cc: Konrad Rzeszutek Wilk Signed-off-by: Vegard Nossum Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- drivers/block/xen-blkback/blkback.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index d81dfca755d1..03dd4aa612db 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -649,6 +649,8 @@ static int dispatch_discard_io(struct xen_blkif *blkif, unsigned long secure; struct phys_req preq; + xen_blkif_get(blkif); + preq.sector_number = req->u.discard.sector_number; preq.nr_sects = req->u.discard.nr_sectors; @@ -661,7 +663,6 @@ static int dispatch_discard_io(struct xen_blkif *blkif, } blkif->st_ds_req++; - xen_blkif_get(blkif); secure = (blkif->vbd.discard_secure && (req->u.discard.flag & BLKIF_DISCARD_SECURE)) ? BLKDEV_DISCARD_SECURE : 0; -- cgit v1.2.3 From 16bc5bbba363d71baf24917ec1642962fa273c97 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Tue, 5 Nov 2013 15:15:30 -0600 Subject: rtlwifi: rtl8192de: Fix incorrect signal strength for unassociated AP commit 3545f3d5f4af715c914394123ce7725a9cf0a1c4 upstream. The routine that processes received frames was returning the RSSI value for the signal strength; however, that value is available only for associated APs. As a result, the strength was the absurd value of 10 dBm. As a result, scans return incorrect values for the strength, which causes unwanted attempts to roam. Signed-off-by: Larry Finger Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/rtlwifi/rtl8192de/trx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/trx.c b/drivers/net/wireless/rtlwifi/rtl8192de/trx.c index b8ec718a0fab..542394c843e6 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192de/trx.c @@ -525,7 +525,7 @@ bool rtl92de_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats, p_drvinfo); } /*rx_status->qual = stats->signal; */ - rx_status->signal = stats->rssi + 10; + rx_status->signal = stats->recvsignalpower + 10; /*rx_status->noise = -stats->noise; */ return true; } -- cgit v1.2.3 From b642081da4873e8fa3d7097076d2df9ba557d54e Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Tue, 5 Nov 2013 15:15:28 -0600 Subject: rtlwifi: rtl8192se: Fix incorrect signal strength for unassociated AP commit b4ade797668e33b4e8353c2701ce01d7084dfafa upstream. The routine that processes received frames was returning the RSSI value for the signal strength; however, that value is available only for associated APs. As a result, the strength was the absurd value of 10 dBm. As a result, scans return incorrect values for the strength, which causes unwanted attempts to roam. This patch fixes https://bugzilla.kernel.org/show_bug.cgi?id=63881. Signed-off-by: Larry Finger Reported-by: Matthieu Baerts Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/rtlwifi/rtl8192se/trx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c index c7095118de6e..7d0f2e20f1a2 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c @@ -329,7 +329,7 @@ bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats, } /*rx_status->qual = stats->signal; */ - rx_status->signal = stats->rssi + 10; + rx_status->signal = stats->recvsignalpower + 10; /*rx_status->noise = -stats->noise; */ return true; -- cgit v1.2.3 From e6a159898766541f6ed3bb48fe45dbba19ffa7eb Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Tue, 5 Nov 2013 15:15:29 -0600 Subject: rtlwifi: rtl8192cu: Fix incorrect signal strength for unassociated AP commit 78dbfecb95be4635b995af3bd29fa10013409fcd upstream. The routine that processes received frames was returning the RSSI value for the signal strength; however, that value is available only for associated APs. As a result, the strength was the absurd value of 10 dBm. As a result, scans return incorrect values for the strength, which causes unwanted attempts to roam. Signed-off-by: Larry Finger Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/rtlwifi/rtl8192cu/trx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c index 5dfe7e2513ae..5c52a8ac314c 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c @@ -349,7 +349,7 @@ bool rtl92cu_rx_query_desc(struct ieee80211_hw *hw, p_drvinfo); } /*rx_status->qual = stats->signal; */ - rx_status->signal = stats->rssi + 10; + rx_status->signal = stats->recvsignalpower + 10; /*rx_status->noise = -stats->noise; */ return true; } -- cgit v1.2.3 From 9dc2f267425869786d195a99eadbc2aad3f4edaa Mon Sep 17 00:00:00 2001 From: Ursula Braun Date: Wed, 6 Nov 2013 09:04:52 +0100 Subject: qeth: avoid buffer overflow in snmp ioctl commit 6fb392b1a63ae36c31f62bc3fc8630b49d602b62 upstream. Check user-defined length in snmp ioctl request and allow request only if it fits into a qeth command buffer. Signed-off-by: Ursula Braun Signed-off-by: Frank Blaschka Reviewed-by: Heiko Carstens Reported-by: Nico Golde Reported-by: Fabian Yamaguchi Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/s390/net/qeth_core_main.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 6cd0fc1b203a..e06cb8f8d0c2 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -4448,7 +4448,7 @@ int qeth_snmp_command(struct qeth_card *card, char __user *udata) struct qeth_cmd_buffer *iob; struct qeth_ipa_cmd *cmd; struct qeth_snmp_ureq *ureq; - int req_len; + unsigned int req_len; struct qeth_arp_query_info qinfo = {0, }; int rc = 0; @@ -4464,6 +4464,10 @@ int qeth_snmp_command(struct qeth_card *card, char __user *udata) /* skip 4 bytes (data_len struct member) to get req_len */ if (copy_from_user(&req_len, udata + sizeof(int), sizeof(int))) return -EFAULT; + if (req_len > (QETH_BUFSIZE - IPA_PDU_HEADER_SIZE - + sizeof(struct qeth_ipacmd_hdr) - + sizeof(struct qeth_ipacmd_setadpparms_hdr))) + return -EINVAL; ureq = memdup_user(udata, req_len + sizeof(struct qeth_snmp_ureq_hdr)); if (IS_ERR(ureq)) { QETH_CARD_TEXT(card, 2, "snmpnome"); -- cgit v1.2.3 From df3e475e43ae5e2112a464335c28368092d53edd Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Tue, 15 Oct 2013 14:28:48 +0200 Subject: rt2400pci: fix RSSI read commit 2bf127a5cc372b9319afcbae10b090663b621c8b upstream. RSSI value is provided on word3 not on word2. Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/rt2x00/rt2400pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index f7143733d7e9..a3a2dcd27a1e 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1261,7 +1261,7 @@ static void rt2400pci_fill_rxdone(struct queue_entry *entry, */ rxdesc->timestamp = ((u64)rx_high << 32) | rx_low; rxdesc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL) & ~0x08; - rxdesc->rssi = rt2x00_get_field32(word2, RXD_W3_RSSI) - + rxdesc->rssi = rt2x00_get_field32(word3, RXD_W3_RSSI) - entry->queue->rt2x00dev->rssi_offset; rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); -- cgit v1.2.3 From 3cbafaa72d3afc4a4177f0d76178cd26a525589b Mon Sep 17 00:00:00 2001 From: Akira Takeuchi Date: Tue, 12 Nov 2013 15:08:21 -0800 Subject: mm: ensure get_unmapped_area() returns higher address than mmap_min_addr commit 2afc745f3e3079ab16c826be4860da2529054dd2 upstream. This patch fixes the problem that get_unmapped_area() can return illegal address and result in failing mmap(2) etc. In case that the address higher than PAGE_SIZE is set to /proc/sys/vm/mmap_min_addr, the address lower than mmap_min_addr can be returned by get_unmapped_area(), even if you do not pass any virtual address hint (i.e. the second argument). This is because the current get_unmapped_area() code does not take into account mmap_min_addr. This leads to two actual problems as follows: 1. mmap(2) can fail with EPERM on the process without CAP_SYS_RAWIO, although any illegal parameter is not passed. 2. The bottom-up search path after the top-down search might not work in arch_get_unmapped_area_topdown(). Note: The first and third chunk of my patch, which changes "len" check, are for more precise check using mmap_min_addr, and not for solving the above problem. [How to reproduce] --- test.c ------------------------------------------------- #include #include #include #include int main(int argc, char *argv[]) { void *ret = NULL, *last_map; size_t pagesize = sysconf(_SC_PAGESIZE); do { last_map = ret; ret = mmap(0, pagesize, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); // printf("ret=%p\n", ret); } while (ret != MAP_FAILED); if (errno != ENOMEM) { printf("ERR: unexpected errno: %d (last map=%p)\n", errno, last_map); } return 0; } --------------------------------------------------------------- $ gcc -m32 -o test test.c $ sudo sysctl -w vm.mmap_min_addr=65536 vm.mmap_min_addr = 65536 $ ./test (run as non-priviledge user) ERR: unexpected errno: 1 (last map=0x10000) Signed-off-by: Akira Takeuchi Signed-off-by: Kiyoshi Owada Reviewed-by: Naoya Horiguchi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/mmap.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mm/mmap.c b/mm/mmap.c index 8d25fdc653be..8f87b14c7968 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1853,7 +1853,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, struct vm_area_struct *vma; struct vm_unmapped_area_info info; - if (len > TASK_SIZE) + if (len > TASK_SIZE - mmap_min_addr) return -ENOMEM; if (flags & MAP_FIXED) @@ -1862,7 +1862,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, if (addr) { addr = PAGE_ALIGN(addr); vma = find_vma(mm, addr); - if (TASK_SIZE - len >= addr && + if (TASK_SIZE - len >= addr && addr >= mmap_min_addr && (!vma || addr + len <= vma->vm_start)) return addr; } @@ -1901,7 +1901,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, struct vm_unmapped_area_info info; /* requested length too big for entire address space */ - if (len > TASK_SIZE) + if (len > TASK_SIZE - mmap_min_addr) return -ENOMEM; if (flags & MAP_FIXED) @@ -1911,14 +1911,14 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, if (addr) { addr = PAGE_ALIGN(addr); vma = find_vma(mm, addr); - if (TASK_SIZE - len >= addr && + if (TASK_SIZE - len >= addr && addr >= mmap_min_addr && (!vma || addr + len <= vma->vm_start)) return addr; } info.flags = VM_UNMAPPED_AREA_TOPDOWN; info.length = len; - info.low_limit = PAGE_SIZE; + info.low_limit = max(PAGE_SIZE, mmap_min_addr); info.high_limit = mm->mmap_base; info.align_mask = 0; addr = vm_unmapped_area(&info); -- cgit v1.2.3 From 6edfd0331f788a5d62736c6a422488708175b4c4 Mon Sep 17 00:00:00 2001 From: Ludovic Desroches Date: Mon, 9 Sep 2013 17:29:56 +0200 Subject: mmc: atmel-mci: abort transfer on timeout error commit c1fa3426aa5c782724c97394303d52228206eda4 upstream. When a software timeout occurs, the transfer is not stopped. In DMA case, it causes DMA channel to be stuck because the transfer is still active causing following transfers to be queued but not computed. Signed-off-by: Ludovic Desroches Reported-by: Alexander Morozov Acked-by: Nicolas Ferre Signed-off-by: Chris Ball Signed-off-by: Greg Kroah-Hartman --- drivers/mmc/host/atmel-mci.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index aca59d93d5a9..5d68ac958112 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -584,6 +584,13 @@ static void atmci_timeout_timer(unsigned long data) if (host->mrq->cmd->data) { host->mrq->cmd->data->error = -ETIMEDOUT; host->data = NULL; + /* + * With some SDIO modules, sometimes DMA transfer hangs. If + * stop_transfer() is not called then the DMA request is not + * removed, following ones are queued and never computed. + */ + if (host->state == STATE_DATA_XFER) + host->stop_transfer(host); } else { host->mrq->cmd->error = -ETIMEDOUT; host->cmd = NULL; -- cgit v1.2.3 From 63a23e393fed93ca823f7c7fc415795e2ffe7670 Mon Sep 17 00:00:00 2001 From: Rodolfo Giometti Date: Mon, 9 Sep 2013 17:31:59 +0200 Subject: mmc: atmel-mci: fix oops in atmci_tasklet_func commit fbd986cd420d1deeabf1039ec4e74075a5639db5 upstream. In some cases, a NULL pointer dereference happens because data is NULL when STATE_END_REQUEST case is reached in atmci_tasklet_func. Signed-off-by: Rodolfo Giometti Acked-by: Ludovic Desroches Acked-by: Nicolas Ferre Signed-off-by: Chris Ball Signed-off-by: Greg Kroah-Hartman --- drivers/mmc/host/atmel-mci.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 5d68ac958112..b5c95043f7ef 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -1794,12 +1794,14 @@ static void atmci_tasklet_func(unsigned long priv) if (unlikely(status)) { host->stop_transfer(host); host->data = NULL; - if (status & ATMCI_DTOE) { - data->error = -ETIMEDOUT; - } else if (status & ATMCI_DCRCE) { - data->error = -EILSEQ; - } else { - data->error = -EIO; + if (data) { + if (status & ATMCI_DTOE) { + data->error = -ETIMEDOUT; + } else if (status & ATMCI_DCRCE) { + data->error = -EILSEQ; + } else { + data->error = -EIO; + } } } -- cgit v1.2.3 From 9fb1b9d041cb34f4381038e2622900dfdc4cd7b0 Mon Sep 17 00:00:00 2001 From: Shiva Krishna Merla Date: Wed, 30 Oct 2013 03:26:38 +0000 Subject: dm mpath: fix race condition between multipath_dtr and pg_init_done commit 954a73d5d3073df2231820c718fdd2f18b0fe4c9 upstream. Whenever multipath_dtr() is happening we must prevent queueing any further path activation work. Implement this by adding a new 'pg_init_disabled' flag to the multipath structure that denotes future path activation work should be skipped if it is set. By disabling pg_init and then re-enabling in flush_multipath_work() we also avoid the potential for pg_init to be initiated while suspending an mpath device. Without this patch a race condition exists that may result in a kernel panic: 1) If after pg_init_done() decrements pg_init_in_progress to 0, a call to wait_for_pg_init_completion() assumes there are no more pending path management commands. 2) If pg_init_required is set by pg_init_done(), due to retryable mode_select errors, then process_queued_ios() will again queue the path activation work. 3) If free_multipath() completes before activate_path() work is called a NULL pointer dereference like the following can be seen when accessing members of the recently destructed multipath: BUG: unable to handle kernel NULL pointer dereference at 0000000000000090 RIP: 0010:[] [] activate_path+0x1b/0x30 [dm_multipath] [] worker_thread+0x170/0x2a0 [] ? autoremove_wake_function+0x0/0x40 [switch to disabling pg_init in flush_multipath_work & header edits by Mike Snitzer] Signed-off-by: Shiva Krishna Merla Reviewed-by: Krishnasamy Somasundaram Tested-by: Speagle Andy Acked-by: Junichi Nomura Signed-off-by: Mike Snitzer Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-mpath.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index c5b7b3dd91cc..eb7ddb20fd48 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c @@ -86,6 +86,7 @@ struct multipath { unsigned queue_if_no_path:1; /* Queue I/O if last path fails? */ unsigned saved_queue_if_no_path:1; /* Saved state during suspension */ unsigned retain_attached_hw_handler:1; /* If there's already a hw_handler present, don't change it. */ + unsigned pg_init_disabled:1; /* pg_init is not currently allowed */ unsigned pg_init_retries; /* Number of times to retry pg_init */ unsigned pg_init_count; /* Number of times pg_init called */ @@ -497,7 +498,8 @@ static void process_queued_ios(struct work_struct *work) (!pgpath && !m->queue_if_no_path)) must_queue = 0; - if (m->pg_init_required && !m->pg_init_in_progress && pgpath) + if (m->pg_init_required && !m->pg_init_in_progress && pgpath && + !m->pg_init_disabled) __pg_init_all_paths(m); spin_unlock_irqrestore(&m->lock, flags); @@ -942,10 +944,20 @@ static void multipath_wait_for_pg_init_completion(struct multipath *m) static void flush_multipath_work(struct multipath *m) { + unsigned long flags; + + spin_lock_irqsave(&m->lock, flags); + m->pg_init_disabled = 1; + spin_unlock_irqrestore(&m->lock, flags); + flush_workqueue(kmpath_handlerd); multipath_wait_for_pg_init_completion(m); flush_workqueue(kmultipathd); flush_work(&m->trigger_event); + + spin_lock_irqsave(&m->lock, flags); + m->pg_init_disabled = 0; + spin_unlock_irqrestore(&m->lock, flags); } static void multipath_dtr(struct dm_target *ti) @@ -1164,7 +1176,7 @@ static int pg_init_limit_reached(struct multipath *m, struct pgpath *pgpath) spin_lock_irqsave(&m->lock, flags); - if (m->pg_init_count <= m->pg_init_retries) + if (m->pg_init_count <= m->pg_init_retries && !m->pg_init_disabled) m->pg_init_required = 1; else limit_reached = 1; @@ -1699,7 +1711,7 @@ out: *---------------------------------------------------------------*/ static struct target_type multipath_target = { .name = "multipath", - .version = {1, 5, 1}, + .version = {1, 6, 0}, .module = THIS_MODULE, .ctr = multipath_ctr, .dtr = multipath_dtr, -- cgit v1.2.3 From 0c5fd99e89b5f288ffe5c2ed301d2ffaac091891 Mon Sep 17 00:00:00 2001 From: Joe Thornber Date: Wed, 30 Oct 2013 11:19:59 +0000 Subject: dm array: fix bug in growing array commit 9c1d4de56066e4d6abc66ec188faafd7b303fb08 upstream. Entries would be lost if the old tail block was partially filled. Signed-off-by: Joe Thornber Signed-off-by: Mike Snitzer Signed-off-by: Greg Kroah-Hartman --- drivers/md/persistent-data/dm-array.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/md/persistent-data/dm-array.c b/drivers/md/persistent-data/dm-array.c index 172147eb1d40..af96e24ec328 100644 --- a/drivers/md/persistent-data/dm-array.c +++ b/drivers/md/persistent-data/dm-array.c @@ -509,15 +509,18 @@ static int grow_add_tail_block(struct resize *resize) static int grow_needs_more_blocks(struct resize *resize) { int r; + unsigned old_nr_blocks = resize->old_nr_full_blocks; if (resize->old_nr_entries_in_last_block > 0) { + old_nr_blocks++; + r = grow_extend_tail_block(resize, resize->max_entries); if (r) return r; } r = insert_full_ablocks(resize->info, resize->size_of_block, - resize->old_nr_full_blocks, + old_nr_blocks, resize->new_nr_full_blocks, resize->max_entries, resize->value, &resize->root); -- cgit v1.2.3 From 8fafee9829f539e17ea8678a6f56d2b897ffe3cc Mon Sep 17 00:00:00 2001 From: Joe Thornber Date: Wed, 30 Oct 2013 17:11:58 +0000 Subject: dm cache: fix a race condition between queuing new migrations and quiescing for a shutdown commit 66cb1910df17b38334153462ec8166e48058035f upstream. The code that was trying to do this was inadequate. The postsuspend method (in ioctl context), needs to wait for the worker thread to acknowledge the request to quiesce. Otherwise the migration count may drop to zero temporarily before the worker thread realises we're quiescing. In this case the target will be taken down, but the worker thread may have issued a new migration, which will cause an oops when it completes. Signed-off-by: Joe Thornber Signed-off-by: Mike Snitzer Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-cache-target.c | 54 ++++++++++++++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 14 deletions(-) diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c index df44b60e66f2..516f9c922bb2 100644 --- a/drivers/md/dm-cache-target.c +++ b/drivers/md/dm-cache-target.c @@ -151,6 +151,9 @@ struct cache { atomic_t nr_migrations; wait_queue_head_t migration_wait; + wait_queue_head_t quiescing_wait; + atomic_t quiescing_ack; + /* * cache_size entries, dirty if set */ @@ -742,8 +745,9 @@ static void cell_defer(struct cache *cache, struct dm_bio_prison_cell *cell, static void cleanup_migration(struct dm_cache_migration *mg) { - dec_nr_migrations(mg->cache); + struct cache *cache = mg->cache; free_migration(mg); + dec_nr_migrations(cache); } static void migration_failure(struct dm_cache_migration *mg) @@ -1340,34 +1344,51 @@ static void writeback_some_dirty_blocks(struct cache *cache) /*---------------------------------------------------------------- * Main worker loop *--------------------------------------------------------------*/ -static void start_quiescing(struct cache *cache) +static bool is_quiescing(struct cache *cache) { + int r; unsigned long flags; spin_lock_irqsave(&cache->lock, flags); - cache->quiescing = 1; + r = cache->quiescing; spin_unlock_irqrestore(&cache->lock, flags); + + return r; } -static void stop_quiescing(struct cache *cache) +static void ack_quiescing(struct cache *cache) +{ + if (is_quiescing(cache)) { + atomic_inc(&cache->quiescing_ack); + wake_up(&cache->quiescing_wait); + } +} + +static void wait_for_quiescing_ack(struct cache *cache) +{ + wait_event(cache->quiescing_wait, atomic_read(&cache->quiescing_ack)); +} + +static void start_quiescing(struct cache *cache) { unsigned long flags; spin_lock_irqsave(&cache->lock, flags); - cache->quiescing = 0; + cache->quiescing = true; spin_unlock_irqrestore(&cache->lock, flags); + + wait_for_quiescing_ack(cache); } -static bool is_quiescing(struct cache *cache) +static void stop_quiescing(struct cache *cache) { - int r; unsigned long flags; spin_lock_irqsave(&cache->lock, flags); - r = cache->quiescing; + cache->quiescing = false; spin_unlock_irqrestore(&cache->lock, flags); - return r; + atomic_set(&cache->quiescing_ack, 0); } static void wait_for_migrations(struct cache *cache) @@ -1414,16 +1435,15 @@ static void do_worker(struct work_struct *ws) struct cache *cache = container_of(ws, struct cache, worker); do { - if (!is_quiescing(cache)) + if (!is_quiescing(cache)) { + writeback_some_dirty_blocks(cache); + process_deferred_writethrough_bios(cache); process_deferred_bios(cache); + } process_migrations(cache, &cache->quiesced_migrations, issue_copy); process_migrations(cache, &cache->completed_migrations, complete_migration); - writeback_some_dirty_blocks(cache); - - process_deferred_writethrough_bios(cache); - if (commit_if_needed(cache)) { process_deferred_flush_bios(cache, false); @@ -1436,6 +1456,9 @@ static void do_worker(struct work_struct *ws) process_migrations(cache, &cache->need_commit_migrations, migration_success_post_commit); } + + ack_quiescing(cache); + } while (more_work(cache)); } @@ -1998,6 +2021,9 @@ static int cache_create(struct cache_args *ca, struct cache **result) atomic_set(&cache->nr_migrations, 0); init_waitqueue_head(&cache->migration_wait); + init_waitqueue_head(&cache->quiescing_wait); + atomic_set(&cache->quiescing_ack, 0); + r = -ENOMEM; cache->nr_dirty = 0; cache->dirty_bitset = alloc_bitset(from_cblock(cache->cache_size)); -- cgit v1.2.3 From 4c52f001344510d1e26a33cfdf971a12338a63d9 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Thu, 31 Oct 2013 13:55:45 -0400 Subject: dm: allocate buffer for messages with small number of arguments using GFP_NOIO commit f36afb3957353d2529cb2b00f78fdccd14fc5e9c upstream. dm-mpath and dm-thin must process messages even if some device is suspended, so we allocate argv buffer with GFP_NOIO. These messages have a small fixed number of arguments. On the other hand, dm-switch needs to process bulk data using messages so excessive use of GFP_NOIO could cause trouble. The patch also lowers the default number of arguments from 64 to 8, so that there is smaller load on GFP_NOIO allocations. Signed-off-by: Mikulas Patocka Acked-by: Alasdair G Kergon Signed-off-by: Mike Snitzer Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-table.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 1ff252ab7d46..9e3a045eb7a2 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -580,14 +580,28 @@ static int adjoin(struct dm_table *table, struct dm_target *ti) /* * Used to dynamically allocate the arg array. + * + * We do first allocation with GFP_NOIO because dm-mpath and dm-thin must + * process messages even if some device is suspended. These messages have a + * small fixed number of arguments. + * + * On the other hand, dm-switch needs to process bulk data using messages and + * excessive use of GFP_NOIO could cause trouble. */ static char **realloc_argv(unsigned *array_size, char **old_argv) { char **argv; unsigned new_size; + gfp_t gfp; - new_size = *array_size ? *array_size * 2 : 64; - argv = kmalloc(new_size * sizeof(*argv), GFP_KERNEL); + if (*array_size) { + new_size = *array_size * 2; + gfp = GFP_KERNEL; + } else { + new_size = 8; + gfp = GFP_NOIO; + } + argv = kmalloc(new_size * sizeof(*argv), gfp); if (argv) { memcpy(argv, old_argv, *array_size * sizeof(*argv)); *array_size = new_size; -- cgit v1.2.3 From b8e15d48cdbbac38b5815b95dd99ac85a0b05edb Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 13 Nov 2013 10:15:42 -0800 Subject: ioatdma: fix sed pool selection commit 5d48b9b5d80e3aa38a5161565398b1e48a650573 upstream. The array to lookup the sed pool based on the number of sources (pq16_idx_to_sedi) is 16 entries and expects a max source index. However, we pass the total source count which runs off the end of the array when src_cnt == 16. The minimal fix is to just pass src_cnt-1, but given we know the source count is > 8 we can just calculate the sed pool by (src_cnt - 2) >> 3. Cc: Dave Jiang Acked-by: Dave Jiang Signed-off-by: Dan Williams Signed-off-by: Greg Kroah-Hartman --- drivers/dma/ioat/dma_v3.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/drivers/dma/ioat/dma_v3.c b/drivers/dma/ioat/dma_v3.c index ca6ea9b3551b..f30f1127a0a9 100644 --- a/drivers/dma/ioat/dma_v3.c +++ b/drivers/dma/ioat/dma_v3.c @@ -87,13 +87,6 @@ static const u8 pq_idx_to_field[] = { 1, 4, 5, 0, 1, 2, 4, 5 }; static const u8 pq16_idx_to_field[] = { 1, 4, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6 }; -/* - * technically sources 1 and 2 do not require SED, but the op will have - * at least 9 descriptors so that's irrelevant. - */ -static const u8 pq16_idx_to_sed[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 1, 1, 1 }; - static void ioat3_eh(struct ioat2_dma_chan *ioat); static dma_addr_t xor_get_src(struct ioat_raw_descriptor *descs[2], int idx) @@ -135,12 +128,6 @@ static void pq_set_src(struct ioat_raw_descriptor *descs[2], pq->coef[idx] = coef; } -static int sed_get_pq16_pool_idx(int src_cnt) -{ - - return pq16_idx_to_sed[src_cnt]; -} - static bool is_jf_ioat(struct pci_dev *pdev) { switch (pdev->device) { @@ -1212,8 +1199,7 @@ __ioat3_prep_pq16_lock(struct dma_chan *c, enum sum_check_flags *result, descs[0] = (struct ioat_raw_descriptor *) pq; - desc->sed = ioat3_alloc_sed(device, - sed_get_pq16_pool_idx(src_cnt)); + desc->sed = ioat3_alloc_sed(device, (src_cnt-2) >> 3); if (!desc->sed) { dev_err(to_dev(chan), "%s: no free sed entries\n", __func__); -- cgit v1.2.3 From 36dabd38dc3432fdb0c922357a60f9331c9334f4 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 13 Nov 2013 10:37:36 -0800 Subject: ioatdma: fix selection of 16 vs 8 source path commit 21e96c7313486390c694919522a76dfea0a86c59 upstream. When performing continuations there are implied sources that need to be added to the source count. Quoting dma_set_maxpq: /* dma_maxpq - reduce maxpq in the face of continued operations * @dma - dma device with PQ capability * @flags - to check if DMA_PREP_CONTINUE and DMA_PREP_PQ_DISABLE_P are set * * When an engine does not support native continuation we need 3 extra * source slots to reuse P and Q with the following coefficients: * 1/ {00} * P : remove P from Q', but use it as a source for P' * 2/ {01} * Q : use Q to continue Q' calculation * 3/ {00} * Q : subtract Q from P' to cancel (2) * * In the case where P is disabled we only need 1 extra source: * 1/ {01} * Q : use Q to continue Q' calculation */ ...fix the selection of the 16 source path to take these implied sources into account. Note this also kills the BUG_ON(src_cnt < 9) check in __ioat3_prep_pq16_lock(). Besides not accounting for implied sources the check is redundant given we already made the path selection. Cc: Dave Jiang Acked-by: Dave Jiang Signed-off-by: Dan Williams Signed-off-by: Greg Kroah-Hartman --- drivers/dma/ioat/dma_v3.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/dma/ioat/dma_v3.c b/drivers/dma/ioat/dma_v3.c index f30f1127a0a9..fa43a42ccc86 100644 --- a/drivers/dma/ioat/dma_v3.c +++ b/drivers/dma/ioat/dma_v3.c @@ -1169,9 +1169,6 @@ __ioat3_prep_pq16_lock(struct dma_chan *c, enum sum_check_flags *result, u8 op; int i, s, idx, num_descs; - /* this function only handles src_cnt 9 - 16 */ - BUG_ON(src_cnt < 9); - /* this function is only called with 9-16 sources */ op = result ? IOAT_OP_PQ_VAL_16S : IOAT_OP_PQ_16S; @@ -1257,13 +1254,21 @@ __ioat3_prep_pq16_lock(struct dma_chan *c, enum sum_check_flags *result, return &desc->txd; } +static int src_cnt_flags(unsigned int src_cnt, unsigned long flags) +{ + if (dmaf_p_disabled_continue(flags)) + return src_cnt + 1; + else if (dmaf_continue(flags)) + return src_cnt + 3; + else + return src_cnt; +} + static struct dma_async_tx_descriptor * ioat3_prep_pq(struct dma_chan *chan, dma_addr_t *dst, dma_addr_t *src, unsigned int src_cnt, const unsigned char *scf, size_t len, unsigned long flags) { - struct dma_device *dma = chan->device; - /* specify valid address for disabled result */ if (flags & DMA_PREP_PQ_DISABLE_P) dst[0] = dst[1]; @@ -1283,7 +1288,7 @@ ioat3_prep_pq(struct dma_chan *chan, dma_addr_t *dst, dma_addr_t *src, single_source_coef[0] = scf[0]; single_source_coef[1] = 0; - return (src_cnt > 8) && (dma->max_pq > 8) ? + return src_cnt_flags(src_cnt, flags) > 8 ? __ioat3_prep_pq16_lock(chan, NULL, dst, single_source, 2, single_source_coef, len, flags) : @@ -1291,7 +1296,7 @@ ioat3_prep_pq(struct dma_chan *chan, dma_addr_t *dst, dma_addr_t *src, single_source_coef, len, flags); } else { - return (src_cnt > 8) && (dma->max_pq > 8) ? + return src_cnt_flags(src_cnt, flags) > 8 ? __ioat3_prep_pq16_lock(chan, NULL, dst, src, src_cnt, scf, len, flags) : __ioat3_prep_pq_lock(chan, NULL, dst, src, src_cnt, @@ -1304,8 +1309,6 @@ ioat3_prep_pq_val(struct dma_chan *chan, dma_addr_t *pq, dma_addr_t *src, unsigned int src_cnt, const unsigned char *scf, size_t len, enum sum_check_flags *pqres, unsigned long flags) { - struct dma_device *dma = chan->device; - /* specify valid address for disabled result */ if (flags & DMA_PREP_PQ_DISABLE_P) pq[0] = pq[1]; @@ -1317,7 +1320,7 @@ ioat3_prep_pq_val(struct dma_chan *chan, dma_addr_t *pq, dma_addr_t *src, */ *pqres = 0; - return (src_cnt > 8) && (dma->max_pq > 8) ? + return src_cnt_flags(src_cnt, flags) > 8 ? __ioat3_prep_pq16_lock(chan, pqres, pq, src, src_cnt, scf, len, flags) : __ioat3_prep_pq_lock(chan, pqres, pq, src, src_cnt, scf, len, @@ -1328,7 +1331,6 @@ static struct dma_async_tx_descriptor * ioat3_prep_pqxor(struct dma_chan *chan, dma_addr_t dst, dma_addr_t *src, unsigned int src_cnt, size_t len, unsigned long flags) { - struct dma_device *dma = chan->device; unsigned char scf[src_cnt]; dma_addr_t pq[2]; @@ -1337,7 +1339,7 @@ ioat3_prep_pqxor(struct dma_chan *chan, dma_addr_t dst, dma_addr_t *src, flags |= DMA_PREP_PQ_DISABLE_Q; pq[1] = dst; /* specify valid address for disabled result */ - return (src_cnt > 8) && (dma->max_pq > 8) ? + return src_cnt_flags(src_cnt, flags) > 8 ? __ioat3_prep_pq16_lock(chan, NULL, pq, src, src_cnt, scf, len, flags) : __ioat3_prep_pq_lock(chan, NULL, pq, src, src_cnt, scf, len, @@ -1349,7 +1351,6 @@ ioat3_prep_pqxor_val(struct dma_chan *chan, dma_addr_t *src, unsigned int src_cnt, size_t len, enum sum_check_flags *result, unsigned long flags) { - struct dma_device *dma = chan->device; unsigned char scf[src_cnt]; dma_addr_t pq[2]; @@ -1363,8 +1364,7 @@ ioat3_prep_pqxor_val(struct dma_chan *chan, dma_addr_t *src, flags |= DMA_PREP_PQ_DISABLE_Q; pq[1] = pq[0]; /* specify valid address for disabled result */ - - return (src_cnt > 8) && (dma->max_pq > 8) ? + return src_cnt_flags(src_cnt, flags) > 8 ? __ioat3_prep_pq16_lock(chan, result, pq, &src[1], src_cnt - 1, scf, len, flags) : __ioat3_prep_pq_lock(chan, result, pq, &src[1], src_cnt - 1, -- cgit v1.2.3 From d8db1a5f3133ec936bcbaced67890f229551d24f Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Mon, 14 Oct 2013 12:11:36 -0400 Subject: blk-core: Fix memory corruption if blkcg_init_queue fails commit fff4996b7db7955414ac74386efa5e07fd766b50 upstream. If blkcg_init_queue fails, blk_alloc_queue_node doesn't call bdi_destroy to clean up structures allocated by the backing dev. ------------[ cut here ]------------ WARNING: at lib/debugobjects.c:260 debug_print_object+0x85/0xa0() ODEBUG: free active (active state 0) object type: percpu_counter hint: (null) Modules linked in: dm_loop dm_mod ip6table_filter ip6_tables uvesafb cfbcopyarea cfbimgblt cfbfillrect fbcon font bitblit fbcon_rotate fbcon_cw fbcon_ud fbcon_ccw softcursor fb fbdev ipt_MASQUERADE iptable_nat nf_nat_ipv4 msr nf_conntrack_ipv4 nf_defrag_ipv4 xt_state ipt_REJECT xt_tcpudp iptable_filter ip_tables x_tables bridge stp llc tun ipv6 cpufreq_userspace cpufreq_stats cpufreq_powersave cpufreq_ondemand cpufreq_conservative spadfs fuse hid_generic usbhid hid raid0 md_mod dmi_sysfs nf_nat_ftp nf_nat nf_conntrack_ftp nf_conntrack lm85 hwmon_vid snd_usb_audio snd_pcm_oss snd_mixer_oss snd_pcm snd_timer snd_page_alloc snd_hwdep snd_usbmidi_lib snd_rawmidi snd soundcore acpi_cpufreq freq_table mperf sata_svw serverworks kvm_amd ide_core ehci_pci ohci_hcd libata ehci_hcd kvm usbcore tg3 usb_common libphy k10temp pcspkr ptp i2c_piix4 i2c_core evdev microcode hwmon rtc_cmos pps_core e100 skge floppy mii processor button unix CPU: 0 PID: 2739 Comm: lvchange Tainted: G W 3.10.15-devel #14 Hardware name: empty empty/S3992-E, BIOS 'V1.06 ' 06/09/2009 0000000000000009 ffff88023c3c1ae8 ffffffff813c8fd4 ffff88023c3c1b20 ffffffff810399eb ffff88043d35cd58 ffffffff81651940 ffff88023c3c1bf8 ffffffff82479d90 0000000000000005 ffff88023c3c1b80 ffffffff81039a67 Call Trace: [] dump_stack+0x19/0x1b [] warn_slowpath_common+0x6b/0xa0 [] warn_slowpath_fmt+0x47/0x50 [] ? debug_check_no_obj_freed+0xcf/0x250 [] debug_print_object+0x85/0xa0 [] debug_check_no_obj_freed+0x203/0x250 [] kmem_cache_free+0x20c/0x3a0 [] blk_alloc_queue_node+0x2a9/0x2c0 [] blk_alloc_queue+0xe/0x10 [] dm_create+0x1a3/0x530 [dm_mod] [] ? list_version_get_info+0xe0/0xe0 [dm_mod] [] dev_create+0x57/0x2b0 [dm_mod] [] ? list_version_get_info+0xe0/0xe0 [dm_mod] [] ? list_version_get_info+0xe0/0xe0 [dm_mod] [] ctl_ioctl+0x268/0x500 [dm_mod] [] ? get_lock_stats+0x22/0x70 [] dm_ctl_ioctl+0xe/0x20 [dm_mod] [] do_vfs_ioctl+0x2ed/0x520 [] ? fget_light+0x377/0x4e0 [] SyS_ioctl+0x4b/0x90 [] system_call_fastpath+0x1a/0x1f ---[ end trace 4b5ff0d55673d986 ]--- ------------[ cut here ]------------ This fix should be backported to stable kernels starting with 2.6.37. Note that in the kernels prior to 3.5 the affected code is different, but the bug is still there - bdi_init is called and bdi_destroy isn't. Signed-off-by: Mikulas Patocka Acked-by: Tejun Heo Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- block/blk-core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/block/blk-core.c b/block/blk-core.c index 45f3a51f6b56..acf3bf6a44d1 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -645,10 +645,12 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id) __set_bit(QUEUE_FLAG_BYPASS, &q->queue_flags); if (blkcg_init_queue(q)) - goto fail_id; + goto fail_bdi; return q; +fail_bdi: + bdi_destroy(&q->backing_dev_info); fail_id: ida_simple_remove(&blk_queue_ida, q->id); fail_q: -- cgit v1.2.3 From 67b51f87ef941607e1e891bf477bd18df53ce6f1 Mon Sep 17 00:00:00 2001 From: Aaron Lu Date: Wed, 6 Nov 2013 08:41:31 +0800 Subject: PM / hibernate: Avoid overflow in hibernate_preallocate_memory() commit fd432b9f8c7c88428a4635b9f5a9c6e174df6e36 upstream. When system has a lot of highmem (e.g. 16GiB using a 32 bits kernel), the code to calculate how much memory we need to preallocate in normal zone may cause overflow. As Leon has analysed: It looks that during computing 'alloc' variable there is overflow: alloc = (3943404 - 1970542) - 1978280 = -5418 (signed) And this function goes to err_out. Fix this by avoiding that overflow. References: https://bugzilla.kernel.org/show_bug.cgi?id=60817 Reported-and-tested-by: Leon Drugi Signed-off-by: Aaron Lu Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- kernel/power/snapshot.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c index 0de28576807d..91c04f16e79c 100644 --- a/kernel/power/snapshot.c +++ b/kernel/power/snapshot.c @@ -1398,7 +1398,11 @@ int hibernate_preallocate_memory(void) * highmem and non-highmem zones separately. */ pages_highmem = preallocate_image_highmem(highmem / 2); - alloc = (count - max_size) - pages_highmem; + alloc = count - max_size; + if (alloc > pages_highmem) + alloc -= pages_highmem; + else + alloc = 0; pages = preallocate_image_memory(alloc, avail_normal); if (pages < alloc) { /* We have exhausted non-highmem pages, try highmem. */ -- cgit v1.2.3 From 2aed351e3f2014138a9551e0cb481128d3f3bd91 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 7 Nov 2013 01:51:15 +0100 Subject: PM / runtime: Use pm_runtime_put_sync() in __device_release_driver() commit baab52ded242c35a2290e1fa82e0cc147d0d8c1a upstream. Commit fa180eb448fa (PM / Runtime: Idle devices asynchronously after probe|release) modified __device_release_driver() to call pm_runtime_put(dev) instead of pm_runtime_put_sync(dev) before detaching the driver from the device. However, that was a mistake, because pm_runtime_put(dev) causes rpm_idle() to be queued up and the driver may be gone already when that function is executed. That breaks the assumptions the drivers have the right to make about the core's behavior on the basis of the existing documentation and actually causes problems to happen, so revert that part of commit fa180eb448fa and restore the previous behavior of __device_release_driver(). Reported-by: Tomi Valkeinen Fixes: fa180eb448fa (PM / Runtime: Idle devices asynchronously after probe|release) Signed-off-by: Rafael J. Wysocki Acked-by: Kevin Hilman Acked-by: Ulf Hansson Signed-off-by: Greg Kroah-Hartman --- drivers/base/dd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 35fa36898916..06051767393f 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -499,7 +499,7 @@ static void __device_release_driver(struct device *dev) BUS_NOTIFY_UNBIND_DRIVER, dev); - pm_runtime_put(dev); + pm_runtime_put_sync(dev); if (dev->bus && dev->bus->remove) dev->bus->remove(dev); -- cgit v1.2.3 From fb675efa409c853ca3464ad93c4cf5d8577ef5e0 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 4 Nov 2013 16:38:08 +1000 Subject: qxl: avoid an oops in the deferred io code. commit cc87509d87696d7cd393882f5dedea01e03e41a9 upstream. If we are using deferred io due to plymouth or X.org fbdev driver we will oops in memcpy due to this pointless multiply here, removing it fixes fbdev to start and not oops. Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/qxl/qxl_fb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/qxl/qxl_fb.c b/drivers/gpu/drm/qxl/qxl_fb.c index b3c51275df5c..7002de79e5da 100644 --- a/drivers/gpu/drm/qxl/qxl_fb.c +++ b/drivers/gpu/drm/qxl/qxl_fb.c @@ -91,7 +91,7 @@ static void qxl_fb_dirty_flush(struct fb_info *info) u32 x1, x2, y1, y2; /* TODO: hard coding 32 bpp */ - int stride = qfbdev->qfb.base.pitches[0] * 4; + int stride = qfbdev->qfb.base.pitches[0]; x1 = qfbdev->dirty.x1; x2 = qfbdev->dirty.x2; -- cgit v1.2.3 From 0c17d9208119338ccb95d1b55ee74d7062928336 Mon Sep 17 00:00:00 2001 From: Avinash Patil Date: Tue, 5 Nov 2013 15:01:44 -0800 Subject: mwifiex: correct packet length for packets from SDIO interface commit d03b4aa77e1187b77dfe37d14a923547f00baa66 upstream. While receiving a packet on SDIO interface, we allocate skb with size multiple of SDIO block size. We need to resize this skb after RX using packet length from RX header. Signed-off-by: Avinash Patil Signed-off-by: Bing Zhao Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/mwifiex/sdio.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c index 139c9581aecc..047a6f348d3d 100644 --- a/drivers/net/wireless/mwifiex/sdio.c +++ b/drivers/net/wireless/mwifiex/sdio.c @@ -930,7 +930,10 @@ static int mwifiex_decode_rx_packet(struct mwifiex_adapter *adapter, struct sk_buff *skb, u32 upld_typ) { u8 *cmd_buf; + __le16 *curr_ptr = (__le16 *)skb->data; + u16 pkt_len = le16_to_cpu(*curr_ptr); + skb_trim(skb, pkt_len); skb_pull(skb, INTF_HEADER_LEN); switch (upld_typ) { -- cgit v1.2.3 From 88870d019e42cb9a9d594c77ea2bdd52e6a68361 Mon Sep 17 00:00:00 2001 From: Ujjal Roy Date: Tue, 5 Nov 2013 15:01:45 -0800 Subject: mwifiex: fix wrong eth_hdr usage for bridged packets in AP mode commit 8d93f1f309d38b65fce0b9f0de91ba6c96990c07 upstream. The eth_hdr is never defined in this driver but it gets compiled without any warning/error because kernel has defined eth_hdr. Fix it by defining our own p_ethhdr and use it instead of eth_hdr. Signed-off-by: Ujjal Roy Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/mwifiex/uap_txrx.c | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/mwifiex/uap_txrx.c b/drivers/net/wireless/mwifiex/uap_txrx.c index a018e42d117e..48e67247e8b1 100644 --- a/drivers/net/wireless/mwifiex/uap_txrx.c +++ b/drivers/net/wireless/mwifiex/uap_txrx.c @@ -34,6 +34,7 @@ static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv, struct mwifiex_txinfo *tx_info; int hdr_chop; struct timeval tv; + struct ethhdr *p_ethhdr; u8 rfc1042_eth_hdr[ETH_ALEN] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; uap_rx_pd = (struct uap_rxpd *)(skb->data); @@ -48,14 +49,36 @@ static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv, } if (!memcmp(&rx_pkt_hdr->rfc1042_hdr, - rfc1042_eth_hdr, sizeof(rfc1042_eth_hdr))) + rfc1042_eth_hdr, sizeof(rfc1042_eth_hdr))) { + /* Replace the 803 header and rfc1042 header (llc/snap) with + * an Ethernet II header, keep the src/dst and snap_type + * (ethertype). + * + * The firmware only passes up SNAP frames converting all RX + * data from 802.11 to 802.2/LLC/SNAP frames. + * + * To create the Ethernet II, just move the src, dst address + * right before the snap_type. + */ + p_ethhdr = (struct ethhdr *) + ((u8 *)(&rx_pkt_hdr->eth803_hdr) + + sizeof(rx_pkt_hdr->eth803_hdr) + + sizeof(rx_pkt_hdr->rfc1042_hdr) + - sizeof(rx_pkt_hdr->eth803_hdr.h_dest) + - sizeof(rx_pkt_hdr->eth803_hdr.h_source) + - sizeof(rx_pkt_hdr->rfc1042_hdr.snap_type)); + memcpy(p_ethhdr->h_source, rx_pkt_hdr->eth803_hdr.h_source, + sizeof(p_ethhdr->h_source)); + memcpy(p_ethhdr->h_dest, rx_pkt_hdr->eth803_hdr.h_dest, + sizeof(p_ethhdr->h_dest)); /* Chop off the rxpd + the excess memory from * 802.2/llc/snap header that was removed. */ - hdr_chop = (u8 *)eth_hdr - (u8 *)uap_rx_pd; - else + hdr_chop = (u8 *)p_ethhdr - (u8 *)uap_rx_pd; + } else { /* Chop off the rxpd */ hdr_chop = (u8 *)&rx_pkt_hdr->eth803_hdr - (u8 *)uap_rx_pd; + } /* Chop off the leading header bytes so the it points * to the start of either the reconstructed EthII frame -- cgit v1.2.3 From b1427212a66869dde67ab630a400bf69fce5dbc0 Mon Sep 17 00:00:00 2001 From: Tyler Hicks Date: Thu, 25 Jul 2013 18:02:55 -0700 Subject: audit: printk USER_AVC messages when audit isn't enabled commit 0868a5e150bc4c47e7a003367cd755811eb41e0b upstream. When the audit=1 kernel parameter is absent and auditd is not running, AUDIT_USER_AVC messages are being silently discarded. AUDIT_USER_AVC messages should be sent to userspace using printk(), as mentioned in the commit message of 4a4cd633 ("AUDIT: Optimise the audit-disabled case for discarding user messages"). When audit_enabled is 0, audit_receive_msg() discards all user messages except for AUDIT_USER_AVC messages. However, audit_log_common_recv_msg() refuses to allocate an audit_buffer if audit_enabled is 0. The fix is to special case AUDIT_USER_AVC messages in both functions. It looks like commit 50397bd1 ("[AUDIT] clean up audit_receive_msg()") introduced this bug. Signed-off-by: Tyler Hicks Cc: Al Viro Cc: Eric Paris Cc: linux-audit@redhat.com Acked-by: Kees Cook Signed-off-by: Richard Guy Briggs Signed-off-by: Eric Paris Signed-off-by: Greg Kroah-Hartman --- kernel/audit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/audit.c b/kernel/audit.c index 7b0e23a740ce..f5dc4b5db72e 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -613,7 +613,7 @@ static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type) int rc = 0; uid_t uid = from_kuid(&init_user_ns, current_uid()); - if (!audit_enabled) { + if (!audit_enabled && msg_type != AUDIT_USER_AVC) { *ab = NULL; return rc; } -- cgit v1.2.3 From d6770065f950cf0f7a2d89b4b419af6c0499ccfe Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Mon, 30 Sep 2013 22:04:25 +0200 Subject: audit: use nlmsg_len() to get message payload length commit 4d8fe7376a12bf4524783dd95cbc00f1fece6232 upstream. Using the nlmsg_len member of the netlink header to test if the message is valid is wrong as it includes the size of the netlink header itself. Thereby allowing to send short netlink messages that pass those checks. Use nlmsg_len() instead to test for the right message length. The result of nlmsg_len() is guaranteed to be non-negative as the netlink message already passed the checks of nlmsg_ok(). Also switch to min_t() to please checkpatch.pl. Cc: Al Viro Cc: Eric Paris Signed-off-by: Mathias Krause Signed-off-by: Richard Guy Briggs Signed-off-by: Eric Paris Signed-off-by: Greg Kroah-Hartman --- kernel/audit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/audit.c b/kernel/audit.c index f5dc4b5db72e..5ce53337a9e4 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -670,7 +670,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) &status_set, sizeof(status_set)); break; case AUDIT_SET: - if (nlh->nlmsg_len < sizeof(struct audit_status)) + if (nlmsg_len(nlh) < sizeof(struct audit_status)) return -EINVAL; status_get = (struct audit_status *)data; if (status_get->mask & AUDIT_STATUS_ENABLED) { @@ -832,7 +832,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) memset(&s, 0, sizeof(s)); /* guard against past and future API changes */ - memcpy(&s, data, min(sizeof(s), (size_t)nlh->nlmsg_len)); + memcpy(&s, data, min_t(size_t, sizeof(s), nlmsg_len(nlh))); if ((s.enabled != 0 && s.enabled != 1) || (s.log_passwd != 0 && s.log_passwd != 1)) return -EINVAL; -- cgit v1.2.3 From 3dc7095c8e78dfeb20dce066fe8bfdfd8497212e Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Mon, 30 Sep 2013 22:04:24 +0200 Subject: audit: fix info leak in AUDIT_GET requests commit 64fbff9ae0a0a843365d922e0057fc785f23f0e3 upstream. We leak 4 bytes of kernel stack in response to an AUDIT_GET request as we miss to initialize the mask member of status_set. Fix that. Cc: Al Viro Cc: Eric Paris Signed-off-by: Mathias Krause Signed-off-by: Richard Guy Briggs Signed-off-by: Eric Paris Signed-off-by: Greg Kroah-Hartman --- kernel/audit.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/audit.c b/kernel/audit.c index 5ce53337a9e4..34eeb48f9c34 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -659,6 +659,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) switch (msg_type) { case AUDIT_GET: + status_set.mask = 0; status_set.enabled = audit_enabled; status_set.failure = audit_failure; status_set.pid = audit_pid; -- cgit v1.2.3 From 24dccf86dd157e545698fdea4723ddf6f699ed87 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Mon, 8 Jul 2013 15:59:36 -0700 Subject: audit: fix mq_open and mq_unlink to add the MQ root as a hidden parent audit_names record commit 79f6530cb59e2a0af6953742a33cc29e98ca631c upstream. The old audit PATH records for mq_open looked like this: type=PATH msg=audit(1366282323.982:869): item=1 name=(null) inode=6777 dev=00:0c mode=041777 ouid=0 ogid=0 rdev=00:00 obj=system_u:object_r:tmpfs_t:s15:c0.c1023 type=PATH msg=audit(1366282323.982:869): item=0 name="test_mq" inode=26732 dev=00:0c mode=0100700 ouid=0 ogid=0 rdev=00:00 obj=staff_u:object_r:user_tmpfs_t:s15:c0.c1023 ...with the audit related changes that went into 3.7, they now look like this: type=PATH msg=audit(1366282236.776:3606): item=2 name=(null) inode=66655 dev=00:0c mode=0100700 ouid=0 ogid=0 rdev=00:00 obj=staff_u:object_r:user_tmpfs_t:s15:c0.c1023 type=PATH msg=audit(1366282236.776:3606): item=1 name=(null) inode=6926 dev=00:0c mode=041777 ouid=0 ogid=0 rdev=00:00 obj=system_u:object_r:tmpfs_t:s15:c0.c1023 type=PATH msg=audit(1366282236.776:3606): item=0 name="test_mq" Both of these look wrong to me. As Steve Grubb pointed out: "What we need is 1 PATH record that identifies the MQ. The other PATH records probably should not be there." Fix it to record the mq root as a parent, and flag it such that it should be hidden from view when the names are logged, since the root of the mq filesystem isn't terribly interesting. With this change, we get a single PATH record that looks more like this: type=PATH msg=audit(1368021604.836:484): item=0 name="test_mq" inode=16914 dev=00:0c mode=0100644 ouid=0 ogid=0 rdev=00:00 obj=unconfined_u:object_r:user_tmpfs_t:s0 In order to do this, a new audit_inode_parent_hidden() function is added. If we do it this way, then we avoid having the existing callers of audit_inode needing to do any sort of flag conversion if auditing is inactive. Signed-off-by: Jeff Layton Reported-by: Jiri Jaburek Cc: Steve Grubb Cc: Eric Paris Cc: Al Viro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- include/linux/audit.h | 26 ++++++++++++++++++++++---- ipc/mqueue.c | 2 ++ kernel/audit.h | 1 + kernel/auditsc.c | 12 +++++++++--- 4 files changed, 34 insertions(+), 7 deletions(-) diff --git a/include/linux/audit.h b/include/linux/audit.h index b20b03852f21..729a4d165bcc 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -103,8 +103,11 @@ extern void __audit_syscall_exit(int ret_success, long ret_value); extern struct filename *__audit_reusename(const __user char *uptr); extern void __audit_getname(struct filename *name); extern void audit_putname(struct filename *name); + +#define AUDIT_INODE_PARENT 1 /* dentry represents the parent */ +#define AUDIT_INODE_HIDDEN 2 /* audit record should be hidden */ extern void __audit_inode(struct filename *name, const struct dentry *dentry, - unsigned int parent); + unsigned int flags); extern void __audit_inode_child(const struct inode *parent, const struct dentry *dentry, const unsigned char type); @@ -148,10 +151,22 @@ static inline void audit_getname(struct filename *name) if (unlikely(!audit_dummy_context())) __audit_getname(name); } -static inline void audit_inode(struct filename *name, const struct dentry *dentry, +static inline void audit_inode(struct filename *name, + const struct dentry *dentry, unsigned int parent) { + if (unlikely(!audit_dummy_context())) { + unsigned int flags = 0; + if (parent) + flags |= AUDIT_INODE_PARENT; + __audit_inode(name, dentry, flags); + } +} +static inline void audit_inode_parent_hidden(struct filename *name, + const struct dentry *dentry) +{ if (unlikely(!audit_dummy_context())) - __audit_inode(name, dentry, parent); + __audit_inode(name, dentry, + AUDIT_INODE_PARENT | AUDIT_INODE_HIDDEN); } static inline void audit_inode_child(const struct inode *parent, const struct dentry *dentry, @@ -311,7 +326,7 @@ static inline void audit_putname(struct filename *name) { } static inline void __audit_inode(struct filename *name, const struct dentry *dentry, - unsigned int parent) + unsigned int flags) { } static inline void __audit_inode_child(const struct inode *parent, const struct dentry *dentry, @@ -321,6 +336,9 @@ static inline void audit_inode(struct filename *name, const struct dentry *dentry, unsigned int parent) { } +static inline void audit_inode_parent_hidden(struct filename *name, + const struct dentry *dentry) +{ } static inline void audit_inode_child(const struct inode *parent, const struct dentry *dentry, const unsigned char type) diff --git a/ipc/mqueue.c b/ipc/mqueue.c index e4e47f647446..ae1996d3c539 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -823,6 +823,7 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode, error = ro; goto out; } + audit_inode_parent_hidden(name, root); filp = do_create(ipc_ns, root->d_inode, &path, oflag, mode, u_attr ? &attr : NULL); @@ -868,6 +869,7 @@ SYSCALL_DEFINE1(mq_unlink, const char __user *, u_name) if (IS_ERR(name)) return PTR_ERR(name); + audit_inode_parent_hidden(name, mnt->mnt_root); err = mnt_want_write(mnt); if (err) goto out_name; diff --git a/kernel/audit.h b/kernel/audit.h index 1c95131ef760..123c9b7c3979 100644 --- a/kernel/audit.h +++ b/kernel/audit.h @@ -85,6 +85,7 @@ struct audit_names { struct filename *name; int name_len; /* number of chars to log */ + bool hidden; /* don't log this record */ bool name_put; /* call __putname()? */ unsigned long ino; diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 3c8a601324a2..9845cb32b60a 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -1399,8 +1399,11 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts } i = 0; - list_for_each_entry(n, &context->names_list, list) + list_for_each_entry(n, &context->names_list, list) { + if (n->hidden) + continue; audit_log_name(context, n, NULL, i++, &call_panic); + } /* Send end of event record to help user space know we are finished */ ab = audit_log_start(context, GFP_KERNEL, AUDIT_EOE); @@ -1769,14 +1772,15 @@ void audit_putname(struct filename *name) * __audit_inode - store the inode and device from a lookup * @name: name being audited * @dentry: dentry being audited - * @parent: does this dentry represent the parent? + * @flags: attributes for this particular entry */ void __audit_inode(struct filename *name, const struct dentry *dentry, - unsigned int parent) + unsigned int flags) { struct audit_context *context = current->audit_context; const struct inode *inode = dentry->d_inode; struct audit_names *n; + bool parent = flags & AUDIT_INODE_PARENT; if (!context->in_syscall) return; @@ -1831,6 +1835,8 @@ out: if (parent) { n->name_len = n->name ? parent_len(n->name->name) : AUDIT_NAME_FULL; n->type = AUDIT_TYPE_PARENT; + if (flags & AUDIT_INODE_HIDDEN) + n->hidden = true; } else { n->name_len = AUDIT_NAME_FULL; n->type = AUDIT_TYPE_NORMAL; -- cgit v1.2.3 From 1ec12a816c2312d55a51a0bcf8748e9c7049d015 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Wed, 8 May 2013 10:25:58 -0400 Subject: audit: add child record before the create to handle case where create fails commit 14e972b4517128ac8e30e3de2ee4fbd995084223 upstream. Historically, when a syscall that creates a dentry fails, you get an audit record that looks something like this (when trying to create a file named "new" in "/tmp/tmp.SxiLnCcv63"): type=PATH msg=audit(1366128956.279:965): item=0 name="/tmp/tmp.SxiLnCcv63/new" inode=2138308 dev=fd:02 mode=040700 ouid=0 ogid=0 rdev=00:00 obj=staff_u:object_r:user_tmp_t:s15:c0.c1023 This record makes no sense since it's associating the inode information for "/tmp/tmp.SxiLnCcv63" with the path "/tmp/tmp.SxiLnCcv63/new". The recent patch I posted to fix the audit_inode call in do_last fixes this, by making it look more like this: type=PATH msg=audit(1366128765.989:13875): item=0 name="/tmp/tmp.DJ1O8V3e4f/" inode=141 dev=fd:02 mode=040700 ouid=0 ogid=0 rdev=00:00 obj=staff_u:object_r:user_tmp_t:s15:c0.c1023 While this is more correct, if the creation of the file fails, then we have no record of the filename that the user tried to create. This patch adds a call to audit_inode_child to may_create. This creates an AUDIT_TYPE_CHILD_CREATE record that will sit in place until the create succeeds. When and if the create does succeed, then this record will be updated with the correct inode info from the create. This fixes what was broken in commit bfcec708. Commit 79f6530c should also be backported to stable v3.7+. Signed-off-by: Jeff Layton Signed-off-by: Eric Paris Signed-off-by: Richard Guy Briggs Signed-off-by: Eric Paris Signed-off-by: Greg Kroah-Hartman --- fs/namei.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/namei.c b/fs/namei.c index 9ed9361223c0..cccaf77e76c5 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -2263,6 +2263,7 @@ static int may_delete(struct inode *dir,struct dentry *victim,int isdir) */ static inline int may_create(struct inode *dir, struct dentry *child) { + audit_inode_child(dir, child, AUDIT_TYPE_CHILD_CREATE); if (child->d_inode) return -EEXIST; if (IS_DEADDIR(dir)) -- cgit v1.2.3 From 3733596c40dc8ef2be53b2945e978373d86312c6 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Wed, 8 May 2013 10:32:23 -0400 Subject: audit: log the audit_names record type commit d3aea84a4ace5ff9ce7fb7714cee07bebef681c2 upstream. ...to make it clear what the intent behind each record's operation was. In many cases you can infer this, based on the context of the syscall and the result. In other cases it's not so obvious. For instance, in the case where you have a file being renamed over another, you'll have two different records with the same filename but different inode info. By logging this information we can clearly tell which one was created and which was deleted. This fixes what was broken in commit bfcec708. Commit 79f6530c should also be backported to stable v3.7+. Signed-off-by: Jeff Layton Signed-off-by: Eric Paris Signed-off-by: Richard Guy Briggs Signed-off-by: Eric Paris Signed-off-by: Greg Kroah-Hartman --- kernel/audit.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/kernel/audit.c b/kernel/audit.c index 34eeb48f9c34..7ddfd8a00a2a 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -1537,6 +1537,26 @@ void audit_log_name(struct audit_context *context, struct audit_names *n, } } + /* log the audit_names record type */ + audit_log_format(ab, " nametype="); + switch(n->type) { + case AUDIT_TYPE_NORMAL: + audit_log_format(ab, "NORMAL"); + break; + case AUDIT_TYPE_PARENT: + audit_log_format(ab, "PARENT"); + break; + case AUDIT_TYPE_CHILD_DELETE: + audit_log_format(ab, "DELETE"); + break; + case AUDIT_TYPE_CHILD_CREATE: + audit_log_format(ab, "CREATE"); + break; + default: + audit_log_format(ab, "UNKNOWN"); + break; + } + audit_log_fcaps(ab, n); audit_log_end(ab); } -- cgit v1.2.3 From cad6526a7a12079819b73c63cefdff076858830e Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Mon, 18 Nov 2013 17:02:45 -0700 Subject: PCI: Remove duplicate pci_disable_device() from pcie_portdrv_remove() commit e7cc5cf74544d97d7b69e2701595037474db1f96 upstream. The pcie_portdrv .probe() method calls pci_enable_device() once, in pcie_port_device_register(), but the .remove() method calls pci_disable_device() twice, in pcie_port_device_remove() and in pcie_portdrv_remove(). That causes a "disabling already-disabled device" warning when removing a PCIe port device. This happens all the time when removing Thunderbolt devices, but is also easy to reproduce with, e.g., "echo 0000:00:1c.3 > /sys/bus/pci/drivers/pcieport/unbind" This patch removes the disable from pcie_portdrv_remove(). [bhelgaas: changelog, tag for stable] Reported-by: David Bulkow Reported-by: Mika Westerberg Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pcie/portdrv_pci.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index 696caed5fdf5..ce8acc71f1a8 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c @@ -223,7 +223,6 @@ static int pcie_portdrv_probe(struct pci_dev *dev, static void pcie_portdrv_remove(struct pci_dev *dev) { pcie_port_device_remove(dev); - pci_disable_device(dev); } static int error_detected_iter(struct device *device, void *data) -- cgit v1.2.3 From 1ba9563629aced9bd4471cd088fbffe11910e6f2 Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Wed, 20 Nov 2013 14:25:34 +0100 Subject: ACPI / hotplug: Fix conflicted PCI bridge notify handlers commit ca499fc87ed945094d952da0eb7eea7dbeb1feec upstream. The PCI host bridge scan handler installs its own notify handler, handle_hotplug_event_root(), by itself. Nevertheless, the ACPI hotplug framework also installs the common notify handler, acpi_hotplug_notify_cb(), for PCI root bridges. This causes acpi_hotplug_notify_cb() to call _OST method with unsupported error as hotplug.enabled is not set. To address this issue, introduce hotplug.ignore flag, which indicates that the scan handler installs its own notify handler by itself. The ACPI hotplug framework does not install the common notify handler when this flag is set. Signed-off-by: Toshi Kani [rjw: Changed the name of the new flag] Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/pci_root.c | 3 +++ drivers/acpi/scan.c | 2 +- include/acpi/acpi_bus.h | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index e36842b9e1fa..a02a91cd1de4 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -63,6 +63,9 @@ static struct acpi_scan_handler pci_root_handler = { .ids = root_device_ids, .attach = acpi_pci_root_add, .detach = acpi_pci_root_remove, + .hotplug = { + .ignore = true, + }, }; /* Lock to protect both acpi_pci_roots lists */ diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 362f0c2aa1ea..cca761e80d89 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1790,7 +1790,7 @@ static void acpi_scan_init_hotplug(acpi_handle handle, int type) */ list_for_each_entry(hwid, &pnp.ids, list) { handler = acpi_scan_match_handler(hwid->id, NULL); - if (handler) { + if (handler && !handler->hotplug.ignore) { acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, acpi_hotplug_notify_cb, handler); break; diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index f45b2a7800c4..6b66efdcd197 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -97,6 +97,7 @@ enum acpi_hotplug_mode { struct acpi_hotplug_profile { struct kobject kobj; bool enabled:1; + bool ignore:1; enum acpi_hotplug_mode mode; }; -- cgit v1.2.3 From 6be060cda95bb7d65d209b382add52bd2dee7662 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Thu, 26 Sep 2013 17:00:46 -0400 Subject: selinux: correct locking in selinux_netlbl_socket_connect) commit 42d64e1add3a1ce8a787116036163b8724362145 upstream. The SELinux/NetLabel glue code has a locking bug that affects systems with NetLabel enabled, see the kernel error message below. This patch corrects this problem by converting the bottom half socket lock to a more conventional, and correct for this call-path, lock_sock() call. =============================== [ INFO: suspicious RCU usage. ] 3.11.0-rc3+ #19 Not tainted ------------------------------- net/ipv4/cipso_ipv4.c:1928 suspicious rcu_dereference_protected() usage! other info that might help us debug this: rcu_scheduler_active = 1, debug_locks = 0 2 locks held by ping/731: #0: (slock-AF_INET/1){+.-...}, at: [...] selinux_netlbl_socket_connect #1: (rcu_read_lock){.+.+..}, at: [<...>] netlbl_conn_setattr stack backtrace: CPU: 1 PID: 731 Comm: ping Not tainted 3.11.0-rc3+ #19 Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011 0000000000000001 ffff88006f659d28 ffffffff81726b6a ffff88003732c500 ffff88006f659d58 ffffffff810e4457 ffff88006b845a00 0000000000000000 000000000000000c ffff880075aa2f50 ffff88006f659d90 ffffffff8169bec7 Call Trace: [] dump_stack+0x54/0x74 [] lockdep_rcu_suspicious+0xe7/0x120 [] cipso_v4_sock_setattr+0x187/0x1a0 [] netlbl_conn_setattr+0x187/0x190 [] ? netlbl_conn_setattr+0x5/0x190 [] selinux_netlbl_socket_connect+0xae/0xc0 [] selinux_socket_connect+0x135/0x170 [] ? might_fault+0x57/0xb0 [] security_socket_connect+0x16/0x20 [] SYSC_connect+0x73/0x130 [] ? sysret_check+0x22/0x5d [] ? trace_hardirqs_on_caller+0xfd/0x1c0 [] ? trace_hardirqs_on_thunk+0x3a/0x3f [] SyS_connect+0xe/0x10 [] system_call_fastpath+0x16/0x1b Signed-off-by: Paul Moore Signed-off-by: Greg Kroah-Hartman --- security/selinux/netlabel.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c index da4b8b233280..6235d052338b 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c @@ -442,8 +442,7 @@ int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr) sksec->nlbl_state != NLBL_CONNLABELED) return 0; - local_bh_disable(); - bh_lock_sock_nested(sk); + lock_sock(sk); /* connected sockets are allowed to disconnect when the address family * is set to AF_UNSPEC, if that is what is happening we want to reset @@ -464,7 +463,6 @@ int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr) sksec->nlbl_state = NLBL_CONNLABELED; socket_connect_return: - bh_unlock_sock(sk); - local_bh_enable(); + release_sock(sk); return rc; } -- cgit v1.2.3 From bf4730f3ac2dcfce9bf3d50a138aa4065283d1d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Bie=C3=9Fmann?= Date: Thu, 24 Oct 2013 12:31:03 +0200 Subject: avr32: setup crt for early panic() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 7a2a74f4b856993218aa7cdeeb6c3103101340db upstream. Before the CRT was (fully) set up in kernel_entry (bss cleared before in _start, but also not before jump to panic() in no_tag_table case). This patch fixes this up to have a fully working CRT when branching to panic() in no_tag_table. Signed-off-by: Andreas Bießmann Acked-by: Hans-Christian Egtvedt Cc: Haavard Skinnemoen Signed-off-by: Greg Kroah-Hartman --- arch/avr32/boot/u-boot/head.S | 30 +++++++++++++++++++++++++----- arch/avr32/kernel/head.S | 20 -------------------- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/arch/avr32/boot/u-boot/head.S b/arch/avr32/boot/u-boot/head.S index 4488fa27fe94..d36d865308df 100644 --- a/arch/avr32/boot/u-boot/head.S +++ b/arch/avr32/boot/u-boot/head.S @@ -8,6 +8,8 @@ * published by the Free Software Foundation. */ #include +#include +#include /* * The kernel is loaded where we want it to be and all caches @@ -20,11 +22,6 @@ .section .init.text,"ax" .global _start _start: - /* Check if the boot loader actually provided a tag table */ - lddpc r0, magic_number - cp.w r12, r0 - brne no_tag_table - /* Initialize .bss */ lddpc r2, bss_start_addr lddpc r3, end_addr @@ -34,6 +31,25 @@ _start: cp r2, r3 brlo 1b + /* Initialize status register */ + lddpc r0, init_sr + mtsr SYSREG_SR, r0 + + /* Set initial stack pointer */ + lddpc sp, stack_addr + sub sp, -THREAD_SIZE + +#ifdef CONFIG_FRAME_POINTER + /* Mark last stack frame */ + mov lr, 0 + mov r7, 0 +#endif + + /* Check if the boot loader actually provided a tag table */ + lddpc r0, magic_number + cp.w r12, r0 + brne no_tag_table + /* * Save the tag table address for later use. This must be done * _after_ .bss has been initialized... @@ -53,6 +69,10 @@ bss_start_addr: .long __bss_start end_addr: .long _end +init_sr: + .long 0x007f0000 /* Supervisor mode, everything masked */ +stack_addr: + .long init_thread_union no_tag_table: sub r12, pc, (. - 2f) diff --git a/arch/avr32/kernel/head.S b/arch/avr32/kernel/head.S index 6163bd0acb95..59eae6dfbed2 100644 --- a/arch/avr32/kernel/head.S +++ b/arch/avr32/kernel/head.S @@ -10,33 +10,13 @@ #include #include -#include -#include .section .init.text,"ax" .global kernel_entry kernel_entry: - /* Initialize status register */ - lddpc r0, init_sr - mtsr SYSREG_SR, r0 - - /* Set initial stack pointer */ - lddpc sp, stack_addr - sub sp, -THREAD_SIZE - -#ifdef CONFIG_FRAME_POINTER - /* Mark last stack frame */ - mov lr, 0 - mov r7, 0 -#endif - /* Start the show */ lddpc pc, kernel_start_addr .align 2 -init_sr: - .long 0x007f0000 /* Supervisor mode, everything masked */ -stack_addr: - .long init_thread_union kernel_start_addr: .long start_kernel -- cgit v1.2.3 From 378c1677f76df7f3b9c65cdd839a18e922d389d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Bie=C3=9Fmann?= Date: Thu, 24 Oct 2013 12:31:04 +0200 Subject: avr32: fix out-of-range jump in large kernels MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit d617b338bbfdd77e9cbd8e7dc949cee3dd73d575 upstream. This patch fixes following error (for big kernels): ---8<--- arch/avr32/boot/u-boot/head.o: In function `no_tag_table': (.init.text+0x44): relocation truncated to fit: R_AVR32_22H_PCREL against symbol `panic' defined in .text.unlikely section in kernel/built-in.o arch/avr32/kernel/built-in.o: In function `bad_return': (.ex.text+0x236): relocation truncated to fit: R_AVR32_22H_PCREL against symbol `panic' defined in .text.unlikely section in kernel/built-in.o --->8--- It comes up when the kernel increases and 'panic()' is too far away to fit in the +/- 2MiB range. Which in turn issues from the 21-bit displacement in 'br{cond4}' mnemonic which is one of the two ways to do jumps (rjmp has just 10-bit displacement and therefore a way smaller range). This fact was stated before in 8d29b7b9f81d6b83d869ff054e6c189d6da73f1f. One solution to solve this is to add a local storage for the symbol address and just load the $pc with that value. Signed-off-by: Andreas Bießmann Acked-by: Hans-Christian Egtvedt Cc: Haavard Skinnemoen Signed-off-by: Greg Kroah-Hartman --- arch/avr32/boot/u-boot/head.S | 5 ++++- arch/avr32/kernel/entry-avr32b.S | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/avr32/boot/u-boot/head.S b/arch/avr32/boot/u-boot/head.S index d36d865308df..2ffc298f061b 100644 --- a/arch/avr32/boot/u-boot/head.S +++ b/arch/avr32/boot/u-boot/head.S @@ -73,8 +73,11 @@ init_sr: .long 0x007f0000 /* Supervisor mode, everything masked */ stack_addr: .long init_thread_union +panic_addr: + .long panic no_tag_table: sub r12, pc, (. - 2f) - bral panic + /* branch to panic() which can be far away with that construct */ + lddpc pc, panic_addr 2: .asciz "Boot loader didn't provide correct magic number\n" diff --git a/arch/avr32/kernel/entry-avr32b.S b/arch/avr32/kernel/entry-avr32b.S index 9899d3cc6f03..7301f4806bbe 100644 --- a/arch/avr32/kernel/entry-avr32b.S +++ b/arch/avr32/kernel/entry-avr32b.S @@ -401,9 +401,10 @@ handle_critical: /* We should never get here... */ bad_return: sub r12, pc, (. - 1f) - bral panic + lddpc pc, 2f .align 2 1: .asciz "Return from critical exception!" +2: .long panic .align 1 do_bus_error_write: -- cgit v1.2.3 From ad03714db9cd8085abbf03891db70daf3cfdcb8b Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 8 Nov 2013 13:39:44 -0600 Subject: prism54: set netdev type to "wlan" commit 8e3ffa471091c560deb6738ed9ab7445b7a5fd04 upstream. Userspace uses the netdev devtype for stuff like device naming and type detection. Be nice and set it. Remove the pointless #if/#endif around SET_NETDEV_DEV too. Signed-off-by: Dan Williams Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/prism54/islpci_dev.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c index 5970ff6f40cc..d498b02f2d01 100644 --- a/drivers/net/wireless/prism54/islpci_dev.c +++ b/drivers/net/wireless/prism54/islpci_dev.c @@ -811,6 +811,10 @@ static const struct net_device_ops islpci_netdev_ops = { .ndo_validate_addr = eth_validate_addr, }; +static struct device_type wlan_type = { + .name = "wlan", +}; + struct net_device * islpci_setup(struct pci_dev *pdev) { @@ -821,9 +825,8 @@ islpci_setup(struct pci_dev *pdev) return ndev; pci_set_drvdata(pdev, ndev); -#if defined(SET_NETDEV_DEV) SET_NETDEV_DEV(ndev, &pdev->dev); -#endif + SET_NETDEV_DEVTYPE(ndev, &wlan_type); /* setup the structure members */ ndev->base_addr = pci_resource_start(pdev, 0); -- cgit v1.2.3 From 2940c25bec92f40a3f7f32504b8ea115d1701892 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Red Hat)" Date: Mon, 25 Nov 2013 20:59:46 -0500 Subject: ftrace: Fix function graph with loading of modules commit 8a56d7761d2d041ae5e8215d20b4167d8aa93f51 upstream. Commit 8c4f3c3fa9681 "ftrace: Check module functions being traced on reload" fixed module loading and unloading with respect to function tracing, but it missed the function graph tracer. If you perform the following # cd /sys/kernel/debug/tracing # echo function_graph > current_tracer # modprobe nfsd # echo nop > current_tracer You'll get the following oops message: ------------[ cut here ]------------ WARNING: CPU: 2 PID: 2910 at /linux.git/kernel/trace/ftrace.c:1640 __ftrace_hash_rec_update.part.35+0x168/0x1b9() Modules linked in: nfsd exportfs nfs_acl lockd ipt_MASQUERADE sunrpc ip6t_REJECT nf_conntrack_ipv6 nf_defrag_ipv6 ip6table_filter ip6_tables uinput snd_hda_codec_idt CPU: 2 PID: 2910 Comm: bash Not tainted 3.13.0-rc1-test #7 Hardware name: To Be Filled By O.E.M. To Be Filled By O.E.M./To be filled by O.E.M., BIOS SDBLI944.86P 05/08/2007 0000000000000668 ffff8800787efcf8 ffffffff814fe193 ffff88007d500000 0000000000000000 ffff8800787efd38 ffffffff8103b80a 0000000000000668 ffffffff810b2b9a ffffffff81a48370 0000000000000001 ffff880037aea000 Call Trace: [] dump_stack+0x4f/0x7c [] warn_slowpath_common+0x81/0x9b [] ? __ftrace_hash_rec_update.part.35+0x168/0x1b9 [] warn_slowpath_null+0x1a/0x1c [] __ftrace_hash_rec_update.part.35+0x168/0x1b9 [] ? __mutex_lock_slowpath+0x364/0x364 [] ftrace_shutdown+0xd7/0x12b [] unregister_ftrace_graph+0x49/0x78 [] graph_trace_reset+0xe/0x10 [] tracing_set_tracer+0xa7/0x26a [] tracing_set_trace_write+0x8b/0xbd [] ? ftrace_return_to_handler+0xb2/0xde [] ? __sb_end_write+0x5e/0x5e [] vfs_write+0xab/0xf6 [] ftrace_graph_caller+0x85/0x85 [] SyS_write+0x59/0x82 [] ftrace_graph_caller+0x85/0x85 [] system_call_fastpath+0x16/0x1b ---[ end trace 940358030751eafb ]--- The above mentioned commit didn't go far enough. Well, it covered the function tracer by adding checks in __register_ftrace_function(). The problem is that the function graph tracer circumvents that (for a slight efficiency gain when function graph trace is running with a function tracer. The gain was not worth this). The problem came with ftrace_startup() which should always be called after __register_ftrace_function(), if you want this bug to be completely fixed. Anyway, this solution moves __register_ftrace_function() inside of ftrace_startup() and removes the need to call them both. Reported-by: Dave Wysochanski Fixes: ed926f9b35cd ("ftrace: Use counters to enable functions to trace") Signed-off-by: Steven Rostedt Signed-off-by: Greg Kroah-Hartman --- kernel/trace/ftrace.c | 64 ++++++++++++++++++++++++++++----------------------- 1 file changed, 35 insertions(+), 29 deletions(-) diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index f23449d0650e..331c102177a6 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -367,9 +367,6 @@ static int remove_ftrace_list_ops(struct ftrace_ops **list, static int __register_ftrace_function(struct ftrace_ops *ops) { - if (unlikely(ftrace_disabled)) - return -ENODEV; - if (FTRACE_WARN_ON(ops == &global_ops)) return -EINVAL; @@ -417,9 +414,6 @@ static int __unregister_ftrace_function(struct ftrace_ops *ops) { int ret; - if (ftrace_disabled) - return -ENODEV; - if (WARN_ON(!(ops->flags & FTRACE_OPS_FL_ENABLED))) return -EBUSY; @@ -2048,10 +2042,15 @@ static void ftrace_startup_enable(int command) static int ftrace_startup(struct ftrace_ops *ops, int command) { bool hash_enable = true; + int ret; if (unlikely(ftrace_disabled)) return -ENODEV; + ret = __register_ftrace_function(ops); + if (ret) + return ret; + ftrace_start_up++; command |= FTRACE_UPDATE_CALLS; @@ -2073,12 +2072,17 @@ static int ftrace_startup(struct ftrace_ops *ops, int command) return 0; } -static void ftrace_shutdown(struct ftrace_ops *ops, int command) +static int ftrace_shutdown(struct ftrace_ops *ops, int command) { bool hash_disable = true; + int ret; if (unlikely(ftrace_disabled)) - return; + return -ENODEV; + + ret = __unregister_ftrace_function(ops); + if (ret) + return ret; ftrace_start_up--; /* @@ -2113,9 +2117,10 @@ static void ftrace_shutdown(struct ftrace_ops *ops, int command) } if (!command || !ftrace_enabled) - return; + return 0; ftrace_run_update_code(command); + return 0; } static void ftrace_startup_sysctl(void) @@ -3020,16 +3025,13 @@ static void __enable_ftrace_function_probe(void) if (i == FTRACE_FUNC_HASHSIZE) return; - ret = __register_ftrace_function(&trace_probe_ops); - if (!ret) - ret = ftrace_startup(&trace_probe_ops, 0); + ret = ftrace_startup(&trace_probe_ops, 0); ftrace_probe_registered = 1; } static void __disable_ftrace_function_probe(void) { - int ret; int i; if (!ftrace_probe_registered) @@ -3042,9 +3044,7 @@ static void __disable_ftrace_function_probe(void) } /* no more funcs left */ - ret = __unregister_ftrace_function(&trace_probe_ops); - if (!ret) - ftrace_shutdown(&trace_probe_ops, 0); + ftrace_shutdown(&trace_probe_ops, 0); ftrace_probe_registered = 0; } @@ -4241,12 +4241,15 @@ core_initcall(ftrace_nodyn_init); static inline int ftrace_init_dyn_debugfs(struct dentry *d_tracer) { return 0; } static inline void ftrace_startup_enable(int command) { } /* Keep as macros so we do not need to define the commands */ -# define ftrace_startup(ops, command) \ - ({ \ - (ops)->flags |= FTRACE_OPS_FL_ENABLED; \ - 0; \ +# define ftrace_startup(ops, command) \ + ({ \ + int ___ret = __register_ftrace_function(ops); \ + if (!___ret) \ + (ops)->flags |= FTRACE_OPS_FL_ENABLED; \ + ___ret; \ }) -# define ftrace_shutdown(ops, command) do { } while (0) +# define ftrace_shutdown(ops, command) __unregister_ftrace_function(ops) + # define ftrace_startup_sysctl() do { } while (0) # define ftrace_shutdown_sysctl() do { } while (0) @@ -4646,9 +4649,7 @@ int register_ftrace_function(struct ftrace_ops *ops) mutex_lock(&ftrace_lock); - ret = __register_ftrace_function(ops); - if (!ret) - ret = ftrace_startup(ops, 0); + ret = ftrace_startup(ops, 0); mutex_unlock(&ftrace_lock); @@ -4667,9 +4668,7 @@ int unregister_ftrace_function(struct ftrace_ops *ops) int ret; mutex_lock(&ftrace_lock); - ret = __unregister_ftrace_function(ops); - if (!ret) - ftrace_shutdown(ops, 0); + ret = ftrace_shutdown(ops, 0); mutex_unlock(&ftrace_lock); return ret; @@ -4863,6 +4862,13 @@ ftrace_suspend_notifier_call(struct notifier_block *bl, unsigned long state, return NOTIFY_DONE; } +/* Just a place holder for function graph */ +static struct ftrace_ops fgraph_ops __read_mostly = { + .func = ftrace_stub, + .flags = FTRACE_OPS_FL_STUB | FTRACE_OPS_FL_GLOBAL | + FTRACE_OPS_FL_RECURSION_SAFE, +}; + int register_ftrace_graph(trace_func_graph_ret_t retfunc, trace_func_graph_ent_t entryfunc) { @@ -4889,7 +4895,7 @@ int register_ftrace_graph(trace_func_graph_ret_t retfunc, ftrace_graph_return = retfunc; ftrace_graph_entry = entryfunc; - ret = ftrace_startup(&global_ops, FTRACE_START_FUNC_RET); + ret = ftrace_startup(&fgraph_ops, FTRACE_START_FUNC_RET); out: mutex_unlock(&ftrace_lock); @@ -4906,7 +4912,7 @@ void unregister_ftrace_graph(void) ftrace_graph_active--; ftrace_graph_return = (trace_func_graph_ret_t)ftrace_stub; ftrace_graph_entry = ftrace_graph_entry_stub; - ftrace_shutdown(&global_ops, FTRACE_STOP_FUNC_RET); + ftrace_shutdown(&fgraph_ops, FTRACE_STOP_FUNC_RET); unregister_pm_notifier(&ftrace_suspend_notifier); unregister_trace_sched_switch(ftrace_graph_probe_sched_switch, NULL); -- cgit v1.2.3 From 4f94b6e4b43ca3a1027803bd3cab21e72bbb991e Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Mon, 28 Oct 2013 02:02:19 -0700 Subject: drm/ttm: Fix memory type compatibility check commit 59c8e66378fb78adbcd05f0d09783dde6fef282b upstream. Also check the busy placements before deciding to move a buffer object. Failing to do this may result in a completely unneccessary move within a single memory type. Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/ttm/ttm_bo.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 9b07b7d44a58..8697abd7b173 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -1153,24 +1153,32 @@ out_unlock: return ret; } -static int ttm_bo_mem_compat(struct ttm_placement *placement, - struct ttm_mem_reg *mem) +static bool ttm_bo_mem_compat(struct ttm_placement *placement, + struct ttm_mem_reg *mem, + uint32_t *new_flags) { int i; if (mem->mm_node && placement->lpfn != 0 && (mem->start < placement->fpfn || mem->start + mem->num_pages > placement->lpfn)) - return -1; + return false; for (i = 0; i < placement->num_placement; i++) { - if ((placement->placement[i] & mem->placement & - TTM_PL_MASK_CACHING) && - (placement->placement[i] & mem->placement & - TTM_PL_MASK_MEM)) - return i; + *new_flags = placement->placement[i]; + if ((*new_flags & mem->placement & TTM_PL_MASK_CACHING) && + (*new_flags & mem->placement & TTM_PL_MASK_MEM)) + return true; + } + + for (i = 0; i < placement->num_busy_placement; i++) { + *new_flags = placement->busy_placement[i]; + if ((*new_flags & mem->placement & TTM_PL_MASK_CACHING) && + (*new_flags & mem->placement & TTM_PL_MASK_MEM)) + return true; } - return -1; + + return false; } int ttm_bo_validate(struct ttm_buffer_object *bo, @@ -1179,6 +1187,7 @@ int ttm_bo_validate(struct ttm_buffer_object *bo, bool no_wait_gpu) { int ret; + uint32_t new_flags; BUG_ON(!ttm_bo_is_reserved(bo)); /* Check that range is valid */ @@ -1189,8 +1198,7 @@ int ttm_bo_validate(struct ttm_buffer_object *bo, /* * Check whether we need to move buffer. */ - ret = ttm_bo_mem_compat(placement, &bo->mem); - if (ret < 0) { + if (!ttm_bo_mem_compat(placement, &bo->mem, &new_flags)) { ret = ttm_bo_move_buffer(bo, placement, interruptible, no_wait_gpu); if (ret) @@ -1200,7 +1208,7 @@ int ttm_bo_validate(struct ttm_buffer_object *bo, * Use the access and other non-mapping-related flag bits from * the compatible memory placement flags to the active flags */ - ttm_flag_masked(&bo->mem.placement, placement->placement[ret], + ttm_flag_masked(&bo->mem.placement, new_flags, ~TTM_PL_MASK_MEMTYPE); } /* -- cgit v1.2.3 From f692d2d8bebddeb8c8faedfc41e4732f3dc23e5b Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Wed, 30 Oct 2013 02:46:56 -0700 Subject: drm/ttm: Handle in-memory region copies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 9a0599ddeae012a771bba5e23393fc52d8a59d89 upstream. Fix the case where the ttm pointer may be NULL causing a NULL pointer dereference. Signed-off-by: Jakob Bornecrantz Signed-off-by: Thomas Hellström Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/ttm/ttm_bo_util.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index af894584dd90..068341ad1f5f 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -347,7 +347,9 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, if (old_iomap == NULL && ttm == NULL) goto out2; - if (ttm->state == tt_unpopulated) { + /* TTM might be null for moves within the same region. + */ + if (ttm && ttm->state == tt_unpopulated) { ret = ttm->bdev->driver->ttm_tt_populate(ttm); if (ret) { /* if we fail here don't nuke the mm node -- cgit v1.2.3 From 6c3c00e3f509af95f7ca80492311a3ce485528e2 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 30 Oct 2013 03:29:50 -0700 Subject: drm/ttm: Fix ttm_bo_move_memcpy commit da95c788ef0c645378ffccb7060a0df1a33aee38 upstream. All error paths will want to keep the mm node, so handle this at the function exit. This fixes an ioremap failure error path. Also add some comments to make the function a bit easier to understand. Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/ttm/ttm_bo_util.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 068341ad1f5f..b7f757158df7 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -342,21 +342,25 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, if (ret) goto out; + /* + * Single TTM move. NOP. + */ if (old_iomap == NULL && new_iomap == NULL) goto out2; + + /* + * Move nonexistent data. NOP. + */ if (old_iomap == NULL && ttm == NULL) goto out2; - /* TTM might be null for moves within the same region. + /* + * TTM might be null for moves within the same region. */ if (ttm && ttm->state == tt_unpopulated) { ret = ttm->bdev->driver->ttm_tt_populate(ttm); - if (ret) { - /* if we fail here don't nuke the mm node - * as the bo still owns it */ - old_copy.mm_node = NULL; + if (ret) goto out1; - } } add = 0; @@ -382,11 +386,8 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, prot); } else ret = ttm_copy_io_page(new_iomap, old_iomap, page); - if (ret) { - /* failing here, means keep old copy as-is */ - old_copy.mm_node = NULL; + if (ret) goto out1; - } } mb(); out2: @@ -404,7 +405,12 @@ out1: ttm_mem_reg_iounmap(bdev, old_mem, new_iomap); out: ttm_mem_reg_iounmap(bdev, &old_copy, old_iomap); - ttm_bo_mem_put(bo, &old_copy); + + /* + * On error, keep the mm node! + */ + if (!ret) + ttm_bo_mem_put(bo, &old_copy); return ret; } EXPORT_SYMBOL(ttm_bo_move_memcpy); -- cgit v1.2.3 From 0c405f5ffe3415927a937fec905393cae640e24e Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 4 Nov 2013 08:13:45 +0100 Subject: drm/i915: flush cursors harder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit b2ea8ef559b4d94190009f3651b5b3ab7c05afd3 upstream. Apparently they need the same treatment as primary planes. This fixes modesetting failures because of stuck cursors (!) on Thomas' i830M machine. I've figured while at it I'll also roll it out for the ivb 3 pipe version of this function. I didn't do this for i845/i865 since Bspec says the update mechanism works differently, and there's some additional rules about what can be updated in which order. Tested-by: Thomas Richter Cc: Thomas Richter Cc: Ville Syrjälä Signed-off-by: Daniel Vetter Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_display.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index ab952595e088..c714d4d5bedb 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6262,7 +6262,9 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base) intel_crtc->cursor_visible = visible; } /* and commit changes on next vblank */ + POSTING_READ(CURCNTR(pipe)); I915_WRITE(CURBASE(pipe), base); + POSTING_READ(CURBASE(pipe)); } static void ivb_update_cursor(struct drm_crtc *crtc, u32 base) @@ -6289,7 +6291,9 @@ static void ivb_update_cursor(struct drm_crtc *crtc, u32 base) intel_crtc->cursor_visible = visible; } /* and commit changes on next vblank */ + POSTING_READ(CURCNTR_IVB(pipe)); I915_WRITE(CURBASE_IVB(pipe), base); + POSTING_READ(CURBASE_IVB(pipe)); } /* If no-part of the cursor is visible on the framebuffer, then the GPU may hang... */ -- cgit v1.2.3 From 31278c7029bfeb279e367a437ddeeb45307321a7 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 13 Nov 2013 15:18:32 +1000 Subject: drm/nouveau: when bailing out of a pushbuf ioctl, do not remove previous fence commit 9360bd1112d8874d21942e2ae74f5416b00a8db6 upstream. Signed-off-by: Ben Skeggs Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/nouveau/nouveau_gem.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index b4b4d0c1f4af..5bccf31cc974 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -287,7 +287,8 @@ validate_fini_list(struct list_head *list, struct nouveau_fence *fence) list_for_each_safe(entry, tmp, list) { nvbo = list_entry(entry, struct nouveau_bo, entry); - nouveau_bo_fence(nvbo, fence); + if (likely(fence)) + nouveau_bo_fence(nvbo, fence); if (unlikely(nvbo->validate_mapped)) { ttm_bo_kunmap(&nvbo->kmap); -- cgit v1.2.3 From 48527487543e8290ae7127b27cce5dd7d9df567f Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 28 Oct 2013 10:56:23 -0400 Subject: drm/radeon/si: fix define for MC_SEQ_TRAIN_WAKEUP_CNTL commit d5693761b2b4ff530c8af8af9ec55b6eae76e617 upstream. Typo in the register offset. Noticed-by: Sylvain BERTRAND Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/sid.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h index 495f41f2900b..108c8d2503c9 100644 --- a/drivers/gpu/drm/radeon/sid.h +++ b/drivers/gpu/drm/radeon/sid.h @@ -247,7 +247,7 @@ #define NOOFGROUPS_SHIFT 12 #define NOOFGROUPS_MASK 0x00001000 -#define MC_SEQ_TRAIN_WAKEUP_CNTL 0x2808 +#define MC_SEQ_TRAIN_WAKEUP_CNTL 0x28e8 #define TRAIN_DONE_D0 (1 << 30) #define TRAIN_DONE_D1 (1 << 31) -- cgit v1.2.3 From 08ab0aac9ec2d6c07acb6bd96f3e9e872b3dfbaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Wed, 30 Oct 2013 12:56:04 +0100 Subject: drm/radeon: activate UVD clocks before sending the destroy msg MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit c154a76311293f9671439286834aa325b7ef59fe upstream. Make sure the UVD clocks are still active before sending the destroy message, otherwise the hw might hang. Signed-off-by: Christian König Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_uvd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c index f3ccf6d4addb..a809b1733e7b 100644 --- a/drivers/gpu/drm/radeon/radeon_uvd.c +++ b/drivers/gpu/drm/radeon/radeon_uvd.c @@ -242,6 +242,8 @@ void radeon_uvd_free_handles(struct radeon_device *rdev, struct drm_file *filp) if (handle != 0 && rdev->uvd.filp[i] == filp) { struct radeon_fence *fence; + radeon_uvd_note_usage(rdev); + r = radeon_uvd_get_destroy_msg(rdev, R600_RING_TYPE_UVD_INDEX, handle, &fence); if (r) { -- cgit v1.2.3 From ed540279a8af2c4005430303f74df05ca5576879 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 31 Oct 2013 16:43:27 -0400 Subject: drm/radeon: don't share PPLLs on DCE4.1 commit 70471860ff9f335c60c004d42ebd48945bfa5403 upstream. Sharing PPLLs seems to cause problems on some boards. Bug: https://bugs.freedesktop.org/show_bug.cgi?id=45334 Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/atombios_crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index d5df8fd10217..22f06c8d8e0b 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -1683,7 +1683,7 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc) if (pll != ATOM_PPLL_INVALID) return pll; } - } else { + } else if (!ASIC_IS_DCE41(rdev)) { /* Don't share PLLs on DCE4.1 chips */ /* use the same PPLL for all monitors with the same clock */ pll = radeon_get_shared_nondp_ppll(crtc); if (pll != ATOM_PPLL_INVALID) -- cgit v1.2.3 From 65007af07bb8c82207a7b2d2428773b28a3d614e Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Tue, 12 Nov 2013 10:51:16 -0500 Subject: radeon: workaround pinning failure on low ram gpu commit 97b6ff6be9da7675aab339334fda996d6c5077d9 upstream. GPU with low amount of ram can fails at pinning new framebuffer before unpinning old one. On such failure, retry with unpinning old one before pinning new one allowing to work around the issue. This is somewhat ugly but only affect those old GPU we care about. Signed-off-by: Jerome Glisse Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_legacy_crtc.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index 7cb178a34a0f..bc73021d3596 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c @@ -422,6 +422,7 @@ int radeon_crtc_do_set_base(struct drm_crtc *crtc, /* Pin framebuffer & get tilling informations */ obj = radeon_fb->obj; rbo = gem_to_radeon_bo(obj); +retry: r = radeon_bo_reserve(rbo, false); if (unlikely(r != 0)) return r; @@ -430,6 +431,33 @@ int radeon_crtc_do_set_base(struct drm_crtc *crtc, &base); if (unlikely(r != 0)) { radeon_bo_unreserve(rbo); + + /* On old GPU like RN50 with little vram pining can fails because + * current fb is taking all space needed. So instead of unpining + * the old buffer after pining the new one, first unpin old one + * and then retry pining new one. + * + * As only master can set mode only master can pin and it is + * unlikely the master client will race with itself especialy + * on those old gpu with single crtc. + * + * We don't shutdown the display controller because new buffer + * will end up in same spot. + */ + if (!atomic && fb && fb != crtc->fb) { + struct radeon_bo *old_rbo; + unsigned long nsize, osize; + + old_rbo = gem_to_radeon_bo(to_radeon_framebuffer(fb)->obj); + osize = radeon_bo_size(old_rbo); + nsize = radeon_bo_size(rbo); + if (nsize <= osize && !radeon_bo_reserve(old_rbo, false)) { + radeon_bo_unpin(old_rbo); + radeon_bo_unreserve(old_rbo); + fb = NULL; + goto retry; + } + } return -EINVAL; } radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL); -- cgit v1.2.3 From 57a5b135c2fd42bfcab2fa4b25395234038e4a16 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Thu, 10 Oct 2013 18:23:38 +0200 Subject: edac, highbank: Fix interrupt setup of mem and l2 controller commit a72b8859fd3941cc1d2940d5c43026d2c6fb959e upstream. Register and enable interrupts after the edac registration. Otherwise incomming ecc error interrupts lead to crashes during device setup. Fixing this in drivers for mc and l2. Signed-off-by: Robert Richter Acked-by: Rob Herring Signed-off-by: Robert Richter Signed-off-by: Greg Kroah-Hartman --- drivers/edac/highbank_l2_edac.c | 18 ++++++++++-------- drivers/edac/highbank_mc_edac.c | 18 ++++++++++-------- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/drivers/edac/highbank_l2_edac.c b/drivers/edac/highbank_l2_edac.c index c2bd8c6a4349..10d3d298b640 100644 --- a/drivers/edac/highbank_l2_edac.c +++ b/drivers/edac/highbank_l2_edac.c @@ -90,28 +90,30 @@ static int highbank_l2_err_probe(struct platform_device *pdev) goto err; } + dci->mod_name = dev_name(&pdev->dev); + dci->dev_name = dev_name(&pdev->dev); + + if (edac_device_add_device(dci)) + goto err; + drvdata->db_irq = platform_get_irq(pdev, 0); res = devm_request_irq(&pdev->dev, drvdata->db_irq, highbank_l2_err_handler, 0, dev_name(&pdev->dev), dci); if (res < 0) - goto err; + goto err2; drvdata->sb_irq = platform_get_irq(pdev, 1); res = devm_request_irq(&pdev->dev, drvdata->sb_irq, highbank_l2_err_handler, 0, dev_name(&pdev->dev), dci); if (res < 0) - goto err; - - dci->mod_name = dev_name(&pdev->dev); - dci->dev_name = dev_name(&pdev->dev); - - if (edac_device_add_device(dci)) - goto err; + goto err2; devres_close_group(&pdev->dev, NULL); return 0; +err2: + edac_device_del_device(&pdev->dev); err: devres_release_group(&pdev->dev, NULL); edac_device_free_ctl_info(dci); diff --git a/drivers/edac/highbank_mc_edac.c b/drivers/edac/highbank_mc_edac.c index 4695dd2d71fd..7a78307588bc 100644 --- a/drivers/edac/highbank_mc_edac.c +++ b/drivers/edac/highbank_mc_edac.c @@ -189,14 +189,6 @@ static int highbank_mc_probe(struct platform_device *pdev) goto err; } - irq = platform_get_irq(pdev, 0); - res = devm_request_irq(&pdev->dev, irq, highbank_mc_err_handler, - 0, dev_name(&pdev->dev), mci); - if (res < 0) { - dev_err(&pdev->dev, "Unable to request irq %d\n", irq); - goto err; - } - mci->mtype_cap = MEM_FLAG_DDR3; mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; mci->edac_cap = EDAC_FLAG_SECDED; @@ -217,10 +209,20 @@ static int highbank_mc_probe(struct platform_device *pdev) if (res < 0) goto err; + irq = platform_get_irq(pdev, 0); + res = devm_request_irq(&pdev->dev, irq, highbank_mc_err_handler, + 0, dev_name(&pdev->dev), mci); + if (res < 0) { + dev_err(&pdev->dev, "Unable to request irq %d\n", irq); + goto err2; + } + highbank_mc_create_debugfs_nodes(mci); devres_close_group(&pdev->dev, NULL); return 0; +err2: + edac_mc_del_mc(&pdev->dev); err: devres_release_group(&pdev->dev, NULL); edac_mc_free(mci); -- cgit v1.2.3 From 9d41513cef9d3e3083a0cb83216b88074492f461 Mon Sep 17 00:00:00 2001 From: Steve French Date: Fri, 15 Nov 2013 20:41:32 -0600 Subject: setfacl removes part of ACL when setting POSIX ACLs to Samba commit b1d93356427be6f050dc55c86eb019d173700af6 upstream. setfacl over cifs mounts can remove the default ACL when setting the (non-default part of) the ACL and vice versa (we were leaving at 0 rather than setting to -1 the count field for the unaffected half of the ACL. For example notice the setfacl removed the default ACL in this sequence: steven@steven-GA-970A-DS3:~/cifs-2.6$ getfacl /mnt/test-dir ; setfacl -m default:user:test:rwx,user:test:rwx /mnt/test-dir getfacl: Removing leading '/' from absolute path names user::rwx group::r-x other::r-x default:user::rwx default:user:test:rwx default:group::r-x default:mask::rwx default:other::r-x steven@steven-GA-970A-DS3:~/cifs-2.6$ getfacl /mnt/test-dir getfacl: Removing leading '/' from absolute path names user::rwx user:test:rwx group::r-x mask::rwx other::r-x Signed-off-by: Steve French Acked-by: Jeremy Allison Signed-off-by: Greg Kroah-Hartman --- fs/cifs/cifssmb.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index a58dc77cc443..d17c5d72cd29 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -3306,11 +3306,13 @@ static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL, return 0; } cifs_acl->version = cpu_to_le16(1); - if (acl_type == ACL_TYPE_ACCESS) + if (acl_type == ACL_TYPE_ACCESS) { cifs_acl->access_entry_count = cpu_to_le16(count); - else if (acl_type == ACL_TYPE_DEFAULT) + cifs_acl->default_entry_count = __constant_cpu_to_le16(0xFFFF); + } else if (acl_type == ACL_TYPE_DEFAULT) { cifs_acl->default_entry_count = cpu_to_le16(count); - else { + cifs_acl->access_entry_count = __constant_cpu_to_le16(0xFFFF); + } else { cifs_dbg(FYI, "unknown ACL type %d\n", acl_type); return 0; } -- cgit v1.2.3 From 8e43aac1ec86b5955ecf396395f6fd8b4be42157 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 14 Nov 2013 15:16:15 +1100 Subject: md: fix calculation of stacking limits on level change. commit 02e5f5c0a0f726e66e3d8506ea1691e344277969 upstream. The various ->run routines of md personalities assume that the 'queue' has been initialised by the blk_set_stacking_limits() call in md_alloc(). However when the level is changed (by level_store()) the ->run routine for the new level is called for an array which has already had the stacking limits modified. This can result in incorrect final settings. So call blk_set_stacking_limits() before ->run in level_store(). A specific consequence of this bug is that it causes discard_granularity to be set incorrectly when reshaping a RAID4 to a RAID0. This is suitable for any -stable kernel since 3.3 in which blk_set_stacking_limits() was introduced. Reported-and-tested-by: "Baldysiak, Pawel" Signed-off-by: NeilBrown Signed-off-by: Greg Kroah-Hartman --- drivers/md/md.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/md/md.c b/drivers/md/md.c index d78f1fffab01..2290b95009de 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -3619,6 +3619,7 @@ level_store(struct mddev *mddev, const char *buf, size_t len) mddev->in_sync = 1; del_timer_sync(&mddev->safemode_timer); } + blk_set_stacking_limits(&mddev->queue->limits); pers->run(mddev); set_bit(MD_CHANGE_DEVS, &mddev->flags); mddev_resume(mddev); -- cgit v1.2.3 From 5b80fd00af8b03e0b03ec52aec90485525eb2e73 Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Tue, 26 Nov 2013 13:58:18 +0100 Subject: HID: uhid: fix leak for 64/32 UHID_CREATE commit 80897aa787ecd58eabb29deab7cbec9249c9b7e6 upstream. UHID allows short writes so user-space can omit unused fields. We automatically set them to 0 in the kernel. However, the 64/32 bit compat-handler didn't do that in the UHID_CREATE fallback. This will reveal random kernel heap data (of random size, even) to user-space. Fixes: befde0226a59 ('HID: uhid: make creating devices work on 64/32 systems') Reported-by: Ben Hutchings Signed-off-by: David Herrmann Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/hid/uhid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hid/uhid.c b/drivers/hid/uhid.c index 145a4cb5c872..0bb3bb889b71 100644 --- a/drivers/hid/uhid.c +++ b/drivers/hid/uhid.c @@ -312,7 +312,7 @@ static int uhid_event_from_user(const char __user *buffer, size_t len, */ struct uhid_create_req_compat *compat; - compat = kmalloc(sizeof(*compat), GFP_KERNEL); + compat = kzalloc(sizeof(*compat), GFP_KERNEL); if (!compat) return -ENOMEM; -- cgit v1.2.3 From 8e7314052be20d6a00bc524648a2a8daf7139d46 Mon Sep 17 00:00:00 2001 From: Michael Neuling Date: Mon, 25 Nov 2013 11:12:20 +1100 Subject: powerpc/signals: Improved mark VSX not saved with small contexts fix commit ec67ad82814bee92251fd963bf01c7a173856555 upstream. In a recent patch: commit c13f20ac48328b05cd3b8c19e31ed6c132b44b42 Author: Michael Neuling powerpc/signals: Mark VSX not saved with small contexts We fixed an issue but an improved solution was later discussed after the patch was merged. Firstly, this patch doesn't handle the 64bit signals case, which could also hit this issue (but has never been reported). Secondly, the original patch isn't clear what MSR VSX should be set to. The new approach below always clears the MSR VSX bit (to indicate no VSX is in the context) and sets it only in the specific case where VSX is available (ie. when VSX has been used and the signal context passed has space to provide the state). This reverts the original patch and replaces it with the improved solution. It also adds a 64 bit version. Signed-off-by: Michael Neuling Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/kernel/signal_32.c | 16 +++++++--------- arch/powerpc/kernel/signal_64.c | 6 ++++++ 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index 323309963cd3..7e9dff80e1dc 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c @@ -442,6 +442,12 @@ static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame, #endif /* CONFIG_ALTIVEC */ if (copy_fpr_to_user(&frame->mc_fregs, current)) return 1; + + /* + * Clear the MSR VSX bit to indicate there is no valid state attached + * to this context, except in the specific case below where we set it. + */ + msr &= ~MSR_VSX; #ifdef CONFIG_VSX /* * Copy VSR 0-31 upper half from thread_struct to local @@ -454,15 +460,7 @@ static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame, if (copy_vsx_to_user(&frame->mc_vsregs, current)) return 1; msr |= MSR_VSX; - } else if (!ctx_has_vsx_region) - /* - * With a small context structure we can't hold the VSX - * registers, hence clear the MSR value to indicate the state - * was not saved. - */ - msr &= ~MSR_VSX; - - + } #endif /* CONFIG_VSX */ #ifdef CONFIG_SPE /* save spe registers */ diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c index 887e99d85bc2..35c20a1fb365 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c @@ -121,6 +121,12 @@ static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, flush_fp_to_thread(current); /* copy fpr regs and fpscr */ err |= copy_fpr_to_user(&sc->fp_regs, current); + + /* + * Clear the MSR VSX bit to indicate there is no valid state attached + * to this context, except in the specific case below where we set it. + */ + msr &= ~MSR_VSX; #ifdef CONFIG_VSX /* * Copy VSX low doubleword to local buffer for formatting, -- cgit v1.2.3 From 1a2d670b28befe626d50a39af579da44ecd22245 Mon Sep 17 00:00:00 2001 From: Frank Zago Date: Wed, 13 Nov 2013 22:53:00 +0000 Subject: iio:accel:kxsd9 fix missing mutex unlock commit 0ee005c7dc2803125275e24598f0fb37775a6af3 upstream. This will leave a lock held after reading from the device, preventing any further reads. Signed-off-by: Frank Zago Signed-off-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/iio/accel/kxsd9.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/iio/accel/kxsd9.c b/drivers/iio/accel/kxsd9.c index 7229645bf1d7..7c9a1d97dc68 100644 --- a/drivers/iio/accel/kxsd9.c +++ b/drivers/iio/accel/kxsd9.c @@ -112,9 +112,10 @@ static int kxsd9_read(struct iio_dev *indio_dev, u8 address) mutex_lock(&st->buf_lock); st->tx[0] = KXSD9_READ(address); ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers)); - if (ret) - return ret; - return (((u16)(st->rx[0])) << 8) | (st->rx[1] & 0xF0); + if (!ret) + ret = (((u16)(st->rx[0])) << 8) | (st->rx[1] & 0xF0); + mutex_unlock(&st->buf_lock); + return ret; } static IIO_CONST_ATTR(accel_scale_available, -- cgit v1.2.3 From 3df594a7ac9a732413ecaad15682945715df4443 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 21 Nov 2013 16:22:17 +0100 Subject: s390/uaccess: add missing page table walk range check commit 71a86ef055f569b93bc6901f007bdf447dbf515f upstream. When translating a user space address, the address must be checked against the ASCE limit of the process. If the address is larger than the maximum address that is reachable with the ASCE, an ASCE type exception must be generated. The current code simply ignored the higher order bits. This resulted in an address wrap around in user space instead of an exception in user space. Reviewed-by: Gerald Schaefer Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky Signed-off-by: Greg Kroah-Hartman --- arch/s390/lib/uaccess_pt.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/s390/lib/uaccess_pt.c b/arch/s390/lib/uaccess_pt.c index 50ea137a2d3c..1bf40ef57cf6 100644 --- a/arch/s390/lib/uaccess_pt.c +++ b/arch/s390/lib/uaccess_pt.c @@ -78,11 +78,14 @@ static size_t copy_in_kernel(size_t count, void __user *to, * contains the (negative) exception code. */ #ifdef CONFIG_64BIT + static unsigned long follow_table(struct mm_struct *mm, unsigned long address, int write) { unsigned long *table = (unsigned long *)__pa(mm->pgd); + if (unlikely(address > mm->context.asce_limit - 1)) + return -0x38UL; switch (mm->context.asce_bits & _ASCE_TYPE_MASK) { case _ASCE_TYPE_REGION1: table = table + ((address >> 53) & 0x7ff); -- cgit v1.2.3 From ced4ac92852e8f17fabcbed7492ba459619640aa Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 5 Sep 2013 12:30:04 -0400 Subject: workqueue: fix ordered workqueues in NUMA setups commit 8a2b75384444488fc4f2cbb9f0921b6a0794838f upstream. An ordered workqueue implements execution ordering by using single pool_workqueue with max_active == 1. On a given pool_workqueue, work items are processed in FIFO order and limiting max_active to 1 enforces the queued work items to be processed one by one. Unfortunately, 4c16bd327c ("workqueue: implement NUMA affinity for unbound workqueues") accidentally broke this guarantee by applying NUMA affinity to ordered workqueues too. On NUMA setups, an ordered workqueue would end up with separate pool_workqueues for different nodes. Each pool_workqueue still limits max_active to 1 but multiple work items may be executed concurrently and out of order depending on which node they are queued to. Fix it by using dedicated ordered_wq_attrs[] when creating ordered workqueues. The new attrs match the unbound ones except that no_numa is always set thus forcing all NUMA nodes to share the default pool_workqueue. While at it, add sanity check in workqueue creation path which verifies that an ordered workqueues has only the default pool_workqueue. Signed-off-by: Tejun Heo Reported-by: Libin Cc: Lai Jiangshan Signed-off-by: Greg Kroah-Hartman --- kernel/workqueue.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/kernel/workqueue.c b/kernel/workqueue.c index e52d002d3893..68086a34b8ef 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -295,6 +295,9 @@ static DEFINE_HASHTABLE(unbound_pool_hash, UNBOUND_POOL_HASH_ORDER); /* I: attributes used when instantiating standard unbound pools on demand */ static struct workqueue_attrs *unbound_std_wq_attrs[NR_STD_WORKER_POOLS]; +/* I: attributes used when instantiating ordered pools on demand */ +static struct workqueue_attrs *ordered_wq_attrs[NR_STD_WORKER_POOLS]; + struct workqueue_struct *system_wq __read_mostly; EXPORT_SYMBOL(system_wq); struct workqueue_struct *system_highpri_wq __read_mostly; @@ -4059,7 +4062,7 @@ out_unlock: static int alloc_and_link_pwqs(struct workqueue_struct *wq) { bool highpri = wq->flags & WQ_HIGHPRI; - int cpu; + int cpu, ret; if (!(wq->flags & WQ_UNBOUND)) { wq->cpu_pwqs = alloc_percpu(struct pool_workqueue); @@ -4079,6 +4082,13 @@ static int alloc_and_link_pwqs(struct workqueue_struct *wq) mutex_unlock(&wq->mutex); } return 0; + } else if (wq->flags & __WQ_ORDERED) { + ret = apply_workqueue_attrs(wq, ordered_wq_attrs[highpri]); + /* there should only be single pwq for ordering guarantee */ + WARN(!ret && (wq->pwqs.next != &wq->dfl_pwq->pwqs_node || + wq->pwqs.prev != &wq->dfl_pwq->pwqs_node), + "ordering guarantee broken for workqueue %s\n", wq->name); + return ret; } else { return apply_workqueue_attrs(wq, unbound_std_wq_attrs[highpri]); } @@ -4990,13 +5000,23 @@ static int __init init_workqueues(void) } } - /* create default unbound wq attrs */ + /* create default unbound and ordered wq attrs */ for (i = 0; i < NR_STD_WORKER_POOLS; i++) { struct workqueue_attrs *attrs; BUG_ON(!(attrs = alloc_workqueue_attrs(GFP_KERNEL))); attrs->nice = std_nice[i]; unbound_std_wq_attrs[i] = attrs; + + /* + * An ordered wq should have only one pwq as ordering is + * guaranteed by max_active which is enforced by pwqs. + * Turn off NUMA so that dfl_pwq is used for all nodes. + */ + BUG_ON(!(attrs = alloc_workqueue_attrs(GFP_KERNEL))); + attrs->nice = std_nice[i]; + attrs->no_numa = true; + ordered_wq_attrs[i] = attrs; } system_wq = alloc_workqueue("events", 0, 0); -- cgit v1.2.3 From ddff5adaf7ec9d2591718b04074605914f9987cd Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 26 Nov 2013 15:03:41 +0100 Subject: cpuset: Fix memory allocator deadlock commit 0fc0287c9ed1ffd3706f8b4d9b314aa102ef1245 upstream. Juri hit the below lockdep report: [ 4.303391] ====================================================== [ 4.303392] [ INFO: SOFTIRQ-safe -> SOFTIRQ-unsafe lock order detected ] [ 4.303394] 3.12.0-dl-peterz+ #144 Not tainted [ 4.303395] ------------------------------------------------------ [ 4.303397] kworker/u4:3/689 [HC0[0]:SC0[0]:HE0:SE1] is trying to acquire: [ 4.303399] (&p->mems_allowed_seq){+.+...}, at: [] new_slab+0x6c/0x290 [ 4.303417] [ 4.303417] and this task is already holding: [ 4.303418] (&(&q->__queue_lock)->rlock){..-...}, at: [] blk_execute_rq_nowait+0x5b/0x100 [ 4.303431] which would create a new lock dependency: [ 4.303432] (&(&q->__queue_lock)->rlock){..-...} -> (&p->mems_allowed_seq){+.+...} [ 4.303436] [ 4.303898] the dependencies between the lock to be acquired and SOFTIRQ-irq-unsafe lock: [ 4.303918] -> (&p->mems_allowed_seq){+.+...} ops: 2762 { [ 4.303922] HARDIRQ-ON-W at: [ 4.303923] [] __lock_acquire+0x65a/0x1ff0 [ 4.303926] [] lock_acquire+0x93/0x140 [ 4.303929] [] kthreadd+0x86/0x180 [ 4.303931] [] ret_from_fork+0x7c/0xb0 [ 4.303933] SOFTIRQ-ON-W at: [ 4.303933] [] __lock_acquire+0x68c/0x1ff0 [ 4.303935] [] lock_acquire+0x93/0x140 [ 4.303940] [] kthreadd+0x86/0x180 [ 4.303955] [] ret_from_fork+0x7c/0xb0 [ 4.303959] INITIAL USE at: [ 4.303960] [] __lock_acquire+0x344/0x1ff0 [ 4.303963] [] lock_acquire+0x93/0x140 [ 4.303966] [] kthreadd+0x86/0x180 [ 4.303969] [] ret_from_fork+0x7c/0xb0 [ 4.303972] } Which reports that we take mems_allowed_seq with interrupts enabled. A little digging found that this can only be from cpuset_change_task_nodemask(). This is an actual deadlock because an interrupt doing an allocation will hit get_mems_allowed()->...->__read_seqcount_begin(), which will spin forever waiting for the write side to complete. Cc: John Stultz Cc: Mel Gorman Reported-by: Juri Lelli Signed-off-by: Peter Zijlstra Tested-by: Juri Lelli Acked-by: Li Zefan Acked-by: Mel Gorman Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- kernel/cpuset.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 6948e9476b42..d313870dcd02 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -984,8 +984,10 @@ static void cpuset_change_task_nodemask(struct task_struct *tsk, need_loop = task_has_mempolicy(tsk) || !nodes_intersects(*newmems, tsk->mems_allowed); - if (need_loop) + if (need_loop) { + local_irq_disable(); write_seqcount_begin(&tsk->mems_allowed_seq); + } nodes_or(tsk->mems_allowed, tsk->mems_allowed, *newmems); mpol_rebind_task(tsk, newmems, MPOL_REBIND_STEP1); @@ -993,8 +995,10 @@ static void cpuset_change_task_nodemask(struct task_struct *tsk, mpol_rebind_task(tsk, newmems, MPOL_REBIND_STEP2); tsk->mems_allowed = *newmems; - if (need_loop) + if (need_loop) { write_seqcount_end(&tsk->mems_allowed_seq); + local_irq_enable(); + } task_unlock(tsk); } -- cgit v1.2.3 From e1a8b1a389031976d9e40c93662beff169a10d06 Mon Sep 17 00:00:00 2001 From: Kailang Yang Date: Tue, 26 Nov 2013 15:41:40 +0800 Subject: ALSA: hda/realtek - Set pcbeep amp for ALC668 commit 9ad54547cf6f4410eba83bb95dfd2a0966718d6d upstream. Set the missing pcbeep default amp for ALC668. Signed-off-by: Kailang Yang Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 8bce044583ed..531160c7b1fb 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4494,6 +4494,7 @@ static int patch_alc662(struct hda_codec *codec) case 0x10ec0272: case 0x10ec0663: case 0x10ec0665: + case 0x10ec0668: set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); break; case 0x10ec0273: -- cgit v1.2.3 From eda7913868a57fe6047459290b59d66007f99053 Mon Sep 17 00:00:00 2001 From: Kailang Yang Date: Tue, 26 Nov 2013 15:17:50 +0800 Subject: ALSA: hda/realtek - Add support of ALC231 codec commit ba4c4d0a9021ab034554d532a98133d668b87599 upstream. It's compatible with ALC269. Signed-off-by: Kailang Yang Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 531160c7b1fb..fa8a1570e4dd 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4552,6 +4552,7 @@ static int patch_alc680(struct hda_codec *codec) */ static const struct hda_codec_preset snd_hda_preset_realtek[] = { { .id = 0x10ec0221, .name = "ALC221", .patch = patch_alc269 }, + { .id = 0x10ec0231, .name = "ALC231", .patch = patch_alc269 }, { .id = 0x10ec0233, .name = "ALC233", .patch = patch_alc269 }, { .id = 0x10ec0255, .name = "ALC255", .patch = patch_alc269 }, { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 }, -- cgit v1.2.3 From 5fb0e7deb22f290a47686898a01fb39a581f9970 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 26 Nov 2013 08:44:26 +0100 Subject: ALSA: hda - Fix hp-mic mode without VREF bits commit 16c0cefe8951b2c4b824fd06011ac1b359b1ab3b upstream. When the hp mic pin has no VREF bits, the driver forgot to set PIN_IN bit. Spotted during debugging old MacBook Airs. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=65681 Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/hda_generic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 26ed56f00b7c..fd856cc6ed63 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c @@ -2703,7 +2703,7 @@ static int hp_mic_jack_mode_put(struct snd_kcontrol *kcontrol, val &= ~(AC_PINCTL_VREFEN | PIN_HP); val |= get_vref_idx(vref_caps, idx) | PIN_IN; } else - val = snd_hda_get_default_vref(codec, nid); + val = snd_hda_get_default_vref(codec, nid) | PIN_IN; } snd_hda_set_pin_ctl_cache(codec, nid, val); call_hp_automute(codec, NULL); -- cgit v1.2.3 From 41d7a448d028d328ce608b9207172a64ece4a005 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 26 Nov 2013 08:33:45 +0100 Subject: ALSA: hda - Create Headhpone Mic Jack Mode when really needed commit ced4cefc75fdb8be95eaee325ad0f6b2fc0a484b upstream. When a headphone jack is configurable as input, the generic parser tries to make it retaskable as Headphone Mic. The switching can be done smoothly if Capture Source control exists (i.e. there is another input source). Or when user explicitly enables the creation of jack mode controls, "Headhpone Mic Jack Mode" will be created accordingly. However, if the headphone mic is the only input source, we have to create "Headphone Mic Jack Mode" control because there is no capture source selection. Otherwise, the generic parser assumes that the input is constantly enabled, thus the headphone is permanently set as input. This situation happens on the old MacBook Airs where no input is supported properly, for example. This patch fixes the problem: now "Headphone Mic Jack Mode" is created when such an input selection isn't possible. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=65681 Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/hda_generic.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index fd856cc6ed63..3a3abfa6150c 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c @@ -2445,12 +2445,8 @@ static int create_out_jack_modes(struct hda_codec *codec, int num_pins, for (i = 0; i < num_pins; i++) { hda_nid_t pin = pins[i]; - if (pin == spec->hp_mic_pin) { - int ret = create_hp_mic_jack_mode(codec, pin); - if (ret < 0) - return ret; + if (pin == spec->hp_mic_pin) continue; - } if (get_out_jack_num_items(codec, pin) > 1) { struct snd_kcontrol_new *knew; char name[44]; @@ -2723,9 +2719,6 @@ static int create_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t pin) struct hda_gen_spec *spec = codec->spec; struct snd_kcontrol_new *knew; - if (get_out_jack_num_items(codec, pin) <= 1 && - get_in_jack_num_items(codec, pin) <= 1) - return 0; /* no need */ knew = snd_hda_gen_add_kctl(spec, "Headphone Mic Jack Mode", &hp_mic_jack_mode_enum); if (!knew) @@ -4287,6 +4280,17 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec, if (err < 0) return err; + /* create "Headphone Mic Jack Mode" if no input selection is + * available (or user specifies add_jack_modes hint) + */ + if (spec->hp_mic_pin && + (spec->auto_mic || spec->input_mux.num_items == 1 || + spec->add_jack_modes)) { + err = create_hp_mic_jack_mode(codec, spec->hp_mic_pin); + if (err < 0) + return err; + } + if (spec->add_jack_modes) { if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { err = create_out_jack_modes(codec, cfg->line_outs, -- cgit v1.2.3 From 7f9bf8ad0ea7457c6f3d5c6b04fe6c7b99fec63d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 28 Nov 2013 15:21:21 +0100 Subject: ALSA: hda - Initialize missing bass speaker pin for ASUS AIO ET2700 commit 1f0bbf03cb829162ec8e6d03c98aaaed88c6f534 upstream. Add a fixup entry for the missing bass speaker pin 0x16 on ASUS ET2700 AiO desktop. The channel map will be added in the next patch, so that this can be backported easily to stable kernels. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=65961 Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index fa8a1570e4dd..661afe7d85e4 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -1765,6 +1765,7 @@ enum { ALC889_FIXUP_IMAC91_VREF, ALC882_FIXUP_INV_DMIC, ALC882_FIXUP_NO_PRIMARY_HP, + ALC887_FIXUP_ASUS_BASS, }; static void alc889_fixup_coef(struct hda_codec *codec, @@ -2086,6 +2087,13 @@ static const struct hda_fixup alc882_fixups[] = { .type = HDA_FIXUP_FUNC, .v.func = alc882_fixup_no_primary_hp, }, + [ALC887_FIXUP_ASUS_BASS] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { + {0x16, 0x99130130}, /* bass speaker */ + {} + }, + }, }; static const struct snd_pci_quirk alc882_fixup_tbl[] = { @@ -2119,6 +2127,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { SND_PCI_QUIRK(0x1043, 0x1873, "ASUS W90V", ALC882_FIXUP_ASUS_W90V), SND_PCI_QUIRK(0x1043, 0x1971, "Asus W2JC", ALC882_FIXUP_ASUS_W2JC), SND_PCI_QUIRK(0x1043, 0x835f, "Asus Eee 1601", ALC888_FIXUP_EEE1601), + SND_PCI_QUIRK(0x1043, 0x84bc, "ASUS ET2700", ALC887_FIXUP_ASUS_BASS), SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC889_FIXUP_VAIO_TT), SND_PCI_QUIRK(0x104d, 0x905a, "Sony Vaio Z", ALC882_FIXUP_NO_PRIMARY_HP), SND_PCI_QUIRK(0x104d, 0x9043, "Sony Vaio VGC-LN51JGB", ALC882_FIXUP_NO_PRIMARY_HP), -- cgit v1.2.3 From fe070ad95a7f94a658273f5f359a6875ad3cd38c Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 28 Nov 2013 11:05:28 +0100 Subject: ALSA: hda - Check leaf nodes to find aamix amps commit 2ded3e5b61d61d0bc90bebb8004db6184c7db6eb upstream. The current generic parser assumes blindly that the volume and mute amps are found in the aamix node itself. But on some codecs, typically Analog Devices ones, the aamix amps are separately implemented in each leaf node of the aamix node, and the current driver can't establish the correct amp controls. This is a regression compared with the previous static quirks. This patch extends the search for the amps to the leaf nodes for allowing the aamix controls again on such codecs. In this implementation, I didn't code to loop through the whole paths, since usually one depth should suffice, and we can't search too deeply, as it may result in the conflicting control assignments. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=65641 Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/hda_generic.c | 57 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 45 insertions(+), 12 deletions(-) diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 3a3abfa6150c..7975031312cb 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c @@ -2747,6 +2747,42 @@ static int add_loopback_list(struct hda_gen_spec *spec, hda_nid_t mix, int idx) return 0; } +/* return true if either a volume or a mute amp is found for the given + * aamix path; the amp has to be either in the mixer node or its direct leaf + */ +static bool look_for_mix_leaf_ctls(struct hda_codec *codec, hda_nid_t mix_nid, + hda_nid_t pin, unsigned int *mix_val, + unsigned int *mute_val) +{ + int idx, num_conns; + const hda_nid_t *list; + hda_nid_t nid; + + idx = snd_hda_get_conn_index(codec, mix_nid, pin, true); + if (idx < 0) + return false; + + *mix_val = *mute_val = 0; + if (nid_has_volume(codec, mix_nid, HDA_INPUT)) + *mix_val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT); + if (nid_has_mute(codec, mix_nid, HDA_INPUT)) + *mute_val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT); + if (*mix_val && *mute_val) + return true; + + /* check leaf node */ + num_conns = snd_hda_get_conn_list(codec, mix_nid, &list); + if (num_conns < idx) + return false; + nid = list[idx]; + if (!*mix_val && nid_has_volume(codec, nid, HDA_OUTPUT)) + *mix_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT); + if (!*mute_val && nid_has_mute(codec, nid, HDA_OUTPUT)) + *mute_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT); + + return *mix_val || *mute_val; +} + /* create input playback/capture controls for the given pin */ static int new_analog_input(struct hda_codec *codec, int input_idx, hda_nid_t pin, const char *ctlname, int ctlidx, @@ -2754,12 +2790,11 @@ static int new_analog_input(struct hda_codec *codec, int input_idx, { struct hda_gen_spec *spec = codec->spec; struct nid_path *path; - unsigned int val; + unsigned int mix_val, mute_val; int err, idx; - if (!nid_has_volume(codec, mix_nid, HDA_INPUT) && - !nid_has_mute(codec, mix_nid, HDA_INPUT)) - return 0; /* no need for analog loopback */ + if (!look_for_mix_leaf_ctls(codec, mix_nid, pin, &mix_val, &mute_val)) + return 0; path = snd_hda_add_new_path(codec, pin, mix_nid, 0); if (!path) @@ -2768,20 +2803,18 @@ static int new_analog_input(struct hda_codec *codec, int input_idx, spec->loopback_paths[input_idx] = snd_hda_get_path_idx(codec, path); idx = path->idx[path->depth - 1]; - if (nid_has_volume(codec, mix_nid, HDA_INPUT)) { - val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT); - err = __add_pb_vol_ctrl(spec, HDA_CTL_WIDGET_VOL, ctlname, ctlidx, val); + if (mix_val) { + err = __add_pb_vol_ctrl(spec, HDA_CTL_WIDGET_VOL, ctlname, ctlidx, mix_val); if (err < 0) return err; - path->ctls[NID_PATH_VOL_CTL] = val; + path->ctls[NID_PATH_VOL_CTL] = mix_val; } - if (nid_has_mute(codec, mix_nid, HDA_INPUT)) { - val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT); - err = __add_pb_sw_ctrl(spec, HDA_CTL_WIDGET_MUTE, ctlname, ctlidx, val); + if (mute_val) { + err = __add_pb_sw_ctrl(spec, HDA_CTL_WIDGET_MUTE, ctlname, ctlidx, mute_val); if (err < 0) return err; - path->ctls[NID_PATH_MUTE_CTL] = val; + path->ctls[NID_PATH_MUTE_CTL] = mute_val; } path->active = true; -- cgit v1.2.3 From 1bfdf02fc01d8b4c96cd536ee9e2552268e67784 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Red Hat)" Date: Tue, 26 Nov 2013 09:22:54 -0500 Subject: tracing: Allow events to have NULL strings commit 4e58e54754dc1fec21c3a9e824bc108b05fdf46e upstream. If an TRACE_EVENT() uses __assign_str() or __get_str on a NULL pointer then the following oops will happen: BUG: unable to handle kernel NULL pointer dereference at (null) IP: [] strlen+0x10/0x1a *pde = 00000000 ^M Oops: 0000 [#1] PREEMPT SMP Modules linked in: CPU: 1 PID: 0 Comm: swapper/1 Not tainted 3.13.0-rc1-test+ #2 Hardware name: /DG965MQ, BIOS MQ96510J.86A.0372.2006.0605.1717 06/05/2006^M task: f5cde9f0 ti: f5e5e000 task.ti: f5e5e000 EIP: 0060:[] EFLAGS: 00210046 CPU: 1 EIP is at strlen+0x10/0x1a EAX: 00000000 EBX: c2472da8 ECX: ffffffff EDX: c2472da8 ESI: c1c5e5fc EDI: 00000000 EBP: f5e5fe84 ESP: f5e5fe80 DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 CR0: 8005003b CR2: 00000000 CR3: 01f32000 CR4: 000007d0 Stack: f5f18b90 f5e5feb8 c10687a8 0759004f 00000005 00000005 00000005 00200046 00000002 00000000 c1082a93 f56c7e28 c2472da8 c1082a93 f5e5fee4 c106bc61^M 00000000 c1082a93 00000000 00000000 00000001 00200046 00200082 00000000 Call Trace: [] ftrace_raw_event_lock+0x39/0xc0 [] ? ktime_get+0x29/0x69 [] ? ktime_get+0x29/0x69 [] lock_release+0x57/0x1a5 [] ? ktime_get+0x29/0x69 [] read_seqcount_begin.constprop.7+0x4d/0x75 [] ? ktime_get+0x29/0x69^M [] ktime_get+0x29/0x69 [] __tick_nohz_idle_enter+0x1e/0x426 [] ? lock_release_holdtime.part.19+0x48/0x4d [] ? time_hardirqs_off+0xe/0x28 [] ? trace_hardirqs_off_caller+0x3f/0xaf [] tick_nohz_idle_enter+0x59/0x62 [] cpu_startup_entry+0x64/0x192 [] start_secondary+0x277/0x27c Code: 90 89 c6 89 d0 88 c4 ac 38 e0 74 09 84 c0 75 f7 be 01 00 00 00 89 f0 48 5e 5d c3 55 89 e5 57 66 66 66 66 90 83 c9 ff 89 c7 31 c0 ae f7 d1 8d 41 ff 5f 5d c3 55 89 e5 57 66 66 66 66 90 31 ff EIP: [] strlen+0x10/0x1a SS:ESP 0068:f5e5fe80 CR2: 0000000000000000 ---[ end trace 01bc47bf519ec1b2 ]--- New tracepoints have been added that have allowed for NULL pointers being assigned to strings. To fix this, change the TRACE_EVENT() code to check for NULL and if it is, it will assign "(null)" to it instead (similar to what glibc printf does). Reported-by: Shuah Khan Reported-by: Jovi Zhangwei Link: http://lkml.kernel.org/r/CAGdX0WFeEuy+DtpsJzyzn0343qEEjLX97+o1VREFkUEhndC+5Q@mail.gmail.com Link: http://lkml.kernel.org/r/528D6972.9010702@samsung.com Fixes: 9cbf117662e2 ("tracing/events: provide string with undefined size support") Signed-off-by: Steven Rostedt Signed-off-by: Greg Kroah-Hartman --- include/trace/ftrace.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/trace/ftrace.h b/include/trace/ftrace.h index 19edd7facaa1..66dba42128d7 100644 --- a/include/trace/ftrace.h +++ b/include/trace/ftrace.h @@ -368,7 +368,8 @@ ftrace_define_fields_##call(struct ftrace_event_call *event_call) \ __data_size += (len) * sizeof(type); #undef __string -#define __string(item, src) __dynamic_array(char, item, strlen(src) + 1) +#define __string(item, src) __dynamic_array(char, item, \ + strlen((src) ? (const char *)(src) : "(null)") + 1) #undef DECLARE_EVENT_CLASS #define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \ @@ -498,7 +499,7 @@ static inline notrace int ftrace_get_offsets_##call( \ #undef __assign_str #define __assign_str(dst, src) \ - strcpy(__get_str(dst), src); + strcpy(__get_str(dst), (src) ? (const char *)(src) : "(null)"); #undef TP_fast_assign #define TP_fast_assign(args...) args -- cgit v1.2.3 From cb8e5e98aeae9e0d845576f6f59227c9ad8f76ff Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Thu, 31 Oct 2013 00:25:34 -0700 Subject: Input: evdev - fall back to vmalloc for client event buffer commit 92eb77d0ffbaa71b501a0a8dabf09a351bf4267f upstream. evdev always tries to allocate the event buffer for clients using kzalloc rather than vmalloc, presumably to avoid mapping overhead where possible. However, drivers like bcm5974, which claims support for reporting 16 fingers simultaneously, can have an extraordinarily large buffer. The resultant contiguous order-4 allocation attempt fails due to fragmentation, and the device is thus unusable until reboot. Try kzalloc if we can to avoid the mapping overhead, but if that fails, fall back to vzalloc. Signed-off-by: Daniel Stone Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/input/evdev.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index f0f8928b3c8a..c122dd2adc22 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include #include #include @@ -289,7 +291,11 @@ static int evdev_release(struct inode *inode, struct file *file) mutex_unlock(&evdev->mutex); evdev_detach_client(evdev, client); - kfree(client); + + if (is_vmalloc_addr(client)) + vfree(client); + else + kfree(client); evdev_close_device(evdev); @@ -309,12 +315,14 @@ static int evdev_open(struct inode *inode, struct file *file) { struct evdev *evdev = container_of(inode->i_cdev, struct evdev, cdev); unsigned int bufsize = evdev_compute_buffer_size(evdev->handle.dev); + unsigned int size = sizeof(struct evdev_client) + + bufsize * sizeof(struct input_event); struct evdev_client *client; int error; - client = kzalloc(sizeof(struct evdev_client) + - bufsize * sizeof(struct input_event), - GFP_KERNEL); + client = kzalloc(size, GFP_KERNEL | __GFP_NOWARN); + if (!client) + client = vzalloc(size); if (!client) return -ENOMEM; -- cgit v1.2.3 From 5b1c45c29961824f123ae8ed1020db2bd8d072ba Mon Sep 17 00:00:00 2001 From: Joseph Salisbury Date: Wed, 16 Oct 2013 09:19:40 -0700 Subject: Input: cypress_ps2 - do not consider data bad if palm is detected commit 5df682b297f6b23ec35615ed7bb50cbb25d25869 upstream. If hardware (or firmware) detects palm on the surface of the device it does not mean that the data packet is bad from the protocol standpoint. Instead of reporting PSMOUSE_BAD_DATA in this case simply threat it as if nothing touches the surface. BugLink: http://bugs.launchpad.net/bugs/1229361 Signed-off-by: Joseph Salisbury Tested-by: Kamal Mostafa Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/input/mouse/cypress_ps2.c | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/drivers/input/mouse/cypress_ps2.c b/drivers/input/mouse/cypress_ps2.c index f51765fff054..888a81a7ea3d 100644 --- a/drivers/input/mouse/cypress_ps2.c +++ b/drivers/input/mouse/cypress_ps2.c @@ -439,7 +439,7 @@ static int cypress_get_finger_count(unsigned char header_byte) case 2: return 5; default: /* Invalid contact (e.g. palm). Ignore it. */ - return -1; + return 0; } } @@ -452,17 +452,10 @@ static int cypress_parse_packet(struct psmouse *psmouse, { unsigned char *packet = psmouse->packet; unsigned char header_byte = packet[0]; - int contact_cnt; memset(report_data, 0, sizeof(struct cytp_report_data)); - contact_cnt = cypress_get_finger_count(header_byte); - - if (contact_cnt < 0) /* e.g. palm detect */ - return -EINVAL; - - report_data->contact_cnt = contact_cnt; - + report_data->contact_cnt = cypress_get_finger_count(header_byte); report_data->tap = (header_byte & ABS_MULTIFINGER_TAP) ? 1 : 0; if (report_data->contact_cnt == 1) { @@ -535,11 +528,9 @@ static void cypress_process_packet(struct psmouse *psmouse, bool zero_pkt) int slots[CYTP_MAX_MT_SLOTS]; int n; - if (cypress_parse_packet(psmouse, cytp, &report_data)) - return; + cypress_parse_packet(psmouse, cytp, &report_data); n = report_data.contact_cnt; - if (n > CYTP_MAX_MT_SLOTS) n = CYTP_MAX_MT_SLOTS; @@ -605,10 +596,6 @@ static psmouse_ret_t cypress_validate_byte(struct psmouse *psmouse) return PSMOUSE_BAD_DATA; contact_cnt = cypress_get_finger_count(packet[0]); - - if (contact_cnt < 0) - return PSMOUSE_BAD_DATA; - if (cytp->mode & CYTP_BIT_ABS_NO_PRESSURE) cypress_set_packet_size(psmouse, contact_cnt == 2 ? 7 : 4); else -- cgit v1.2.3 From d84c1fcb5bdb1ac919fe7262505306a2ca1a6281 Mon Sep 17 00:00:00 2001 From: Tom Gundersen Date: Thu, 31 Oct 2013 00:33:54 -0700 Subject: Input: i8042 - add PNP modaliases commit 78551277e4df57864b0b0e7f85c23ede2be2edb8 upstream. This allows the module to be autoloaded in the common case. In order to work on non-PnP systems the module should be compiled in or loaded unconditionally at boot (c.f. modules-load.d(5)), as before. Signed-off-by: Tom Gundersen Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/input/serio/i8042-x86ia64io.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 5f306f79da0c..0ec9abbe31fe 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -765,6 +765,7 @@ static struct pnp_device_id pnp_kbd_devids[] = { { .id = "CPQA0D7", .driver_data = 0 }, { .id = "", }, }; +MODULE_DEVICE_TABLE(pnp, pnp_kbd_devids); static struct pnp_driver i8042_pnp_kbd_driver = { .name = "i8042 kbd", @@ -786,6 +787,7 @@ static struct pnp_device_id pnp_aux_devids[] = { { .id = "SYN0801", .driver_data = 0 }, { .id = "", }, }; +MODULE_DEVICE_TABLE(pnp, pnp_aux_devids); static struct pnp_driver i8042_pnp_aux_driver = { .name = "i8042 aux", -- cgit v1.2.3 From 59f466a632b8502d2fb35b2cd119a061f8922021 Mon Sep 17 00:00:00 2001 From: Forest Bond Date: Mon, 21 Oct 2013 12:38:02 -0400 Subject: HID: don't ignore eGalax/D-Wav/EETI HIDs commit 95d50b6c5e18ff7351c5f2a6ff53afaed5f7e664 upstream. Certain devices with class HID, protocol None did not work with the HID driver at one point, and as a result were bound to usbtouchscreen instead as of commit 139ebe8 ("Input: usbtouchscreen - fix eGalax HID ignoring"). This change was prompted by the following report: https://lkml.org/lkml/2009/1/25/127 Unfortunately, the device mentioned in this report is no longer available for testing. We've recently discovered that some devices with class HID, protocol None do not work with usbtouchscreen, but do work with usbhid. Here is the report that made this evident: http://comments.gmane.org/gmane.linux.kernel.input/31710 Driver binding for these devices has flip-flopped a few times, so both of the above reports were regressions. This situation would appear to leave us with no easy way to bind every device to the right driver. However, in my own testing with several devices I have not found a device with class HID that does not work with the current HID driver. It is my belief that changes to the HID driver since the original report have likely fixed the issue(s) that made it unsuitable at the time, and that we should prefer it over usbtouchscreen for these devices. In particular, HID quirks affecting these devices were added/removed in the following commits since then: fe6065d HID: add multi-input quirk for eGalax Touchcontroller 77933c3 Merge branch 'egalax' into for-linus ebd11fe HID: Add quirk for eGalax touch controler. d34c4aa HID: add no-get quirk for eGalax touch controller This patch makes the HID driver no longer ignore eGalax/D-Wav/EETI devices with class HID. If there are in fact devices with class HID that still do not work with the HID driver, we will see another round of regressions. In that case I propose we investigate why the device is not working with the HID driver rather than re-introduce regressions for functioning HID devices by again binding them to usbtouchscreen. The corresponding change to usbtouchscreen will be made separately. Signed-off-by: Forest Bond Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/hid/hid-core.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index e04bf0ef93a9..ab9280660f02 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -2317,15 +2317,6 @@ bool hid_ignore(struct hid_device *hdev) hdev->type == HID_TYPE_USBNONE) return true; break; - case USB_VENDOR_ID_DWAV: - /* These are handled by usbtouchscreen. hdev->type is probably - * HID_TYPE_USBNONE, but we say !HID_TYPE_USBMOUSE to match - * usbtouchscreen. */ - if ((hdev->product == USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER || - hdev->product == USB_DEVICE_ID_DWAV_TOUCHCONTROLLER) && - hdev->type != HID_TYPE_USBMOUSE) - return true; - break; case USB_VENDOR_ID_VELLEMAN: /* These are not HID devices. They are handled by comedi. */ if ((hdev->product >= USB_DEVICE_ID_VELLEMAN_K8055_FIRST && -- cgit v1.2.3 From c2dd82b43dcc08aad0e139e23509efb195ad6fc1 Mon Sep 17 00:00:00 2001 From: Forest Bond Date: Mon, 21 Oct 2013 12:38:18 -0400 Subject: Input: usbtouchscreen: ignore eGalax/D-Wav/EETI HIDs commit ae2aa3a512fa5f50f67feba9e66bc2efb394bd63 upstream. The HID driver now handles these devices, regardless of what protocol the device claims it supports. Signed-off-by: Forest Bond Acked-by: Dmitry Torokhov Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/input/touchscreen/usbtouchscreen.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c index 721fdb3597ca..ae4b6b903629 100644 --- a/drivers/input/touchscreen/usbtouchscreen.c +++ b/drivers/input/touchscreen/usbtouchscreen.c @@ -146,12 +146,10 @@ enum { #define USB_DEVICE_HID_CLASS(vend, prod) \ .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS \ - | USB_DEVICE_ID_MATCH_INT_PROTOCOL \ | USB_DEVICE_ID_MATCH_DEVICE, \ .idVendor = (vend), \ .idProduct = (prod), \ - .bInterfaceClass = USB_INTERFACE_CLASS_HID, \ - .bInterfaceProtocol = USB_INTERFACE_PROTOCOL_MOUSE + .bInterfaceClass = USB_INTERFACE_CLASS_HID static const struct usb_device_id usbtouch_devices[] = { #ifdef CONFIG_TOUCHSCREEN_USB_EGALAX -- cgit v1.2.3 From 16802f7ac3a42b6e97af4e9b203adfa7bbb25994 Mon Sep 17 00:00:00 2001 From: Mark Langsdorf Date: Tue, 1 Oct 2013 10:30:24 -0500 Subject: cpufreq: highbank-cpufreq: Enable Midway/ECX-2000 commit fbbc5bfb44a22e7a8ef753a1c8dfb448d7ac8b85 upstream. Calxeda's new ECX-2000 part uses the same cpufreq interface as highbank, so add it to the driver's compatibility list. This is a minor change that can safely be applied to the 3.10 and 3.11 stable trees. Signed-off-by: Mark Langsdorf Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- drivers/cpufreq/highbank-cpufreq.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/cpufreq/highbank-cpufreq.c b/drivers/cpufreq/highbank-cpufreq.c index b61b5a3fad64..8c4771da1b89 100644 --- a/drivers/cpufreq/highbank-cpufreq.c +++ b/drivers/cpufreq/highbank-cpufreq.c @@ -66,7 +66,8 @@ static int hb_cpufreq_driver_init(void) struct device_node *np; int ret; - if (!of_machine_is_compatible("calxeda,highbank")) + if ((!of_machine_is_compatible("calxeda,highbank")) && + (!of_machine_is_compatible("calxeda,ecx-2000"))) return -ENODEV; for_each_child_of_node(of_find_node_by_path("/cpus"), np) -- cgit v1.2.3 From 0e6a2932d63564f8f5eb81c9fbe22ba1ba8d19df Mon Sep 17 00:00:00 2001 From: Simon Guinot Date: Thu, 3 Oct 2013 12:05:02 +0200 Subject: clk: armada-370: fix tclk frequencies commit 1022c75f5abd3a3b25e679bc8793d21bedd009b4 upstream. This patch fixes the tclk frequency array for the Armada-370 SoC. This bug has been introduced by commit 6b72333d ("clk: mvebu: add Armada 370 SoC-centric clock init"). A wrong tclk frequency affects the following drivers: mvsdio, mvneta, i2c-mv64xxx and mvebu-devbus. This list may be incomplete. About the mvneta Ethernet driver, note that the tclk frequency is used to compute the Rx time coalescence. Then, this bug harms the coalescence configuration and also degrades the networking performances with the default values. Signed-off-by: Simon Guinot Cc: Andrew Lunn Cc: Gregory CLEMENT Cc: Sebastian Hesselbarth Acked-by: Jason Cooper Signed-off-by: Michael Turquette Signed-off-by: Greg Kroah-Hartman --- drivers/clk/mvebu/clk-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/mvebu/clk-core.c b/drivers/clk/mvebu/clk-core.c index 0a53edbae8b8..e5c477b49934 100644 --- a/drivers/clk/mvebu/clk-core.c +++ b/drivers/clk/mvebu/clk-core.c @@ -126,8 +126,8 @@ static void __init mvebu_clk_core_setup(struct device_node *np, #define SARH_AXP_FAB_FREQ_OPT_SHIFT 4 static const u32 __initconst armada_370_tclk_frequencies[] = { - 16600000, - 20000000, + 166000000, + 200000000, }; static u32 __init armada_370_get_tclk_freq(void __iomem *sar) -- cgit v1.2.3 From 7e7ea1bd73f1307df3d375f2df4fa0d6783510de Mon Sep 17 00:00:00 2001 From: Michael Marineau Date: Sun, 11 Aug 2013 00:53:45 -0400 Subject: 9p: send uevent after adding/removing mount_tag attribute commit e0d6cb9cd3a3ac8a3b8e5b22b83c4f8619786f22 upstream. This driver adds an attribute to the existing virtio device so a CHANGE event is required in order udev rules to make use of it. The ADD event happens before this driver is probed and unlike a more typical driver like a block device there isn't a higher level device to watch for. Signed-off-by: Michael Marineau Signed-off-by: Eric Van Hensbergen Signed-off-by: Greg Kroah-Hartman --- net/9p/trans_virtio.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index e1c26b101830..990afab2be1b 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c @@ -577,6 +577,10 @@ static int p9_virtio_probe(struct virtio_device *vdev) mutex_lock(&virtio_9p_lock); list_add_tail(&chan->chan_list, &virtio_chan_list); mutex_unlock(&virtio_9p_lock); + + /* Let udev rules use the new mount_tag attribute. */ + kobject_uevent(&(vdev->dev.kobj), KOBJ_CHANGE); + return 0; out_free_tag: @@ -654,6 +658,7 @@ static void p9_virtio_remove(struct virtio_device *vdev) list_del(&chan->chan_list); mutex_unlock(&virtio_9p_lock); sysfs_remove_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr); + kobject_uevent(&(vdev->dev.kobj), KOBJ_CHANGE); kfree(chan->tag); kfree(chan->vc_wq); kfree(chan); -- cgit v1.2.3 From be8c7f057c6c9257956eb796b58500c5c4f939c3 Mon Sep 17 00:00:00 2001 From: Luosong Date: Wed, 2 Oct 2013 11:20:00 +0200 Subject: HID: multitouch: Fix GeneralTouch products and add more PIDs commit 7b2262920db2b98fe2cd32cde52141f02fd9eecf upstream. GeneralTouch products should use the quirk SLOT_IS_CONTACTID instead of SLOT_IS_CONTACTNUMBER. Adding PIDs 0101,e100,0102,0106,010a from the new products. Tested on new and older products by GeneralTouch engineers. Signed-off-by: Luosong Signed-off-by: Benjamin Tissoires Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/hid/hid-ids.h | 5 +++++ drivers/hid/hid-multitouch.c | 19 +++++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 114fd1661834..96e055ea3cf1 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -330,6 +330,11 @@ #define USB_VENDOR_ID_GENERAL_TOUCH 0x0dfc #define USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS 0x0003 #define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PWT_TENFINGERS 0x0100 +#define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_0101 0x0101 +#define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_0102 0x0102 +#define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_0106 0x0106 +#define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_010A 0x010a +#define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_E100 0xe100 #define USB_VENDOR_ID_GLAB 0x06c2 #define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038 diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index b6701cec80ff..0c55f26f0f61 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -244,12 +244,12 @@ static struct mt_class mt_classes[] = { { .name = MT_CLS_GENERALTOUCH_TWOFINGERS, .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP | MT_QUIRK_VALID_IS_INRANGE | - MT_QUIRK_SLOT_IS_CONTACTNUMBER, + MT_QUIRK_SLOT_IS_CONTACTID, .maxcontacts = 2 }, { .name = MT_CLS_GENERALTOUCH_PWT_TENFINGERS, .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP | - MT_QUIRK_SLOT_IS_CONTACTNUMBER + MT_QUIRK_SLOT_IS_CONTACTID }, { .name = MT_CLS_FLATFROG, @@ -1191,6 +1191,21 @@ static const struct hid_device_id mt_devices[] = { { .driver_data = MT_CLS_GENERALTOUCH_PWT_TENFINGERS, MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PWT_TENFINGERS) }, + { .driver_data = MT_CLS_GENERALTOUCH_TWOFINGERS, + MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, + USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_0101) }, + { .driver_data = MT_CLS_GENERALTOUCH_PWT_TENFINGERS, + MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, + USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_0102) }, + { .driver_data = MT_CLS_GENERALTOUCH_PWT_TENFINGERS, + MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, + USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_0106) }, + { .driver_data = MT_CLS_GENERALTOUCH_PWT_TENFINGERS, + MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, + USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_010A) }, + { .driver_data = MT_CLS_GENERALTOUCH_PWT_TENFINGERS, + MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, + USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_E100) }, /* Gametel game controller */ { .driver_data = MT_CLS_NSMU, -- cgit v1.2.3 From 82a645a3ecd757206d4d6be182d7e47d50a7dd4c Mon Sep 17 00:00:00 2001 From: Elias Vanderstuyft Date: Mon, 7 Oct 2013 19:48:12 +0300 Subject: HID: logitech - lg2ff: Add IDs for Formula Vibration Feedback Wheel commit bd04363d3990c0727b7512a79a08c68436878bb0 upstream. Add USB IDs for Logitech Formula Vibration Feedback Wheel (046d:ca04). The lg2ff force feedback subdriver is used for vibration and HID_GD_MULTIAXIS is set to avoid deadzone like other Logitech wheels. Kconfig description etc are also updated accordingly. Signed-off-by: Elias Vanderstuyft [anssi.hannula@iki.fi: added description and CCs] Signed-off-by: Anssi Hannula Signed-off-by: Simon Wood Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/hid/Kconfig | 8 +++++--- drivers/hid/hid-core.c | 1 + drivers/hid/hid-ids.h | 1 + drivers/hid/hid-lg.c | 3 +++ drivers/hid/hid-lg2ff.c | 2 +- 5 files changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index fb52f3f6de80..304c02b9e0c8 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -352,12 +352,14 @@ config LOGITECH_FF force feedback. config LOGIRUMBLEPAD2_FF - bool "Logitech RumblePad/Rumblepad 2 force feedback support" + bool "Logitech force feedback support (variant 2)" depends on HID_LOGITECH select INPUT_FF_MEMLESS help - Say Y here if you want to enable force feedback support for Logitech - RumblePad and Rumblepad 2 devices. + Say Y here if you want to enable force feedback support for: + - Logitech RumblePad + - Logitech Rumblepad 2 + - Logitech Formula Vibration Feedback Wheel config LOGIG940_FF bool "Logitech Flight System G940 force feedback support" diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index ab9280660f02..86fd33ff9a8d 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1703,6 +1703,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FLIGHT_SYSTEM_G940) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_VIBRATION_WHEEL) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFP_WHEEL) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFGT_WHEEL) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 96e055ea3cf1..ae821939730b 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -562,6 +562,7 @@ #define USB_DEVICE_ID_DINOVO_EDGE 0xc714 #define USB_DEVICE_ID_DINOVO_MINI 0xc71f #define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2 0xca03 +#define USB_DEVICE_ID_LOGITECH_VIBRATION_WHEEL 0xca04 #define USB_VENDOR_ID_LUMIO 0x202e #define USB_DEVICE_ID_CRYSTALTOUCH 0x0006 diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c index 6f12ecd36c88..c2c7dab7d2c4 100644 --- a/drivers/hid/hid-lg.c +++ b/drivers/hid/hid-lg.c @@ -492,6 +492,7 @@ static int lg_input_mapped(struct hid_device *hdev, struct hid_input *hi, case USB_DEVICE_ID_LOGITECH_G27_WHEEL: case USB_DEVICE_ID_LOGITECH_WII_WHEEL: case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2: + case USB_DEVICE_ID_LOGITECH_VIBRATION_WHEEL: field->application = HID_GD_MULTIAXIS; break; default: @@ -639,6 +640,8 @@ static const struct hid_device_id lg_devices[] = { .driver_data = LG_NOGET | LG_FF4 }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2), .driver_data = LG_FF4 }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_VIBRATION_WHEEL), + .driver_data = LG_FF2 }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL), .driver_data = LG_FF4 }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFGT_WHEEL), diff --git a/drivers/hid/hid-lg2ff.c b/drivers/hid/hid-lg2ff.c index 1a42eaa6ca02..0e3fb1a7e421 100644 --- a/drivers/hid/hid-lg2ff.c +++ b/drivers/hid/hid-lg2ff.c @@ -95,7 +95,7 @@ int lg2ff_init(struct hid_device *hid) hid_hw_request(hid, report, HID_REQ_SET_REPORT); - hid_info(hid, "Force feedback for Logitech RumblePad/Rumblepad 2 by Anssi Hannula \n"); + hid_info(hid, "Force feedback for Logitech variant 2 rumble devices by Anssi Hannula \n"); return 0; } -- cgit v1.2.3 From a7a6904f5f39e7aeb3740415900020346e0a9f01 Mon Sep 17 00:00:00 2001 From: Forest Bond Date: Mon, 21 Oct 2013 12:38:49 -0400 Subject: HID: hid-multitouch: add support for SiS panels commit a6802e008e19845fd9669511b895f7515ef9c48b upstream. Add support for SiS multitouch panels. Signed-off-by: Forest Bond Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/hid/Kconfig | 1 + drivers/hid/hid-core.c | 2 ++ drivers/hid/hid-ids.h | 4 ++++ drivers/hid/hid-multitouch.c | 8 ++++++++ drivers/hid/usbhid/hid-quirks.c | 2 ++ 5 files changed, 17 insertions(+) diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 304c02b9e0c8..731240d1c1ef 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -438,6 +438,7 @@ config HID_MULTITOUCH - Pixcir dual touch panels - Quanta panels - eGalax dual-touch panels, including the Joojoo and Wetab tablets + - SiS multitouch panels - Stantum multitouch panels - Touch International Panels - Unitec Panels diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 86fd33ff9a8d..43831f18e4ca 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1766,6 +1766,8 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_PS1000) }, { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SIS2_TOUCH, USB_DEVICE_ID_SIS9200_TOUCH) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SIS2_TOUCH, USB_DEVICE_ID_SIS817_TOUCH) }, { HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE, USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index ae821939730b..76aa9894b463 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -736,6 +736,10 @@ #define USB_VENDOR_ID_SIGMATEL 0x066F #define USB_DEVICE_ID_SIGMATEL_STMP3780 0x3780 +#define USB_VENDOR_ID_SIS2_TOUCH 0x0457 +#define USB_DEVICE_ID_SIS9200_TOUCH 0x9200 +#define USB_DEVICE_ID_SIS817_TOUCH 0x0817 + #define USB_VENDOR_ID_SKYCABLE 0x1223 #define USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER 0x3F07 diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 0c55f26f0f61..f79ad2cb3f4a 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -1317,6 +1317,14 @@ static const struct hid_device_id mt_devices[] = { MT_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008) }, + /* SiS panels */ + { .driver_data = MT_CLS_DEFAULT, + HID_USB_DEVICE(USB_VENDOR_ID_SIS2_TOUCH, + USB_DEVICE_ID_SIS9200_TOUCH) }, + { .driver_data = MT_CLS_DEFAULT, + HID_USB_DEVICE(USB_VENDOR_ID_SIS2_TOUCH, + USB_DEVICE_ID_SIS817_TOUCH) }, + /* Stantum panels */ { .driver_data = MT_CLS_CONFIDENCE, MT_USB_DEVICE(USB_VENDOR_ID_STANTUM, diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 07345521f421..ae5c63478b92 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -84,6 +84,8 @@ static const struct hid_blacklist { { USB_VENDOR_ID_REALTEK, USB_DEVICE_ID_REALTEK_READER, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SIGMATEL, USB_DEVICE_ID_SIGMATEL_STMP3780, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_SIS2_TOUCH, USB_DEVICE_ID_SIS9200_TOUCH, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_SIS2_TOUCH, USB_DEVICE_ID_SIS817_TOUCH, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_1, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_2, HID_QUIRK_NOGET }, -- cgit v1.2.3 From 505014c1880ece595f7ac118c10efc432213bf58 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Sat, 26 Oct 2013 10:04:09 -0700 Subject: HID: hid-sensor-hub: fix report size commit d4b1bba76171cb783e32441b28462fe841073ed8 upstream. Most of the hid sensor field size is reported in report_size field in the report descriptor. For rotation fusion sensor the quaternion data is 16 byte field, the report size was set to 4 and report count field is set to 4. So the total size is 16 bytes. But the current driver has a bug and not taking account for report count field. This causes user space to see only 4 bytes of data sent via IIO interface. The number of bytes in a field needs to take account of report_count field. Need to multiply report_size and report_count to get total number of bytes. Signed-off-by: Srinivas Pandruvada Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/hid/hid-sensor-hub.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c index aa34755ca205..b189feb69789 100644 --- a/drivers/hid/hid-sensor-hub.c +++ b/drivers/hid/hid-sensor-hub.c @@ -327,7 +327,8 @@ int sensor_hub_input_get_attribute_info(struct hid_sensor_hub_device *hsdev, field->logical == attr_usage_id) { sensor_hub_fill_attr_info(info, i, report->id, field->unit, field->unit_exponent, - field->report_size); + field->report_size * + field->report_count); ret = 0; } else { for (j = 0; j < field->maxusage; ++j) { @@ -339,7 +340,8 @@ int sensor_hub_input_get_attribute_info(struct hid_sensor_hub_device *hsdev, i, report->id, field->unit, field->unit_exponent, - field->report_size); + field->report_size * + field->report_count); ret = 0; break; } @@ -426,9 +428,10 @@ static int sensor_hub_raw_event(struct hid_device *hdev, hid_dbg(hdev, "%d collection_index:%x hid:%x sz:%x\n", i, report->field[i]->usage->collection_index, report->field[i]->usage->hid, - report->field[i]->report_size/8); - - sz = report->field[i]->report_size/8; + (report->field[i]->report_size * + report->field[i]->report_count)/8); + sz = (report->field[i]->report_size * + report->field[i]->report_count)/8; if (pdata->pending.status && pdata->pending.attr_usage_id == report->field[i]->usage->hid) { hid_dbg(hdev, "data was pending ...\n"); -- cgit v1.2.3 From 7d366a5ec599406ca43fd4b967d0a81307c3bce4 Mon Sep 17 00:00:00 2001 From: KaiChung Cheng Date: Thu, 21 Nov 2013 10:04:30 +0100 Subject: HID: multicouh: add PID VID to support 1 new Wistron optical touch device commit bf9d121efc18c30caa2caad85358cf9408eca117 upstream. This patch adds PID VID to support for the Wistron Inc. Optical touch panel. Signed-off-by: KaiChung Cheng Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/hid/Kconfig | 1 + drivers/hid/hid-ids.h | 3 +++ drivers/hid/hid-multitouch.c | 6 ++++++ 3 files changed, 10 insertions(+) diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 731240d1c1ef..bee88ee8066e 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -442,6 +442,7 @@ config HID_MULTITOUCH - Stantum multitouch panels - Touch International Panels - Unitec Panels + - Wistron optical touch panels - XAT optical touch panels - Xiroku optical touch panels - Zytronic touch panels diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 76aa9894b463..799dbec2646b 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -879,6 +879,9 @@ #define USB_DEVICE_ID_SUPER_DUAL_BOX_PRO 0x8802 #define USB_DEVICE_ID_SUPER_JOY_BOX_5_PRO 0x8804 +#define USB_VENDOR_ID_WISTRON 0x0fb8 +#define USB_DEVICE_ID_WISTRON_OPTICAL_TOUCH 0x1109 + #define USB_VENDOR_ID_X_TENSIONS 0x1ae7 #define USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE 0x9001 diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index f79ad2cb3f4a..3d8e58ac7499 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -1353,6 +1353,12 @@ static const struct hid_device_id mt_devices[] = { { .driver_data = MT_CLS_NSMU, MT_USB_DEVICE(USB_VENDOR_ID_UNITEC, USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19) }, + + /* Wistron panels */ + { .driver_data = MT_CLS_NSMU, + MT_USB_DEVICE(USB_VENDOR_ID_WISTRON, + USB_DEVICE_ID_WISTRON_OPTICAL_TOUCH) }, + /* XAT */ { .driver_data = MT_CLS_NSMU, MT_USB_DEVICE(USB_VENDOR_ID_XAT, -- cgit v1.2.3 From 236b365b1a65da3f18d1eda848418421c1601396 Mon Sep 17 00:00:00 2001 From: Simon Wood Date: Wed, 6 Nov 2013 12:30:40 -0700 Subject: HID:hid-lg4ff: Scale autocentering force properly on Logitech wheel commit f8c231569a7a455dfa1907294a46ba52b3aa8859 upstream. Adjust the scaling and lineartity to match that of the Windows driver (from MOMO testing). Reported-by: Elias Vanderstuyft Signed-off-by: Simon Wood Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/hid/hid-lg4ff.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c index 8782fe1aaa07..530fcd19e90e 100644 --- a/drivers/hid/hid-lg4ff.c +++ b/drivers/hid/hid-lg4ff.c @@ -218,12 +218,21 @@ static void hid_lg4ff_set_autocenter_default(struct input_dev *dev, u16 magnitud struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; struct hid_report *report = list_entry(report_list->next, struct hid_report, list); __s32 *value = report->field[0]->value; + __u32 expand_a, expand_b; + + if (magnitude <= 0xaaaa) { + expand_a = 0x0c * magnitude; + expand_b = 0x80 * magnitude; + } else { + expand_a = (0x0c * 0xaaaa) + 0x06 * (magnitude - 0xaaaa); + expand_b = (0x80 * 0xaaaa) + 0xff * (magnitude - 0xaaaa); + } value[0] = 0xfe; value[1] = 0x0d; - value[2] = magnitude >> 13; - value[3] = magnitude >> 13; - value[4] = magnitude >> 8; + value[2] = expand_a / 0xaaaa; + value[3] = expand_a / 0xaaaa; + value[4] = expand_b / 0xaaaa; value[5] = 0x00; value[6] = 0x00; -- cgit v1.2.3 From b806304bde504aff3b74f9a75e579b7170b5d65a Mon Sep 17 00:00:00 2001 From: Simon Wood Date: Wed, 6 Nov 2013 12:30:41 -0700 Subject: HID:hid-lg4ff: Switch autocentering off when strength is set to zero. commit d2c02da549b468bbb28e67d269bd3c9e10683ff5 upstream. When the autocenter is set to zero, this patch issues a command to totally disable the autocenter - this results in less resistance in the wheel. Reported-by: Elias Vanderstuyft Signed-off-by: Simon Wood Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/hid/hid-lg4ff.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c index 530fcd19e90e..49f6cc0f9919 100644 --- a/drivers/hid/hid-lg4ff.c +++ b/drivers/hid/hid-lg4ff.c @@ -220,6 +220,20 @@ static void hid_lg4ff_set_autocenter_default(struct input_dev *dev, u16 magnitud __s32 *value = report->field[0]->value; __u32 expand_a, expand_b; + /* De-activate Auto-Center */ + if (magnitude == 0) { + value[0] = 0xf5; + value[1] = 0x00; + value[2] = 0x00; + value[3] = 0x00; + value[4] = 0x00; + value[5] = 0x00; + value[6] = 0x00; + + hid_hw_request(hid, report, HID_REQ_SET_REPORT); + return; + } + if (magnitude <= 0xaaaa) { expand_a = 0x0c * magnitude; expand_b = 0x80 * magnitude; @@ -237,6 +251,17 @@ static void hid_lg4ff_set_autocenter_default(struct input_dev *dev, u16 magnitud value[6] = 0x00; hid_hw_request(hid, report, HID_REQ_SET_REPORT); + + /* Activate Auto-Center */ + value[0] = 0x14; + value[1] = 0x00; + value[2] = 0x00; + value[3] = 0x00; + value[4] = 0x00; + value[5] = 0x00; + value[6] = 0x00; + + hid_hw_request(hid, report, HID_REQ_SET_REPORT); } /* Sends autocentering command compatible with Formula Force EX */ -- cgit v1.2.3 From 43f0ba99fcd871a936df8c25b438759708884df8 Mon Sep 17 00:00:00 2001 From: Simon Wood Date: Wed, 6 Nov 2013 12:30:43 -0700 Subject: HID:hid-lg4ff: Initialize device properties before we touch autocentering. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 114a55cf9dd1576e7ac56189832cd4d7dc56c218 upstream. Re-arrange code slightly to ensure that device properties are configured before calling auto-center command. Reported-by: Michal Malý Signed-off-by: Simon Wood Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/hid/hid-lg4ff.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c index 49f6cc0f9919..351805362290 100644 --- a/drivers/hid/hid-lg4ff.c +++ b/drivers/hid/hid-lg4ff.c @@ -574,17 +574,6 @@ int lg4ff_init(struct hid_device *hid) if (error) return error; - /* Check if autocentering is available and - * set the centering force to zero by default */ - if (test_bit(FF_AUTOCENTER, dev->ffbit)) { - if (rev_maj == FFEX_REV_MAJ && rev_min == FFEX_REV_MIN) /* Formula Force EX expects different autocentering command */ - dev->ff->set_autocenter = hid_lg4ff_set_autocenter_ffex; - else - dev->ff->set_autocenter = hid_lg4ff_set_autocenter_default; - - dev->ff->set_autocenter(dev, 0); - } - /* Get private driver data */ drv_data = hid_get_drvdata(hid); if (!drv_data) { @@ -605,6 +594,17 @@ int lg4ff_init(struct hid_device *hid) entry->max_range = lg4ff_devices[i].max_range; entry->set_range = lg4ff_devices[i].set_range; + /* Check if autocentering is available and + * set the centering force to zero by default */ + if (test_bit(FF_AUTOCENTER, dev->ffbit)) { + if (rev_maj == FFEX_REV_MAJ && rev_min == FFEX_REV_MIN) /* Formula Force EX expects different autocentering command */ + dev->ff->set_autocenter = hid_lg4ff_set_autocenter_ffex; + else + dev->ff->set_autocenter = hid_lg4ff_set_autocenter_default; + + dev->ff->set_autocenter(dev, 0); + } + /* Create sysfs interface */ error = device_create_file(&hid->dev, &dev_attr_range); if (error) -- cgit v1.2.3 From d53217196e679ed97e85f86f75800def863beb08 Mon Sep 17 00:00:00 2001 From: Simon Wood Date: Thu, 10 Oct 2013 08:20:12 -0600 Subject: HID: lg: fix ReportDescriptor for Logitech Formula Vibration commit 7f50547059bd55ac6a98c29fd1989421bdc36ec9 upstream. By default the Logitech Formula Vibration presents a combined accel/brake axis ('Y'). This patch modifies the HID descriptor to present seperate accel/brake axes ('Y' and 'Z'). Signed-off-by: Simon Wood Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/hid/hid-lg.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c index c2c7dab7d2c4..1bfd292cac8f 100644 --- a/drivers/hid/hid-lg.c +++ b/drivers/hid/hid-lg.c @@ -45,6 +45,7 @@ /* Size of the original descriptors of the Driving Force (and Pro) wheels */ #define DF_RDESC_ORIG_SIZE 130 #define DFP_RDESC_ORIG_SIZE 97 +#define FV_RDESC_ORIG_SIZE 130 #define MOMO_RDESC_ORIG_SIZE 87 /* Fixed report descriptors for Logitech Driving Force (and Pro) @@ -170,6 +171,73 @@ static __u8 dfp_rdesc_fixed[] = { 0xC0 /* End Collection */ }; +static __u8 fv_rdesc_fixed[] = { +0x05, 0x01, /* Usage Page (Desktop), */ +0x09, 0x04, /* Usage (Joystik), */ +0xA1, 0x01, /* Collection (Application), */ +0xA1, 0x02, /* Collection (Logical), */ +0x95, 0x01, /* Report Count (1), */ +0x75, 0x0A, /* Report Size (10), */ +0x15, 0x00, /* Logical Minimum (0), */ +0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ +0x35, 0x00, /* Physical Minimum (0), */ +0x46, 0xFF, 0x03, /* Physical Maximum (1023), */ +0x09, 0x30, /* Usage (X), */ +0x81, 0x02, /* Input (Variable), */ +0x95, 0x0C, /* Report Count (12), */ +0x75, 0x01, /* Report Size (1), */ +0x25, 0x01, /* Logical Maximum (1), */ +0x45, 0x01, /* Physical Maximum (1), */ +0x05, 0x09, /* Usage Page (Button), */ +0x19, 0x01, /* Usage Minimum (01h), */ +0x29, 0x0C, /* Usage Maximum (0Ch), */ +0x81, 0x02, /* Input (Variable), */ +0x95, 0x02, /* Report Count (2), */ +0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ +0x09, 0x01, /* Usage (01h), */ +0x81, 0x02, /* Input (Variable), */ +0x09, 0x02, /* Usage (02h), */ +0x26, 0xFF, 0x00, /* Logical Maximum (255), */ +0x46, 0xFF, 0x00, /* Physical Maximum (255), */ +0x95, 0x01, /* Report Count (1), */ +0x75, 0x08, /* Report Size (8), */ +0x81, 0x02, /* Input (Variable), */ +0x05, 0x01, /* Usage Page (Desktop), */ +0x25, 0x07, /* Logical Maximum (7), */ +0x46, 0x3B, 0x01, /* Physical Maximum (315), */ +0x75, 0x04, /* Report Size (4), */ +0x65, 0x14, /* Unit (Degrees), */ +0x09, 0x39, /* Usage (Hat Switch), */ +0x81, 0x42, /* Input (Variable, Null State), */ +0x75, 0x01, /* Report Size (1), */ +0x95, 0x04, /* Report Count (4), */ +0x65, 0x00, /* Unit, */ +0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ +0x09, 0x01, /* Usage (01h), */ +0x25, 0x01, /* Logical Maximum (1), */ +0x45, 0x01, /* Physical Maximum (1), */ +0x81, 0x02, /* Input (Variable), */ +0x05, 0x01, /* Usage Page (Desktop), */ +0x95, 0x01, /* Report Count (1), */ +0x75, 0x08, /* Report Size (8), */ +0x26, 0xFF, 0x00, /* Logical Maximum (255), */ +0x46, 0xFF, 0x00, /* Physical Maximum (255), */ +0x09, 0x31, /* Usage (Y), */ +0x81, 0x02, /* Input (Variable), */ +0x09, 0x32, /* Usage (Z), */ +0x81, 0x02, /* Input (Variable), */ +0xC0, /* End Collection, */ +0xA1, 0x02, /* Collection (Logical), */ +0x26, 0xFF, 0x00, /* Logical Maximum (255), */ +0x46, 0xFF, 0x00, /* Physical Maximum (255), */ +0x95, 0x07, /* Report Count (7), */ +0x75, 0x08, /* Report Size (8), */ +0x09, 0x03, /* Usage (03h), */ +0x91, 0x02, /* Output (Variable), */ +0xC0, /* End Collection, */ +0xC0 /* End Collection */ +}; + static __u8 momo_rdesc_fixed[] = { 0x05, 0x01, /* Usage Page (Desktop), */ 0x09, 0x04, /* Usage (Joystik), */ @@ -275,6 +343,15 @@ static __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc, } break; + case USB_DEVICE_ID_LOGITECH_VIBRATION_WHEEL: + if (*rsize == FV_RDESC_ORIG_SIZE) { + hid_info(hdev, + "fixing up Logitech Formula Vibration report descriptor\n"); + rdesc = fv_rdesc_fixed; + *rsize = sizeof(fv_rdesc_fixed); + } + break; + case USB_DEVICE_ID_LOGITECH_DFP_WHEEL: if (*rsize == DFP_RDESC_ORIG_SIZE) { hid_info(hdev, -- cgit v1.2.3 From 52915b499962c637289f1ac04cc0858e690bbfe4 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 27 Nov 2013 08:47:02 +0100 Subject: gpio: pl061: move irqdomain initialization commit 2ba3154d9cb13697b97723cce75633b48adfe826 upstream. The PL061 driver had the irqdomain initialization in an unfortunate place: when used with device tree (and thus passing the base IRQ 0) the driver would work, as this registers an irqdomain and waits for mappings to be done dynamically as the devices request their IRQs, whereas when booting using platform data the irqdomain core would attempt to allocate IRQ descriptors dynamically (which works fine) but also to associate the irq_domain_associate_many() on all IRQs, which in turn will call the mapping function which at this point will try to set the type of the IRQ and then tries to acquire a non-initialized spinlock yielding a backtrace like this: CPU: 0 PID: 1 Comm: swapper Not tainted 3.13.0-rc1+ #652 Backtrace: [] (dump_backtrace) from [] (show_stack+0x18/0x1c) r6:c798ace0 r5:00000000 r4:c78257e0 r3:00200140 [] (show_stack) from [] (dump_stack+0x20/0x28) [] (dump_stack) from [] (__lock_acquire+0x1c0/0x1b80) [] (__lock_acquire) from [] (lock_acquire+0x6c/0x80) r10:00000000 r9:c0455234 r8:00000060 r7:c047d798 r6:600000d3 r5:00000000 r4:c782c000 [] (lock_acquire) from [] (_raw_spin_lock_irqsave+0x60/0x74) r6:c01a1100 r5:800000d3 r4:c798acd0 [] (_raw_spin_lock_irqsave) from [] (pl061_irq_type+0x28/0x) r6:00000000 r5:00000000 r4:c798acd0 [] (pl061_irq_type) from [] (__irq_set_trigger+0x70/0x104) r6:00000000 r5:c01a10d8 r4:c046da1c r3:c01a10d8 [] (__irq_set_trigger) from [] (irq_set_irq_type+0x40/0x60) r10:c043240c r8:00000060 r7:00000000 r6:c046da1c r5:00000060 r4:00000000 [] (irq_set_irq_type) from [] (pl061_irq_map+0x40/0x54) r6:c79693c0 r5:c798acd0 r4:00000060 [] (pl061_irq_map) from [] (irq_domain_associate+0xc0/0x190) r5:00000060 r4:c046da1c [] (irq_domain_associate) from [] (irq_domain_associate_man) r8:00000008 r7:00000000 r6:c79693c0 r5:00000060 r4:00000000 [] (irq_domain_associate_many) from [] (irq_domain_add_simp) r8:c046578c r7:c035b72c r6:c79693c0 r5:00000060 r4:00000008 r3:00000008 [] (irq_domain_add_simple) from [] (pl061_probe+0xc4/0x22c) r6:00000060 r5:c0464380 r4:c798acd0 [] (pl061_probe) from [] (amba_probe+0x74/0xe0) r10:c043240c r9:c0455234 r8:00000000 r7:c047d7f8 r6:c047d744 r5:00000000 r4:c0464380 This moves the irqdomain initialization to a point where the spinlock and GPIO chip are both fully propulated, so the callbacks can be used without crashes. I had some problem reproducing the crash, as the devm_kzalloc():ed zeroed memory would seemingly mask the spinlock as something OK, but by poisoning the lock like this: u32 *dum; dum = (u32 *) &chip->lock; *dum = 0xaaaaaaaaU; I could reproduce, fix and test the patch. Reported-by: Russell King Cc: Rob Herring Cc: Haojian Zhuang Cc: Baruch Siach Signed-off-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman --- drivers/gpio/gpio-pl061.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c index 6a4bd0dae0ce..4fbe12d283d5 100644 --- a/drivers/gpio/gpio-pl061.c +++ b/drivers/gpio/gpio-pl061.c @@ -286,11 +286,6 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id) if (!chip->base) return -ENOMEM; - chip->domain = irq_domain_add_simple(adev->dev.of_node, PL061_GPIO_NR, - irq_base, &pl061_domain_ops, chip); - if (!chip->domain) - return -ENODEV; - spin_lock_init(&chip->lock); chip->gc.request = pl061_gpio_request; @@ -320,6 +315,11 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id) irq_set_chained_handler(irq, pl061_irq_handler); irq_set_handler_data(irq, chip); + chip->domain = irq_domain_add_simple(adev->dev.of_node, PL061_GPIO_NR, + irq_base, &pl061_domain_ops, chip); + if (!chip->domain) + return -ENODEV; + for (i = 0; i < PL061_GPIO_NR; i++) { if (pdata) { if (pdata->directions & (1 << i)) -- cgit v1.2.3 From a6647e9e4bdd231a008a12302d008a6cd81596bf Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 22 Nov 2013 17:14:39 -0500 Subject: cgroup: use a dedicated workqueue for cgroup destruction commit e5fca243abae1445afbfceebda5f08462ef869d3 upstream. Since be44562613851 ("cgroup: remove synchronize_rcu() from cgroup_diput()"), cgroup destruction path makes use of workqueue. css freeing is performed from a work item from that point on and a later commit, ea15f8ccdb430 ("cgroup: split cgroup destruction into two steps"), moves css offlining to workqueue too. As cgroup destruction isn't depended upon for memory reclaim, the destruction work items were put on the system_wq; unfortunately, some controller may block in the destruction path for considerable duration while holding cgroup_mutex. As large part of destruction path is synchronized through cgroup_mutex, when combined with high rate of cgroup removals, this has potential to fill up system_wq's max_active of 256. Also, it turns out that memcg's css destruction path ends up queueing and waiting for work items on system_wq through work_on_cpu(). If such operation happens while system_wq is fully occupied by cgroup destruction work items, work_on_cpu() can't make forward progress because system_wq is full and other destruction work items on system_wq can't make forward progress because the work item waiting for work_on_cpu() is holding cgroup_mutex, leading to deadlock. This can be fixed by queueing destruction work items on a separate workqueue. This patch creates a dedicated workqueue - cgroup_destroy_wq - for this purpose. As these work items shouldn't have inter-dependencies and mostly serialized by cgroup_mutex anyway, giving high concurrency level doesn't buy anything and the workqueue's @max_active is set to 1 so that destruction work items are executed one by one on each CPU. Hugh Dickins: Because cgroup_init() is run before init_workqueues(), cgroup_destroy_wq can't be allocated from cgroup_init(). Do it from a separate core_initcall(). In the future, we probably want to reorder so that workqueue init happens before cgroup_init(). Signed-off-by: Tejun Heo Reported-by: Hugh Dickins Reported-by: Shawn Bohrer Link: http://lkml.kernel.org/r/20131111220626.GA7509@sbohrermbp13-local.rgmadvisors.com Link: http://lkml.kernel.org/g/alpine.LNX.2.00.1310301606080.2333@eggly.anvils Cc: stable@vger.kernel.org # v3.9+ Signed-off-by: Greg Kroah-Hartman --- kernel/cgroup.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/kernel/cgroup.c b/kernel/cgroup.c index b6b26faf1740..d0def7fc2848 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -91,6 +91,14 @@ static DEFINE_MUTEX(cgroup_mutex); static DEFINE_MUTEX(cgroup_root_mutex); +/* + * cgroup destruction makes heavy use of work items and there can be a lot + * of concurrent destructions. Use a separate workqueue so that cgroup + * destruction work items don't end up filling up max_active of system_wq + * which may lead to deadlock. + */ +static struct workqueue_struct *cgroup_destroy_wq; + /* * Generate an array of cgroup subsystem pointers. At boot time, this is * populated with the built in subsystems, and modular subsystems are @@ -873,7 +881,7 @@ static void cgroup_free_rcu(struct rcu_head *head) { struct cgroup *cgrp = container_of(head, struct cgroup, rcu_head); - schedule_work(&cgrp->free_work); + queue_work(cgroup_destroy_wq, &cgrp->free_work); } static void cgroup_diput(struct dentry *dentry, struct inode *inode) @@ -4686,6 +4694,22 @@ out: return err; } +static int __init cgroup_wq_init(void) +{ + /* + * There isn't much point in executing destruction path in + * parallel. Good chunk is serialized with cgroup_mutex anyway. + * Use 1 for @max_active. + * + * We would prefer to do this in cgroup_init() above, but that + * is called before init_workqueues(): so leave this until after. + */ + cgroup_destroy_wq = alloc_workqueue("cgroup_destroy", 0, 1); + BUG_ON(!cgroup_destroy_wq); + return 0; +} +core_initcall(cgroup_wq_init); + /* * proc_cgroup_show() * - Print task's cgroup paths into seq_file, one line for each hierarchy @@ -4996,7 +5020,7 @@ void __css_put(struct cgroup_subsys_state *css) v = css_unbias_refcnt(atomic_dec_return(&css->refcnt)); if (v == 0) - schedule_work(&css->dput_work); + queue_work(cgroup_destroy_wq, &css->dput_work); } EXPORT_SYMBOL_GPL(__css_put); -- cgit v1.2.3 From 7c5f3874d9d697f9e21acbdd8be9e65af6f5a880 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 13 Nov 2013 15:25:35 -0500 Subject: drm/radeon/vm: don't attempt to update ptes if ib allocation fails MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 4cc948b94a222c310ae089c36718aac7a03aec90 upstream. If we fail to allocate an indirect buffer (ib) when updating the ptes, return an error instead of trying to use the ib. Avoids a null pointer dereference. Bug: https://bugzilla.kernel.org/show_bug.cgi?id=58621 v2 (chk): rebased on drm-fixes-3.12 for stable inclusion Reviewed-by: Christian König Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_gart.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index 5ce190b8bd1f..2915a1c56934 100644 --- a/drivers/gpu/drm/radeon/radeon_gart.c +++ b/drivers/gpu/drm/radeon/radeon_gart.c @@ -1157,6 +1157,8 @@ int radeon_vm_bo_update_pte(struct radeon_device *rdev, return -ENOMEM; r = radeon_ib_get(rdev, ridx, &ib, NULL, ndw * 4); + if (r) + return r; ib.length_dw = 0; r = radeon_vm_update_pdes(rdev, vm, &ib, bo_va->soffset, bo_va->eoffset); -- cgit v1.2.3 From f98c4b05dc4582055fdb58635d99232e3c6ffc47 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 21 Oct 2013 11:33:35 +0200 Subject: cfg80211: fix scheduled scan pointer access commit 79845c662eeb95c9a180b9bd0d3ad848ee65b94c upstream. Since rdev->sched_scan_req is dereferenced outside the lock protecting it, this might be done at the wrong time, causing crashes. Move the dereference to where it should be - inside the RTNL locked section. Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/wireless/scan.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/wireless/scan.c b/net/wireless/scan.c index fd99ea495b7e..81019ee3ddc8 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -253,10 +253,10 @@ void __cfg80211_sched_scan_results(struct work_struct *wk) rdev = container_of(wk, struct cfg80211_registered_device, sched_scan_results_wk); - request = rdev->sched_scan_req; - mutex_lock(&rdev->sched_scan_mtx); + request = rdev->sched_scan_req; + /* we don't have sched_scan_req anymore if the scan is stopping */ if (request) { if (request->flags & NL80211_SCAN_FLAG_FLUSH) { -- cgit v1.2.3 From b20dcb6c21f4f670569b8f756ed2c5f1ba1e44e4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 2 Nov 2013 08:13:02 -0300 Subject: media: mxl111sf: Don't use dynamic static allocation commit c98300a0e8cf160aaea60bc05d2cd156a7666173 upstream. Dynamic static allocation is evil, as Kernel stack is too low, and compilation complains about it on some archs: drivers/media/usb/dvb-usb-v2/mxl111sf.c:74:1: warning: 'mxl111sf_ctrl_msg' uses dynamic stack allocation [enabled by default] Instead, let's enforce a limit for the buffer to be the max size of a control URB payload data (64 bytes). Signed-off-by: Mauro Carvalho Chehab Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/usb/dvb-usb-v2/mxl111sf.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.c b/drivers/media/usb/dvb-usb-v2/mxl111sf.c index efdcb15358f1..419a7c7ed059 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.c @@ -23,6 +23,9 @@ #include "lgdt3305.h" #include "lg2160.h" +/* Max transfer size done by I2C transfer functions */ +#define MAX_XFER_SIZE 64 + int dvb_usb_mxl111sf_debug; module_param_named(debug, dvb_usb_mxl111sf_debug, int, 0644); MODULE_PARM_DESC(debug, "set debugging level " @@ -63,7 +66,12 @@ int mxl111sf_ctrl_msg(struct dvb_usb_device *d, { int wo = (rbuf == NULL || rlen == 0); /* write-only */ int ret; - u8 sndbuf[1+wlen]; + u8 sndbuf[MAX_XFER_SIZE]; + + if (1 + wlen > sizeof(sndbuf)) { + pr_warn("%s: len=%d is too big!\n", __func__, wlen); + return -EOPNOTSUPP; + } deb_adv("%s(wlen = %d, rlen = %d)\n", __func__, wlen, rlen); -- cgit v1.2.3 From fd30877d2b8ef6a7cd82d780c4f21f13f2263144 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 2 Nov 2013 08:07:12 -0300 Subject: media: af9035: Don't use dynamic static allocation commit 7760e148350bf6df95662bc0db3734e9d991cb03 upstream. Dynamic static allocation is evil, as Kernel stack is too low, and compilation complains about it on some archs: drivers/media/usb/dvb-usb-v2/af9035.c:142:1: warning: 'af9035_wr_regs' uses dynamic stack allocation [enabled by default] drivers/media/usb/dvb-usb-v2/af9035.c:305:1: warning: 'af9035_i2c_master_xfer' uses dynamic stack allocation [enabled by default] Instead, let's enforce a limit for the buffer to be the max size of a control URB payload data (64 bytes). Signed-off-by: Mauro Carvalho Chehab Reviewed-by: Hans Verkuil Reviewed-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/usb/dvb-usb-v2/af9035.c | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c b/drivers/media/usb/dvb-usb-v2/af9035.c index b638fc1cd574..3968bff341e6 100644 --- a/drivers/media/usb/dvb-usb-v2/af9035.c +++ b/drivers/media/usb/dvb-usb-v2/af9035.c @@ -21,6 +21,9 @@ #include "af9035.h" +/* Max transfer size done by I2C transfer functions */ +#define MAX_XFER_SIZE 64 + DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); static u16 af9035_checksum(const u8 *buf, size_t len) @@ -125,10 +128,16 @@ exit: /* write multiple registers */ static int af9035_wr_regs(struct dvb_usb_device *d, u32 reg, u8 *val, int len) { - u8 wbuf[6 + len]; + u8 wbuf[MAX_XFER_SIZE]; u8 mbox = (reg >> 16) & 0xff; struct usb_req req = { CMD_MEM_WR, mbox, sizeof(wbuf), wbuf, 0, NULL }; + if (6 + len > sizeof(wbuf)) { + dev_warn(&d->udev->dev, "%s: i2c wr: len=%d is too big!\n", + KBUILD_MODNAME, len); + return -EOPNOTSUPP; + } + wbuf[0] = len; wbuf[1] = 2; wbuf[2] = 0; @@ -227,9 +236,16 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap, msg[1].len); } else { /* I2C */ - u8 buf[5 + msg[0].len]; + u8 buf[MAX_XFER_SIZE]; struct usb_req req = { CMD_I2C_RD, 0, sizeof(buf), buf, msg[1].len, msg[1].buf }; + + if (5 + msg[0].len > sizeof(buf)) { + dev_warn(&d->udev->dev, + "%s: i2c xfer: len=%d is too big!\n", + KBUILD_MODNAME, msg[0].len); + return -EOPNOTSUPP; + } req.mbox |= ((msg[0].addr & 0x80) >> 3); buf[0] = msg[1].len; buf[1] = msg[0].addr << 1; @@ -256,9 +272,16 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap, msg[0].len - 3); } else { /* I2C */ - u8 buf[5 + msg[0].len]; + u8 buf[MAX_XFER_SIZE]; struct usb_req req = { CMD_I2C_WR, 0, sizeof(buf), buf, 0, NULL }; + + if (5 + msg[0].len > sizeof(buf)) { + dev_warn(&d->udev->dev, + "%s: i2c xfer: len=%d is too big!\n", + KBUILD_MODNAME, msg[0].len); + return -EOPNOTSUPP; + } req.mbox |= ((msg[0].addr & 0x80) >> 3); buf[0] = msg[0].len; buf[1] = msg[0].addr << 1; -- cgit v1.2.3 From 08c049cf8a259c6c1f204451ab2ed661be3c5dd5 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 2 Nov 2013 07:52:04 -0300 Subject: media: af9015: Don't use dynamic static allocation commit 65e2f1cb3fe0f0630834b9517ba8f631936f325c upstream. Dynamic static allocation is evil, as Kernel stack is too low, and compilation complains about it on some archs: drivers/media/usb/dvb-usb-v2/af9015.c:433:1: warning: 'af9015_eeprom_hash' uses dynamic stack allocation [enabled by default] In this specific case, it is a gcc bug, as the size is a const, but it is easy to just change it from const to a #define, getting rid of the gcc warning. Signed-off-by: Mauro Carvalho Chehab Reviewed-by: Hans Verkuil Reviewed-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/usb/dvb-usb-v2/af9015.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/media/usb/dvb-usb-v2/af9015.c b/drivers/media/usb/dvb-usb-v2/af9015.c index d556042cf312..da47d2392f2a 100644 --- a/drivers/media/usb/dvb-usb-v2/af9015.c +++ b/drivers/media/usb/dvb-usb-v2/af9015.c @@ -397,12 +397,13 @@ error: return ret; } +#define AF9015_EEPROM_SIZE 256 + /* hash (and dump) eeprom */ static int af9015_eeprom_hash(struct dvb_usb_device *d) { struct af9015_state *state = d_to_priv(d); int ret, i; - static const unsigned int AF9015_EEPROM_SIZE = 256; u8 buf[AF9015_EEPROM_SIZE]; struct req_t req = {READ_I2C, AF9015_I2C_EEPROM, 0, 0, 1, 1, NULL}; -- cgit v1.2.3 From b49dfbeea93ebd078fa57404913d7e89320e94fa Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 2 Nov 2013 07:43:40 -0300 Subject: media: dw2102: Don't use dynamic static allocation commit 0065a79a8698a953e4b201c5fce8db8940530578 upstream. Dynamic static allocation is evil, as Kernel stack is too low, and compilation complains about it on some archs: drivers/media/usb/dvb-usb/dw2102.c:368:1: warning: 'dw2102_earda_i2c_transfer' uses dynamic stack allocation [enabled by default] drivers/media/usb/dvb-usb/dw2102.c:449:1: warning: 'dw2104_i2c_transfer' uses dynamic stack allocation [enabled by default] drivers/media/usb/dvb-usb/dw2102.c:512:1: warning: 'dw3101_i2c_transfer' uses dynamic stack allocation [enabled by default] drivers/media/usb/dvb-usb/dw2102.c:621:1: warning: 's6x0_i2c_transfer' uses dynamic stack allocation [enabled by default] Instead, let's enforce a limit for the buffer to be the max size of a control URB payload data (64 bytes). Signed-off-by: Mauro Carvalho Chehab Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/usb/dvb-usb/dw2102.c | 90 +++++++++++++++++++++++++++++++++----- 1 file changed, 80 insertions(+), 10 deletions(-) diff --git a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c index 6e237b6dd0a8..71b22f5a05ce 100644 --- a/drivers/media/usb/dvb-usb/dw2102.c +++ b/drivers/media/usb/dvb-usb/dw2102.c @@ -30,6 +30,9 @@ #include "stb6100_proc.h" #include "m88rs2000.h" +/* Max transfer size done by I2C transfer functions */ +#define MAX_XFER_SIZE 64 + #ifndef USB_PID_DW2102 #define USB_PID_DW2102 0x2102 #endif @@ -308,7 +311,14 @@ static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg ms case 2: { /* read */ /* first write first register number */ - u8 ibuf[msg[1].len + 2], obuf[3]; + u8 ibuf[MAX_XFER_SIZE], obuf[3]; + + if (2 + msg[1].len > sizeof(ibuf)) { + warn("i2c rd: len=%d is too big!\n", + msg[1].len); + return -EOPNOTSUPP; + } + obuf[0] = msg[0].addr << 1; obuf[1] = msg[0].len; obuf[2] = msg[0].buf[0]; @@ -325,7 +335,14 @@ static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg ms switch (msg[0].addr) { case 0x68: { /* write to register */ - u8 obuf[msg[0].len + 2]; + u8 obuf[MAX_XFER_SIZE]; + + if (2 + msg[0].len > sizeof(obuf)) { + warn("i2c wr: len=%d is too big!\n", + msg[1].len); + return -EOPNOTSUPP; + } + obuf[0] = msg[0].addr << 1; obuf[1] = msg[0].len; memcpy(obuf + 2, msg[0].buf, msg[0].len); @@ -335,7 +352,14 @@ static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg ms } case 0x61: { /* write to tuner */ - u8 obuf[msg[0].len + 2]; + u8 obuf[MAX_XFER_SIZE]; + + if (2 + msg[0].len > sizeof(obuf)) { + warn("i2c wr: len=%d is too big!\n", + msg[1].len); + return -EOPNOTSUPP; + } + obuf[0] = msg[0].addr << 1; obuf[1] = msg[0].len; memcpy(obuf + 2, msg[0].buf, msg[0].len); @@ -401,7 +425,14 @@ static int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], i default: { if (msg[j].flags == I2C_M_RD) { /* read registers */ - u8 ibuf[msg[j].len + 2]; + u8 ibuf[MAX_XFER_SIZE]; + + if (2 + msg[j].len > sizeof(ibuf)) { + warn("i2c rd: len=%d is too big!\n", + msg[j].len); + return -EOPNOTSUPP; + } + dw210x_op_rw(d->udev, 0xc3, (msg[j].addr << 1) + 1, 0, ibuf, msg[j].len + 2, @@ -430,7 +461,14 @@ static int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], i } while (len > 0); } else { /* write registers */ - u8 obuf[msg[j].len + 2]; + u8 obuf[MAX_XFER_SIZE]; + + if (2 + msg[j].len > sizeof(obuf)) { + warn("i2c wr: len=%d is too big!\n", + msg[j].len); + return -EOPNOTSUPP; + } + obuf[0] = msg[j].addr << 1; obuf[1] = msg[j].len; memcpy(obuf + 2, msg[j].buf, msg[j].len); @@ -463,7 +501,13 @@ static int dw3101_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], case 2: { /* read */ /* first write first register number */ - u8 ibuf[msg[1].len + 2], obuf[3]; + u8 ibuf[MAX_XFER_SIZE], obuf[3]; + + if (2 + msg[1].len > sizeof(ibuf)) { + warn("i2c rd: len=%d is too big!\n", + msg[1].len); + return -EOPNOTSUPP; + } obuf[0] = msg[0].addr << 1; obuf[1] = msg[0].len; obuf[2] = msg[0].buf[0]; @@ -481,7 +525,13 @@ static int dw3101_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], case 0x60: case 0x0c: { /* write to register */ - u8 obuf[msg[0].len + 2]; + u8 obuf[MAX_XFER_SIZE]; + + if (2 + msg[0].len > sizeof(obuf)) { + warn("i2c wr: len=%d is too big!\n", + msg[0].len); + return -EOPNOTSUPP; + } obuf[0] = msg[0].addr << 1; obuf[1] = msg[0].len; memcpy(obuf + 2, msg[0].buf, msg[0].len); @@ -563,7 +613,14 @@ static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], default: { if (msg[j].flags == I2C_M_RD) { /* read registers */ - u8 ibuf[msg[j].len]; + u8 ibuf[MAX_XFER_SIZE]; + + if (msg[j].len > sizeof(ibuf)) { + warn("i2c rd: len=%d is too big!\n", + msg[j].len); + return -EOPNOTSUPP; + } + dw210x_op_rw(d->udev, 0x91, 0, 0, ibuf, msg[j].len, DW210X_READ_MSG); @@ -590,7 +647,14 @@ static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], } while (len > 0); } else if (j < (num - 1)) { /* write register addr before read */ - u8 obuf[msg[j].len + 2]; + u8 obuf[MAX_XFER_SIZE]; + + if (2 + msg[j].len > sizeof(obuf)) { + warn("i2c wr: len=%d is too big!\n", + msg[j].len); + return -EOPNOTSUPP; + } + obuf[0] = msg[j + 1].len; obuf[1] = (msg[j].addr << 1); memcpy(obuf + 2, msg[j].buf, msg[j].len); @@ -602,7 +666,13 @@ static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], break; } else { /* write registers */ - u8 obuf[msg[j].len + 2]; + u8 obuf[MAX_XFER_SIZE]; + + if (2 + msg[j].len > sizeof(obuf)) { + warn("i2c wr: len=%d is too big!\n", + msg[j].len); + return -EOPNOTSUPP; + } obuf[0] = msg[j].len + 1; obuf[1] = (msg[j].addr << 1); memcpy(obuf + 2, msg[j].buf, msg[j].len); -- cgit v1.2.3 From 7ce9cdbe07651a2417a00d0a37c8b9fefae12f4b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 2 Nov 2013 07:23:49 -0300 Subject: media: dibusb-common: Don't use dynamic static allocation commit 1d7fa359d4c0fbb2756fa01cc47212908d90b7b0 upstream. Dynamic static allocation is evil, as Kernel stack is too low, and compilation complains about it on some archs: drivers/media/usb/dvb-usb/dibusb-common.c:124:1: warning: 'dibusb_i2c_msg' uses dynamic stack allocation [enabled by default] Instead, let's enforce a limit for the buffer to be the max size of a control URB payload data (64 bytes). Signed-off-by: Mauro Carvalho Chehab Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/usb/dvb-usb/dibusb-common.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/media/usb/dvb-usb/dibusb-common.c b/drivers/media/usb/dvb-usb/dibusb-common.c index c2dded92f1d3..6d68af0c49c8 100644 --- a/drivers/media/usb/dvb-usb/dibusb-common.c +++ b/drivers/media/usb/dvb-usb/dibusb-common.c @@ -12,6 +12,9 @@ #include #include "dibusb.h" +/* Max transfer size done by I2C transfer functions */ +#define MAX_XFER_SIZE 64 + static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "set debugging level (1=info (|-able))." DVB_USB_DEBUG_STATUS); @@ -105,11 +108,16 @@ EXPORT_SYMBOL(dibusb2_0_power_ctrl); static int dibusb_i2c_msg(struct dvb_usb_device *d, u8 addr, u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen) { - u8 sndbuf[wlen+4]; /* lead(1) devaddr,direction(1) addr(2) data(wlen) (len(2) (when reading)) */ + u8 sndbuf[MAX_XFER_SIZE]; /* lead(1) devaddr,direction(1) addr(2) data(wlen) (len(2) (when reading)) */ /* write only ? */ int wo = (rbuf == NULL || rlen == 0), len = 2 + wlen + (wo ? 0 : 2); + if (4 + wlen > sizeof(sndbuf)) { + warn("i2c wr: len=%d is too big!\n", wlen); + return -EOPNOTSUPP; + } + sndbuf[0] = wo ? DIBUSB_REQ_I2C_WRITE : DIBUSB_REQ_I2C_READ; sndbuf[1] = (addr << 1) | (wo ? 0 : 1); -- cgit v1.2.3 From a691956557756a05d948ce37a23b7011b88a53b7 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 2 Nov 2013 07:18:09 -0300 Subject: media: cxusb: Don't use dynamic static allocation commit 64f7ef8afbf89f3c72c4d2472e4914ca198c0668 upstream. Dynamic static allocation is evil, as Kernel stack is too low, and compilation complains about it on some archs: drivers/media/usb/dvb-usb/cxusb.c:209:1: warning: 'cxusb_i2c_xfer' uses dynamic stack allocation [enabled by default] drivers/media/usb/dvb-usb/cxusb.c:69:1: warning: 'cxusb_ctrl_msg' uses dynamic stack allocation [enabled by default] Instead, let's enforce a limit for the buffer to be the max size of a control URB payload data (64 bytes). Signed-off-by: Mauro Carvalho Chehab Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/usb/dvb-usb/cxusb.c | 41 +++++++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/drivers/media/usb/dvb-usb/cxusb.c b/drivers/media/usb/dvb-usb/cxusb.c index 3940bb0f9ef6..20e345d9fe8f 100644 --- a/drivers/media/usb/dvb-usb/cxusb.c +++ b/drivers/media/usb/dvb-usb/cxusb.c @@ -43,6 +43,9 @@ #include "lgs8gxx.h" #include "atbm8830.h" +/* Max transfer size done by I2C transfer functions */ +#define MAX_XFER_SIZE 64 + /* debug */ static int dvb_usb_cxusb_debug; module_param_named(debug, dvb_usb_cxusb_debug, int, 0644); @@ -57,7 +60,14 @@ static int cxusb_ctrl_msg(struct dvb_usb_device *d, u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen) { int wo = (rbuf == NULL || rlen == 0); /* write-only */ - u8 sndbuf[1+wlen]; + u8 sndbuf[MAX_XFER_SIZE]; + + if (1 + wlen > sizeof(sndbuf)) { + warn("i2c wr: len=%d is too big!\n", + wlen); + return -EOPNOTSUPP; + } + memset(sndbuf, 0, 1+wlen); sndbuf[0] = cmd; @@ -158,7 +168,13 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], if (msg[i].flags & I2C_M_RD) { /* read only */ - u8 obuf[3], ibuf[1+msg[i].len]; + u8 obuf[3], ibuf[MAX_XFER_SIZE]; + + if (1 + msg[i].len > sizeof(ibuf)) { + warn("i2c rd: len=%d is too big!\n", + msg[i].len); + return -EOPNOTSUPP; + } obuf[0] = 0; obuf[1] = msg[i].len; obuf[2] = msg[i].addr; @@ -172,7 +188,18 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], } else if (i+1 < num && (msg[i+1].flags & I2C_M_RD) && msg[i].addr == msg[i+1].addr) { /* write to then read from same address */ - u8 obuf[3+msg[i].len], ibuf[1+msg[i+1].len]; + u8 obuf[MAX_XFER_SIZE], ibuf[MAX_XFER_SIZE]; + + if (3 + msg[i].len > sizeof(obuf)) { + warn("i2c wr: len=%d is too big!\n", + msg[i].len); + return -EOPNOTSUPP; + } + if (1 + msg[i + 1].len > sizeof(ibuf)) { + warn("i2c rd: len=%d is too big!\n", + msg[i + 1].len); + return -EOPNOTSUPP; + } obuf[0] = msg[i].len; obuf[1] = msg[i+1].len; obuf[2] = msg[i].addr; @@ -191,7 +218,13 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], i++; } else { /* write only */ - u8 obuf[2+msg[i].len], ibuf; + u8 obuf[MAX_XFER_SIZE], ibuf; + + if (2 + msg[i].len > sizeof(obuf)) { + warn("i2c wr: len=%d is too big!\n", + msg[i].len); + return -EOPNOTSUPP; + } obuf[0] = msg[i].addr; obuf[1] = msg[i].len; memcpy(&obuf[2], msg[i].buf, msg[i].len); -- cgit v1.2.3 From 227aebf46dddbff678fe4248cc424ac11f5267dc Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 2 Nov 2013 05:51:59 -0300 Subject: media: av7110_hw: Don't use dynamic static allocation commit 5bf30b3bc4ff80ef71a733a1f459cca4fa507892 upstream. Dynamic static allocation is evil, as Kernel stack is too low, and compilation complains about it on some archs: drivers/media/pci/ttpci/av7110_hw.c:510:1: warning: 'av7110_fw_cmd' uses dynamic stack allocation [enabled by default] Instead, let's enforce a limit for the buffer. In the specific case of this driver, the maximum fw command size is 6 + 2, as checked using: $ git grep -A1 av7110_fw_cmd drivers/media/pci/ttpci/ So, use 8 for the buffer size. Signed-off-by: Mauro Carvalho Chehab Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/pci/ttpci/av7110_hw.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/media/pci/ttpci/av7110_hw.c b/drivers/media/pci/ttpci/av7110_hw.c index f1cbfe526989..6299d5dadb82 100644 --- a/drivers/media/pci/ttpci/av7110_hw.c +++ b/drivers/media/pci/ttpci/av7110_hw.c @@ -22,7 +22,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Or, point your browser to http://www.gnu.org/copyleft/gpl.html * - * the project's page is at http://www.linuxtv.org/ + * the project's page is at http://www.linuxtv.org/ */ /* for debugging ARM communication: */ @@ -40,6 +40,14 @@ #define _NOHANDSHAKE +/* + * Max transfer size done by av7110_fw_cmd() + * + * The maximum size passed to this function is 6 bytes. The buffer also + * uses two additional ones for type and size. So, 8 bytes is enough. + */ +#define MAX_XFER_SIZE 8 + /**************************************************************************** * DEBI functions ****************************************************************************/ @@ -488,11 +496,18 @@ static int av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length) int av7110_fw_cmd(struct av7110 *av7110, int type, int com, int num, ...) { va_list args; - u16 buf[num + 2]; + u16 buf[MAX_XFER_SIZE]; int i, ret; // dprintk(4, "%p\n", av7110); + if (2 + num > sizeof(buf)) { + printk(KERN_WARNING + "%s: %s len=%d is too big!\n", + KBUILD_MODNAME, __func__, num); + return -EINVAL; + } + buf[0] = ((type << 8) | com); buf[1] = num; -- cgit v1.2.3 From e84c43168ac1837d2dab02d141ddc1172c75fea5 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 2 Nov 2013 06:17:47 -0300 Subject: media: cimax2: Don't use dynamic static allocation commit 278ba83a3a1932805be726bdd7dfb3156286d33a upstream. Dynamic static allocation is evil, as Kernel stack is too low, and compilation complains about it on some archs: drivers/media/pci/cx23885/cimax2.c:149:1: warning: 'netup_write_i2c' uses dynamic stack allocation [enabled by default] Instead, let's enforce a limit for the buffer. Considering that I2C transfers are generally limited, and that devices used on USB has a max data length of 64 bytes for the control URBs. So, it seem safe to use 64 bytes as the hard limit for all those devices. On most cases, the limit is a way lower than that, but this limit is small enough to not affect the Kernel stack, and it is a no brain limit, as using smaller ones would require to either carefully each driver or to take a look on each datasheet. Signed-off-by: Mauro Carvalho Chehab Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/pci/cx23885/cimax2.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/media/pci/cx23885/cimax2.c b/drivers/media/pci/cx23885/cimax2.c index 7344849183a7..16fa7ea4d4aa 100644 --- a/drivers/media/pci/cx23885/cimax2.c +++ b/drivers/media/pci/cx23885/cimax2.c @@ -26,6 +26,10 @@ #include "cx23885.h" #include "cimax2.h" #include "dvb_ca_en50221.h" + +/* Max transfer size done by I2C transfer functions */ +#define MAX_XFER_SIZE 64 + /**** Bit definitions for MC417_RWD and MC417_OEN registers *** bits 31-16 +-----------+ @@ -125,7 +129,7 @@ static int netup_write_i2c(struct i2c_adapter *i2c_adap, u8 addr, u8 reg, u8 *buf, int len) { int ret; - u8 buffer[len + 1]; + u8 buffer[MAX_XFER_SIZE]; struct i2c_msg msg = { .addr = addr, @@ -134,6 +138,13 @@ static int netup_write_i2c(struct i2c_adapter *i2c_adap, u8 addr, u8 reg, .len = len + 1 }; + if (1 + len > sizeof(buffer)) { + printk(KERN_WARNING + "%s: i2c wr reg=%04x: len=%d is too big!\n", + KBUILD_MODNAME, reg, len); + return -EINVAL; + } + buffer[0] = reg; memcpy(&buffer[1], buf, len); -- cgit v1.2.3 From ef144824aceec873f0e61c1bb8a95c618534b21f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 1 Nov 2013 13:09:47 -0300 Subject: media: cx18: struct i2c_client is too big for stack commit 1d212cf0c2d89adf3d0a6d62d729076f49f087dc upstream. drivers/media/pci/cx18/cx18-driver.c: In function 'cx18_read_eeprom': drivers/media/pci/cx18/cx18-driver.c:357:1: warning: the frame size of 1072 bytes is larger than 1024 bytes [-Wframe-larger-than=] That happens because the routine allocates 256 bytes for an eeprom buffer, plus the size of struct i2c_client, with is big. Change the logic to dynamically allocate/deallocate space for struct i2c_client, instead of using the stack. Signed-off-by: Mauro Carvalho Chehab Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/pci/cx18/cx18-driver.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/drivers/media/pci/cx18/cx18-driver.c b/drivers/media/pci/cx18/cx18-driver.c index 67b61cf3e03a..13c9718a5ace 100644 --- a/drivers/media/pci/cx18/cx18-driver.c +++ b/drivers/media/pci/cx18/cx18-driver.c @@ -324,23 +324,24 @@ static void cx18_eeprom_dump(struct cx18 *cx, unsigned char *eedata, int len) /* Hauppauge card? get values from tveeprom */ void cx18_read_eeprom(struct cx18 *cx, struct tveeprom *tv) { - struct i2c_client c; + struct i2c_client *c; u8 eedata[256]; - memset(&c, 0, sizeof(c)); - strlcpy(c.name, "cx18 tveeprom tmp", sizeof(c.name)); - c.adapter = &cx->i2c_adap[0]; - c.addr = 0xA0 >> 1; + c = kzalloc(sizeof(*c), GFP_KERNEL); + + strlcpy(c->name, "cx18 tveeprom tmp", sizeof(c->name)); + c->adapter = &cx->i2c_adap[0]; + c->addr = 0xa0 >> 1; memset(tv, 0, sizeof(*tv)); - if (tveeprom_read(&c, eedata, sizeof(eedata))) - return; + if (tveeprom_read(c, eedata, sizeof(eedata))) + goto ret; switch (cx->card->type) { case CX18_CARD_HVR_1600_ESMT: case CX18_CARD_HVR_1600_SAMSUNG: case CX18_CARD_HVR_1600_S5H1411: - tveeprom_hauppauge_analog(&c, tv, eedata); + tveeprom_hauppauge_analog(c, tv, eedata); break; case CX18_CARD_YUAN_MPC718: case CX18_CARD_GOTVIEW_PCI_DVD3: @@ -354,6 +355,9 @@ void cx18_read_eeprom(struct cx18 *cx, struct tveeprom *tv) cx18_eeprom_dump(cx, eedata, sizeof(eedata)); break; } + +ret: + kfree(c); } static void cx18_process_eeprom(struct cx18 *cx) -- cgit v1.2.3 From 85217792a27009a1fd48832269fb5fd181f4834a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 2 Nov 2013 08:16:47 -0300 Subject: media: lirc_zilog: Don't use dynamic static allocation commit ac5b4b6bf0c84c48d7e2e3fce22e35b04282ba76 upstream. Dynamic static allocation is evil, as Kernel stack is too low, and ompilation complains about it on some archs: drivers/staging/media/lirc/lirc_zilog.c:967:1: warning: 'read' uses dynamic stack allocation [enabled by default] Instead, let's enforce a limit for the buffer to be 64. That should be more than enough. Signed-off-by: Mauro Carvalho Chehab Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/staging/media/lirc/lirc_zilog.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/staging/media/lirc/lirc_zilog.c b/drivers/staging/media/lirc/lirc_zilog.c index 11d5338b4f2f..0feeaadf29dc 100644 --- a/drivers/staging/media/lirc/lirc_zilog.c +++ b/drivers/staging/media/lirc/lirc_zilog.c @@ -61,6 +61,9 @@ #include #include +/* Max transfer size done by I2C transfer functions */ +#define MAX_XFER_SIZE 64 + struct IR; struct IR_rx { @@ -941,7 +944,14 @@ static ssize_t read(struct file *filep, char *outbuf, size_t n, loff_t *ppos) schedule(); set_current_state(TASK_INTERRUPTIBLE); } else { - unsigned char buf[rbuf->chunk_size]; + unsigned char buf[MAX_XFER_SIZE]; + + if (rbuf->chunk_size > sizeof(buf)) { + zilog_error("chunk_size is too big (%d)!\n", + rbuf->chunk_size); + ret = -EINVAL; + break; + } m = lirc_buffer_read(rbuf, buf); if (m == rbuf->chunk_size) { ret = copy_to_user((void *)outbuf+written, buf, -- cgit v1.2.3 From e4b95ceb002456b9628512cb0bd898bf1b62936c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 2 Nov 2013 06:13:11 -0300 Subject: media: tuner-xc2028: Don't use dynamic static allocation commit 56ac033725ec93a45170caf3979eb2b1211a59a8 upstream. Dynamic static allocation is evil, as Kernel stack is too low, and compilation complains about it on some archs: drivers/media/tuners/tuner-xc2028.c:651:1: warning: 'load_firmware' uses dynamic stack allocation [enabled by default] Instead, let's enforce a limit for the buffer. In the specific case of this driver, the maximum limit is 80, used only on tm6000 driver. This limit is due to the size of the USB control URBs. Ok, it would be theoretically possible to use a bigger size on PCI devices, but the firmware load time is already good enough. Anyway, if some usage requires more, it is just a matter of also increasing the buffer size at load_firmware(). Signed-off-by: Mauro Carvalho Chehab Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/tuners/tuner-xc2028.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/media/tuners/tuner-xc2028.c b/drivers/media/tuners/tuner-xc2028.c index 878d2c4d9e8e..9771cd83c06e 100644 --- a/drivers/media/tuners/tuner-xc2028.c +++ b/drivers/media/tuners/tuner-xc2028.c @@ -24,6 +24,9 @@ #include #include "dvb_frontend.h" +/* Max transfer size done by I2C transfer functions */ +#define MAX_XFER_SIZE 80 + /* Registers (Write-only) */ #define XREG_INIT 0x00 #define XREG_RF_FREQ 0x02 @@ -547,7 +550,10 @@ static int load_firmware(struct dvb_frontend *fe, unsigned int type, { struct xc2028_data *priv = fe->tuner_priv; int pos, rc; - unsigned char *p, *endp, buf[priv->ctrl.max_len]; + unsigned char *p, *endp, buf[MAX_XFER_SIZE]; + + if (priv->ctrl.max_len > sizeof(buf)) + priv->ctrl.max_len = sizeof(buf); tuner_dbg("%s called\n", __func__); -- cgit v1.2.3 From 9269743b3dcb031fb94d962ca90d14836dc8b4c4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 2 Nov 2013 06:07:42 -0300 Subject: media: tuners: Don't use dynamic static allocation commit f1baab870f6e93b668af7b34d6f6ba49f1b0e982 upstream. Dynamic static allocation is evil, as Kernel stack is too low, and compilation complains about it on some archs: drivers/media/tuners/e4000.c:50:1: warning: 'e4000_wr_regs' uses dynamic stack allocation [enabled by default] drivers/media/tuners/e4000.c:83:1: warning: 'e4000_rd_regs' uses dynamic stack allocation [enabled by default] drivers/media/tuners/fc2580.c:66:1: warning: 'fc2580_wr_regs.constprop.1' uses dynamic stack allocation [enabled by default] drivers/media/tuners/fc2580.c:98:1: warning: 'fc2580_rd_regs.constprop.0' uses dynamic stack allocation [enabled by default] drivers/media/tuners/tda18212.c:57:1: warning: 'tda18212_wr_regs' uses dynamic stack allocation [enabled by default] drivers/media/tuners/tda18212.c:90:1: warning: 'tda18212_rd_regs.constprop.0' uses dynamic stack allocation [enabled by default] drivers/media/tuners/tda18218.c:60:1: warning: 'tda18218_wr_regs' uses dynamic stack allocation [enabled by default] drivers/media/tuners/tda18218.c:92:1: warning: 'tda18218_rd_regs.constprop.0' uses dynamic stack allocation [enabled by default] Instead, let's enforce a limit for the buffer. Considering that I2C transfers are generally limited, and that devices used on USB has a max data length of 64 bytes for the control URBs. So, it seem safe to use 64 bytes as the hard limit for all those devices. On most cases, the limit is a way lower than that, but this limit is small enough to not affect the Kernel stack, and it is a no brain limit, as using smaller ones would require to either carefully each driver or to take a look on each datasheet. Signed-off-by: Mauro Carvalho Chehab Reviewed-by: Hans Verkuil Reviewed-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/tuners/e4000.c | 25 +++++++++++++++++++++---- drivers/media/tuners/fc2580.c | 25 +++++++++++++++++++++---- drivers/media/tuners/tda18212.c | 25 +++++++++++++++++++++---- drivers/media/tuners/tda18218.c | 23 ++++++++++++++++++++--- 4 files changed, 83 insertions(+), 15 deletions(-) diff --git a/drivers/media/tuners/e4000.c b/drivers/media/tuners/e4000.c index 1b33ed368abe..c4ce45007810 100644 --- a/drivers/media/tuners/e4000.c +++ b/drivers/media/tuners/e4000.c @@ -20,20 +20,30 @@ #include "e4000_priv.h" +/* Max transfer size done by I2C transfer functions */ +#define MAX_XFER_SIZE 64 + /* write multiple registers */ static int e4000_wr_regs(struct e4000_priv *priv, u8 reg, u8 *val, int len) { int ret; - u8 buf[1 + len]; + u8 buf[MAX_XFER_SIZE]; struct i2c_msg msg[1] = { { .addr = priv->cfg->i2c_addr, .flags = 0, - .len = sizeof(buf), + .len = 1 + len, .buf = buf, } }; + if (1 + len > sizeof(buf)) { + dev_warn(&priv->i2c->dev, + "%s: i2c wr reg=%04x: len=%d is too big!\n", + KBUILD_MODNAME, reg, len); + return -EINVAL; + } + buf[0] = reg; memcpy(&buf[1], val, len); @@ -52,7 +62,7 @@ static int e4000_wr_regs(struct e4000_priv *priv, u8 reg, u8 *val, int len) static int e4000_rd_regs(struct e4000_priv *priv, u8 reg, u8 *val, int len) { int ret; - u8 buf[len]; + u8 buf[MAX_XFER_SIZE]; struct i2c_msg msg[2] = { { .addr = priv->cfg->i2c_addr, @@ -62,11 +72,18 @@ static int e4000_rd_regs(struct e4000_priv *priv, u8 reg, u8 *val, int len) }, { .addr = priv->cfg->i2c_addr, .flags = I2C_M_RD, - .len = sizeof(buf), + .len = len, .buf = buf, } }; + if (len > sizeof(buf)) { + dev_warn(&priv->i2c->dev, + "%s: i2c rd reg=%04x: len=%d is too big!\n", + KBUILD_MODNAME, reg, len); + return -EINVAL; + } + ret = i2c_transfer(priv->i2c, msg, 2); if (ret == 2) { memcpy(val, buf, len); diff --git a/drivers/media/tuners/fc2580.c b/drivers/media/tuners/fc2580.c index 81f38aae9c66..3aecaf465094 100644 --- a/drivers/media/tuners/fc2580.c +++ b/drivers/media/tuners/fc2580.c @@ -20,6 +20,9 @@ #include "fc2580_priv.h" +/* Max transfer size done by I2C transfer functions */ +#define MAX_XFER_SIZE 64 + /* * TODO: * I2C write and read works only for one single register. Multiple registers @@ -41,16 +44,23 @@ static int fc2580_wr_regs(struct fc2580_priv *priv, u8 reg, u8 *val, int len) { int ret; - u8 buf[1 + len]; + u8 buf[MAX_XFER_SIZE]; struct i2c_msg msg[1] = { { .addr = priv->cfg->i2c_addr, .flags = 0, - .len = sizeof(buf), + .len = 1 + len, .buf = buf, } }; + if (1 + len > sizeof(buf)) { + dev_warn(&priv->i2c->dev, + "%s: i2c wr reg=%04x: len=%d is too big!\n", + KBUILD_MODNAME, reg, len); + return -EINVAL; + } + buf[0] = reg; memcpy(&buf[1], val, len); @@ -69,7 +79,7 @@ static int fc2580_wr_regs(struct fc2580_priv *priv, u8 reg, u8 *val, int len) static int fc2580_rd_regs(struct fc2580_priv *priv, u8 reg, u8 *val, int len) { int ret; - u8 buf[len]; + u8 buf[MAX_XFER_SIZE]; struct i2c_msg msg[2] = { { .addr = priv->cfg->i2c_addr, @@ -79,11 +89,18 @@ static int fc2580_rd_regs(struct fc2580_priv *priv, u8 reg, u8 *val, int len) }, { .addr = priv->cfg->i2c_addr, .flags = I2C_M_RD, - .len = sizeof(buf), + .len = len, .buf = buf, } }; + if (len > sizeof(buf)) { + dev_warn(&priv->i2c->dev, + "%s: i2c rd reg=%04x: len=%d is too big!\n", + KBUILD_MODNAME, reg, len); + return -EINVAL; + } + ret = i2c_transfer(priv->i2c, msg, 2); if (ret == 2) { memcpy(val, buf, len); diff --git a/drivers/media/tuners/tda18212.c b/drivers/media/tuners/tda18212.c index e4a84ee231cf..abe256e1f843 100644 --- a/drivers/media/tuners/tda18212.c +++ b/drivers/media/tuners/tda18212.c @@ -20,6 +20,9 @@ #include "tda18212.h" +/* Max transfer size done by I2C transfer functions */ +#define MAX_XFER_SIZE 64 + struct tda18212_priv { struct tda18212_config *cfg; struct i2c_adapter *i2c; @@ -32,16 +35,23 @@ static int tda18212_wr_regs(struct tda18212_priv *priv, u8 reg, u8 *val, int len) { int ret; - u8 buf[len+1]; + u8 buf[MAX_XFER_SIZE]; struct i2c_msg msg[1] = { { .addr = priv->cfg->i2c_address, .flags = 0, - .len = sizeof(buf), + .len = 1 + len, .buf = buf, } }; + if (1 + len > sizeof(buf)) { + dev_warn(&priv->i2c->dev, + "%s: i2c wr reg=%04x: len=%d is too big!\n", + KBUILD_MODNAME, reg, len); + return -EINVAL; + } + buf[0] = reg; memcpy(&buf[1], val, len); @@ -61,7 +71,7 @@ static int tda18212_rd_regs(struct tda18212_priv *priv, u8 reg, u8 *val, int len) { int ret; - u8 buf[len]; + u8 buf[MAX_XFER_SIZE]; struct i2c_msg msg[2] = { { .addr = priv->cfg->i2c_address, @@ -71,11 +81,18 @@ static int tda18212_rd_regs(struct tda18212_priv *priv, u8 reg, u8 *val, }, { .addr = priv->cfg->i2c_address, .flags = I2C_M_RD, - .len = sizeof(buf), + .len = len, .buf = buf, } }; + if (len > sizeof(buf)) { + dev_warn(&priv->i2c->dev, + "%s: i2c rd reg=%04x: len=%d is too big!\n", + KBUILD_MODNAME, reg, len); + return -EINVAL; + } + ret = i2c_transfer(priv->i2c, msg, 2); if (ret == 2) { memcpy(val, buf, len); diff --git a/drivers/media/tuners/tda18218.c b/drivers/media/tuners/tda18218.c index 2d31aeb6b088..9300e9361e3b 100644 --- a/drivers/media/tuners/tda18218.c +++ b/drivers/media/tuners/tda18218.c @@ -20,11 +20,14 @@ #include "tda18218_priv.h" +/* Max transfer size done by I2C transfer functions */ +#define MAX_XFER_SIZE 64 + /* write multiple registers */ static int tda18218_wr_regs(struct tda18218_priv *priv, u8 reg, u8 *val, u8 len) { int ret = 0, len2, remaining; - u8 buf[1 + len]; + u8 buf[MAX_XFER_SIZE]; struct i2c_msg msg[1] = { { .addr = priv->cfg->i2c_address, @@ -33,6 +36,13 @@ static int tda18218_wr_regs(struct tda18218_priv *priv, u8 reg, u8 *val, u8 len) } }; + if (1 + len > sizeof(buf)) { + dev_warn(&priv->i2c->dev, + "%s: i2c wr reg=%04x: len=%d is too big!\n", + KBUILD_MODNAME, reg, len); + return -EINVAL; + } + for (remaining = len; remaining > 0; remaining -= (priv->cfg->i2c_wr_max - 1)) { len2 = remaining; @@ -63,7 +73,7 @@ static int tda18218_wr_regs(struct tda18218_priv *priv, u8 reg, u8 *val, u8 len) static int tda18218_rd_regs(struct tda18218_priv *priv, u8 reg, u8 *val, u8 len) { int ret; - u8 buf[reg+len]; /* we must start read always from reg 0x00 */ + u8 buf[MAX_XFER_SIZE]; /* we must start read always from reg 0x00 */ struct i2c_msg msg[2] = { { .addr = priv->cfg->i2c_address, @@ -73,11 +83,18 @@ static int tda18218_rd_regs(struct tda18218_priv *priv, u8 reg, u8 *val, u8 len) }, { .addr = priv->cfg->i2c_address, .flags = I2C_M_RD, - .len = sizeof(buf), + .len = reg + len, .buf = buf, } }; + if (reg + len > sizeof(buf)) { + dev_warn(&priv->i2c->dev, + "%s: i2c wr reg=%04x: len=%d is too big!\n", + KBUILD_MODNAME, reg, len); + return -EINVAL; + } + ret = i2c_transfer(priv->i2c, msg, 2); if (ret == 2) { memcpy(val, &buf[reg], len); -- cgit v1.2.3 From bea929cb3ef0887cccf8e30331574f23f530ba99 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 2 Nov 2013 05:18:49 -0300 Subject: media: stv090x: Don't use dynamic static allocation commit f7a35df15b1f7de7823946aebc9164854e66ea07 upstream. Dynamic static allocation is evil, as Kernel stack is too low, and compilation complains about it on some archs: drivers/media/dvb-frontends/stv090x.c:750:1: warning: 'stv090x_write_regs.constprop.6' uses dynamic stack allocation [enabled by default] Instead, let's enforce a limit for the buffer. Considering that I2C transfers are generally limited, and that devices used on USB has a max data length of 64 bytes for the control URBs. So, it seem safe to use 64 bytes as the hard limit for all those devices. On most cases, the limit is a way lower than that, but this limit is small enough to not affect the Kernel stack, and it is a no brain limit, as using smaller ones would require to either carefully each driver or to take a look on each datasheet. Signed-off-by: Mauro Carvalho Chehab Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/dvb-frontends/stv090x.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/media/dvb-frontends/stv090x.c b/drivers/media/dvb-frontends/stv090x.c index 56d470ad5a82..23e872f84742 100644 --- a/drivers/media/dvb-frontends/stv090x.c +++ b/drivers/media/dvb-frontends/stv090x.c @@ -35,6 +35,9 @@ #include "stv090x.h" #include "stv090x_priv.h" +/* Max transfer size done by I2C transfer functions */ +#define MAX_XFER_SIZE 64 + static unsigned int verbose; module_param(verbose, int, 0644); @@ -722,9 +725,16 @@ static int stv090x_write_regs(struct stv090x_state *state, unsigned int reg, u8 { const struct stv090x_config *config = state->config; int ret; - u8 buf[2 + count]; + u8 buf[MAX_XFER_SIZE]; struct i2c_msg i2c_msg = { .addr = config->address, .flags = 0, .buf = buf, .len = 2 + count }; + if (2 + count > sizeof(buf)) { + printk(KERN_WARNING + "%s: i2c wr reg=%04x: len=%d is too big!\n", + KBUILD_MODNAME, reg, count); + return -EINVAL; + } + buf[0] = reg >> 8; buf[1] = reg & 0xff; memcpy(&buf[2], data, count); -- cgit v1.2.3 From 6d3ac5e79294ecf2c437de63e9a38d125b7c5922 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 2 Nov 2013 05:17:01 -0300 Subject: media: stv0367: Don't use dynamic static allocation commit 9aca4fb0571ce9cfef680ceb08d19dd008015307 upstream. Dynamic static allocation is evil, as Kernel stack is too low, and compilation complains about it on some archs: drivers/media/dvb-frontends/stv0367.c:791:1: warning: 'stv0367_writeregs.constprop.4' uses dynamic stack allocation [enabled by default] Instead, let's enforce a limit for the buffer. Considering that I2C transfers are generally limited, and that devices used on USB has a max data length of 64 bytes for the control URBs. So, it seem safe to use 64 bytes as the hard limit for all those devices. On most cases, the limit is a way lower than that, but this limit is small enough to not affect the Kernel stack, and it is a no brain limit, as using smaller ones would require to either carefully each driver or to take a look on each datasheet. Signed-off-by: Mauro Carvalho Chehab Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/dvb-frontends/stv0367.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/media/dvb-frontends/stv0367.c b/drivers/media/dvb-frontends/stv0367.c index 0c8e45949b11..f6c7277999fe 100644 --- a/drivers/media/dvb-frontends/stv0367.c +++ b/drivers/media/dvb-frontends/stv0367.c @@ -33,6 +33,9 @@ #include "stv0367_regs.h" #include "stv0367_priv.h" +/* Max transfer size done by I2C transfer functions */ +#define MAX_XFER_SIZE 64 + static int stvdebug; module_param_named(debug, stvdebug, int, 0644); @@ -767,7 +770,7 @@ static struct st_register def0367cab[STV0367CAB_NBREGS] = { static int stv0367_writeregs(struct stv0367_state *state, u16 reg, u8 *data, int len) { - u8 buf[len + 2]; + u8 buf[MAX_XFER_SIZE]; struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, @@ -776,6 +779,14 @@ int stv0367_writeregs(struct stv0367_state *state, u16 reg, u8 *data, int len) }; int ret; + if (2 + len > sizeof(buf)) { + printk(KERN_WARNING + "%s: i2c wr reg=%04x: len=%d is too big!\n", + KBUILD_MODNAME, reg, len); + return -EINVAL; + } + + buf[0] = MSB(reg); buf[1] = LSB(reg); memcpy(buf + 2, data, len); -- cgit v1.2.3 From 845b09830c162084301f65c947894389cd48e8b6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 2 Nov 2013 05:14:58 -0300 Subject: media: stb0899_drv: Don't use dynamic static allocation commit ba4746423488aafa435739c32bfe0758f3dd5d77 upstream. Dynamic static allocation is evil, as Kernel stack is too low, and compilation complains about it on some archs: drivers/media/dvb-frontends/stb0899_drv.c:540:1: warning: 'stb0899_write_regs' uses dynamic stack allocation [enabled by default] Instead, let's enforce a limit for the buffer. Considering that I2C transfers are generally limited, and that devices used on USB has a max data length of 64 bytes for the control URBs. So, it seem safe to use 64 bytes as the hard limit for all those devices. On most cases, the limit is a way lower than that, but this limit is small enough to not affect the Kernel stack, and it is a no brain limit, as using smaller ones would require to either carefully each driver or to take a look on each datasheet. Signed-off-by: Mauro Carvalho Chehab Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/dvb-frontends/stb0899_drv.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/media/dvb-frontends/stb0899_drv.c b/drivers/media/dvb-frontends/stb0899_drv.c index cc278b3d6d5a..2a979cfac146 100644 --- a/drivers/media/dvb-frontends/stb0899_drv.c +++ b/drivers/media/dvb-frontends/stb0899_drv.c @@ -32,6 +32,9 @@ #include "stb0899_priv.h" #include "stb0899_reg.h" +/* Max transfer size done by I2C transfer functions */ +#define MAX_XFER_SIZE 64 + static unsigned int verbose = 0;//1; module_param(verbose, int, 0644); @@ -499,7 +502,7 @@ err: int stb0899_write_regs(struct stb0899_state *state, unsigned int reg, u8 *data, u32 count) { int ret; - u8 buf[2 + count]; + u8 buf[MAX_XFER_SIZE]; struct i2c_msg i2c_msg = { .addr = state->config->demod_address, .flags = 0, @@ -507,6 +510,13 @@ int stb0899_write_regs(struct stb0899_state *state, unsigned int reg, u8 *data, .len = 2 + count }; + if (2 + count > sizeof(buf)) { + printk(KERN_WARNING + "%s: i2c wr reg=%04x: len=%d is too big!\n", + KBUILD_MODNAME, reg, count); + return -EINVAL; + } + buf[0] = reg >> 8; buf[1] = reg & 0xff; memcpy(&buf[2], data, count); -- cgit v1.2.3 From 10184cdc523eb232ff416c6aa5819dfbcb681870 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 2 Nov 2013 05:11:47 -0300 Subject: media: dvb-frontends: Don't use dynamic static allocation commit 37ebaf6891ee81687bb558e8375c0712d8264ed8 upstream. Dynamic static allocation is evil, as Kernel stack is too low, and compilation complains about it on some archs: drivers/media/dvb-frontends/af9013.c:77:1: warning: 'af9013_wr_regs_i2c' uses dynamic stack allocation [enabled by default] drivers/media/dvb-frontends/af9033.c:188:1: warning: 'af9033_wr_reg_val_tab' uses dynamic stack allocation [enabled by default] drivers/media/dvb-frontends/af9033.c:68:1: warning: 'af9033_wr_regs' uses dynamic stack allocation [enabled by default] drivers/media/dvb-frontends/bcm3510.c:230:1: warning: 'bcm3510_do_hab_cmd' uses dynamic stack allocation [enabled by default] drivers/media/dvb-frontends/cxd2820r_core.c:84:1: warning: 'cxd2820r_rd_regs_i2c.isra.1' uses dynamic stack allocation [enabled by default] drivers/media/dvb-frontends/rtl2830.c:56:1: warning: 'rtl2830_wr' uses dynamic stack allocation [enabled by default] drivers/media/dvb-frontends/rtl2832.c:187:1: warning: 'rtl2832_wr' uses dynamic stack allocation [enabled by default] drivers/media/dvb-frontends/tda10071.c:52:1: warning: 'tda10071_wr_regs' uses dynamic stack allocation [enabled by default] drivers/media/dvb-frontends/tda10071.c:84:1: warning: 'tda10071_rd_regs' uses dynamic stack allocation [enabled by default] Instead, let's enforce a limit for the buffer. Considering that I2C transfers are generally limited, and that devices used on USB has a max data length of 64 bytes for the control URBs. So, it seem safe to use 64 bytes as the hard limit for all those devices. On most cases, the limit is a way lower than that, but this limit is small enough to not affect the Kernel stack, and it is a no brain limit, as using smaller ones would require to either carefully each driver or to take a look on each datasheet. Signed-off-by: Mauro Carvalho Chehab Reviewed-by: Hans Verkuil Reviewed-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/dvb-frontends/af9013.c | 14 ++++++++++++-- drivers/media/dvb-frontends/af9033.c | 23 ++++++++++++++++++++--- drivers/media/dvb-frontends/cxd2820r_core.c | 21 +++++++++++++++++++-- drivers/media/dvb-frontends/rtl2830.c | 14 ++++++++++++-- drivers/media/dvb-frontends/rtl2832.c | 14 ++++++++++++-- drivers/media/dvb-frontends/tda10071.c | 25 +++++++++++++++++++++---- 6 files changed, 96 insertions(+), 15 deletions(-) diff --git a/drivers/media/dvb-frontends/af9013.c b/drivers/media/dvb-frontends/af9013.c index a204f2828820..fb504f1e9125 100644 --- a/drivers/media/dvb-frontends/af9013.c +++ b/drivers/media/dvb-frontends/af9013.c @@ -24,6 +24,9 @@ #include "af9013_priv.h" +/* Max transfer size done by I2C transfer functions */ +#define MAX_XFER_SIZE 64 + struct af9013_state { struct i2c_adapter *i2c; struct dvb_frontend fe; @@ -50,16 +53,23 @@ static int af9013_wr_regs_i2c(struct af9013_state *priv, u8 mbox, u16 reg, const u8 *val, int len) { int ret; - u8 buf[3+len]; + u8 buf[MAX_XFER_SIZE]; struct i2c_msg msg[1] = { { .addr = priv->config.i2c_addr, .flags = 0, - .len = sizeof(buf), + .len = 3 + len, .buf = buf, } }; + if (3 + len > sizeof(buf)) { + dev_warn(&priv->i2c->dev, + "%s: i2c wr reg=%04x: len=%d is too big!\n", + KBUILD_MODNAME, reg, len); + return -EINVAL; + } + buf[0] = (reg >> 8) & 0xff; buf[1] = (reg >> 0) & 0xff; buf[2] = mbox; diff --git a/drivers/media/dvb-frontends/af9033.c b/drivers/media/dvb-frontends/af9033.c index a777b4b944eb..30ee59052157 100644 --- a/drivers/media/dvb-frontends/af9033.c +++ b/drivers/media/dvb-frontends/af9033.c @@ -21,6 +21,9 @@ #include "af9033_priv.h" +/* Max transfer size done by I2C transfer functions */ +#define MAX_XFER_SIZE 64 + struct af9033_state { struct i2c_adapter *i2c; struct dvb_frontend fe; @@ -40,16 +43,23 @@ static int af9033_wr_regs(struct af9033_state *state, u32 reg, const u8 *val, int len) { int ret; - u8 buf[3 + len]; + u8 buf[MAX_XFER_SIZE]; struct i2c_msg msg[1] = { { .addr = state->cfg.i2c_addr, .flags = 0, - .len = sizeof(buf), + .len = 3 + len, .buf = buf, } }; + if (3 + len > sizeof(buf)) { + dev_warn(&state->i2c->dev, + "%s: i2c wr reg=%04x: len=%d is too big!\n", + KBUILD_MODNAME, reg, len); + return -EINVAL; + } + buf[0] = (reg >> 16) & 0xff; buf[1] = (reg >> 8) & 0xff; buf[2] = (reg >> 0) & 0xff; @@ -161,7 +171,14 @@ static int af9033_wr_reg_val_tab(struct af9033_state *state, const struct reg_val *tab, int tab_len) { int ret, i, j; - u8 buf[tab_len]; + u8 buf[MAX_XFER_SIZE]; + + if (tab_len > sizeof(buf)) { + dev_warn(&state->i2c->dev, + "%s: i2c wr len=%d is too big!\n", + KBUILD_MODNAME, tab_len); + return -EINVAL; + } dev_dbg(&state->i2c->dev, "%s: tab_len=%d\n", __func__, tab_len); diff --git a/drivers/media/dvb-frontends/cxd2820r_core.c b/drivers/media/dvb-frontends/cxd2820r_core.c index 7ca5c69dd200..51447a04d8f2 100644 --- a/drivers/media/dvb-frontends/cxd2820r_core.c +++ b/drivers/media/dvb-frontends/cxd2820r_core.c @@ -21,12 +21,15 @@ #include "cxd2820r_priv.h" +/* Max transfer size done by I2C transfer functions */ +#define MAX_XFER_SIZE 64 + /* write multiple registers */ static int cxd2820r_wr_regs_i2c(struct cxd2820r_priv *priv, u8 i2c, u8 reg, u8 *val, int len) { int ret; - u8 buf[len+1]; + u8 buf[MAX_XFER_SIZE]; struct i2c_msg msg[1] = { { .addr = i2c, @@ -36,6 +39,13 @@ static int cxd2820r_wr_regs_i2c(struct cxd2820r_priv *priv, u8 i2c, u8 reg, } }; + if (1 + len > sizeof(buf)) { + dev_warn(&priv->i2c->dev, + "%s: i2c wr reg=%04x: len=%d is too big!\n", + KBUILD_MODNAME, reg, len); + return -EINVAL; + } + buf[0] = reg; memcpy(&buf[1], val, len); @@ -55,7 +65,7 @@ static int cxd2820r_rd_regs_i2c(struct cxd2820r_priv *priv, u8 i2c, u8 reg, u8 *val, int len) { int ret; - u8 buf[len]; + u8 buf[MAX_XFER_SIZE]; struct i2c_msg msg[2] = { { .addr = i2c, @@ -70,6 +80,13 @@ static int cxd2820r_rd_regs_i2c(struct cxd2820r_priv *priv, u8 i2c, u8 reg, } }; + if (len > sizeof(buf)) { + dev_warn(&priv->i2c->dev, + "%s: i2c wr reg=%04x: len=%d is too big!\n", + KBUILD_MODNAME, reg, len); + return -EINVAL; + } + ret = i2c_transfer(priv->i2c, msg, 2); if (ret == 2) { memcpy(val, buf, len); diff --git a/drivers/media/dvb-frontends/rtl2830.c b/drivers/media/dvb-frontends/rtl2830.c index 362d26d11e82..7efb796c472c 100644 --- a/drivers/media/dvb-frontends/rtl2830.c +++ b/drivers/media/dvb-frontends/rtl2830.c @@ -27,20 +27,30 @@ #include "rtl2830_priv.h" +/* Max transfer size done by I2C transfer functions */ +#define MAX_XFER_SIZE 64 + /* write multiple hardware registers */ static int rtl2830_wr(struct rtl2830_priv *priv, u8 reg, const u8 *val, int len) { int ret; - u8 buf[1+len]; + u8 buf[MAX_XFER_SIZE]; struct i2c_msg msg[1] = { { .addr = priv->cfg.i2c_addr, .flags = 0, - .len = 1+len, + .len = 1 + len, .buf = buf, } }; + if (1 + len > sizeof(buf)) { + dev_warn(&priv->i2c->dev, + "%s: i2c wr reg=%04x: len=%d is too big!\n", + KBUILD_MODNAME, reg, len); + return -EINVAL; + } + buf[0] = reg; memcpy(&buf[1], val, len); diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c index facb84841518..b8dd0a135461 100644 --- a/drivers/media/dvb-frontends/rtl2832.c +++ b/drivers/media/dvb-frontends/rtl2832.c @@ -22,6 +22,9 @@ #include "dvb_math.h" #include +/* Max transfer size done by I2C transfer functions */ +#define MAX_XFER_SIZE 64 + int rtl2832_debug; module_param_named(debug, rtl2832_debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); @@ -162,16 +165,23 @@ static const struct rtl2832_reg_entry registers[] = { static int rtl2832_wr(struct rtl2832_priv *priv, u8 reg, u8 *val, int len) { int ret; - u8 buf[1+len]; + u8 buf[MAX_XFER_SIZE]; struct i2c_msg msg[1] = { { .addr = priv->cfg.i2c_addr, .flags = 0, - .len = 1+len, + .len = 1 + len, .buf = buf, } }; + if (1 + len > sizeof(buf)) { + dev_warn(&priv->i2c->dev, + "%s: i2c wr reg=%04x: len=%d is too big!\n", + KBUILD_MODNAME, reg, len); + return -EINVAL; + } + buf[0] = reg; memcpy(&buf[1], val, len); diff --git a/drivers/media/dvb-frontends/tda10071.c b/drivers/media/dvb-frontends/tda10071.c index 2521f7e23018..36eb27d3fdf1 100644 --- a/drivers/media/dvb-frontends/tda10071.c +++ b/drivers/media/dvb-frontends/tda10071.c @@ -20,6 +20,9 @@ #include "tda10071_priv.h" +/* Max transfer size done by I2C transfer functions */ +#define MAX_XFER_SIZE 64 + static struct dvb_frontend_ops tda10071_ops; /* write multiple registers */ @@ -27,16 +30,23 @@ static int tda10071_wr_regs(struct tda10071_priv *priv, u8 reg, u8 *val, int len) { int ret; - u8 buf[len+1]; + u8 buf[MAX_XFER_SIZE]; struct i2c_msg msg[1] = { { .addr = priv->cfg.demod_i2c_addr, .flags = 0, - .len = sizeof(buf), + .len = 1 + len, .buf = buf, } }; + if (1 + len > sizeof(buf)) { + dev_warn(&priv->i2c->dev, + "%s: i2c wr reg=%04x: len=%d is too big!\n", + KBUILD_MODNAME, reg, len); + return -EINVAL; + } + buf[0] = reg; memcpy(&buf[1], val, len); @@ -56,7 +66,7 @@ static int tda10071_rd_regs(struct tda10071_priv *priv, u8 reg, u8 *val, int len) { int ret; - u8 buf[len]; + u8 buf[MAX_XFER_SIZE]; struct i2c_msg msg[2] = { { .addr = priv->cfg.demod_i2c_addr, @@ -66,11 +76,18 @@ static int tda10071_rd_regs(struct tda10071_priv *priv, u8 reg, u8 *val, }, { .addr = priv->cfg.demod_i2c_addr, .flags = I2C_M_RD, - .len = sizeof(buf), + .len = len, .buf = buf, } }; + if (len > sizeof(buf)) { + dev_warn(&priv->i2c->dev, + "%s: i2c wr reg=%04x: len=%d is too big!\n", + KBUILD_MODNAME, reg, len); + return -EINVAL; + } + ret = i2c_transfer(priv->i2c, msg, 2); if (ret == 2) { memcpy(val, buf, len); -- cgit v1.2.3 From 830658240837a0545307e689c612b637bd4f9b22 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 2 Nov 2013 05:05:18 -0300 Subject: media: dvb-frontends: Don't use dynamic static allocation commit 8393796dfa4cf5dffcceec464c7789bec3a2f471 upstream. Dynamic static allocation is evil, as Kernel stack is too low, and compilation complains about it on some archs: drivers/media/dvb-frontends/bcm3510.c:230:1: warning: 'bcm3510_do_hab_cmd' uses dynamic stack allocation [enabled by default] drivers/media/dvb-frontends/itd1000.c:69:1: warning: 'itd1000_write_regs.constprop.0' uses dynamic stack allocation [enabled by default] drivers/media/dvb-frontends/mt312.c:126:1: warning: 'mt312_write' uses dynamic stack allocation [enabled by default] drivers/media/dvb-frontends/nxt200x.c:111:1: warning: 'nxt200x_writebytes' uses dynamic stack allocation [enabled by default] drivers/media/dvb-frontends/stb6100.c:216:1: warning: 'stb6100_write_reg_range.constprop.3' uses dynamic stack allocation [enabled by default] drivers/media/dvb-frontends/stv6110.c:98:1: warning: 'stv6110_write_regs' uses dynamic stack allocation [enabled by default] drivers/media/dvb-frontends/stv6110x.c:85:1: warning: 'stv6110x_write_regs' uses dynamic stack allocation [enabled by default] drivers/media/dvb-frontends/tda18271c2dd.c:147:1: warning: 'WriteRegs' uses dynamic stack allocation [enabled by default] drivers/media/dvb-frontends/zl10039.c:119:1: warning: 'zl10039_write' uses dynamic stack allocation [enabled by default] Instead, let's enforce a limit for the buffer. Considering that I2C transfers are generally limited, and that devices used on USB has a max data length of 64 bytes for the control URBs. So, it seem safe to use 64 bytes as the hard limit for all those devices. On most cases, the limit is a way lower than that, but this limit is small enough to not affect the Kernel stack, and it is a no brain limit, as using smaller ones would require to either carefully each driver or to take a look on each datasheet. Signed-off-by: Mauro Carvalho Chehab Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/dvb-frontends/bcm3510.c | 15 ++++++++++++++- drivers/media/dvb-frontends/itd1000.c | 13 ++++++++++++- drivers/media/dvb-frontends/mt312.c | 10 +++++++++- drivers/media/dvb-frontends/nxt200x.c | 11 ++++++++++- drivers/media/dvb-frontends/stb6100.c | 11 ++++++++++- drivers/media/dvb-frontends/stv6110.c | 12 +++++++++++- drivers/media/dvb-frontends/stv6110x.c | 13 ++++++++++++- drivers/media/dvb-frontends/tda18271c2dd.c | 14 ++++++++++++-- drivers/media/dvb-frontends/zl10039.c | 12 +++++++++++- 9 files changed, 101 insertions(+), 10 deletions(-) diff --git a/drivers/media/dvb-frontends/bcm3510.c b/drivers/media/dvb-frontends/bcm3510.c index 1b77909c0c71..39a29dd29519 100644 --- a/drivers/media/dvb-frontends/bcm3510.c +++ b/drivers/media/dvb-frontends/bcm3510.c @@ -44,6 +44,9 @@ #include "bcm3510.h" #include "bcm3510_priv.h" +/* Max transfer size done by bcm3510_do_hab_cmd() function */ +#define MAX_XFER_SIZE 128 + struct bcm3510_state { struct i2c_adapter* i2c; @@ -201,9 +204,19 @@ static int bcm3510_hab_send_request(struct bcm3510_state *st, u8 *buf, int len) static int bcm3510_do_hab_cmd(struct bcm3510_state *st, u8 cmd, u8 msgid, u8 *obuf, u8 olen, u8 *ibuf, u8 ilen) { - u8 ob[olen+2],ib[ilen+2]; + u8 ob[MAX_XFER_SIZE], ib[MAX_XFER_SIZE]; int ret = 0; + if (ilen + 2 > sizeof(ib)) { + deb_hab("do_hab_cmd: ilen=%d is too big!\n", ilen); + return -EINVAL; + } + + if (olen + 2 > sizeof(ob)) { + deb_hab("do_hab_cmd: olen=%d is too big!\n", olen); + return -EINVAL; + } + ob[0] = cmd; ob[1] = msgid; memcpy(&ob[2],obuf,olen); diff --git a/drivers/media/dvb-frontends/itd1000.c b/drivers/media/dvb-frontends/itd1000.c index c1c3400b2173..cadcae4cff89 100644 --- a/drivers/media/dvb-frontends/itd1000.c +++ b/drivers/media/dvb-frontends/itd1000.c @@ -31,6 +31,9 @@ #include "itd1000.h" #include "itd1000_priv.h" +/* Max transfer size done by I2C transfer functions */ +#define MAX_XFER_SIZE 64 + static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); @@ -52,10 +55,18 @@ MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); /* don't write more than one byte with flexcop behind */ static int itd1000_write_regs(struct itd1000_state *state, u8 reg, u8 v[], u8 len) { - u8 buf[1+len]; + u8 buf[MAX_XFER_SIZE]; struct i2c_msg msg = { .addr = state->cfg->i2c_address, .flags = 0, .buf = buf, .len = len+1 }; + + if (1 + len > sizeof(buf)) { + printk(KERN_WARNING + "itd1000: i2c wr reg=%04x: len=%d is too big!\n", + reg, len); + return -EINVAL; + } + buf[0] = reg; memcpy(&buf[1], v, len); diff --git a/drivers/media/dvb-frontends/mt312.c b/drivers/media/dvb-frontends/mt312.c index ec388c1d6913..a74ac0ddb833 100644 --- a/drivers/media/dvb-frontends/mt312.c +++ b/drivers/media/dvb-frontends/mt312.c @@ -36,6 +36,8 @@ #include "mt312_priv.h" #include "mt312.h" +/* Max transfer size done by I2C transfer functions */ +#define MAX_XFER_SIZE 64 struct mt312_state { struct i2c_adapter *i2c; @@ -96,9 +98,15 @@ static int mt312_write(struct mt312_state *state, const enum mt312_reg_addr reg, const u8 *src, const size_t count) { int ret; - u8 buf[count + 1]; + u8 buf[MAX_XFER_SIZE]; struct i2c_msg msg; + if (1 + count > sizeof(buf)) { + printk(KERN_WARNING + "mt312: write: len=%zd is too big!\n", count); + return -EINVAL; + } + if (debug) { int i; dprintk("W(%d):", reg & 0x7f); diff --git a/drivers/media/dvb-frontends/nxt200x.c b/drivers/media/dvb-frontends/nxt200x.c index 8e288940a61f..fbca9856313a 100644 --- a/drivers/media/dvb-frontends/nxt200x.c +++ b/drivers/media/dvb-frontends/nxt200x.c @@ -39,6 +39,9 @@ */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +/* Max transfer size done by I2C transfer functions */ +#define MAX_XFER_SIZE 64 + #define NXT2002_DEFAULT_FIRMWARE "dvb-fe-nxt2002.fw" #define NXT2004_DEFAULT_FIRMWARE "dvb-fe-nxt2004.fw" #define CRC_CCIT_MASK 0x1021 @@ -95,10 +98,16 @@ static int i2c_readbytes(struct nxt200x_state *state, u8 addr, u8 *buf, u8 len) static int nxt200x_writebytes (struct nxt200x_state* state, u8 reg, const u8 *buf, u8 len) { - u8 buf2 [len+1]; + u8 buf2[MAX_XFER_SIZE]; int err; struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf2, .len = len + 1 }; + if (1 + len > sizeof(buf2)) { + pr_warn("%s: i2c wr reg=%04x: len=%d is too big!\n", + __func__, reg, len); + return -EINVAL; + } + buf2[0] = reg; memcpy(&buf2[1], buf, len); diff --git a/drivers/media/dvb-frontends/stb6100.c b/drivers/media/dvb-frontends/stb6100.c index 45f9523f968f..cea175d19890 100644 --- a/drivers/media/dvb-frontends/stb6100.c +++ b/drivers/media/dvb-frontends/stb6100.c @@ -31,6 +31,8 @@ static unsigned int verbose; module_param(verbose, int, 0644); +/* Max transfer size done by I2C transfer functions */ +#define MAX_XFER_SIZE 64 #define FE_ERROR 0 #define FE_NOTICE 1 @@ -183,7 +185,7 @@ static int stb6100_read_reg(struct stb6100_state *state, u8 reg) static int stb6100_write_reg_range(struct stb6100_state *state, u8 buf[], int start, int len) { int rc; - u8 cmdbuf[len + 1]; + u8 cmdbuf[MAX_XFER_SIZE]; struct i2c_msg msg = { .addr = state->config->tuner_address, .flags = 0, @@ -191,6 +193,13 @@ static int stb6100_write_reg_range(struct stb6100_state *state, u8 buf[], int st .len = len + 1 }; + if (1 + len > sizeof(buf)) { + printk(KERN_WARNING + "%s: i2c wr: len=%d is too big!\n", + KBUILD_MODNAME, len); + return -EINVAL; + } + if (unlikely(start < 1 || start + len > STB6100_NUMREGS)) { dprintk(verbose, FE_ERROR, 1, "Invalid register range %d:%d", start, len); diff --git a/drivers/media/dvb-frontends/stv6110.c b/drivers/media/dvb-frontends/stv6110.c index 20b5fa92c53e..b1425830a24e 100644 --- a/drivers/media/dvb-frontends/stv6110.c +++ b/drivers/media/dvb-frontends/stv6110.c @@ -30,6 +30,9 @@ #include "stv6110.h" +/* Max transfer size done by I2C transfer functions */ +#define MAX_XFER_SIZE 64 + static int debug; struct stv6110_priv { @@ -68,7 +71,7 @@ static int stv6110_write_regs(struct dvb_frontend *fe, u8 buf[], { struct stv6110_priv *priv = fe->tuner_priv; int rc; - u8 cmdbuf[len + 1]; + u8 cmdbuf[MAX_XFER_SIZE]; struct i2c_msg msg = { .addr = priv->i2c_address, .flags = 0, @@ -78,6 +81,13 @@ static int stv6110_write_regs(struct dvb_frontend *fe, u8 buf[], dprintk("%s\n", __func__); + if (1 + len > sizeof(cmdbuf)) { + printk(KERN_WARNING + "%s: i2c wr: len=%d is too big!\n", + KBUILD_MODNAME, len); + return -EINVAL; + } + if (start + len > 8) return -EINVAL; diff --git a/drivers/media/dvb-frontends/stv6110x.c b/drivers/media/dvb-frontends/stv6110x.c index f36cab12bdc7..e66154e5c1d7 100644 --- a/drivers/media/dvb-frontends/stv6110x.c +++ b/drivers/media/dvb-frontends/stv6110x.c @@ -32,6 +32,9 @@ #include "stv6110x.h" #include "stv6110x_priv.h" +/* Max transfer size done by I2C transfer functions */ +#define MAX_XFER_SIZE 64 + static unsigned int verbose; module_param(verbose, int, 0644); MODULE_PARM_DESC(verbose, "Set Verbosity level"); @@ -61,7 +64,8 @@ static int stv6110x_write_regs(struct stv6110x_state *stv6110x, int start, u8 da { int ret; const struct stv6110x_config *config = stv6110x->config; - u8 buf[len + 1]; + u8 buf[MAX_XFER_SIZE]; + struct i2c_msg msg = { .addr = config->addr, .flags = 0, @@ -69,6 +73,13 @@ static int stv6110x_write_regs(struct stv6110x_state *stv6110x, int start, u8 da .len = len + 1 }; + if (1 + len > sizeof(buf)) { + printk(KERN_WARNING + "%s: i2c wr: len=%d is too big!\n", + KBUILD_MODNAME, len); + return -EINVAL; + } + if (start + len > 8) return -EINVAL; diff --git a/drivers/media/dvb-frontends/tda18271c2dd.c b/drivers/media/dvb-frontends/tda18271c2dd.c index d281f77d5c28..2c54586ac07f 100644 --- a/drivers/media/dvb-frontends/tda18271c2dd.c +++ b/drivers/media/dvb-frontends/tda18271c2dd.c @@ -34,6 +34,9 @@ #include "dvb_frontend.h" #include "tda18271c2dd.h" +/* Max transfer size done by I2C transfer functions */ +#define MAX_XFER_SIZE 64 + struct SStandardParam { s32 m_IFFrequency; u32 m_BandWidth; @@ -139,11 +142,18 @@ static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len) static int WriteRegs(struct tda_state *state, u8 SubAddr, u8 *Regs, u16 nRegs) { - u8 data[nRegs+1]; + u8 data[MAX_XFER_SIZE]; + + if (1 + nRegs > sizeof(data)) { + printk(KERN_WARNING + "%s: i2c wr: len=%d is too big!\n", + KBUILD_MODNAME, nRegs); + return -EINVAL; + } data[0] = SubAddr; memcpy(data + 1, Regs, nRegs); - return i2c_write(state->i2c, state->adr, data, nRegs+1); + return i2c_write(state->i2c, state->adr, data, nRegs + 1); } static int WriteReg(struct tda_state *state, u8 SubAddr, u8 Reg) diff --git a/drivers/media/dvb-frontends/zl10039.c b/drivers/media/dvb-frontends/zl10039.c index eff9c5fde50a..91b6b2e9b792 100644 --- a/drivers/media/dvb-frontends/zl10039.c +++ b/drivers/media/dvb-frontends/zl10039.c @@ -30,6 +30,9 @@ static int debug; +/* Max transfer size done by I2C transfer functions */ +#define MAX_XFER_SIZE 64 + #define dprintk(args...) \ do { \ if (debug) \ @@ -98,7 +101,7 @@ static int zl10039_write(struct zl10039_state *state, const enum zl10039_reg_addr reg, const u8 *src, const size_t count) { - u8 buf[count + 1]; + u8 buf[MAX_XFER_SIZE]; struct i2c_msg msg = { .addr = state->i2c_addr, .flags = 0, @@ -106,6 +109,13 @@ static int zl10039_write(struct zl10039_state *state, .len = count + 1, }; + if (1 + count > sizeof(buf)) { + printk(KERN_WARNING + "%s: i2c wr reg=%04x: len=%zd is too big!\n", + KBUILD_MODNAME, reg, count); + return -EINVAL; + } + dprintk("%s\n", __func__); /* Write register address and data in one go */ buf[0] = reg; -- cgit v1.2.3 From ffc0c180edbae4149206ad5eb8485d3040cb350e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 2 Nov 2013 04:29:42 -0300 Subject: media: s5h1420: Don't use dynamic static allocation commit 9736a89dafe07359d9c86bf9c3b815a250b354bc upstream. Dynamic static allocation is evil, as Kernel stack is too low, and compilation complains about it on some archs: drivers/media/dvb-frontends/s5h1420.c:851:1: warning: 's5h1420_tuner_i2c_tuner_xfer' uses dynamic stack allocation [enabled by default] Instead, let's enforce a limit for the buffer. In the specific case of this frontend, only ttpci uses it. The maximum number of messages there is two, on I2C read operations. As the logic can add an extra operation, change the size to 3. Signed-off-by: Mauro Carvalho Chehab Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/dvb-frontends/s5h1420.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/media/dvb-frontends/s5h1420.c b/drivers/media/dvb-frontends/s5h1420.c index e2fec9ebf947..93eeaf7118fd 100644 --- a/drivers/media/dvb-frontends/s5h1420.c +++ b/drivers/media/dvb-frontends/s5h1420.c @@ -836,9 +836,16 @@ static u32 s5h1420_tuner_i2c_func(struct i2c_adapter *adapter) static int s5h1420_tuner_i2c_tuner_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num) { struct s5h1420_state *state = i2c_get_adapdata(i2c_adap); - struct i2c_msg m[1 + num]; + struct i2c_msg m[3]; u8 tx_open[2] = { CON_1, state->CON_1_val | 1 }; /* repeater stops once there was a stop condition */ + if (1 + num > ARRAY_SIZE(m)) { + printk(KERN_WARNING + "%s: i2c xfer: num=%d is too big!\n", + KBUILD_MODNAME, num); + return -EOPNOTSUPP; + } + memset(m, 0, sizeof(struct i2c_msg) * (1 + num)); m[0].addr = state->config->demod_address; @@ -847,7 +854,7 @@ static int s5h1420_tuner_i2c_tuner_xfer(struct i2c_adapter *i2c_adap, struct i2c memcpy(&m[1], msg, sizeof(struct i2c_msg) * num); - return i2c_transfer(state->i2c, m, 1+num) == 1 + num ? num : -EIO; + return i2c_transfer(state->i2c, m, 1 + num) == 1 + num ? num : -EIO; } static struct i2c_algorithm s5h1420_tuner_i2c_algo = { -- cgit v1.2.3 From d8f0a31aa3ccf94e1902ff6c0c68410e3b68ecca Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 18 Jun 2013 17:40:44 +0100 Subject: X.509: Remove certificate date checks commit 124df926090b32a998483f6e43ebeccdbe5b5302 upstream. Remove the certificate date checks that are performed when a certificate is parsed. There are two checks: a valid from and a valid to. The first check is causing a lot of problems with system clocks that don't keep good time and the second places an implicit expiry date upon the kernel when used for module signing, so do we really need them? Signed-off-by: David Howells cc: David Woodhouse cc: Rusty Russell cc: Josh Boyer cc: Alexander Holler Signed-off-by: Greg Kroah-Hartman --- crypto/asymmetric_keys/x509_public_key.c | 38 -------------------------------- 1 file changed, 38 deletions(-) diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c index 06007f0e880c..52222a2f34ba 100644 --- a/crypto/asymmetric_keys/x509_public_key.c +++ b/crypto/asymmetric_keys/x509_public_key.c @@ -106,7 +106,6 @@ error_no_sig: static int x509_key_preparse(struct key_preparsed_payload *prep) { struct x509_certificate *cert; - struct tm now; size_t srlen, sulen; char *desc = NULL; int ret; @@ -137,43 +136,6 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) goto error_free_cert; } - time_to_tm(CURRENT_TIME.tv_sec, 0, &now); - pr_devel("Now: %04ld-%02d-%02d %02d:%02d:%02d\n", - now.tm_year + 1900, now.tm_mon + 1, now.tm_mday, - now.tm_hour, now.tm_min, now.tm_sec); - if (now.tm_year < cert->valid_from.tm_year || - (now.tm_year == cert->valid_from.tm_year && - (now.tm_mon < cert->valid_from.tm_mon || - (now.tm_mon == cert->valid_from.tm_mon && - (now.tm_mday < cert->valid_from.tm_mday || - (now.tm_mday == cert->valid_from.tm_mday && - (now.tm_hour < cert->valid_from.tm_hour || - (now.tm_hour == cert->valid_from.tm_hour && - (now.tm_min < cert->valid_from.tm_min || - (now.tm_min == cert->valid_from.tm_min && - (now.tm_sec < cert->valid_from.tm_sec - ))))))))))) { - pr_warn("Cert %s is not yet valid\n", cert->fingerprint); - ret = -EKEYREJECTED; - goto error_free_cert; - } - if (now.tm_year > cert->valid_to.tm_year || - (now.tm_year == cert->valid_to.tm_year && - (now.tm_mon > cert->valid_to.tm_mon || - (now.tm_mon == cert->valid_to.tm_mon && - (now.tm_mday > cert->valid_to.tm_mday || - (now.tm_mday == cert->valid_to.tm_mday && - (now.tm_hour > cert->valid_to.tm_hour || - (now.tm_hour == cert->valid_to.tm_hour && - (now.tm_min > cert->valid_to.tm_min || - (now.tm_min == cert->valid_to.tm_min && - (now.tm_sec > cert->valid_to.tm_sec - ))))))))))) { - pr_warn("Cert %s has expired\n", cert->fingerprint); - ret = -EKEYEXPIRED; - goto error_free_cert; - } - cert->pub->algo = x509_public_key_algorithms[cert->pkey_algo]; cert->pub->id_type = PKEY_ID_X509; -- cgit v1.2.3 From 405052f57cb5f3b7e6042c36c952d3980375fd5b Mon Sep 17 00:00:00 2001 From: Stefan Achatz Date: Mon, 28 Oct 2013 18:52:03 +0100 Subject: HID: roccat: add new device return value commit 14fc4290df2fb94a28f39dab9ed32feaa5527bef upstream. Ryos uses a new return value for critical errors, others have been confirmed. Signed-off-by: Stefan Achatz Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/hid/hid-roccat-common.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/hid/hid-roccat-common.c b/drivers/hid/hid-roccat-common.c index 74f704032627..e84089998900 100644 --- a/drivers/hid/hid-roccat-common.c +++ b/drivers/hid/hid-roccat-common.c @@ -65,10 +65,11 @@ int roccat_common2_send(struct usb_device *usb_dev, uint report_id, EXPORT_SYMBOL_GPL(roccat_common2_send); enum roccat_common2_control_states { - ROCCAT_COMMON_CONTROL_STATUS_OVERLOAD = 0, + ROCCAT_COMMON_CONTROL_STATUS_CRITICAL = 0, ROCCAT_COMMON_CONTROL_STATUS_OK = 1, ROCCAT_COMMON_CONTROL_STATUS_INVALID = 2, - ROCCAT_COMMON_CONTROL_STATUS_WAIT = 3, + ROCCAT_COMMON_CONTROL_STATUS_BUSY = 3, + ROCCAT_COMMON_CONTROL_STATUS_CRITICAL_NEW = 4, }; static int roccat_common2_receive_control_status(struct usb_device *usb_dev) @@ -88,13 +89,12 @@ static int roccat_common2_receive_control_status(struct usb_device *usb_dev) switch (control.value) { case ROCCAT_COMMON_CONTROL_STATUS_OK: return 0; - case ROCCAT_COMMON_CONTROL_STATUS_WAIT: + case ROCCAT_COMMON_CONTROL_STATUS_BUSY: msleep(500); continue; case ROCCAT_COMMON_CONTROL_STATUS_INVALID: - - case ROCCAT_COMMON_CONTROL_STATUS_OVERLOAD: - /* seems to be critical - replug necessary */ + case ROCCAT_COMMON_CONTROL_STATUS_CRITICAL: + case ROCCAT_COMMON_CONTROL_STATUS_CRITICAL_NEW: return -EINVAL; default: dev_err(&usb_dev->dev, -- cgit v1.2.3 From 95f5725870267aa819025237a14c2ccacd78b85b Mon Sep 17 00:00:00 2001 From: Stefan Achatz Date: Sun, 3 Nov 2013 06:25:33 +0100 Subject: HID: roccat: fix Coverity CID 141438 commit 7be63f20b00840a6f1c718dcee00855688d64acd upstream. Add missing switch breaks. Signed-off-by: Stefan Achatz Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/hid/hid-roccat-kovaplus.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/hid/hid-roccat-kovaplus.c b/drivers/hid/hid-roccat-kovaplus.c index b8b37789b864..2c571dadf062 100644 --- a/drivers/hid/hid-roccat-kovaplus.c +++ b/drivers/hid/hid-roccat-kovaplus.c @@ -577,9 +577,13 @@ static void kovaplus_keep_values_up_to_date(struct kovaplus_device *kovaplus, break; case KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_CPI: kovaplus->actual_cpi = kovaplus_convert_event_cpi(button_report->data1); + break; case KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_SENSITIVITY: kovaplus->actual_x_sensitivity = button_report->data1; kovaplus->actual_y_sensitivity = button_report->data2; + break; + default: + break; } } -- cgit v1.2.3 From 4370a0d55bc5f14e02b2e79b8bd5ef8f713e4a0c Mon Sep 17 00:00:00 2001 From: Stefan Achatz Date: Fri, 8 Nov 2013 14:12:00 +0100 Subject: HID: roccat: add missing special driver declarations commit e078809df5611600965f4d3420c3256260fc3e3d upstream. Forgot two special driver declarations and sorted the list. Signed-off-by: Stefan Achatz Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/hid/hid-core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 43831f18e4ca..d17988d178d0 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1751,12 +1751,14 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) }, { HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_KEYBOARD) }, #if IS_ENABLED(CONFIG_HID_ROCCAT) - { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONE) }, { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ARVO) }, { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKU) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKUFX) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONE) }, { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) }, { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPURE) }, { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPURE_OPTICAL) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEXTD) }, { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KOVAPLUS) }, { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_LUA) }, { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) }, -- cgit v1.2.3 From bb4522d30c7d110d33cece574f50db128016a69e Mon Sep 17 00:00:00 2001 From: Tristan Rice Date: Tue, 12 Nov 2013 19:06:23 +0100 Subject: HID: enable Mayflash USB Gamecube Adapter commit e17f5d7667c5414b8f12a93ef14aae0824bd2beb upstream. This is a patch that adds the new Mayflash Gamecube Controller to USB adapter (ID 1a34:f705 ACRUX) to the ACRUX driver (drivers/hid/hid-axff.c) with full force feedback support. Signed-off-by: Tristan Rice Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/hid/hid-axff.c | 3 ++- drivers/hid/hid-core.c | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/hid/hid-axff.c b/drivers/hid/hid-axff.c index 64ab94a55aa7..a594e478a1e2 100644 --- a/drivers/hid/hid-axff.c +++ b/drivers/hid/hid-axff.c @@ -95,7 +95,7 @@ static int axff_init(struct hid_device *hid) } } - if (field_count < 4) { + if (field_count < 4 && hid->product != 0xf705) { hid_err(hid, "not enough fields in the report: %d\n", field_count); return -ENODEV; @@ -180,6 +180,7 @@ static void ax_remove(struct hid_device *hdev) static const struct hid_device_id ax_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0x0802), }, + { HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0xf705), }, { } }; MODULE_DEVICE_TABLE(hid, ax_devices); diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index d17988d178d0..c4e5cdfa5d24 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1562,6 +1562,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D) }, { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_RP_649) }, { HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0x0802) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0xf705) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICMOUSE) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICTRACKPAD) }, -- cgit v1.2.3 From b18cd40e6228da53f2781f37f9b94a1930c6ee9c Mon Sep 17 00:00:00 2001 From: Nanno Langstraat Date: Mon, 14 Oct 2013 16:07:15 +0200 Subject: HID: apple: option to swap the 'Option' ("Alt") and 'Command' ("Flag") keys. commit 43c831468b3d26dbe8f2e061ccaf1abaf9cc1b8b upstream. Use case: people who use both Apple and PC keyboards regularly, and desire to keep&use their PC muscle memory. A particular use case: an Apple compact external keyboard connected to a PC laptop. (This use case can't be covered well by X.org key remappings etc.) Signed-off-by: Nanno Langstraat Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/hid/hid-apple.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index c7710b5c69af..d54e1d0a4b14 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c @@ -46,6 +46,12 @@ module_param(iso_layout, uint, 0644); MODULE_PARM_DESC(iso_layout, "Enable/Disable hardcoded ISO-layout of the keyboard. " "(0 = disabled, [1] = enabled)"); +static unsigned int swap_opt_cmd = 0; +module_param(swap_opt_cmd, uint, 0644); +MODULE_PARM_DESC(swap_opt_cmd, "Swap the Option (\"Alt\") and Command (\"Flag\") keys. " + "(For people who want to keep Windows PC keyboard muscle memory. " + "[0] = as-is, Mac layout. 1 = swapped, Windows layout.)"); + struct apple_sc { unsigned long quirks; unsigned int fn_on; @@ -150,6 +156,14 @@ static const struct apple_key_translation apple_iso_keyboard[] = { { } }; +static const struct apple_key_translation swapped_option_cmd_keys[] = { + { KEY_LEFTALT, KEY_LEFTMETA }, + { KEY_LEFTMETA, KEY_LEFTALT }, + { KEY_RIGHTALT, KEY_RIGHTMETA }, + { KEY_RIGHTMETA,KEY_RIGHTALT }, + { } +}; + static const struct apple_key_translation *apple_find_translation( const struct apple_key_translation *table, u16 from) { @@ -242,6 +256,14 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input, } } + if (swap_opt_cmd) { + trans = apple_find_translation(swapped_option_cmd_keys, usage->code); + if (trans) { + input_event(input, usage->type, trans->to, value); + return 1; + } + } + return 0; } -- cgit v1.2.3 From 78c3ae2cb101bc10f3b9cc851e826484246088e1 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 27 Sep 2013 18:09:54 -0400 Subject: drm/radeon: use 64-bit math to calculate CTS values for audio (v2) commit 062c2e4363451d49ef840232fe65e8bff0dde2a5 upstream. Avoid losing precision. See bug: https://bugs.freedesktop.org/show_bug.cgi?id=69675 v2: fix math as per Anssi's comments. Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/r600_hdmi.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c index 0efe2a93ca97..322e42737ef7 100644 --- a/drivers/gpu/drm/radeon/r600_hdmi.c +++ b/drivers/gpu/drm/radeon/r600_hdmi.c @@ -75,8 +75,15 @@ static const struct radeon_hdmi_acr r600_hdmi_predefined_acr[] = { */ static void r600_hdmi_calc_cts(uint32_t clock, int *CTS, int N, int freq) { - if (*CTS == 0) - *CTS = clock * N / (128 * freq) * 1000; + u64 n; + u32 d; + + if (*CTS == 0) { + n = (u64)clock * (u64)N * 1000ULL; + d = 128 * freq; + do_div(n, d); + *CTS = n; + } DRM_DEBUG("Using ACR timing N=%d CTS=%d for frequency %d\n", N, *CTS, freq); } -- cgit v1.2.3 From eebf839b51416e440d40660d00a8ea465bfa74c6 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 27 Sep 2013 18:19:42 -0400 Subject: drm/radeon: fix N/CTS clock matching for audio commit e7d12c2f98ae1e68c7298e5028048d150fa553a1 upstream. The drm code that calculates the 1001 clocks rounds up rather than truncating. This allows the table to match properly on those modes. See bug: https://bugs.freedesktop.org/show_bug.cgi?id=69675 Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/r600_hdmi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c index 322e42737ef7..1c41309b027a 100644 --- a/drivers/gpu/drm/radeon/r600_hdmi.c +++ b/drivers/gpu/drm/radeon/r600_hdmi.c @@ -57,15 +57,15 @@ enum r600_hdmi_iec_status_bits { static const struct radeon_hdmi_acr r600_hdmi_predefined_acr[] = { /* 32kHz 44.1kHz 48kHz */ /* Clock N CTS N CTS N CTS */ - { 25174, 4576, 28125, 7007, 31250, 6864, 28125 }, /* 25,20/1.001 MHz */ + { 25175, 4576, 28125, 7007, 31250, 6864, 28125 }, /* 25,20/1.001 MHz */ { 25200, 4096, 25200, 6272, 28000, 6144, 25200 }, /* 25.20 MHz */ { 27000, 4096, 27000, 6272, 30000, 6144, 27000 }, /* 27.00 MHz */ { 27027, 4096, 27027, 6272, 30030, 6144, 27027 }, /* 27.00*1.001 MHz */ { 54000, 4096, 54000, 6272, 60000, 6144, 54000 }, /* 54.00 MHz */ { 54054, 4096, 54054, 6272, 60060, 6144, 54054 }, /* 54.00*1.001 MHz */ - { 74175, 11648, 210937, 17836, 234375, 11648, 140625 }, /* 74.25/1.001 MHz */ + { 74176, 11648, 210937, 17836, 234375, 11648, 140625 }, /* 74.25/1.001 MHz */ { 74250, 4096, 74250, 6272, 82500, 6144, 74250 }, /* 74.25 MHz */ - { 148351, 11648, 421875, 8918, 234375, 5824, 140625 }, /* 148.50/1.001 MHz */ + { 148352, 11648, 421875, 8918, 234375, 5824, 140625 }, /* 148.50/1.001 MHz */ { 148500, 4096, 148500, 6272, 165000, 6144, 148500 }, /* 148.50 MHz */ { 0, 4096, 0, 6272, 0, 6144, 0 } /* Other */ }; -- cgit v1.2.3 From 26f99321a04b01d59cedc434788830fd31b3c7d9 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 27 Sep 2013 18:22:15 -0400 Subject: drm/radeon: use hw generated CTS/N values for audio commit ee0fec312a1c4e26f255955da942562cd8908a4b upstream. Use the hw generated values rather than calculating them in the driver. There may be some older r6xx asics where this doesn't work correctly. This remains to be seen. See bug: https://bugs.freedesktop.org/show_bug.cgi?id=69675 Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/evergreen_hdmi.c | 3 +-- drivers/gpu/drm/radeon/r600_hdmi.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/radeon/evergreen_hdmi.c b/drivers/gpu/drm/radeon/evergreen_hdmi.c index bb9ea3641312..067cc1fc48e5 100644 --- a/drivers/gpu/drm/radeon/evergreen_hdmi.c +++ b/drivers/gpu/drm/radeon/evergreen_hdmi.c @@ -219,8 +219,7 @@ void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode /* fglrx clears sth in AFMT_AUDIO_PACKET_CONTROL2 here */ WREG32(HDMI_ACR_PACKET_CONTROL + offset, - HDMI_ACR_AUTO_SEND | /* allow hw to sent ACR packets when required */ - HDMI_ACR_SOURCE); /* select SW CTS value */ + HDMI_ACR_AUTO_SEND); /* allow hw to sent ACR packets when required */ evergreen_hdmi_update_ACR(encoder, mode->clock); diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c index 1c41309b027a..7b3e1f1e8fb6 100644 --- a/drivers/gpu/drm/radeon/r600_hdmi.c +++ b/drivers/gpu/drm/radeon/r600_hdmi.c @@ -320,8 +320,7 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod } WREG32(HDMI0_ACR_PACKET_CONTROL + offset, - HDMI0_ACR_AUTO_SEND | /* allow hw to sent ACR packets when required */ - HDMI0_ACR_SOURCE); /* select SW CTS value */ + HDMI0_ACR_AUTO_SEND); /* allow hw to sent ACR packets when required */ WREG32(HDMI0_VBI_PACKET_CONTROL + offset, HDMI0_NULL_SEND | /* send null packets when required */ -- cgit v1.2.3 From d2e99b2fc1056d2c5f4bf7fd691d37ba216c1455 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 10 Oct 2013 11:47:01 -0400 Subject: drm/radeon: re-enable sw ACR support on pre-DCE4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit b852c985010a77c850b7548d64bbb964ca462b02 upstream. HW ACR support may have issues on some older chips, so use SW ACR for now until we've tested further. Signed-off-by: Alex Deucher CC: Rafał Miłecki Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/r600_hdmi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c index 7b3e1f1e8fb6..635e8f2e84f7 100644 --- a/drivers/gpu/drm/radeon/r600_hdmi.c +++ b/drivers/gpu/drm/radeon/r600_hdmi.c @@ -320,6 +320,7 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod } WREG32(HDMI0_ACR_PACKET_CONTROL + offset, + HDMI0_ACR_SOURCE | /* select SW CTS value - XXX verify that hw CTS works on all families */ HDMI0_ACR_AUTO_SEND); /* allow hw to sent ACR packets when required */ WREG32(HDMI0_VBI_PACKET_CONTROL + offset, -- cgit v1.2.3 From a1daae5dbf42e8f4446c122a63a24fdb8b2c854b Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sun, 15 Sep 2013 11:37:17 +0300 Subject: iwlwifi: don't WARN on host commands sent when firmware is dead commit 8ca95995e64f5d270889badb3e449dca91106a2b upstream. This triggers automatic bug reports and add no valuable information. Print a simple error instead and drop the host command. Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/iwlwifi/iwl-trans.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 7a13790b5bfe..72d2ecce0b8d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -605,8 +605,10 @@ static inline int iwl_trans_send_cmd(struct iwl_trans *trans, { int ret; - WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE, - "%s bad state = %d", __func__, trans->state); + if (trans->state != IWL_TRANS_FW_ALIVE) { + IWL_ERR(trans, "%s bad state = %d", __func__, trans->state); + return -EIO; + } if (!(cmd->flags & CMD_ASYNC)) lock_map_acquire_read(&trans->sync_cmd_lockdep_map); -- cgit v1.2.3 From 78ab8cbc11ee095ec27d7f6edde91e2c3af1540d Mon Sep 17 00:00:00 2001 From: Michal Kubecek Date: Wed, 11 Sep 2013 10:17:27 +0200 Subject: netfilter: nf_conntrack: use RCU safe kfree for conntrack extensions commit c13a84a830a208fb3443628773c8ca0557773cc7 upstream. Commit 68b80f11 (netfilter: nf_nat: fix RCU races) introduced RCU protection for freeing extension data when reallocation moves them to a new location. We need the same protection when freeing them in nf_ct_ext_free() in order to prevent a use-after-free by other threads referencing a NAT extension data via bysource list. Signed-off-by: Michal Kubecek Signed-off-by: Pablo Neira Ayuso Signed-off-by: Greg Kroah-Hartman --- include/net/netfilter/nf_conntrack_extend.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/net/netfilter/nf_conntrack_extend.h b/include/net/netfilter/nf_conntrack_extend.h index 977bc8a46444..331310851cfb 100644 --- a/include/net/netfilter/nf_conntrack_extend.h +++ b/include/net/netfilter/nf_conntrack_extend.h @@ -80,7 +80,7 @@ static inline void nf_ct_ext_destroy(struct nf_conn *ct) static inline void nf_ct_ext_free(struct nf_conn *ct) { if (ct->ext) - kfree(ct->ext); + kfree_rcu(ct->ext, rcu); } /* Add this type, returns pointer to data or NULL. */ -- cgit v1.2.3 From d4e937777fa1a97b21916eecd7d7d9dd8534d3d1 Mon Sep 17 00:00:00 2001 From: Johannes Koch Date: Wed, 17 Jul 2013 14:28:16 -0300 Subject: media: cx23885: Fix TeVii S471 regression since introduction of ts2020 commit b43ea8068d2090cb1e44632c8a938ab40d2c7419 upstream. Patch to make TeVii S471 cards use the ts2020 tuner, since ds3000 driver no longer contains tuning code. Signed-off-by: Johannes Koch Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/pci/cx23885/cx23885-dvb.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/media/pci/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c index 9c5ed10b2c5e..bb291c661143 100644 --- a/drivers/media/pci/cx23885/cx23885-dvb.c +++ b/drivers/media/pci/cx23885/cx23885-dvb.c @@ -1249,6 +1249,10 @@ static int dvb_register(struct cx23885_tsport *port) fe0->dvb.frontend = dvb_attach(ds3000_attach, &tevii_ds3000_config, &i2c_bus->i2c_adap); + if (fe0->dvb.frontend != NULL) { + dvb_attach(ts2020_attach, fe0->dvb.frontend, + &tevii_ts2020_config, &i2c_bus->i2c_adap); + } break; case CX23885_BOARD_PROF_8000: i2c_bus = &dev->i2c_bus[0]; -- cgit v1.2.3 From 2c4805f3ae216cfd6fc2a386ea523d5a6eee6fdc Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 28 Jun 2013 08:05:06 -0700 Subject: iwl3945: better skb management in rx path commit 45fe142cefa864b685615bcb930159f6749c3667 upstream. Steinar reported reallocations of skb->head with IPv6, leading to a warning in skb_try_coalesce() It turns out iwl3945 has several problems : 1) skb->truesize is underestimated. We really consume PAGE_SIZE bytes for a fragment, not the frame length. 2) 128 bytes of initial headroom is a bit low and forces reallocations. 3) We can avoid consuming a full page for small enough frames. Reported-by: Steinar H. Gunderson Signed-off-by: Eric Dumazet Cc: Paul Stewart Acked-by: Stanislaw Gruszka Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/iwlegacy/3945.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/iwlegacy/3945.c b/drivers/net/wireless/iwlegacy/3945.c index dc1e6da9976a..9a5f36e5c864 100644 --- a/drivers/net/wireless/iwlegacy/3945.c +++ b/drivers/net/wireless/iwlegacy/3945.c @@ -462,6 +462,8 @@ il3945_is_network_packet(struct il_priv *il, struct ieee80211_hdr *header) } } +#define SMALL_PACKET_SIZE 256 + static void il3945_pass_packet_to_mac80211(struct il_priv *il, struct il_rx_buf *rxb, struct ieee80211_rx_status *stats) @@ -470,14 +472,13 @@ il3945_pass_packet_to_mac80211(struct il_priv *il, struct il_rx_buf *rxb, struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)IL_RX_DATA(pkt); struct il3945_rx_frame_hdr *rx_hdr = IL_RX_HDR(pkt); struct il3945_rx_frame_end *rx_end = IL_RX_END(pkt); - u16 len = le16_to_cpu(rx_hdr->len); + u32 len = le16_to_cpu(rx_hdr->len); struct sk_buff *skb; __le16 fc = hdr->frame_control; + u32 fraglen = PAGE_SIZE << il->hw_params.rx_page_order; /* We received data from the HW, so stop the watchdog */ - if (unlikely - (len + IL39_RX_FRAME_SIZE > - PAGE_SIZE << il->hw_params.rx_page_order)) { + if (unlikely(len + IL39_RX_FRAME_SIZE > fraglen)) { D_DROP("Corruption detected!\n"); return; } @@ -488,26 +489,32 @@ il3945_pass_packet_to_mac80211(struct il_priv *il, struct il_rx_buf *rxb, return; } - skb = dev_alloc_skb(128); + skb = dev_alloc_skb(SMALL_PACKET_SIZE); if (!skb) { IL_ERR("dev_alloc_skb failed\n"); return; } if (!il3945_mod_params.sw_crypto) - il_set_decrypted_flag(il, (struct ieee80211_hdr *)rxb_addr(rxb), + il_set_decrypted_flag(il, (struct ieee80211_hdr *)pkt, le32_to_cpu(rx_end->status), stats); - skb_add_rx_frag(skb, 0, rxb->page, - (void *)rx_hdr->payload - (void *)pkt, len, - len); - + /* If frame is small enough to fit into skb->head, copy it + * and do not consume a full page + */ + if (len <= SMALL_PACKET_SIZE) { + memcpy(skb_put(skb, len), rx_hdr->payload, len); + } else { + skb_add_rx_frag(skb, 0, rxb->page, + (void *)rx_hdr->payload - (void *)pkt, len, + fraglen); + il->alloc_rxb_page--; + rxb->page = NULL; + } il_update_stats(il, false, fc, len); memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats)); ieee80211_rx(il->hw, skb); - il->alloc_rxb_page--; - rxb->page = NULL; } #define IL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6) -- cgit v1.2.3 From 69848a721c5a84b63f1801e340cc2e6cdde17c61 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Mon, 1 Jul 2013 14:19:30 +0200 Subject: iwl4965: better skb management in rx path commit c1de4a9557d9e25e41fc4ba034b9659152205539 upstream. 4965 version of Eric patch "iwl3945: better skb management in rx path". It fixes several problems : 1) skb->truesize is underestimated. We really consume PAGE_SIZE bytes for a fragment, not the frame length. 2) 128 bytes of initial headroom is a bit low and forces reallocations. 3) We can avoid consuming a full page for small enough frames. Signed-off-by: Stanislaw Gruszka Acked-by: Eric Dumazet Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/iwlegacy/4965-mac.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index a8eff95ee677..d2586f09f45c 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c @@ -574,9 +574,11 @@ il4965_translate_rx_status(struct il_priv *il, u32 decrypt_in) return decrypt_out; } +#define SMALL_PACKET_SIZE 256 + static void il4965_pass_packet_to_mac80211(struct il_priv *il, struct ieee80211_hdr *hdr, - u16 len, u32 ampdu_status, struct il_rx_buf *rxb, + u32 len, u32 ampdu_status, struct il_rx_buf *rxb, struct ieee80211_rx_status *stats) { struct sk_buff *skb; @@ -593,21 +595,25 @@ il4965_pass_packet_to_mac80211(struct il_priv *il, struct ieee80211_hdr *hdr, il_set_decrypted_flag(il, hdr, ampdu_status, stats)) return; - skb = dev_alloc_skb(128); + skb = dev_alloc_skb(SMALL_PACKET_SIZE); if (!skb) { IL_ERR("dev_alloc_skb failed\n"); return; } - skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len, - len); + if (len <= SMALL_PACKET_SIZE) { + memcpy(skb_put(skb, len), hdr, len); + } else { + skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), + len, PAGE_SIZE << il->hw_params.rx_page_order); + il->alloc_rxb_page--; + rxb->page = NULL; + } il_update_stats(il, false, fc, len); memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats)); ieee80211_rx(il->hw, skb); - il->alloc_rxb_page--; - rxb->page = NULL; } /* Called for N_RX (legacy ABG frames), or -- cgit v1.2.3 From 88a810def754d5516252b9a8b9efc34d875d399f Mon Sep 17 00:00:00 2001 From: Wei Liu Date: Mon, 2 Dec 2013 17:49:54 +0000 Subject: xen-netback: fix refcnt unbalance for 3.10 With the introduction of "xen-netback: Don't destroy the netdev until the vif is shut down" (upstream commit id 279f438e36), vif disconnect and free are separated. However in the backported version reference counting code was not correctly modified, and the reset of vif->irq was lost. If frontend goes through vif life cycle more than once the reference counting is skewed. This patch adds back the missing vif->irq reset line. It also moves several lines of the reference counting code to vif_free, so the moved code corresponds to the counterpart in vif_alloc, thus the reference counting is balanced. Signed-off-by: Wei Liu Acked-by: Ian Campbell Cc: Konrad Wilk Cc: David Vrabel Signed-off-by: Greg Kroah-Hartman --- drivers/net/xen-netback/interface.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index c4a2eb2cd8a0..540a796593a3 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@ -365,17 +365,19 @@ void xenvif_disconnect(struct xenvif *vif) if (netif_carrier_ok(vif->dev)) xenvif_carrier_off(vif); - atomic_dec(&vif->refcnt); - wait_event(vif->waiting_to_free, atomic_read(&vif->refcnt) == 0); - - if (vif->irq) + if (vif->irq) { unbind_from_irqhandler(vif->irq, vif); + vif->irq = 0; + } xen_netbk_unmap_frontend_rings(vif); } void xenvif_free(struct xenvif *vif) { + atomic_dec(&vif->refcnt); + wait_event(vif->waiting_to_free, atomic_read(&vif->refcnt) == 0); + unregister_netdev(vif->dev); free_netdev(vif->dev); -- cgit v1.2.3 From 538069756ce13f9d0e0ccb7a17b6935a0bfb7cad Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 4 Dec 2013 11:03:31 -0800 Subject: Linux 3.10.22 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index c0635fbab87f..001188ce8241 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 10 -SUBLEVEL = 21 +SUBLEVEL = 22 EXTRAVERSION = NAME = TOSSUG Baby Fish -- cgit v1.2.3 From 024abeeced731bf7cba90edad7e352bbc4ee1dd1 Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Tue, 5 Nov 2013 02:41:27 +0100 Subject: ipv6: fix headroom calculation in udp6_ufo_fragment [ Upstream commit 0e033e04c2678dbbe74a46b23fffb7bb918c288e ] Commit 1e2bd517c108816220f262d7954b697af03b5f9c ("udp6: Fix udp fragmentation for tunnel traffic.") changed the calculation if there is enough space to include a fragment header in the skb from a skb->mac_header dervived one to skb_headroom. Because we already peeled off the skb to transport_header this is wrong. Change this back to check if we have enough room before the mac_header. This fixes a panic Saran Neti reported. He used the tbf scheduler which skb_gso_segments the skb. The offsets get negative and we panic in memcpy because the skb was erroneously not expanded at the head. Reported-by: Saran Neti Cc: Pravin B Shelar Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv6/udp_offload.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c index d3cfaf9c7a08..76f165ef8d49 100644 --- a/net/ipv6/udp_offload.c +++ b/net/ipv6/udp_offload.c @@ -85,7 +85,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, /* Check if there is enough headroom to insert fragment header. */ tnl_hlen = skb_tnl_header_len(skb); - if (skb_headroom(skb) < (tnl_hlen + frag_hdr_sz)) { + if (skb->mac_header < (tnl_hlen + frag_hdr_sz)) { if (gso_pskb_expand_head(skb, tnl_hlen + frag_hdr_sz)) goto out; } -- cgit v1.2.3 From 99e9489477a4b5c90d64f82a40dbc9680c630b1c Mon Sep 17 00:00:00 2001 From: Amir Vadai Date: Thu, 7 Nov 2013 11:08:30 +0200 Subject: net/mlx4_en: Fixed crash when port type is changed [ Upstream commit 1ec4864b10171b0691ee196d7006ae56d2c153f2 ] timecounter_init() was was called only after first potential timecounter_read(). Moved mlx4_en_init_timestamp() before mlx4_en_init_netdev() Signed-off-by: Amir Vadai Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/mellanox/mlx4/en_main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/en_main.c b/drivers/net/ethernet/mellanox/mlx4/en_main.c index a5c9df07a7d0..c72e214eb47c 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_main.c @@ -264,6 +264,10 @@ static void *mlx4_en_add(struct mlx4_dev *dev) mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH) mdev->port_cnt++; + /* Initialize time stamp mechanism */ + if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_TS) + mlx4_en_init_timestamp(mdev); + mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH) { if (!dev->caps.comp_pool) { mdev->profile.prof[i].rx_ring_num = @@ -301,10 +305,6 @@ static void *mlx4_en_add(struct mlx4_dev *dev) mdev->pndev[i] = NULL; } - /* Initialize time stamp mechanism */ - if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_TS) - mlx4_en_init_timestamp(mdev); - return mdev; err_mr: -- cgit v1.2.3 From d9160deb040a6b6dbd467cd2a20d731155b742fd Mon Sep 17 00:00:00 2001 From: Andreas Henriksson Date: Thu, 7 Nov 2013 18:26:38 +0100 Subject: net: Fix "ip rule delete table 256" [ Upstream commit 13eb2ab2d33c57ebddc57437a7d341995fc9138c ] When trying to delete a table >= 256 using iproute2 the local table will be deleted. The table id is specified as a netlink attribute when it needs more then 8 bits and iproute2 then sets the table field to RT_TABLE_UNSPEC (0). Preconditions to matching the table id in the rule delete code doesn't seem to take the "table id in netlink attribute" into condition so the frh_get_table helper function never gets to do its job when matching against current rule. Use the helper function twice instead of peaking at the table value directly. Originally reported at: http://bugs.debian.org/724783 Reported-by: Nicolas HICHER Signed-off-by: Andreas Henriksson Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/fib_rules.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c index d5a9f8ead0d8..0e9131195eb0 100644 --- a/net/core/fib_rules.c +++ b/net/core/fib_rules.c @@ -445,7 +445,8 @@ static int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh) if (frh->action && (frh->action != rule->action)) continue; - if (frh->table && (frh_get_table(frh, tb) != rule->table)) + if (frh_get_table(frh, tb) && + (frh_get_table(frh, tb) != rule->table)) continue; if (tb[FRA_PRIORITY] && -- cgit v1.2.3 From ea136c0d81a94c812dbcf6edc21b6fb3c210b4ca Mon Sep 17 00:00:00 2001 From: Duan Jiong Date: Fri, 8 Nov 2013 09:56:53 +0800 Subject: ipv6: use rt6_get_dflt_router to get default router in rt6_route_rcv [ Upstream commit f104a567e673f382b09542a8dc3500aa689957b4 ] As the rfc 4191 said, the Router Preference and Lifetime values in a ::/0 Route Information Option should override the preference and lifetime values in the Router Advertisement header. But when the kernel deals with a ::/0 Route Information Option, the rt6_get_route_info() always return NULL, that means that overriding will not happen, because those default routers were added without flag RTF_ROUTEINFO in rt6_add_dflt_router(). In order to deal with that condition, we should call rt6_get_dflt_router when the prefix length is 0. Signed-off-by: Duan Jiong Acked-by: Hannes Frederic Sowa Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv6/route.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 548a1f7c1a29..5a8bf536026c 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -728,8 +728,11 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len, prefix = &prefix_buf; } - rt = rt6_get_route_info(net, prefix, rinfo->prefix_len, gwaddr, - dev->ifindex); + if (rinfo->prefix_len == 0) + rt = rt6_get_dflt_router(gwaddr, dev); + else + rt = rt6_get_route_info(net, prefix, rinfo->prefix_len, + gwaddr, dev->ifindex); if (rt && !lifetime) { ip6_del_rt(rt); -- cgit v1.2.3 From e688cd4d32cfbf0b5198ba95da428038e907e633 Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Fri, 8 Nov 2013 19:26:21 +0100 Subject: ipv6: protect for_each_sk_fl_rcu in mem_check with rcu_read_lock_bh [ Upstream commit f8c31c8f80dd882f7eb49276989a4078d33d67a7 ] Fixes a suspicious rcu derference warning. Cc: Florent Fourcot Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv6/ip6_flowlabel.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index 46e88433ec7d..f0ccdb787100 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c @@ -453,8 +453,10 @@ static int mem_check(struct sock *sk) if (room > FL_MAX_SIZE - FL_MAX_PER_SOCK) return 0; + rcu_read_lock_bh(); for_each_sk_fl_rcu(np, sfl) count++; + rcu_read_unlock_bh(); if (room <= 0 || ((count >= FL_MAX_PER_SOCK || -- cgit v1.2.3 From e29507fecb79c00ae76f9ef626d282af8b1f4225 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Mon, 11 Nov 2013 12:20:32 +0100 Subject: random32: fix off-by-one in seeding requirement [ Upstream commit 51c37a70aaa3f95773af560e6db3073520513912 ] For properly initialising the Tausworthe generator [1], we have a strict seeding requirement, that is, s1 > 1, s2 > 7, s3 > 15. Commit 697f8d0348 ("random32: seeding improvement") introduced a __seed() function that imposes boundary checks proposed by the errata paper [2] to properly ensure above conditions. However, we're off by one, as the function is implemented as: "return (x < m) ? x + m : x;", and called with __seed(X, 1), __seed(X, 7), __seed(X, 15). Thus, an unwanted seed of 1, 7, 15 would be possible, whereas the lower boundary should actually be of at least 2, 8, 16, just as GSL does. Fix this, as otherwise an initialization with an unwanted seed could have the effect that Tausworthe's PRNG properties cannot not be ensured. Note that this PRNG is *not* used for cryptography in the kernel. [1] http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme.ps [2] http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme2.ps Joint work with Hannes Frederic Sowa. Fixes: 697f8d0348a6 ("random32: seeding improvement") Cc: Stephen Hemminger Cc: Florian Weimer Cc: Theodore Ts'o Signed-off-by: Daniel Borkmann Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/linux/random.h | 6 +++--- lib/random32.c | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/include/linux/random.h b/include/linux/random.h index 6312dd9ba449..bf9085e89fb5 100644 --- a/include/linux/random.h +++ b/include/linux/random.h @@ -50,9 +50,9 @@ static inline void prandom_seed_state(struct rnd_state *state, u64 seed) { u32 i = (seed >> 32) ^ (seed << 10) ^ seed; - state->s1 = __seed(i, 1); - state->s2 = __seed(i, 7); - state->s3 = __seed(i, 15); + state->s1 = __seed(i, 2); + state->s2 = __seed(i, 8); + state->s3 = __seed(i, 16); } #ifdef CONFIG_ARCH_RANDOM diff --git a/lib/random32.c b/lib/random32.c index 52280d5526be..01e8890d1089 100644 --- a/lib/random32.c +++ b/lib/random32.c @@ -141,7 +141,7 @@ void prandom_seed(u32 entropy) */ for_each_possible_cpu (i) { struct rnd_state *state = &per_cpu(net_rand_state, i); - state->s1 = __seed(state->s1 ^ entropy, 1); + state->s1 = __seed(state->s1 ^ entropy, 2); } } EXPORT_SYMBOL(prandom_seed); @@ -158,9 +158,9 @@ static int __init prandom_init(void) struct rnd_state *state = &per_cpu(net_rand_state,i); #define LCG(x) ((x) * 69069) /* super-duper LCG */ - state->s1 = __seed(LCG(i + jiffies), 1); - state->s2 = __seed(LCG(state->s1), 7); - state->s3 = __seed(LCG(state->s2), 15); + state->s1 = __seed(LCG(i + jiffies), 2); + state->s2 = __seed(LCG(state->s1), 8); + state->s3 = __seed(LCG(state->s2), 16); /* "warm it up" */ prandom_u32_state(state); @@ -187,9 +187,9 @@ static int __init prandom_reseed(void) u32 seeds[3]; get_random_bytes(&seeds, sizeof(seeds)); - state->s1 = __seed(seeds[0], 1); - state->s2 = __seed(seeds[1], 7); - state->s3 = __seed(seeds[2], 15); + state->s1 = __seed(seeds[0], 2); + state->s2 = __seed(seeds[1], 8); + state->s3 = __seed(seeds[2], 16); /* mix it in */ prandom_u32_state(state); -- cgit v1.2.3 From e9a2fa2a6192f03f095772aa02cff12c60475b43 Mon Sep 17 00:00:00 2001 From: Veaceslav Falico Date: Tue, 12 Nov 2013 15:37:40 +0100 Subject: bonding: don't permit to use ARP monitoring in 802.3ad mode [ Upstream commit ec9f1d15db8185f63a2c3143dc1e90ba18541b08 ] Currently the ARP monitoring is not supported with 802.3ad, and it's prohibited to use it via the module params. However we still can set it afterwards via sysfs, cause we only check for *LB modes there. To fix this - add a check for 802.3ad mode in bonding_store_arp_interval. Signed-off-by: Veaceslav Falico CC: Jay Vosburgh CC: Andy Gospodarek Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/bonding/bond_sysfs.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index d7434e0a610e..50ddeb9c0480 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -537,8 +537,9 @@ static ssize_t bonding_store_arp_interval(struct device *d, goto out; } if (bond->params.mode == BOND_MODE_ALB || - bond->params.mode == BOND_MODE_TLB) { - pr_info("%s: ARP monitoring cannot be used with ALB/TLB. Only MII monitoring is supported on %s.\n", + bond->params.mode == BOND_MODE_TLB || + bond->params.mode == BOND_MODE_8023AD) { + pr_info("%s: ARP monitoring cannot be used with ALB/TLB/802.3ad. Only MII monitoring is supported on %s.\n", bond->dev->name, bond->dev->name); ret = -EINVAL; goto out; -- cgit v1.2.3 From 5a9b1ba637310f5bf1f684303dd5abdb65259357 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 12 Nov 2013 16:34:41 +0100 Subject: usbnet: fix status interrupt urb handling [ Upstream commit 52f48d0d9aaa621ffa5e08d79da99a3f8c93b848 ] Since commit 7b0c5f21f348a66de495868b8df0284e8dfd6bbf "sierra_net: keep status interrupt URB active", sierra_net triggers status interrupt polling before the net_device is opened (in order to properly receive the sync message response). To be able to receive further interrupts, the interrupt urb needs to be re-submitted, so this patch removes the bogus check for netif_running(). Signed-off-by: Felix Fietkau Tested-by: Dan Williams Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/usb/usbnet.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 06ee82f557d4..28f16ed6422d 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -206,9 +206,6 @@ static void intr_complete (struct urb *urb) break; } - if (!netif_running (dev->net)) - return; - status = usb_submit_urb (urb, GFP_ATOMIC); if (status != 0) netif_err(dev, timer, dev->net, -- cgit v1.2.3 From 2d02839a2b8439eab70e53401029c7a6c0629ffd Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Wed, 13 Nov 2013 11:03:39 +0200 Subject: 6lowpan: Uncompression of traffic class field was incorrect [ Upstream commit 1188f05497e7bd2f2614b99c54adfbe7413d5749 ] If priority/traffic class field in IPv6 header is set (seen when using ssh), the uncompression sets the TC and Flow fields incorrectly. Example: This is IPv6 header of a sent packet. Note the priority/TC (=1) in the first byte. 00000000: 61 00 00 00 00 2c 06 40 fe 80 00 00 00 00 00 00 00000010: 02 02 72 ff fe c6 42 10 fe 80 00 00 00 00 00 00 00000020: 02 1e ab ff fe 4c 52 57 This gets compressed like this in the sending side 00000000: 72 31 04 06 02 1e ab ff fe 4c 52 57 ec c2 00 16 00000010: aa 2d fe 92 86 4e be c6 .... In the receiving end, the packet gets uncompressed to this IPv6 header 00000000: 60 06 06 02 00 2a 1e 40 fe 80 00 00 00 00 00 00 00000010: 02 02 72 ff fe c6 42 10 fe 80 00 00 00 00 00 00 00000020: ab ff fe 4c 52 57 ec c2 First four bytes are set incorrectly and we have also lost two bytes from destination address. The fix is to switch the case values in switch statement when checking the TC field. Signed-off-by: Jukka Rissanen Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ieee802154/6lowpan.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c index 55e1fd5b3e56..31b127e8086b 100644 --- a/net/ieee802154/6lowpan.c +++ b/net/ieee802154/6lowpan.c @@ -862,7 +862,7 @@ lowpan_process_data(struct sk_buff *skb) * Traffic class carried in-line * ECN + DSCP (1 byte), Flow Label is elided */ - case 1: /* 10b */ + case 2: /* 10b */ if (lowpan_fetch_skb_u8(skb, &tmp)) goto drop; @@ -875,7 +875,7 @@ lowpan_process_data(struct sk_buff *skb) * Flow Label carried in-line * ECN + 2-bit Pad + Flow Label (3 bytes), DSCP is elided */ - case 2: /* 01b */ + case 1: /* 01b */ if (lowpan_fetch_skb_u8(skb, &tmp)) goto drop; -- cgit v1.2.3 From 4ccc92f8e5ae05dddd4cce8bee59cc37152b41cc Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Wed, 13 Nov 2013 14:00:39 +0800 Subject: tuntap: limit head length of skb allocated [ Upstream commit 96f8d9ecf227638c89f98ccdcdd50b569891976c ] We currently use hdr_len as a hint of head length which is advertised by guest. But when guest advertise a very big value, it can lead to an 64K+ allocating of kmalloc() which has a very high possibility of failure when host memory is fragmented or under heavy stress. The huge hdr_len also reduce the effect of zerocopy or even disable if a gso skb is linearized in guest. To solves those issues, this patch introduces an upper limit (PAGE_SIZE) of the head, which guarantees an order 0 allocation each time. Signed-off-by: Jason Wang Cc: Stefan Hajnoczi Cc: Michael S. Tsirkin Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/tun.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index b18ead556994..9ef85fea1d1e 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -1069,6 +1069,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, struct sk_buff *skb; size_t len = total_len, align = NET_SKB_PAD, linear; struct virtio_net_hdr gso = { 0 }; + int good_linear; int offset = 0; int copylen; bool zerocopy = false; @@ -1109,12 +1110,16 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, return -EINVAL; } + good_linear = SKB_MAX_HEAD(align); + if (msg_control) { /* There are 256 bytes to be copied in skb, so there is * enough room for skb expand head in case it is used. * The rest of the buffer is mapped from userspace. */ copylen = gso.hdr_len ? gso.hdr_len : GOODCOPY_LEN; + if (copylen > good_linear) + copylen = good_linear; linear = copylen; if (iov_pages(iv, offset + copylen, count) <= MAX_SKB_FRAGS) zerocopy = true; @@ -1122,7 +1127,10 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, if (!zerocopy) { copylen = len; - linear = gso.hdr_len; + if (gso.hdr_len > good_linear) + linear = good_linear; + else + linear = gso.hdr_len; } skb = tun_alloc_skb(tfile, align, copylen, linear, noblock); -- cgit v1.2.3 From a6c8afd6ef8037c550d646ddb195ad5f0b5bebcf Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Wed, 13 Nov 2013 14:00:40 +0800 Subject: macvtap: limit head length of skb allocated [ Upstream commit 16a3fa28630331e28208872fa5341ce210b901c7 ] We currently use hdr_len as a hint of head length which is advertised by guest. But when guest advertise a very big value, it can lead to an 64K+ allocating of kmalloc() which has a very high possibility of failure when host memory is fragmented or under heavy stress. The huge hdr_len also reduce the effect of zerocopy or even disable if a gso skb is linearized in guest. To solves those issues, this patch introduces an upper limit (PAGE_SIZE) of the head, which guarantees an order 0 allocation each time. Signed-off-by: Jason Wang Cc: Stefan Hajnoczi Cc: Michael S. Tsirkin Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/macvtap.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 523d6b2426a8..c70ff7dac00e 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -661,6 +661,7 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, const struct iovec *iv, unsigned long total_len, size_t count, int noblock) { + int good_linear = SKB_MAX_HEAD(NET_IP_ALIGN); struct sk_buff *skb; struct macvlan_dev *vlan; unsigned long len = total_len; @@ -703,6 +704,8 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, if (m && m->msg_control && sock_flag(&q->sk, SOCK_ZEROCOPY)) { copylen = vnet_hdr.hdr_len ? vnet_hdr.hdr_len : GOODCOPY_LEN; + if (copylen > good_linear) + copylen = good_linear; linear = copylen; if (iov_pages(iv, vnet_hdr_len + copylen, count) <= MAX_SKB_FRAGS) @@ -711,7 +714,10 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, if (!zerocopy) { copylen = len; - linear = vnet_hdr.hdr_len; + if (vnet_hdr.hdr_len > good_linear) + linear = good_linear; + else + linear = vnet_hdr.hdr_len; } skb = macvtap_alloc_skb(&q->sk, NET_IP_ALIGN, copylen, -- cgit v1.2.3 From 6ef30bdab8dab92939edbc964237b844efbe5946 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 13 Nov 2013 06:32:54 -0800 Subject: tcp: tsq: restore minimal amount of queueing [ Upstream commit 98e09386c0ef4dfd48af7ba60ff908f0d525cdee ] After commit c9eeec26e32e ("tcp: TSQ can use a dynamic limit"), several users reported throughput regressions, notably on mvneta and wifi adapters. 802.11 AMPDU requires a fair amount of queueing to be effective. This patch partially reverts the change done in tcp_write_xmit() so that the minimal amount is sysctl_tcp_limit_output_bytes. It also remove the use of this sysctl while building skb stored in write queue, as TSO autosizing does the right thing anyway. Users with well behaving NICS and correct qdisc (like sch_fq), can then lower the default sysctl_tcp_limit_output_bytes value from 128KB to 8KB. This new usage of sysctl_tcp_limit_output_bytes permits each driver authors to check how their driver performs when/if the value is set to a minimum of 4KB. Normally, line rate for a single TCP flow should be possible, but some drivers rely on timers to perform TX completion and too long TX completion delays prevent reaching full throughput. Fixes: c9eeec26e32e ("tcp: TSQ can use a dynamic limit") Signed-off-by: Eric Dumazet Reported-by: Sujith Manoharan Reported-by: Arnaud Ebalard Tested-by: Sujith Manoharan Cc: Felix Fietkau Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- Documentation/networking/ip-sysctl.txt | 3 --- net/ipv4/tcp.c | 6 ------ net/ipv4/tcp_output.c | 6 +++++- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index 3994f0bbeeb6..a59ee432a98f 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -571,9 +571,6 @@ tcp_limit_output_bytes - INTEGER typical pfifo_fast qdiscs. tcp_limit_output_bytes limits the number of bytes on qdisc or device to reduce artificial RTT/cwnd and reduce bufferbloat. - Note: For GSO/TSO enabled flows, we try to have at least two - packets in flight. Reducing tcp_limit_output_bytes might also - reduce the size of individual GSO packet (64KB being the max) Default: 131072 tcp_challenge_ack_limit - INTEGER diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index c888abf5a728..ae15c18df880 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -807,12 +807,6 @@ static unsigned int tcp_xmit_size_goal(struct sock *sk, u32 mss_now, xmit_size_goal = min_t(u32, gso_size, sk->sk_gso_max_size - 1 - hlen); - /* TSQ : try to have at least two segments in flight - * (one in NIC TX ring, another in Qdisc) - */ - xmit_size_goal = min_t(u32, xmit_size_goal, - sysctl_tcp_limit_output_bytes >> 1); - xmit_size_goal = tcp_bound_to_half_wnd(tp, xmit_size_goal); /* We try hard to avoid divides here */ diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index cd16eb06bebf..e21be13f74a6 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -1866,8 +1866,12 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle, * - better RTT estimation and ACK scheduling * - faster recovery * - high rates + * Alas, some drivers / subsystems require a fair amount + * of queued bytes to ensure line rate. + * One example is wifi aggregation (802.11 AMPDU) */ - limit = max(skb->truesize, sk->sk_pacing_rate >> 10); + limit = max_t(unsigned int, sysctl_tcp_limit_output_bytes, + sk->sk_pacing_rate >> 10); if (atomic_read(&sk->sk_wmem_alloc) > limit) { set_bit(TSQ_THROTTLED, &tp->tsq_flags); -- cgit v1.2.3 From 9571243bac246e21eab0301fe48b7456d8804821 Mon Sep 17 00:00:00 2001 From: Nikolay Aleksandrov Date: Wed, 13 Nov 2013 17:07:46 +0100 Subject: bonding: fix two race conditions in bond_store_updelay/downdelay [ Upstream commit b869ccfab1e324507fa3596e3e1308444fb68227 ] This patch fixes two race conditions between bond_store_updelay/downdelay and bond_store_miimon which could lead to division by zero as miimon can be set to 0 while either updelay/downdelay are being set and thus miss the zero check in the beginning, the zero div happens because updelay/downdelay are stored as new_value / bond->params.miimon. Use rtnl to synchronize with miimon setting. Signed-off-by: Nikolay Aleksandrov CC: Jay Vosburgh CC: Andy Gospodarek CC: Veaceslav Falico Acked-by: Veaceslav Falico Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/bonding/bond_sysfs.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index 50ddeb9c0480..a88d04b3a77a 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -697,6 +697,8 @@ static ssize_t bonding_store_downdelay(struct device *d, int new_value, ret = count; struct bonding *bond = to_bond(d); + if (!rtnl_trylock()) + return restart_syscall(); if (!(bond->params.miimon)) { pr_err("%s: Unable to set down delay as MII monitoring is disabled\n", bond->dev->name); @@ -730,6 +732,7 @@ static ssize_t bonding_store_downdelay(struct device *d, } out: + rtnl_unlock(); return ret; } static DEVICE_ATTR(downdelay, S_IRUGO | S_IWUSR, @@ -752,6 +755,8 @@ static ssize_t bonding_store_updelay(struct device *d, int new_value, ret = count; struct bonding *bond = to_bond(d); + if (!rtnl_trylock()) + return restart_syscall(); if (!(bond->params.miimon)) { pr_err("%s: Unable to set up delay as MII monitoring is disabled\n", bond->dev->name); @@ -785,6 +790,7 @@ static ssize_t bonding_store_updelay(struct device *d, } out: + rtnl_unlock(); return ret; } static DEVICE_ATTR(updelay, S_IRUGO | S_IWUSR, -- cgit v1.2.3 From 5e8c945dc7573ba2f28bddf51ca06b152b4bf749 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 13 Nov 2013 15:00:46 -0800 Subject: net-tcp: fix panic in tcp_fastopen_cache_set() [ Upstream commit dccf76ca6b626c0c4a4e09bb221adee3270ab0ef ] We had some reports of crashes using TCP fastopen, and Dave Jones gave a nice stack trace pointing to the error. Issue is that tcp_get_metrics() should not be called with a NULL dst Fixes: 1fe4c481ba637 ("net-tcp: Fast Open client - cookie cache") Signed-off-by: Eric Dumazet Reported-by: Dave Jones Cc: Yuchung Cheng Acked-by: Yuchung Cheng Tested-by: Dave Jones Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/tcp_metrics.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/ipv4/tcp_metrics.c b/net/ipv4/tcp_metrics.c index f6a005c485a9..306dbd9a9441 100644 --- a/net/ipv4/tcp_metrics.c +++ b/net/ipv4/tcp_metrics.c @@ -665,10 +665,13 @@ void tcp_fastopen_cache_get(struct sock *sk, u16 *mss, void tcp_fastopen_cache_set(struct sock *sk, u16 mss, struct tcp_fastopen_cookie *cookie, bool syn_lost) { + struct dst_entry *dst = __sk_dst_get(sk); struct tcp_metrics_block *tm; + if (!dst) + return; rcu_read_lock(); - tm = tcp_get_metrics(sk, __sk_dst_get(sk), true); + tm = tcp_get_metrics(sk, dst, true); if (tm) { struct tcp_fastopen_metrics *tfom = &tm->tcpm_fastopen; -- cgit v1.2.3 From 0056eb8b08101a3f9c21d3069ebc300fe5008813 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 14 Nov 2013 11:21:10 +0300 Subject: isdnloop: use strlcpy() instead of strcpy() [ Upstream commit f9a23c84486ed350cce7bb1b2828abd1f6658796 ] These strings come from a copy_from_user() and there is no way to be sure they are NUL terminated. Signed-off-by: Dan Carpenter Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/isdn/isdnloop/isdnloop.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/isdn/isdnloop/isdnloop.c b/drivers/isdn/isdnloop/isdnloop.c index baf2686aa8eb..02125e6a9109 100644 --- a/drivers/isdn/isdnloop/isdnloop.c +++ b/drivers/isdn/isdnloop/isdnloop.c @@ -1083,8 +1083,10 @@ isdnloop_start(isdnloop_card *card, isdnloop_sdef *sdefp) spin_unlock_irqrestore(&card->isdnloop_lock, flags); return -ENOMEM; } - for (i = 0; i < 3; i++) - strcpy(card->s0num[i], sdef.num[i]); + for (i = 0; i < 3; i++) { + strlcpy(card->s0num[i], sdef.num[i], + sizeof(card->s0num[0])); + } break; case ISDN_PTYPE_1TR6: if (isdnloop_fake(card, "DRV1.04TC-1TR6-CAPI-CNS-BASIS-29.11.95", @@ -1097,7 +1099,7 @@ isdnloop_start(isdnloop_card *card, isdnloop_sdef *sdefp) spin_unlock_irqrestore(&card->isdnloop_lock, flags); return -ENOMEM; } - strcpy(card->s0num[0], sdef.num[0]); + strlcpy(card->s0num[0], sdef.num[0], sizeof(card->s0num[0])); card->s0num[1][0] = '\0'; card->s0num[2][0] = '\0'; break; -- cgit v1.2.3 From f0173a11a965e9e6cc248ccf9efa88cfd22355f9 Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Thu, 14 Nov 2013 12:09:21 -0500 Subject: connector: improved unaligned access error fix [ Upstream commit 1ca1a4cf59ea343a1a70084fe7cc96f37f3cf5b1 ] In af3e095a1fb4, Erik Jacobsen fixed one type of unaligned access bug for ia64 by converting a 64-bit write to use put_unaligned(). Unfortunately, since gcc will convert a short memset() to a series of appropriately-aligned stores, the problem is now visible again on tilegx, where the memset that zeros out proc_event is converted to three 64-bit stores, causing an unaligned access panic. A better fix for the original problem is to ensure that proc_event is aligned to 8 bytes here. We can do that relatively easily by arranging to start the struct cn_msg aligned to 8 bytes and then offset by 4 bytes. Doing so means that the immediately following proc_event structure is then correctly aligned to 8 bytes. The result is that the memset() stores are now aligned, and as an added benefit, we can remove the put_unaligned() calls in the code. Signed-off-by: Chris Metcalf Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/connector/cn_proc.c | 72 ++++++++++++++++++++++++++------------------- 1 file changed, 42 insertions(+), 30 deletions(-) diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c index c73fc2b74de2..18c5b9b16645 100644 --- a/drivers/connector/cn_proc.c +++ b/drivers/connector/cn_proc.c @@ -32,11 +32,23 @@ #include #include -#include - #include -#define CN_PROC_MSG_SIZE (sizeof(struct cn_msg) + sizeof(struct proc_event)) +/* + * Size of a cn_msg followed by a proc_event structure. Since the + * sizeof struct cn_msg is a multiple of 4 bytes, but not 8 bytes, we + * add one 4-byte word to the size here, and then start the actual + * cn_msg structure 4 bytes into the stack buffer. The result is that + * the immediately following proc_event structure is aligned to 8 bytes. + */ +#define CN_PROC_MSG_SIZE (sizeof(struct cn_msg) + sizeof(struct proc_event) + 4) + +/* See comment above; we test our assumption about sizeof struct cn_msg here. */ +static inline struct cn_msg *buffer_to_cn_msg(__u8 *buffer) +{ + BUILD_BUG_ON(sizeof(struct cn_msg) != 20); + return (struct cn_msg *)(buffer + 4); +} static atomic_t proc_event_num_listeners = ATOMIC_INIT(0); static struct cb_id cn_proc_event_id = { CN_IDX_PROC, CN_VAL_PROC }; @@ -56,19 +68,19 @@ void proc_fork_connector(struct task_struct *task) { struct cn_msg *msg; struct proc_event *ev; - __u8 buffer[CN_PROC_MSG_SIZE]; + __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8); struct timespec ts; struct task_struct *parent; if (atomic_read(&proc_event_num_listeners) < 1) return; - msg = (struct cn_msg *)buffer; + msg = buffer_to_cn_msg(buffer); ev = (struct proc_event *)msg->data; memset(&ev->event_data, 0, sizeof(ev->event_data)); get_seq(&msg->seq, &ev->cpu); ktime_get_ts(&ts); /* get high res monotonic timestamp */ - put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); + ev->timestamp_ns = timespec_to_ns(&ts); ev->what = PROC_EVENT_FORK; rcu_read_lock(); parent = rcu_dereference(task->real_parent); @@ -91,17 +103,17 @@ void proc_exec_connector(struct task_struct *task) struct cn_msg *msg; struct proc_event *ev; struct timespec ts; - __u8 buffer[CN_PROC_MSG_SIZE]; + __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8); if (atomic_read(&proc_event_num_listeners) < 1) return; - msg = (struct cn_msg *)buffer; + msg = buffer_to_cn_msg(buffer); ev = (struct proc_event *)msg->data; memset(&ev->event_data, 0, sizeof(ev->event_data)); get_seq(&msg->seq, &ev->cpu); ktime_get_ts(&ts); /* get high res monotonic timestamp */ - put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); + ev->timestamp_ns = timespec_to_ns(&ts); ev->what = PROC_EVENT_EXEC; ev->event_data.exec.process_pid = task->pid; ev->event_data.exec.process_tgid = task->tgid; @@ -117,14 +129,14 @@ void proc_id_connector(struct task_struct *task, int which_id) { struct cn_msg *msg; struct proc_event *ev; - __u8 buffer[CN_PROC_MSG_SIZE]; + __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8); struct timespec ts; const struct cred *cred; if (atomic_read(&proc_event_num_listeners) < 1) return; - msg = (struct cn_msg *)buffer; + msg = buffer_to_cn_msg(buffer); ev = (struct proc_event *)msg->data; memset(&ev->event_data, 0, sizeof(ev->event_data)); ev->what = which_id; @@ -145,7 +157,7 @@ void proc_id_connector(struct task_struct *task, int which_id) rcu_read_unlock(); get_seq(&msg->seq, &ev->cpu); ktime_get_ts(&ts); /* get high res monotonic timestamp */ - put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); + ev->timestamp_ns = timespec_to_ns(&ts); memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); msg->ack = 0; /* not used */ @@ -159,17 +171,17 @@ void proc_sid_connector(struct task_struct *task) struct cn_msg *msg; struct proc_event *ev; struct timespec ts; - __u8 buffer[CN_PROC_MSG_SIZE]; + __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8); if (atomic_read(&proc_event_num_listeners) < 1) return; - msg = (struct cn_msg *)buffer; + msg = buffer_to_cn_msg(buffer); ev = (struct proc_event *)msg->data; memset(&ev->event_data, 0, sizeof(ev->event_data)); get_seq(&msg->seq, &ev->cpu); ktime_get_ts(&ts); /* get high res monotonic timestamp */ - put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); + ev->timestamp_ns = timespec_to_ns(&ts); ev->what = PROC_EVENT_SID; ev->event_data.sid.process_pid = task->pid; ev->event_data.sid.process_tgid = task->tgid; @@ -186,17 +198,17 @@ void proc_ptrace_connector(struct task_struct *task, int ptrace_id) struct cn_msg *msg; struct proc_event *ev; struct timespec ts; - __u8 buffer[CN_PROC_MSG_SIZE]; + __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8); if (atomic_read(&proc_event_num_listeners) < 1) return; - msg = (struct cn_msg *)buffer; + msg = buffer_to_cn_msg(buffer); ev = (struct proc_event *)msg->data; memset(&ev->event_data, 0, sizeof(ev->event_data)); get_seq(&msg->seq, &ev->cpu); ktime_get_ts(&ts); /* get high res monotonic timestamp */ - put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); + ev->timestamp_ns = timespec_to_ns(&ts); ev->what = PROC_EVENT_PTRACE; ev->event_data.ptrace.process_pid = task->pid; ev->event_data.ptrace.process_tgid = task->tgid; @@ -221,17 +233,17 @@ void proc_comm_connector(struct task_struct *task) struct cn_msg *msg; struct proc_event *ev; struct timespec ts; - __u8 buffer[CN_PROC_MSG_SIZE]; + __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8); if (atomic_read(&proc_event_num_listeners) < 1) return; - msg = (struct cn_msg *)buffer; + msg = buffer_to_cn_msg(buffer); ev = (struct proc_event *)msg->data; memset(&ev->event_data, 0, sizeof(ev->event_data)); get_seq(&msg->seq, &ev->cpu); ktime_get_ts(&ts); /* get high res monotonic timestamp */ - put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); + ev->timestamp_ns = timespec_to_ns(&ts); ev->what = PROC_EVENT_COMM; ev->event_data.comm.process_pid = task->pid; ev->event_data.comm.process_tgid = task->tgid; @@ -248,18 +260,18 @@ void proc_coredump_connector(struct task_struct *task) { struct cn_msg *msg; struct proc_event *ev; - __u8 buffer[CN_PROC_MSG_SIZE]; + __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8); struct timespec ts; if (atomic_read(&proc_event_num_listeners) < 1) return; - msg = (struct cn_msg *)buffer; + msg = buffer_to_cn_msg(buffer); ev = (struct proc_event *)msg->data; memset(&ev->event_data, 0, sizeof(ev->event_data)); get_seq(&msg->seq, &ev->cpu); ktime_get_ts(&ts); /* get high res monotonic timestamp */ - put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); + ev->timestamp_ns = timespec_to_ns(&ts); ev->what = PROC_EVENT_COREDUMP; ev->event_data.coredump.process_pid = task->pid; ev->event_data.coredump.process_tgid = task->tgid; @@ -275,18 +287,18 @@ void proc_exit_connector(struct task_struct *task) { struct cn_msg *msg; struct proc_event *ev; - __u8 buffer[CN_PROC_MSG_SIZE]; + __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8); struct timespec ts; if (atomic_read(&proc_event_num_listeners) < 1) return; - msg = (struct cn_msg *)buffer; + msg = buffer_to_cn_msg(buffer); ev = (struct proc_event *)msg->data; memset(&ev->event_data, 0, sizeof(ev->event_data)); get_seq(&msg->seq, &ev->cpu); ktime_get_ts(&ts); /* get high res monotonic timestamp */ - put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); + ev->timestamp_ns = timespec_to_ns(&ts); ev->what = PROC_EVENT_EXIT; ev->event_data.exit.process_pid = task->pid; ev->event_data.exit.process_tgid = task->tgid; @@ -312,18 +324,18 @@ static void cn_proc_ack(int err, int rcvd_seq, int rcvd_ack) { struct cn_msg *msg; struct proc_event *ev; - __u8 buffer[CN_PROC_MSG_SIZE]; + __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8); struct timespec ts; if (atomic_read(&proc_event_num_listeners) < 1) return; - msg = (struct cn_msg *)buffer; + msg = buffer_to_cn_msg(buffer); ev = (struct proc_event *)msg->data; memset(&ev->event_data, 0, sizeof(ev->event_data)); msg->seq = rcvd_seq; ktime_get_ts(&ts); /* get high res monotonic timestamp */ - put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); + ev->timestamp_ns = timespec_to_ns(&ts); ev->cpu = -1; ev->what = PROC_EVENT_NONE; ev->event_data.ack.err = err; -- cgit v1.2.3 From ac6a5b926d2d8df1596f7cb91f46afc18e5e39f9 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 14 Nov 2013 13:37:54 -0800 Subject: ipv4: fix possible seqlock deadlock [ Upstream commit c9e9042994d37cbc1ee538c500e9da1bb9d1bcdf ] ip4_datagram_connect() being called from process context, it should use IP_INC_STATS() instead of IP_INC_STATS_BH() otherwise we can deadlock on 32bit arches, or get corruptions of SNMP counters. Fixes: 584bdf8cbdf6 ("[IPV4]: Fix "ipOutNoRoutes" counter error for TCP and UDP") Signed-off-by: Eric Dumazet Reported-by: Dave Jones Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/datagram.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c index b28e863fe0a7..19e36376d2a0 100644 --- a/net/ipv4/datagram.c +++ b/net/ipv4/datagram.c @@ -57,7 +57,7 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) if (IS_ERR(rt)) { err = PTR_ERR(rt); if (err == -ENETUNREACH) - IP_INC_STATS_BH(sock_net(sk), IPSTATS_MIB_OUTNOROUTES); + IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTNOROUTES); goto out; } -- cgit v1.2.3 From a2214488937a84d8d0b5a3b546f97b2485029a17 Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Mon, 18 Nov 2013 04:20:45 +0100 Subject: inet: prevent leakage of uninitialized memory to user in recv syscalls [ Upstream commit bceaa90240b6019ed73b49965eac7d167610be69 ] Only update *addr_len when we actually fill in sockaddr, otherwise we can return uninitialized memory from the stack to the caller in the recvfrom, recvmmsg and recvmsg syscalls. Drop the the (addr_len == NULL) checks because we only get called with a valid addr_len pointer either from sock_common_recvmsg or inet_recvmsg. If a blocking read waits on a socket which is concurrently shut down we now return zero and set msg_msgnamelen to 0. Reported-by: mpb Suggested-by: Eric Dumazet Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ieee802154/dgram.c | 3 +-- net/ipv4/ping.c | 9 ++++----- net/ipv4/raw.c | 4 +--- net/ipv4/udp.c | 7 +------ net/ipv6/raw.c | 4 +--- net/ipv6/udp.c | 5 +---- net/l2tp/l2tp_ip.c | 4 +--- net/phonet/datagram.c | 9 ++++----- 8 files changed, 14 insertions(+), 31 deletions(-) diff --git a/net/ieee802154/dgram.c b/net/ieee802154/dgram.c index 581a59504bd5..1865fdf5a5a5 100644 --- a/net/ieee802154/dgram.c +++ b/net/ieee802154/dgram.c @@ -315,9 +315,8 @@ static int dgram_recvmsg(struct kiocb *iocb, struct sock *sk, if (saddr) { saddr->family = AF_IEEE802154; saddr->addr = mac_cb(skb)->sa; - } - if (addr_len) *addr_len = sizeof(*saddr); + } if (flags & MSG_TRUNC) copied = skb->len; diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index 7d93d62cd5fd..be01d5b8571a 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c @@ -626,7 +626,6 @@ static int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, size_t len, int noblock, int flags, int *addr_len) { struct inet_sock *isk = inet_sk(sk); - struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name; struct sk_buff *skb; int copied, err; @@ -636,9 +635,6 @@ static int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, if (flags & MSG_OOB) goto out; - if (addr_len) - *addr_len = sizeof(*sin); - if (flags & MSG_ERRQUEUE) return ip_recv_error(sk, msg, len); @@ -660,11 +656,14 @@ static int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, sock_recv_timestamp(msg, sk, skb); /* Copy the address. */ - if (sin) { + if (msg->msg_name) { + struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name; + sin->sin_family = AF_INET; sin->sin_port = 0 /* skb->h.uh->source */; sin->sin_addr.s_addr = ip_hdr(skb)->saddr; memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); + *addr_len = sizeof(*sin); } if (isk->cmsg_flags) ip_cmsg_recv(msg, skb); diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 6fb233772f79..448e5a77fa88 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -692,9 +692,6 @@ static int raw_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, if (flags & MSG_OOB) goto out; - if (addr_len) - *addr_len = sizeof(*sin); - if (flags & MSG_ERRQUEUE) { err = ip_recv_error(sk, msg, len); goto out; @@ -722,6 +719,7 @@ static int raw_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, sin->sin_addr.s_addr = ip_hdr(skb)->saddr; sin->sin_port = 0; memset(&sin->sin_zero, 0, sizeof(sin->sin_zero)); + *addr_len = sizeof(*sin); } if (inet->cmsg_flags) ip_cmsg_recv(msg, skb); diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 93b731d53221..eeb3474daa3f 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1207,12 +1207,6 @@ int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, int is_udplite = IS_UDPLITE(sk); bool slow; - /* - * Check any passed addresses - */ - if (addr_len) - *addr_len = sizeof(*sin); - if (flags & MSG_ERRQUEUE) return ip_recv_error(sk, msg, len); @@ -1274,6 +1268,7 @@ try_again: sin->sin_port = udp_hdr(skb)->source; sin->sin_addr.s_addr = ip_hdr(skb)->saddr; memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); + *addr_len = sizeof(*sin); } if (inet->cmsg_flags) ip_cmsg_recv(msg, skb); diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index eedff8ccded5..d3c01a601955 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -459,9 +459,6 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk, if (flags & MSG_OOB) return -EOPNOTSUPP; - if (addr_len) - *addr_len=sizeof(*sin6); - if (flags & MSG_ERRQUEUE) return ipv6_recv_error(sk, msg, len); @@ -500,6 +497,7 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk, sin6->sin6_flowinfo = 0; sin6->sin6_scope_id = ipv6_iface_scope_id(&sin6->sin6_addr, IP6CB(skb)->iif); + *addr_len = sizeof(*sin6); } sock_recv_ts_and_drops(msg, sk, skb); diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index e7b28f9bb02b..f10f1186da0b 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -373,9 +373,6 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk, int is_udp4; bool slow; - if (addr_len) - *addr_len = sizeof(struct sockaddr_in6); - if (flags & MSG_ERRQUEUE) return ipv6_recv_error(sk, msg, len); @@ -461,7 +458,7 @@ try_again: ipv6_iface_scope_id(&sin6->sin6_addr, IP6CB(skb)->iif); } - + *addr_len = sizeof(*sin6); } if (is_udp4) { if (inet->cmsg_flags) diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c index 571db8dd2292..da1a1cee1a08 100644 --- a/net/l2tp/l2tp_ip.c +++ b/net/l2tp/l2tp_ip.c @@ -518,9 +518,6 @@ static int l2tp_ip_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m if (flags & MSG_OOB) goto out; - if (addr_len) - *addr_len = sizeof(*sin); - skb = skb_recv_datagram(sk, flags, noblock, &err); if (!skb) goto out; @@ -543,6 +540,7 @@ static int l2tp_ip_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m sin->sin_addr.s_addr = ip_hdr(skb)->saddr; sin->sin_port = 0; memset(&sin->sin_zero, 0, sizeof(sin->sin_zero)); + *addr_len = sizeof(*sin); } if (inet->cmsg_flags) ip_cmsg_recv(msg, skb); diff --git a/net/phonet/datagram.c b/net/phonet/datagram.c index 12c30f3e643e..38946b26e471 100644 --- a/net/phonet/datagram.c +++ b/net/phonet/datagram.c @@ -139,9 +139,6 @@ static int pn_recvmsg(struct kiocb *iocb, struct sock *sk, MSG_CMSG_COMPAT)) goto out_nofree; - if (addr_len) - *addr_len = sizeof(sa); - skb = skb_recv_datagram(sk, flags, noblock, &rval); if (skb == NULL) goto out_nofree; @@ -162,8 +159,10 @@ static int pn_recvmsg(struct kiocb *iocb, struct sock *sk, rval = (flags & MSG_TRUNC) ? skb->len : copylen; - if (msg->msg_name != NULL) - memcpy(msg->msg_name, &sa, sizeof(struct sockaddr_pn)); + if (msg->msg_name != NULL) { + memcpy(msg->msg_name, &sa, sizeof(sa)); + *addr_len = sizeof(sa); + } out: skb_free_datagram(sk, skb); -- cgit v1.2.3 From 2f73d7fde99d702cba6a05062c27605a6eef1b78 Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Thu, 21 Nov 2013 03:14:22 +0100 Subject: net: rework recvmsg handler msg_name and msg_namelen logic [ Upstream commit f3d3342602f8bcbf37d7c46641cb9bca7618eb1c ] This patch now always passes msg->msg_namelen as 0. recvmsg handlers must set msg_namelen to the proper size <= sizeof(struct sockaddr_storage) to return msg_name to the user. This prevents numerous uninitialized memory leaks we had in the recvmsg handlers and makes it harder for new code to accidentally leak uninitialized memory. Optimize for the case recvfrom is called with NULL as address. We don't need to copy the address at all, so set it to NULL before invoking the recvmsg handler. We can do so, because all the recvmsg handlers must cope with the case a plain read() is called on them. read() also sets msg_name to NULL. Also document these changes in include/linux/net.h as suggested by David Miller. Changes since RFC: Set msg->msg_name = NULL if user specified a NULL in msg_name but had a non-null msg_namelen in verify_iovec/verify_compat_iovec. This doesn't affect sendto as it would bail out earlier while trying to copy-in the address. It also more naturally reflects the logic by the callers of verify_iovec. With this change in place I could remove " if (!uaddr || msg_sys->msg_namelen == 0) msg->msg_name = NULL ". This change does not alter the user visible error logic as we ignore msg_namelen as long as msg_name is NULL. Also remove two unnecessary curly brackets in ___sys_recvmsg and change comments to netdev style. Cc: David Miller Suggested-by: Eric Dumazet Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- crypto/algif_hash.c | 2 -- crypto/algif_skcipher.c | 1 - drivers/isdn/mISDN/socket.c | 13 ++++--------- drivers/net/ppp/pppoe.c | 2 -- include/linux/net.h | 8 ++++++++ net/appletalk/ddp.c | 16 +++++++--------- net/atm/common.c | 2 -- net/ax25/af_ax25.c | 4 ++-- net/bluetooth/af_bluetooth.c | 4 ---- net/bluetooth/hci_sock.c | 2 -- net/bluetooth/rfcomm/sock.c | 1 - net/bluetooth/sco.c | 1 - net/caif/caif_socket.c | 4 ---- net/compat.c | 3 ++- net/core/iovec.c | 3 ++- net/ipx/af_ipx.c | 3 +-- net/irda/af_irda.c | 4 ---- net/iucv/af_iucv.c | 2 -- net/key/af_key.c | 1 - net/l2tp/l2tp_ppp.c | 2 -- net/llc/af_llc.c | 2 -- net/netlink/af_netlink.c | 2 -- net/netrom/af_netrom.c | 3 +-- net/nfc/llcp_sock.c | 2 -- net/nfc/rawsock.c | 2 -- net/packet/af_packet.c | 32 +++++++++++++++----------------- net/rds/recv.c | 2 -- net/rose/af_rose.c | 8 +++++--- net/rxrpc/ar-recvmsg.c | 9 ++++++--- net/socket.c | 19 +++++++++++-------- net/tipc/socket.c | 6 ------ net/unix/af_unix.c | 5 ----- net/vmw_vsock/af_vsock.c | 2 -- net/vmw_vsock/vmci_transport.c | 2 -- net/x25/af_x25.c | 3 +-- 35 files changed, 65 insertions(+), 112 deletions(-) diff --git a/crypto/algif_hash.c b/crypto/algif_hash.c index 0262210cad38..ef5356cd280a 100644 --- a/crypto/algif_hash.c +++ b/crypto/algif_hash.c @@ -161,8 +161,6 @@ static int hash_recvmsg(struct kiocb *unused, struct socket *sock, else if (len < ds) msg->msg_flags |= MSG_TRUNC; - msg->msg_namelen = 0; - lock_sock(sk); if (ctx->more) { ctx->more = 0; diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c index a1c4f0a55583..6a6dfc062d2a 100644 --- a/crypto/algif_skcipher.c +++ b/crypto/algif_skcipher.c @@ -432,7 +432,6 @@ static int skcipher_recvmsg(struct kiocb *unused, struct socket *sock, long copied = 0; lock_sock(sk); - msg->msg_namelen = 0; for (iov = msg->msg_iov, iovlen = msg->msg_iovlen; iovlen > 0; iovlen--, iov++) { unsigned long seglen = iov->iov_len; diff --git a/drivers/isdn/mISDN/socket.c b/drivers/isdn/mISDN/socket.c index e47dcb9d1e91..5cefb479c707 100644 --- a/drivers/isdn/mISDN/socket.c +++ b/drivers/isdn/mISDN/socket.c @@ -117,7 +117,6 @@ mISDN_sock_recvmsg(struct kiocb *iocb, struct socket *sock, { struct sk_buff *skb; struct sock *sk = sock->sk; - struct sockaddr_mISDN *maddr; int copied, err; @@ -135,9 +134,9 @@ mISDN_sock_recvmsg(struct kiocb *iocb, struct socket *sock, if (!skb) return err; - if (msg->msg_namelen >= sizeof(struct sockaddr_mISDN)) { - msg->msg_namelen = sizeof(struct sockaddr_mISDN); - maddr = (struct sockaddr_mISDN *)msg->msg_name; + if (msg->msg_name) { + struct sockaddr_mISDN *maddr = msg->msg_name; + maddr->family = AF_ISDN; maddr->dev = _pms(sk)->dev->id; if ((sk->sk_protocol == ISDN_P_LAPD_TE) || @@ -150,11 +149,7 @@ mISDN_sock_recvmsg(struct kiocb *iocb, struct socket *sock, maddr->sapi = _pms(sk)->ch.addr & 0xFF; maddr->tei = (_pms(sk)->ch.addr >> 8) & 0xFF; } - } else { - if (msg->msg_namelen) - printk(KERN_WARNING "%s: too small namelen %d\n", - __func__, msg->msg_namelen); - msg->msg_namelen = 0; + msg->msg_namelen = sizeof(*maddr); } copied = skb->len + MISDN_HEADER_LEN; diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c index bb07ba94c3aa..6839fb07a4c9 100644 --- a/drivers/net/ppp/pppoe.c +++ b/drivers/net/ppp/pppoe.c @@ -979,8 +979,6 @@ static int pppoe_recvmsg(struct kiocb *iocb, struct socket *sock, if (error < 0) goto end; - m->msg_namelen = 0; - if (skb) { total_len = min_t(size_t, total_len, skb->len); error = skb_copy_datagram_iovec(skb, 0, m->msg_iov, total_len); diff --git a/include/linux/net.h b/include/linux/net.h index 99c9f0c103c2..0c4ae5d94de9 100644 --- a/include/linux/net.h +++ b/include/linux/net.h @@ -163,6 +163,14 @@ struct proto_ops { #endif int (*sendmsg) (struct kiocb *iocb, struct socket *sock, struct msghdr *m, size_t total_len); + /* Notes for implementing recvmsg: + * =============================== + * msg->msg_namelen should get updated by the recvmsg handlers + * iff msg_name != NULL. It is by default 0 to prevent + * returning uninitialized memory to user space. The recvfrom + * handlers can assume that msg.msg_name is either NULL or has + * a minimum size of sizeof(struct sockaddr_storage). + */ int (*recvmsg) (struct kiocb *iocb, struct socket *sock, struct msghdr *m, size_t total_len, int flags); diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index ef12839a7cfe..0018daccdea9 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c @@ -1735,7 +1735,6 @@ static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr size_t size, int flags) { struct sock *sk = sock->sk; - struct sockaddr_at *sat = (struct sockaddr_at *)msg->msg_name; struct ddpehdr *ddp; int copied = 0; int offset = 0; @@ -1764,14 +1763,13 @@ static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr } err = skb_copy_datagram_iovec(skb, offset, msg->msg_iov, copied); - if (!err) { - if (sat) { - sat->sat_family = AF_APPLETALK; - sat->sat_port = ddp->deh_sport; - sat->sat_addr.s_node = ddp->deh_snode; - sat->sat_addr.s_net = ddp->deh_snet; - } - msg->msg_namelen = sizeof(*sat); + if (!err && msg->msg_name) { + struct sockaddr_at *sat = msg->msg_name; + sat->sat_family = AF_APPLETALK; + sat->sat_port = ddp->deh_sport; + sat->sat_addr.s_node = ddp->deh_snode; + sat->sat_addr.s_net = ddp->deh_snet; + msg->msg_namelen = sizeof(*sat); } skb_free_datagram(sk, skb); /* Free the datagram. */ diff --git a/net/atm/common.c b/net/atm/common.c index 737bef59ce89..7b491006eaf4 100644 --- a/net/atm/common.c +++ b/net/atm/common.c @@ -531,8 +531,6 @@ int vcc_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, struct sk_buff *skb; int copied, error = -EINVAL; - msg->msg_namelen = 0; - if (sock->state != SS_CONNECTED) return -ENOTCONN; diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index e277e38f736b..ba6db78a02b1 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -1636,11 +1636,11 @@ static int ax25_recvmsg(struct kiocb *iocb, struct socket *sock, skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); - if (msg->msg_namelen != 0) { - struct sockaddr_ax25 *sax = (struct sockaddr_ax25 *)msg->msg_name; + if (msg->msg_name) { ax25_digi digi; ax25_address src; const unsigned char *mac = skb_mac_header(skb); + struct sockaddr_ax25 *sax = msg->msg_name; memset(sax, 0, sizeof(struct full_sockaddr_ax25)); ax25_addr_parse(mac + 1, skb->data - mac - 1, &src, NULL, diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 9096137c889c..6629cdc134dc 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -221,8 +221,6 @@ int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, if (flags & (MSG_OOB)) return -EOPNOTSUPP; - msg->msg_namelen = 0; - skb = skb_recv_datagram(sk, flags, noblock, &err); if (!skb) { if (sk->sk_shutdown & RCV_SHUTDOWN) @@ -287,8 +285,6 @@ int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock, if (flags & MSG_OOB) return -EOPNOTSUPP; - msg->msg_namelen = 0; - BT_DBG("sk %p size %zu", sk, size); lock_sock(sk); diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index 9bd7d959e384..fa4bf6631425 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -752,8 +752,6 @@ static int hci_sock_recvmsg(struct kiocb *iocb, struct socket *sock, if (!skb) return err; - msg->msg_namelen = 0; - copied = skb->len; if (len < copied) { msg->msg_flags |= MSG_TRUNC; diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 30b3721dc6d7..c1c6028e389a 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -608,7 +608,6 @@ static int rfcomm_sock_recvmsg(struct kiocb *iocb, struct socket *sock, if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) { rfcomm_dlc_accept(d); - msg->msg_namelen = 0; return 0; } diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index e7bd4eea575c..2bb1d3a5e76b 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -700,7 +700,6 @@ static int sco_sock_recvmsg(struct kiocb *iocb, struct socket *sock, test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) { sco_conn_defer_accept(pi->conn->hcon, 0); sk->sk_state = BT_CONFIG; - msg->msg_namelen = 0; release_sock(sk); return 0; diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c index 05a41c7ec304..d6be3edb7a43 100644 --- a/net/caif/caif_socket.c +++ b/net/caif/caif_socket.c @@ -286,8 +286,6 @@ static int caif_seqpkt_recvmsg(struct kiocb *iocb, struct socket *sock, if (m->msg_flags&MSG_OOB) goto read_error; - m->msg_namelen = 0; - skb = skb_recv_datagram(sk, flags, 0 , &ret); if (!skb) goto read_error; @@ -361,8 +359,6 @@ static int caif_stream_recvmsg(struct kiocb *iocb, struct socket *sock, if (flags&MSG_OOB) goto out; - msg->msg_namelen = 0; - /* * Lock the socket to prevent queue disordering * while sleeps in memcpy_tomsg diff --git a/net/compat.c b/net/compat.c index 89032580bd1d..618c6a8a911b 100644 --- a/net/compat.c +++ b/net/compat.c @@ -93,7 +93,8 @@ int verify_compat_iovec(struct msghdr *kern_msg, struct iovec *kern_iov, if (err < 0) return err; } - kern_msg->msg_name = kern_address; + if (kern_msg->msg_name) + kern_msg->msg_name = kern_address; } else kern_msg->msg_name = NULL; diff --git a/net/core/iovec.c b/net/core/iovec.c index de178e462682..9a31515fb8e3 100644 --- a/net/core/iovec.c +++ b/net/core/iovec.c @@ -48,7 +48,8 @@ int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr_storage *a if (err < 0) return err; } - m->msg_name = address; + if (m->msg_name) + m->msg_name = address; } else { m->msg_name = NULL; } diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c index f547a47d381c..e0897377b3b4 100644 --- a/net/ipx/af_ipx.c +++ b/net/ipx/af_ipx.c @@ -1823,8 +1823,6 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock, if (skb->tstamp.tv64) sk->sk_stamp = skb->tstamp; - msg->msg_namelen = sizeof(*sipx); - if (sipx) { sipx->sipx_family = AF_IPX; sipx->sipx_port = ipx->ipx_source.sock; @@ -1832,6 +1830,7 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock, sipx->sipx_network = IPX_SKB_CB(skb)->ipx_source_net; sipx->sipx_type = ipx->ipx_type; sipx->sipx_zero = 0; + msg->msg_namelen = sizeof(*sipx); } rc = copied; diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c index 0578d4fa00a9..a5e62ef57155 100644 --- a/net/irda/af_irda.c +++ b/net/irda/af_irda.c @@ -1385,8 +1385,6 @@ static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock, IRDA_DEBUG(4, "%s()\n", __func__); - msg->msg_namelen = 0; - skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, flags & MSG_DONTWAIT, &err); if (!skb) @@ -1451,8 +1449,6 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock, target = sock_rcvlowat(sk, flags & MSG_WAITALL, size); timeo = sock_rcvtimeo(sk, noblock); - msg->msg_namelen = 0; - do { int chunk; struct sk_buff *skb = skb_dequeue(&sk->sk_receive_queue); diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index ae691651b721..276aa86f366b 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c @@ -1324,8 +1324,6 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock, int err = 0; u32 offset; - msg->msg_namelen = 0; - if ((sk->sk_state == IUCV_DISCONN) && skb_queue_empty(&iucv->backlog_skb_q) && skb_queue_empty(&sk->sk_receive_queue) && diff --git a/net/key/af_key.c b/net/key/af_key.c index ab8bd2cabfa0..66f51c5a8a3a 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -3623,7 +3623,6 @@ static int pfkey_recvmsg(struct kiocb *kiocb, if (flags & ~(MSG_PEEK|MSG_DONTWAIT|MSG_TRUNC|MSG_CMSG_COMPAT)) goto out; - msg->msg_namelen = 0; skb = skb_recv_datagram(sk, flags, flags & MSG_DONTWAIT, &err); if (skb == NULL) goto out; diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c index 8c46b271064a..44441c0c5037 100644 --- a/net/l2tp/l2tp_ppp.c +++ b/net/l2tp/l2tp_ppp.c @@ -197,8 +197,6 @@ static int pppol2tp_recvmsg(struct kiocb *iocb, struct socket *sock, if (sk->sk_state & PPPOX_BOUND) goto end; - msg->msg_namelen = 0; - err = 0; skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, flags & MSG_DONTWAIT, &err); diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index 48aaa89253e0..88709882c464 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -720,8 +720,6 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock, int target; /* Read at least this many bytes */ long timeo; - msg->msg_namelen = 0; - lock_sock(sk); copied = -ENOTCONN; if (unlikely(sk->sk_type == SOCK_STREAM && sk->sk_state == TCP_LISTEN)) diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 57ee84d21470..c9c2a8441d32 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -2168,8 +2168,6 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock, } #endif - msg->msg_namelen = 0; - copied = data_skb->len; if (len < copied) { msg->msg_flags |= MSG_TRUNC; diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index ec0c80fde69f..13b92982a506 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c @@ -1179,10 +1179,9 @@ static int nr_recvmsg(struct kiocb *iocb, struct socket *sock, sax->sax25_family = AF_NETROM; skb_copy_from_linear_data_offset(skb, 7, sax->sax25_call.ax25_call, AX25_ADDR_LEN); + msg->msg_namelen = sizeof(*sax); } - msg->msg_namelen = sizeof(*sax); - skb_free_datagram(sk, skb); release_sock(sk); diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c index 7522c3708723..86470cf54cee 100644 --- a/net/nfc/llcp_sock.c +++ b/net/nfc/llcp_sock.c @@ -800,8 +800,6 @@ static int llcp_sock_recvmsg(struct kiocb *iocb, struct socket *sock, pr_debug("%p %zu\n", sk, len); - msg->msg_namelen = 0; - lock_sock(sk); if (sk->sk_state == LLCP_CLOSED && diff --git a/net/nfc/rawsock.c b/net/nfc/rawsock.c index 313bf1bc848a..5d11f4ac3ecb 100644 --- a/net/nfc/rawsock.c +++ b/net/nfc/rawsock.c @@ -241,8 +241,6 @@ static int rawsock_recvmsg(struct kiocb *iocb, struct socket *sock, if (!skb) return rc; - msg->msg_namelen = 0; - copied = skb->len; if (len < copied) { msg->msg_flags |= MSG_TRUNC; diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index a6895ab597c2..92e2d0201f90 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -2694,7 +2694,6 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock, struct sock *sk = sock->sk; struct sk_buff *skb; int copied, err; - struct sockaddr_ll *sll; int vnet_hdr_len = 0; err = -EINVAL; @@ -2777,22 +2776,10 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock, goto out_free; } - /* - * If the address length field is there to be filled in, we fill - * it in now. - */ - - sll = &PACKET_SKB_CB(skb)->sa.ll; - if (sock->type == SOCK_PACKET) - msg->msg_namelen = sizeof(struct sockaddr_pkt); - else - msg->msg_namelen = sll->sll_halen + offsetof(struct sockaddr_ll, sll_addr); - - /* - * You lose any data beyond the buffer you gave. If it worries a - * user program they can ask the device for its MTU anyway. + /* You lose any data beyond the buffer you gave. If it worries + * a user program they can ask the device for its MTU + * anyway. */ - copied = skb->len; if (copied > len) { copied = len; @@ -2805,9 +2792,20 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock, sock_recv_ts_and_drops(msg, sk, skb); - if (msg->msg_name) + if (msg->msg_name) { + /* If the address length field is there to be filled + * in, we fill it in now. + */ + if (sock->type == SOCK_PACKET) { + msg->msg_namelen = sizeof(struct sockaddr_pkt); + } else { + struct sockaddr_ll *sll = &PACKET_SKB_CB(skb)->sa.ll; + msg->msg_namelen = sll->sll_halen + + offsetof(struct sockaddr_ll, sll_addr); + } memcpy(msg->msg_name, &PACKET_SKB_CB(skb)->sa, msg->msg_namelen); + } if (pkt_sk(sk)->auxdata) { struct tpacket_auxdata aux; diff --git a/net/rds/recv.c b/net/rds/recv.c index 9f0f17cf6bf9..de339b24ca14 100644 --- a/net/rds/recv.c +++ b/net/rds/recv.c @@ -410,8 +410,6 @@ int rds_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, rdsdebug("size %zu flags 0x%x timeo %ld\n", size, msg_flags, timeo); - msg->msg_namelen = 0; - if (msg_flags & MSG_OOB) goto out; diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index 9c8347451597..abf0ad6311d0 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c @@ -1216,7 +1216,6 @@ static int rose_recvmsg(struct kiocb *iocb, struct socket *sock, { struct sock *sk = sock->sk; struct rose_sock *rose = rose_sk(sk); - struct sockaddr_rose *srose = (struct sockaddr_rose *)msg->msg_name; size_t copied; unsigned char *asmptr; struct sk_buff *skb; @@ -1252,8 +1251,11 @@ static int rose_recvmsg(struct kiocb *iocb, struct socket *sock, skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); - if (srose != NULL) { - memset(srose, 0, msg->msg_namelen); + if (msg->msg_name) { + struct sockaddr_rose *srose; + + memset(msg->msg_name, 0, sizeof(struct full_sockaddr_rose)); + srose = msg->msg_name; srose->srose_family = AF_ROSE; srose->srose_addr = rose->dest_addr; srose->srose_call = rose->dest_call; diff --git a/net/rxrpc/ar-recvmsg.c b/net/rxrpc/ar-recvmsg.c index 4b48687c3890..898492a8d61b 100644 --- a/net/rxrpc/ar-recvmsg.c +++ b/net/rxrpc/ar-recvmsg.c @@ -143,10 +143,13 @@ int rxrpc_recvmsg(struct kiocb *iocb, struct socket *sock, /* copy the peer address and timestamp */ if (!continue_call) { - if (msg->msg_name && msg->msg_namelen > 0) + if (msg->msg_name) { + size_t len = + sizeof(call->conn->trans->peer->srx); memcpy(msg->msg_name, - &call->conn->trans->peer->srx, - sizeof(call->conn->trans->peer->srx)); + &call->conn->trans->peer->srx, len); + msg->msg_namelen = len; + } sock_recv_ts_and_drops(msg, &rx->sk, skb); } diff --git a/net/socket.c b/net/socket.c index 9c467b2afc84..9f7d6263f7fa 100644 --- a/net/socket.c +++ b/net/socket.c @@ -1832,8 +1832,10 @@ SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size, msg.msg_iov = &iov; iov.iov_len = size; iov.iov_base = ubuf; - msg.msg_name = (struct sockaddr *)&address; - msg.msg_namelen = sizeof(address); + /* Save some cycles and don't copy the address if not needed */ + msg.msg_name = addr ? (struct sockaddr *)&address : NULL; + /* We assume all kernel code knows the size of sockaddr_storage */ + msg.msg_namelen = 0; if (sock->file->f_flags & O_NONBLOCK) flags |= MSG_DONTWAIT; err = sock_recvmsg(sock, &msg, size, flags); @@ -2213,16 +2215,14 @@ static int ___sys_recvmsg(struct socket *sock, struct msghdr __user *msg, goto out; } - /* - * Save the user-mode address (verify_iovec will change the - * kernel msghdr to use the kernel address space) + /* Save the user-mode address (verify_iovec will change the + * kernel msghdr to use the kernel address space) */ - uaddr = (__force void __user *)msg_sys->msg_name; uaddr_len = COMPAT_NAMELEN(msg); - if (MSG_CMSG_COMPAT & flags) { + if (MSG_CMSG_COMPAT & flags) err = verify_compat_iovec(msg_sys, iov, &addr, VERIFY_WRITE); - } else + else err = verify_iovec(msg_sys, iov, &addr, VERIFY_WRITE); if (err < 0) goto out_freeiov; @@ -2231,6 +2231,9 @@ static int ___sys_recvmsg(struct socket *sock, struct msghdr __user *msg, cmsg_ptr = (unsigned long)msg_sys->msg_control; msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT); + /* We assume all kernel code knows the size of sockaddr_storage */ + msg_sys->msg_namelen = 0; + if (sock->file->f_flags & O_NONBLOCK) flags |= MSG_DONTWAIT; err = (nosec ? sock_recvmsg_nosec : sock_recvmsg)(sock, msg_sys, diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 7e26ad416af1..2b1d7c2d677d 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -905,9 +905,6 @@ static int recv_msg(struct kiocb *iocb, struct socket *sock, goto exit; } - /* will be updated in set_orig_addr() if needed */ - m->msg_namelen = 0; - timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); restart: @@ -1017,9 +1014,6 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock, goto exit; } - /* will be updated in set_orig_addr() if needed */ - m->msg_namelen = 0; - target = sock_rcvlowat(sk, flags & MSG_WAITALL, buf_len); timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 0258072a518f..8664ad0d5797 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -1761,7 +1761,6 @@ static void unix_copy_addr(struct msghdr *msg, struct sock *sk) { struct unix_sock *u = unix_sk(sk); - msg->msg_namelen = 0; if (u->addr) { msg->msg_namelen = u->addr->len; memcpy(msg->msg_name, u->addr->name, u->addr->len); @@ -1785,8 +1784,6 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock, if (flags&MSG_OOB) goto out; - msg->msg_namelen = 0; - err = mutex_lock_interruptible(&u->readlock); if (err) { err = sock_intr_errno(sock_rcvtimeo(sk, noblock)); @@ -1926,8 +1923,6 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, target = sock_rcvlowat(sk, flags&MSG_WAITALL, size); timeo = sock_rcvtimeo(sk, flags&MSG_DONTWAIT); - msg->msg_namelen = 0; - /* Lock the socket to prevent queue disordering * while sleeps in memcpy_tomsg */ diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c index 3f77f42a3b58..9b88693bcc99 100644 --- a/net/vmw_vsock/af_vsock.c +++ b/net/vmw_vsock/af_vsock.c @@ -1670,8 +1670,6 @@ vsock_stream_recvmsg(struct kiocb *kiocb, vsk = vsock_sk(sk); err = 0; - msg->msg_namelen = 0; - lock_sock(sk); if (sk->sk_state != SS_CONNECTED) { diff --git a/net/vmw_vsock/vmci_transport.c b/net/vmw_vsock/vmci_transport.c index daff75200e25..62bbf7d73980 100644 --- a/net/vmw_vsock/vmci_transport.c +++ b/net/vmw_vsock/vmci_transport.c @@ -1746,8 +1746,6 @@ static int vmci_transport_dgram_dequeue(struct kiocb *kiocb, if (flags & MSG_OOB || flags & MSG_ERRQUEUE) return -EOPNOTSUPP; - msg->msg_namelen = 0; - /* Retrieve the head sk_buff from the socket's receive queue. */ err = 0; skb = skb_recv_datagram(&vsk->sk, flags, noblock, &err); diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index 22c88d2e6846..f96af3b96322 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c @@ -1340,10 +1340,9 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock, if (sx25) { sx25->sx25_family = AF_X25; sx25->sx25_addr = x25->dest_addr; + msg->msg_namelen = sizeof(*sx25); } - msg->msg_namelen = sizeof(struct sockaddr_x25); - x25_check_rbuf(sk); rc = copied; out_free_dgram: -- cgit v1.2.3 From 5c586f163dc452d8cc19b456f6f2f3e704025462 Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Thu, 21 Nov 2013 03:14:34 +0100 Subject: net: add BUG_ON if kernel advertises msg_namelen > sizeof(struct sockaddr_storage) [ Upstream commit 68c6beb373955da0886d8f4f5995b3922ceda4be ] In that case it is probable that kernel code overwrote part of the stack. So we should bail out loudly here. The BUG_ON may be removed in future if we are sure all protocols are conformant. Suggested-by: Eric Dumazet Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/socket.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/socket.c b/net/socket.c index 9f7d6263f7fa..921d1a55c32d 100644 --- a/net/socket.c +++ b/net/socket.c @@ -215,12 +215,13 @@ static int move_addr_to_user(struct sockaddr_storage *kaddr, int klen, int err; int len; + BUG_ON(klen > sizeof(struct sockaddr_storage)); err = get_user(len, ulen); if (err) return err; if (len > klen) len = klen; - if (len < 0 || len > sizeof(struct sockaddr_storage)) + if (len < 0) return -EINVAL; if (len) { if (audit_sockaddr(klen, kaddr)) -- cgit v1.2.3 From 08c62a109ed5f716556b2211f8cfd0d5fe6d18d2 Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Sat, 23 Nov 2013 00:46:12 +0100 Subject: inet: fix addr_len/msg->msg_namelen assignment in recv_error and rxpmtu functions [ Upstream commit 85fbaa75037d0b6b786ff18658ddf0b4014ce2a4 ] Commit bceaa90240b6019ed73b49965eac7d167610be69 ("inet: prevent leakage of uninitialized memory to user in recv syscalls") conditionally updated addr_len if the msg_name is written to. The recv_error and rxpmtu functions relied on the recvmsg functions to set up addr_len before. As this does not happen any more we have to pass addr_len to those functions as well and set it to the size of the corresponding sockaddr length. This broke traceroute and such. Fixes: bceaa90240b6 ("inet: prevent leakage of uninitialized memory to user in recv syscalls") Reported-by: Brad Spengler Reported-by: Tom Labanowski Cc: mpb Cc: David S. Miller Cc: Eric Dumazet Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/net/ip.h | 2 +- include/net/ipv6.h | 6 ++++-- net/ipv4/ip_sockglue.c | 3 ++- net/ipv4/ping.c | 2 +- net/ipv4/raw.c | 2 +- net/ipv4/udp.c | 2 +- net/ipv6/datagram.c | 7 +++++-- net/ipv6/raw.c | 4 ++-- net/ipv6/udp.c | 4 ++-- net/l2tp/l2tp_ip6.c | 2 +- 10 files changed, 20 insertions(+), 14 deletions(-) diff --git a/include/net/ip.h b/include/net/ip.h index edfa59174d9a..788f1d8a796f 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -454,7 +454,7 @@ extern int compat_ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen); extern int ip_ra_control(struct sock *sk, unsigned char on, void (*destructor)(struct sock *)); -extern int ip_recv_error(struct sock *sk, struct msghdr *msg, int len); +extern int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len); extern void ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err, __be16 port, u32 info, u8 *payload); extern void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 dport, diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 0810aa57c780..9e093fc33dab 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -793,8 +793,10 @@ extern int compat_ipv6_getsockopt(struct sock *sk, extern int ip6_datagram_connect(struct sock *sk, struct sockaddr *addr, int addr_len); -extern int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len); -extern int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len); +extern int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, + int *addr_len); +extern int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len, + int *addr_len); extern void ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err, __be16 port, u32 info, u8 *payload); extern void ipv6_local_error(struct sock *sk, int err, struct flowi6 *fl6, u32 info); diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index d9c4f113d709..23e6ab0a2dc0 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c @@ -368,7 +368,7 @@ void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 port, u32 inf /* * Handle MSG_ERRQUEUE */ -int ip_recv_error(struct sock *sk, struct msghdr *msg, int len) +int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) { struct sock_exterr_skb *serr; struct sk_buff *skb, *skb2; @@ -405,6 +405,7 @@ int ip_recv_error(struct sock *sk, struct msghdr *msg, int len) serr->addr_offset); sin->sin_port = serr->port; memset(&sin->sin_zero, 0, sizeof(sin->sin_zero)); + *addr_len = sizeof(*sin); } memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err)); diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index be01d5b8571a..a475b30ce289 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c @@ -636,7 +636,7 @@ static int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, goto out; if (flags & MSG_ERRQUEUE) - return ip_recv_error(sk, msg, len); + return ip_recv_error(sk, msg, len, addr_len); skb = skb_recv_datagram(sk, flags, noblock, &err); if (!skb) diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 448e5a77fa88..402870fdfa0e 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -693,7 +693,7 @@ static int raw_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, goto out; if (flags & MSG_ERRQUEUE) { - err = ip_recv_error(sk, msg, len); + err = ip_recv_error(sk, msg, len, addr_len); goto out; } diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index eeb3474daa3f..2e65ac850ca6 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1208,7 +1208,7 @@ int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, bool slow; if (flags & MSG_ERRQUEUE) - return ip_recv_error(sk, msg, len); + return ip_recv_error(sk, msg, len, addr_len); try_again: skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0), diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 4b56cbbc7890..e0a30a7f32bf 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c @@ -318,7 +318,7 @@ void ipv6_local_rxpmtu(struct sock *sk, struct flowi6 *fl6, u32 mtu) /* * Handle MSG_ERRQUEUE */ -int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len) +int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) { struct ipv6_pinfo *np = inet6_sk(sk); struct sock_exterr_skb *serr; @@ -369,6 +369,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len) &sin->sin6_addr); sin->sin6_scope_id = 0; } + *addr_len = sizeof(*sin); } memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err)); @@ -423,7 +424,8 @@ EXPORT_SYMBOL_GPL(ipv6_recv_error); /* * Handle IPV6_RECVPATHMTU */ -int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len) +int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len, + int *addr_len) { struct ipv6_pinfo *np = inet6_sk(sk); struct sk_buff *skb; @@ -457,6 +459,7 @@ int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len) sin->sin6_port = 0; sin->sin6_scope_id = mtu_info.ip6m_addr.sin6_scope_id; sin->sin6_addr = mtu_info.ip6m_addr.sin6_addr; + *addr_len = sizeof(*sin); } put_cmsg(msg, SOL_IPV6, IPV6_PATHMTU, sizeof(mtu_info), &mtu_info); diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index d3c01a601955..464b1c9c08e4 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -460,10 +460,10 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk, return -EOPNOTSUPP; if (flags & MSG_ERRQUEUE) - return ipv6_recv_error(sk, msg, len); + return ipv6_recv_error(sk, msg, len, addr_len); if (np->rxpmtu && np->rxopt.bits.rxpmtu) - return ipv6_recv_rxpmtu(sk, msg, len); + return ipv6_recv_rxpmtu(sk, msg, len, addr_len); skb = skb_recv_datagram(sk, flags, noblock, &err); if (!skb) diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index f10f1186da0b..6b298dc614e3 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -374,10 +374,10 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk, bool slow; if (flags & MSG_ERRQUEUE) - return ipv6_recv_error(sk, msg, len); + return ipv6_recv_error(sk, msg, len, addr_len); if (np->rxpmtu && np->rxopt.bits.rxpmtu) - return ipv6_recv_rxpmtu(sk, msg, len); + return ipv6_recv_rxpmtu(sk, msg, len, addr_len); try_again: skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0), diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c index b8a6039314e8..e6e8408c9e36 100644 --- a/net/l2tp/l2tp_ip6.c +++ b/net/l2tp/l2tp_ip6.c @@ -665,7 +665,7 @@ static int l2tp_ip6_recvmsg(struct kiocb *iocb, struct sock *sk, *addr_len = sizeof(*lsa); if (flags & MSG_ERRQUEUE) - return ipv6_recv_error(sk, msg, len); + return ipv6_recv_error(sk, msg, len, addr_len); skb = skb_recv_datagram(sk, flags, noblock, &err); if (!skb) -- cgit v1.2.3 From ed47bba241c68cd39964dac3248e0a2962c8b7ff Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 27 Nov 2013 15:40:21 +0300 Subject: net: clamp ->msg_namelen instead of returning an error [ Upstream commit db31c55a6fb245fdbb752a2ca4aefec89afabb06 ] If kmsg->msg_namelen > sizeof(struct sockaddr_storage) then in the original code that would lead to memory corruption in the kernel if you had audit configured. If you didn't have audit configured it was harmless. There are some programs such as beta versions of Ruby which use too large of a buffer and returning an error code breaks them. We should clamp the ->msg_namelen value instead. Fixes: 1661bf364ae9 ("net: heap overflow in __audit_sockaddr()") Reported-by: Eric Wong Signed-off-by: Dan Carpenter Tested-by: Eric Wong Acked-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/compat.c | 2 +- net/socket.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/net/compat.c b/net/compat.c index 618c6a8a911b..dd32e34c1e2c 100644 --- a/net/compat.c +++ b/net/compat.c @@ -72,7 +72,7 @@ int get_compat_msghdr(struct msghdr *kmsg, struct compat_msghdr __user *umsg) __get_user(kmsg->msg_flags, &umsg->msg_flags)) return -EFAULT; if (kmsg->msg_namelen > sizeof(struct sockaddr_storage)) - return -EINVAL; + kmsg->msg_namelen = sizeof(struct sockaddr_storage); kmsg->msg_name = compat_ptr(tmp1); kmsg->msg_iov = compat_ptr(tmp2); kmsg->msg_control = compat_ptr(tmp3); diff --git a/net/socket.c b/net/socket.c index 921d1a55c32d..ac72efc3d965 100644 --- a/net/socket.c +++ b/net/socket.c @@ -1965,7 +1965,7 @@ static int copy_msghdr_from_user(struct msghdr *kmsg, if (copy_from_user(kmsg, umsg, sizeof(struct msghdr))) return -EFAULT; if (kmsg->msg_namelen > sizeof(struct sockaddr_storage)) - return -EINVAL; + kmsg->msg_namelen = sizeof(struct sockaddr_storage); return 0; } -- cgit v1.2.3 From 2d71627c5af3a50d3b22fe6900b6dd29e0445fd7 Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Sat, 23 Nov 2013 07:22:33 +0100 Subject: ipv6: fix leaking uninitialized port number of offender sockaddr [ Upstream commit 1fa4c710b6fe7b0aac9907240291b6fe6aafc3b8 ] Offenders don't have port numbers, so set it to 0. Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv6/datagram.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index e0a30a7f32bf..8997340e3742 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c @@ -378,6 +378,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) if (serr->ee.ee_origin != SO_EE_ORIGIN_LOCAL) { sin->sin6_family = AF_INET6; sin->sin6_flowinfo = 0; + sin->sin6_port = 0; if (skb->protocol == htons(ETH_P_IPV6)) { sin->sin6_addr = ipv6_hdr(skb)->saddr; if (np->rxopt.all) -- cgit v1.2.3 From 2d9a30962d0310d33372c245a6191499a06409f3 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Wed, 6 Nov 2013 17:52:19 +0100 Subject: ip6_output: fragment outgoing reassembled skb properly [ Upstream commit 9037c3579a277f3a23ba476664629fda8c35f7c4 ] If reassembled packet would fit into outdev MTU, it is not fragmented according the original frag size and it is send as single big packet. The second case is if skb is gso. In that case fragmentation does not happen according to the original frag size. This patch fixes these. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv6/ip6_output.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 878f8027ebf6..53630d0d0f43 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -150,7 +150,8 @@ static int ip6_finish_output2(struct sk_buff *skb) static int ip6_finish_output(struct sk_buff *skb) { if ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) || - dst_allfrag(skb_dst(skb))) + dst_allfrag(skb_dst(skb)) || + (IP6CB(skb)->frag_max_size && skb->len > IP6CB(skb)->frag_max_size)) return ip6_fragment(skb, ip6_finish_output2); else return ip6_finish_output2(skb); -- cgit v1.2.3 From fddd8b501c59c87d63a0917c8e9e14bd28e3c724 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Wed, 6 Nov 2013 17:52:20 +0100 Subject: netfilter: push reasm skb through instead of original frag skbs [ Upstream commit 6aafeef03b9d9ecf255f3a80ed85ee070260e1ae ] Pushing original fragments through causes several problems. For example for matching, frags may not be matched correctly. Take following example: On HOSTA do: ip6tables -I INPUT -p icmpv6 -j DROP ip6tables -I INPUT -p icmpv6 -m icmp6 --icmpv6-type 128 -j ACCEPT and on HOSTB you do: ping6 HOSTA -s2000 (MTU is 1500) Incoming echo requests will be filtered out on HOSTA. This issue does not occur with smaller packets than MTU (where fragmentation does not happen) As was discussed previously, the only correct solution seems to be to use reassembled skb instead of separete frags. Doing this has positive side effects in reducing sk_buff by one pointer (nfct_reasm) and also the reams dances in ipvs and conntrack can be removed. Future plan is to remove net/ipv6/netfilter/nf_conntrack_reasm.c entirely and use code in net/ipv6/reassembly.c instead. Signed-off-by: Jiri Pirko Acked-by: Julian Anastasov Signed-off-by: Marcelo Ricardo Leitner Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/linux/skbuff.h | 32 --------------- include/net/ip_vs.h | 32 +-------------- include/net/netfilter/ipv6/nf_defrag_ipv6.h | 5 +-- net/core/skbuff.c | 3 -- net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 54 +------------------------ net/ipv6/netfilter/nf_conntrack_reasm.c | 19 +-------- net/ipv6/netfilter/nf_defrag_ipv6_hooks.c | 7 +++- net/netfilter/ipvs/ip_vs_core.c | 55 +------------------------- net/netfilter/ipvs/ip_vs_pe_sip.c | 8 +--- 9 files changed, 13 insertions(+), 202 deletions(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index eaf602781635..74db47ec09ea 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -331,11 +331,6 @@ typedef unsigned int sk_buff_data_t; typedef unsigned char *sk_buff_data_t; #endif -#if defined(CONFIG_NF_DEFRAG_IPV4) || defined(CONFIG_NF_DEFRAG_IPV4_MODULE) || \ - defined(CONFIG_NF_DEFRAG_IPV6) || defined(CONFIG_NF_DEFRAG_IPV6_MODULE) -#define NET_SKBUFF_NF_DEFRAG_NEEDED 1 -#endif - /** * struct sk_buff - socket buffer * @next: Next buffer in list @@ -368,7 +363,6 @@ typedef unsigned char *sk_buff_data_t; * @protocol: Packet protocol from driver * @destructor: Destruct function * @nfct: Associated connection, if any - * @nfct_reasm: netfilter conntrack re-assembly pointer * @nf_bridge: Saved data about a bridged frame - see br_netfilter.c * @skb_iif: ifindex of device we arrived on * @tc_index: Traffic control index @@ -455,9 +449,6 @@ struct sk_buff { #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) struct nf_conntrack *nfct; #endif -#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED - struct sk_buff *nfct_reasm; -#endif #ifdef CONFIG_BRIDGE_NETFILTER struct nf_bridge_info *nf_bridge; #endif @@ -2700,18 +2691,6 @@ static inline void nf_conntrack_get(struct nf_conntrack *nfct) atomic_inc(&nfct->use); } #endif -#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED -static inline void nf_conntrack_get_reasm(struct sk_buff *skb) -{ - if (skb) - atomic_inc(&skb->users); -} -static inline void nf_conntrack_put_reasm(struct sk_buff *skb) -{ - if (skb) - kfree_skb(skb); -} -#endif #ifdef CONFIG_BRIDGE_NETFILTER static inline void nf_bridge_put(struct nf_bridge_info *nf_bridge) { @@ -2730,10 +2709,6 @@ static inline void nf_reset(struct sk_buff *skb) nf_conntrack_put(skb->nfct); skb->nfct = NULL; #endif -#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED - nf_conntrack_put_reasm(skb->nfct_reasm); - skb->nfct_reasm = NULL; -#endif #ifdef CONFIG_BRIDGE_NETFILTER nf_bridge_put(skb->nf_bridge); skb->nf_bridge = NULL; @@ -2755,10 +2730,6 @@ static inline void __nf_copy(struct sk_buff *dst, const struct sk_buff *src) nf_conntrack_get(src->nfct); dst->nfctinfo = src->nfctinfo; #endif -#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED - dst->nfct_reasm = src->nfct_reasm; - nf_conntrack_get_reasm(src->nfct_reasm); -#endif #ifdef CONFIG_BRIDGE_NETFILTER dst->nf_bridge = src->nf_bridge; nf_bridge_get(src->nf_bridge); @@ -2770,9 +2741,6 @@ static inline void nf_copy(struct sk_buff *dst, const struct sk_buff *src) #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) nf_conntrack_put(dst->nfct); #endif -#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED - nf_conntrack_put_reasm(dst->nfct_reasm); -#endif #ifdef CONFIG_BRIDGE_NETFILTER nf_bridge_put(dst->nf_bridge); #endif diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index 4c062ccff9aa..f0c13a386bf3 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h @@ -109,7 +109,6 @@ extern int ip_vs_conn_tab_size; struct ip_vs_iphdr { __u32 len; /* IPv4 simply where L4 starts IPv6 where L4 Transport Header starts */ - __u32 thoff_reasm; /* Transport Header Offset in nfct_reasm skb */ __u16 fragoffs; /* IPv6 fragment offset, 0 if first frag (or not frag)*/ __s16 protocol; __s32 flags; @@ -117,34 +116,12 @@ struct ip_vs_iphdr { union nf_inet_addr daddr; }; -/* Dependency to module: nf_defrag_ipv6 */ -#if defined(CONFIG_NF_DEFRAG_IPV6) || defined(CONFIG_NF_DEFRAG_IPV6_MODULE) -static inline struct sk_buff *skb_nfct_reasm(const struct sk_buff *skb) -{ - return skb->nfct_reasm; -} -static inline void *frag_safe_skb_hp(const struct sk_buff *skb, int offset, - int len, void *buffer, - const struct ip_vs_iphdr *ipvsh) -{ - if (unlikely(ipvsh->fragoffs && skb_nfct_reasm(skb))) - return skb_header_pointer(skb_nfct_reasm(skb), - ipvsh->thoff_reasm, len, buffer); - - return skb_header_pointer(skb, offset, len, buffer); -} -#else -static inline struct sk_buff *skb_nfct_reasm(const struct sk_buff *skb) -{ - return NULL; -} static inline void *frag_safe_skb_hp(const struct sk_buff *skb, int offset, int len, void *buffer, const struct ip_vs_iphdr *ipvsh) { return skb_header_pointer(skb, offset, len, buffer); } -#endif static inline void ip_vs_fill_ip4hdr(const void *nh, struct ip_vs_iphdr *iphdr) @@ -171,19 +148,12 @@ ip_vs_fill_iph_skb(int af, const struct sk_buff *skb, struct ip_vs_iphdr *iphdr) (struct ipv6hdr *)skb_network_header(skb); iphdr->saddr.in6 = iph->saddr; iphdr->daddr.in6 = iph->daddr; - /* ipv6_find_hdr() updates len, flags, thoff_reasm */ - iphdr->thoff_reasm = 0; + /* ipv6_find_hdr() updates len, flags */ iphdr->len = 0; iphdr->flags = 0; iphdr->protocol = ipv6_find_hdr(skb, &iphdr->len, -1, &iphdr->fragoffs, &iphdr->flags); - /* get proto from re-assembled packet and it's offset */ - if (skb_nfct_reasm(skb)) - iphdr->protocol = ipv6_find_hdr(skb_nfct_reasm(skb), - &iphdr->thoff_reasm, - -1, NULL, NULL); - } else #endif { diff --git a/include/net/netfilter/ipv6/nf_defrag_ipv6.h b/include/net/netfilter/ipv6/nf_defrag_ipv6.h index fd79c9a1779d..17920d847b40 100644 --- a/include/net/netfilter/ipv6/nf_defrag_ipv6.h +++ b/include/net/netfilter/ipv6/nf_defrag_ipv6.h @@ -6,10 +6,7 @@ extern void nf_defrag_ipv6_enable(void); extern int nf_ct_frag6_init(void); extern void nf_ct_frag6_cleanup(void); extern struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user); -extern void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb, - struct net_device *in, - struct net_device *out, - int (*okfn)(struct sk_buff *)); +extern void nf_ct_frag6_consume_orig(struct sk_buff *skb); struct inet_frags_ctl; diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 1c1738cc4538..d9e8736bcdc1 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -585,9 +585,6 @@ static void skb_release_head_state(struct sk_buff *skb) #if IS_ENABLED(CONFIG_NF_CONNTRACK) nf_conntrack_put(skb->nfct); #endif -#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED - nf_conntrack_put_reasm(skb->nfct_reasm); -#endif #ifdef CONFIG_BRIDGE_NETFILTER nf_bridge_put(skb->nf_bridge); #endif diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index c9b6a6e6a1e8..97cd7507c1a4 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c @@ -172,63 +172,13 @@ out: return nf_conntrack_confirm(skb); } -static unsigned int __ipv6_conntrack_in(struct net *net, - unsigned int hooknum, - struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - int (*okfn)(struct sk_buff *)) -{ - struct sk_buff *reasm = skb->nfct_reasm; - const struct nf_conn_help *help; - struct nf_conn *ct; - enum ip_conntrack_info ctinfo; - - /* This packet is fragmented and has reassembled packet. */ - if (reasm) { - /* Reassembled packet isn't parsed yet ? */ - if (!reasm->nfct) { - unsigned int ret; - - ret = nf_conntrack_in(net, PF_INET6, hooknum, reasm); - if (ret != NF_ACCEPT) - return ret; - } - - /* Conntrack helpers need the entire reassembled packet in the - * POST_ROUTING hook. In case of unconfirmed connections NAT - * might reassign a helper, so the entire packet is also - * required. - */ - ct = nf_ct_get(reasm, &ctinfo); - if (ct != NULL && !nf_ct_is_untracked(ct)) { - help = nfct_help(ct); - if ((help && help->helper) || !nf_ct_is_confirmed(ct)) { - nf_conntrack_get_reasm(reasm); - NF_HOOK_THRESH(NFPROTO_IPV6, hooknum, reasm, - (struct net_device *)in, - (struct net_device *)out, - okfn, NF_IP6_PRI_CONNTRACK + 1); - return NF_DROP_ERR(-ECANCELED); - } - } - - nf_conntrack_get(reasm->nfct); - skb->nfct = reasm->nfct; - skb->nfctinfo = reasm->nfctinfo; - return NF_ACCEPT; - } - - return nf_conntrack_in(net, PF_INET6, hooknum, skb); -} - static unsigned int ipv6_conntrack_in(unsigned int hooknum, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) { - return __ipv6_conntrack_in(dev_net(in), hooknum, skb, in, out, okfn); + return nf_conntrack_in(dev_net(in), PF_INET6, hooknum, skb); } static unsigned int ipv6_conntrack_local(unsigned int hooknum, @@ -242,7 +192,7 @@ static unsigned int ipv6_conntrack_local(unsigned int hooknum, net_notice_ratelimited("ipv6_conntrack_local: packet too short\n"); return NF_ACCEPT; } - return __ipv6_conntrack_in(dev_net(out), hooknum, skb, in, out, okfn); + return nf_conntrack_in(dev_net(out), PF_INET6, hooknum, skb); } static struct nf_hook_ops ipv6_conntrack_ops[] __read_mostly = { diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index dffdc1a389c5..253566a8d55b 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c @@ -621,31 +621,16 @@ ret_orig: return skb; } -void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb, - struct net_device *in, struct net_device *out, - int (*okfn)(struct sk_buff *)) +void nf_ct_frag6_consume_orig(struct sk_buff *skb) { struct sk_buff *s, *s2; - unsigned int ret = 0; for (s = NFCT_FRAG6_CB(skb)->orig; s;) { - nf_conntrack_put_reasm(s->nfct_reasm); - nf_conntrack_get_reasm(skb); - s->nfct_reasm = skb; - s2 = s->next; s->next = NULL; - - if (ret != -ECANCELED) - ret = NF_HOOK_THRESH(NFPROTO_IPV6, hooknum, s, - in, out, okfn, - NF_IP6_PRI_CONNTRACK_DEFRAG + 1); - else - kfree_skb(s); - + consume_skb(s); s = s2; } - nf_conntrack_put_reasm(skb); } static int nf_ct_net_init(struct net *net) diff --git a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c index aacd121fe8c5..581dd9ede0de 100644 --- a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c +++ b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c @@ -75,8 +75,11 @@ static unsigned int ipv6_defrag(unsigned int hooknum, if (reasm == skb) return NF_ACCEPT; - nf_ct_frag6_output(hooknum, reasm, (struct net_device *)in, - (struct net_device *)out, okfn); + nf_ct_frag6_consume_orig(reasm); + + NF_HOOK_THRESH(NFPROTO_IPV6, hooknum, reasm, + (struct net_device *) in, (struct net_device *) out, + okfn, NF_IP6_PRI_CONNTRACK_DEFRAG + 1); return NF_STOLEN; } diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index 23b8eb53a569..21a3a475d7cd 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c @@ -1131,12 +1131,6 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af) ip_vs_fill_iph_skb(af, skb, &iph); #ifdef CONFIG_IP_VS_IPV6 if (af == AF_INET6) { - if (!iph.fragoffs && skb_nfct_reasm(skb)) { - struct sk_buff *reasm = skb_nfct_reasm(skb); - /* Save fw mark for coming frags */ - reasm->ipvs_property = 1; - reasm->mark = skb->mark; - } if (unlikely(iph.protocol == IPPROTO_ICMPV6)) { int related; int verdict = ip_vs_out_icmp_v6(skb, &related, @@ -1606,12 +1600,6 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af) #ifdef CONFIG_IP_VS_IPV6 if (af == AF_INET6) { - if (!iph.fragoffs && skb_nfct_reasm(skb)) { - struct sk_buff *reasm = skb_nfct_reasm(skb); - /* Save fw mark for coming frags. */ - reasm->ipvs_property = 1; - reasm->mark = skb->mark; - } if (unlikely(iph.protocol == IPPROTO_ICMPV6)) { int related; int verdict = ip_vs_in_icmp_v6(skb, &related, hooknum, @@ -1663,9 +1651,8 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af) /* sorry, all this trouble for a no-hit :) */ IP_VS_DBG_PKT(12, af, pp, skb, 0, "ip_vs_in: packet continues traversal as normal"); - if (iph.fragoffs && !skb_nfct_reasm(skb)) { + if (iph.fragoffs) { /* Fragment that couldn't be mapped to a conn entry - * and don't have any pointer to a reasm skb * is missing module nf_defrag_ipv6 */ IP_VS_DBG_RL("Unhandled frag, load nf_defrag_ipv6\n"); @@ -1747,38 +1734,6 @@ ip_vs_local_request4(unsigned int hooknum, struct sk_buff *skb, #ifdef CONFIG_IP_VS_IPV6 -/* - * AF_INET6 fragment handling - * Copy info from first fragment, to the rest of them. - */ -static unsigned int -ip_vs_preroute_frag6(unsigned int hooknum, struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - int (*okfn)(struct sk_buff *)) -{ - struct sk_buff *reasm = skb_nfct_reasm(skb); - struct net *net; - - /* Skip if not a "replay" from nf_ct_frag6_output or first fragment. - * ipvs_property is set when checking first fragment - * in ip_vs_in() and ip_vs_out(). - */ - if (reasm) - IP_VS_DBG(2, "Fragment recv prop:%d\n", reasm->ipvs_property); - if (!reasm || !reasm->ipvs_property) - return NF_ACCEPT; - - net = skb_net(skb); - if (!net_ipvs(net)->enable) - return NF_ACCEPT; - - /* Copy stored fw mark, saved in ip_vs_{in,out} */ - skb->mark = reasm->mark; - - return NF_ACCEPT; -} - /* * AF_INET6 handler in NF_INET_LOCAL_IN chain * Schedule and forward packets from remote clients @@ -1916,14 +1871,6 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = { .priority = 100, }, #ifdef CONFIG_IP_VS_IPV6 - /* After mangle & nat fetch 2:nd fragment and following */ - { - .hook = ip_vs_preroute_frag6, - .owner = THIS_MODULE, - .pf = NFPROTO_IPV6, - .hooknum = NF_INET_PRE_ROUTING, - .priority = NF_IP6_PRI_NAT_DST + 1, - }, /* After packet filtering, change source only for VS/NAT */ { .hook = ip_vs_reply6, diff --git a/net/netfilter/ipvs/ip_vs_pe_sip.c b/net/netfilter/ipvs/ip_vs_pe_sip.c index 9ef22bdce9f1..bed5f7042529 100644 --- a/net/netfilter/ipvs/ip_vs_pe_sip.c +++ b/net/netfilter/ipvs/ip_vs_pe_sip.c @@ -65,7 +65,6 @@ static int get_callid(const char *dptr, unsigned int dataoff, static int ip_vs_sip_fill_param(struct ip_vs_conn_param *p, struct sk_buff *skb) { - struct sk_buff *reasm = skb_nfct_reasm(skb); struct ip_vs_iphdr iph; unsigned int dataoff, datalen, matchoff, matchlen; const char *dptr; @@ -79,15 +78,10 @@ ip_vs_sip_fill_param(struct ip_vs_conn_param *p, struct sk_buff *skb) /* todo: IPv6 fragments: * I think this only should be done for the first fragment. /HS */ - if (reasm) { - skb = reasm; - dataoff = iph.thoff_reasm + sizeof(struct udphdr); - } else - dataoff = iph.len + sizeof(struct udphdr); + dataoff = iph.len + sizeof(struct udphdr); if (dataoff >= skb->len) return -EINVAL; - /* todo: Check if this will mess-up the reasm skb !!! /HS */ retc = skb_linearize(skb); if (retc < 0) return retc; -- cgit v1.2.3 From bdf1643e0536042df717443d6bfd73e07643c237 Mon Sep 17 00:00:00 2001 From: "fan.du" Date: Tue, 19 Nov 2013 16:53:28 +0800 Subject: xfrm: Release dst if this dst is improper for vti tunnel [ Upstream commit 236c9f84868534c718b6889aa624de64763281f9 ] After searching rt by the vti tunnel dst/src parameter, if this rt has neither attached to any transformation nor the transformation is not tunnel oriented, this rt should be released back to ip layer. otherwise causing dst memory leakage. Signed-off-by: Fan Du Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/ip_vti.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c index 065604127418..feb19db62359 100644 --- a/net/ipv4/ip_vti.c +++ b/net/ipv4/ip_vti.c @@ -350,6 +350,7 @@ static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) if (!rt->dst.xfrm || rt->dst.xfrm->props.mode != XFRM_MODE_TUNNEL) { dev->stats.tx_carrier_errors++; + ip_rt_put(rt); goto tx_error_icmp; } tdev = rt->dst.dev; -- cgit v1.2.3 From e1667fa212d940b130c4f5d839bdd0091d2b0128 Mon Sep 17 00:00:00 2001 From: Ying Xue Date: Tue, 19 Nov 2013 18:09:27 +0800 Subject: atm: idt77252: fix dev refcnt leak [ Upstream commit b5de4a22f157ca345cdb3575207bf46402414bc1 ] init_card() calls dev_get_by_name() to get a network deceive. But it doesn't decrease network device reference count after the device is used. Signed-off-by: Ying Xue Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/atm/idt77252.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c index 272f00927761..1bdf104e90bb 100644 --- a/drivers/atm/idt77252.c +++ b/drivers/atm/idt77252.c @@ -3511,7 +3511,7 @@ static int init_card(struct atm_dev *dev) tmp = dev_get_by_name(&init_net, tname); /* jhs: was "tmp = dev_get(tname);" */ if (tmp) { memcpy(card->atmdev->esi, tmp->dev_addr, 6); - + dev_put(tmp); printk("%s: ESI %pM\n", card->name, card->atmdev->esi); } /* -- cgit v1.2.3 From 8392415810ff70ffb61ed1d4dbe5672ce34de9a2 Mon Sep 17 00:00:00 2001 From: Andrey Vagin Date: Tue, 19 Nov 2013 22:10:06 +0400 Subject: tcp: don't update snd_nxt, when a socket is switched from repair mode [ Upstream commit dbde497966804e63a38fdedc1e3815e77097efc2 ] snd_nxt must be updated synchronously with sk_send_head. Otherwise tp->packets_out may be updated incorrectly, what may bring a kernel panic. Here is a kernel panic from my host. [ 103.043194] BUG: unable to handle kernel NULL pointer dereference at 0000000000000048 [ 103.044025] IP: [] tcp_rearm_rto+0xcf/0x150 ... [ 146.301158] Call Trace: [ 146.301158] [] tcp_ack+0xcc0/0x12c0 Before this panic a tcp socket was restored. This socket had sent and unsent data in the write queue. Sent data was restored in repair mode, then the socket was switched from reapair mode and unsent data was restored. After that the socket was switched back into repair mode. In that moment we had a socket where write queue looks like this: snd_una snd_nxt write_seq |_________|________| | sk_send_head After a second switching from repair mode the state of socket was changed: snd_una snd_nxt, write_seq |_________ ________| | sk_send_head This state is inconsistent, because snd_nxt and sk_send_head are not synchronized. Bellow you can find a call trace, how packets_out can be incremented twice for one skb, if snd_nxt and sk_send_head are not synchronized. In this case packets_out will be always positive, even when sk_write_queue is empty. tcp_write_wakeup skb = tcp_send_head(sk); tcp_fragment if (!before(tp->snd_nxt, TCP_SKB_CB(buff)->end_seq)) tcp_adjust_pcount(sk, skb, diff); tcp_event_new_data_sent tp->packets_out += tcp_skb_pcount(skb); I think update of snd_nxt isn't required, when a socket is switched from repair mode. Because it's initialized in tcp_connect_init. Then when a write queue is restored, snd_nxt is incremented in tcp_event_new_data_sent, so it's always is in consistent state. I have checked, that the bug is not reproduced with this patch and all tests about restoring tcp connections work fine. Signed-off-by: Andrey Vagin Cc: Pavel Emelyanov Cc: Eric Dumazet Cc: "David S. Miller" Cc: Alexey Kuznetsov Cc: James Morris Cc: Hideaki YOSHIFUJI Cc: Patrick McHardy Acked-by: Pavel Emelyanov Acked-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/tcp_output.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index e21be13f74a6..5560abfe6d30 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -3102,7 +3102,6 @@ void tcp_send_window_probe(struct sock *sk) { if (sk->sk_state == TCP_ESTABLISHED) { tcp_sk(sk)->snd_wl1 = tcp_sk(sk)->rcv_nxt - 1; - tcp_sk(sk)->snd_nxt = tcp_sk(sk)->write_seq; tcp_xmit_probe_skb(sk, 0); } } -- cgit v1.2.3 From 62713c4b6bc10c2d082ee1540e11b01a2b2162ab Mon Sep 17 00:00:00 2001 From: Alexei Starovoitov Date: Tue, 19 Nov 2013 19:12:34 -0800 Subject: ipv4: fix race in concurrent ip_route_input_slow() [ Upstream commit dcdfdf56b4a6c9437fc37dbc9cee94a788f9b0c4 ] CPUs can ask for local route via ip_route_input_noref() concurrently. if nh_rth_input is not cached yet, CPUs will proceed to allocate equivalent DSTs on 'lo' and then will try to cache them in nh_rth_input via rt_cache_route() Most of the time they succeed, but on occasion the following two lines: orig = *p; prev = cmpxchg(p, orig, rt); in rt_cache_route() do race and one of the cpus fails to complete cmpxchg. But ip_route_input_slow() doesn't check the return code of rt_cache_route(), so dst is leaking. dst_destroy() is never called and 'lo' device refcnt doesn't go to zero, which can be seen in the logs as: unregister_netdevice: waiting for lo to become free. Usage count = 1 Adding mdelay() between above two lines makes it easily reproducible. Fix it similar to nh_pcpu_rth_output case. Fixes: d2d68ba9fe8b ("ipv4: Cache input routes in fib_info nexthops.") Signed-off-by: Alexei Starovoitov Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/route.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index d11e73ce9365..f6c6ab14da41 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1720,8 +1720,12 @@ local_input: rth->dst.error= -err; rth->rt_flags &= ~RTCF_LOCAL; } - if (do_cache) - rt_cache_route(&FIB_RES_NH(res), rth); + if (do_cache) { + if (unlikely(!rt_cache_route(&FIB_RES_NH(res), rth))) { + rth->dst.flags |= DST_NOCACHE; + rt_add_uncached_list(rth); + } + } skb_dst_set(skb, &rth->dst); err = 0; goto out; -- cgit v1.2.3 From 05cf2143b56099f6452b13b60593e2cc8c9aff51 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Tue, 19 Nov 2013 20:47:15 -0500 Subject: net: core: Always propagate flag changes to interfaces [ Upstream commit d2615bf450694c1302d86b9cc8a8958edfe4c3a4 ] The following commit: b6c40d68ff6498b7f63ddf97cf0aa818d748dee7 net: only invoke dev->change_rx_flags when device is UP tried to fix a problem with VLAN devices and promiscuouse flag setting. The issue was that VLAN device was setting a flag on an interface that was down, thus resulting in bad promiscuity count. This commit blocked flag propagation to any device that is currently down. A later commit: deede2fabe24e00bd7e246eb81cd5767dc6fcfc7 vlan: Don't propagate flag changes on down interfaces fixed VLAN code to only propagate flags when the VLAN interface is up, thus fixing the same issue as above, only localized to VLAN. The problem we have now is that if we have create a complex stack involving multiple software devices like bridges, bonds, and vlans, then it is possible that the flags would not propagate properly to the physical devices. A simple examle of the scenario is the following: eth0----> bond0 ----> bridge0 ---> vlan50 If bond0 or eth0 happen to be down at the time bond0 is added to the bridge, then eth0 will never have promisc mode set which is currently required for operation as part of the bridge. As a result, packets with vlan50 will be dropped by the interface. The only 2 devices that implement the special flag handling are VLAN and DSA and they both have required code to prevent incorrect flag propagation. As a result we can remove the generic solution introduced in b6c40d68ff6498b7f63ddf97cf0aa818d748dee7 and leave it to the individual devices to decide whether they will block flag propagation or not. Reported-by: Stefan Priebe Suggested-by: Veaceslav Falico Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/dev.c b/net/core/dev.c index 7ddbb31b10d3..1283c8442e99 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4478,7 +4478,7 @@ static void dev_change_rx_flags(struct net_device *dev, int flags) { const struct net_device_ops *ops = dev->netdev_ops; - if ((dev->flags & IFF_UP) && ops->ndo_change_rx_flags) + if (ops->ndo_change_rx_flags) ops->ndo_change_rx_flags(dev, flags); } -- cgit v1.2.3 From 1acb97aeff84a72999eeb9cbea523a0079c5ce6d Mon Sep 17 00:00:00 2001 From: Ding Tianhong Date: Sat, 7 Dec 2013 22:12:05 +0800 Subject: bridge: flush br's address entry in fdb when remove the bridge dev [ Upstream commit f873042093c0b418d2351fe142222b625c740149 ] When the following commands are executed: brctl addbr br0 ifconfig br0 hw ether rmmod bridge The calltrace will occur: [ 563.312114] device eth1 left promiscuous mode [ 563.312188] br0: port 1(eth1) entered disabled state [ 563.468190] kmem_cache_destroy bridge_fdb_cache: Slab cache still has objects [ 563.468197] CPU: 6 PID: 6982 Comm: rmmod Tainted: G O 3.12.0-0.7-default+ #9 [ 563.468199] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2007 [ 563.468200] 0000000000000880 ffff88010f111e98 ffffffff814d1c92 ffff88010f111eb8 [ 563.468204] ffffffff81148efd ffff88010f111eb8 0000000000000000 ffff88010f111ec8 [ 563.468206] ffffffffa062a270 ffff88010f111ed8 ffffffffa063ac76 ffff88010f111f78 [ 563.468209] Call Trace: [ 563.468218] [] dump_stack+0x6a/0x78 [ 563.468234] [] kmem_cache_destroy+0xfd/0x100 [ 563.468242] [] br_fdb_fini+0x10/0x20 [bridge] [ 563.468247] [] br_deinit+0x4e/0x50 [bridge] [ 563.468254] [] SyS_delete_module+0x199/0x2b0 [ 563.468259] [] system_call_fastpath+0x16/0x1b [ 570.377958] Bridge firewalling registered --------------------------- cut here ------------------------------- The reason is that when the bridge dev's address is changed, the br_fdb_change_mac_address() will add new address in fdb, but when the bridge was removed, the address entry in the fdb did not free, the bridge_fdb_cache still has objects when destroy the cache, Fix this by flushing the bridge address entry when removing the bridge. v2: according to the Toshiaki Makita and Vlad's suggestion, I only delete the vlan0 entry, it still have a leak here if the vlan id is other number, so I need to call fdb_delete_by_port(br, NULL, 1) to flush all entries whose dst is NULL for the bridge. Suggested-by: Toshiaki Makita Suggested-by: Vlad Yasevich Signed-off-by: Ding Tianhong Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/bridge/br_if.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 4cdba60926ff..32bd1e87f149 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -172,6 +172,8 @@ void br_dev_delete(struct net_device *dev, struct list_head *head) del_nbp(p); } + br_fdb_delete_by_port(br, NULL, 1); + del_timer_sync(&br->gc_timer); br_sysfs_delbr(br->dev); -- cgit v1.2.3 From 026bb4057a0473132bdfa910bd2089de1a7af3f6 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Thu, 21 Nov 2013 16:50:58 +0100 Subject: packet: fix use after free race in send path when dev is released [ Upstream commit e40526cb20b5ee53419452e1f03d97092f144418 ] Salam reported a use after free bug in PF_PACKET that occurs when we're sending out frames on a socket bound device and suddenly the net device is being unregistered. It appears that commit 827d9780 introduced a possible race condition between {t,}packet_snd() and packet_notifier(). In the case of a bound socket, packet_notifier() can drop the last reference to the net_device and {t,}packet_snd() might end up suddenly sending a packet over a freed net_device. To avoid reverting 827d9780 and thus introducing a performance regression compared to the current state of things, we decided to hold a cached RCU protected pointer to the net device and maintain it on write side via bind spin_lock protected register_prot_hook() and __unregister_prot_hook() calls. In {t,}packet_snd() path, we access this pointer under rcu_read_lock through packet_cached_dev_get() that holds reference to the device to prevent it from being freed through packet_notifier() while we're in send path. This is okay to do as dev_put()/dev_hold() are per-cpu counters, so this should not be a performance issue. Also, the code simplifies a bit as we don't need need_rls_dev anymore. Fixes: 827d978037d7 ("af-packet: Use existing netdev reference for bound sockets.") Reported-by: Salam Noureddine Signed-off-by: Daniel Borkmann Signed-off-by: Salam Noureddine Cc: Ben Greear Cc: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/packet/af_packet.c | 59 ++++++++++++++++++++++++++++++-------------------- net/packet/internal.h | 1 + 2 files changed, 37 insertions(+), 23 deletions(-) diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 92e2d0201f90..f0aa20c2bfbf 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -244,11 +244,15 @@ static void __fanout_link(struct sock *sk, struct packet_sock *po); static void register_prot_hook(struct sock *sk) { struct packet_sock *po = pkt_sk(sk); + if (!po->running) { - if (po->fanout) + if (po->fanout) { __fanout_link(sk, po); - else + } else { dev_add_pack(&po->prot_hook); + rcu_assign_pointer(po->cached_dev, po->prot_hook.dev); + } + sock_hold(sk); po->running = 1; } @@ -266,10 +270,13 @@ static void __unregister_prot_hook(struct sock *sk, bool sync) struct packet_sock *po = pkt_sk(sk); po->running = 0; - if (po->fanout) + if (po->fanout) { __fanout_unlink(sk, po); - else + } else { __dev_remove_pack(&po->prot_hook); + RCU_INIT_POINTER(po->cached_dev, NULL); + } + __sock_put(sk); if (sync) { @@ -2041,12 +2048,24 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb, return tp_len; } +static struct net_device *packet_cached_dev_get(struct packet_sock *po) +{ + struct net_device *dev; + + rcu_read_lock(); + dev = rcu_dereference(po->cached_dev); + if (dev) + dev_hold(dev); + rcu_read_unlock(); + + return dev; +} + static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) { struct sk_buff *skb; struct net_device *dev; __be16 proto; - bool need_rls_dev = false; int err, reserve = 0; void *ph; struct sockaddr_ll *saddr = (struct sockaddr_ll *)msg->msg_name; @@ -2059,7 +2078,7 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) mutex_lock(&po->pg_vec_lock); if (saddr == NULL) { - dev = po->prot_hook.dev; + dev = packet_cached_dev_get(po); proto = po->num; addr = NULL; } else { @@ -2073,19 +2092,17 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) proto = saddr->sll_protocol; addr = saddr->sll_addr; dev = dev_get_by_index(sock_net(&po->sk), saddr->sll_ifindex); - need_rls_dev = true; } err = -ENXIO; if (unlikely(dev == NULL)) goto out; - - reserve = dev->hard_header_len; - err = -ENETDOWN; if (unlikely(!(dev->flags & IFF_UP))) goto out_put; + reserve = dev->hard_header_len; + size_max = po->tx_ring.frame_size - (po->tp_hdrlen - sizeof(struct sockaddr_ll)); @@ -2162,8 +2179,7 @@ out_status: __packet_set_status(po, ph, status); kfree_skb(skb); out_put: - if (need_rls_dev) - dev_put(dev); + dev_put(dev); out: mutex_unlock(&po->pg_vec_lock); return err; @@ -2201,7 +2217,6 @@ static int packet_snd(struct socket *sock, struct sk_buff *skb; struct net_device *dev; __be16 proto; - bool need_rls_dev = false; unsigned char *addr; int err, reserve = 0; struct virtio_net_hdr vnet_hdr = { 0 }; @@ -2217,7 +2232,7 @@ static int packet_snd(struct socket *sock, */ if (saddr == NULL) { - dev = po->prot_hook.dev; + dev = packet_cached_dev_get(po); proto = po->num; addr = NULL; } else { @@ -2229,19 +2244,17 @@ static int packet_snd(struct socket *sock, proto = saddr->sll_protocol; addr = saddr->sll_addr; dev = dev_get_by_index(sock_net(sk), saddr->sll_ifindex); - need_rls_dev = true; } err = -ENXIO; - if (dev == NULL) + if (unlikely(dev == NULL)) goto out_unlock; - if (sock->type == SOCK_RAW) - reserve = dev->hard_header_len; - err = -ENETDOWN; - if (!(dev->flags & IFF_UP)) + if (unlikely(!(dev->flags & IFF_UP))) goto out_unlock; + if (sock->type == SOCK_RAW) + reserve = dev->hard_header_len; if (po->has_vnet_hdr) { vnet_hdr_len = sizeof(vnet_hdr); @@ -2375,15 +2388,14 @@ static int packet_snd(struct socket *sock, if (err > 0 && (err = net_xmit_errno(err)) != 0) goto out_unlock; - if (need_rls_dev) - dev_put(dev); + dev_put(dev); return len; out_free: kfree_skb(skb); out_unlock: - if (dev && need_rls_dev) + if (dev) dev_put(dev); out: return err; @@ -2603,6 +2615,7 @@ static int packet_create(struct net *net, struct socket *sock, int protocol, po = pkt_sk(sk); sk->sk_family = PF_PACKET; po->num = proto; + RCU_INIT_POINTER(po->cached_dev, NULL); sk->sk_destruct = packet_sock_destruct; sk_refcnt_debug_inc(sk); diff --git a/net/packet/internal.h b/net/packet/internal.h index c4e4b4561207..1035fa2d909c 100644 --- a/net/packet/internal.h +++ b/net/packet/internal.h @@ -113,6 +113,7 @@ struct packet_sock { unsigned int tp_loss:1; unsigned int tp_tx_has_off:1; unsigned int tp_tstamp; + struct net_device __rcu *cached_dev; struct packet_type prot_hook ____cacheline_aligned_in_smp; }; -- cgit v1.2.3 From 5b9e9be7756854ddd525fb9882f1feddd9435831 Mon Sep 17 00:00:00 2001 From: Veaceslav Falico Date: Fri, 29 Nov 2013 09:53:23 +0100 Subject: af_packet: block BH in prb_shutdown_retire_blk_timer() [ Upstream commit ec6f809ff6f19fafba3212f6aff0dda71dfac8e8 ] Currently we're using plain spin_lock() in prb_shutdown_retire_blk_timer(), however the timer might fire right in the middle and thus try to re-aquire the same spinlock, leaving us in a endless loop. To fix that, use the spin_lock_bh() to block it. Fixes: f6fb8f100b80 ("af-packet: TPACKET_V3 flexible buffer implementation.") CC: "David S. Miller" CC: Daniel Borkmann CC: Willem de Bruijn CC: Phil Sutter CC: Eric Dumazet Reported-by: Jan Stancek Tested-by: Jan Stancek Signed-off-by: Veaceslav Falico Acked-by: Daniel Borkmann Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/packet/af_packet.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index f0aa20c2bfbf..c503ad6f610f 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -439,9 +439,9 @@ static void prb_shutdown_retire_blk_timer(struct packet_sock *po, pkc = tx_ring ? &po->tx_ring.prb_bdqc : &po->rx_ring.prb_bdqc; - spin_lock(&rb_queue->lock); + spin_lock_bh(&rb_queue->lock); pkc->delete_blk_timer = 1; - spin_unlock(&rb_queue->lock); + spin_unlock_bh(&rb_queue->lock); prb_del_retire_blk_timer(pkc); } -- cgit v1.2.3 From 1562432658a5bf8aa32d25a99c30cfdda5b43818 Mon Sep 17 00:00:00 2001 From: David Chang Date: Wed, 27 Nov 2013 15:48:36 +0800 Subject: r8169: check ALDPS bit and disable it if enabled for the 8168g [ Upstream commit 1bac1072425c86f1ac85bd5967910706677ef8b3 ] Windows driver will enable ALDPS function, but linux driver and firmware do not have any configuration related to ALDPS function for 8168g. So restart system to linux and remove the NIC cable, LAN enter ALDPS, then LAN RX will be disabled. This issue can be easily reproduced on dual boot windows and linux system with RTL_GIGA_MAC_VER_40 chip. Realtek said, ALDPS function can be disabled by configuring to PHY, switch to page 0x0A43, reg0x10 bit2=0. Signed-off-by: David Chang Acked-by: Hayes Wang Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/realtek/r8169.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 7199d2a8dcf8..e9b5d77a90db 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -3456,6 +3456,11 @@ static void rtl8168g_1_hw_phy_config(struct rtl8169_private *tp) rtl_writephy(tp, 0x14, 0x9065); rtl_writephy(tp, 0x14, 0x1065); + /* Check ALDPS bit, disable it if enabled */ + rtl_writephy(tp, 0x1f, 0x0a43); + if (rtl_readphy(tp, 0x10) & 0x0004) + rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0004); + rtl_writephy(tp, 0x1f, 0x0000); } -- cgit v1.2.3 From ac3e7d9bc445b256fc386a30df55dfd1b3fda0be Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Wed, 27 Nov 2013 14:32:52 +0800 Subject: net: 8139cp: fix a BUG_ON triggered by wrong bytes_compl [ Upstream commit 7fe0ee099ad5e3dea88d4ee1b6f20246b1ca57c3 ] Using iperf to send packets(GSO mode is on), a bug is triggered: [ 212.672781] kernel BUG at lib/dynamic_queue_limits.c:26! [ 212.673396] invalid opcode: 0000 [#1] SMP [ 212.673882] Modules linked in: 8139cp(O) nls_utf8 edd fuse loop dm_mod ipv6 i2c_piix4 8139too i2c_core intel_agp joydev pcspkr hid_generic intel_gtt floppy sr_mod mii button sg cdrom ext3 jbd mbcache usbhid hid uhci_hcd ehci_hcd usbcore sd_mod usb_common crc_t10dif crct10dif_common processor thermal_sys hwmon scsi_dh_emc scsi_dh_rdac scsi_dh_hp_sw scsi_dh ata_generic ata_piix libata scsi_mod [last unloaded: 8139cp] [ 212.676084] CPU: 0 PID: 4124 Comm: iperf Tainted: G O 3.12.0-0.7-default+ #16 [ 212.676084] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2007 [ 212.676084] task: ffff8800d83966c0 ti: ffff8800db4c8000 task.ti: ffff8800db4c8000 [ 212.676084] RIP: 0010:[] [] dql_completed+0x17f/0x190 [ 212.676084] RSP: 0018:ffff880116e03e30 EFLAGS: 00010083 [ 212.676084] RAX: 00000000000005ea RBX: 0000000000000f7c RCX: 0000000000000002 [ 212.676084] RDX: ffff880111dd0dc0 RSI: 0000000000000bd4 RDI: ffff8800db6ffcc0 [ 212.676084] RBP: ffff880116e03e48 R08: 0000000000000992 R09: 0000000000000000 [ 212.676084] R10: ffffffff8181e400 R11: 0000000000000004 R12: 000000000000000f [ 212.676084] R13: ffff8800d94ec840 R14: ffff8800db440c80 R15: 000000000000000e [ 212.676084] FS: 00007f6685a3c700(0000) GS:ffff880116e00000(0000) knlGS:0000000000000000 [ 212.676084] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 212.676084] CR2: 00007f6685ad6460 CR3: 00000000db714000 CR4: 00000000000006f0 [ 212.676084] Stack: [ 212.676084] ffff8800db6ffc00 000000000000000f ffff8800d94ec840 ffff880116e03eb8 [ 212.676084] ffffffffa041509f ffff880116e03e88 0000000f16e03e88 ffff8800d94ec000 [ 212.676084] 00000bd400059858 000000050000000f ffffffff81094c36 ffff880116e03eb8 [ 212.676084] Call Trace: [ 212.676084] [ 212.676084] [] cp_interrupt+0x4ef/0x590 [8139cp] [ 212.676084] [] ? ktime_get+0x56/0xd0 [ 212.676084] [] handle_irq_event_percpu+0x53/0x170 [ 212.676084] [] handle_irq_event+0x3c/0x60 [ 212.676084] [] handle_fasteoi_irq+0x55/0xf0 [ 212.676084] [] handle_irq+0x1f/0x30 [ 212.676084] [] do_IRQ+0x5b/0xe0 [ 212.676084] [] common_interrupt+0x6a/0x6a [ 212.676084] [ 212.676084] [] ? cp_start_xmit+0x621/0x97c [8139cp] [ 212.676084] [] ? cp_start_xmit+0x609/0x97c [8139cp] [ 212.676084] [] dev_hard_start_xmit+0x2c9/0x550 [ 212.676084] [] sch_direct_xmit+0x179/0x1d0 [ 212.676084] [] dev_queue_xmit+0x293/0x440 [ 212.676084] [] ip_finish_output+0x236/0x450 [ 212.676084] [] ? __alloc_pages_nodemask+0x187/0xb10 [ 212.676084] [] ip_output+0x88/0x90 [ 212.676084] [] ip_local_out+0x24/0x30 [ 212.676084] [] ip_queue_xmit+0x14d/0x3e0 [ 212.676084] [] tcp_transmit_skb+0x501/0x840 [ 212.676084] [] tcp_write_xmit+0x1e3/0xb20 [ 212.676084] [] ? skb_page_frag_refill+0x87/0xd0 [ 212.676084] [] tcp_push_one+0x2b/0x40 [ 212.676084] [] tcp_sendmsg+0x926/0xc90 [ 212.676084] [] inet_sendmsg+0x61/0xc0 [ 212.676084] [] sock_aio_write+0x101/0x120 [ 212.676084] [] ? vma_adjust+0x2e1/0x5d0 [ 212.676084] [] ? timerqueue_add+0x60/0xb0 [ 212.676084] [] do_sync_write+0x60/0x90 [ 212.676084] [] ? rw_verify_area+0x54/0xf0 [ 212.676084] [] vfs_write+0x186/0x190 [ 212.676084] [] SyS_write+0x5d/0xa0 [ 212.676084] [] system_call_fastpath+0x16/0x1b [ 212.676084] Code: ca 41 89 dc 41 29 cc 45 31 db 29 c2 41 89 c5 89 d0 45 29 c5 f7 d0 c1 e8 1f e9 43 ff ff ff 66 0f 1f 44 00 00 31 c0 e9 7b ff ff ff <0f> 0b eb fe 66 66 66 66 2e 0f 1f 84 00 00 00 00 00 c7 47 40 00 [ 212.676084] RIP [] dql_completed+0x17f/0x190 ------------[ cut here ]------------ When a skb has frags, bytes_compl plus skb->len nr_frags times in cp_tx(). It's not the correct value(actually, it should plus skb->len once) and it will trigger the BUG_ON(bytes_compl > num_queued - dql->num_completed). So only increase bytes_compl when finish sending all frags. pkts_compl also has a wrong value, fix it too. It's introduced by commit 871f0d4c ("8139cp: enable bql"). Suggested-by: Eric Dumazet Signed-off-by: Yang Yingliang Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/realtek/8139cp.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c index 9095ff930f29..064425d3178d 100644 --- a/drivers/net/ethernet/realtek/8139cp.c +++ b/drivers/net/ethernet/realtek/8139cp.c @@ -678,9 +678,6 @@ static void cp_tx (struct cp_private *cp) le32_to_cpu(txd->opts1) & 0xffff, PCI_DMA_TODEVICE); - bytes_compl += skb->len; - pkts_compl++; - if (status & LastFrag) { if (status & (TxError | TxFIFOUnder)) { netif_dbg(cp, tx_err, cp->dev, @@ -702,6 +699,8 @@ static void cp_tx (struct cp_private *cp) netif_dbg(cp, tx_done, cp->dev, "tx done, slot %d\n", tx_tail); } + bytes_compl += skb->len; + pkts_compl++; dev_kfree_skb_irq(skb); } -- cgit v1.2.3 From 86a243440a102e315438c6faf57881796533528d Mon Sep 17 00:00:00 2001 From: Shawn Landden Date: Sun, 24 Nov 2013 22:36:28 -0800 Subject: net: update consumers of MSG_MORE to recognize MSG_SENDPAGE_NOTLAST [ Upstream commit d3f7d56a7a4671d395e8af87071068a195257bf6 ] Commit 35f9c09fe (tcp: tcp_sendpages() should call tcp_push() once) added an internal flag MSG_SENDPAGE_NOTLAST, similar to MSG_MORE. algif_hash, algif_skcipher, and udp used MSG_MORE from tcp_sendpages() and need to see the new flag as identical to MSG_MORE. This fixes sendfile() on AF_ALG. v3: also fix udp Reported-and-tested-by: Shawn Landden Cc: Tom Herbert Cc: Eric Dumazet Cc: David S. Miller Original-patch: Richard Weinberger Signed-off-by: Shawn Landden Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- crypto/algif_hash.c | 3 +++ crypto/algif_skcipher.c | 3 +++ net/ipv4/udp.c | 3 +++ 3 files changed, 9 insertions(+) diff --git a/crypto/algif_hash.c b/crypto/algif_hash.c index ef5356cd280a..850246206b12 100644 --- a/crypto/algif_hash.c +++ b/crypto/algif_hash.c @@ -114,6 +114,9 @@ static ssize_t hash_sendpage(struct socket *sock, struct page *page, struct hash_ctx *ctx = ask->private; int err; + if (flags & MSG_SENDPAGE_NOTLAST) + flags |= MSG_MORE; + lock_sock(sk); sg_init_table(ctx->sgl.sg, 1); sg_set_page(ctx->sgl.sg, page, size, offset); diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c index 6a6dfc062d2a..a19c027b29bd 100644 --- a/crypto/algif_skcipher.c +++ b/crypto/algif_skcipher.c @@ -378,6 +378,9 @@ static ssize_t skcipher_sendpage(struct socket *sock, struct page *page, struct skcipher_sg_list *sgl; int err = -EINVAL; + if (flags & MSG_SENDPAGE_NOTLAST) + flags |= MSG_MORE; + lock_sock(sk); if (!ctx->more && ctx->used) goto unlock; diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 2e65ac850ca6..3f1db34df5a5 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1070,6 +1070,9 @@ int udp_sendpage(struct sock *sk, struct page *page, int offset, struct udp_sock *up = udp_sk(sk); int ret; + if (flags & MSG_SENDPAGE_NOTLAST) + flags |= MSG_MORE; + if (!up->pending) { struct msghdr msg = { .msg_flags = flags|MSG_MORE }; -- cgit v1.2.3 From a52a9149f57d0b00dab0699028174a4f91dcb02f Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 28 Nov 2013 18:01:38 +0100 Subject: team: fix master carrier set when user linkup is enabled [ Upstream commit f5e0d34382e18f396d7673a84df8e3342bea7eb6 ] When user linkup is enabled and user sets linkup of individual port, we need to recompute linkup (carrier) of master interface so the change is reflected. Fix this by calling __team_carrier_check() which does the needed work. Please apply to all stable kernels as well. Thanks. Reported-by: Jan Tluka Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/team/team.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index b3051052f3ad..fe3fd77821bf 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -1217,6 +1217,8 @@ static int team_user_linkup_option_get(struct team *team, return 0; } +static void __team_carrier_check(struct team *team); + static int team_user_linkup_option_set(struct team *team, struct team_gsetter_ctx *ctx) { @@ -1224,6 +1226,7 @@ static int team_user_linkup_option_set(struct team *team, port->user.linkup = ctx->data.bool_val; team_refresh_port_linkup(port); + __team_carrier_check(port->team); return 0; } @@ -1243,6 +1246,7 @@ static int team_user_linkup_en_option_set(struct team *team, port->user.linkup_enabled = ctx->data.bool_val; team_refresh_port_linkup(port); + __team_carrier_check(port->team); return 0; } -- cgit v1.2.3 From 7be560d6fa090edd57fa2761282f46ef85a20088 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 28 Nov 2013 09:51:22 -0800 Subject: inet: fix possible seqlock deadlocks [ Upstream commit f1d8cba61c3c4b1eb88e507249c4cb8d635d9a76 ] In commit c9e9042994d3 ("ipv4: fix possible seqlock deadlock") I left another places where IP_INC_STATS_BH() were improperly used. udp_sendmsg(), ping_v4_sendmsg() and tcp_v4_connect() are called from process context, not from softirq context. This was detected by lockdep seqlock support. Reported-by: jongman heo Fixes: 584bdf8cbdf6 ("[IPV4]: Fix "ipOutNoRoutes" counter error for TCP and UDP") Fixes: c319b4d76b9e ("net: ipv4: add IPPROTO_ICMP socket kind") Signed-off-by: Eric Dumazet Cc: Hannes Frederic Sowa Acked-by: Hannes Frederic Sowa Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/ping.c | 2 +- net/ipv4/tcp_ipv4.c | 2 +- net/ipv4/udp.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index a475b30ce289..8cae28f5c3cf 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c @@ -570,7 +570,7 @@ static int ping_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, err = PTR_ERR(rt); rt = NULL; if (err == -ENETUNREACH) - IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES); + IP_INC_STATS(net, IPSTATS_MIB_OUTNOROUTES); goto out; } diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 7999fc55c83b..5d87806d3ade 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -176,7 +176,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) if (IS_ERR(rt)) { err = PTR_ERR(rt); if (err == -ENETUNREACH) - IP_INC_STATS_BH(sock_net(sk), IPSTATS_MIB_OUTNOROUTES); + IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTNOROUTES); return err; } diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 3f1db34df5a5..c3075b552248 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -971,7 +971,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, err = PTR_ERR(rt); rt = NULL; if (err == -ENETUNREACH) - IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES); + IP_INC_STATS(net, IPSTATS_MIB_OUTNOROUTES); goto out; } -- cgit v1.2.3 From e761bada6f1eb056e720afd5704a21a79fb8df35 Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Fri, 29 Nov 2013 06:39:44 +0100 Subject: ipv6: fix possible seqlock deadlock in ip6_finish_output2 [ Upstream commit 7f88c6b23afbd31545c676dea77ba9593a1a14bf ] IPv6 stats are 64 bits and thus are protected with a seqlock. By not disabling bottom-half we could deadlock here if we don't disable bh and a softirq reentrantly updates the same mib. Cc: Eric Dumazet Signed-off-by: Hannes Frederic Sowa Acked-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv6/ip6_output.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 53630d0d0f43..b98b8e06739e 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -141,8 +141,8 @@ static int ip6_finish_output2(struct sk_buff *skb) } rcu_read_unlock_bh(); - IP6_INC_STATS_BH(dev_net(dst->dev), - ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); + IP6_INC_STATS(dev_net(dst->dev), + ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); kfree_skb(skb); return -EINVAL; } -- cgit v1.2.3 From dd5e5276c4e7922e784c156be630972341d51370 Mon Sep 17 00:00:00 2001 From: "fan.du" Date: Sun, 1 Dec 2013 16:28:48 +0800 Subject: {pktgen, xfrm} Update IPv4 header total len and checksum after tranformation [ Upstream commit 3868204d6b89ea373a273e760609cb08020beb1a ] commit a553e4a6317b2cfc7659542c10fe43184ffe53da ("[PKTGEN]: IPSEC support") tried to support IPsec ESP transport transformation for pktgen, but acctually this doesn't work at all for two reasons(The orignal transformed packet has bad IPv4 checksum value, as well as wrong auth value, reported by wireshark) - After transpormation, IPv4 header total length needs update, because encrypted payload's length is NOT same as that of plain text. - After transformation, IPv4 checksum needs re-caculate because of payload has been changed. With this patch, armmed pktgen with below cofiguration, Wireshark is able to decrypted ESP packet generated by pktgen without any IPv4 checksum error or auth value error. pgset "flag IPSEC" pgset "flows 1" Signed-off-by: Fan Du Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/pktgen.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 11f2704c3810..ebbea5371967 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -2515,6 +2515,8 @@ static int process_ipsec(struct pktgen_dev *pkt_dev, if (x) { int ret; __u8 *eth; + struct iphdr *iph; + nhead = x->props.header_len - skb_headroom(skb); if (nhead > 0) { ret = pskb_expand_head(skb, nhead, 0, GFP_ATOMIC); @@ -2536,6 +2538,11 @@ static int process_ipsec(struct pktgen_dev *pkt_dev, eth = (__u8 *) skb_push(skb, ETH_HLEN); memcpy(eth, pkt_dev->hh, 12); *(u16 *) ð[12] = protocol; + + /* Update IPv4 header len as well as checksum value */ + iph = ip_hdr(skb); + iph->tot_len = htons(skb->len - ETH_HLEN); + ip_send_check(iph); } } return 1; -- cgit v1.2.3 From e8ef7efffbd51a4f256c5a3fe0c77f067db0c525 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 25 Oct 2013 17:26:17 -0700 Subject: tcp: gso: fix truesize tracking [ Upstream commit 0d08c42cf9a71530fef5ebcfe368f38f2dd0476f ] commit 6ff50cd55545 ("tcp: gso: do not generate out of order packets") had an heuristic that can trigger a warning in skb_try_coalesce(), because skb->truesize of the gso segments were exactly set to mss. This breaks the requirement that skb->truesize >= skb->len + truesizeof(struct sk_buff); It can trivially be reproduced by : ifconfig lo mtu 1500 ethtool -K lo tso off netperf As the skbs are looped into the TCP networking stack, skb_try_coalesce() warns us of these skb under-estimating their truesize. Signed-off-by: Eric Dumazet Reported-by: Alexei Starovoitov Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/tcp.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index ae15c18df880..1a2e249cef49 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2899,6 +2899,7 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, netdev_features_t features) { struct sk_buff *segs = ERR_PTR(-EINVAL); + unsigned int sum_truesize = 0; struct tcphdr *th; unsigned int thlen; unsigned int seq; @@ -2982,13 +2983,7 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, if (copy_destructor) { skb->destructor = gso_skb->destructor; skb->sk = gso_skb->sk; - /* {tcp|sock}_wfree() use exact truesize accounting : - * sum(skb->truesize) MUST be exactly be gso_skb->truesize - * So we account mss bytes of 'true size' for each segment. - * The last segment will contain the remaining. - */ - skb->truesize = mss; - gso_skb->truesize -= mss; + sum_truesize += skb->truesize; } skb = skb->next; th = tcp_hdr(skb); @@ -3005,7 +3000,9 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, if (copy_destructor) { swap(gso_skb->sk, skb->sk); swap(gso_skb->destructor, skb->destructor); - swap(gso_skb->truesize, skb->truesize); + sum_truesize += skb->truesize; + atomic_add(sum_truesize - gso_skb->truesize, + &skb->sk->sk_wmem_alloc); } delta = htonl(oldlen + (skb->tail - skb->transport_header) + -- cgit v1.2.3 From bdd0a8e5ace90cad14c1bf1bf49c3bfabb77f831 Mon Sep 17 00:00:00 2001 From: Dwight Engen Date: Thu, 15 Aug 2013 14:08:03 -0400 Subject: xfs: add capability check to free eofblocks ioctl commit 8c567a7fab6e086a0284eee2db82348521e7120c upstream. Check for CAP_SYS_ADMIN since the caller can truncate preallocated blocks from files they do not own nor have write access to. A more fine grained access check was considered: require the caller to specify their own uid/gid and to use inode_permission to check for write, but this would not catch the case of an inode not reachable via path traversal from the callers mount namespace. Add check for read-only filesystem to free eofblocks ioctl. Reviewed-by: Brian Foster Reviewed-by: Dave Chinner Reviewed-by: Gao feng Signed-off-by: Dwight Engen Signed-off-by: Ben Myers Cc: Kees Cook Signed-off-by: Greg Kroah-Hartman --- fs/xfs/xfs_ioctl.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index 5e999680094a..ca01d830e989 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -1612,6 +1612,12 @@ xfs_file_ioctl( case XFS_IOC_FREE_EOFBLOCKS: { struct xfs_eofblocks eofb; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + if (mp->m_flags & XFS_MOUNT_RDONLY) + return -XFS_ERROR(EROFS); + if (copy_from_user(&eofb, arg, sizeof(eofb))) return -XFS_ERROR(EFAULT); -- cgit v1.2.3 From 604ae797e7cd1eca7897eac555961a5a25a9bde5 Mon Sep 17 00:00:00 2001 From: KOBAYASHI Yoshitake Date: Sun, 7 Jul 2013 07:35:45 +0900 Subject: mmc: block: fix a bug of error handling in MMC driver commit c8760069627ad3b0dbbea170f0c4c58b16e18d3d upstream. Current MMC driver doesn't handle generic error (bit19 of device status) in write sequence. As a result, write data gets lost when generic error occurs. For example, a generic error when updating a filesystem management information causes a loss of write data and corrupts the filesystem. In the worst case, the system will never boot. This patch includes the following functionality: 1. To enable error checking for the response of CMD12 and CMD13 in write command sequence 2. To retry write sequence when a generic error occurs Messages are added for v2 to show what occurs. Signed-off-by: KOBAYASHI Yoshitake Signed-off-by: Chris Ball Signed-off-by: Greg Kroah-Hartman --- drivers/mmc/card/block.c | 45 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index dd27b0783d52..76a3d3a752d8 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -769,7 +769,7 @@ static int mmc_blk_cmd_error(struct request *req, const char *name, int error, * Otherwise we don't understand what happened, so abort. */ static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req, - struct mmc_blk_request *brq, int *ecc_err) + struct mmc_blk_request *brq, int *ecc_err, int *gen_err) { bool prev_cmd_status_valid = true; u32 status, stop_status = 0; @@ -807,6 +807,16 @@ static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req, (brq->cmd.resp[0] & R1_CARD_ECC_FAILED)) *ecc_err = 1; + /* Flag General errors */ + if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) + if ((status & R1_ERROR) || + (brq->stop.resp[0] & R1_ERROR)) { + pr_err("%s: %s: general error sending stop or status command, stop cmd response %#x, card status %#x\n", + req->rq_disk->disk_name, __func__, + brq->stop.resp[0], status); + *gen_err = 1; + } + /* * Check the current card state. If it is in some data transfer * mode, tell it to stop (and hopefully transition back to TRAN.) @@ -826,6 +836,13 @@ static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req, return ERR_ABORT; if (stop_status & R1_CARD_ECC_FAILED) *ecc_err = 1; + if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) + if (stop_status & R1_ERROR) { + pr_err("%s: %s: general error sending stop command, stop cmd response %#x\n", + req->rq_disk->disk_name, __func__, + stop_status); + *gen_err = 1; + } } /* Check for set block count errors */ @@ -1069,7 +1086,7 @@ static int mmc_blk_err_check(struct mmc_card *card, mmc_active); struct mmc_blk_request *brq = &mq_mrq->brq; struct request *req = mq_mrq->req; - int ecc_err = 0; + int ecc_err = 0, gen_err = 0; /* * sbc.error indicates a problem with the set block count @@ -1083,7 +1100,7 @@ static int mmc_blk_err_check(struct mmc_card *card, */ if (brq->sbc.error || brq->cmd.error || brq->stop.error || brq->data.error) { - switch (mmc_blk_cmd_recovery(card, req, brq, &ecc_err)) { + switch (mmc_blk_cmd_recovery(card, req, brq, &ecc_err, &gen_err)) { case ERR_RETRY: return MMC_BLK_RETRY; case ERR_ABORT: @@ -1115,6 +1132,14 @@ static int mmc_blk_err_check(struct mmc_card *card, u32 status; unsigned long timeout; + /* Check stop command response */ + if (brq->stop.resp[0] & R1_ERROR) { + pr_err("%s: %s: general error sending stop command, stop cmd response %#x\n", + req->rq_disk->disk_name, __func__, + brq->stop.resp[0]); + gen_err = 1; + } + timeout = jiffies + msecs_to_jiffies(MMC_BLK_TIMEOUT_MS); do { int err = get_card_status(card, &status, 5); @@ -1124,6 +1149,13 @@ static int mmc_blk_err_check(struct mmc_card *card, return MMC_BLK_CMD_ERR; } + if (status & R1_ERROR) { + pr_err("%s: %s: general error sending status command, card status %#x\n", + req->rq_disk->disk_name, __func__, + status); + gen_err = 1; + } + /* Timeout if the device never becomes ready for data * and never leaves the program state. */ @@ -1143,6 +1175,13 @@ static int mmc_blk_err_check(struct mmc_card *card, (R1_CURRENT_STATE(status) == R1_STATE_PRG)); } + /* if general error occurs, retry the write operation. */ + if (gen_err) { + pr_warn("%s: retrying write for general error\n", + req->rq_disk->disk_name); + return MMC_BLK_RETRY; + } + if (brq->data.error) { pr_err("%s: error %d transferring data, sector %u, nr %u, cmd response %#x, card status %#x\n", req->rq_disk->disk_name, brq->data.error, -- cgit v1.2.3 From f8715e7d2a096cedd1c5ef4768deae7126659dcf Mon Sep 17 00:00:00 2001 From: Mateusz Guzik Date: Thu, 5 Dec 2013 11:09:02 +0100 Subject: aio: restore locking of ioctx list on removal Commit 36f5588905c10a8c4568a210d601fe8c3c27e0f0 "aio: refcounting cleanup" resulted in ioctx_lock not being held during ctx removal, leaving the list susceptible to corruptions. In mainline kernel the issue went away as a side effect of db446a08c23d5475e6b08c87acca79ebb20f283c "aio: convert the ioctx list to table lookup v3". Fix the problem by restoring appropriate locking. Signed-off-by: Mateusz Guzik Reported-by: Eryu Guan Cc: Jeff Moyer Cc: Kent Overstreet Acked-by: Benjamin LaHaise Signed-off-by: Greg Kroah-Hartman --- fs/aio.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/fs/aio.c b/fs/aio.c index 2bbcacf74d0c..ebd06fd0de89 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -423,10 +423,12 @@ static void kill_ioctx_rcu(struct rcu_head *head) * when the processes owning a context have all exited to encourage * the rapid destruction of the kioctx. */ -static void kill_ioctx(struct kioctx *ctx) +static void kill_ioctx(struct mm_struct *mm, struct kioctx *ctx) { if (!atomic_xchg(&ctx->dead, 1)) { + spin_lock(&mm->ioctx_lock); hlist_del_rcu(&ctx->list); + spin_unlock(&mm->ioctx_lock); /* * It'd be more correct to do this in free_ioctx(), after all @@ -494,7 +496,7 @@ void exit_aio(struct mm_struct *mm) */ ctx->mmap_size = 0; - kill_ioctx(ctx); + kill_ioctx(mm, ctx); } } @@ -852,7 +854,7 @@ SYSCALL_DEFINE2(io_setup, unsigned, nr_events, aio_context_t __user *, ctxp) if (!IS_ERR(ioctx)) { ret = put_user(ioctx->user_id, ctxp); if (ret) - kill_ioctx(ioctx); + kill_ioctx(current->mm, ioctx); put_ioctx(ioctx); } @@ -870,7 +872,7 @@ SYSCALL_DEFINE1(io_destroy, aio_context_t, ctx) { struct kioctx *ioctx = lookup_ioctx(ctx); if (likely(NULL != ioctx)) { - kill_ioctx(ioctx); + kill_ioctx(current->mm, ioctx); put_ioctx(ioctx); return 0; } -- cgit v1.2.3 From e8d630331dfe32c63438a4558eeda6f79c712485 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 25 Apr 2013 20:31:47 +0000 Subject: clockevents: Get rid of the notifier chain commit 7172a286ced0c1f4f239a0fa09db54ed37d3ead2 upstream. 7+ years and still a single user. Kill it. Signed-off-by: Thomas Gleixner Cc: John Stultz Cc: Magnus Damm Link: http://lkml.kernel.org/r/20130425143436.098520211@linutronix.de Signed-off-by: Thomas Gleixner Cc: Kim Phillips Signed-off-by: Greg Kroah-Hartman --- include/linux/clockchips.h | 1 - kernel/time/clockevents.c | 35 +++-------------------------------- kernel/time/tick-broadcast.c | 5 ++--- kernel/time/tick-common.c | 30 +++++------------------------- kernel/time/tick-internal.h | 7 ++++--- 5 files changed, 14 insertions(+), 64 deletions(-) diff --git a/include/linux/clockchips.h b/include/linux/clockchips.h index 963d71431388..2f498f66c1bb 100644 --- a/include/linux/clockchips.h +++ b/include/linux/clockchips.h @@ -150,7 +150,6 @@ extern void clockevents_exchange_device(struct clock_event_device *old, struct clock_event_device *new); extern void clockevents_set_mode(struct clock_event_device *dev, enum clock_event_mode mode); -extern int clockevents_register_notifier(struct notifier_block *nb); extern int clockevents_program_event(struct clock_event_device *dev, ktime_t expires, bool force); diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c index 6a23c6c556c3..ae7d9141f0b6 100644 --- a/kernel/time/clockevents.c +++ b/kernel/time/clockevents.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include "tick-internal.h" @@ -23,10 +22,6 @@ /* The registered clock event devices */ static LIST_HEAD(clockevent_devices); static LIST_HEAD(clockevents_released); - -/* Notification for clock events */ -static RAW_NOTIFIER_HEAD(clockevents_chain); - /* Protection for the above */ static DEFINE_RAW_SPINLOCK(clockevents_lock); @@ -267,30 +262,6 @@ int clockevents_program_event(struct clock_event_device *dev, ktime_t expires, return (rc && force) ? clockevents_program_min_delta(dev) : rc; } -/** - * clockevents_register_notifier - register a clock events change listener - */ -int clockevents_register_notifier(struct notifier_block *nb) -{ - unsigned long flags; - int ret; - - raw_spin_lock_irqsave(&clockevents_lock, flags); - ret = raw_notifier_chain_register(&clockevents_chain, nb); - raw_spin_unlock_irqrestore(&clockevents_lock, flags); - - return ret; -} - -/* - * Notify about a clock event change. Called with clockevents_lock - * held. - */ -static void clockevents_do_notify(unsigned long reason, void *dev) -{ - raw_notifier_call_chain(&clockevents_chain, reason, dev); -} - /* * Called after a notify add to make devices available which were * released from the notifier call. @@ -304,7 +275,7 @@ static void clockevents_notify_released(void) struct clock_event_device, list); list_del(&dev->list); list_add(&dev->list, &clockevent_devices); - clockevents_do_notify(CLOCK_EVT_NOTIFY_ADD, dev); + tick_check_new_device(dev); } } @@ -325,7 +296,7 @@ void clockevents_register_device(struct clock_event_device *dev) raw_spin_lock_irqsave(&clockevents_lock, flags); list_add(&dev->list, &clockevent_devices); - clockevents_do_notify(CLOCK_EVT_NOTIFY_ADD, dev); + tick_check_new_device(dev); clockevents_notify_released(); raw_spin_unlock_irqrestore(&clockevents_lock, flags); @@ -468,7 +439,7 @@ void clockevents_notify(unsigned long reason, void *arg) int cpu; raw_spin_lock_irqsave(&clockevents_lock, flags); - clockevents_do_notify(reason, arg); + tick_notify(reason, arg); switch (reason) { case CLOCK_EVT_NOTIFY_CPU_DEAD: diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c index 297b90b5277e..753e910b647b 100644 --- a/kernel/time/tick-broadcast.c +++ b/kernel/time/tick-broadcast.c @@ -65,7 +65,7 @@ static void tick_broadcast_start_periodic(struct clock_event_device *bc) /* * Check, if the device can be utilized as broadcast device: */ -int tick_check_broadcast_device(struct clock_event_device *dev) +void tick_install_broadcast_device(struct clock_event_device *dev) { struct clock_event_device *cur = tick_broadcast_device.evtdev; @@ -73,7 +73,7 @@ int tick_check_broadcast_device(struct clock_event_device *dev) (tick_broadcast_device.evtdev && tick_broadcast_device.evtdev->rating >= dev->rating) || (dev->features & CLOCK_EVT_FEAT_C3STOP)) - return 0; + return; clockevents_exchange_device(tick_broadcast_device.evtdev, dev); if (cur) @@ -91,7 +91,6 @@ int tick_check_broadcast_device(struct clock_event_device *dev) */ if (dev->features & CLOCK_EVT_FEAT_ONESHOT) tick_clock_notify(); - return 1; } /* diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c index 7ce5e5a4a4c5..d8e328cf481e 100644 --- a/kernel/time/tick-common.c +++ b/kernel/time/tick-common.c @@ -209,11 +209,11 @@ static void tick_setup_device(struct tick_device *td, /* * Check, if the new registered device should be used. */ -static int tick_check_new_device(struct clock_event_device *newdev) +void tick_check_new_device(struct clock_event_device *newdev) { struct clock_event_device *curdev; struct tick_device *td; - int cpu, ret = NOTIFY_OK; + int cpu; unsigned long flags; raw_spin_lock_irqsave(&tick_device_lock, flags); @@ -276,18 +276,14 @@ static int tick_check_new_device(struct clock_event_device *newdev) tick_oneshot_notify(); raw_spin_unlock_irqrestore(&tick_device_lock, flags); - return NOTIFY_STOP; + return; out_bc: /* * Can the new device be used as a broadcast device ? */ - if (tick_check_broadcast_device(newdev)) - ret = NOTIFY_STOP; - + tick_install_broadcast_device(newdev); raw_spin_unlock_irqrestore(&tick_device_lock, flags); - - return ret; } /* @@ -361,17 +357,10 @@ static void tick_resume(void) raw_spin_unlock_irqrestore(&tick_device_lock, flags); } -/* - * Notification about clock event devices - */ -static int tick_notify(struct notifier_block *nb, unsigned long reason, - void *dev) +void tick_notify(unsigned long reason, void *dev) { switch (reason) { - case CLOCK_EVT_NOTIFY_ADD: - return tick_check_new_device(dev); - case CLOCK_EVT_NOTIFY_BROADCAST_ON: case CLOCK_EVT_NOTIFY_BROADCAST_OFF: case CLOCK_EVT_NOTIFY_BROADCAST_FORCE: @@ -405,21 +394,12 @@ static int tick_notify(struct notifier_block *nb, unsigned long reason, default: break; } - - return NOTIFY_OK; } -static struct notifier_block tick_notifier = { - .notifier_call = tick_notify, -}; - /** * tick_init - initialize the tick control - * - * Register the notifier with the clockevents framework */ void __init tick_init(void) { - clockevents_register_notifier(&tick_notifier); tick_broadcast_init(); } diff --git a/kernel/time/tick-internal.h b/kernel/time/tick-internal.h index f0299eae4602..60742fe6f63d 100644 --- a/kernel/time/tick-internal.h +++ b/kernel/time/tick-internal.h @@ -18,6 +18,8 @@ extern int tick_do_timer_cpu __read_mostly; extern void tick_setup_periodic(struct clock_event_device *dev, int broadcast); extern void tick_handle_periodic(struct clock_event_device *dev); +extern void tick_notify(unsigned long reason, void *dev); +extern void tick_check_new_device(struct clock_event_device *dev); extern void clockevents_shutdown(struct clock_event_device *dev); @@ -90,7 +92,7 @@ static inline bool tick_broadcast_oneshot_available(void) { return false; } */ #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST extern int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu); -extern int tick_check_broadcast_device(struct clock_event_device *dev); +extern void tick_install_broadcast_device(struct clock_event_device *dev); extern int tick_is_broadcast_device(struct clock_event_device *dev); extern void tick_broadcast_on_off(unsigned long reason, int *oncpu); extern void tick_shutdown_broadcast(unsigned int *cpup); @@ -102,9 +104,8 @@ tick_set_periodic_handler(struct clock_event_device *dev, int broadcast); #else /* !BROADCAST */ -static inline int tick_check_broadcast_device(struct clock_event_device *dev) +static inline void tick_install_broadcast_device(struct clock_event_device *dev) { - return 0; } static inline int tick_is_broadcast_device(struct clock_event_device *dev) -- cgit v1.2.3 From 409d4ffaf0c8b29693243918217cec0044979395 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 25 Apr 2013 20:31:49 +0000 Subject: clockevents: Add module refcount commit ccf33d6880f39a35158fff66db13000ae4943fac upstream. We want to be able to remove clockevent modules as well. Add a refcount so we don't remove a module with an active clock event device. Signed-off-by: Thomas Gleixner Cc: John Stultz Cc: Magnus Damm Link: http://lkml.kernel.org/r/20130425143436.307435149@linutronix.de Signed-off-by: Thomas Gleixner Cc: Kim Phillips Signed-off-by: Greg Kroah-Hartman --- include/linux/clockchips.h | 3 +++ kernel/time/clockevents.c | 1 + kernel/time/tick-broadcast.c | 3 +++ kernel/time/tick-common.c | 4 ++++ 4 files changed, 11 insertions(+) diff --git a/include/linux/clockchips.h b/include/linux/clockchips.h index 2f498f66c1bb..ae1193bcf074 100644 --- a/include/linux/clockchips.h +++ b/include/linux/clockchips.h @@ -30,6 +30,7 @@ enum clock_event_nofitiers { #include struct clock_event_device; +struct module; /* Clock event mode commands */ enum clock_event_mode { @@ -83,6 +84,7 @@ enum clock_event_mode { * @irq: IRQ number (only for non CPU local devices) * @cpumask: cpumask to indicate for which CPUs this device works * @list: list head for the management code + * @owner: module reference */ struct clock_event_device { void (*event_handler)(struct clock_event_device *); @@ -112,6 +114,7 @@ struct clock_event_device { int irq; const struct cpumask *cpumask; struct list_head list; + struct module *owner; } ____cacheline_aligned; /* diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c index ae7d9141f0b6..9df0e3b19f09 100644 --- a/kernel/time/clockevents.c +++ b/kernel/time/clockevents.c @@ -392,6 +392,7 @@ void clockevents_exchange_device(struct clock_event_device *old, * released list and do a notify add later. */ if (old) { + module_put(old->owner); clockevents_set_mode(old, CLOCK_EVT_MODE_UNUSED); list_del(&old->list); list_add(&old->list, &clockevents_released); diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c index 753e910b647b..c15921f88f14 100644 --- a/kernel/time/tick-broadcast.c +++ b/kernel/time/tick-broadcast.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "tick-internal.h" @@ -74,6 +75,8 @@ void tick_install_broadcast_device(struct clock_event_device *dev) tick_broadcast_device.evtdev->rating >= dev->rating) || (dev->features & CLOCK_EVT_FEAT_C3STOP)) return; + if (!try_module_get(dev->owner)) + return; clockevents_exchange_device(tick_broadcast_device.evtdev, dev); if (cur) diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c index d8e328cf481e..e93af50726e2 100644 --- a/kernel/time/tick-common.c +++ b/kernel/time/tick-common.c @@ -18,6 +18,7 @@ #include #include #include +#include #include @@ -261,6 +262,9 @@ void tick_check_new_device(struct clock_event_device *newdev) goto out_bc; } + if (!try_module_get(newdev->owner)) + return; + /* * Replace the eventually existing device by the new * device. If the current device is the broadcast device, do -- cgit v1.2.3 From 9bae8ea0544becdd8e6716b318c1844aeea41a69 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 25 Apr 2013 20:31:50 +0000 Subject: clockevents: Split out selection logic commit 45cb8e01b2ecef1c2afb18333e95793fa1a90281 upstream. Split out the clockevent device selection logic. Preparatory patch to allow unbinding active clockevent devices. Signed-off-by: Thomas Gleixner Cc: John Stultz Cc: Magnus Damm Link: http://lkml.kernel.org/r/20130425143436.431796247@linutronix.de Signed-off-by: Thomas Gleixner Cc: Kim Phillips Signed-off-by: Greg Kroah-Hartman --- kernel/time/tick-broadcast.c | 25 ++++++++++++---- kernel/time/tick-common.c | 69 +++++++++++++++++++++++--------------------- 2 files changed, 56 insertions(+), 38 deletions(-) diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c index c15921f88f14..52d4827cf2d4 100644 --- a/kernel/time/tick-broadcast.c +++ b/kernel/time/tick-broadcast.c @@ -66,19 +66,34 @@ static void tick_broadcast_start_periodic(struct clock_event_device *bc) /* * Check, if the device can be utilized as broadcast device: */ +static bool tick_check_broadcast_device(struct clock_event_device *curdev, + struct clock_event_device *newdev) +{ + if ((newdev->features & CLOCK_EVT_FEAT_DUMMY) || + (newdev->features & CLOCK_EVT_FEAT_C3STOP)) + return false; + + if (tick_broadcast_device.mode == TICKDEV_MODE_ONESHOT && + !(newdev->features & CLOCK_EVT_FEAT_ONESHOT)) + return false; + + return !curdev || newdev->rating > curdev->rating; +} + +/* + * Conditionally install/replace broadcast device + */ void tick_install_broadcast_device(struct clock_event_device *dev) { struct clock_event_device *cur = tick_broadcast_device.evtdev; - if ((dev->features & CLOCK_EVT_FEAT_DUMMY) || - (tick_broadcast_device.evtdev && - tick_broadcast_device.evtdev->rating >= dev->rating) || - (dev->features & CLOCK_EVT_FEAT_C3STOP)) + if (!tick_check_broadcast_device(cur, dev)) return; + if (!try_module_get(dev->owner)) return; - clockevents_exchange_device(tick_broadcast_device.evtdev, dev); + clockevents_exchange_device(cur, dev); if (cur) cur->event_handler = clockevents_handle_noop; tick_broadcast_device.evtdev = dev; diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c index e93af50726e2..e91f1019d662 100644 --- a/kernel/time/tick-common.c +++ b/kernel/time/tick-common.c @@ -207,6 +207,37 @@ static void tick_setup_device(struct tick_device *td, tick_setup_oneshot(newdev, handler, next_event); } +static bool tick_check_percpu(struct clock_event_device *curdev, + struct clock_event_device *newdev, int cpu) +{ + if (!cpumask_test_cpu(cpu, newdev->cpumask)) + return false; + if (cpumask_equal(newdev->cpumask, cpumask_of(cpu))) + return true; + /* Check if irq affinity can be set */ + if (newdev->irq >= 0 && !irq_can_set_affinity(newdev->irq)) + return false; + /* Prefer an existing cpu local device */ + if (curdev && cpumask_equal(curdev->cpumask, cpumask_of(cpu))) + return false; + return true; +} + +static bool tick_check_preferred(struct clock_event_device *curdev, + struct clock_event_device *newdev) +{ + /* Prefer oneshot capable device */ + if (!(newdev->features & CLOCK_EVT_FEAT_ONESHOT)) { + if (curdev && (curdev->features & CLOCK_EVT_FEAT_ONESHOT)) + return false; + if (tick_oneshot_mode_active()) + return false; + } + + /* Use the higher rated one */ + return !curdev || newdev->rating > curdev->rating; +} + /* * Check, if the new registered device should be used. */ @@ -227,40 +258,12 @@ void tick_check_new_device(struct clock_event_device *newdev) curdev = td->evtdev; /* cpu local device ? */ - if (!cpumask_equal(newdev->cpumask, cpumask_of(cpu))) { - - /* - * If the cpu affinity of the device interrupt can not - * be set, ignore it. - */ - if (!irq_can_set_affinity(newdev->irq)) - goto out_bc; - - /* - * If we have a cpu local device already, do not replace it - * by a non cpu local device - */ - if (curdev && cpumask_equal(curdev->cpumask, cpumask_of(cpu))) - goto out_bc; - } + if (!tick_check_percpu(curdev, newdev, cpu)) + goto out_bc; - /* - * If we have an active device, then check the rating and the oneshot - * feature. - */ - if (curdev) { - /* - * Prefer one shot capable devices ! - */ - if ((curdev->features & CLOCK_EVT_FEAT_ONESHOT) && - !(newdev->features & CLOCK_EVT_FEAT_ONESHOT)) - goto out_bc; - /* - * Check the rating - */ - if (curdev->rating >= newdev->rating) - goto out_bc; - } + /* Preference decision */ + if (!tick_check_preferred(curdev, newdev)) + goto out_bc; if (!try_module_get(newdev->owner)) return; -- cgit v1.2.3 From 7281bb5614bcdbf6789e9559420b814689b122e3 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Thu, 13 Jun 2013 11:39:50 -0700 Subject: clockevents: Prefer CPU local devices over global devices commit 70e5975d3a04be5479a28eec4a2fb10f98ad2785 upstream. On an SMP system with only one global clockevent and a dummy clockevent per CPU we run into problems. We want the dummy clockevents to be registered as the per CPU tick devices, but we can only achieve that if we register the dummy clockevents before the global clockevent or if we artificially inflate the rating of the dummy clockevents to be higher than the rating of the global clockevent. Failure to do so leads to boot hangs when the dummy timers are registered on all other CPUs besides the CPU that accepted the global clockevent as its tick device and there is no broadcast timer to poke the dummy devices. If we're registering multiple clockevents and one clockevent is global and the other is local to a particular CPU we should choose to use the local clockevent regardless of the rating of the device. This way, if the clockevent is a dummy it will take the tick device duty as long as there isn't a higher rated tick device and any global clockevent will be bumped out into broadcast mode, fixing the problem described above. Reported-and-tested-by: Mark Rutland Signed-off-by: Stephen Boyd Tested-by: soren.brinkmann@xilinx.com Cc: John Stultz Cc: Daniel Lezcano Cc: linux-arm-kernel@lists.infradead.org Cc: John Stultz Link: http://lkml.kernel.org/r/20130613183950.GA32061@codeaurora.org Signed-off-by: Thomas Gleixner Cc: Kim Phillips Signed-off-by: Greg Kroah-Hartman --- kernel/time/tick-common.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c index e91f1019d662..086216c433fa 100644 --- a/kernel/time/tick-common.c +++ b/kernel/time/tick-common.c @@ -234,8 +234,13 @@ static bool tick_check_preferred(struct clock_event_device *curdev, return false; } - /* Use the higher rated one */ - return !curdev || newdev->rating > curdev->rating; + /* + * Use the higher rated one, but prefer a CPU local device with a lower + * rating than a non-CPU local device + */ + return !curdev || + newdev->rating > curdev->rating || + !cpumask_equal(curdev->cpumask, newdev->cpumask); } /* -- cgit v1.2.3 From f99510dc9a9b63ba8131e1e5eb70884db122a1bc Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Tue, 12 Nov 2013 15:08:32 -0800 Subject: mm: numa: return the number of base pages altered by protection changes commit 72403b4a0fbdf433c1fe0127e49864658f6f6468 upstream. Commit 0255d4918480 ("mm: Account for a THP NUMA hinting update as one PTE update") was added to account for the number of PTE updates when marking pages prot_numa. task_numa_work was using the old return value to track how much address space had been updated. Altering the return value causes the scanner to do more work than it is configured or documented to in a single unit of work. This patch reverts that commit and accounts for the number of THP updates separately in vmstat. It is up to the administrator to interpret the pair of values correctly. This is a straight-forward operation and likely to only be of interest when actively debugging NUMA balancing problems. The impact of this patch is that the NUMA PTE scanner will scan slower when THP is enabled and workloads may converge slower as a result. On the flip size system CPU usage should be lower than recent tests reported. This is an illustrative example of a short single JVM specjbb test specjbb 3.12.0 3.12.0 vanilla acctupdates TPut 1 26143.00 ( 0.00%) 25747.00 ( -1.51%) TPut 7 185257.00 ( 0.00%) 183202.00 ( -1.11%) TPut 13 329760.00 ( 0.00%) 346577.00 ( 5.10%) TPut 19 442502.00 ( 0.00%) 460146.00 ( 3.99%) TPut 25 540634.00 ( 0.00%) 549053.00 ( 1.56%) TPut 31 512098.00 ( 0.00%) 519611.00 ( 1.47%) TPut 37 461276.00 ( 0.00%) 474973.00 ( 2.97%) TPut 43 403089.00 ( 0.00%) 414172.00 ( 2.75%) 3.12.0 3.12.0 vanillaacctupdates User 5169.64 5184.14 System 100.45 80.02 Elapsed 252.75 251.85 Performance is similar but note the reduction in system CPU time. While this showed a performance gain, it will not be universal but at least it'll be behaving as documented. The vmstats are obviously different but here is an obvious interpretation of them from mmtests. 3.12.0 3.12.0 vanillaacctupdates NUMA page range updates 1408326 11043064 NUMA huge PMD updates 0 21040 NUMA PTE updates 1408326 291624 "NUMA page range updates" == nr_pte_updates and is the value returned to the NUMA pte scanner. NUMA huge PMD updates were the number of THP updates which in combination can be used to calculate how many ptes were updated from userspace. Signed-off-by: Mel Gorman Reported-by: Alex Thorlton Reviewed-by: Rik van Riel Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Mel Gorman Signed-off-by: Greg Kroah-Hartman --- include/linux/vm_event_item.h | 1 + mm/mprotect.c | 7 ++++++- mm/vmstat.c | 1 + 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/include/linux/vm_event_item.h b/include/linux/vm_event_item.h index bd6cf61142be..8c0f6cb2a603 100644 --- a/include/linux/vm_event_item.h +++ b/include/linux/vm_event_item.h @@ -39,6 +39,7 @@ enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT, PAGEOUTRUN, ALLOCSTALL, PGROTATED, #ifdef CONFIG_NUMA_BALANCING NUMA_PTE_UPDATES, + NUMA_HUGE_PTE_UPDATES, NUMA_HINT_FAULTS, NUMA_HINT_FAULTS_LOCAL, NUMA_PAGE_MIGRATE, diff --git a/mm/mprotect.c b/mm/mprotect.c index 2bbb648ea73f..d4d5399c7aba 100644 --- a/mm/mprotect.c +++ b/mm/mprotect.c @@ -135,6 +135,7 @@ static inline unsigned long change_pmd_range(struct vm_area_struct *vma, pmd_t *pmd; unsigned long next; unsigned long pages = 0; + unsigned long nr_huge_updates = 0; bool all_same_node; pmd = pmd_offset(pud, addr); @@ -145,7 +146,8 @@ static inline unsigned long change_pmd_range(struct vm_area_struct *vma, split_huge_page_pmd(vma, addr, pmd); else if (change_huge_pmd(vma, pmd, addr, newprot, prot_numa)) { - pages++; + pages += HPAGE_PMD_NR; + nr_huge_updates++; continue; } /* fall through */ @@ -165,6 +167,9 @@ static inline unsigned long change_pmd_range(struct vm_area_struct *vma, change_pmd_protnuma(vma->vm_mm, addr, pmd); } while (pmd++, addr = next, addr != end); + if (nr_huge_updates) + count_vm_numa_events(NUMA_HUGE_PTE_UPDATES, nr_huge_updates); + return pages; } diff --git a/mm/vmstat.c b/mm/vmstat.c index f42745e65780..10bbb5427a6d 100644 --- a/mm/vmstat.c +++ b/mm/vmstat.c @@ -779,6 +779,7 @@ const char * const vmstat_text[] = { #ifdef CONFIG_NUMA_BALANCING "numa_pte_updates", + "numa_huge_pte_updates", "numa_hint_faults", "numa_hint_faults_local", "numa_pages_migrated", -- cgit v1.2.3 From ca77581ebaa42e9279a231fbcb98ee031c37fe3a Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Tue, 19 Nov 2013 14:25:36 -0500 Subject: video: kyro: fix incorrect sizes when copying to userspace commit 2ab68ec927310dc488f3403bb48f9e4ad00a9491 upstream. kyro would copy u32s and specify sizeof(unsigned long) as the size to copy. This would copy more data than intended and cause memory corruption and might leak kernel memory. Signed-off-by: Sasha Levin Signed-off-by: Tomi Valkeinen Signed-off-by: Greg Kroah-Hartman --- drivers/video/kyro/fbdev.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/video/kyro/fbdev.c b/drivers/video/kyro/fbdev.c index 6157f74ac600..ec7fc87fa5ab 100644 --- a/drivers/video/kyro/fbdev.c +++ b/drivers/video/kyro/fbdev.c @@ -625,15 +625,15 @@ static int kyrofb_ioctl(struct fb_info *info, } break; case KYRO_IOCTL_UVSTRIDE: - if (copy_to_user(argp, &deviceInfo.ulOverlayUVStride, sizeof(unsigned long))) + if (copy_to_user(argp, &deviceInfo.ulOverlayUVStride, sizeof(deviceInfo.ulOverlayUVStride))) return -EFAULT; break; case KYRO_IOCTL_STRIDE: - if (copy_to_user(argp, &deviceInfo.ulOverlayStride, sizeof(unsigned long))) + if (copy_to_user(argp, &deviceInfo.ulOverlayStride, sizeof(deviceInfo.ulOverlayStride))) return -EFAULT; break; case KYRO_IOCTL_OVERLAY_OFFSET: - if (copy_to_user(argp, &deviceInfo.ulOverlayOffset, sizeof(unsigned long))) + if (copy_to_user(argp, &deviceInfo.ulOverlayOffset, sizeof(deviceInfo.ulOverlayOffset))) return -EFAULT; break; } -- cgit v1.2.3 From 7dc39b55ecc16a4db44c820263c73a60fc750b27 Mon Sep 17 00:00:00 2001 From: Simon Wood Date: Thu, 10 Oct 2013 08:20:13 -0600 Subject: HID: lg: fix Report Descriptor for Logitech MOMO Force (Black) commit 348cbaa800f8161168b20f85f72abb541c145132 upstream. By default the Logitech MOMO Force (Black) presents a combined accel/brake axis ('Y'). This patch modifies the HID descriptor to present seperate accel/brake axes ('Y' and 'Z'). Signed-off-by: Simon Wood Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/hid/hid-lg.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c index 1bfd292cac8f..06eb45fa6331 100644 --- a/drivers/hid/hid-lg.c +++ b/drivers/hid/hid-lg.c @@ -47,6 +47,7 @@ #define DFP_RDESC_ORIG_SIZE 97 #define FV_RDESC_ORIG_SIZE 130 #define MOMO_RDESC_ORIG_SIZE 87 +#define MOMO2_RDESC_ORIG_SIZE 87 /* Fixed report descriptors for Logitech Driving Force (and Pro) * wheel controllers @@ -284,6 +285,54 @@ static __u8 momo_rdesc_fixed[] = { 0xC0 /* End Collection */ }; +static __u8 momo2_rdesc_fixed[] = { +0x05, 0x01, /* Usage Page (Desktop), */ +0x09, 0x04, /* Usage (Joystik), */ +0xA1, 0x01, /* Collection (Application), */ +0xA1, 0x02, /* Collection (Logical), */ +0x95, 0x01, /* Report Count (1), */ +0x75, 0x0A, /* Report Size (10), */ +0x15, 0x00, /* Logical Minimum (0), */ +0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ +0x35, 0x00, /* Physical Minimum (0), */ +0x46, 0xFF, 0x03, /* Physical Maximum (1023), */ +0x09, 0x30, /* Usage (X), */ +0x81, 0x02, /* Input (Variable), */ +0x95, 0x0A, /* Report Count (10), */ +0x75, 0x01, /* Report Size (1), */ +0x25, 0x01, /* Logical Maximum (1), */ +0x45, 0x01, /* Physical Maximum (1), */ +0x05, 0x09, /* Usage Page (Button), */ +0x19, 0x01, /* Usage Minimum (01h), */ +0x29, 0x0A, /* Usage Maximum (0Ah), */ +0x81, 0x02, /* Input (Variable), */ +0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ +0x09, 0x00, /* Usage (00h), */ +0x95, 0x04, /* Report Count (4), */ +0x81, 0x02, /* Input (Variable), */ +0x95, 0x01, /* Report Count (1), */ +0x75, 0x08, /* Report Size (8), */ +0x26, 0xFF, 0x00, /* Logical Maximum (255), */ +0x46, 0xFF, 0x00, /* Physical Maximum (255), */ +0x09, 0x01, /* Usage (01h), */ +0x81, 0x02, /* Input (Variable), */ +0x05, 0x01, /* Usage Page (Desktop), */ +0x09, 0x31, /* Usage (Y), */ +0x81, 0x02, /* Input (Variable), */ +0x09, 0x32, /* Usage (Z), */ +0x81, 0x02, /* Input (Variable), */ +0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ +0x09, 0x00, /* Usage (00h), */ +0x81, 0x02, /* Input (Variable), */ +0xC0, /* End Collection, */ +0xA1, 0x02, /* Collection (Logical), */ +0x09, 0x02, /* Usage (02h), */ +0x95, 0x07, /* Report Count (7), */ +0x91, 0x02, /* Output (Variable), */ +0xC0, /* End Collection, */ +0xC0 /* End Collection */ +}; + /* * Certain Logitech keyboards send in report #3 keys which are far * above the logical maximum described in descriptor. This extends @@ -343,6 +392,15 @@ static __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc, } break; + case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2: + if (*rsize == MOMO2_RDESC_ORIG_SIZE) { + hid_info(hdev, + "fixing up Logitech Momo Racing Force (Black) report descriptor\n"); + rdesc = momo2_rdesc_fixed; + *rsize = sizeof(momo2_rdesc_fixed); + } + break; + case USB_DEVICE_ID_LOGITECH_VIBRATION_WHEEL: if (*rsize == FV_RDESC_ORIG_SIZE) { hid_info(hdev, -- cgit v1.2.3 From 3de762b3d32ff3d0440ca809e1ba084c682f0ca7 Mon Sep 17 00:00:00 2001 From: Julian Stecklina Date: Wed, 9 Oct 2013 10:03:52 +0200 Subject: iommu/vt-d: Fixed interaction of VFIO_IOMMU_MAP_DMA with IOMMU address limits commit f9423606ade08653dd8a43334f0a7fb45504c5cc upstream. The BUG_ON in drivers/iommu/intel-iommu.c:785 can be triggered from userspace via VFIO by calling the VFIO_IOMMU_MAP_DMA ioctl on a vfio device with any address beyond the addressing capabilities of the IOMMU. The problem is that the ioctl code calls iommu_iova_to_phys before it calls iommu_map. iommu_map handles the case that it gets addresses beyond the addressing capabilities of its IOMMU. intel_iommu_iova_to_phys does not. This patch fixes iommu_iova_to_phys to return NULL for addresses beyond what the IOMMU can handle. This in turn causes the ioctl call to fail in iommu_map and (correctly) return EFAULT to the user with a helpful warning message in the kernel log. Signed-off-by: Julian Stecklina Acked-by: Alex Williamson Signed-off-by: Joerg Roedel Signed-off-by: Greg Kroah-Hartman --- drivers/iommu/intel-iommu.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index fa004b112a89..25943a683d15 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -782,7 +782,11 @@ static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain, int offset; BUG_ON(!domain->pgd); - BUG_ON(addr_width < BITS_PER_LONG && pfn >> addr_width); + + if (addr_width < BITS_PER_LONG && pfn >> addr_width) + /* Address beyond IOMMU's addressing capabilities. */ + return NULL; + parent = domain->pgd; while (level > 0) { -- cgit v1.2.3 From 645451235dc5098f08cc51e2f1205d9fa9ca8262 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Fri, 27 Sep 2013 12:53:35 -0400 Subject: iommu: Remove stack trace from broken irq remapping warning commit 05104a4e8713b27291c7bb49c1e7e68b4e243571 upstream. The warning for the irq remapping broken check in intel_irq_remapping.c is pretty pointless. We need the warning, but we know where its comming from, the stack trace will always be the same, and it needlessly triggers things like Abrt. This changes the warning to just print a text warning about BIOS being broken, without the stack trace, then sets the appropriate taint bit. Since we automatically disable irq remapping, theres no need to contiue making Abrt jump at this problem Signed-off-by: Neil Horman CC: Joerg Roedel CC: Bjorn Helgaas CC: Andy Lutomirski CC: Konrad Rzeszutek Wilk CC: Sebastian Andrzej Siewior Signed-off-by: Joerg Roedel Signed-off-by: Greg Kroah-Hartman --- drivers/iommu/intel_irq_remapping.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c index 5b19b2d6ec2d..45011f63ad16 100644 --- a/drivers/iommu/intel_irq_remapping.c +++ b/drivers/iommu/intel_irq_remapping.c @@ -525,12 +525,13 @@ static int __init intel_irq_remapping_supported(void) if (disable_irq_remap) return 0; if (irq_remap_broken) { - WARN_TAINT(1, TAINT_FIRMWARE_WORKAROUND, - "This system BIOS has enabled interrupt remapping\n" - "on a chipset that contains an erratum making that\n" - "feature unstable. To maintain system stability\n" - "interrupt remapping is being disabled. Please\n" - "contact your BIOS vendor for an update\n"); + printk(KERN_WARNING + "This system BIOS has enabled interrupt remapping\n" + "on a chipset that contains an erratum making that\n" + "feature unstable. To maintain system stability\n" + "interrupt remapping is being disabled. Please\n" + "contact your BIOS vendor for an update\n"); + add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK); disable_irq_remap = 1; return 0; } -- cgit v1.2.3 From 6d53d39270ccd29938dcbd611a44870c63032521 Mon Sep 17 00:00:00 2001 From: Tomoki Sekiyama Date: Tue, 15 Oct 2013 16:42:16 -0600 Subject: elevator: Fix a race in elevator switching and md device initialization commit eb1c160b22655fd4ec44be732d6594fd1b1e44f4 upstream. The soft lockup below happens at the boot time of the system using dm multipath and the udev rules to switch scheduler. [ 356.127001] BUG: soft lockup - CPU#3 stuck for 22s! [sh:483] [ 356.127001] RIP: 0010:[] [] lock_timer_base.isra.35+0x1d/0x50 ... [ 356.127001] Call Trace: [ 356.127001] [] try_to_del_timer_sync+0x20/0x70 [ 356.127001] [] ? kmem_cache_alloc_node_trace+0x20a/0x230 [ 356.127001] [] del_timer_sync+0x52/0x60 [ 356.127001] [] cfq_exit_queue+0x32/0xf0 [ 356.127001] [] elevator_exit+0x2f/0x50 [ 356.127001] [] elevator_change+0xf1/0x1c0 [ 356.127001] [] elv_iosched_store+0x20/0x50 [ 356.127001] [] queue_attr_store+0x59/0xb0 [ 356.127001] [] sysfs_write_file+0xc6/0x140 [ 356.127001] [] vfs_write+0xbd/0x1e0 [ 356.127001] [] SyS_write+0x49/0xa0 [ 356.127001] [] system_call_fastpath+0x16/0x1b This is caused by a race between md device initialization by multipathd and shell script to switch the scheduler using sysfs. - multipathd: SyS_ioctl -> do_vfs_ioctl -> dm_ctl_ioctl -> ctl_ioctl -> table_load -> dm_setup_md_queue -> blk_init_allocated_queue -> elevator_init q->elevator = elevator_alloc(q, e); // not yet initialized - sh -c 'echo deadline > /sys/$DEVPATH/queue/scheduler': elevator_switch (in the call trace above) struct elevator_queue *old = q->elevator; q->elevator = elevator_alloc(q, new_e); elevator_exit(old); // lockup! (*) - multipathd: (cont.) err = e->ops.elevator_init_fn(q); // init fails; q->elevator is modified (*) When del_timer_sync() is called, lock_timer_base() will loop infinitely while timer->base == NULL. In this case, as timer will never initialized, it results in lockup. This patch introduces acquisition of q->sysfs_lock around elevator_init() into blk_init_allocated_queue(), to provide mutual exclusion between initialization of the q->scheduler and switching of the scheduler. This should fix this bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=902012 Signed-off-by: Tomoki Sekiyama Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- block/blk-core.c | 10 +++++++++- block/elevator.c | 6 ++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/block/blk-core.c b/block/blk-core.c index acf3bf6a44d1..2c66daba44dd 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -741,9 +741,17 @@ blk_init_allocated_queue(struct request_queue *q, request_fn_proc *rfn, q->sg_reserved_size = INT_MAX; + /* Protect q->elevator from elevator_change */ + mutex_lock(&q->sysfs_lock); + /* init elevator */ - if (elevator_init(q, NULL)) + if (elevator_init(q, NULL)) { + mutex_unlock(&q->sysfs_lock); return NULL; + } + + mutex_unlock(&q->sysfs_lock); + return q; } EXPORT_SYMBOL(blk_init_allocated_queue); diff --git a/block/elevator.c b/block/elevator.c index 668394d18588..02d4390afeeb 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -186,6 +186,12 @@ int elevator_init(struct request_queue *q, char *name) struct elevator_type *e = NULL; int err; + /* + * q->sysfs_lock must be held to provide mutual exclusion between + * elevator_switch() and here. + */ + lockdep_assert_held(&q->sysfs_lock); + if (unlikely(q->elevator)) return 0; -- cgit v1.2.3 From 72b9401c2f5ac465d97969ef7933753642bde8bf Mon Sep 17 00:00:00 2001 From: Tomoki Sekiyama Date: Tue, 15 Oct 2013 16:42:19 -0600 Subject: elevator: acquire q->sysfs_lock in elevator_change() commit 7c8a3679e3d8e9d92d58f282161760a0e247df97 upstream. Add locking of q->sysfs_lock into elevator_change() (an exported function) to ensure it is held to protect q->elevator from elevator_init(), even if elevator_change() is called from non-sysfs paths. sysfs path (elv_iosched_store) uses __elevator_change(), non-locking version, as the lock is already taken by elv_iosched_store(). Signed-off-by: Tomoki Sekiyama Signed-off-by: Jens Axboe Cc: Josh Boyer Signed-off-by: Greg Kroah-Hartman --- block/elevator.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/block/elevator.c b/block/elevator.c index 02d4390afeeb..6d765f7e2b2b 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -965,7 +965,7 @@ fail_init: /* * Switch this queue to the given IO scheduler. */ -int elevator_change(struct request_queue *q, const char *name) +static int __elevator_change(struct request_queue *q, const char *name) { char elevator_name[ELV_NAME_MAX]; struct elevator_type *e; @@ -987,6 +987,18 @@ int elevator_change(struct request_queue *q, const char *name) return elevator_switch(q, e); } + +int elevator_change(struct request_queue *q, const char *name) +{ + int ret; + + /* Protect q->elevator from elevator_init() */ + mutex_lock(&q->sysfs_lock); + ret = __elevator_change(q, name); + mutex_unlock(&q->sysfs_lock); + + return ret; +} EXPORT_SYMBOL(elevator_change); ssize_t elv_iosched_store(struct request_queue *q, const char *name, @@ -997,7 +1009,7 @@ ssize_t elv_iosched_store(struct request_queue *q, const char *name, if (!q->elevator) return count; - ret = elevator_change(q, name); + ret = __elevator_change(q, name); if (!ret) return count; -- cgit v1.2.3 From 9baca2ff1035fbdc7f910a4b6fb34d4bec3f443b Mon Sep 17 00:00:00 2001 From: Miroslav Lichvar Date: Thu, 1 Aug 2013 19:31:35 +0200 Subject: ntp: Make periodic RTC update more reliable commit a97ad0c4b447a132a322cedc3a5f7fa4cab4b304 upstream. The current code requires that the scheduled update of the RTC happens in the closest tick to the half of the second. This seems to be difficult to achieve reliably. The scheduled work may be missing the target time by a tick or two and be constantly rescheduled every second. Relax the limit to 10 ticks. As a typical RTC drifts in the 11-minute update interval by several milliseconds, this shouldn't affect the overall accuracy of the RTC much. Signed-off-by: Miroslav Lichvar Signed-off-by: John Stultz Cc: Josh Boyer Signed-off-by: Greg Kroah-Hartman --- kernel/time/ntp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c index bb2215174f05..af8d1d4f3d55 100644 --- a/kernel/time/ntp.c +++ b/kernel/time/ntp.c @@ -475,6 +475,7 @@ static void sync_cmos_clock(struct work_struct *work) * called as close as possible to 500 ms before the new second starts. * This code is run on a timer. If the clock is set, that timer * may not expire at the correct time. Thus, we adjust... + * We want the clock to be within a couple of ticks from the target. */ if (!ntp_synced()) { /* @@ -485,7 +486,7 @@ static void sync_cmos_clock(struct work_struct *work) } getnstimeofday(&now); - if (abs(now.tv_nsec - (NSEC_PER_SEC / 2)) <= tick_nsec / 2) { + if (abs(now.tv_nsec - (NSEC_PER_SEC / 2)) <= tick_nsec * 5) { struct timespec adjust = now; fail = -ENODEV; -- cgit v1.2.3 From f789de214b88dd2f5bbb372625b2e284f8469c4b Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 6 Nov 2013 20:09:08 +0100 Subject: drm/radeon/audio: improve ACR calculation commit a2098250fbda149cfad9e626afe80abe3b21e574 upstream. In order to have any realistic chance of calculating proper ACR values, we need to be able to calculate both N and CTS, not just CTS. We still aim for the ideal N as specified in the HDMI spec though. bug: https://bugs.freedesktop.org/show_bug.cgi?id=69675 Signed-off-by: Pierre Ossman Signed-off-by: Alex Deucher Cc: Josh Boyer Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/r600_hdmi.c | 68 ++++++++++++++++++++++++++------------ 1 file changed, 46 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c index 635e8f2e84f7..cf4c10090399 100644 --- a/drivers/gpu/drm/radeon/r600_hdmi.c +++ b/drivers/gpu/drm/radeon/r600_hdmi.c @@ -24,6 +24,7 @@ * Authors: Christian König */ #include +#include #include #include #include "radeon.h" @@ -67,25 +68,47 @@ static const struct radeon_hdmi_acr r600_hdmi_predefined_acr[] = { { 74250, 4096, 74250, 6272, 82500, 6144, 74250 }, /* 74.25 MHz */ { 148352, 11648, 421875, 8918, 234375, 5824, 140625 }, /* 148.50/1.001 MHz */ { 148500, 4096, 148500, 6272, 165000, 6144, 148500 }, /* 148.50 MHz */ - { 0, 4096, 0, 6272, 0, 6144, 0 } /* Other */ }; + /* - * calculate CTS value if it's not found in the table + * calculate CTS and N values if they are not found in the table */ -static void r600_hdmi_calc_cts(uint32_t clock, int *CTS, int N, int freq) +static void r600_hdmi_calc_cts(uint32_t clock, int *CTS, int *N, int freq) { - u64 n; - u32 d; - - if (*CTS == 0) { - n = (u64)clock * (u64)N * 1000ULL; - d = 128 * freq; - do_div(n, d); - *CTS = n; - } - DRM_DEBUG("Using ACR timing N=%d CTS=%d for frequency %d\n", - N, *CTS, freq); + int n, cts; + unsigned long div, mul; + + /* Safe, but overly large values */ + n = 128 * freq; + cts = clock * 1000; + + /* Smallest valid fraction */ + div = gcd(n, cts); + + n /= div; + cts /= div; + + /* + * The optimal N is 128*freq/1000. Calculate the closest larger + * value that doesn't truncate any bits. + */ + mul = ((128*freq/1000) + (n-1))/n; + + n *= mul; + cts *= mul; + + /* Check that we are in spec (not always possible) */ + if (n < (128*freq/1500)) + printk(KERN_WARNING "Calculated ACR N value is too small. You may experience audio problems.\n"); + if (n > (128*freq/300)) + printk(KERN_WARNING "Calculated ACR N value is too large. You may experience audio problems.\n"); + + *N = n; + *CTS = cts; + + DRM_DEBUG("Calculated ACR timing N=%d CTS=%d for frequency %d\n", + *N, *CTS, freq); } struct radeon_hdmi_acr r600_hdmi_acr(uint32_t clock) @@ -93,15 +116,16 @@ struct radeon_hdmi_acr r600_hdmi_acr(uint32_t clock) struct radeon_hdmi_acr res; u8 i; - for (i = 0; r600_hdmi_predefined_acr[i].clock != clock && - r600_hdmi_predefined_acr[i].clock != 0; i++) - ; - res = r600_hdmi_predefined_acr[i]; + /* Precalculated values for common clocks */ + for (i = 0; i < ARRAY_SIZE(r600_hdmi_predefined_acr); i++) { + if (r600_hdmi_predefined_acr[i].clock == clock) + return r600_hdmi_predefined_acr[i]; + } - /* In case some CTS are missing */ - r600_hdmi_calc_cts(clock, &res.cts_32khz, res.n_32khz, 32000); - r600_hdmi_calc_cts(clock, &res.cts_44_1khz, res.n_44_1khz, 44100); - r600_hdmi_calc_cts(clock, &res.cts_48khz, res.n_48khz, 48000); + /* And odd clocks get manually calculated */ + r600_hdmi_calc_cts(clock, &res.cts_32khz, &res.n_32khz, 32000); + r600_hdmi_calc_cts(clock, &res.cts_44_1khz, &res.n_44_1khz, 44100); + r600_hdmi_calc_cts(clock, &res.cts_48khz, &res.n_48khz, 48000); return res; } -- cgit v1.2.3 From 84a0264e3992db6dd46d4485e171a13be4550d0c Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 6 Nov 2013 20:00:32 +0100 Subject: drm/radeon/audio: correct ACR table commit 3e71985f2439d8c4090dc2820e497e6f3d72dcff upstream. The values were taken from the HDMI spec, but they assumed exact x/1.001 clocks. Since we round the clocks, we also need to calculate different N and CTS values. Note that the N for 25.2/1.001 MHz at 44.1 kHz audio is out of spec. Hopefully this mode is rarely used and/or HDMI sinks tolerate overly large values of N. bug: https://bugs.freedesktop.org/show_bug.cgi?id=69675 Signed-off-by: Pierre Ossman Signed-off-by: Alex Deucher Cc: Josh Boyer Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/r600_hdmi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c index cf4c10090399..01ed8ac4d156 100644 --- a/drivers/gpu/drm/radeon/r600_hdmi.c +++ b/drivers/gpu/drm/radeon/r600_hdmi.c @@ -58,15 +58,15 @@ enum r600_hdmi_iec_status_bits { static const struct radeon_hdmi_acr r600_hdmi_predefined_acr[] = { /* 32kHz 44.1kHz 48kHz */ /* Clock N CTS N CTS N CTS */ - { 25175, 4576, 28125, 7007, 31250, 6864, 28125 }, /* 25,20/1.001 MHz */ + { 25175, 4096, 25175, 28224, 125875, 6144, 25175 }, /* 25,20/1.001 MHz */ { 25200, 4096, 25200, 6272, 28000, 6144, 25200 }, /* 25.20 MHz */ { 27000, 4096, 27000, 6272, 30000, 6144, 27000 }, /* 27.00 MHz */ { 27027, 4096, 27027, 6272, 30030, 6144, 27027 }, /* 27.00*1.001 MHz */ { 54000, 4096, 54000, 6272, 60000, 6144, 54000 }, /* 54.00 MHz */ { 54054, 4096, 54054, 6272, 60060, 6144, 54054 }, /* 54.00*1.001 MHz */ - { 74176, 11648, 210937, 17836, 234375, 11648, 140625 }, /* 74.25/1.001 MHz */ + { 74176, 4096, 74176, 5733, 75335, 6144, 74176 }, /* 74.25/1.001 MHz */ { 74250, 4096, 74250, 6272, 82500, 6144, 74250 }, /* 74.25 MHz */ - { 148352, 11648, 421875, 8918, 234375, 5824, 140625 }, /* 148.50/1.001 MHz */ + { 148352, 4096, 148352, 5733, 150670, 6144, 148352 }, /* 148.50/1.001 MHz */ { 148500, 4096, 148500, 6272, 165000, 6144, 148500 }, /* 148.50 MHz */ }; -- cgit v1.2.3 From 184c20bbc978eb7a2e1d3637b7864208822c7ebc Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 8 Dec 2013 08:17:21 -0800 Subject: Linux 3.10.23 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 001188ce8241..c6d2ec5e9580 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 10 -SUBLEVEL = 22 +SUBLEVEL = 23 EXTRAVERSION = NAME = TOSSUG Baby Fish -- cgit v1.2.3 From daba76170151aa64ba29d46c9426b4d0b204601d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 29 Nov 2013 12:47:34 +0100 Subject: ALSA: hda - Fix silent output on ASUS W7J laptop commit 6ddf0fd1c462a418a3cbb8b0653820dc48ffbd98 upstream. The recent kernels got regressions on ASUS W7J with ALC660 codec where no sound comes out. After a long debugging session, we found out that setting the pin control on the unused NID 0x10 is mandatory for the outputs. And, it was found out that another magic of NID 0x0f that is required for other ASUS laptops isn't needed on this machine. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=66081 Reported-and-tested-by: Andrey Lipaev Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 661afe7d85e4..8b7c9e86b7d8 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -3896,6 +3896,7 @@ enum { ALC861_FIXUP_AMP_VREF_0F, ALC861_FIXUP_NO_JACK_DETECT, ALC861_FIXUP_ASUS_A6RP, + ALC660_FIXUP_ASUS_W7J, }; /* On some laptops, VREF of pin 0x0f is abused for controlling the main amp */ @@ -3945,10 +3946,21 @@ static const struct hda_fixup alc861_fixups[] = { .v.func = alc861_fixup_asus_amp_vref_0f, .chained = true, .chain_id = ALC861_FIXUP_NO_JACK_DETECT, + }, + [ALC660_FIXUP_ASUS_W7J] = { + .type = HDA_FIXUP_VERBS, + .v.verbs = (const struct hda_verb[]) { + /* ASUS W7J needs a magic pin setup on unused NID 0x10 + * for enabling outputs + */ + {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, + { } + }, } }; static const struct snd_pci_quirk alc861_fixup_tbl[] = { + SND_PCI_QUIRK(0x1043, 0x1253, "ASUS W7J", ALC660_FIXUP_ASUS_W7J), SND_PCI_QUIRK(0x1043, 0x1393, "ASUS A6Rp", ALC861_FIXUP_ASUS_A6RP), SND_PCI_QUIRK_VENDOR(0x1043, "ASUS laptop", ALC861_FIXUP_AMP_VREF_0F), SND_PCI_QUIRK(0x1462, 0x7254, "HP DX2200", ALC861_FIXUP_NO_JACK_DETECT), -- cgit v1.2.3 From e0979ec7e098007b943b6e779093eb62b4551884 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 2 Dec 2013 15:27:19 +0100 Subject: ALSA: hda - Another fixup for ASUS laptop with ALC660 codec commit e7ca237bfcf6a288702cb95e94ab94f642ccad88 upstream. ASUS Z35HL laptop also needs the very same fix as the previous one that was applied to ASUS W7J. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=66231 Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 8b7c9e86b7d8..db5168555a14 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -3961,6 +3961,7 @@ static const struct hda_fixup alc861_fixups[] = { static const struct snd_pci_quirk alc861_fixup_tbl[] = { SND_PCI_QUIRK(0x1043, 0x1253, "ASUS W7J", ALC660_FIXUP_ASUS_W7J), + SND_PCI_QUIRK(0x1043, 0x1263, "ASUS Z35HL", ALC660_FIXUP_ASUS_W7J), SND_PCI_QUIRK(0x1043, 0x1393, "ASUS A6Rp", ALC861_FIXUP_ASUS_A6RP), SND_PCI_QUIRK_VENDOR(0x1043, "ASUS laptop", ALC861_FIXUP_AMP_VREF_0F), SND_PCI_QUIRK(0x1462, 0x7254, "HP DX2200", ALC861_FIXUP_NO_JACK_DETECT), -- cgit v1.2.3 From c4fcb3cd61aecde82df7d9856e3d2201e908ca65 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Mon, 2 Dec 2013 18:06:20 +0800 Subject: ALSA: hda - Fix headset mic input after muted internal mic (Dell/Realtek) commit d59915d0655c5864b514f21daaeac98c047875dc upstream. By trial and error, I found this patch could work around an issue where the headset mic would stop working if you switch between the internal mic and the headset mic, and the internal mic was muted. It still takes a second or two before the headset mic actually starts working, but still better than nothing. Information update from Kailang: The verb was ADC digital mute(bit 6 default 1). Switch internal mic and headset mic will run alc_headset_mode_default. The coef index 0x11 will set to 0x0041. Because headset mode was fixed type. It doesn't need to run alc_determine_headset_type. So, the value still keep 0x0041. ADC was muted. BugLink: https://bugs.launchpad.net/bugs/1256840 Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index db5168555a14..a7605db321a4 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -3041,6 +3041,7 @@ static void alc_headset_mode_ctia(struct hda_codec *codec) alc_write_coef_idx(codec, 0x18, 0x7388); break; case 0x10ec0668: + alc_write_coef_idx(codec, 0x11, 0x0001); alc_write_coef_idx(codec, 0x15, 0x0d60); alc_write_coef_idx(codec, 0xc3, 0x0000); break; @@ -3063,6 +3064,7 @@ static void alc_headset_mode_omtp(struct hda_codec *codec) alc_write_coef_idx(codec, 0x18, 0x7388); break; case 0x10ec0668: + alc_write_coef_idx(codec, 0x11, 0x0001); alc_write_coef_idx(codec, 0x15, 0x0d50); alc_write_coef_idx(codec, 0xc3, 0x0000); break; -- cgit v1.2.3 From 64871fb0be804a971bcdc5db337101d2537167b4 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 4 Dec 2013 13:59:45 +0100 Subject: ALSA: hda - Fix silent output on MacBook Air 2,1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 0756f09c4946fe2d9ce2ebcb6f2e3c58830d22a3 upstream. MacBook Air 2,1 has a fairly different pin assignment from its brother MBA 1,1, and yet another quirks are needed for pin 0x18 and 0x19, similarly like what iMac 9,1 requires, in order to make the sound working on it. Reported-and-tested-by: Bruno Prémont Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 39 +++++++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index a7605db321a4..e755f5109d84 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -1763,6 +1763,7 @@ enum { ALC889_FIXUP_DAC_ROUTE, ALC889_FIXUP_MBP_VREF, ALC889_FIXUP_IMAC91_VREF, + ALC889_FIXUP_MBA21_VREF, ALC882_FIXUP_INV_DMIC, ALC882_FIXUP_NO_PRIMARY_HP, ALC887_FIXUP_ASUS_BASS, @@ -1866,17 +1867,13 @@ static void alc889_fixup_mbp_vref(struct hda_codec *codec, } } -/* Set VREF on speaker pins on imac91 */ -static void alc889_fixup_imac91_vref(struct hda_codec *codec, - const struct hda_fixup *fix, int action) +static void alc889_fixup_mac_pins(struct hda_codec *codec, + const hda_nid_t *nids, int num_nids) { struct alc_spec *spec = codec->spec; - static hda_nid_t nids[2] = { 0x18, 0x1a }; int i; - if (action != HDA_FIXUP_ACT_INIT) - return; - for (i = 0; i < ARRAY_SIZE(nids); i++) { + for (i = 0; i < num_nids; i++) { unsigned int val; val = snd_hda_codec_get_pin_target(codec, nids[i]); val |= AC_PINCTL_VREF_50; @@ -1885,6 +1882,26 @@ static void alc889_fixup_imac91_vref(struct hda_codec *codec, spec->gen.keep_vref_in_automute = 1; } +/* Set VREF on speaker pins on imac91 */ +static void alc889_fixup_imac91_vref(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + static hda_nid_t nids[2] = { 0x18, 0x1a }; + + if (action == HDA_FIXUP_ACT_INIT) + alc889_fixup_mac_pins(codec, nids, ARRAY_SIZE(nids)); +} + +/* Set VREF on speaker pins on mba21 */ +static void alc889_fixup_mba21_vref(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + static hda_nid_t nids[2] = { 0x18, 0x19 }; + + if (action == HDA_FIXUP_ACT_INIT) + alc889_fixup_mac_pins(codec, nids, ARRAY_SIZE(nids)); +} + /* Don't take HP output as primary * Strangely, the speaker output doesn't work on Vaio Z and some Vaio * all-in-one desktop PCs (for example VGC-LN51JGB) through DAC 0x05 @@ -2079,6 +2096,12 @@ static const struct hda_fixup alc882_fixups[] = { .chained = true, .chain_id = ALC882_FIXUP_GPIO1, }, + [ALC889_FIXUP_MBA21_VREF] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc889_fixup_mba21_vref, + .chained = true, + .chain_id = ALC889_FIXUP_MBP_VREF, + }, [ALC882_FIXUP_INV_DMIC] = { .type = HDA_FIXUP_FUNC, .v.func = alc_fixup_inv_dmic_0x12, @@ -2143,7 +2166,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { SND_PCI_QUIRK(0x106b, 0x3000, "iMac", ALC889_FIXUP_MBP_VREF), SND_PCI_QUIRK(0x106b, 0x3200, "iMac 7,1 Aluminum", ALC882_FIXUP_EAPD), SND_PCI_QUIRK(0x106b, 0x3400, "MacBookAir 1,1", ALC889_FIXUP_MBP_VREF), - SND_PCI_QUIRK(0x106b, 0x3500, "MacBookAir 2,1", ALC889_FIXUP_MBP_VREF), + SND_PCI_QUIRK(0x106b, 0x3500, "MacBookAir 2,1", ALC889_FIXUP_MBA21_VREF), SND_PCI_QUIRK(0x106b, 0x3600, "Macbook 3,1", ALC889_FIXUP_MBP_VREF), SND_PCI_QUIRK(0x106b, 0x3800, "MacbookPro 4,1", ALC889_FIXUP_MBP_VREF), SND_PCI_QUIRK(0x106b, 0x3e00, "iMac 24 Aluminum", ALC885_FIXUP_MACPRO_GPIO), -- cgit v1.2.3 From 87a226e9df5efd1c7d26756fab9e9f29a267ac47 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Fri, 29 Nov 2013 15:10:20 +0800 Subject: ALSA: hda - Add mono speaker quirk for Dell Inspiron 5439 commit eb82594b75b0cf54c667189e061934b7c49b5d42 upstream. This machine also has mono output if run through DAC node 0x03. BugLink: https://bugs.launchpad.net/bugs/1256212 Tested-by: David Chen Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index e755f5109d84..937079a5265a 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -3657,6 +3657,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1028, 0x0613, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x0614, "Dell Inspiron 3135", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x0616, "Dell Vostro 5470", ALC290_FIXUP_MONO_SPEAKERS), + SND_PCI_QUIRK(0x1028, 0x0638, "Dell Inspiron 5439", ALC290_FIXUP_MONO_SPEAKERS), SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2), SND_PCI_QUIRK(0x103c, 0x18e6, "HP", ALC269_FIXUP_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x1973, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1), -- cgit v1.2.3 From da94360f55be9d57c866f4d6b0861d9ecd1a1aeb Mon Sep 17 00:00:00 2001 From: Gerald Schaefer Date: Tue, 19 Nov 2013 17:12:47 +0100 Subject: crypto: s390 - Fix aes-xts parameter corruption commit 9dda2769af4f3f3093434648c409bb351120d9e8 upstream. Some s390 crypto algorithms incorrectly use the crypto_tfm structure to store private data. As the tfm can be shared among multiple threads, this can result in data corruption. This patch fixes aes-xts by moving the xts and pcc parameter blocks from the tfm onto the stack (48 + 96 bytes). Signed-off-by: Gerald Schaefer Signed-off-by: Herbert Xu Signed-off-by: Greg Kroah-Hartman --- arch/s390/crypto/aes_s390.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/arch/s390/crypto/aes_s390.c b/arch/s390/crypto/aes_s390.c index 2e4b5be31a1b..94e20dd2729f 100644 --- a/arch/s390/crypto/aes_s390.c +++ b/arch/s390/crypto/aes_s390.c @@ -55,8 +55,7 @@ struct pcc_param { struct s390_xts_ctx { u8 key[32]; - u8 xts_param[16]; - struct pcc_param pcc; + u8 pcc_key[32]; long enc; long dec; int key_len; @@ -591,7 +590,7 @@ static int xts_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, xts_ctx->enc = KM_XTS_128_ENCRYPT; xts_ctx->dec = KM_XTS_128_DECRYPT; memcpy(xts_ctx->key + 16, in_key, 16); - memcpy(xts_ctx->pcc.key + 16, in_key + 16, 16); + memcpy(xts_ctx->pcc_key + 16, in_key + 16, 16); break; case 48: xts_ctx->enc = 0; @@ -602,7 +601,7 @@ static int xts_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, xts_ctx->enc = KM_XTS_256_ENCRYPT; xts_ctx->dec = KM_XTS_256_DECRYPT; memcpy(xts_ctx->key, in_key, 32); - memcpy(xts_ctx->pcc.key, in_key + 32, 32); + memcpy(xts_ctx->pcc_key, in_key + 32, 32); break; default: *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; @@ -621,29 +620,33 @@ static int xts_aes_crypt(struct blkcipher_desc *desc, long func, unsigned int nbytes = walk->nbytes; unsigned int n; u8 *in, *out; - void *param; + struct pcc_param pcc_param; + struct { + u8 key[32]; + u8 init[16]; + } xts_param; if (!nbytes) goto out; - memset(xts_ctx->pcc.block, 0, sizeof(xts_ctx->pcc.block)); - memset(xts_ctx->pcc.bit, 0, sizeof(xts_ctx->pcc.bit)); - memset(xts_ctx->pcc.xts, 0, sizeof(xts_ctx->pcc.xts)); - memcpy(xts_ctx->pcc.tweak, walk->iv, sizeof(xts_ctx->pcc.tweak)); - param = xts_ctx->pcc.key + offset; - ret = crypt_s390_pcc(func, param); + memset(pcc_param.block, 0, sizeof(pcc_param.block)); + memset(pcc_param.bit, 0, sizeof(pcc_param.bit)); + memset(pcc_param.xts, 0, sizeof(pcc_param.xts)); + memcpy(pcc_param.tweak, walk->iv, sizeof(pcc_param.tweak)); + memcpy(pcc_param.key, xts_ctx->pcc_key, 32); + ret = crypt_s390_pcc(func, &pcc_param.key[offset]); if (ret < 0) return -EIO; - memcpy(xts_ctx->xts_param, xts_ctx->pcc.xts, 16); - param = xts_ctx->key + offset; + memcpy(xts_param.key, xts_ctx->key, 32); + memcpy(xts_param.init, pcc_param.xts, 16); do { /* only use complete blocks */ n = nbytes & ~(AES_BLOCK_SIZE - 1); out = walk->dst.virt.addr; in = walk->src.virt.addr; - ret = crypt_s390_km(func, param, out, in, n); + ret = crypt_s390_km(func, &xts_param.key[offset], out, in, n); if (ret < 0 || ret != n) return -EIO; -- cgit v1.2.3 From a426ea27b26cca933cba53e189d6478bd04eddd1 Mon Sep 17 00:00:00 2001 From: Tom Lendacky Date: Tue, 12 Nov 2013 11:46:10 -0600 Subject: crypto: scatterwalk - Set the chain pointer indication bit commit 41da8b5adba77e22584f8b45f9641504fa885308 upstream. The scatterwalk_crypto_chain function invokes the scatterwalk_sg_chain function to chain two scatterlists, but the chain pointer indication bit is not set. When the resulting scatterlist is used, for example, by sg_nents to count the number of scatterlist entries, a segfault occurs because sg_nents does not follow the chain pointer to the chained scatterlist. Update scatterwalk_sg_chain to set the chain pointer indication bit as is done by the sg_chain function. Signed-off-by: Tom Lendacky Signed-off-by: Herbert Xu Signed-off-by: Greg Kroah-Hartman --- include/crypto/scatterwalk.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/crypto/scatterwalk.h b/include/crypto/scatterwalk.h index 3744d2a642df..09ef1a0c5499 100644 --- a/include/crypto/scatterwalk.h +++ b/include/crypto/scatterwalk.h @@ -36,6 +36,7 @@ static inline void scatterwalk_sg_chain(struct scatterlist *sg1, int num, { sg_set_page(&sg1[num - 1], (void *)sg2, 0, 0); sg1[num - 1].page_link &= ~0x02; + sg1[num - 1].page_link |= 0x01; } static inline struct scatterlist *scatterwalk_sg_next(struct scatterlist *sg) -- cgit v1.2.3 From bf2e52300b9e5a329c5f76ba8d77e33ade976b1c Mon Sep 17 00:00:00 2001 From: Horia Geanta Date: Thu, 28 Nov 2013 15:11:15 +0200 Subject: crypto: ccm - Fix handling of zero plaintext when computing mac commit 5638cabf3e4883f38dfb246c30980cebf694fbda upstream. There are cases when cryptlen can be zero in crypto_ccm_auth(): -encryptiom: input scatterlist length is zero (no plaintext) -decryption: input scatterlist contains only the mac plus the condition of having different source and destination buffers (or else scatterlist length = max(plaintext_len, ciphertext_len)). These are not handled correctly, leading to crashes like: root@p4080ds:~/crypto# insmod tcrypt.ko mode=45 ------------[ cut here ]------------ kernel BUG at crypto/scatterwalk.c:37! Oops: Exception in kernel mode, sig: 5 [#1] SMP NR_CPUS=8 P4080 DS Modules linked in: tcrypt(+) crc32c xts xcbc vmac pcbc ecb gcm ghash_generic gf128mul ccm ctr seqiv CPU: 3 PID: 1082 Comm: cryptomgr_test Not tainted 3.11.0 #14 task: ee12c5b0 ti: eecd0000 task.ti: eecd0000 NIP: c0204d98 LR: f9225848 CTR: c0204d80 REGS: eecd1b70 TRAP: 0700 Not tainted (3.11.0) MSR: 00029002 CR: 22044022 XER: 20000000 GPR00: f9225c94 eecd1c20 ee12c5b0 eecd1c28 ee879400 ee879400 00000000 ee607464 GPR08: 00000001 00000001 00000000 006b0000 c0204d80 00000000 00000002 c0698e20 GPR16: ee987000 ee895000 fffffff4 ee879500 00000100 eecd1d58 00000001 00000000 GPR24: ee879400 00000020 00000000 00000000 ee5b2800 ee607430 00000004 ee607460 NIP [c0204d98] scatterwalk_start+0x18/0x30 LR [f9225848] get_data_to_compute+0x28/0x2f0 [ccm] Call Trace: [eecd1c20] [f9225974] get_data_to_compute+0x154/0x2f0 [ccm] (unreliable) [eecd1c70] [f9225c94] crypto_ccm_auth+0x184/0x1d0 [ccm] [eecd1cb0] [f9225d40] crypto_ccm_encrypt+0x60/0x2d0 [ccm] [eecd1cf0] [c020d77c] __test_aead+0x3ec/0xe20 [eecd1e20] [c020f35c] test_aead+0x6c/0xe0 [eecd1e40] [c020f420] alg_test_aead+0x50/0xd0 [eecd1e60] [c020e5e4] alg_test+0x114/0x2e0 [eecd1ee0] [c020bd1c] cryptomgr_test+0x4c/0x60 [eecd1ef0] [c0047058] kthread+0xa8/0xb0 [eecd1f40] [c000eb0c] ret_from_kernel_thread+0x5c/0x64 Instruction dump: 0f080000 81290024 552807fe 0f080000 5529003a 4bffffb4 90830000 39400000 39000001 8124000c 2f890000 7d28579e <0f090000> 81240008 91230004 4e800020 ---[ end trace 6d652dfcd1be37bd ]--- Cc: Jussi Kivilinna Signed-off-by: Horia Geanta Signed-off-by: Herbert Xu Signed-off-by: Greg Kroah-Hartman --- crypto/ccm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crypto/ccm.c b/crypto/ccm.c index 499c91717d93..ed009b77e67d 100644 --- a/crypto/ccm.c +++ b/crypto/ccm.c @@ -271,7 +271,8 @@ static int crypto_ccm_auth(struct aead_request *req, struct scatterlist *plain, } /* compute plaintext into mac */ - get_data_to_compute(cipher, pctx, plain, cryptlen); + if (cryptlen) + get_data_to_compute(cipher, pctx, plain, cryptlen); out: return err; -- cgit v1.2.3 From 1c651d3627a2d3ba10f2f116303ca620e17b14d5 Mon Sep 17 00:00:00 2001 From: Tom Lendacky Date: Tue, 12 Nov 2013 11:46:04 -0600 Subject: crypto: authenc - Find proper IV address in ablkcipher callback commit fc019c7122dfcd69c50142b57a735539aec5da95 upstream. When performing an asynchronous ablkcipher operation the authenc completion callback routine is invoked, but it does not locate and use the proper IV. The callback routine, crypto_authenc_encrypt_done, is updated to use the same method of calculating the address of the IV as is done in crypto_authenc_encrypt function which sets up the callback. Signed-off-by: Tom Lendacky Signed-off-by: Herbert Xu Signed-off-by: Greg Kroah-Hartman --- crypto/authenc.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/crypto/authenc.c b/crypto/authenc.c index ffce19de05cf..528b00bc4769 100644 --- a/crypto/authenc.c +++ b/crypto/authenc.c @@ -368,9 +368,10 @@ static void crypto_authenc_encrypt_done(struct crypto_async_request *req, if (!err) { struct crypto_aead *authenc = crypto_aead_reqtfm(areq); struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc); - struct ablkcipher_request *abreq = aead_request_ctx(areq); - u8 *iv = (u8 *)(abreq + 1) + - crypto_ablkcipher_reqsize(ctx->enc); + struct authenc_request_ctx *areq_ctx = aead_request_ctx(areq); + struct ablkcipher_request *abreq = (void *)(areq_ctx->tail + + ctx->reqoff); + u8 *iv = (u8 *)abreq - crypto_ablkcipher_ivsize(ctx->enc); err = crypto_authenc_genicv(areq, iv, 0); } -- cgit v1.2.3 From d47787bdf7cd4dfccfaffdab00b5b593d6270a6a Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 28 Nov 2013 21:43:40 +0000 Subject: ARM: fix booting low-vectors machines commit d8aa712c30148ba26fd89a5dc14de95d4c375184 upstream. Commit f6f91b0d9fd9 (ARM: allow kuser helpers to be removed from the vector page) required two pages for the vectors code. Although the code setting up the initial page tables was updated, the code which allocates page tables for new processes wasn't, neither was the code which tears down the mappings. Fix this. Fixes: f6f91b0d9fd9 ("ARM: allow kuser helpers to be removed from the vector page") Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/include/asm/pgtable.h | 2 +- arch/arm/mm/mmap.c | 2 +- arch/arm/mm/pgd.c | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index 9bcd262a9008..5aac06fcc97e 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h @@ -58,7 +58,7 @@ extern void __pgd_error(const char *file, int line, pgd_t); * mapping to be mapped at. This is particularly important for * non-high vector CPUs. */ -#define FIRST_USER_ADDRESS PAGE_SIZE +#define FIRST_USER_ADDRESS (PAGE_SIZE * 2) /* * Use TASK_SIZE as the ceiling argument for free_pgtables() and diff --git a/arch/arm/mm/mmap.c b/arch/arm/mm/mmap.c index 10062ceadd1c..f0ef2f7d4ad7 100644 --- a/arch/arm/mm/mmap.c +++ b/arch/arm/mm/mmap.c @@ -146,7 +146,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, info.flags = VM_UNMAPPED_AREA_TOPDOWN; info.length = len; - info.low_limit = PAGE_SIZE; + info.low_limit = FIRST_USER_ADDRESS; info.high_limit = mm->mmap_base; info.align_mask = do_align ? (PAGE_MASK & (SHMLBA - 1)) : 0; info.align_offset = pgoff << PAGE_SHIFT; diff --git a/arch/arm/mm/pgd.c b/arch/arm/mm/pgd.c index 0acb089d0f70..1046b373d1ae 100644 --- a/arch/arm/mm/pgd.c +++ b/arch/arm/mm/pgd.c @@ -87,7 +87,8 @@ pgd_t *pgd_alloc(struct mm_struct *mm) init_pud = pud_offset(init_pgd, 0); init_pmd = pmd_offset(init_pud, 0); init_pte = pte_offset_map(init_pmd, 0); - set_pte_ext(new_pte, *init_pte, 0); + set_pte_ext(new_pte + 0, init_pte[0], 0); + set_pte_ext(new_pte + 1, init_pte[1], 0); pte_unmap(init_pte); pte_unmap(new_pte); } -- cgit v1.2.3 From d877bdfe0c784f4b1d9e0d0ba151d0f4e6a2d09b Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 28 Nov 2013 21:55:41 +0000 Subject: ARM: footbridge: fix VGA initialisation commit 43659222e7a0113912ed02f6b2231550b3e471ac upstream. It's no good setting vga_base after the VGA console has been initialised, because if we do that we get this: Unable to handle kernel paging request at virtual address 000b8000 pgd = c0004000 [000b8000] *pgd=07ffc831, *pte=00000000, *ppte=00000000 0Internal error: Oops: 5017 [#1] ARM Modules linked in: CPU: 0 PID: 0 Comm: swapper Not tainted 3.12.0+ #49 task: c03e2974 ti: c03d8000 task.ti: c03d8000 PC is at vgacon_startup+0x258/0x39c LR is at request_resource+0x10/0x1c pc : [] lr : [] psr: 60000053 sp : c03d9f68 ip : 000b8000 fp : c03d9f8c r10: 000055aa r9 : 4401a103 r8 : ffffaa55 r7 : c03e357c r6 : c051b460 r5 : 000000ff r4 : 000c0000 r3 : 000b8000 r2 : c03e0514 r1 : 00000000 r0 : c0304971 Flags: nZCv IRQs on FIQs off Mode SVC_32 ISA ARM Segment kernel which is an access to the 0xb8000 without the PCI offset required to make it work. Fixes: cc22b4c18540 ("ARM: set vga memory base at run-time") Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-footbridge/common.c | 3 +++ arch/arm/mach-footbridge/dc21285.c | 2 -- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-footbridge/common.c b/arch/arm/mach-footbridge/common.c index a42b369bc439..95d0b6e6438b 100644 --- a/arch/arm/mach-footbridge/common.c +++ b/arch/arm/mach-footbridge/common.c @@ -15,6 +15,7 @@ #include #include #include +#include