From 5596732fa8c14139018ecda8356eabbfb599d830 Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Mon, 7 Apr 2014 08:08:52 +0200 Subject: xfrm: Fix crash with ipv6 IPsec tunnel and NAT. The ipv6 xfrm output path is not aware that packets can be rerouted by NAT to not use IPsec. We crash in this case because we expect to have a xfrm state at the dst_entry. This crash happens if the ipv6 layer does IPsec and NAT or if we have an interfamily IPsec tunnel with ipv4 NAT. We fix this by checking for a NAT rerouted packet in each address family and dst_output() to the new destination in this case. Reported-by: Martin Pelikan Tested-by: Martin Pelikan Signed-off-by: Steffen Klassert --- net/ipv4/xfrm4_output.c | 32 ++++++++++++++++++-------------- net/ipv6/xfrm6_output.c | 22 +++++++++++++--------- 2 files changed, 31 insertions(+), 23 deletions(-) diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c index baa0f63731fd..f3800bf79d86 100644 --- a/net/ipv4/xfrm4_output.c +++ b/net/ipv4/xfrm4_output.c @@ -62,10 +62,7 @@ int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb) if (err) return err; - memset(IPCB(skb), 0, sizeof(*IPCB(skb))); - IPCB(skb)->flags |= IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED; - - skb->protocol = htons(ETH_P_IP); + IPCB(skb)->flags |= IPSKB_XFRM_TUNNEL_SIZE; return x->outer_mode->output2(x, skb); } @@ -73,27 +70,34 @@ EXPORT_SYMBOL(xfrm4_prepare_output); int xfrm4_output_finish(struct sk_buff *skb) { + memset(IPCB(skb), 0, sizeof(*IPCB(skb))); + skb->protocol = htons(ETH_P_IP); + +#ifdef CONFIG_NETFILTER + IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED; +#endif + + return xfrm_output(skb); +} + +static int __xfrm4_output(struct sk_buff *skb) +{ + struct xfrm_state *x = skb_dst(skb)->xfrm; + #ifdef CONFIG_NETFILTER - if (!skb_dst(skb)->xfrm) { + if (!x) { IPCB(skb)->flags |= IPSKB_REROUTED; return dst_output(skb); } - - IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED; #endif - skb->protocol = htons(ETH_P_IP); - return xfrm_output(skb); + return x->outer_mode->afinfo->output_finish(skb); } int xfrm4_output(struct sk_buff *skb) { - struct dst_entry *dst = skb_dst(skb); - struct xfrm_state *x = dst->xfrm; - return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, skb, - NULL, dst->dev, - x->outer_mode->afinfo->output_finish, + NULL, skb_dst(skb)->dev, __xfrm4_output, !(IPCB(skb)->flags & IPSKB_REROUTED)); } diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c index 6cd625e37706..ba624331451c 100644 --- a/net/ipv6/xfrm6_output.c +++ b/net/ipv6/xfrm6_output.c @@ -114,12 +114,6 @@ int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb) if (err) return err; - memset(IP6CB(skb), 0, sizeof(*IP6CB(skb))); -#ifdef CONFIG_NETFILTER - IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED; -#endif - - skb->protocol = htons(ETH_P_IPV6); skb->local_df = 1; return x->outer_mode->output2(x, skb); @@ -128,11 +122,13 @@ EXPORT_SYMBOL(xfrm6_prepare_output); int xfrm6_output_finish(struct sk_buff *skb) { + memset(IP6CB(skb), 0, sizeof(*IP6CB(skb))); + skb->protocol = htons(ETH_P_IPV6); + #ifdef CONFIG_NETFILTER IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED; #endif - skb->protocol = htons(ETH_P_IPV6); return xfrm_output(skb); } @@ -142,6 +138,13 @@ static int __xfrm6_output(struct sk_buff *skb) struct xfrm_state *x = dst->xfrm; int mtu; +#ifdef CONFIG_NETFILTER + if (!x) { + IP6CB(skb)->flags |= IP6SKB_REROUTED; + return dst_output(skb); + } +#endif + if (skb->protocol == htons(ETH_P_IPV6)) mtu = ip6_skb_dst_mtu(skb); else @@ -165,6 +168,7 @@ static int __xfrm6_output(struct sk_buff *skb) int xfrm6_output(struct sk_buff *skb) { - return NF_HOOK(NFPROTO_IPV6, NF_INET_POST_ROUTING, skb, NULL, - skb_dst(skb)->dev, __xfrm6_output); + return NF_HOOK_COND(NFPROTO_IPV6, NF_INET_POST_ROUTING, skb, + NULL, skb_dst(skb)->dev, __xfrm6_output, + !(IP6CB(skb)->flags & IP6SKB_REROUTED)); } -- cgit v1.2.3 From ef67f18dece707eb2fb1ef25ccca47062842dc4a Mon Sep 17 00:00:00 2001 From: Alexander Bondar Date: Sun, 30 Mar 2014 10:47:08 +0300 Subject: iwlwifi: mvm: several fixes in scan The firmware doesn't handle properly the fragmented scan. Stop using it. While at it change max_out_time and suspend_time units from usec to TUs as expected by firmware API. Signed-off-by: Alexander Bondar Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h | 8 ++-- drivers/net/wireless/iwlwifi/mvm/scan.c | 53 ++++++-------------------- 2 files changed, 16 insertions(+), 45 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h index 9426905de6b2..d73a89ecd78a 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h @@ -183,9 +183,9 @@ enum iwl_scan_type { * this number of packets were received (typically 1) * @passive2active: is auto switching from passive to active during scan allowed * @rxchain_sel_flags: RXON_RX_CHAIN_* - * @max_out_time: in usecs, max out of serving channel time + * @max_out_time: in TUs, max out of serving channel time * @suspend_time: how long to pause scan when returning to service channel: - * bits 0-19: beacon interal in usecs (suspend before executing) + * bits 0-19: beacon interal in TUs (suspend before executing) * bits 20-23: reserved * bits 24-31: number of beacons (suspend between channels) * @rxon_flags: RXON_FLG_* @@ -383,8 +383,8 @@ enum scan_framework_client { * @quiet_plcp_th: quiet channel num of packets threshold * @good_CRC_th: passive to active promotion threshold * @rx_chain: RXON rx chain. - * @max_out_time: max uSec to be out of assoceated channel - * @suspend_time: pause scan this long when returning to service channel + * @max_out_time: max TUs to be out of assoceated channel + * @suspend_time: pause scan this TUs when returning to service channel * @flags: RXON flags * @filter_flags: RXONfilter * @tx_cmd: tx command for active scan; for 2GHz and for 5GHz. diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index c91dc8498852..cba88a379fc8 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c @@ -277,51 +277,22 @@ static void iwl_mvm_scan_calc_params(struct iwl_mvm *mvm, IEEE80211_IFACE_ITER_NORMAL, iwl_mvm_scan_condition_iterator, &global_bound); - /* - * Under low latency traffic passive scan is fragmented meaning - * that dwell on a particular channel will be fragmented. Each fragment - * dwell time is 20ms and fragments period is 105ms. Skipping to next - * channel will be delayed by the same period - 105ms. So suspend_time - * parameter describing both fragments and channels skipping periods is - * set to 105ms. This value is chosen so that overall passive scan - * duration will not be too long. Max_out_time in this case is set to - * 70ms, so for active scanning operating channel will be left for 70ms - * while for passive still for 20ms (fragment dwell). - */ - if (global_bound) { - if (!iwl_mvm_low_latency(mvm)) { - params->suspend_time = ieee80211_tu_to_usec(100); - params->max_out_time = ieee80211_tu_to_usec(600); - } else { - params->suspend_time = ieee80211_tu_to_usec(105); - /* P2P doesn't support fragmented passive scan, so - * configure max_out_time to be at least longest dwell - * time for passive scan. - */ - if (vif->type == NL80211_IFTYPE_STATION && !vif->p2p) { - params->max_out_time = ieee80211_tu_to_usec(70); - params->passive_fragmented = true; - } else { - u32 passive_dwell; - /* - * Use band G so that passive channel dwell time - * will be assigned with maximum value. - */ - band = IEEE80211_BAND_2GHZ; - passive_dwell = iwl_mvm_get_passive_dwell(band); - params->max_out_time = - ieee80211_tu_to_usec(passive_dwell); - } - } + if (!global_bound) + goto not_bound; + + params->suspend_time = 100; + params->max_out_time = 600; + + if (iwl_mvm_low_latency(mvm)) { + params->suspend_time = 250; + params->max_out_time = 250; } +not_bound: + for (band = IEEE80211_BAND_2GHZ; band < IEEE80211_NUM_BANDS; band++) { - if (params->passive_fragmented) - params->dwell[band].passive = 20; - else - params->dwell[band].passive = - iwl_mvm_get_passive_dwell(band); + params->dwell[band].passive = iwl_mvm_get_passive_dwell(band); params->dwell[band].active = iwl_mvm_get_active_dwell(band, n_ssids); } -- cgit v1.2.3 From 04ebcb5405105d9b9bd9633d74e87e0979bddc55 Mon Sep 17 00:00:00 2001 From: Emilio López Date: Wed, 19 Mar 2014 15:19:31 -0300 Subject: ARM: sun7i: fix PLL4 clock and add PLL8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allwinner reworked the PLL4 clock in sun7i; so we need to change the compatible. Additionally, PLL8 is compatible with this new PLL4 implementation, so let's add a node for it as well. Signed-off-by: Emilio López Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun7i-a20.dtsi | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi index 32efc105df83..c4f665f1b793 100644 --- a/arch/arm/boot/dts/sun7i-a20.dtsi +++ b/arch/arm/boot/dts/sun7i-a20.dtsi @@ -87,7 +87,7 @@ pll4: clk@01c20018 { #clock-cells = <0>; - compatible = "allwinner,sun4i-a10-pll1-clk"; + compatible = "allwinner,sun7i-a20-pll4-clk"; reg = <0x01c20018 0x4>; clocks = <&osc24M>; clock-output-names = "pll4"; @@ -109,6 +109,14 @@ clock-output-names = "pll6_sata", "pll6_other", "pll6"; }; + pll8: clk@01c20040 { + #clock-cells = <0>; + compatible = "allwinner,sun7i-a20-pll4-clk"; + reg = <0x01c20040 0x4>; + clocks = <&osc24M>; + clock-output-names = "pll8"; + }; + cpu: cpu@01c20054 { #clock-cells = <0>; compatible = "allwinner,sun4i-a10-cpu-clk"; -- cgit v1.2.3 From 5a838c3b60e3a36ade764cf7751b8f17d7c9c2da Mon Sep 17 00:00:00 2001 From: Jianyu Zhan Date: Mon, 14 Apr 2014 13:47:40 +0800 Subject: percpu: make pcpu_alloc_chunk() use pcpu_mem_free() instead of kfree() pcpu_chunk_struct_size = sizeof(struct pcpu_chunk) + BITS_TO_LONGS(pcpu_unit_pages) * sizeof(unsigned long) It hardly could be ever bigger than PAGE_SIZE even for large-scale machine, but for consistency with its couterpart pcpu_mem_zalloc(), use pcpu_mem_free() instead. Commit b4916cb17c26 ("percpu: make pcpu_free_chunk() use pcpu_mem_free() instead of kfree()") addressed this problem, but missed this one. tj: commit message updated Signed-off-by: Jianyu Zhan Signed-off-by: Tejun Heo Fixes: 099a19d91ca4 ("percpu: allow limited allocation before slab is online) Cc: stable@vger.kernel.org --- mm/percpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/percpu.c b/mm/percpu.c index 63e24fb4387b..2ddf9a990dbd 100644 --- a/mm/percpu.c +++ b/mm/percpu.c @@ -610,7 +610,7 @@ static struct pcpu_chunk *pcpu_alloc_chunk(void) chunk->map = pcpu_mem_zalloc(PCPU_DFL_MAP_ALLOC * sizeof(chunk->map[0])); if (!chunk->map) { - kfree(chunk); + pcpu_mem_free(chunk, pcpu_chunk_struct_size); return NULL; } -- cgit v1.2.3 From 1fd10f98d9abcde090b77cfa82c3f32f159e2d94 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Wed, 9 Apr 2014 12:42:35 -0300 Subject: [media] rtl28xxu: do not hard depend on staging SDR module RTL2832 SDR extension module is currently on staging. SDR module headers were included from staging causing direct dependency staging directory. As a solution, add needed headers to main driver. Motivation of that change comes from Luis / driver backports project. Reported-by: Luis R. Rodriguez Cc: backports@vger.kernel.org Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/Makefile | 1 - drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 21 ++++++++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/drivers/media/usb/dvb-usb-v2/Makefile b/drivers/media/usb/dvb-usb-v2/Makefile index 7407b8338ccf..bc38f03394cd 100644 --- a/drivers/media/usb/dvb-usb-v2/Makefile +++ b/drivers/media/usb/dvb-usb-v2/Makefile @@ -41,4 +41,3 @@ ccflags-y += -I$(srctree)/drivers/media/dvb-core ccflags-y += -I$(srctree)/drivers/media/dvb-frontends ccflags-y += -I$(srctree)/drivers/media/tuners ccflags-y += -I$(srctree)/drivers/media/common -ccflags-y += -I$(srctree)/drivers/staging/media/rtl2832u_sdr diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index 61d196e8b3ab..3a7a5a7f95a7 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -24,7 +24,6 @@ #include "rtl2830.h" #include "rtl2832.h" -#include "rtl2832_sdr.h" #include "qt1010.h" #include "mt2060.h" @@ -36,6 +35,26 @@ #include "tua9001.h" #include "r820t.h" +/* + * RTL2832_SDR module is in staging. That logic is added in order to avoid any + * hard dependency to drivers/staging/ directory as we want compile mainline + * driver even whole staging directory is missing. + */ +#include + +#if IS_ENABLED(CONFIG_DVB_RTL2832_SDR) +struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, const struct rtl2832_config *cfg, + struct v4l2_subdev *sd); +#else +static inline struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, const struct rtl2832_config *cfg, + struct v4l2_subdev *sd) +{ + return NULL; +} +#endif + static int rtl28xxu_disable_rc; module_param_named(disable_rc, rtl28xxu_disable_rc, int, 0644); MODULE_PARM_DESC(disable_rc, "disable RTL2832U remote controller"); -- cgit v1.2.3 From beab1b530efa46164fbec3dc9b779cc7739b4f2c Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Wed, 9 Apr 2014 18:08:37 -0300 Subject: [media] rtl28xxu: silence error log about disabled rtl2832_sdr module It printed a little bit too heavy looking error log "DVB: Unable to find symbol rtl2832_sdr_attach()" when staging module was disabled. Silence that error by introducing own version of dvb_attach() macro without the error logging. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index 3a7a5a7f95a7..dcbd392e6efc 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -55,6 +55,25 @@ static inline struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe, } #endif +#ifdef CONFIG_MEDIA_ATTACH +#define dvb_attach_sdr(FUNCTION, ARGS...) ({ \ + void *__r = NULL; \ + typeof(&FUNCTION) __a = symbol_request(FUNCTION); \ + if (__a) { \ + __r = (void *) __a(ARGS); \ + if (__r == NULL) \ + symbol_put(FUNCTION); \ + } \ + __r; \ +}) + +#else +#define dvb_attach_sdr(FUNCTION, ARGS...) ({ \ + FUNCTION(ARGS); \ +}) + +#endif + static int rtl28xxu_disable_rc; module_param_named(disable_rc, rtl28xxu_disable_rc, int, 0644); MODULE_PARM_DESC(disable_rc, "disable RTL2832U remote controller"); @@ -927,7 +946,7 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) adap->fe[0]->ops.tuner_ops.get_rf_strength; /* attach SDR */ - dvb_attach(rtl2832_sdr_attach, adap->fe[0], &d->i2c_adap, + dvb_attach_sdr(rtl2832_sdr_attach, adap->fe[0], &d->i2c_adap, &rtl28xxu_rtl2832_fc0012_config, NULL); break; case TUNER_RTL2832_FC0013: @@ -939,7 +958,7 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) adap->fe[0]->ops.tuner_ops.get_rf_strength; /* attach SDR */ - dvb_attach(rtl2832_sdr_attach, adap->fe[0], &d->i2c_adap, + dvb_attach_sdr(rtl2832_sdr_attach, adap->fe[0], &d->i2c_adap, &rtl28xxu_rtl2832_fc0013_config, NULL); break; case TUNER_RTL2832_E4000: { @@ -970,7 +989,7 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) i2c_set_adapdata(i2c_adap_internal, d); /* attach SDR */ - dvb_attach(rtl2832_sdr_attach, adap->fe[0], + dvb_attach_sdr(rtl2832_sdr_attach, adap->fe[0], i2c_adap_internal, &rtl28xxu_rtl2832_e4000_config, sd); } @@ -1001,7 +1020,7 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) adap->fe[0]->ops.tuner_ops.get_rf_strength; /* attach SDR */ - dvb_attach(rtl2832_sdr_attach, adap->fe[0], &d->i2c_adap, + dvb_attach_sdr(rtl2832_sdr_attach, adap->fe[0], &d->i2c_adap, &rtl28xxu_rtl2832_r820t_config, NULL); break; case TUNER_RTL2832_R828D: -- cgit v1.2.3 From 41f484d12c0105ce01ea79acdc094fff9124491b Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Tue, 8 Apr 2014 10:05:03 -0300 Subject: [media] s5c73m3: Add missing rename of v4l2_of_get_next_endpoint() function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes following build error: CC drivers/media/i2c/s5c73m3/s5c73m3-core.o CC drivers/md/dm-ioctl.o CC net/ipv4/inet_lro.o drivers/media/i2c/s5c73m3/s5c73m3-core.c: In function ‘s5c73m3_get_platform_data’: drivers/media/i2c/s5c73m3/s5c73m3-core.c:1619:2: error: implicit declaration of function ‘v4l2_of_get_next_endpoint’ [-Werror=implicit-function-declaration] drivers/media/i2c/s5c73m3/s5c73m3-core.c:1619:10: warning: assignment makes pointer from integer without a cast [enabled by default] Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/s5c73m3/s5c73m3-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-core.c b/drivers/media/i2c/s5c73m3/s5c73m3-core.c index a4459301b5f8..ee0f57e01b56 100644 --- a/drivers/media/i2c/s5c73m3/s5c73m3-core.c +++ b/drivers/media/i2c/s5c73m3/s5c73m3-core.c @@ -1616,7 +1616,7 @@ static int s5c73m3_get_platform_data(struct s5c73m3 *state) if (ret < 0) return -EINVAL; - node_ep = v4l2_of_get_next_endpoint(node, NULL); + node_ep = of_graph_get_next_endpoint(node, NULL); if (!node_ep) { dev_warn(dev, "no endpoint defined for node: %s\n", node->full_name); -- cgit v1.2.3 From e3fadbdf1cbac7164aaefae5fb331cba86255c46 Mon Sep 17 00:00:00 2001 From: Nicolas Dufresne Date: Tue, 25 Mar 2014 17:50:11 -0300 Subject: [media] s5p-fimc: Fix YUV422P depth All YUV 422 has 16bit per pixels. Signed-off-by: Nicolas Dufresne Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/exynos4-is/fimc-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/exynos4-is/fimc-core.c b/drivers/media/platform/exynos4-is/fimc-core.c index da2fc86cc524..25dbf5b05a96 100644 --- a/drivers/media/platform/exynos4-is/fimc-core.c +++ b/drivers/media/platform/exynos4-is/fimc-core.c @@ -122,7 +122,7 @@ static struct fimc_fmt fimc_formats[] = { }, { .name = "YUV 4:2:2 planar, Y/Cb/Cr", .fourcc = V4L2_PIX_FMT_YUV422P, - .depth = { 12 }, + .depth = { 16 }, .color = FIMC_FMT_YCBYCR422, .memplanes = 1, .colplanes = 3, -- cgit v1.2.3 From e6ba3db1049548df10f90234328441b2873a4bd3 Mon Sep 17 00:00:00 2001 From: "Lad, Prabhakar" Date: Sat, 22 Mar 2014 08:03:07 -0300 Subject: [media] media: davinci: vpif_capture: fix releasing of active buffers from commit-id: b3379c6201bb3555298cdbf0aa004af260f2a6a4 "vb2: only call start_streaming if sufficient buffers are queued" the vb2 framework warns on (WARN_ON()) if all the active buffers are not released when streaming is stopped, initially the vb2 silently released the buffer internally if the buffer was not released by the driver. Also this patch moves the disabling of interrupts from relase() callback to stop_streaming() callback as which needs to be done ideally. This patch fixes following issue: WARNING: CPU: 0 PID: 2049 at drivers/media/v4l2-core/videobuf2-core.c:2011 __vb2_queue_cancel+0x1a0/0x218() Modules linked in: CPU: 0 PID: 2049 Comm: vpif_capture Tainted: G W 3.14.0-rc5-00414-ged97a6f #89 [] (unwind_backtrace) from [] (show_stack+0x10/0x14) [] (show_stack) from [] (warn_slowpath_common+0x68/0x88) [] (warn_slowpath_common) from [] (warn_slowpath_null+0x1c/0x24) [] (warn_slowpath_null) from [] (__vb2_queue_cancel+0x1a0/0x218) [] (__vb2_queue_cancel) from [] (vb2_queue_release+0x14/0x24) [] (vb2_queue_release) from [] (vpif_release+0x60/0x230) [] (vpif_release) from [] (v4l2_release+0x34/0x74) [] (v4l2_release) from [] (__fput+0x80/0x224) [] (__fput) from [] (task_work_run+0xa0/0xd0) [] (task_work_run) from [] (do_exit+0x244/0x918) [] (do_exit) from [] (do_group_exit+0x48/0xdc) [] (do_group_exit) from [] (get_signal_to_deliver+0x2a0/0x5bc) [] (get_signal_to_deliver) from [] (do_signal+0x78/0x3a0) [] (do_signal) from [] (do_work_pending+0xa4/0xb4) [] (do_work_pending) from [] (work_pending+0xc/0x20) ---[ end trace 5faa75e8c2f8a6a1 ]--- ------------[ cut here ]------------ WARNING: CPU: 0 PID: 2049 at drivers/media/v4l2-core/videobuf2-core.c:1095 vb2_buffer_done+0x1e0/0x224() Modules linked in: CPU: 0 PID: 2049 Comm: vpif_capture Tainted: G W 3.14.0-rc5-00414-ged97a6f #89 [] (unwind_backtrace) from [] (show_stack+0x10/0x14) [] (show_stack) from [] (warn_slowpath_common+0x68/0x88) [] (warn_slowpath_common) from [] (warn_slowpath_null+0x1c/0x24) [] (warn_slowpath_null) from [] (vb2_buffer_done+0x1e0/0x224) [] (vb2_buffer_done) from [] (__vb2_queue_cancel+0x1d0/0x218) [] (__vb2_queue_cancel) from [] (vb2_queue_release+0x14/0x24) [] (vb2_queue_release) from [] (vpif_release+0x60/0x230) [] (vpif_release) from [] (v4l2_release+0x34/0x74) [] (v4l2_release) from [] (__fput+0x80/0x224) [] (__fput) from [] (task_work_run+0xa0/0xd0) [] (task_work_run) from [] (do_exit+0x244/0x918) [] (do_exit) from [] (do_group_exit+0x48/0xdc) [] (do_group_exit) from [] (get_signal_to_deliver+0x2a0/0x5bc) [] (get_signal_to_deliver) from [] (do_signal+0x78/0x3a0) [] (do_signal) from [] (do_work_pending+0xa4/0xb4) [] (do_work_pending) from [] (work_pending+0xc/0x20) ---[ end trace 5faa75e8c2f8a6a2 ]--- Signed-off-by: Lad, Prabhakar Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/davinci/vpif_capture.c | 34 ++++++++++++++++++--------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c index 756da78bac23..8dea0b84a3ad 100644 --- a/drivers/media/platform/davinci/vpif_capture.c +++ b/drivers/media/platform/davinci/vpif_capture.c @@ -358,8 +358,31 @@ static int vpif_stop_streaming(struct vb2_queue *vq) common = &ch->common[VPIF_VIDEO_INDEX]; + /* Disable channel as per its device type and channel id */ + if (VPIF_CHANNEL0_VIDEO == ch->channel_id) { + enable_channel0(0); + channel0_intr_enable(0); + } + if ((VPIF_CHANNEL1_VIDEO == ch->channel_id) || + (2 == common->started)) { + enable_channel1(0); + channel1_intr_enable(0); + } + common->started = 0; + /* release all active buffers */ spin_lock_irqsave(&common->irqlock, flags); + if (common->cur_frm == common->next_frm) { + vb2_buffer_done(&common->cur_frm->vb, VB2_BUF_STATE_ERROR); + } else { + if (common->cur_frm != NULL) + vb2_buffer_done(&common->cur_frm->vb, + VB2_BUF_STATE_ERROR); + if (common->next_frm != NULL) + vb2_buffer_done(&common->next_frm->vb, + VB2_BUF_STATE_ERROR); + } + while (!list_empty(&common->dma_queue)) { common->next_frm = list_entry(common->dma_queue.next, struct vpif_cap_buffer, list); @@ -933,17 +956,6 @@ static int vpif_release(struct file *filep) if (fh->io_allowed[VPIF_VIDEO_INDEX]) { /* Reset io_usrs member of channel object */ common->io_usrs = 0; - /* Disable channel as per its device type and channel id */ - if (VPIF_CHANNEL0_VIDEO == ch->channel_id) { - enable_channel0(0); - channel0_intr_enable(0); - } - if ((VPIF_CHANNEL1_VIDEO == ch->channel_id) || - (2 == common->started)) { - enable_channel1(0); - channel1_intr_enable(0); - } - common->started = 0; /* Free buffers allocated */ vb2_queue_release(&common->buffer_queue); vb2_dma_contig_cleanup_ctx(common->alloc_ctx); -- cgit v1.2.3 From 18c7adcf2c1abf7f554a52f57bee126995791748 Mon Sep 17 00:00:00 2001 From: "Lad, Prabhakar" Date: Sat, 22 Mar 2014 08:03:08 -0300 Subject: [media] media: davinci: vpif_display: fix releasing of active buffers from commit-id: b3379c6201bb3555298cdbf0aa004af260f2a6a4 "vb2: only call start_streaming if sufficient buffers are queued" the vb2 framework warns on (WARN_ON()) if all the active buffers are not released when streaming is stopped, initially the vb2 silently released the buffer internally if the buffer was not released by the driver. Also this patch moves the disabling of interrupts from relase() callback to stop_streaming() callback as which needs to be done ideally. This patch fixes following issue: WARNING: CPU: 0 PID: 2049 at drivers/media/v4l2-core/videobuf2-core.c:2011 __vb2_queue_cancel+0x1a0/0x218() Modules linked in: CPU: 0 PID: 2049 Comm: vpif_display Tainted: G W 3.14.0-rc5-00414-ged97a6f #89 [] (unwind_backtrace) from [] (show_stack+0x10/0x14) [] (show_stack) from [] (warn_slowpath_common+0x68/0x88) [] (warn_slowpath_common) from [] (warn_slowpath_null+0x1c/0x24) [] (warn_slowpath_null) from [] (__vb2_queue_cancel+0x1a0/0x218) [] (__vb2_queue_cancel) from [] (vb2_queue_release+0x14/0x24) [] (vb2_queue_release) from [] (vpif_release+0x60/0x230) [] (vpif_release) from [] (v4l2_release+0x34/0x74) [] (v4l2_release) from [] (__fput+0x80/0x224) [] (__fput) from [] (task_work_run+0xa0/0xd0) [] (task_work_run) from [] (do_exit+0x244/0x918) [] (do_exit) from [] (do_group_exit+0x48/0xdc) [] (do_group_exit) from [] (get_signal_to_deliver+0x2a0/0x5bc) [] (get_signal_to_deliver) from [] (do_signal+0x78/0x3a0) [] (do_signal) from [] (do_work_pending+0xa4/0xb4) [] (do_work_pending) from [] (work_pending+0xc/0x20) ---[ end trace 5faa75e8c2f8a6a1 ]--- ------------[ cut here ]------------ WARNING: CPU: 0 PID: 2049 at drivers/media/v4l2-core/videobuf2-core.c:1095 vb2_buffer_done+0x1e0/0x224() Modules linked in: CPU: 0 PID: 2049 Comm: vpif_display Tainted: G W 3.14.0-rc5-00414-ged97a6f #89 [] (unwind_backtrace) from [] (show_stack+0x10/0x14) [] (show_stack) from [] (warn_slowpath_common+0x68/0x88) [] (warn_slowpath_common) from [] (warn_slowpath_null+0x1c/0x24) [] (warn_slowpath_null) from [] (vb2_buffer_done+0x1e0/0x224) [] (vb2_buffer_done) from [] (__vb2_queue_cancel+0x1d0/0x218) [] (__vb2_queue_cancel) from [] (vb2_queue_release+0x14/0x24) [] (vb2_queue_release) from [] (vpif_release+0x60/0x230) [] (vpif_release) from [] (v4l2_release+0x34/0x74) [] (v4l2_release) from [] (__fput+0x80/0x224) [] (__fput) from [] (task_work_run+0xa0/0xd0) [] (task_work_run) from [] (do_exit+0x244/0x918) [] (do_exit) from [] (do_group_exit+0x48/0xdc) [] (do_group_exit) from [] (get_signal_to_deliver+0x2a0/0x5bc) [] (get_signal_to_deliver) from [] (do_signal+0x78/0x3a0) [] (do_signal) from [] (do_work_pending+0xa4/0xb4) [] (do_work_pending) from [] (work_pending+0xc/0x20) ---[ end trace 5faa75e8c2f8a6a2 ]--- Signed-off-by: Lad, Prabhakar Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/davinci/vpif_display.c | 35 ++++++++++++++++++--------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c index 0ac841e35aa4..aed41edd0501 100644 --- a/drivers/media/platform/davinci/vpif_display.c +++ b/drivers/media/platform/davinci/vpif_display.c @@ -320,8 +320,31 @@ static int vpif_stop_streaming(struct vb2_queue *vq) common = &ch->common[VPIF_VIDEO_INDEX]; + /* Disable channel */ + if (VPIF_CHANNEL2_VIDEO == ch->channel_id) { + enable_channel2(0); + channel2_intr_enable(0); + } + if ((VPIF_CHANNEL3_VIDEO == ch->channel_id) || + (2 == common->started)) { + enable_channel3(0); + channel3_intr_enable(0); + } + common->started = 0; + /* release all active buffers */ spin_lock_irqsave(&common->irqlock, flags); + if (common->cur_frm == common->next_frm) { + vb2_buffer_done(&common->cur_frm->vb, VB2_BUF_STATE_ERROR); + } else { + if (common->cur_frm != NULL) + vb2_buffer_done(&common->cur_frm->vb, + VB2_BUF_STATE_ERROR); + if (common->next_frm != NULL) + vb2_buffer_done(&common->next_frm->vb, + VB2_BUF_STATE_ERROR); + } + while (!list_empty(&common->dma_queue)) { common->next_frm = list_entry(common->dma_queue.next, struct vpif_disp_buffer, list); @@ -773,18 +796,6 @@ static int vpif_release(struct file *filep) if (fh->io_allowed[VPIF_VIDEO_INDEX]) { /* Reset io_usrs member of channel object */ common->io_usrs = 0; - /* Disable channel */ - if (VPIF_CHANNEL2_VIDEO == ch->channel_id) { - enable_channel2(0); - channel2_intr_enable(0); - } - if ((VPIF_CHANNEL3_VIDEO == ch->channel_id) || - (2 == common->started)) { - enable_channel3(0); - channel3_intr_enable(0); - } - common->started = 0; - /* Free buffers allocated */ vb2_queue_release(&common->buffer_queue); vb2_dma_contig_cleanup_ctx(common->alloc_ctx); -- cgit v1.2.3 From b699f09d0d003cc1622aec30d81f3158da6790aa Mon Sep 17 00:00:00 2001 From: "Lad, Prabhakar" Date: Sat, 22 Mar 2014 08:03:09 -0300 Subject: [media] media: davinci: vpbe_display: fix releasing of active buffers from commit-id: b3379c6201bb3555298cdbf0aa004af260f2a6a4 "vb2: only call start_streaming if sufficient buffers are queued" the vb2 framework warns on (WARN_ON()) if all the active buffers are not released when streaming is stopped, initially the vb2 silently released the buffer internally if the buffer was not released by the driver. This patch fixes following issue: WARNING: CPU: 0 PID: 2049 at drivers/media/v4l2-core/videobuf2-core.c:2011 __vb2_queue_cancel+0x1a0/0x218() Modules linked in: CPU: 0 PID: 2049 Comm: vpbe_display Tainted: G W 3.14.0-rc5-00414-ged97a6f #89 [] (unwind_backtrace) from [] (show_stack+0x10/0x14) [] (show_stack) from [] (warn_slowpath_common+0x68/0x88) [] (warn_slowpath_common) from [] (warn_slowpath_null+0x1c/0x24) [] (warn_slowpath_null) from [] (__vb2_queue_cancel+0x1a0/0x218) [] (__vb2_queue_cancel) from [] (vb2_queue_release+0x14/0x24) [] (vb2_queue_release) from [] (vpbe_display_release+0x60/0x230) [] (vpbe_display_release) from [] (v4l2_release+0x34/0x74) [] (v4l2_release) from [] (__fput+0x80/0x224) [] (__fput) from [] (task_work_run+0xa0/0xd0) [] (task_work_run) from [] (do_exit+0x244/0x918) [] (do_exit) from [] (do_group_exit+0x48/0xdc) [] (do_group_exit) from [] (get_signal_to_deliver+0x2a0/0x5bc) [] (get_signal_to_deliver) from [] (do_signal+0x78/0x3a0) [] (do_signal) from [] (do_work_pending+0xa4/0xb4) [] (do_work_pending) from [] (work_pending+0xc/0x20) ---[ end trace 5faa75e8c2f8a6a1 ]--- ------------[ cut here ]------------ WARNING: CPU: 0 PID: 2049 at drivers/media/v4l2-core/videobuf2-core.c:1095 vb2_buffer_done+0x1e0/0x224() Modules linked in: CPU: 0 PID: 2049 Comm: vpbe_display Tainted: G W 3.14.0-rc5-00414-ged97a6f #89 [] (unwind_backtrace) from [] (show_stack+0x10/0x14) [] (show_stack) from [] (warn_slowpath_common+0x68/0x88) [] (warn_slowpath_common) from [] (warn_slowpath_null+0x1c/0x24) [] (warn_slowpath_null) from [] (vb2_buffer_done+0x1e0/0x224) [] (vb2_buffer_done) from [] (__vb2_queue_cancel+0x1d0/0x218) [] (__vb2_queue_cancel) from [] (vb2_queue_release+0x14/0x24) [] (vb2_queue_release) from [] (vpbe_display_release+0x60/0x230) [] (vpbe_display_release) from [] (v4l2_release+0x34/0x74) [] (v4l2_release) from [] (__fput+0x80/0x224) [] (__fput) from [] (task_work_run+0xa0/0xd0) [] (task_work_run) from [] (do_exit+0x244/0x918) [] (do_exit) from [] (do_group_exit+0x48/0xdc) [] (do_group_exit) from [] (get_signal_to_deliver+0x2a0/0x5bc) [] (get_signal_to_deliver) from [] (do_signal+0x78/0x3a0) [] (do_signal) from [] (do_work_pending+0xa4/0xb4) [] (do_work_pending) from [] (work_pending+0xc/0x20) ---[ end trace 5faa75e8c2f8a6a2 ]--- Signed-off-by: Lad, Prabhakar Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/davinci/vpbe_display.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/davinci/vpbe_display.c b/drivers/media/platform/davinci/vpbe_display.c index b4f12d00be05..656708252962 100644 --- a/drivers/media/platform/davinci/vpbe_display.c +++ b/drivers/media/platform/davinci/vpbe_display.c @@ -372,18 +372,32 @@ static int vpbe_stop_streaming(struct vb2_queue *vq) { struct vpbe_fh *fh = vb2_get_drv_priv(vq); struct vpbe_layer *layer = fh->layer; + struct vpbe_display *disp = fh->disp_dev; + unsigned long flags; if (!vb2_is_streaming(vq)) return 0; /* release all active buffers */ + spin_lock_irqsave(&disp->dma_queue_lock, flags); + if (layer->cur_frm == layer->next_frm) { + vb2_buffer_done(&layer->cur_frm->vb, VB2_BUF_STATE_ERROR); + } else { + if (layer->cur_frm != NULL) + vb2_buffer_done(&layer->cur_frm->vb, + VB2_BUF_STATE_ERROR); + if (layer->next_frm != NULL) + vb2_buffer_done(&layer->next_frm->vb, + VB2_BUF_STATE_ERROR); + } + while (!list_empty(&layer->dma_queue)) { layer->next_frm = list_entry(layer->dma_queue.next, struct vpbe_disp_buffer, list); list_del(&layer->next_frm->list); vb2_buffer_done(&layer->next_frm->vb, VB2_BUF_STATE_ERROR); } - + spin_unlock_irqrestore(&disp->dma_queue_lock, flags); return 0; } -- cgit v1.2.3 From d891ae5ef1efda590569b4483664c64b4aca4a4d Mon Sep 17 00:00:00 2001 From: "Lad, Prabhakar" Date: Sun, 23 Mar 2014 02:16:46 -0300 Subject: [media] staging: media: davinci: vpfe: make sure all the buffers are released from commit-id: b3379c6201bb3555298cdbf0aa004af260f2a6a4 "vb2: only call start_streaming if sufficient buffers are queued" the vb2 framework warns on (WARN_ON()) if all the active buffers are not released when streaming is stopped, initially the vb2 silently released the buffer internally if the buffer was not released by the driver. This patch fixes following issue: WARNING: CPU: 0 PID: 2049 at drivers/media/v4l2-core/videobuf2-core.c:2011 __vb2_queue_cancel+0x1a0/0x218() Modules linked in: CPU: 0 PID: 2049 Comm: vpfe_video Tainted: G W 3.14.0-rc5-00414-ged97a6f #89 [] (unwind_backtrace) from [] (show_stack+0x10/0x14) [] (show_stack) from [] (warn_slowpath_common+0x68/0x88) [] (warn_slowpath_common) from [] (warn_slowpath_null+0x1c/0x24) [] (warn_slowpath_null) from [] (__vb2_queue_cancel+0x1a0/0x218) [] (__vb2_queue_cancel) from [] (vb2_queue_release+0x14/0x24) [] (vb2_queue_release) from [] (vpfe_release+0x60/0x230) [] (vpfe_release) from [] (v4l2_release+0x34/0x74) [] (v4l2_release) from [] (__fput+0x80/0x224) [] (__fput) from [] (task_work_run+0xa0/0xd0) [] (task_work_run) from [] (do_exit+0x244/0x918) [] (do_exit) from [] (do_group_exit+0x48/0xdc) [] (do_group_exit) from [] (get_signal_to_deliver+0x2a0/0x5bc) [] (get_signal_to_deliver) from [] (do_signal+0x78/0x3a0) [] (do_signal) from [] (do_work_pending+0xa4/0xb4) [] (do_work_pending) from [] (work_pending+0xc/0x20) ---[ end trace 5faa75e8c2f8a6a1 ]--- ------------[ cut here ]------------ WARNING: CPU: 0 PID: 2049 at drivers/media/v4l2-core/videobuf2-core.c:1095 vb2_buffer_done+0x1e0/0x224() Modules linked in: CPU: 0 PID: 2049 Comm: vpfe_video Tainted: G W 3.14.0-rc5-00414-ged97a6f #89 [] (unwind_backtrace) from [] (show_stack+0x10/0x14) [] (show_stack) from [] (warn_slowpath_common+0x68/0x88) [] (warn_slowpath_common) from [] (warn_slowpath_null+0x1c/0x24) [] (warn_slowpath_null) from [] (vb2_buffer_done+0x1e0/0x224) [] (vb2_buffer_done) from [] (__vb2_queue_cancel+0x1d0/0x218) [] (__vb2_queue_cancel) from [] (vb2_queue_release+0x14/0x24) [] (vb2_queue_release) from [] (vpfe_release+0x60/0x230) [] (vpfe_release) from [] (v4l2_release+0x34/0x74) [] (v4l2_release) from [] (__fput+0x80/0x224) [] (__fput) from [] (task_work_run+0xa0/0xd0) [] (task_work_run) from [] (do_exit+0x244/0x918) [] (do_exit) from [] (do_group_exit+0x48/0xdc) [] (do_group_exit) from [] (get_signal_to_deliver+0x2a0/0x5bc) [] (get_signal_to_deliver) from [] (do_signal+0x78/0x3a0) [] (do_signal) from [] (do_work_pending+0xa4/0xb4) [] (do_work_pending) from [] (work_pending+0xc/0x20) ---[ end trace 5faa75e8c2f8a6a2 ]--- Signed-off-by: Lad, Prabhakar Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/davinci_vpfe/vpfe_video.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/staging/media/davinci_vpfe/vpfe_video.c b/drivers/staging/media/davinci_vpfe/vpfe_video.c index 8c101cbbee97..acc8184c46cd 100644 --- a/drivers/staging/media/davinci_vpfe/vpfe_video.c +++ b/drivers/staging/media/davinci_vpfe/vpfe_video.c @@ -1247,9 +1247,18 @@ static int vpfe_stop_streaming(struct vb2_queue *vq) struct vpfe_fh *fh = vb2_get_drv_priv(vq); struct vpfe_video_device *video = fh->video; - if (!vb2_is_streaming(vq)) - return 0; /* release all active buffers */ + if (video->cur_frm == video->next_frm) { + vb2_buffer_done(&video->cur_frm->vb, VB2_BUF_STATE_ERROR); + } else { + if (video->cur_frm != NULL) + vb2_buffer_done(&video->cur_frm->vb, + VB2_BUF_STATE_ERROR); + if (video->next_frm != NULL) + vb2_buffer_done(&video->next_frm->vb, + VB2_BUF_STATE_ERROR); + } + while (!list_empty(&video->dma_queue)) { video->next_frm = list_entry(video->dma_queue.next, struct vpfe_cap_buffer, list); -- cgit v1.2.3 From c1d1e40b8bbd712d6a8c74d8278178c8448b7abc Mon Sep 17 00:00:00 2001 From: "Lad, Prabhakar" Date: Sun, 23 Mar 2014 02:44:11 -0300 Subject: [media] media: davinci: vpfe: make sure all the buffers unmapped and released this patch makes sure that it terminates if any IO in progress and also makes sure that all the buffers are unmapped. It was observed that with several runs of application the application sometimes failed to allocate memory, This patch makes sure it all the buffers are released. Using kmemleak it was found that buffer were not released, this patch fixes following issue, echo scan > /sys/kernel/debug/kmemleak Kernel message reads: memleak: 3 new suspected memory leaks (see /sys/kernel/debug/kmemleak) Then, cat /sys/kernel/debug/kmemleak unreferenced object 0xc564a480 (size 192): comm "mttest", pid 764, jiffies 4294945878 (age 487.160s) hex dump (first 32 bytes): 00 00 00 00 28 07 07 20 d0 02 00 00 e0 01 00 00 ....(.. ........ 00 00 00 00 00 64 05 00 01 00 00 00 01 00 00 00 .....d.......... backtrace: [] create_object+0x10c/0x28c [] kmemleak_alloc+0x3c/0x70 [] __kmalloc+0x11c/0x1d4 [] __videobuf_alloc+0x1c/0x3c [] videobuf_alloc_vb+0x38/0x80 [] __videobuf_mmap_setup+0x9c/0x108 [] videobuf_reqbufs.part.10+0x12c/0x1bc [] videobuf_reqbufs+0x6c/0x8c [] vpfe_reqbufs+0xcc/0x130 [] v4l_reqbufs+0x50/0x54 [] __video_do_ioctl+0x260/0x2c4 [] video_usercopy+0xf0/0x310 [] video_ioctl2+0x14/0x1c [] v4l2_ioctl+0x104/0x14c [] do_vfs_ioctl+0x80/0x2d0 [] SyS_ioctl+0x44/0x64 unreferenced object 0xc564ac00 (size 192): comm "mttest", pid 764, jiffies 4294945878 (age 487.160s) hex dump (first 32 bytes): 01 00 00 00 28 07 07 20 d0 02 00 00 e0 01 00 00 ....(.. ........ 00 00 00 00 00 64 05 00 01 00 00 00 01 00 00 00 .....d.......... backtrace: [] create_object+0x10c/0x28c [] kmemleak_alloc+0x3c/0x70 [] __kmalloc+0x11c/0x1d4 [] __videobuf_alloc+0x1c/0x3c [] videobuf_alloc_vb+0x38/0x80 [] __videobuf_mmap_setup+0x9c/0x108 [] videobuf_reqbufs.part.10+0x12c/0x1bc [] videobuf_reqbufs+0x6c/0x8c [] vpfe_reqbufs+0xcc/0x130 [] v4l_reqbufs+0x50/0x54 [] __video_do_ioctl+0x260/0x2c4 [] video_usercopy+0xf0/0x310 [] video_ioctl2+0x14/0x1c [] v4l2_ioctl+0x104/0x14c [] do_vfs_ioctl+0x80/0x2d0 [] SyS_ioctl+0x44/0x64 unreferenced object 0xc564a180 (size 192): comm "mttest", pid 764, jiffies 4294945880 (age 487.140s) hex dump (first 32 bytes): 02 00 00 00 28 07 07 20 d0 02 00 00 e0 01 00 00 ....(.. ........ 00 00 00 00 00 64 05 00 01 00 00 00 01 00 00 00 .....d.......... backtrace: [] create_object+0x10c/0x28c [] kmemleak_alloc+0x3c/0x70 [] __kmalloc+0x11c/0x1d4 [] __videobuf_alloc+0x1c/0x3c [] videobuf_alloc_vb+0x38/0x80 [] __videobuf_mmap_setup+0x9c/0x108 [] videobuf_reqbufs.part.10+0x12c/0x1bc [] videobuf_reqbufs+0x6c/0x8c [] vpfe_reqbufs+0xcc/0x130 [] v4l_reqbufs+0x50/0x54 [] __video_do_ioctl+0x260/0x2c4 [] video_usercopy+0xf0/0x310 [] video_ioctl2+0x14/0x1c [] v4l2_ioctl+0x104/0x14c [] do_vfs_ioctl+0x80/0x2d0 [] SyS_ioctl+0x44/0x64 Reported-by: Jimmy Ho Signed-off-by: Lad, Prabhakar Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/davinci/vpfe_capture.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/platform/davinci/vpfe_capture.c b/drivers/media/platform/davinci/vpfe_capture.c index d762246eabf5..0379cb9f9a9c 100644 --- a/drivers/media/platform/davinci/vpfe_capture.c +++ b/drivers/media/platform/davinci/vpfe_capture.c @@ -734,6 +734,8 @@ static int vpfe_release(struct file *file) } vpfe_dev->io_usrs = 0; vpfe_dev->numbuffers = config_params.numbuffers; + videobuf_stop(&vpfe_dev->buffer_queue); + videobuf_mmap_free(&vpfe_dev->buffer_queue); } /* Decrement device usrs counter */ -- cgit v1.2.3 From 877ed143065c3b823cfe54b5a695c6be3659e445 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Fri, 11 Apr 2014 04:15:32 -0300 Subject: [media] Prefer gspca_sonixb over sn9c102 for all devices The sn9c102 driver is deprecated. It was moved to staging in anticipation of its removal in a future kernel version. However, USB devices 0C45:6024 and 0C45:6025 are still handled by sn9c102 when both sn9c102 and gspca_sonixb are enabled. We must migrate all the users of these devices to the gspca_sonixb driver now, so that it gets sufficient testing before the sn9c102 driver is finally phased out. Signed-off-by: Jean Delvare Acked-by: Greg Kroah-Hartman Acked-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/gspca/sonixb.c | 2 -- drivers/staging/media/sn9c102/sn9c102_devtable.h | 2 -- 2 files changed, 4 deletions(-) diff --git a/drivers/media/usb/gspca/sonixb.c b/drivers/media/usb/gspca/sonixb.c index 7277dbd2afcd..ecbcb39feb71 100644 --- a/drivers/media/usb/gspca/sonixb.c +++ b/drivers/media/usb/gspca/sonixb.c @@ -1430,10 +1430,8 @@ static const struct usb_device_id device_table[] = { {USB_DEVICE(0x0c45, 0x600d), SB(PAS106, 101)}, {USB_DEVICE(0x0c45, 0x6011), SB(OV6650, 101)}, {USB_DEVICE(0x0c45, 0x6019), SB(OV7630, 101)}, -#if !IS_ENABLED(CONFIG_USB_SN9C102) {USB_DEVICE(0x0c45, 0x6024), SB(TAS5130CXX, 102)}, {USB_DEVICE(0x0c45, 0x6025), SB(TAS5130CXX, 102)}, -#endif {USB_DEVICE(0x0c45, 0x6027), SB(OV7630, 101)}, /* Genius Eye 310 */ {USB_DEVICE(0x0c45, 0x6028), SB(PAS202, 102)}, {USB_DEVICE(0x0c45, 0x6029), SB(PAS106, 102)}, diff --git a/drivers/staging/media/sn9c102/sn9c102_devtable.h b/drivers/staging/media/sn9c102/sn9c102_devtable.h index b3d2cc729657..4ba569258498 100644 --- a/drivers/staging/media/sn9c102/sn9c102_devtable.h +++ b/drivers/staging/media/sn9c102/sn9c102_devtable.h @@ -48,10 +48,8 @@ static const struct usb_device_id sn9c102_id_table[] = { { SN9C102_USB_DEVICE(0x0c45, 0x600d, BRIDGE_SN9C102), }, /* { SN9C102_USB_DEVICE(0x0c45, 0x6011, BRIDGE_SN9C102), }, OV6650 */ { SN9C102_USB_DEVICE(0x0c45, 0x6019, BRIDGE_SN9C102), }, -#endif { SN9C102_USB_DEVICE(0x0c45, 0x6024, BRIDGE_SN9C102), }, { SN9C102_USB_DEVICE(0x0c45, 0x6025, BRIDGE_SN9C102), }, -#if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE { SN9C102_USB_DEVICE(0x0c45, 0x6028, BRIDGE_SN9C102), }, { SN9C102_USB_DEVICE(0x0c45, 0x6029, BRIDGE_SN9C102), }, { SN9C102_USB_DEVICE(0x0c45, 0x602a, BRIDGE_SN9C102), }, -- cgit v1.2.3 From a32452366b7250c42e96a18ffc3ad8db9e0ca3c2 Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Wed, 16 Apr 2014 09:01:03 +0200 Subject: vti4: Don't count header length twice. We currently count the size of LL_MAX_HEADER and struct iphdr twice for vti4 devices, this leads to a wrong device mtu. The size of LL_MAX_HEADER and struct iphdr is already counted in ip_tunnel_bind_dev(), so don't do it again in vti_tunnel_init(). Fixes: b9959fd3 ("vti: switch to new ip tunnel code") Signed-off-by: Steffen Klassert --- net/ipv4/ip_vti.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c index 687ddef4e574..cd62596e9a87 100644 --- a/net/ipv4/ip_vti.c +++ b/net/ipv4/ip_vti.c @@ -349,7 +349,6 @@ static int vti_tunnel_init(struct net_device *dev) memcpy(dev->broadcast, &iph->daddr, 4); dev->type = ARPHRD_TUNNEL; - dev->hard_header_len = LL_MAX_HEADER + sizeof(struct iphdr); dev->mtu = ETH_DATA_LEN; dev->flags = IFF_NOARP; dev->iflink = 0; -- cgit v1.2.3 From 77f300b198f93328c26191b52655ce1b62e202cf Mon Sep 17 00:00:00 2001 From: Daeseok Youn Date: Wed, 16 Apr 2014 14:32:29 +0900 Subject: workqueue: fix bugs in wq_update_unbound_numa() failure path wq_update_unbound_numa() failure path has the following two bugs. - alloc_unbound_pwq() is called without holding wq->mutex; however, if the allocation fails, it jumps to out_unlock which tries to unlock wq->mutex. - The function should switch to dfl_pwq on failure but didn't do so after alloc_unbound_pwq() failure. Fix it by regrabbing wq->mutex and jumping to use_dfl_pwq on alloc_unbound_pwq() failure. Signed-off-by: Daeseok Youn Acked-by: Lai Jiangshan Signed-off-by: Tejun Heo Cc: stable@vger.kernel.org Fixes: 4c16bd327c74 ("workqueue: implement NUMA affinity for unbound workqueues") --- kernel/workqueue.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 0ee63af30bd1..3150b217c936 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -4100,7 +4100,8 @@ static void wq_update_unbound_numa(struct workqueue_struct *wq, int cpu, if (!pwq) { pr_warning("workqueue: allocation failed while updating NUMA affinity of \"%s\"\n", wq->name); - goto out_unlock; + mutex_lock(&wq->mutex); + goto use_dfl_pwq; } /* -- cgit v1.2.3 From 8845cc6415ec28ef8d57b3fb81c75ef9bce69c5f Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Thu, 10 Apr 2014 21:18:16 -0300 Subject: [media] fc2580: fix tuning failure on 32-bit arch There was some frequency calculation overflows which caused tuning failure on 32-bit architecture. Use 64-bit numbers where needed in order to avoid calculation overflows. Thanks for the Finnish person, who asked remain anonymous, reporting, testing and suggesting the fix. Cc: Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/tuners/fc2580.c | 6 +++--- drivers/media/tuners/fc2580_priv.h | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/media/tuners/fc2580.c b/drivers/media/tuners/fc2580.c index 3aecaf465094..f0c9c42867de 100644 --- a/drivers/media/tuners/fc2580.c +++ b/drivers/media/tuners/fc2580.c @@ -195,7 +195,7 @@ static int fc2580_set_params(struct dvb_frontend *fe) f_ref = 2UL * priv->cfg->clock / r_val; n_val = div_u64_rem(f_vco, f_ref, &k_val); - k_val_reg = 1UL * k_val * (1 << 20) / f_ref; + k_val_reg = div_u64(1ULL * k_val * (1 << 20), f_ref); ret = fc2580_wr_reg(priv, 0x18, r18_val | ((k_val_reg >> 16) & 0xff)); if (ret < 0) @@ -348,8 +348,8 @@ static int fc2580_set_params(struct dvb_frontend *fe) if (ret < 0) goto err; - ret = fc2580_wr_reg(priv, 0x37, 1UL * priv->cfg->clock * \ - fc2580_if_filter_lut[i].mul / 1000000000); + ret = fc2580_wr_reg(priv, 0x37, div_u64(1ULL * priv->cfg->clock * + fc2580_if_filter_lut[i].mul, 1000000000)); if (ret < 0) goto err; diff --git a/drivers/media/tuners/fc2580_priv.h b/drivers/media/tuners/fc2580_priv.h index be38a9e637e0..646c99452136 100644 --- a/drivers/media/tuners/fc2580_priv.h +++ b/drivers/media/tuners/fc2580_priv.h @@ -22,6 +22,7 @@ #define FC2580_PRIV_H #include "fc2580.h" +#include struct fc2580_reg_val { u8 reg; -- cgit v1.2.3 From ce965c3d2e68c5325dd5624eb101d70423022fef Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Mon, 14 Apr 2014 17:29:18 +0200 Subject: memory: mvebu-devbus: fix the conversion of the bus width According to the Armada 370 and Armada XP datasheets, the part of the Device Bus register that configure the bus width should contain 0 for a 8 bits bus width, and 1 for a 16 bits bus width (other values are unsupported/reserved). However, the current conversion done in the driver to convert from a bus width in bits to the value expected by the register leads to setting the register to 1 for a 8 bits bus, and 2 for a 16 bits bus. This mistake was compensated by a mistake in the existing Device Tree files for Armada 370/XP platforms: they were declaring a 8 bits bus width, while the hardware in fact uses a 16 bits bus width. This commit fixes that by adjusting the conversion logic. This patch fixes a bug that was introduced in 3edad321b1bd2e6c8b5f38146c115c8982438f06 ('drivers: memory: Introduce Marvell EBU Device Bus driver'), which was merged in v3.11. Signed-off-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1397489361-5833-2-git-send-email-thomas.petazzoni@free-electrons.com Fixes: 3edad321b1bd ('drivers: memory: Introduce Marvell EBU Device Bus driver') Cc: stable@vger.kernel.org # v3.11+ Acked-by: Ezequiel Garcia Acked-by: Gregory CLEMENT Signed-off-by: Jason Cooper --- drivers/memory/mvebu-devbus.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/memory/mvebu-devbus.c b/drivers/memory/mvebu-devbus.c index 110c03627051..b59a17fb7c3e 100644 --- a/drivers/memory/mvebu-devbus.c +++ b/drivers/memory/mvebu-devbus.c @@ -108,8 +108,19 @@ static int devbus_set_timing_params(struct devbus *devbus, node->full_name); return err; } - /* Convert bit width to byte width */ - r.bus_width /= 8; + + /* + * The bus width is encoded into the register as 0 for 8 bits, + * and 1 for 16 bits, so we do the necessary conversion here. + */ + if (r.bus_width == 8) + r.bus_width = 0; + else if (r.bus_width == 16) + r.bus_width = 1; + else { + dev_err(devbus->dev, "invalid bus width %d\n", r.bus_width); + return -EINVAL; + } err = get_timing_param_ps(devbus, node, "devbus,badr-skew-ps", &r.badr_skew); -- cgit v1.2.3 From 1cc9d48145b81e307fab94a5cf6ee66ec2f0de60 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Sun, 13 Apr 2014 16:39:38 +0200 Subject: ARM: orion5x: fix target ID for crypto SRAM window In commit 4ca2c04085a1caa903e92a5fc0da25362150aac2 ('ARM: orion5x: Move to ID based window creation'), the mach-orion5x code was changed to use the new mvebu-mbus API. However, in the process, a mistake was made on the crypto SRAM window target ID: it should have been 0x9 (verified in the datasheet) and not 0x0. Signed-off-by: Thomas Petazzoni Acked-by: Sebastian Hesselbarth Link: https://lkml.kernel.org/r/1397400006-4315-2-git-send-email-thomas.petazzoni@free-electrons.com Fixes: 4ca2c04085a1 ('ARM: orion5x: Move to ID based window creation') Cc: stable@vger.kernel.org # v3.12+ Signed-off-by: Jason Cooper --- arch/arm/mach-orion5x/common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-orion5x/common.h b/arch/arm/mach-orion5x/common.h index f565f9944af2..7548db2bfb8a 100644 --- a/arch/arm/mach-orion5x/common.h +++ b/arch/arm/mach-orion5x/common.h @@ -21,7 +21,7 @@ struct mv_sata_platform_data; #define ORION_MBUS_DEVBUS_BOOT_ATTR 0x0f #define ORION_MBUS_DEVBUS_TARGET(cs) 0x01 #define ORION_MBUS_DEVBUS_ATTR(cs) (~(1 << cs)) -#define ORION_MBUS_SRAM_TARGET 0x00 +#define ORION_MBUS_SRAM_TARGET 0x09 #define ORION_MBUS_SRAM_ATTR 0x00 /* -- cgit v1.2.3 From d0f02ce3b1685ef6ffe43692034599790f83e7ab Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 4 Apr 2014 15:55:13 +0200 Subject: clk: tegra: Fix PLLE programming PLLE has M, N and P divider shift and width parameters that differ from the defaults. Furthermore, when clearing the M, N and P divider fields the corresponding masks were never shifted, thereby clearing only the lowest bits of the register. This lead to a situation where the PLLE programming would only work if the register hadn't been touched before. Signed-off-by: Thierry Reding Acked-by: Stephen Warren --- drivers/clk/tegra/clk-pll.c | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c index 0d20241e0770..357911303315 100644 --- a/drivers/clk/tegra/clk-pll.c +++ b/drivers/clk/tegra/clk-pll.c @@ -58,9 +58,9 @@ #define PLLDU_LFCON_SET_DIVN 600 #define PLLE_BASE_DIVCML_SHIFT 24 -#define PLLE_BASE_DIVCML_WIDTH 4 +#define PLLE_BASE_DIVCML_MASK 0xf #define PLLE_BASE_DIVP_SHIFT 16 -#define PLLE_BASE_DIVP_WIDTH 7 +#define PLLE_BASE_DIVP_WIDTH 6 #define PLLE_BASE_DIVN_SHIFT 8 #define PLLE_BASE_DIVN_WIDTH 8 #define PLLE_BASE_DIVM_SHIFT 0 @@ -730,8 +730,10 @@ static int clk_plle_enable(struct clk_hw *hw) if (pll->params->flags & TEGRA_PLLE_CONFIGURE) { /* configure dividers */ val = pll_readl_base(pll); - val &= ~(divm_mask(pll) | divn_mask(pll) | divp_mask(pll)); - val &= ~(PLLE_BASE_DIVCML_WIDTH << PLLE_BASE_DIVCML_SHIFT); + val &= ~(divp_mask(pll) << PLLE_BASE_DIVP_SHIFT | + divn_mask(pll) << PLLE_BASE_DIVN_SHIFT | + divm_mask(pll) << PLLE_BASE_DIVM_SHIFT); + val &= ~(PLLE_BASE_DIVCML_MASK << PLLE_BASE_DIVCML_SHIFT); val |= sel.m << pll->params->div_nmp->divm_shift; val |= sel.n << pll->params->div_nmp->divn_shift; val |= sel.p << pll->params->div_nmp->divp_shift; @@ -745,6 +747,7 @@ static int clk_plle_enable(struct clk_hw *hw) pll_writel_misc(val, pll); val = readl(pll->clk_base + PLLE_SS_CTRL); + val &= ~PLLE_SS_COEFFICIENTS_MASK; val |= PLLE_SS_DISABLE; writel(val, pll->clk_base + PLLE_SS_CTRL); @@ -1292,8 +1295,10 @@ static int clk_plle_tegra114_enable(struct clk_hw *hw) pll_writel(val, PLLE_SS_CTRL, pll); val = pll_readl_base(pll); - val &= ~(divm_mask(pll) | divn_mask(pll) | divp_mask(pll)); - val &= ~(PLLE_BASE_DIVCML_WIDTH << PLLE_BASE_DIVCML_SHIFT); + val &= ~(divp_mask(pll) << PLLE_BASE_DIVP_SHIFT | + divn_mask(pll) << PLLE_BASE_DIVN_SHIFT | + divm_mask(pll) << PLLE_BASE_DIVM_SHIFT); + val &= ~(PLLE_BASE_DIVCML_MASK << PLLE_BASE_DIVCML_SHIFT); val |= sel.m << pll->params->div_nmp->divm_shift; val |= sel.n << pll->params->div_nmp->divn_shift; val |= sel.cpcon << PLLE_BASE_DIVCML_SHIFT; @@ -1410,6 +1415,15 @@ struct clk *tegra_clk_register_pll(const char *name, const char *parent_name, return clk; } +static struct div_nmp pll_e_nmp = { + .divn_shift = PLLE_BASE_DIVN_SHIFT, + .divn_width = PLLE_BASE_DIVN_WIDTH, + .divm_shift = PLLE_BASE_DIVM_SHIFT, + .divm_width = PLLE_BASE_DIVM_WIDTH, + .divp_shift = PLLE_BASE_DIVP_SHIFT, + .divp_width = PLLE_BASE_DIVP_WIDTH, +}; + struct clk *tegra_clk_register_plle(const char *name, const char *parent_name, void __iomem *clk_base, void __iomem *pmc, unsigned long flags, struct tegra_clk_pll_params *pll_params, @@ -1420,6 +1434,10 @@ struct clk *tegra_clk_register_plle(const char *name, const char *parent_name, pll_params->flags |= TEGRA_PLL_LOCK_MISC | TEGRA_PLL_BYPASS; pll_params->flags |= TEGRA_PLL_HAS_LOCK_ENABLE; + + if (!pll_params->div_nmp) + pll_params->div_nmp = &pll_e_nmp; + pll = _tegra_init_pll(clk_base, pmc, pll_params, lock); if (IS_ERR(pll)) return ERR_CAST(pll); -- cgit v1.2.3 From c61e4e75b95bda4c6fec134aa9f08b5629b532e6 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 4 Apr 2014 15:55:14 +0200 Subject: clk: tegra: Introduce divider mask and shift helpers Add div{m,n,p}_shift() and div{m,n,p}_mask_shifted() helpers to make the code that modifies the m-, n- and p-divider fields of PLLs shorter and easier to read. Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-pll.c | 44 ++++++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c index 357911303315..1187187a1cf2 100644 --- a/drivers/clk/tegra/clk-pll.c +++ b/drivers/clk/tegra/clk-pll.c @@ -183,6 +183,14 @@ #define divp_mask(p) (p->params->flags & TEGRA_PLLU ? PLLU_POST_DIVP_MASK :\ mask(p->params->div_nmp->divp_width)) +#define divm_shift(p) (p)->params->div_nmp->divm_shift +#define divn_shift(p) (p)->params->div_nmp->divn_shift +#define divp_shift(p) (p)->params->div_nmp->divp_shift + +#define divm_mask_shifted(p) (divm_mask(p) << divm_shift(p)) +#define divn_mask_shifted(p) (divn_mask(p) << divn_shift(p)) +#define divp_mask_shifted(p) (divp_mask(p) << divp_shift(p)) + #define divm_max(p) (divm_mask(p)) #define divn_max(p) (divn_mask(p)) #define divp_max(p) (1 << (divp_mask(p))) @@ -476,13 +484,12 @@ static void _update_pll_mnp(struct tegra_clk_pll *pll, } else { val = pll_readl_base(pll); - val &= ~((divm_mask(pll) << div_nmp->divm_shift) | - (divn_mask(pll) << div_nmp->divn_shift) | - (divp_mask(pll) << div_nmp->divp_shift)); + val &= ~(divm_mask_shifted(pll) | divn_mask_shifted(pll) | + divp_mask_shifted(pll)); - val |= ((cfg->m << div_nmp->divm_shift) | - (cfg->n << div_nmp->divn_shift) | - (cfg->p << div_nmp->divp_shift)); + val |= (cfg->m << divm_shift(pll)) | + (cfg->n << divn_shift(pll)) | + (cfg->p << divp_shift(pll)); pll_writel_base(val, pll); } @@ -730,13 +737,12 @@ static int clk_plle_enable(struct clk_hw *hw) if (pll->params->flags & TEGRA_PLLE_CONFIGURE) { /* configure dividers */ val = pll_readl_base(pll); - val &= ~(divp_mask(pll) << PLLE_BASE_DIVP_SHIFT | - divn_mask(pll) << PLLE_BASE_DIVN_SHIFT | - divm_mask(pll) << PLLE_BASE_DIVM_SHIFT); + val &= ~(divp_mask_shifted(pll) | divn_mask_shifted(pll) | + divm_mask_shifted(pll)); val &= ~(PLLE_BASE_DIVCML_MASK << PLLE_BASE_DIVCML_SHIFT); - val |= sel.m << pll->params->div_nmp->divm_shift; - val |= sel.n << pll->params->div_nmp->divn_shift; - val |= sel.p << pll->params->div_nmp->divp_shift; + val |= sel.m << divm_shift(pll); + val |= sel.n << divn_shift(pll); + val |= sel.p << divp_shift(pll); val |= sel.cpcon << PLLE_BASE_DIVCML_SHIFT; pll_writel_base(val, pll); } @@ -1295,12 +1301,11 @@ static int clk_plle_tegra114_enable(struct clk_hw *hw) pll_writel(val, PLLE_SS_CTRL, pll); val = pll_readl_base(pll); - val &= ~(divp_mask(pll) << PLLE_BASE_DIVP_SHIFT | - divn_mask(pll) << PLLE_BASE_DIVN_SHIFT | - divm_mask(pll) << PLLE_BASE_DIVM_SHIFT); + val &= ~(divp_mask_shifted(pll) | divn_mask_shifted(pll) | + divm_mask_shifted(pll)); val &= ~(PLLE_BASE_DIVCML_MASK << PLLE_BASE_DIVCML_SHIFT); - val |= sel.m << pll->params->div_nmp->divm_shift; - val |= sel.n << pll->params->div_nmp->divn_shift; + val |= sel.m << divm_shift(pll); + val |= sel.n << divn_shift(pll); val |= sel.cpcon << PLLE_BASE_DIVCML_SHIFT; pll_writel_base(val, pll); udelay(1); @@ -1575,9 +1580,8 @@ struct clk *tegra_clk_register_pllre(const char *name, const char *parent_name, int m; m = _pll_fixed_mdiv(pll_params, parent_rate); - val = m << PLL_BASE_DIVM_SHIFT; - val |= (pll_params->vco_min / parent_rate) - << PLL_BASE_DIVN_SHIFT; + val = m << divm_shift(pll); + val |= (pll_params->vco_min / parent_rate) << divn_shift(pll); pll_writel_base(val, pll); } -- cgit v1.2.3 From 4ccc402ece35695dd2884ec0b652d52ae0230f13 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 4 Apr 2014 15:55:15 +0200 Subject: clk: tegra: Fix enabling of PLLE When enabling the PLLE as its final step, clk_plle_enable() would accidentally OR in the value previously written to the PLLE_SS_CTRL register. Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-pll.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c index 1187187a1cf2..7a1b70dac824 100644 --- a/drivers/clk/tegra/clk-pll.c +++ b/drivers/clk/tegra/clk-pll.c @@ -757,7 +757,7 @@ static int clk_plle_enable(struct clk_hw *hw) val |= PLLE_SS_DISABLE; writel(val, pll->clk_base + PLLE_SS_CTRL); - val |= pll_readl_base(pll); + val = pll_readl_base(pll); val |= (PLL_BASE_BYPASS | PLL_BASE_ENABLE); pll_writel_base(val, pll); -- cgit v1.2.3 From e37a06f10994c2ba86f54d8f96734f2483a869b8 Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Thu, 17 Apr 2014 13:53:08 +0800 Subject: cgroup: fix the retry path of cgroup_mount() If we hit the retry path, we'll call parse_cgroupfs_options() again, but the string we pass to it has been modified by the previous call to this function. This bug can be observed by: # mount -t cgroup -o name=foo,cpuset xxx /mnt && umount /mnt && \ mount -t cgroup -o name=foo,cpuset xxx /mnt mount: wrong fs type, bad option, bad superblock on xxx, missing codepage or helper program, or other error ... The second mount passed "name=foo,cpuset" to the parser, and then it hit the retry path and call the parser again, but this time the string passed to the parser is "name=foo". To fix this, we avoid calling parse_cgroupfs_options() again in this case. Signed-off-by: Li Zefan Signed-off-by: Tejun Heo --- kernel/cgroup.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 9fcdaa705b6c..11a03d67635a 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -1495,7 +1495,7 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type, */ if (!use_task_css_set_links) cgroup_enable_task_cg_lists(); -retry: + mutex_lock(&cgroup_tree_mutex); mutex_lock(&cgroup_mutex); @@ -1503,7 +1503,7 @@ retry: ret = parse_cgroupfs_options(data, &opts); if (ret) goto out_unlock; - +retry: /* look for a matching existing root */ if (!opts.subsys_mask && !opts.none && !opts.name) { cgrp_dfl_root_visible = true; @@ -1562,9 +1562,9 @@ retry: if (!atomic_inc_not_zero(&root->cgrp.refcnt)) { mutex_unlock(&cgroup_mutex); mutex_unlock(&cgroup_tree_mutex); - kfree(opts.release_agent); - kfree(opts.name); msleep(10); + mutex_lock(&cgroup_tree_mutex); + mutex_lock(&cgroup_mutex); goto retry; } -- cgit v1.2.3 From 4d595b866d2c653dc90a492b9973a834eabfa354 Mon Sep 17 00:00:00 2001 From: Lai Jiangshan Date: Fri, 18 Apr 2014 11:04:16 -0400 Subject: workqueue: make rescuer_thread() empty wq->maydays list before exiting After a @pwq is scheduled for emergency execution, other workers may consume the affectd work items before the rescuer gets to them. This means that a workqueue many have pwqs queued on @wq->maydays list while not having any work item pending or in-flight. If destroy_workqueue() executes in such condition, the rescuer may exit without emptying @wq->maydays. This currently doesn't cause any actual harm. destroy_workqueue() can safely destroy all the involved data structures whether @wq->maydays is populated or not as nobody access the list once the rescuer exits. However, this is nasty and makes future development difficult. Let's update rescuer_thread() so that it empties @wq->maydays after seeing should_stop to guarantee that the list is empty on rescuer exit. tj: Updated comment and patch description. Signed-off-by: Lai Jiangshan Signed-off-by: Tejun Heo Cc: stable@vger.kernel.org # v3.10+ --- kernel/workqueue.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 3150b217c936..6ba0c6054224 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -2398,6 +2398,7 @@ static int rescuer_thread(void *__rescuer) struct worker *rescuer = __rescuer; struct workqueue_struct *wq = rescuer->rescue_wq; struct list_head *scheduled = &rescuer->scheduled; + bool should_stop; set_user_nice(current, RESCUER_NICE_LEVEL); @@ -2409,11 +2410,15 @@ static int rescuer_thread(void *__rescuer) repeat: set_current_state(TASK_INTERRUPTIBLE); - if (kthread_should_stop()) { - __set_current_state(TASK_RUNNING); - rescuer->task->flags &= ~PF_WQ_WORKER; - return 0; - } + /* + * By the time the rescuer is requested to stop, the workqueue + * shouldn't have any work pending, but @wq->maydays may still have + * pwq(s) queued. This can happen by non-rescuer workers consuming + * all the work items before the rescuer got to them. Go through + * @wq->maydays processing before acting on should_stop so that the + * list is always empty on exit. + */ + should_stop = kthread_should_stop(); /* see whether any pwq is asking for help */ spin_lock_irq(&wq_mayday_lock); @@ -2459,6 +2464,12 @@ repeat: spin_unlock_irq(&wq_mayday_lock); + if (should_stop) { + __set_current_state(TASK_RUNNING); + rescuer->task->flags &= ~PF_WQ_WORKER; + return 0; + } + /* rescuers should never participate in concurrency management */ WARN_ON_ONCE(!(rescuer->flags & WORKER_NOT_RUNNING)); schedule(); -- cgit v1.2.3 From 77668c8b559e4fe2acf2a0749c7c83cde49a5025 Mon Sep 17 00:00:00 2001 From: Lai Jiangshan Date: Fri, 18 Apr 2014 11:04:16 -0400 Subject: workqueue: fix a possible race condition between rescuer and pwq-release There is a race condition between rescuer_thread() and pwq_unbound_release_workfn(). Even after a pwq is scheduled for rescue, the associated work items may be consumed by any worker. If all of them are consumed before the rescuer gets to them and the pwq's base ref was put due to attribute change, the pwq may be released while still being linked on @wq->maydays list making the rescuer dereference already freed pwq later. Make send_mayday() pin the target pwq until the rescuer is done with it. tj: Updated comment and patch description. Signed-off-by: Lai Jiangshan Signed-off-by: Tejun Heo Cc: stable@vger.kernel.org # v3.10+ --- kernel/workqueue.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 6ba0c6054224..8edc87185427 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -1916,6 +1916,12 @@ static void send_mayday(struct work_struct *work) /* mayday mayday mayday */ if (list_empty(&pwq->mayday_node)) { + /* + * If @pwq is for an unbound wq, its base ref may be put at + * any time due to an attribute change. Pin @pwq until the + * rescuer is done with it. + */ + get_pwq(pwq); list_add_tail(&pwq->mayday_node, &wq->maydays); wake_up_process(wq->rescuer->task); } @@ -2449,6 +2455,12 @@ repeat: process_scheduled_works(rescuer); + /* + * Put the reference grabbed by send_mayday(). @pool won't + * go away while we're holding its lock. + */ + put_pwq(pwq); + /* * Leave this pool. If keep_working() is %true, notify a * regular worker; otherwise, we end up with 0 concurrency -- cgit v1.2.3 From 83596fbeb5d28e8cb8878786133945d4dc7c0090 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 14 Apr 2014 19:39:53 +0200 Subject: spi: core: Ignore unsupported Dual/Quad Transfer Mode bits The availability of SPI Dual or Quad Transfer Mode as indicated by the "spi-tx-bus-width" and "spi-rx-bus-width" properties in the device tree is a hardware property of the SPI master, SPI slave, and board wiring. Hence the SPI core should not reject an SPI slave because an SPI master driver doesn't (yet) support Dual or Quad Transfer Mode. Change the lack of Dual or Quad Transfer Mode support in the SPI master driver from an error condition to a warning condition, and ignore the unsupported mode bits, falling back to Single Transfer Mode, to avoid breakages when running old kernels with new device trees. Fixes: f477b7fb13df (spi: DUAL and QUAD support) Signed-off-by: Geert Uytterhoeven Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- drivers/spi/spi.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 4eb9bf02996c..1534fa1dac34 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1756,7 +1756,7 @@ EXPORT_SYMBOL_GPL(spi_busnum_to_master); */ int spi_setup(struct spi_device *spi) { - unsigned bad_bits; + unsigned bad_bits, ugly_bits; int status = 0; /* check mode to prevent that DUAL and QUAD set at the same time @@ -1776,6 +1776,15 @@ int spi_setup(struct spi_device *spi) * that aren't supported with their current master */ bad_bits = spi->mode & ~spi->master->mode_bits; + ugly_bits = bad_bits & + (SPI_TX_DUAL | SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD); + if (ugly_bits) { + dev_warn(&spi->dev, + "setup: ignoring unsupported mode bits %x\n", + ugly_bits); + spi->mode &= ~ugly_bits; + bad_bits &= ~ugly_bits; + } if (bad_bits) { dev_err(&spi->dev, "setup: unsupported mode bits %x\n", bad_bits); -- cgit v1.2.3 From d44db494a8d5aa2060240e7a770bbb8fefa2d2b1 Mon Sep 17 00:00:00 2001 From: Bo Shen Date: Tue, 1 Apr 2014 15:12:43 +0800 Subject: ARM: at91: fix spi cs on sama5d3 Xplained board The PD16 is the CS3 for SPI0 while not SPI1. Signed-off-by: Bo Shen Acked-by: Alexandre Belloni Signed-off-by: Nicolas Ferre --- arch/arm/boot/dts/at91-sama5d3_xplained.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/at91-sama5d3_xplained.dts b/arch/arm/boot/dts/at91-sama5d3_xplained.dts index ce1375595e5f..4537259ce529 100644 --- a/arch/arm/boot/dts/at91-sama5d3_xplained.dts +++ b/arch/arm/boot/dts/at91-sama5d3_xplained.dts @@ -34,7 +34,7 @@ }; spi0: spi@f0004000 { - cs-gpios = <&pioD 13 0>; + cs-gpios = <&pioD 13 0>, <0>, <0>, <&pioD 16 0>; status = "okay"; }; @@ -79,7 +79,7 @@ }; spi1: spi@f8008000 { - cs-gpios = <&pioC 25 0>, <0>, <0>, <&pioD 16 0>; + cs-gpios = <&pioC 25 0>; status = "okay"; }; -- cgit v1.2.3 From 35d35aae817706800a4913711d563a99e1dc380a Mon Sep 17 00:00:00 2001 From: Tushar Behera Date: Thu, 6 Mar 2014 11:34:43 +0530 Subject: dt-bindings: clock: Move at91.h to dt-bindigs/clock Most of the clock related dt-binding header files are located in dt-bindings/clock folder. It would be good to keep all the similar header files at a single location. Signed-off-by: Tushar Behera CC: Rob Landley CC: Andrew Victor CC: Jean-Christophe Plagniol-Villard Acked-by: Boris BREZILLON [nicolas.ferre@atmel.com: add new at91sam9261 & at91sam9rl] Signed-off-by: Nicolas Ferre --- .../devicetree/bindings/clock/at91-clock.txt | 2 +- arch/arm/boot/dts/at91sam9261.dtsi | 2 +- arch/arm/boot/dts/at91sam9rl.dtsi | 2 +- arch/arm/boot/dts/sama5d3.dtsi | 2 +- arch/arm/boot/dts/sama5d3_mci2.dtsi | 2 +- arch/arm/boot/dts/sama5d3_tcb1.dtsi | 2 +- arch/arm/boot/dts/sama5d3_uart.dtsi | 2 +- include/dt-bindings/clk/at91.h | 22 ---------------------- include/dt-bindings/clock/at91.h | 22 ++++++++++++++++++++++ 9 files changed, 29 insertions(+), 29 deletions(-) delete mode 100644 include/dt-bindings/clk/at91.h create mode 100644 include/dt-bindings/clock/at91.h diff --git a/Documentation/devicetree/bindings/clock/at91-clock.txt b/Documentation/devicetree/bindings/clock/at91-clock.txt index cd5e23912888..6794cdc96d8f 100644 --- a/Documentation/devicetree/bindings/clock/at91-clock.txt +++ b/Documentation/devicetree/bindings/clock/at91-clock.txt @@ -62,7 +62,7 @@ Required properties for PMC node: - interrupt-controller : tell that the PMC is an interrupt controller. - #interrupt-cells : must be set to 1. The first cell encodes the interrupt id, and reflect the bit position in the PMC_ER/DR/SR registers. - You can use the dt macros defined in dt-bindings/clk/at91.h. + You can use the dt macros defined in dt-bindings/clock/at91.h. 0 (AT91_PMC_MOSCS) -> main oscillator ready 1 (AT91_PMC_LOCKA) -> PLL A ready 2 (AT91_PMC_LOCKB) -> PLL B ready diff --git a/arch/arm/boot/dts/at91sam9261.dtsi b/arch/arm/boot/dts/at91sam9261.dtsi index e21dda0e8986..3be973e9889a 100644 --- a/arch/arm/boot/dts/at91sam9261.dtsi +++ b/arch/arm/boot/dts/at91sam9261.dtsi @@ -10,7 +10,7 @@ #include #include #include -#include +#include / { model = "Atmel AT91SAM9261 family SoC"; diff --git a/arch/arm/boot/dts/at91sam9rl.dtsi b/arch/arm/boot/dts/at91sam9rl.dtsi index 63e1784d272c..92a52faebef7 100644 --- a/arch/arm/boot/dts/at91sam9rl.dtsi +++ b/arch/arm/boot/dts/at91sam9rl.dtsi @@ -8,7 +8,7 @@ #include "skeleton.dtsi" #include -#include +#include #include #include diff --git a/arch/arm/boot/dts/sama5d3.dtsi b/arch/arm/boot/dts/sama5d3.dtsi index eabcfdbb403a..a106b0872910 100644 --- a/arch/arm/boot/dts/sama5d3.dtsi +++ b/arch/arm/boot/dts/sama5d3.dtsi @@ -13,7 +13,7 @@ #include #include #include -#include +#include / { model = "Atmel SAMA5D3 family SoC"; diff --git a/arch/arm/boot/dts/sama5d3_mci2.dtsi b/arch/arm/boot/dts/sama5d3_mci2.dtsi index b029fe7ef17a..1b02208ea6ff 100644 --- a/arch/arm/boot/dts/sama5d3_mci2.dtsi +++ b/arch/arm/boot/dts/sama5d3_mci2.dtsi @@ -9,7 +9,7 @@ #include #include -#include +#include / { ahb { diff --git a/arch/arm/boot/dts/sama5d3_tcb1.dtsi b/arch/arm/boot/dts/sama5d3_tcb1.dtsi index 382b04431f66..02848453ca0c 100644 --- a/arch/arm/boot/dts/sama5d3_tcb1.dtsi +++ b/arch/arm/boot/dts/sama5d3_tcb1.dtsi @@ -9,7 +9,7 @@ #include #include -#include +#include / { aliases { diff --git a/arch/arm/boot/dts/sama5d3_uart.dtsi b/arch/arm/boot/dts/sama5d3_uart.dtsi index a9fa75e41652..7a8d4c6115f7 100644 --- a/arch/arm/boot/dts/sama5d3_uart.dtsi +++ b/arch/arm/boot/dts/sama5d3_uart.dtsi @@ -9,7 +9,7 @@ #include #include -#include +#include / { aliases { diff --git a/include/dt-bindings/clk/at91.h b/include/dt-bindings/clk/at91.h deleted file mode 100644 index 0b4cb999a3f7..000000000000 --- a/include/dt-bindings/clk/at91.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * This header provides constants for AT91 pmc status. - * - * The constants defined in this header are being used in dts. - * - * Licensed under GPLv2 or later. - */ - -#ifndef _DT_BINDINGS_CLK_AT91_H -#define _DT_BINDINGS_CLK_AT91_H - -#define AT91_PMC_MOSCS 0 /* MOSCS Flag */ -#define AT91_PMC_LOCKA 1 /* PLLA Lock */ -#define AT91_PMC_LOCKB 2 /* PLLB Lock */ -#define AT91_PMC_MCKRDY 3 /* Master Clock */ -#define AT91_PMC_LOCKU 6 /* UPLL Lock */ -#define AT91_PMC_PCKRDY(id) (8 + (id)) /* Programmable Clock */ -#define AT91_PMC_MOSCSELS 16 /* Main Oscillator Selection */ -#define AT91_PMC_MOSCRCS 17 /* Main On-Chip RC */ -#define AT91_PMC_CFDEV 18 /* Clock Failure Detector Event */ - -#endif diff --git a/include/dt-bindings/clock/at91.h b/include/dt-bindings/clock/at91.h new file mode 100644 index 000000000000..0b4cb999a3f7 --- /dev/null +++ b/include/dt-bindings/clock/at91.h @@ -0,0 +1,22 @@ +/* + * This header provides constants for AT91 pmc status. + * + * The constants defined in this header are being used in dts. + * + * Licensed under GPLv2 or later. + */ + +#ifndef _DT_BINDINGS_CLK_AT91_H +#define _DT_BINDINGS_CLK_AT91_H + +#define AT91_PMC_MOSCS 0 /* MOSCS Flag */ +#define AT91_PMC_LOCKA 1 /* PLLA Lock */ +#define AT91_PMC_LOCKB 2 /* PLLB Lock */ +#define AT91_PMC_MCKRDY 3 /* Master Clock */ +#define AT91_PMC_LOCKU 6 /* UPLL Lock */ +#define AT91_PMC_PCKRDY(id) (8 + (id)) /* Programmable Clock */ +#define AT91_PMC_MOSCSELS 16 /* Main Oscillator Selection */ +#define AT91_PMC_MOSCRCS 17 /* Main On-Chip RC */ +#define AT91_PMC_CFDEV 18 /* Clock Failure Detector Event */ + +#endif -- cgit v1.2.3 From c509bdc20dd255842d4e9302aad12baa7d166911 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Mon, 7 Apr 2014 10:22:36 +0200 Subject: imx-drm: imx-drm-core: fix imx_drm_encoder_get_mux_id The decoder mux id is equal to the port id of the encoder's input port that is connected to the given crtc, not to the endpoint id (which is arbitrary and usually zero). Signed-off-by: Philipp Zabel Tested-by: Shawn Guo Signed-off-by: Russell King --- drivers/staging/imx-drm/imx-drm-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/imx-drm/imx-drm-core.c b/drivers/staging/imx-drm/imx-drm-core.c index 4144a75e5f71..bc7f8bd227c7 100644 --- a/drivers/staging/imx-drm/imx-drm-core.c +++ b/drivers/staging/imx-drm/imx-drm-core.c @@ -517,7 +517,7 @@ int imx_drm_encoder_get_mux_id(struct device_node *node, of_node_put(port); if (port == imx_crtc->port) { ret = of_graph_parse_endpoint(ep, &endpoint); - return ret ? ret : endpoint.id; + return ret ? ret : endpoint.port; } } while (ep); -- cgit v1.2.3 From 1c2366298b105824e68e790bff1106e2d4ee2a30 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Mon, 14 Apr 2014 10:02:26 +0800 Subject: imx-drm: imx-drm-core: skip components whose parent device is disabled In a board setup which disables LDB device node completely by changing status to 'disabled', and only enables HDMI device, we're running into the problem that imx-drm master never succeeds in binding, and hence HDMI does not come up either. &ldb { status = "disabled"; lvds-channel@1 { ... status = "okay"; }; }; The imx-drm-core should really skip the LVDS channels no matter what lvds-channel's status is, if LDB device is disabled. Let's consider such setup a misconfiguration, give a warning in there and not add the component. Signed-off-by: Shawn Guo Acked-by: Philipp Zabel Signed-off-by: Russell King --- drivers/staging/imx-drm/imx-drm-core.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/staging/imx-drm/imx-drm-core.c b/drivers/staging/imx-drm/imx-drm-core.c index bc7f8bd227c7..c270c9ae6d27 100644 --- a/drivers/staging/imx-drm/imx-drm-core.c +++ b/drivers/staging/imx-drm/imx-drm-core.c @@ -675,6 +675,11 @@ static int imx_drm_platform_probe(struct platform_device *pdev) if (!remote || !of_device_is_available(remote)) { of_node_put(remote); continue; + } else if (!of_device_is_available(remote->parent)) { + dev_warn(&pdev->dev, "parent device of %s is not available\n", + remote->full_name); + of_node_put(remote); + continue; } ret = imx_drm_add_component(&pdev->dev, remote); -- cgit v1.2.3 From 79d719749d23234e9b725098aa49133f3ef7299d Mon Sep 17 00:00:00 2001 From: Aristeu Rozanski Date: Mon, 21 Apr 2014 12:13:03 -0400 Subject: device_cgroup: rework device access check and exception checking Whenever a device file is opened and checked against current device cgroup rules, it uses the same function (may_access()) as when a new exception rule is added by writing devices.{allow,deny}. And in both cases, the algorithm is the same, doesn't matter the behavior. First problem is having device access to be considered the same as rule checking. Consider the following structure: A (default behavior: allow, exceptions disallow access) \ B (default behavior: allow, exceptions disallow access) A new exception is added to B by writing devices.deny: c 12:34 rw When checking if that exception is allowed in may_access(): if (dev_cgroup->behavior == DEVCG_DEFAULT_ALLOW) { if (behavior == DEVCG_DEFAULT_ALLOW) { /* the exception will deny access to certain devices */ return true; Which is ok, since B is not getting more privileges than A, it doesn't matter and the rule is accepted Now, consider it's a device file open check and the process belongs to cgroup B. The access will be generated as: behavior: allow exception: c 12:34 rw The very same chunk of code will allow it, even if there's an explicit exception telling to do otherwise. A simple test case: # mkdir new_group # cd new_group # echo $$ >tasks # echo "c 1:3 w" >devices.deny # echo >/dev/null # echo $? 0 This is a serious bug and was introduced on c39a2a3018f8 devcg: prepare may_access() for hierarchy support To solve this problem, the device file open function was split from the new exception check. Second problem is how exceptions are processed by may_access(). The first part of the said function tries to match fully with an existing exception: list_for_each_entry_rcu(ex, &dev_cgroup->exceptions, list) { if ((refex->type & DEV_BLOCK) && !(ex->type & DEV_BLOCK)) continue; if ((refex->type & DEV_CHAR) && !(ex->type & DEV_CHAR)) continue; if (ex->major != ~0 && ex->major != refex->major) continue; if (ex->minor != ~0 && ex->minor != refex->minor) continue; if (refex->access & (~ex->access)) continue; match = true; break; } That means the new exception should be contained into an existing one to be considered a match: New exception Existing match? notes b 12:34 rwm b 12:34 rwm yes b 12:34 r b *:34 rw yes b 12:34 rw b 12:34 w no extra "r" b *:34 rw b 12:34 rw no too broad "*" b *:34 rw b *:34 rwm yes Which is fine in some cases. Consider: A (default behavior: deny, exceptions allow access) \ B (default behavior: deny, exceptions allow access) In this case the full match makes sense, the new exception cannot add more access than the parent allows But this doesn't always work, consider: A (default behavior: allow, exceptions disallow access) \ B (default behavior: deny, exceptions allow access) In this case, a new exception in B shouldn't match any of the exceptions in A, after all you can't allow something that was forbidden by A. But consider this scenario: New exception Existing in A match? outcome b 12:34 rw b 12:34 r no exception is accepted Because the new exception has "w" as extra, it doesn't match, so it'll be added to B's exception list. The same problem can happen during a file access check. Consider a cgroup with allow as default behavior: Access Exception match? b 12:34 rw b 12:34 r no In this case, the access didn't match any of the exceptions in the cgroup, which is required since exceptions will disallow access. To solve this problem, two new functions were created to match an exception either fully or partially. In the example above, a partial check will be performed and it'll produce a match since at least "b 12:34 r" from "b 12:34 rw" access matches. Cc: cgroups@vger.kernel.org Cc: Tejun Heo Cc: Serge Hallyn Cc: Li Zefan Cc: stable@vger.kernel.org Signed-off-by: Aristeu Rozanski Signed-off-by: Tejun Heo --- security/device_cgroup.c | 162 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 122 insertions(+), 40 deletions(-) diff --git a/security/device_cgroup.c b/security/device_cgroup.c index 8365909f5f8c..b9048dc46b1a 100644 --- a/security/device_cgroup.c +++ b/security/device_cgroup.c @@ -306,57 +306,139 @@ static int devcgroup_seq_show(struct seq_file *m, void *v) } /** - * may_access - verifies if a new exception is part of what is allowed - * by a dev cgroup based on the default policy + - * exceptions. This is used to make sure a child cgroup - * won't have more privileges than its parent or to - * verify if a certain access is allowed. - * @dev_cgroup: dev cgroup to be tested against - * @refex: new exception - * @behavior: behavior of the exception + * match_exception - iterates the exception list trying to match a rule + * based on type, major, minor and access type. It is + * considered a match if an exception is found that + * will contain the entire range of provided parameters. + * @exceptions: list of exceptions + * @type: device type (DEV_BLOCK or DEV_CHAR) + * @major: device file major number, ~0 to match all + * @minor: device file minor number, ~0 to match all + * @access: permission mask (ACC_READ, ACC_WRITE, ACC_MKNOD) + * + * returns: true in case it matches an exception completely */ -static bool may_access(struct dev_cgroup *dev_cgroup, - struct dev_exception_item *refex, - enum devcg_behavior behavior) +static bool match_exception(struct list_head *exceptions, short type, + u32 major, u32 minor, short access) { struct dev_exception_item *ex; - bool match = false; - rcu_lockdep_assert(rcu_read_lock_held() || - lockdep_is_held(&devcgroup_mutex), - "device_cgroup::may_access() called without proper synchronization"); + list_for_each_entry_rcu(ex, exceptions, list) { + if ((type & DEV_BLOCK) && !(ex->type & DEV_BLOCK)) + continue; + if ((type & DEV_CHAR) && !(ex->type & DEV_CHAR)) + continue; + if (ex->major != ~0 && ex->major != major) + continue; + if (ex->minor != ~0 && ex->minor != minor) + continue; + /* provided access cannot have more than the exception rule */ + if (access & (~ex->access)) + continue; + return true; + } + return false; +} + +/** + * match_exception_partial - iterates the exception list trying to match a rule + * based on type, major, minor and access type. It is + * considered a match if an exception's range is + * found to contain *any* of the devices specified by + * provided parameters. This is used to make sure no + * extra access is being granted that is forbidden by + * any of the exception list. + * @exceptions: list of exceptions + * @type: device type (DEV_BLOCK or DEV_CHAR) + * @major: device file major number, ~0 to match all + * @minor: device file minor number, ~0 to match all + * @access: permission mask (ACC_READ, ACC_WRITE, ACC_MKNOD) + * + * returns: true in case the provided range mat matches an exception completely + */ +static bool match_exception_partial(struct list_head *exceptions, short type, + u32 major, u32 minor, short access) +{ + struct dev_exception_item *ex; - list_for_each_entry_rcu(ex, &dev_cgroup->exceptions, list) { - if ((refex->type & DEV_BLOCK) && !(ex->type & DEV_BLOCK)) + list_for_each_entry_rcu(ex, exceptions, list) { + if ((type & DEV_BLOCK) && !(ex->type & DEV_BLOCK)) continue; - if ((refex->type & DEV_CHAR) && !(ex->type & DEV_CHAR)) + if ((type & DEV_CHAR) && !(ex->type & DEV_CHAR)) continue; - if (ex->major != ~0 && ex->major != refex->major) + /* + * We must be sure that both the exception and the provided + * range aren't masking all devices + */ + if (ex->major != ~0 && major != ~0 && ex->major != major) continue; - if (ex->minor != ~0 && ex->minor != refex->minor) + if (ex->minor != ~0 && minor != ~0 && ex->minor != minor) continue; - if (refex->access & (~ex->access)) + /* + * In order to make sure the provided range isn't matching + * an exception, all its access bits shouldn't match the + * exception's access bits + */ + if (!(access & ex->access)) continue; - match = true; - break; + return true; } + return false; +} + +/** + * verify_new_ex - verifies if a new exception is part of what is allowed + * by a dev cgroup based on the default policy + + * exceptions. This is used to make sure a child cgroup + * won't have more privileges than its parent + * @dev_cgroup: dev cgroup to be tested against + * @refex: new exception + * @behavior: behavior of the exception's dev_cgroup + */ +static bool verify_new_ex(struct dev_cgroup *dev_cgroup, + struct dev_exception_item *refex, + enum devcg_behavior behavior) +{ + bool match = false; + + rcu_lockdep_assert(rcu_read_lock_held() || + lockdep_is_held(&devcgroup_mutex), + "device_cgroup:verify_new_ex called without proper synchronization"); if (dev_cgroup->behavior == DEVCG_DEFAULT_ALLOW) { if (behavior == DEVCG_DEFAULT_ALLOW) { - /* the exception will deny access to certain devices */ + /* + * new exception in the child doesn't matter, only + * adding extra restrictions + */ return true; } else { - /* the exception will allow access to certain devices */ + /* + * new exception in the child will add more devices + * that can be acessed, so it can't match any of + * parent's exceptions, even slightly + */ + match = match_exception_partial(&dev_cgroup->exceptions, + refex->type, + refex->major, + refex->minor, + refex->access); + if (match) - /* - * a new exception allowing access shouldn't - * match an parent's exception - */ return false; return true; } } else { - /* only behavior == DEVCG_DEFAULT_DENY allowed here */ + /* + * Only behavior == DEVCG_DEFAULT_DENY allowed here, therefore + * the new exception will add access to more devices and must + * be contained completely in an parent's exception to be + * allowed + */ + match = match_exception(&dev_cgroup->exceptions, refex->type, + refex->major, refex->minor, + refex->access); + if (match) /* parent has an exception that matches the proposed */ return true; @@ -378,7 +460,7 @@ static int parent_has_perm(struct dev_cgroup *childcg, if (!parent) return 1; - return may_access(parent, ex, childcg->behavior); + return verify_new_ex(parent, ex, childcg->behavior); } /** @@ -704,18 +786,18 @@ static int __devcgroup_check_permission(short type, u32 major, u32 minor, short access) { struct dev_cgroup *dev_cgroup; - struct dev_exception_item ex; - int rc; - - memset(&ex, 0, sizeof(ex)); - ex.type = type; - ex.major = major; - ex.minor = minor; - ex.access = access; + bool rc; rcu_read_lock(); dev_cgroup = task_devcgroup(current); - rc = may_access(dev_cgroup, &ex, dev_cgroup->behavior); + if (dev_cgroup->behavior == DEVCG_DEFAULT_ALLOW) + /* Can't match any of the exceptions, even partially */ + rc = !match_exception_partial(&dev_cgroup->exceptions, + type, major, minor, access); + else + /* Need to match completely one exception to be allowed */ + rc = match_exception(&dev_cgroup->exceptions, type, major, + minor, access); rcu_read_unlock(); if (!rc) -- cgit v1.2.3 From 062f1d6de01df545ca0df366c6133f0fa164bff6 Mon Sep 17 00:00:00 2001 From: Chun-Yeow Yeoh Date: Tue, 22 Apr 2014 18:19:25 +0800 Subject: mac80211: avoid handling of SMPS for mesh The patch "mac80211: implement SMPS for AP" has caused kernel oops at mesh STA if the peer mesh STA operates in sleep mode and then becomes active mode. It can be easily reproduced by setting the following commands at peer mesh STA: iw mesh0 station set aa:bb:cc:dd:ee:ff mesh_power_mode deep iw mesh0 station set aa:bb:cc:dd:ee:ff mesh_power_mode active Kernel oops will happen at mesh STA aa:bb:cc:dd:ee:ff. Fix this by avoiding SMPS for mesh mode. Signed-off-by: Chun-Yeow Yeoh Signed-off-by: Johannes Berg --- net/mac80211/sta_info.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 137a192e64bc..847d92f6bef6 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -1148,7 +1148,8 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) atomic_dec(&ps->num_sta_ps); /* This station just woke up and isn't aware of our SMPS state */ - if (!ieee80211_smps_is_restrictive(sta->known_smps_mode, + if (!ieee80211_vif_is_mesh(&sdata->vif) && + !ieee80211_smps_is_restrictive(sta->known_smps_mode, sdata->smps_mode) && sta->known_smps_mode != sdata->bss->req_smps && sta_info_tx_streams(sta) != 1) { -- cgit v1.2.3 From 311ab8e1c28659e16a6fe14a68929c3ced4a5757 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Wed, 16 Apr 2014 08:32:41 -0400 Subject: mac80211: fixup radiotap tx flags for RTS/CTS When using RTS/CTS, the CTS-to-Self bit in radiotap TX flags is getting set instead of the RTS bit. Set the correct one. Reported-by: Larry Maxwell Signed-off-by: Bob Copeland Signed-off-by: Johannes Berg --- net/mac80211/status.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 00ba90b02ab2..60cb7a665976 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -314,10 +314,9 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_local *local, !is_multicast_ether_addr(hdr->addr1)) txflags |= IEEE80211_RADIOTAP_F_TX_FAIL; - if ((info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || - (info->status.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) + if (info->status.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) txflags |= IEEE80211_RADIOTAP_F_TX_CTS; - else if (info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) + if (info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) txflags |= IEEE80211_RADIOTAP_F_TX_RTS; put_unaligned_le16(txflags, pos); -- cgit v1.2.3 From d132cb0a162fa55c82e06b771fcaa871d30c9398 Mon Sep 17 00:00:00 2001 From: Wenkai Du Date: Wed, 23 Apr 2014 13:29:30 +0300 Subject: ASoC: Intel: Fix audio crash due to race condition in stream deletion There is a race between sst_byt_stream_free() and sst_byt_get_stream() if sst_byt_get_stream() called from sst_byt_irq_thread() context is accessing the byt->stream_list while a stream is deleted from the list. A stream is added to byt->stream_list in sst_byt_stream_new() and deleted in sst_byt_stream_free(). sst_byt_get_stream() is always protected by sst->spinlock, but the stream addition and deletion are not protected. The patch adds spinlock to both stream addition and deletion. [Jarkko: Same fix added to sst-haswell-ipc.c too] Signed-off-by: Wenkai Du Signed-off-by: Jarkko Nikula Signed-off-by: Mark Brown --- sound/soc/intel/sst-baytrail-ipc.c | 8 ++++++++ sound/soc/intel/sst-haswell-ipc.c | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/sound/soc/intel/sst-baytrail-ipc.c b/sound/soc/intel/sst-baytrail-ipc.c index d0eaeee21be4..0d31dbbf4806 100644 --- a/sound/soc/intel/sst-baytrail-ipc.c +++ b/sound/soc/intel/sst-baytrail-ipc.c @@ -542,16 +542,20 @@ struct sst_byt_stream *sst_byt_stream_new(struct sst_byt *byt, int id, void *data) { struct sst_byt_stream *stream; + struct sst_dsp *sst = byt->dsp; + unsigned long flags; stream = kzalloc(sizeof(*stream), GFP_KERNEL); if (stream == NULL) return NULL; + spin_lock_irqsave(&sst->spinlock, flags); list_add(&stream->node, &byt->stream_list); stream->notify_position = notify_position; stream->pdata = data; stream->byt = byt; stream->str_id = id; + spin_unlock_irqrestore(&sst->spinlock, flags); return stream; } @@ -630,6 +634,8 @@ int sst_byt_stream_free(struct sst_byt *byt, struct sst_byt_stream *stream) { u64 header; int ret = 0; + struct sst_dsp *sst = byt->dsp; + unsigned long flags; if (!stream->commited) goto out; @@ -644,8 +650,10 @@ int sst_byt_stream_free(struct sst_byt *byt, struct sst_byt_stream *stream) stream->commited = false; out: + spin_lock_irqsave(&sst->spinlock, flags); list_del(&stream->node); kfree(stream); + spin_unlock_irqrestore(&sst->spinlock, flags); return ret; } diff --git a/sound/soc/intel/sst-haswell-ipc.c b/sound/soc/intel/sst-haswell-ipc.c index 50e4246d4b57..6c0b4f247a86 100644 --- a/sound/soc/intel/sst-haswell-ipc.c +++ b/sound/soc/intel/sst-haswell-ipc.c @@ -1159,11 +1159,14 @@ struct sst_hsw_stream *sst_hsw_stream_new(struct sst_hsw *hsw, int id, void *data) { struct sst_hsw_stream *stream; + struct sst_dsp *sst = hsw->dsp; + unsigned long flags; stream = kzalloc(sizeof(*stream), GFP_KERNEL); if (stream == NULL) return NULL; + spin_lock_irqsave(&sst->spinlock, flags); list_add(&stream->node, &hsw->stream_list); stream->notify_position = notify_position; stream->pdata = data; @@ -1172,6 +1175,7 @@ struct sst_hsw_stream *sst_hsw_stream_new(struct sst_hsw *hsw, int id, /* work to process notification messages */ INIT_WORK(&stream->notify_work, hsw_notification_work); + spin_unlock_irqrestore(&sst->spinlock, flags); return stream; } @@ -1180,6 +1184,8 @@ int sst_hsw_stream_free(struct sst_hsw *hsw, struct sst_hsw_stream *stream) { u32 header; int ret = 0; + struct sst_dsp *sst = hsw->dsp; + unsigned long flags; /* dont free DSP streams that are not commited */ if (!stream->commited) @@ -1201,8 +1207,10 @@ int sst_hsw_stream_free(struct sst_hsw *hsw, struct sst_hsw_stream *stream) trace_hsw_stream_free_req(stream, &stream->free_req); out: + spin_lock_irqsave(&sst->spinlock, flags); list_del(&stream->node); kfree(stream); + spin_unlock_irqrestore(&sst->spinlock, flags); return ret; } -- cgit v1.2.3 From 836b31fe1a9791d84ed95783ed42ebd5719f7918 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 23 Apr 2014 14:59:12 +0900 Subject: ASoC: rsnd: call rsnd_dai_pointer_update() from outside of lock rsnd_soc_dai_trigger() will be called after rsnd_dai_pointer_update() function which is using rsnd_lock(). Thus, it should be called from outside of rsnd_lock(). Kernel will be hangup without this patch. Special thanks to Kataoka-san Reported-by: Ryo Kataoka Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/core.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 215b668166be..89424470a1f3 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -197,13 +197,12 @@ static void rsnd_dma_complete(void *data) * rsnd_dai_pointer_update() will be called twice, * ant it will breaks io->byte_pos */ - - rsnd_dai_pointer_update(io, io->byte_per_period); - if (dma->submit_loop) rsnd_dma_continue(dma); rsnd_unlock(priv, flags); + + rsnd_dai_pointer_update(io, io->byte_per_period); } static void __rsnd_dma_start(struct rsnd_dma *dma) -- cgit v1.2.3 From 20f670dcc08682e478770b48bd5fe09f19351674 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 23 Apr 2014 11:04:29 -0700 Subject: ARM: dts: Fix bad OTG muxing for cm-t boards Looks like the OTG pins are off by 2 and we get this: pinctrl-single 48002030.pinmux: pin 480021a0.0 already requested by 49020000.serial; cannot claim for 480ab000.usb_otg_hs pinctrl-single 48002030.pinmux: pin-184 (480ab000.usb_otg_hs) status -22 pinctrl-single 48002030.pinmux: could not request pin 184 (480021a0.0) from group pinmux_hsusb0_pins on device pinctrl-single musb-omap2430 480ab000.usb_otg_hs: Error applying setting, reverse things back That's probably because the TRM lists the values as 32-bit registers so every second needs 2 added to the address. The OTG pin start range must start from 0x21a2, not 0x21a0. Cc: Dmitry Lifshitz Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap3-cm-t3x30.dtsi | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/arch/arm/boot/dts/omap3-cm-t3x30.dtsi b/arch/arm/boot/dts/omap3-cm-t3x30.dtsi index d00055809e31..75e0a1f96b60 100644 --- a/arch/arm/boot/dts/omap3-cm-t3x30.dtsi +++ b/arch/arm/boot/dts/omap3-cm-t3x30.dtsi @@ -35,18 +35,18 @@ hsusb0_pins: pinmux_hsusb0_pins { pinctrl-single,pins = < - OMAP3_CORE1_IOPAD(0x21a0, PIN_OUTPUT | MUX_MODE0) /* hsusb0_clk.hsusb0_clk */ - OMAP3_CORE1_IOPAD(0x21a2, PIN_OUTPUT | MUX_MODE0) /* hsusb0_stp.hsusb0_stp */ - OMAP3_CORE1_IOPAD(0x21a4, PIN_INPUT_PULLDOWN | MUX_MODE0) /* hsusb0_dir.hsusb0_dir */ - OMAP3_CORE1_IOPAD(0x21a6, PIN_INPUT_PULLDOWN | MUX_MODE0) /* hsusb0_nxt.hsusb0_nxt */ - OMAP3_CORE1_IOPAD(0x21a8, PIN_INPUT_PULLDOWN | MUX_MODE0) /* hsusb0_data0.hsusb2_data0 */ - OMAP3_CORE1_IOPAD(0x21aa, PIN_INPUT_PULLDOWN | MUX_MODE0) /* hsusb0_data1.hsusb0_data1 */ - OMAP3_CORE1_IOPAD(0x21ac, PIN_INPUT_PULLDOWN | MUX_MODE0) /* hsusb0_data2.hsusb0_data2 */ - OMAP3_CORE1_IOPAD(0x21ae, PIN_INPUT_PULLDOWN | MUX_MODE0) /* hsusb0_data7.hsusb0_data3 */ - OMAP3_CORE1_IOPAD(0x21b0, PIN_INPUT_PULLDOWN | MUX_MODE0) /* hsusb0_data7.hsusb0_data4 */ - OMAP3_CORE1_IOPAD(0x21b2, PIN_INPUT_PULLDOWN | MUX_MODE0) /* hsusb0_data7.hsusb0_data5 */ - OMAP3_CORE1_IOPAD(0x21b4, PIN_INPUT_PULLDOWN | MUX_MODE0) /* hsusb0_data7.hsusb0_data6 */ - OMAP3_CORE1_IOPAD(0x21b6, PIN_INPUT_PULLDOWN | MUX_MODE0) /* hsusb0_data7.hsusb0_data7 */ + OMAP3_CORE1_IOPAD(0x21a2, PIN_OUTPUT | MUX_MODE0) /* hsusb0_clk.hsusb0_clk */ + OMAP3_CORE1_IOPAD(0x21a4, PIN_OUTPUT | MUX_MODE0) /* hsusb0_stp.hsusb0_stp */ + OMAP3_CORE1_IOPAD(0x21a6, PIN_INPUT_PULLDOWN | MUX_MODE0) /* hsusb0_dir.hsusb0_dir */ + OMAP3_CORE1_IOPAD(0x21a8, PIN_INPUT_PULLDOWN | MUX_MODE0) /* hsusb0_nxt.hsusb0_nxt */ + OMAP3_CORE1_IOPAD(0x21aa, PIN_INPUT_PULLDOWN | MUX_MODE0) /* hsusb0_data0.hsusb2_data0 */ + OMAP3_CORE1_IOPAD(0x21ac, PIN_INPUT_PULLDOWN | MUX_MODE0) /* hsusb0_data1.hsusb0_data1 */ + OMAP3_CORE1_IOPAD(0x21ae, PIN_INPUT_PULLDOWN | MUX_MODE0) /* hsusb0_data2.hsusb0_data2 */ + OMAP3_CORE1_IOPAD(0x21b0, PIN_INPUT_PULLDOWN | MUX_MODE0) /* hsusb0_data7.hsusb0_data3 */ + OMAP3_CORE1_IOPAD(0x21b2, PIN_INPUT_PULLDOWN | MUX_MODE0) /* hsusb0_data7.hsusb0_data4 */ + OMAP3_CORE1_IOPAD(0x21b4, PIN_INPUT_PULLDOWN | MUX_MODE0) /* hsusb0_data7.hsusb0_data5 */ + OMAP3_CORE1_IOPAD(0x21b6, PIN_INPUT_PULLDOWN | MUX_MODE0) /* hsusb0_data7.hsusb0_data6 */ + OMAP3_CORE1_IOPAD(0x21b8, PIN_INPUT_PULLDOWN | MUX_MODE0) /* hsusb0_data7.hsusb0_data7 */ >; }; }; -- cgit v1.2.3 From de9949a45ec05a9cd5b98eb0a5b5a65db252f1f3 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 23 Apr 2014 11:04:30 -0700 Subject: ARM: dts: Fix GPMC Ethernet timings for omap cm-t sbc-t boards for device tree Looks like we have wrong GPMC timings we have for the cm-t and sbc-t boards. This can cause occasional strange errors with at least doing an rsync of large files or doing apt-get dist-upgrade. Let's fix the issue in two phases. First let's simplify cm-t and sbc-t to use the shared omap-gpmc-smsc911x.dtsi to avoid fixing the issue in multiple places. Then we can fix the timings in a single place with a follow-up patch. Cc: Dmitry Lifshitz Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap3-cm-t3x30.dtsi | 42 +++-------------------------------- arch/arm/boot/dts/omap3-sb-t35.dtsi | 18 ++------------- arch/arm/boot/dts/omap3-sbc-t3517.dts | 13 +++++++++++ 3 files changed, 18 insertions(+), 55 deletions(-) diff --git a/arch/arm/boot/dts/omap3-cm-t3x30.dtsi b/arch/arm/boot/dts/omap3-cm-t3x30.dtsi index 75e0a1f96b60..25ba08331d88 100644 --- a/arch/arm/boot/dts/omap3-cm-t3x30.dtsi +++ b/arch/arm/boot/dts/omap3-cm-t3x30.dtsi @@ -10,18 +10,6 @@ cpu0-supply = <&vcc>; }; }; - - vddvario: regulator-vddvario { - compatible = "regulator-fixed"; - regulator-name = "vddvario"; - regulator-always-on; - }; - - vdd33a: regulator-vdd33a { - compatible = "regulator-fixed"; - regulator-name = "vdd33a"; - regulator-always-on; - }; }; &omap3_pmx_core { @@ -51,42 +39,18 @@ }; }; +#include "omap-gpmc-smsc911x.dtsi" + &gpmc { ranges = <5 0 0x2c000000 0x01000000>; - smsc1: ethernet@5,0 { + smsc1: ethernet@gpmc { compatible = "smsc,lan9221", "smsc,lan9115"; pinctrl-names = "default"; pinctrl-0 = <&smsc1_pins>; interrupt-parent = <&gpio6>; interrupts = <3 IRQ_TYPE_LEVEL_LOW>; reg = <5 0 0xff>; - bank-width = <2>; - gpmc,mux-add-data; - gpmc,cs-on-ns = <0>; - gpmc,cs-rd-off-ns = <186>; - gpmc,cs-wr-off-ns = <186>; - gpmc,adv-on-ns = <12>; - gpmc,adv-rd-off-ns = <48>; - gpmc,adv-wr-off-ns = <48>; - gpmc,oe-on-ns = <54>; - gpmc,oe-off-ns = <168>; - gpmc,we-on-ns = <54>; - gpmc,we-off-ns = <168>; - gpmc,rd-cycle-ns = <186>; - gpmc,wr-cycle-ns = <186>; - gpmc,access-ns = <114>; - gpmc,page-burst-access-ns = <6>; - gpmc,bus-turnaround-ns = <12>; - gpmc,cycle2cycle-delay-ns = <18>; - gpmc,wr-data-mux-bus-ns = <90>; - gpmc,wr-access-ns = <186>; - gpmc,cycle2cycle-samecsen; - gpmc,cycle2cycle-diffcsen; - vddvario-supply = <&vddvario>; - vdd33a-supply = <&vdd33a>; - reg-io-width = <4>; - smsc,save-mac-address; }; }; diff --git a/arch/arm/boot/dts/omap3-sb-t35.dtsi b/arch/arm/boot/dts/omap3-sb-t35.dtsi index 7909c51b05a5..b3b6e4381021 100644 --- a/arch/arm/boot/dts/omap3-sb-t35.dtsi +++ b/arch/arm/boot/dts/omap3-sb-t35.dtsi @@ -2,20 +2,6 @@ * Common support for CompuLab SB-T35 used on SBC-T3530, SBC-T3517 and SBC-T3730 */ -/ { - vddvario_sb_t35: regulator-vddvario-sb-t35 { - compatible = "regulator-fixed"; - regulator-name = "vddvario"; - regulator-always-on; - }; - - vdd33a_sb_t35: regulator-vdd33a-sb-t35 { - compatible = "regulator-fixed"; - regulator-name = "vdd33a"; - regulator-always-on; - }; -}; - &omap3_pmx_core { smsc2_pins: pinmux_smsc2_pins { pinctrl-single,pins = < @@ -57,8 +43,8 @@ gpmc,wr-access-ns = <186>; gpmc,cycle2cycle-samecsen; gpmc,cycle2cycle-diffcsen; - vddvario-supply = <&vddvario_sb_t35>; - vdd33a-supply = <&vdd33a_sb_t35>; + vddvario-supply = <&vddvario>; + vdd33a-supply = <&vdd33a>; reg-io-width = <4>; smsc,save-mac-address; }; diff --git a/arch/arm/boot/dts/omap3-sbc-t3517.dts b/arch/arm/boot/dts/omap3-sbc-t3517.dts index 024c9c6c682d..42189b65d393 100644 --- a/arch/arm/boot/dts/omap3-sbc-t3517.dts +++ b/arch/arm/boot/dts/omap3-sbc-t3517.dts @@ -8,6 +8,19 @@ / { model = "CompuLab SBC-T3517 with CM-T3517"; compatible = "compulab,omap3-sbc-t3517", "compulab,omap3-cm-t3517", "ti,am3517", "ti,omap3"; + + /* Only one GPMC smsc9220 on SBC-T3517, CM-T3517 uses am35x Ethernet */ + vddvario: regulator-vddvario-sb-t35 { + compatible = "regulator-fixed"; + regulator-name = "vddvario"; + regulator-always-on; + }; + + vdd33a: regulator-vdd33a-sb-t35 { + compatible = "regulator-fixed"; + regulator-name = "vdd33a"; + regulator-always-on; + }; }; &omap3_pmx_core { -- cgit v1.2.3 From dcf2191933c4d3b3d1fcd8b6f5818cc913baa8b2 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 23 Apr 2014 11:04:42 -0700 Subject: ARM: dts: Fix GPMC timings for LAN9220 I've noticed occasional random oopsing on my gateway machine since I upgraded it to use device tree based booting. As this machine has worked reliably before that for a few years, pretty much the only difference was narrowed down to the GPMC timings. Turns out that for legacy based booting we are using bootloader timings for GPMC for smsc911x. With device tree we are passing the timings in the .dts file, and the device tree timings are not quite suitable for LAN9920. Enabling DEBUG in gpmc.c I noticed that the device tree configured timings are different from the the known working bootloader timings. So let's fix the timings to match the bootloader timings when looked at the gpmc dmesg output with DEBUG enabled. The changes were done by multiplying the bootloader tick values by six to get the nanosecond value for device tree. This is not generic from the device point of view as the calculations should be based on the device timings. Anyways, further improvments can be done based on the timings documentation for LAN9220. But let's first get things to a known good working state. Note that we still need to change the timings also for sb-t35 also as it has two LAN9220 instances on GPMC and we can currently include the generic timings only once. Also note that any boards that have LAN9221 instead of LAN9220 should be updated to use omap-gpmc-smsc9221.dtsi instead of omap-gpmc-smsc911x.dtsi. The LAN9221 timings are different from LAN9220 timings. Cc: Christoph Fritz Cc: Dmitry Lifshitz Cc: Javier Martinez Canillas Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap-gpmc-smsc911x.dtsi | 19 ++++++++----------- arch/arm/boot/dts/omap3-sb-t35.dtsi | 19 ++++++++----------- 2 files changed, 16 insertions(+), 22 deletions(-) diff --git a/arch/arm/boot/dts/omap-gpmc-smsc911x.dtsi b/arch/arm/boot/dts/omap-gpmc-smsc911x.dtsi index f577b7df9a29..521c587acaee 100644 --- a/arch/arm/boot/dts/omap-gpmc-smsc911x.dtsi +++ b/arch/arm/boot/dts/omap-gpmc-smsc911x.dtsi @@ -24,11 +24,10 @@ compatible = "smsc,lan9221", "smsc,lan9115"; bank-width = <2>; gpmc,mux-add-data; - gpmc,cs-on-ns = <0>; - gpmc,cs-rd-off-ns = <186>; - gpmc,cs-wr-off-ns = <186>; - gpmc,adv-on-ns = <12>; - gpmc,adv-rd-off-ns = <48>; + gpmc,cs-on-ns = <1>; + gpmc,cs-rd-off-ns = <180>; + gpmc,cs-wr-off-ns = <180>; + gpmc,adv-rd-off-ns = <18>; gpmc,adv-wr-off-ns = <48>; gpmc,oe-on-ns = <54>; gpmc,oe-off-ns = <168>; @@ -36,12 +35,10 @@ gpmc,we-off-ns = <168>; gpmc,rd-cycle-ns = <186>; gpmc,wr-cycle-ns = <186>; - gpmc,access-ns = <114>; - gpmc,page-burst-access-ns = <6>; - gpmc,bus-turnaround-ns = <12>; - gpmc,cycle2cycle-delay-ns = <18>; - gpmc,wr-data-mux-bus-ns = <90>; - gpmc,wr-access-ns = <186>; + gpmc,access-ns = <144>; + gpmc,page-burst-access-ns = <24>; + gpmc,bus-turnaround-ns = <90>; + gpmc,cycle2cycle-delay-ns = <90>; gpmc,cycle2cycle-samecsen; gpmc,cycle2cycle-diffcsen; vddvario-supply = <&vddvario>; diff --git a/arch/arm/boot/dts/omap3-sb-t35.dtsi b/arch/arm/boot/dts/omap3-sb-t35.dtsi index b3b6e4381021..d59e3de1441e 100644 --- a/arch/arm/boot/dts/omap3-sb-t35.dtsi +++ b/arch/arm/boot/dts/omap3-sb-t35.dtsi @@ -23,11 +23,10 @@ reg = <4 0 0xff>; bank-width = <2>; gpmc,mux-add-data; - gpmc,cs-on-ns = <0>; - gpmc,cs-rd-off-ns = <186>; - gpmc,cs-wr-off-ns = <186>; - gpmc,adv-on-ns = <12>; - gpmc,adv-rd-off-ns = <48>; + gpmc,cs-on-ns = <1>; + gpmc,cs-rd-off-ns = <180>; + gpmc,cs-wr-off-ns = <180>; + gpmc,adv-rd-off-ns = <18>; gpmc,adv-wr-off-ns = <48>; gpmc,oe-on-ns = <54>; gpmc,oe-off-ns = <168>; @@ -35,12 +34,10 @@ gpmc,we-off-ns = <168>; gpmc,rd-cycle-ns = <186>; gpmc,wr-cycle-ns = <186>; - gpmc,access-ns = <114>; - gpmc,page-burst-access-ns = <6>; - gpmc,bus-turnaround-ns = <12>; - gpmc,cycle2cycle-delay-ns = <18>; - gpmc,wr-data-mux-bus-ns = <90>; - gpmc,wr-access-ns = <186>; + gpmc,access-ns = <144>; + gpmc,page-burst-access-ns = <24>; + gpmc,bus-turnaround-ns = <90>; + gpmc,cycle2cycle-delay-ns = <90>; gpmc,cycle2cycle-samecsen; gpmc,cycle2cycle-diffcsen; vddvario-supply = <&vddvario>; -- cgit v1.2.3 From 27a38856a948c3e8de30dc71647ff9e1778c99fc Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 23 Apr 2014 13:02:35 -0700 Subject: Input: synaptics - add min/max quirk for ThinkPad Edge E431 Cc: stable@vger.kernel.org Signed-off-by: Hans de Goede Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/synaptics.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index ef9f4913450d..d68d33fb5ac2 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -1565,6 +1565,14 @@ static const struct dmi_system_id min_max_dmi_table[] __initconst = { }, .driver_data = (int []){1232, 5710, 1156, 4696}, }, + { + /* Lenovo ThinkPad Edge E431 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad Edge E431"), + }, + .driver_data = (int []){1024, 5022, 2508, 4832}, + }, { /* Lenovo ThinkPad T431s */ .matches = { -- cgit v1.2.3 From b6d07e0273d3296cfbdc88145b8a00ddbefb310a Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Fri, 18 Apr 2014 14:19:50 +0200 Subject: PCI: mvebu: fix off-by-one in the computed size of the mbus windows mvebu_pcie_handle_membase_change() and mvebu_pcie_handle_iobase_change() do not correctly compute the window size. PCI uses an inclusive start/end address pair, which requires a +1 when converting to size. This only worked because a bug in the mbus driver allowed it to silently accept and round up bogus sizes. Fix this by adding one to the computed size. Fixes: 45361a4fe446 ('PCIe driver for Marvell Armada 370/XP systems') Cc: # v3.11+ Signed-off-by: Willy Tarreau Reviewed-By: Jason Gunthorpe Signed-off-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1397823593-1932-5-git-send-email-thomas.petazzoni@free-electrons.com Tested-by: Neil Greatorex Acked-by: Bjorn Helgaas Signed-off-by: Jason Cooper --- drivers/pci/host/pci-mvebu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c index d3d1cfd51e09..48299215cc59 100644 --- a/drivers/pci/host/pci-mvebu.c +++ b/drivers/pci/host/pci-mvebu.c @@ -331,7 +331,7 @@ static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port) port->iowin_base = port->pcie->io.start + iobase; port->iowin_size = ((0xFFF | ((port->bridge.iolimit & 0xF0) << 8) | (port->bridge.iolimitupper << 16)) - - iobase); + iobase) + 1; mvebu_mbus_add_window_remap_by_id(port->io_target, port->io_attr, port->iowin_base, port->iowin_size, @@ -364,7 +364,7 @@ static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port) port->memwin_base = ((port->bridge.membase & 0xFFF0) << 16); port->memwin_size = (((port->bridge.memlimit & 0xFFF0) << 16) | 0xFFFFF) - - port->memwin_base; + port->memwin_base + 1; mvebu_mbus_add_window_by_id(port->mem_target, port->mem_attr, port->memwin_base, port->memwin_size); -- cgit v1.2.3 From 09752a12f430f58523fb6f435f5e30e4048fcfb2 Mon Sep 17 00:00:00 2001 From: Jason Gunthorpe Date: Fri, 18 Apr 2014 14:19:51 +0200 Subject: bus: mvebu-mbus: Avoid setting an undefined window size The mbus hardware requires a power of two size, and size aligned base. Currently, if a non-power of two is passed in to the low level routines they configure the register in a way that results in undefined behaviour. Call WARN and return EINVAL instead. Also, update the debugfs routines to show a message if there is an invalid register setting. All together this makes the recent problems with silent failure of PCI very obvious, noisy and debuggable. Signed-off-by: Jason Gunthorpe Signed-off-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1397823593-1932-6-git-send-email-thomas.petazzoni@free-electrons.com Signed-off-by: Jason Cooper --- drivers/bus/mvebu-mbus.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/bus/mvebu-mbus.c b/drivers/bus/mvebu-mbus.c index 293e2e0a0a87..afee0f731111 100644 --- a/drivers/bus/mvebu-mbus.c +++ b/drivers/bus/mvebu-mbus.c @@ -56,6 +56,7 @@ #include #include #include +#include /* * DDR target is the same on all platforms. @@ -266,6 +267,17 @@ static int mvebu_mbus_setup_window(struct mvebu_mbus_state *mbus, mbus->soc->win_cfg_offset(win); u32 ctrl, remap_addr; + if (!is_power_of_2(size)) { + WARN(true, "Invalid MBus window size: 0x%zx\n", size); + return -EINVAL; + } + + if ((base & (phys_addr_t)(size - 1)) != 0) { + WARN(true, "Invalid MBus base/size: %pa len 0x%zx\n", &base, + size); + return -EINVAL; + } + ctrl = ((size - 1) & WIN_CTRL_SIZE_MASK) | (attr << WIN_CTRL_ATTR_SHIFT) | (target << WIN_CTRL_TGT_SHIFT) | @@ -413,6 +425,10 @@ static int mvebu_devs_debug_show(struct seq_file *seq, void *v) win, (unsigned long long)wbase, (unsigned long long)(wbase + wsize), wtarget, wattr); + if (!is_power_of_2(wsize) || + ((wbase & (u64)(wsize - 1)) != 0)) + seq_puts(seq, " (Invalid base/size!!)"); + if (win < mbus->soc->num_remappable_wins) { seq_printf(seq, " (remap %016llx)\n", (unsigned long long)wremap); -- cgit v1.2.3 From b566e782be32145664d96ada3e389f17d32742e5 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Fri, 18 Apr 2014 14:19:52 +0200 Subject: bus: mvebu-mbus: allow several windows with the same target/attribute Having multiple windows with the same target and attribute is actually legal, and can be useful for PCIe windows, when PCIe BARs have a size that isn't a power of two, and we therefore need to create several MBus windows to cover the PCIe BAR for a given PCIe interface. Fixes: fddddb52a6c4 ('bus: introduce an Marvell EBU MBus driver') Cc: # v3.10+ Signed-off-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1397823593-1932-7-git-send-email-thomas.petazzoni@free-electrons.com Tested-by: Neil Greatorex Signed-off-by: Jason Cooper --- drivers/bus/mvebu-mbus.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/bus/mvebu-mbus.c b/drivers/bus/mvebu-mbus.c index afee0f731111..00b73448b22e 100644 --- a/drivers/bus/mvebu-mbus.c +++ b/drivers/bus/mvebu-mbus.c @@ -223,12 +223,6 @@ static int mvebu_mbus_window_conflicts(struct mvebu_mbus_state *mbus, */ if ((u64)base < wend && end > wbase) return 0; - - /* - * Check if target/attribute conflicts - */ - if (target == wtarget && attr == wattr) - return 0; } return 1; -- cgit v1.2.3 From 398f5d5e10b6b917cd9d35ef21d545b0afbada22 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Fri, 18 Apr 2014 14:19:53 +0200 Subject: PCI: mvebu: split PCIe BARs into multiple MBus windows when needed MBus windows are used on Marvell platforms to map certain peripherals in the physical address space. In the PCIe context, MBus windows are needed to map PCIe I/O and memory regions in the physical address. However, those MBus windows can only have power of two sizes, while PCIe BAR do not necessarily guarantee this. For this reason, the current pci-mvebu breaks on platforms where PCIe devices have BARs that don't sum up to a power of two size at the emulated bridge level. This commit fixes this by allowing the pci-mvebu driver to create multiple contiguous MBus windows (each having a power of two size) to cover a given PCIe BAR. To achieve this, two functions are added: mvebu_pcie_add_windows() and mvebu_pcie_del_windows() to respectively add and remove all the MBus windows that are needed to map the provided PCIe region base and size. The emulated PCI bridge code now calls those functions, instead of directly calling the mvebu-mbus driver functions. Fixes: 45361a4fe446 ('pci: PCIe driver for Marvell Armada 370/XP systems') Cc: # v3.11+ Signed-off-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1397823593-1932-8-git-send-email-thomas.petazzoni@free-electrons.com Tested-by: Neil Greatorex Acked-by: Bjorn Helgaas Signed-off-by: Jason Cooper --- drivers/pci/host/pci-mvebu.c | 88 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 74 insertions(+), 14 deletions(-) diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c index 48299215cc59..e384e2534594 100644 --- a/drivers/pci/host/pci-mvebu.c +++ b/drivers/pci/host/pci-mvebu.c @@ -293,6 +293,58 @@ static int mvebu_pcie_hw_wr_conf(struct mvebu_pcie_port *port, return PCIBIOS_SUCCESSFUL; } +/* + * Remove windows, starting from the largest ones to the smallest + * ones. + */ +static void mvebu_pcie_del_windows(struct mvebu_pcie_port *port, + phys_addr_t base, size_t size) +{ + while (size) { + size_t sz = 1 << (fls(size) - 1); + + mvebu_mbus_del_window(base, sz); + base += sz; + size -= sz; + } +} + +/* + * MBus windows can only have a power of two size, but PCI BARs do not + * have this constraint. Therefore, we have to split the PCI BAR into + * areas each having a power of two size. We start from the largest + * one (i.e highest order bit set in the size). + */ +static void mvebu_pcie_add_windows(struct mvebu_pcie_port *port, + unsigned int target, unsigned int attribute, + phys_addr_t base, size_t size, + phys_addr_t remap) +{ + size_t size_mapped = 0; + + while (size) { + size_t sz = 1 << (fls(size) - 1); + int ret; + + ret = mvebu_mbus_add_window_remap_by_id(target, attribute, base, + sz, remap); + if (ret) { + dev_err(&port->pcie->pdev->dev, + "Could not create MBus window at 0x%x, size 0x%x: %d\n", + base, sz, ret); + mvebu_pcie_del_windows(port, base - size_mapped, + size_mapped); + return; + } + + size -= sz; + size_mapped += sz; + base += sz; + if (remap != MVEBU_MBUS_NO_REMAP) + remap += sz; + } +} + static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port) { phys_addr_t iobase; @@ -304,8 +356,8 @@ static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port) /* If a window was configured, remove it */ if (port->iowin_base) { - mvebu_mbus_del_window(port->iowin_base, - port->iowin_size); + mvebu_pcie_del_windows(port, port->iowin_base, + port->iowin_size); port->iowin_base = 0; port->iowin_size = 0; } @@ -333,9 +385,9 @@ static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port) (port->bridge.iolimitupper << 16)) - iobase) + 1; - mvebu_mbus_add_window_remap_by_id(port->io_target, port->io_attr, - port->iowin_base, port->iowin_size, - iobase); + mvebu_pcie_add_windows(port, port->io_target, port->io_attr, + port->iowin_base, port->iowin_size, + iobase); } static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port) @@ -346,8 +398,8 @@ static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port) /* If a window was configured, remove it */ if (port->memwin_base) { - mvebu_mbus_del_window(port->memwin_base, - port->memwin_size); + mvebu_pcie_del_windows(port, port->memwin_base, + port->memwin_size); port->memwin_base = 0; port->memwin_size = 0; } @@ -366,8 +418,9 @@ static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port) (((port->bridge.memlimit & 0xFFF0) << 16) | 0xFFFFF) - port->memwin_base + 1; - mvebu_mbus_add_window_by_id(port->mem_target, port->mem_attr, - port->memwin_base, port->memwin_size); + mvebu_pcie_add_windows(port, port->mem_target, port->mem_attr, + port->memwin_base, port->memwin_size, + MVEBU_MBUS_NO_REMAP); } /* @@ -743,14 +796,21 @@ static resource_size_t mvebu_pcie_align_resource(struct pci_dev *dev, /* * On the PCI-to-PCI bridge side, the I/O windows must have at - * least a 64 KB size and be aligned on their size, and the - * memory windows must have at least a 1 MB size and be - * aligned on their size + * least a 64 KB size and the memory windows must have at + * least a 1 MB size. Moreover, MBus windows need to have a + * base address aligned on their size, and their size must be + * a power of two. This means that if the BAR doesn't have a + * power of two size, several MBus windows will actually be + * created. We need to ensure that the biggest MBus window + * (which will be the first one) is aligned on its size, which + * explains the rounddown_pow_of_two() being done here. */ if (res->flags & IORESOURCE_IO) - return round_up(start, max_t(resource_size_t, SZ_64K, size)); + return round_up(start, max_t(resource_size_t, SZ_64K, + rounddown_pow_of_two(size))); else if (res->flags & IORESOURCE_MEM) - return round_up(start, max_t(resource_size_t, SZ_1M, size)); + return round_up(start, max_t(resource_size_t, SZ_1M, + rounddown_pow_of_two(size))); else return start; } -- cgit v1.2.3 From db66d756c74acb886c51f11b501c2fe622018a0a Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Fri, 18 Apr 2014 01:59:15 +0900 Subject: sched/docbook: Fix 'make htmldocs' warnings caused by missing description When 'flags' argument to sched_{set,get}attr() syscalls were added in: 6d35ab48090b ("sched: Add 'flags' argument to sched_{set,get}attr() syscalls") no description for 'flags' was added. It causes the following warnings on "make htmldocs": Warning(/kernel/sched/core.c:3645): No description found for parameter 'flags' Warning(/kernel/sched/core.c:3789): No description found for parameter 'flags' Signed-off-by: Masanari Iida Cc: peterz@infradead.org Link: http://lkml.kernel.org/r/1397753955-2914-1-git-send-email-standby24x7@gmail.com Signed-off-by: Ingo Molnar --- kernel/sched/core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 268a45ea238c..9fe2190005cb 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -3639,6 +3639,7 @@ SYSCALL_DEFINE2(sched_setparam, pid_t, pid, struct sched_param __user *, param) * sys_sched_setattr - same as above, but with extended sched_attr * @pid: the pid in question. * @uattr: structure containing the extended parameters. + * @flags: for future extension. */ SYSCALL_DEFINE3(sched_setattr, pid_t, pid, struct sched_attr __user *, uattr, unsigned int, flags) @@ -3783,6 +3784,7 @@ err_size: * @pid: the pid in question. * @uattr: structure containing the extended parameters. * @size: sizeof(attr) for fwd/bwd comp. + * @flags: for future extension. */ SYSCALL_DEFINE4(sched_getattr, pid_t, pid, struct sched_attr __user *, uattr, unsigned int, size, unsigned int, flags) -- cgit v1.2.3 From 7c7606a2464fee1cf50efef34aa44aee1edf453a Mon Sep 17 00:00:00 2001 From: Tomas Sokorai Date: Wed, 23 Apr 2014 10:42:41 -0400 Subject: HID: multitouch: add support of EliteGroup 05D8 panels They need to have the class SERIAL. Note: it is a Win 7 panel, not Win 8 certified. Signed-off-by: Tomas Sokorai Signed-off-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-ids.h | 3 +++ drivers/hid/hid-multitouch.c | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index c8af7202c28d..e7e44f53db59 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -301,6 +301,9 @@ #define USB_VENDOR_ID_DREAM_CHEEKY 0x1d34 +#define USB_VENDOR_ID_ELITEGROUP 0x03fc +#define USB_DEVICE_ID_ELITEGROUP_05D8 0x05d8 + #define USB_VENDOR_ID_ELO 0x04E7 #define USB_DEVICE_ID_ELO_TS2515 0x0022 #define USB_DEVICE_ID_ELO_TS2700 0x0020 diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 35278e43c7a4..51e25b9407f2 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -1155,6 +1155,11 @@ static const struct hid_device_id mt_devices[] = { MT_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001) }, + /* Elitegroup panel */ + { .driver_data = MT_CLS_SERIAL, + MT_USB_DEVICE(USB_VENDOR_ID_ELITEGROUP, + USB_DEVICE_ID_ELITEGROUP_05D8) }, + /* Flatfrog Panels */ { .driver_data = MT_CLS_FLATFROG, MT_USB_DEVICE(USB_VENDOR_ID_FLATFROG, -- cgit v1.2.3 From b8909783a22b4f169ade830e0aa6dafe313426f1 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 24 Apr 2014 08:25:56 +0200 Subject: ASoC: imx-audmux: Fix section mismatch audmux_debugfs_init() is marked as __init, but is called from imx_audmux_probe() which is not marked as __init. This creates a section mismatch and a potential runtime crash (if imx_audmux_probe() is called after the .init section was dropped). This patch removes the __init annotation from audmux_debugfs_init(), which fixes the following warning: WARNING: sound/soc/built-in.o(.text+0x86960): Section mismatch in reference from the function imx_audmux_probe() to the function .init.text:audmux_debugfs_init() Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/fsl/imx-audmux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/fsl/imx-audmux.c b/sound/soc/fsl/imx-audmux.c index ac869931d7f1..267717aa96c1 100644 --- a/sound/soc/fsl/imx-audmux.c +++ b/sound/soc/fsl/imx-audmux.c @@ -145,7 +145,7 @@ static const struct file_operations audmux_debugfs_fops = { .llseek = default_llseek, }; -static void __init audmux_debugfs_init(void) +static void audmux_debugfs_init(void) { int i; char buf[20]; -- cgit v1.2.3 From de30a2ccb20d9baf5dac8a9c8ba8f0d9d5f4361e Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Thu, 24 Apr 2014 10:34:36 +0300 Subject: ASoC: Intel: Cancel hsw_notification_work before freeing the stream I suppose there is a possibility that hsw_notification_work() may run after sst_hsw_stream_free() which can lead to a kernel crash since struct sst_hsw_stream is freed at that point and stream = container_of(work, struct sst_hsw_stream, notify_work) is not valid when hsw_notification_work() is run. Reported-by: Derek Basehore Reported-by: Wenkai Du Signed-off-by: Jarkko Nikula Signed-off-by: Mark Brown --- sound/soc/intel/sst-haswell-ipc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/intel/sst-haswell-ipc.c b/sound/soc/intel/sst-haswell-ipc.c index 6c0b4f247a86..5bcf5963a0ba 100644 --- a/sound/soc/intel/sst-haswell-ipc.c +++ b/sound/soc/intel/sst-haswell-ipc.c @@ -1207,6 +1207,7 @@ int sst_hsw_stream_free(struct sst_hsw *hsw, struct sst_hsw_stream *stream) trace_hsw_stream_free_req(stream, &stream->free_req); out: + cancel_work_sync(&stream->notify_work); spin_lock_irqsave(&sst->spinlock, flags); list_del(&stream->node); kfree(stream); -- cgit v1.2.3 From 0cf4a7d6cf23715276fcd0f1cd1cabc6a9b46942 Mon Sep 17 00:00:00 2001 From: Jacob Pan Date: Tue, 15 Apr 2014 22:27:11 -0700 Subject: ahci: disable DEVSLP for Intel Valleyview On Intel Valleyview SoC, SATA device sleep is not reliable. When DEVSLP is attempted on certain SSDs, port_devslp write would fail and result in malfunction of AHCI controller. AHCI controller may be not shown in PCI enumeration after reset. Complete power source removal may be required to recover from this failure. So we blacklist this device and override host device reported capabilities such that device LPM will only attempt slumber but not DEVSLP. Signed-off-by: Jacob Pan Acked-by: Dan Williams Signed-off-by: Tejun Heo --- drivers/ata/ahci.c | 15 +++++++++++++++ drivers/ata/ahci.h | 1 + drivers/ata/libahci.c | 7 +++++++ 3 files changed, 23 insertions(+) diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 71e15b73513d..60707814a84b 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -1115,6 +1115,17 @@ static bool ahci_broken_online(struct pci_dev *pdev) return pdev->bus->number == (val >> 8) && pdev->devfn == (val & 0xff); } +static bool ahci_broken_devslp(struct pci_dev *pdev) +{ + /* device with broken DEVSLP but still showing SDS capability */ + static const struct pci_device_id ids[] = { + { PCI_VDEVICE(INTEL, 0x0f23)}, /* Valleyview SoC */ + {} + }; + + return pci_match_id(ids, pdev); +} + #ifdef CONFIG_ATA_ACPI static void ahci_gtf_filter_workaround(struct ata_host *host) { @@ -1364,6 +1375,10 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) hpriv->mmio = pcim_iomap_table(pdev)[ahci_pci_bar]; + /* must set flag prior to save config in order to take effect */ + if (ahci_broken_devslp(pdev)) + hpriv->flags |= AHCI_HFLAG_NO_DEVSLP; + /* save initial config */ ahci_pci_save_initial_config(pdev, hpriv); diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h index b5eb886da226..af63c75c2001 100644 --- a/drivers/ata/ahci.h +++ b/drivers/ata/ahci.h @@ -236,6 +236,7 @@ enum { port start (wait until error-handling stage) */ AHCI_HFLAG_MULTI_MSI = (1 << 16), /* multiple PCI MSIs */ + AHCI_HFLAG_NO_DEVSLP = (1 << 17), /* no device sleep */ /* ap->flags bits */ diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index 6bd4f660b4e1..b9861453fc81 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -452,6 +452,13 @@ void ahci_save_initial_config(struct device *dev, cap &= ~HOST_CAP_SNTF; } + if ((cap2 & HOST_CAP2_SDS) && (hpriv->flags & AHCI_HFLAG_NO_DEVSLP)) { + dev_info(dev, + "controller can't do DEVSLP, turning off\n"); + cap2 &= ~HOST_CAP2_SDS; + cap2 &= ~HOST_CAP2_SADM; + } + if (!(cap & HOST_CAP_FBS) && (hpriv->flags & AHCI_HFLAG_YES_FBS)) { dev_info(dev, "controller can do FBS, turning on CAP_FBS\n"); cap |= HOST_CAP_FBS; -- cgit v1.2.3 From a87c9ad956676d84d459739fc14ec5a3c3565717 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Wed, 26 Mar 2014 07:24:23 -0700 Subject: cifs: fix actimeo=0 corner case when cifs_i->time == jiffies actimeo=0 is supposed to be a special case that ensures that inode attributes are always refetched from the server instead of trusting the cache. The cifs code however uses time_in_range() to determine whether the attributes have timed out. In the case where cifs_i->time equals jiffies, this leads to the cifs code not refetching the inode attributes when it should. Fix this by explicitly testing for actimeo=0, and handling it as a special case. Reported-and-tested-by: Tetsuo Handa Signed-off-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/inode.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index aadc2b68678b..a22d667f1069 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -1737,6 +1737,9 @@ cifs_inode_needs_reval(struct inode *inode) if (cifs_i->time == 0) return true; + if (!cifs_sb->actimeo) + return true; + if (!time_in_range(jiffies, cifs_i->time, cifs_i->time + cifs_sb->actimeo)) return true; -- cgit v1.2.3 From 3d725caa9dcc78c3dc9e7ea0c04f626468edd9c9 Mon Sep 17 00:00:00 2001 From: Sheng-Liang Song Date: Thu, 24 Apr 2014 16:28:29 -0700 Subject: Input: atkbd - fix keyboard not working on some LG laptops After issuing ATKBD_CMD_RESET_DIS, keyboard on some LG laptops stops working. The workaround is to stop issuing ATKBD_CMD_RESET_DIS commands. In order to keep changes in atkbd driver to the minimum we check DMI signature and only skip ATKBD_CMD_RESET_DIS if we are running on LG LW25-B7HV or P1-J273B. Cc: stable@vger.kernel.org Signed-off-by: Sheng-Liang Song Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/atkbd.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index 2626773ff29b..2dd1d0dd4f7d 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -243,6 +243,12 @@ static void (*atkbd_platform_fixup)(struct atkbd *, const void *data); static void *atkbd_platform_fixup_data; static unsigned int (*atkbd_platform_scancode_fixup)(struct atkbd *, unsigned int); +/* + * Certain keyboards to not like ATKBD_CMD_RESET_DIS and stop responding + * to many commands until full reset (ATKBD_CMD_RESET_BAT) is performed. + */ +static bool atkbd_skip_deactivate; + static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf, ssize_t (*handler)(struct atkbd *, char *)); static ssize_t atkbd_attr_set_helper(struct device *dev, const char *buf, size_t count, @@ -768,7 +774,8 @@ static int atkbd_probe(struct atkbd *atkbd) * Make sure nothing is coming from the keyboard and disturbs our * internal state. */ - atkbd_deactivate(atkbd); + if (!atkbd_skip_deactivate) + atkbd_deactivate(atkbd); return 0; } @@ -1638,6 +1645,12 @@ static int __init atkbd_setup_scancode_fixup(const struct dmi_system_id *id) return 1; } +static int __init atkbd_deactivate_fixup(const struct dmi_system_id *id) +{ + atkbd_skip_deactivate = true; + return 1; +} + static const struct dmi_system_id atkbd_dmi_quirk_table[] __initconst = { { .matches = { @@ -1775,6 +1788,20 @@ static const struct dmi_system_id atkbd_dmi_quirk_table[] __initconst = { .callback = atkbd_setup_scancode_fixup, .driver_data = atkbd_oqo_01plus_scancode_fixup, }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LG Electronics"), + DMI_MATCH(DMI_PRODUCT_NAME, "LW25-B7HV"), + }, + .callback = atkbd_deactivate_fixup, + }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LG Electronics"), + DMI_MATCH(DMI_PRODUCT_NAME, "P1-J273B"), + }, + .callback = atkbd_deactivate_fixup, + }, { } }; -- cgit v1.2.3 From ef3714fdbc8d4bb0af2eff584519f9687aed0fcb Mon Sep 17 00:00:00 2001 From: "Dr. H. Nikolaus Schaller" Date: Thu, 24 Apr 2014 23:42:43 -0700 Subject: Input: bma150 - extend chip detection for bma180 This driver has been used while on the OpenPhoenux GTA04 with a BMA180. Signed-off-by: H. Nikolaus Schaller Signed-off-by: Dmitry Torokhov --- drivers/input/misc/bma150.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/input/misc/bma150.c b/drivers/input/misc/bma150.c index 52d3a9b28f0b..b36831c828d3 100644 --- a/drivers/input/misc/bma150.c +++ b/drivers/input/misc/bma150.c @@ -70,6 +70,7 @@ #define BMA150_CFG_5_REG 0x11 #define BMA150_CHIP_ID 2 +#define BMA180_CHIP_ID 3 #define BMA150_CHIP_ID_REG BMA150_DATA_0_REG #define BMA150_ACC_X_LSB_REG BMA150_DATA_2_REG @@ -539,7 +540,7 @@ static int bma150_probe(struct i2c_client *client, } chip_id = i2c_smbus_read_byte_data(client, BMA150_CHIP_ID_REG); - if (chip_id != BMA150_CHIP_ID) { + if (chip_id != BMA150_CHIP_ID && chip_id != BMA180_CHIP_ID) { dev_err(&client->dev, "BMA150 chip id error: %d\n", chip_id); return -EINVAL; } @@ -643,6 +644,7 @@ static UNIVERSAL_DEV_PM_OPS(bma150_pm, bma150_suspend, bma150_resume, NULL); static const struct i2c_device_id bma150_id[] = { { "bma150", 0 }, + { "bma180", 0 }, { "smb380", 0 }, { "bma023", 0 }, { } -- cgit v1.2.3 From c16134976fb27d325ae037a8b39b537a77ba1d12 Mon Sep 17 00:00:00 2001 From: "Dr. H. Nikolaus Schaller" Date: Thu, 24 Apr 2014 23:43:36 -0700 Subject: Input: tca8418 - fix loading this driver as a module from a device tree Loading the tca8418 driver as a module on a device tree based system needs a MODULE_ALIAS because the driver name does not match the automatic name generation rules of a 'compatible' entry on i2c bus. Signed-off-by: H. Nikolaus Schaller Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/tca8418_keypad.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/input/keyboard/tca8418_keypad.c b/drivers/input/keyboard/tca8418_keypad.c index 55c15304ddbc..4e491c1762cf 100644 --- a/drivers/input/keyboard/tca8418_keypad.c +++ b/drivers/input/keyboard/tca8418_keypad.c @@ -392,6 +392,13 @@ static const struct of_device_id tca8418_dt_ids[] = { { } }; MODULE_DEVICE_TABLE(of, tca8418_dt_ids); + +/* + * The device tree based i2c loader looks for + * "i2c:" + second_component_of(property("compatible")) + * and therefore we need an alias to be found. + */ +MODULE_ALIAS("i2c:tca8418"); #endif static struct i2c_driver tca8418_keypad_driver = { -- cgit v1.2.3 From 2a1c23e3396d5a77d6c8e379d18cc657b6225779 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 24 Apr 2014 18:51:03 -0700 Subject: ASoC: tlv320aic31xx: Convert /n to \n Use a newline character appropriately. Signed-off-by: Joe Perches Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic31xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c index fa158cfe9b32..d1929de641e2 100644 --- a/sound/soc/codecs/tlv320aic31xx.c +++ b/sound/soc/codecs/tlv320aic31xx.c @@ -376,7 +376,7 @@ static int aic31xx_dapm_power_event(struct snd_soc_dapm_widget *w, reg = AIC31XX_ADCFLAG; break; default: - dev_err(w->codec->dev, "Unknown widget '%s' calling %s/n", + dev_err(w->codec->dev, "Unknown widget '%s' calling %s\n", w->name, __func__); return -EINVAL; } -- cgit v1.2.3 From 7f1950fbb989e8fc5463b307e062b4529d51c862 Mon Sep 17 00:00:00 2001 From: Egbert Eich Date: Fri, 25 Apr 2014 10:56:22 +0200 Subject: drm/i915: Break encoder->crtc link separately in intel_sanitize_crtc() Depending on the SDVO output_flags SDVO may have multiple connectors linking to the same encoder (in intel_connector->encoder->base). Only one of those connectors should be active (ie link to the encoder thru drm_connector->encoder). If intel_connector_break_all_links() is called from intel_sanitize_crtc() we may break the crtc connection of an encoder thru an inactive connector in which case intel_connector_break_all_links() will not be called again for the active connector if this happens to come later in the list due to: if (connector->encoder->base.crtc != &crtc->base) continue; in intel_sanitize_crtc(). This will however leave the drm_connector->encoder linkage for this active connector in place. Subsequently this will cause multiple warnings in intel_connector_check_state() to trigger and the driver will eventually die in drm_encoder_crtc_ok() (because of crtc == NULL). To avoid this remove intel_connector_break_all_links() and move its code to its two calling functions: intel_sanitize_crtc() and intel_sanitize_encoder(). This allows to implement the link breaking more flexibly matching the surrounding code: ie. in intel_sanitize_crtc() we can break the crtc link separatly after the links to the encoders have been broken which avoids above problem. This regression has been introduced in: commit 24929352481f085c5f85d4d4cbc919ddf106d381 Author: Daniel Vetter Date: Mon Jul 2 20:28:59 2012 +0200 drm/i915: read out the modeset hw state at load and resume time so goes back to the very beginning of the modeset rework. v2: This patch takes care of the concernes voiced by Chris Wilson and Daniel Vetter that only breaking links if the drm_connector is linked to an encoder may miss some links. v3: move all encoder handling to encoder loop as suggested by Daniel Vetter. Signed-off-by: Egbert Eich Reviewed-by: Daniel Vetter Cc: stable@vger.kernel.org Cc: Jani Nikula Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_display.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 69bcc42a0e44..48aa516a1ac0 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -11395,15 +11395,6 @@ void intel_modeset_init(struct drm_device *dev) } } -static void -intel_connector_break_all_links(struct intel_connector *connector) -{ - connector->base.dpms = DRM_MODE_DPMS_OFF; - connector->base.encoder = NULL; - connector->encoder->connectors_active = false; - connector->encoder->base.crtc = NULL; -} - static void intel_enable_pipe_a(struct drm_device *dev) { struct intel_connector *connector; @@ -11485,8 +11476,17 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc) if (connector->encoder->base.crtc != &crtc->base) continue; - intel_connector_break_all_links(connector); + connector->base.dpms = DRM_MODE_DPMS_OFF; + connector->base.encoder = NULL; } + /* multiple connectors may have the same encoder: + * handle them and break crtc link separately */ + list_for_each_entry(connector, &dev->mode_config.connector_list, + base.head) + if (connector->encoder->base.crtc == &crtc->base) { + connector->encoder->base.crtc = NULL; + connector->encoder->connectors_active = false; + } WARN_ON(crtc->active); crtc->base.enabled = false; @@ -11568,6 +11568,8 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder) drm_get_encoder_name(&encoder->base)); encoder->disable(encoder); } + encoder->base.crtc = NULL; + encoder->connectors_active = false; /* Inconsistent output/port/pipe state happens presumably due to * a bug in one of the get_hw_state functions. Or someplace else @@ -11578,8 +11580,8 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder) base.head) { if (connector->encoder != encoder) continue; - - intel_connector_break_all_links(connector); + connector->base.dpms = DRM_MODE_DPMS_OFF; + connector->base.encoder = NULL; } } /* Enabled encoders without active connectors will be fixed in -- cgit v1.2.3 From ef139e130c8a18cc6cdaa2d98899f74e14389bd4 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Thu, 24 Apr 2014 18:53:50 +0200 Subject: ARM: dts: omap3-igep0020: use SMSC9221 timings The IGEPv2 board has a SMSC LAN9221i ethernet chip and not a SMSC LAN911x connected to the GPMC. Each chip needs different timings in order to operate correctly so is wrong to include omap-gpmc-smsc911x.dtsi instead of omap-gpmc-smsc9221.dtsi. Signed-off-by: Javier Martinez Canillas [tony@atomide.com: this is needed to avoid potential memory corruption] Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap3-igep.dtsi | 2 +- arch/arm/boot/dts/omap3-igep0020.dts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/omap3-igep.dtsi b/arch/arm/boot/dts/omap3-igep.dtsi index b97736d98a64..e2d163bf0619 100644 --- a/arch/arm/boot/dts/omap3-igep.dtsi +++ b/arch/arm/boot/dts/omap3-igep.dtsi @@ -107,7 +107,7 @@ >; }; - smsc911x_pins: pinmux_smsc911x_pins { + smsc9221_pins: pinmux_smsc9221_pins { pinctrl-single,pins = < 0x1a2 (PIN_INPUT | MUX_MODE4) /* mcspi1_cs2.gpio_176 */ >; diff --git a/arch/arm/boot/dts/omap3-igep0020.dts b/arch/arm/boot/dts/omap3-igep0020.dts index 7abd64f6ae21..b22caaaf774b 100644 --- a/arch/arm/boot/dts/omap3-igep0020.dts +++ b/arch/arm/boot/dts/omap3-igep0020.dts @@ -10,7 +10,7 @@ */ #include "omap3-igep.dtsi" -#include "omap-gpmc-smsc911x.dtsi" +#include "omap-gpmc-smsc9221.dtsi" / { model = "IGEPv2 (TI OMAP AM/DM37x)"; @@ -248,7 +248,7 @@ ethernet@gpmc { pinctrl-names = "default"; - pinctrl-0 = <&smsc911x_pins>; + pinctrl-0 = <&smsc9221_pins>; reg = <5 0 0xff>; interrupt-parent = <&gpio6>; interrupts = <16 IRQ_TYPE_LEVEL_LOW>; -- cgit v1.2.3 From 1ff3859e7ea134c09512498aa2251fd3a57d250d Mon Sep 17 00:00:00 2001 From: Dave Gerlach Date: Fri, 21 Mar 2014 10:50:13 +0530 Subject: ARM: dts: am437x-gp-evm: Do not reset gpio5 Do not reset GPIO5 at boot-up because GPIO5_7 is used on AM437x GP-EVM to control VTT regulators on DDR3. Without this some GP-EVM boards will fail to boot because of DDR3 corruption. Reported-by: Nishanth Menon Tested-by: Nishanth Menon Signed-off-by: Dave Gerlach Signed-off-by: Lokesh Vutla Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am437x-gp-evm.dts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm/boot/dts/am437x-gp-evm.dts b/arch/arm/boot/dts/am437x-gp-evm.dts index df8798e8bd25..a055f7f0f14a 100644 --- a/arch/arm/boot/dts/am437x-gp-evm.dts +++ b/arch/arm/boot/dts/am437x-gp-evm.dts @@ -117,6 +117,11 @@ status = "okay"; }; +&gpio5 { + status = "okay"; + ti,no-reset-on-init; +}; + &mmc1 { status = "okay"; vmmc-supply = <&vmmcsd_fixed>; -- cgit v1.2.3 From da0159fdb57d6fab54ce3179659a1f9e5b593752 Mon Sep 17 00:00:00 2001 From: Joel Fernandes Date: Tue, 22 Apr 2014 14:40:39 -0500 Subject: ARM: OMAP5: Switch to THUMB mode if needed on secondary CPU On my DRA7 system, when the kernel is built in Thumb-2 mode, the secondary CPU (Cortex A15) fails to come up causing SMP boot on second CPU to timeout. This seems to be because the CPU is in ARM mode once the ROM hands over control to the kernel. Switch to Thumb-2 mode if required once the kernel is control of secondary CPU. On OMAP4 on the other hand, it appears to be in Thumb-2 mode on entry so this is not required and SMP boot works as is. Also corrected a spurious '+' and updated copyright information. Cc: Santosh Shilimkar Cc: Russell King Cc: Nishanth Menon Tested-by: Nishanth Menon Acked-by: Santosh Shilimkar Signed-off-by: Joel Fernandes Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/omap-headsmp.S | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-omap2/omap-headsmp.S b/arch/arm/mach-omap2/omap-headsmp.S index 75e92952c18e..40c5d5f1451c 100644 --- a/arch/arm/mach-omap2/omap-headsmp.S +++ b/arch/arm/mach-omap2/omap-headsmp.S @@ -1,7 +1,7 @@ /* * Secondary CPU startup routine source file. * - * Copyright (C) 2009 Texas Instruments, Inc. + * Copyright (C) 2009-2014 Texas Instruments, Inc. * * Author: * Santosh Shilimkar @@ -28,9 +28,13 @@ * code. This routine also provides a holding flag into which * secondary core is held until we're ready for it to initialise. * The primary core will update this flag using a hardware -+ * register AuxCoreBoot0. + * register AuxCoreBoot0. */ ENTRY(omap5_secondary_startup) +.arm +THUMB( adr r9, BSYM(wait) ) @ CPU may be entered in ARM mode. +THUMB( bx r9 ) @ If this is a Thumb-2 kernel, +THUMB( .thumb ) @ switch to Thumb now. wait: ldr r2, =AUX_CORE_BOOT0_PA @ read from AuxCoreBoot0 ldr r0, [r2] mov r0, r0, lsr #5 -- cgit v1.2.3 From 84d89c3123bf4c3145f7b19fca36dba612a69807 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Tue, 22 Apr 2014 17:23:35 -0500 Subject: ARM: dts: OMAP5: Add mailbox dt node to fix boot warning Add the mailbox device DT node for OMAP5 SoC. The OMAP5 mailbox IP is identical to that used in OMAP4. The OMAP5 hwmod data no longer publishes the module address space, so this patch fixes the WARN_ON backtrace associated with the following trace during the kernel boot: "omap_hwmod: mailbox: doesn't have mpu register target base". Otherwise we get a warning like this: WARNING: CPU: 0 PID: 1 at arch/arm/mach-omap2/omap_hwmod.c:2538 _init+0x1c0/0x3dc() omap_hwmod: mailbox: doesn't have mpu register target base Modules linked in: CPU: 0 PID: 1 Comm: swapper/0 Not tainted 3.15.0-rc2-00001-gb5e85a0 #45 [] (unwind_backtrace) from [] (show_stack+0x10/0x14) [] (show_stack) from [] (dump_stack+0x78/0x94) [] (dump_stack) from [] (warn_slowpath_common+0x6c/0x8c) [] (warn_slowpath_common) from [] (warn_slowpath_fmt+0x30/0x40) [] (warn_slowpath_fmt) from [] (_init+0x1c0/0x3dc) [] (_init) from [] (omap_hwmod_for_each+0x34/0x5c) [] (omap_hwmod_for_each) from [] (__omap_hwmod_setup_all+0x24/0x40) [] (__omap_hwmod_setup_all) from [] (do_one_initcall+0x34/0x160) [] (do_one_initcall) from [] (kernel_init_freeable+0xfc/0x1c8) [] (kernel_init_freeable) from [] (kernel_init+0x8/0xe4) [] (kernel_init) from [] (ret_from_fork+0x14/0x2c) Signed-off-by: Suman Anna [tony@atomide.com: updated description to for the warning] Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap5.dtsi | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi index f8c9855ce587..36b4312a5e0d 100644 --- a/arch/arm/boot/dts/omap5.dtsi +++ b/arch/arm/boot/dts/omap5.dtsi @@ -630,6 +630,13 @@ status = "disabled"; }; + mailbox: mailbox@4a0f4000 { + compatible = "ti,omap4-mailbox"; + reg = <0x4a0f4000 0x200>; + interrupts = ; + ti,hwmods = "mailbox"; + }; + timer1: timer@4ae18000 { compatible = "ti,omap5430-timer"; reg = <0x4ae18000 0x80>; -- cgit v1.2.3 From 4fe5bd5da2ea7b1b8c9455246ddcdb39ab734487 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Tue, 22 Apr 2014 17:23:36 -0500 Subject: ARM: dts: OMAP2: Fix interrupts for OMAP2420 mailbox The mailbox module is capable of generating two interrupts to MPU in OMAP2420, compared to one in OMAP2430. The second interrupt is to handle interrupts from the additional IVA processor present only on OMAP2420. Move the current common mailbox DT node into the SoC specific files to allow the above differentiation. Also, added back the interrupt-names on OMAP2420, that were previously defined in hwmod data. This fixes regression caused by the recent dropping of hwmod data in favor for defining it in the .dts files. Signed-off-by: Suman Anna [tony@atomide.com: updated description] Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap2.dtsi | 7 ------- arch/arm/boot/dts/omap2420.dtsi | 8 ++++++++ arch/arm/boot/dts/omap2430.dtsi | 7 +++++++ 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/arch/arm/boot/dts/omap2.dtsi b/arch/arm/boot/dts/omap2.dtsi index 22f35ea142c1..8f8c07da4ac1 100644 --- a/arch/arm/boot/dts/omap2.dtsi +++ b/arch/arm/boot/dts/omap2.dtsi @@ -71,13 +71,6 @@ interrupts = <58>; }; - mailbox: mailbox@48094000 { - compatible = "ti,omap2-mailbox"; - ti,hwmods = "mailbox"; - reg = <0x48094000 0x200>; - interrupts = <26>; - }; - intc: interrupt-controller@1 { compatible = "ti,omap2-intc"; interrupt-controller; diff --git a/arch/arm/boot/dts/omap2420.dtsi b/arch/arm/boot/dts/omap2420.dtsi index 85b1fb014c43..2d9979835f24 100644 --- a/arch/arm/boot/dts/omap2420.dtsi +++ b/arch/arm/boot/dts/omap2420.dtsi @@ -125,6 +125,14 @@ dma-names = "tx", "rx"; }; + mailbox: mailbox@48094000 { + compatible = "ti,omap2-mailbox"; + reg = <0x48094000 0x200>; + interrupts = <26>, <34>; + interrupt-names = "dsp", "iva"; + ti,hwmods = "mailbox"; + }; + timer1: timer@48028000 { compatible = "ti,omap2420-timer"; reg = <0x48028000 0x400>; diff --git a/arch/arm/boot/dts/omap2430.dtsi b/arch/arm/boot/dts/omap2430.dtsi index d09697dab55e..42d2c61c9e2d 100644 --- a/arch/arm/boot/dts/omap2430.dtsi +++ b/arch/arm/boot/dts/omap2430.dtsi @@ -216,6 +216,13 @@ dma-names = "tx", "rx"; }; + mailbox: mailbox@48094000 { + compatible = "ti,omap2-mailbox"; + reg = <0x48094000 0x200>; + interrupts = <26>; + ti,hwmods = "mailbox"; + }; + timer1: timer@49018000 { compatible = "ti,omap2420-timer"; reg = <0x49018000 0x400>; -- cgit v1.2.3 From 4c05160342f16361fc37ae34dcae9210306a83e9 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Tue, 22 Apr 2014 17:23:37 -0500 Subject: ARM: dts: AM3517: Disable absent IPs inherited from OMAP3 AM3517 inherits OMAP3 dts file, but does not have all the IPs that are present on OMAP3. This patch disables the following absent IPs for AM3517: Mailbox, IVA, MMU_ISP, MPU_IVA SmartReflex. A label had to be added for IVA node in omap3.dtsi to be able to get a reference to the node for disabling. Otherwise we get the following warnings during booting: platform iva.2: Cannot lookup hwmod 'iva' platform 48094000.mailbox: Cannot lookup hwmod 'mailbox' platform 480bd400.mmu: Cannot lookup hwmod 'mmu_isp' platform 480c9000.smartreflex: Cannot lookup hwmod 'smartreflex_mpu_iva' Signed-off-by: Suman Anna [tony@atomide.com: updated description for the warnings] Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am3517.dtsi | 16 ++++++++++++++++ arch/arm/boot/dts/omap3.dtsi | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/am3517.dtsi b/arch/arm/boot/dts/am3517.dtsi index 788391f91684..5a452fdd7c5d 100644 --- a/arch/arm/boot/dts/am3517.dtsi +++ b/arch/arm/boot/dts/am3517.dtsi @@ -62,5 +62,21 @@ }; }; +&iva { + status = "disabled"; +}; + +&mailbox { + status = "disabled"; +}; + +&mmu_isp { + status = "disabled"; +}; + +&smartreflex_mpu_iva { + status = "disabled"; +}; + /include/ "am35xx-clocks.dtsi" /include/ "omap36xx-am35xx-omap3430es2plus-clocks.dtsi" diff --git a/arch/arm/boot/dts/omap3.dtsi b/arch/arm/boot/dts/omap3.dtsi index acb9019dc437..4231191ade06 100644 --- a/arch/arm/boot/dts/omap3.dtsi +++ b/arch/arm/boot/dts/omap3.dtsi @@ -61,7 +61,7 @@ ti,hwmods = "mpu"; }; - iva { + iva: iva { compatible = "ti,iva2.2"; ti,hwmods = "iva"; -- cgit v1.2.3 From 05d8f6593d1d0b4677822136b61d48d7581c5d16 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Fri, 25 Apr 2014 12:25:42 -0600 Subject: PCI: Update my email address Signed-off-by: Ben Hutchings Signed-off-by: Bjorn Helgaas --- Documentation/ABI/testing/sysfs-bus-pci | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/ABI/testing/sysfs-bus-pci b/Documentation/ABI/testing/sysfs-bus-pci index a3c5a6685036..ab8d76dfaa80 100644 --- a/Documentation/ABI/testing/sysfs-bus-pci +++ b/Documentation/ABI/testing/sysfs-bus-pci @@ -117,7 +117,7 @@ Description: What: /sys/bus/pci/devices/.../vpd Date: February 2008 -Contact: Ben Hutchings +Contact: Ben Hutchings Description: A file named vpd in a device directory will be a binary file containing the Vital Product Data for the -- cgit v1.2.3 From 1a88f809ccb5db1509a7514b187c00b3a995fc82 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Mon, 14 Apr 2014 17:29:19 +0200 Subject: ARM: mvebu: fix NOR bus-width in Armada XP GP Device Tree The mvebu-devbus driver had a serious bug, which lead to a 8 bits bus width declared in the Device Tree being considered as a 16 bits bus width when configuring the hardware. This bug in mvebu-devbus driver was compensated by a symetric mistake in the Armada XP GP Device Tree: a 8 bits bus width was declared, even though the hardware actually has a 16 bits bus width connection with the NOR flash. Now that we have fixed the mvebu-devbus driver to behave according to its Device Tree binding, this commit fixes the problematic Device Tree files as well. This bug was introduced in commit da8d1b38356853c37116f9afa29f15648d7fb159 ('ARM: mvebu: Add support for NOR flash device on Armada XP-GP board') which was merged in v3.10. Signed-off-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1397489361-5833-3-git-send-email-thomas.petazzoni@free-electrons.com Fixes: da8d1b383568 ('ARM: mvebu: Add support for NOR flash device on Armada XP-GP board') Cc: stable@vger.kernel.org # v3.10+ Acked-by: Ezequiel Garcia Acked-by: Gregory CLEMENT Signed-off-by: Jason Cooper --- arch/arm/boot/dts/armada-xp-gp.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/armada-xp-gp.dts b/arch/arm/boot/dts/armada-xp-gp.dts index 61bda687f782..3a359fdd19cc 100644 --- a/arch/arm/boot/dts/armada-xp-gp.dts +++ b/arch/arm/boot/dts/armada-xp-gp.dts @@ -59,7 +59,7 @@ /* Device Bus parameters are required */ /* Read parameters */ - devbus,bus-width = <8>; + devbus,bus-width = <16>; devbus,turn-off-ps = <60000>; devbus,badr-skew-ps = <0>; devbus,acc-first-ps = <124000>; -- cgit v1.2.3 From f3aec8f3f05025e7b450102dae0759375346706e Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Mon, 14 Apr 2014 17:29:20 +0200 Subject: ARM: mvebu: fix NOR bus-width in Armada XP DB Device Tree The mvebu-devbus driver had a serious bug, which lead to a 8 bits bus width declared in the Device Tree being considered as a 16 bits bus width when configuring the hardware. This bug in mvebu-devbus driver was compensated by a symetric mistake in the Armada XP DB Device Tree: a 8 bits bus width was declared, even though the hardware actually has a 16 bits bus width connection with the NOR flash. Now that we have fixed the mvebu-devbus driver to behave according to its Device Tree binding, this commit fixes the problematic Device Tree files as well. This bug was introduced in commit b484ff42df475c5087d614c4d477273e1906bcb9 ('ARM: mvebu: Add support for NOR flash device on Armada XP-DB board') which was merged in v3.11. Signed-off-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1397489361-5833-4-git-send-email-thomas.petazzoni@free-electrons.com Fixes: b484ff42df47 ('ARM: mvebu: Add support for NOR flash device on Armada XP-DB board') Cc: stable@vger.kernel.org # v3.11+ Acked-by: Ezequiel Garcia Acked-by: Gregory CLEMENT Signed-off-by: Jason Cooper --- arch/arm/boot/dts/armada-xp-db.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/armada-xp-db.dts b/arch/arm/boot/dts/armada-xp-db.dts index 448373c4b0e5..90f0bf6f9271 100644 --- a/arch/arm/boot/dts/armada-xp-db.dts +++ b/arch/arm/boot/dts/armada-xp-db.dts @@ -49,7 +49,7 @@ /* Device Bus parameters are required */ /* Read parameters */ - devbus,bus-width = <8>; + devbus,bus-width = <16>; devbus,turn-off-ps = <60000>; devbus,badr-skew-ps = <0>; devbus,acc-first-ps = <124000>; -- cgit v1.2.3 From 6e20bae8a39c40d4e03698e4160bad2d2629062b Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Mon, 14 Apr 2014 17:29:21 +0200 Subject: ARM: mvebu: fix NOR bus-width in Armada XP OpenBlocks AX3 Device Tree The mvebu-devbus driver had a serious bug, which lead to a 8 bits bus width declared in the Device Tree being considered as a 16 bits bus width when configuring the hardware. This bug in mvebu-devbus driver was compensated by a symetric mistake in the Armada XP OpenBlocks AX3 Device Tree: a 8 bits bus width was declared, even though the hardware actually has a 16 bits bus width connection with the NOR flash. Now that we have fixed the mvebu-devbus driver to behave according to its Device Tree binding, this commit fixes the problematic Device Tree files as well. This bug was introduced in commit a7d4f81821f7eec3175f8e23dd6949c71ab2da43 ('ARM: mvebu: Add support for NOR flash device on Openblocks AX3 board') which was merged in v3.10. Signed-off-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1397489361-5833-5-git-send-email-thomas.petazzoni@free-electrons.com Fixes: a7d4f81821f7 ('ARM: mvebu: Add support for NOR flash device on Openblocks AX3 board') Cc: stable@vger.kernel.org # v3.10+ Acked-by: Ezequiel Garcia Acked-by: Gregory CLEMENT Signed-off-by: Jason Cooper --- arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts b/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts index 985948ce67b3..5d42feb31049 100644 --- a/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts +++ b/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts @@ -39,7 +39,7 @@ /* Device Bus parameters are required */ /* Read parameters */ - devbus,bus-width = <8>; + devbus,bus-width = <16>; devbus,turn-off-ps = <60000>; devbus,badr-skew-ps = <0>; devbus,acc-first-ps = <124000>; -- cgit v1.2.3 From 80fa10f4e9278c4df1636a26025b12588078ad61 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Tue, 15 Apr 2014 15:50:21 +0200 Subject: ARM: mvebu: use qsgmii phy-mode for Armada XP GP interfaces The Armada XP GP isn't using rgmii-id connections between the MAC and PHY, but instead a single QSGMII connection, which is a quad-SGMII connection: a double pair of differential lines that are multiplexed to convey the traffic of four network interfaces between a MAC and a PHY. Until now, the Armada XP GP was relying on the bootloader setting the correct values in various configuration registers. With this change, the mvneta driver can be used as a module on this platform. Signed-off-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1397569821-5530-4-git-send-email-thomas.petazzoni@free-electrons.com Tested-by: Arnaud Ebalard Tested-by: Willy Tarreau Signed-off-by: Jason Cooper --- arch/arm/boot/dts/armada-xp-gp.dts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/armada-xp-gp.dts b/arch/arm/boot/dts/armada-xp-gp.dts index 3a359fdd19cc..0c756421ae6a 100644 --- a/arch/arm/boot/dts/armada-xp-gp.dts +++ b/arch/arm/boot/dts/armada-xp-gp.dts @@ -146,22 +146,22 @@ ethernet@70000 { status = "okay"; phy = <&phy0>; - phy-mode = "rgmii-id"; + phy-mode = "qsgmii"; }; ethernet@74000 { status = "okay"; phy = <&phy1>; - phy-mode = "rgmii-id"; + phy-mode = "qsgmii"; }; ethernet@30000 { status = "okay"; phy = <&phy2>; - phy-mode = "rgmii-id"; + phy-mode = "qsgmii"; }; ethernet@34000 { status = "okay"; phy = <&phy3>; - phy-mode = "rgmii-id"; + phy-mode = "qsgmii"; }; /* Front-side USB slot */ -- cgit v1.2.3 From ac164d1144f1a699d307bb05095e352ed6de236f Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Fri, 18 Apr 2014 09:41:44 +0200 Subject: ARM: mvebu: specify I2C bus frequency on Armada 370 DB In commit 249f3822509b74f8c8d0731aeb7ccea065376c9b ('ARM: mvebu: add audio support to Armada 370 DB'), the I2C bus 0 was enabled on the Armada 370 DB board, and an I2C codec was described as being connected on this bus. However, this commit forgot to define the I2C bus frequency, which leads the i2c-mv64xxx to fail probing, as it cannot calculate the baud rate multiplier/divisor to derive the I2C bus frequency from the core SoC frequency. It makes audio completely unusable, as the I2C bus is not probed, and therefore the audio codec is not probed either. Signed-off-by: Thomas Petazzoni Acked-by: Gregory CLEMENT Link: https://lkml.kernel.org/r/1397806908-7550-2-git-send-email-thomas.petazzoni@free-electrons.com Signed-off-by: Jason Cooper --- arch/arm/boot/dts/armada-370-db.dts | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/armada-370-db.dts b/arch/arm/boot/dts/armada-370-db.dts index 82f238a9063f..3383c4b66803 100644 --- a/arch/arm/boot/dts/armada-370-db.dts +++ b/arch/arm/boot/dts/armada-370-db.dts @@ -67,6 +67,7 @@ i2c@11000 { pinctrl-0 = <&i2c0_pins>; pinctrl-names = "default"; + clock-frequency = <100000>; status = "okay"; audio_codec: audio-codec@4a { compatible = "cirrus,cs42l51"; -- cgit v1.2.3 From d685058f5b878a71f99c8e2fd9707b3f49510b94 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Fri, 18 Apr 2014 09:41:45 +0200 Subject: ARM: mvebu: enable the SATA interface on Armada 375 DB The Armada 375 SoC has a dual-port SATA interface, which is exposed on the Armada 375 DB board. This commit therefore enables this interface on the Armada 375 DB board. Signed-off-by: Thomas Petazzoni Acked-by: Gregory CLEMENT Link: https://lkml.kernel.org/r/1397806908-7550-3-git-send-email-thomas.petazzoni@free-electrons.com Signed-off-by: Jason Cooper --- arch/arm/boot/dts/armada-375-db.dts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm/boot/dts/armada-375-db.dts b/arch/arm/boot/dts/armada-375-db.dts index 9378d3136b41..0451124e8ebf 100644 --- a/arch/arm/boot/dts/armada-375-db.dts +++ b/arch/arm/boot/dts/armada-375-db.dts @@ -79,6 +79,11 @@ }; }; + sata@a0000 { + status = "okay"; + nr-ports = <2>; + }; + nand: nand@d0000 { pinctrl-0 = <&nand_pins>; pinctrl-names = "default"; -- cgit v1.2.3 From e247686085f71e9c25e3488ce83d5d0f77023438 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Tue, 15 Apr 2014 14:40:08 +0200 Subject: ARM: Kirkwood: T5325: Fix double probe of Codec The codec is defined both in DT and the board file. The board file however contains platform data which is required in order that the codec works. When the DT instantiates the codec before the board files does, it is missing the platform data and so fails. Remove the DT node until we have a binding which can pass the additional data. Signed-off-by: Andrew Lunn Link: https://lkml.kernel.org/r/1397565608-1830-1-git-send-email-andrew@lunn.ch Signed-off-by: Jason Cooper --- arch/arm/boot/dts/kirkwood-t5325.dts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/arch/arm/boot/dts/kirkwood-t5325.dts b/arch/arm/boot/dts/kirkwood-t5325.dts index 7d1c7677a18f..0bd70d928c69 100644 --- a/arch/arm/boot/dts/kirkwood-t5325.dts +++ b/arch/arm/boot/dts/kirkwood-t5325.dts @@ -127,11 +127,6 @@ i2c@11000 { status = "okay"; - - alc5621: alc5621@1a { - compatible = "realtek,alc5621"; - reg = <0x1a>; - }; }; serial@12000 { -- cgit v1.2.3 From a3fe964135d0e4b925eaf4a5891c84daa7885c86 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Thu, 10 Apr 2014 14:19:05 +0800 Subject: imx-drm: imx-tve: correct DDC property name to 'ddc-i2c-bus' Commit 62e3879 (imx-drm: imx-tve: Fix DDC I2C bus property) was trying to use 'ddc-i2c-bus' as the DDC property name (we can see that from the commit log), but unfortunately 'i2c-ddc-bus' which is a typo was actually used in the code. This results in some unnecessary inconsistency and confusions, because all the documented DDC property in device tree bindings use 'ddc-i2c-bus'. Documentation/devicetree/bindings/staging/imx-drm/hdmi.txt Documentation/devicetree/bindings/panel/simple-panel.txt Documentation/devicetree/bindings/video/dvi-connector.txt Let's fix it before the error spreads. Signed-off-by: Shawn Guo Acked-by: Philipp Zabel Acked-by: Arnd Bergmann Signed-off-by: Russell King --- arch/arm/boot/dts/imx53-mba53.dts | 2 +- drivers/staging/imx-drm/imx-tve.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/imx53-mba53.dts b/arch/arm/boot/dts/imx53-mba53.dts index 7c8c12969892..a3431d784870 100644 --- a/arch/arm/boot/dts/imx53-mba53.dts +++ b/arch/arm/boot/dts/imx53-mba53.dts @@ -244,7 +244,7 @@ &tve { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_vga_sync_1>; - i2c-ddc-bus = <&i2c3>; + ddc-i2c-bus = <&i2c3>; fsl,tve-mode = "vga"; fsl,hsync-pin = <4>; fsl,vsync-pin = <6>; diff --git a/drivers/staging/imx-drm/imx-tve.c b/drivers/staging/imx-drm/imx-tve.c index 575533f4fd64..a23f4f773146 100644 --- a/drivers/staging/imx-drm/imx-tve.c +++ b/drivers/staging/imx-drm/imx-tve.c @@ -582,7 +582,7 @@ static int imx_tve_bind(struct device *dev, struct device *master, void *data) tve->dev = dev; spin_lock_init(&tve->lock); - ddc_node = of_parse_phandle(np, "i2c-ddc-bus", 0); + ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0); if (ddc_node) { tve->ddc = of_find_i2c_adapter_by_node(ddc_node); of_node_put(ddc_node); -- cgit v1.2.3 From 063aa8e68e53cc0d0961ea90c12cea40c6b94828 Mon Sep 17 00:00:00 2001 From: Julien Grall Date: Fri, 18 Apr 2014 16:54:34 +0100 Subject: arm/xen: Remove definiition of virt_to_pfn in asm/xen/page.h virt_to_pfn has been defined in asm/memory.h by the commit e26a9e0 "ARM: Better virt_to_page() handling" This will result of a compilation warning when CONFIG_XEN is enabled. arch/arm/include/asm/xen/page.h:80:0: warning: "virt_to_pfn" redefined [enabled by default] #define virt_to_pfn(v) (PFN_DOWN(__pa(v))) ^ In file included from arch/arm/include/asm/page.h:163:0, from arch/arm/include/asm/xen/page.h:4, from include/xen/page.h:4, from arch/arm/xen/grant-table.c:33: The definition in memory.h is nearly the same (it directly expand PFN_DOWN), so we can safely drop virt_to_pfn in xen include. Signed-off-by: Julien Grall Signed-off-by: David Vrabel --- arch/arm/include/asm/xen/page.h | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/include/asm/xen/page.h b/arch/arm/include/asm/xen/page.h index cf4f3e867395..ded062f9b358 100644 --- a/arch/arm/include/asm/xen/page.h +++ b/arch/arm/include/asm/xen/page.h @@ -77,7 +77,6 @@ static inline xpaddr_t machine_to_phys(xmaddr_t machine) } /* VIRT <-> MACHINE conversion */ #define virt_to_machine(v) (phys_to_machine(XPADDR(__pa(v)))) -#define virt_to_pfn(v) (PFN_DOWN(__pa(v))) #define virt_to_mfn(v) (pfn_to_mfn(virt_to_pfn(v))) #define mfn_to_virt(m) (__va(mfn_to_pfn(m) << PAGE_SHIFT)) -- cgit v1.2.3 From 05a812ac474d0d6aef6d54b66bb08b81abde79c6 Mon Sep 17 00:00:00 2001 From: Vladimir Murzin Date: Sun, 27 Apr 2014 10:09:12 +0100 Subject: xen/events/fifo: correctly align bitops FIFO event channels require bitops on 32-bit aligned values (the event words). Linux's bitops require unsigned long alignment which may be 64-bits. On arm64 an incorrectly unaligned access will fault. Fix this by aligning the bitops along with an adjustment for bit position and using an unsigned long for the local copy of the ready word. Cc: stable@vger.kernel.org Signed-off-by: Vladimir Murzin Tested-by: Pranavkumar Sawargaonkar Reviewed-by: Ian Campbell Signed-off-by: David Vrabel --- drivers/xen/events/events_fifo.c | 41 +++++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/drivers/xen/events/events_fifo.c b/drivers/xen/events/events_fifo.c index 96109a9972b6..84b4bfb84344 100644 --- a/drivers/xen/events/events_fifo.c +++ b/drivers/xen/events/events_fifo.c @@ -66,7 +66,22 @@ static DEFINE_PER_CPU(struct evtchn_fifo_queue, cpu_queue); static event_word_t *event_array[MAX_EVENT_ARRAY_PAGES] __read_mostly; static unsigned event_array_pages __read_mostly; +/* + * sync_set_bit() and friends must be unsigned long aligned on non-x86 + * platforms. + */ +#if !defined(CONFIG_X86) && BITS_PER_LONG > 32 + +#define BM(w) (unsigned long *)((unsigned long)w & ~0x7UL) +#define EVTCHN_FIFO_BIT(b, w) \ + (((unsigned long)w & 0x4UL) ? (EVTCHN_FIFO_ ##b + 32) : EVTCHN_FIFO_ ##b) + +#else + #define BM(w) ((unsigned long *)(w)) +#define EVTCHN_FIFO_BIT(b, w) EVTCHN_FIFO_ ##b + +#endif static inline event_word_t *event_word_from_port(unsigned port) { @@ -161,33 +176,38 @@ static void evtchn_fifo_bind_to_cpu(struct irq_info *info, unsigned cpu) static void evtchn_fifo_clear_pending(unsigned port) { event_word_t *word = event_word_from_port(port); - sync_clear_bit(EVTCHN_FIFO_PENDING, BM(word)); + sync_clear_bit(EVTCHN_FIFO_BIT(PENDING, word), BM(word)); } static void evtchn_fifo_set_pending(unsigned port) { event_word_t *word = event_word_from_port(port); - sync_set_bit(EVTCHN_FIFO_PENDING, BM(word)); + sync_set_bit(EVTCHN_FIFO_BIT(PENDING, word), BM(word)); } static bool evtchn_fifo_is_pending(unsigned port) { event_word_t *word = event_word_from_port(port); - return sync_test_bit(EVTCHN_FIFO_PENDING, BM(word)); + return sync_test_bit(EVTCHN_FIFO_BIT(PENDING, word), BM(word)); } static bool evtchn_fifo_test_and_set_mask(unsigned port) { event_word_t *word = event_word_from_port(port); - return sync_test_and_set_bit(EVTCHN_FIFO_MASKED, BM(word)); + return sync_test_and_set_bit(EVTCHN_FIFO_BIT(MASKED, word), BM(word)); } static void evtchn_fifo_mask(unsigned port) { event_word_t *word = event_word_from_port(port); - sync_set_bit(EVTCHN_FIFO_MASKED, BM(word)); + sync_set_bit(EVTCHN_FIFO_BIT(MASKED, word), BM(word)); } +static bool evtchn_fifo_is_masked(unsigned port) +{ + event_word_t *word = event_word_from_port(port); + return sync_test_bit(EVTCHN_FIFO_BIT(MASKED, word), BM(word)); +} /* * Clear MASKED, spinning if BUSY is set. */ @@ -211,7 +231,7 @@ static void evtchn_fifo_unmask(unsigned port) BUG_ON(!irqs_disabled()); clear_masked(word); - if (sync_test_bit(EVTCHN_FIFO_PENDING, BM(word))) { + if (evtchn_fifo_is_pending(port)) { struct evtchn_unmask unmask = { .port = port }; (void)HYPERVISOR_event_channel_op(EVTCHNOP_unmask, &unmask); } @@ -243,7 +263,7 @@ static void handle_irq_for_port(unsigned port) static void consume_one_event(unsigned cpu, struct evtchn_fifo_control_block *control_block, - unsigned priority, uint32_t *ready) + unsigned priority, unsigned long *ready) { struct evtchn_fifo_queue *q = &per_cpu(cpu_queue, cpu); uint32_t head; @@ -273,10 +293,9 @@ static void consume_one_event(unsigned cpu, * copy of the ready word. */ if (head == 0) - clear_bit(priority, BM(ready)); + clear_bit(priority, ready); - if (sync_test_bit(EVTCHN_FIFO_PENDING, BM(word)) - && !sync_test_bit(EVTCHN_FIFO_MASKED, BM(word))) + if (evtchn_fifo_is_pending(port) && !evtchn_fifo_is_masked(port)) handle_irq_for_port(port); q->head[priority] = head; @@ -285,7 +304,7 @@ static void consume_one_event(unsigned cpu, static void evtchn_fifo_handle_events(unsigned cpu) { struct evtchn_fifo_control_block *control_block; - uint32_t ready; + unsigned long ready; unsigned q; control_block = per_cpu(cpu_control_block, cpu); -- cgit v1.2.3 From 27c5fb7a84242b66bf1e0b2fe6bf40d19bcc5c04 Mon Sep 17 00:00:00 2001 From: Horia Geanta Date: Fri, 18 Apr 2014 13:01:42 +0300 Subject: crypto: caam - add allocation failure handling in SPRINTFCAT macro GFP_ATOMIC memory allocation could fail. In this case, avoid NULL pointer dereference and notify user. Cc: # 3.2+ Cc: Kim Phillips Signed-off-by: Horia Geanta Signed-off-by: Herbert Xu --- drivers/crypto/caam/error.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/crypto/caam/error.c b/drivers/crypto/caam/error.c index 9f25f5296029..0eabd81e1a90 100644 --- a/drivers/crypto/caam/error.c +++ b/drivers/crypto/caam/error.c @@ -16,9 +16,13 @@ char *tmp; \ \ tmp = kmalloc(sizeof(format) + max_alloc, GFP_ATOMIC); \ - sprintf(tmp, format, param); \ - strcat(str, tmp); \ - kfree(tmp); \ + if (likely(tmp)) { \ + sprintf(tmp, format, param); \ + strcat(str, tmp); \ + kfree(tmp); \ + } else { \ + strcat(str, "kmalloc failure in SPRINTFCAT"); \ + } \ } static void report_jump_idx(u32 status, char *outstr) -- cgit v1.2.3 From 1ad9f23873a4ee837643be5a29c05e405ec54e18 Mon Sep 17 00:00:00 2001 From: "pingfank@linux.vnet.ibm.com" Date: Tue, 15 Apr 2014 16:33:40 +0800 Subject: KVM: PPC: Book3S: HV: make _PAGE_NUMA take effect Numa fault is a method which help to achieve auto numa balancing. When such a page fault takes place, the page fault handler will check whether the page is placed correctly. If not, migration should be involved to cut down the distance between the cpu and pages. A pte with _PAGE_NUMA help to implement numa fault. It means not to allow the MMU to access the page directly. So a page fault is triggered and numa fault handler gets the opportunity to run checker. As for the access of MMU, we need special handling for the powernv's guest. When we mark a pte with _PAGE_NUMA, we already call mmu_notifier to invalidate it in guest's htab, but when we tried to re-insert them, we firstly try to map it in real-mode. Only after this fails, we fallback to virt mode, and most of important, we run numa fault handler in virt mode. This patch guards the way of real-mode to ensure that if a pte is marked with _PAGE_NUMA, it will NOT be mapped in real mode, instead, it will be mapped in virt mode and have the opportunity to be checked with placement. Signed-off-by: Liu Ping Fan Reviewed-by: Aneesh Kumar K.V Signed-off-by: Alexander Graf --- arch/powerpc/kvm/book3s_hv_rm_mmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/kvm/book3s_hv_rm_mmu.c b/arch/powerpc/kvm/book3s_hv_rm_mmu.c index 1d6c56ad5b60..8fcc36306a02 100644 --- a/arch/powerpc/kvm/book3s_hv_rm_mmu.c +++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c @@ -234,7 +234,7 @@ long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags, pte_size = psize; pte = lookup_linux_pte_and_update(pgdir, hva, writing, &pte_size); - if (pte_present(pte)) { + if (pte_present(pte) && !pte_numa(pte)) { if (writing && !pte_write(pte)) /* make the actual HPTE be read-only */ ptel = hpte_make_readonly(ptel); -- cgit v1.2.3 From 0a8eccefcb3423b45dc0a5a527b4799520e2bc94 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Mon, 14 Apr 2014 08:56:26 +1000 Subject: KVM: PPC: Book3S HV: Add missing code for transaction reclaim on guest exit Testing by Michael Neuling revealed that commit e4e38121507a ("KVM: PPC: Book3S HV: Add transactional memory support") is missing the code that saves away the checkpointed state of the guest when switching to the host. This adds that code, which was in earlier versions of the patch but went missing somehow. Reported-by: Michael Neuling Signed-off-by: Paul Mackerras Signed-off-by: Alexander Graf --- arch/powerpc/kvm/book3s_hv_rmhandlers.S | 104 ++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S index ffbb871c2bd8..0ff470170626 100644 --- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S +++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S @@ -1312,6 +1312,110 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206) mr r3, r9 bl kvmppc_save_fp +#ifdef CONFIG_PPC_TRANSACTIONAL_MEM +BEGIN_FTR_SECTION + b 2f +END_FTR_SECTION_IFCLR(CPU_FTR_TM) + /* Turn on TM. */ + mfmsr r8 + li r0, 1 + rldimi r8, r0, MSR_TM_LG, 63-MSR_TM_LG + mtmsrd r8 + + ld r5, VCPU_MSR(r9) + rldicl. r5, r5, 64 - MSR_TS_S_LG, 62 + beq 1f /* TM not active in guest. */ + + li r3, TM_CAUSE_KVM_RESCHED + + /* Clear the MSR RI since r1, r13 are all going to be foobar. */ + li r5, 0 + mtmsrd r5, 1 + + /* All GPRs are volatile at this point. */ + TRECLAIM(R3) + + /* Temporarily store r13 and r9 so we have some regs to play with */ + SET_SCRATCH0(r13) + GET_PACA(r13) + std r9, PACATMSCRATCH(r13) + ld r9, HSTATE_KVM_VCPU(r13) + + /* Get a few more GPRs free. */ + std r29, VCPU_GPRS_TM(29)(r9) + std r30, VCPU_GPRS_TM(30)(r9) + std r31, VCPU_GPRS_TM(31)(r9) + + /* Save away PPR and DSCR soon so don't run with user values. */ + mfspr r31, SPRN_PPR + HMT_MEDIUM + mfspr r30, SPRN_DSCR + ld r29, HSTATE_DSCR(r13) + mtspr SPRN_DSCR, r29 + + /* Save all but r9, r13 & r29-r31 */ + reg = 0 + .rept 29 + .if (reg != 9) && (reg != 13) + std reg, VCPU_GPRS_TM(reg)(r9) + .endif + reg = reg + 1 + .endr + /* ... now save r13 */ + GET_SCRATCH0(r4) + std r4, VCPU_GPRS_TM(13)(r9) + /* ... and save r9 */ + ld r4, PACATMSCRATCH(r13) + std r4, VCPU_GPRS_TM(9)(r9) + + /* Reload stack pointer and TOC. */ + ld r1, HSTATE_HOST_R1(r13) + ld r2, PACATOC(r13) + + /* Set MSR RI now we have r1 and r13 back. */ + li r5, MSR_RI + mtmsrd r5, 1 + + /* Save away checkpinted SPRs. */ + std r31, VCPU_PPR_TM(r9) + std r30, VCPU_DSCR_TM(r9) + mflr r5 + mfcr r6 + mfctr r7 + mfspr r8, SPRN_AMR + mfspr r10, SPRN_TAR + std r5, VCPU_LR_TM(r9) + stw r6, VCPU_CR_TM(r9) + std r7, VCPU_CTR_TM(r9) + std r8, VCPU_AMR_TM(r9) + std r10, VCPU_TAR_TM(r9) + + /* Restore r12 as trap number. */ + lwz r12, VCPU_TRAP(r9) + + /* Save FP/VSX. */ + addi r3, r9, VCPU_FPRS_TM + bl .store_fp_state + addi r3, r9, VCPU_VRS_TM + bl .store_vr_state + mfspr r6, SPRN_VRSAVE + stw r6, VCPU_VRSAVE_TM(r9) +1: + /* + * We need to save these SPRs after the treclaim so that the software + * error code is recorded correctly in the TEXASR. Also the user may + * change these outside of a transaction, so they must always be + * context switched. + */ + mfspr r5, SPRN_TFHAR + mfspr r6, SPRN_TFIAR + mfspr r7, SPRN_TEXASR + std r5, VCPU_TFHAR(r9) + std r6, VCPU_TFIAR(r9) + std r7, VCPU_TEXASR(r9) +2: +#endif + /* Increment yield count if they have a VPA */ ld r8, VCPU_VPA(r9) /* do they have a VPA? */ cmpdi r8, 0 -- cgit v1.2.3 From ab78475c76bd8c54375d8a778200c59314973d30 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Sun, 6 Apr 2014 23:31:48 +0200 Subject: KVM: PPC: Book3S: ifdef on CONFIG_KVM_BOOK3S_32_HANDLER for 32bit The book3s_32 target can get built as module which means we don't see the config define for it in code. Instead, check on the bool define CONFIG_KVM_BOOK3S_32_HANDLER whenever we want to know whether we're building for a book3s_32 host. This fixes running book3s_32 kvm as a module for me. Signed-off-by: Alexander Graf Reviewed-by: Aneesh Kumar K.V --- arch/powerpc/kvm/book3s.c | 6 +++--- arch/powerpc/kvm/book3s_pr.c | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c index 94e597e6f15c..7af190a266b3 100644 --- a/arch/powerpc/kvm/book3s.c +++ b/arch/powerpc/kvm/book3s.c @@ -886,7 +886,7 @@ static int kvmppc_book3s_init(void) r = kvm_init(NULL, sizeof(struct kvm_vcpu), 0, THIS_MODULE); if (r) return r; -#ifdef CONFIG_KVM_BOOK3S_32 +#ifdef CONFIG_KVM_BOOK3S_32_HANDLER r = kvmppc_book3s_init_pr(); #endif return r; @@ -895,7 +895,7 @@ static int kvmppc_book3s_init(void) static void kvmppc_book3s_exit(void) { -#ifdef CONFIG_KVM_BOOK3S_32 +#ifdef CONFIG_KVM_BOOK3S_32_HANDLER kvmppc_book3s_exit_pr(); #endif kvm_exit(); @@ -905,7 +905,7 @@ module_init(kvmppc_book3s_init); module_exit(kvmppc_book3s_exit); /* On 32bit this is our one and only kernel module */ -#ifdef CONFIG_KVM_BOOK3S_32 +#ifdef CONFIG_KVM_BOOK3S_32_HANDLER MODULE_ALIAS_MISCDEV(KVM_MINOR); MODULE_ALIAS("devname:kvm"); #endif diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c index c5c052a9729c..02f1defd8bb9 100644 --- a/arch/powerpc/kvm/book3s_pr.c +++ b/arch/powerpc/kvm/book3s_pr.c @@ -1153,7 +1153,7 @@ static struct kvm_vcpu *kvmppc_core_vcpu_create_pr(struct kvm *kvm, goto free_vcpu; vcpu->arch.book3s = vcpu_book3s; -#ifdef CONFIG_KVM_BOOK3S_32 +#ifdef CONFIG_KVM_BOOK3S_32_HANDLER vcpu->arch.shadow_vcpu = kzalloc(sizeof(*vcpu->arch.shadow_vcpu), GFP_KERNEL); if (!vcpu->arch.shadow_vcpu) @@ -1198,7 +1198,7 @@ static struct kvm_vcpu *kvmppc_core_vcpu_create_pr(struct kvm *kvm, uninit_vcpu: kvm_vcpu_uninit(vcpu); free_shadow_vcpu: -#ifdef CONFIG_KVM_BOOK3S_32 +#ifdef CONFIG_KVM_BOOK3S_32_HANDLER kfree(vcpu->arch.shadow_vcpu); free_vcpu3s: #endif @@ -1215,7 +1215,7 @@ static void kvmppc_core_vcpu_free_pr(struct kvm_vcpu *vcpu) free_page((unsigned long)vcpu->arch.shared & PAGE_MASK); kvm_vcpu_uninit(vcpu); -#ifdef CONFIG_KVM_BOOK3S_32 +#ifdef CONFIG_KVM_BOOK3S_32_HANDLER kfree(vcpu->arch.shadow_vcpu); #endif vfree(vcpu_book3s); -- cgit v1.2.3 From a38670459d6883582bc360ee480f9fcec4900162 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Fri, 18 Apr 2014 21:13:08 +0200 Subject: ARM: sun7i: Fix i2c4 base address For some reason, the base address of the fifth I2C adapter in the A20 was incorrect. Change this to the actual base address. Reported-by: Marcus Cooper Signed-off-by: Maxime Ripard Acked-by: Hans de Goede --- arch/arm/boot/dts/sun7i-a20.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi index c4f665f1b793..aba1c8a3f388 100644 --- a/arch/arm/boot/dts/sun7i-a20.dtsi +++ b/arch/arm/boot/dts/sun7i-a20.dtsi @@ -813,9 +813,9 @@ status = "disabled"; }; - i2c4: i2c@01c2bc00 { + i2c4: i2c@01c2c000 { compatible = "allwinner,sun4i-i2c"; - reg = <0x01c2bc00 0x400>; + reg = <0x01c2c000 0x400>; interrupts = <0 89 4>; clocks = <&apb1_gates 15>; clock-frequency = <100000>; -- cgit v1.2.3 From 98d7e1aee6dd534f468993f8c6a1bc730d4cfa81 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 21 Apr 2014 15:06:23 +0200 Subject: ARM: OMAP3: clock: Back-propagate rate change from cam_mclk to dpll4_m5 on all OMAP3 platforms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 7b2e1277598e4187c9be3e61fd9b0f0423f97986 ("ARM: OMAP3: clock: Back-propagate rate change from cam_mclk to dpll4_m5") enabled clock rate back-propagation from cam_mclk do dpll4_m5 on OMAP3630 only. Perform back-propagation on other OMAP3 platforms as well. Reported-by: Jean-Philippe François Signed-off-by: Laurent Pinchart Cc: Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/cclock3xxx_data.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/cclock3xxx_data.c b/arch/arm/mach-omap2/cclock3xxx_data.c index 8f5121b89688..eb8c75ec3b1a 100644 --- a/arch/arm/mach-omap2/cclock3xxx_data.c +++ b/arch/arm/mach-omap2/cclock3xxx_data.c @@ -456,7 +456,8 @@ static struct clk_hw_omap dpll4_m5x2_ck_hw = { .clkdm_name = "dpll4_clkdm", }; -DEFINE_STRUCT_CLK(dpll4_m5x2_ck, dpll4_m5x2_ck_parent_names, dpll4_m5x2_ck_ops); +DEFINE_STRUCT_CLK_FLAGS(dpll4_m5x2_ck, dpll4_m5x2_ck_parent_names, + dpll4_m5x2_ck_ops, CLK_SET_RATE_PARENT); static struct clk dpll4_m5x2_ck_3630 = { .name = "dpll4_m5x2_ck", -- cgit v1.2.3 From 61622cc6f29034d0479f7ac16f3d48f1eeabf3a1 Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Tue, 29 Apr 2014 07:50:44 +0200 Subject: xfrm4: Properly handle unsupported protocols We don't catch the case if an unsupported protocol is submitted to the xfrm4 protocol handlers, this can lead to NULL pointer dereferences. Fix this by adding the appropriate checks. Fixes: 3328715e ("xfrm4: Add IPsec protocol multiplexer") Signed-off-by: Steffen Klassert --- net/ipv4/xfrm4_protocol.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/net/ipv4/xfrm4_protocol.c b/net/ipv4/xfrm4_protocol.c index 7f7b243e8139..a2ce0101eaac 100644 --- a/net/ipv4/xfrm4_protocol.c +++ b/net/ipv4/xfrm4_protocol.c @@ -50,8 +50,12 @@ int xfrm4_rcv_cb(struct sk_buff *skb, u8 protocol, int err) { int ret; struct xfrm4_protocol *handler; + struct xfrm4_protocol __rcu **head = proto_handlers(protocol); - for_each_protocol_rcu(*proto_handlers(protocol), handler) + if (!head) + return 0; + + for_each_protocol_rcu(*head, handler) if ((ret = handler->cb_handler(skb, err)) <= 0) return ret; @@ -64,15 +68,20 @@ int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi, { int ret; struct xfrm4_protocol *handler; + struct xfrm4_protocol __rcu **head = proto_handlers(nexthdr); XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = NULL; XFRM_SPI_SKB_CB(skb)->family = AF_INET; XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct iphdr, daddr); - for_each_protocol_rcu(*proto_handlers(nexthdr), handler) + if (!head) + goto out; + + for_each_protocol_rcu(*head, handler) if ((ret = handler->input_handler(skb, nexthdr, spi, encap_type)) != -EINVAL) return ret; +out: icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); kfree_skb(skb); @@ -208,6 +217,9 @@ int xfrm4_protocol_register(struct xfrm4_protocol *handler, int ret = -EEXIST; int priority = handler->priority; + if (!proto_handlers(protocol) || !netproto(protocol)) + return -EINVAL; + mutex_lock(&xfrm4_protocol_mutex); if (!rcu_dereference_protected(*proto_handlers(protocol), @@ -250,6 +262,9 @@ int xfrm4_protocol_deregister(struct xfrm4_protocol *handler, struct xfrm4_protocol *t; int ret = -ENOENT; + if (!proto_handlers(protocol) || !netproto(protocol)) + return -EINVAL; + mutex_lock(&xfrm4_protocol_mutex); for (pprev = proto_handlers(protocol); -- cgit v1.2.3 From b18db0b80867931f4e3a844400a3c22a4fd2ff57 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Tue, 29 Apr 2014 12:17:26 +0200 Subject: KVM guest: Make pv trampoline code executable Our PV guest patching code assembles chunks of instructions on the fly when it encounters more complicated instructions to hijack. These instructions need to live in a section that we don't mark as non-executable, as otherwise we fault when jumping there. Right now we put it into the .bss section where it automatically gets marked as non-executable. Add a check to the NX setting function to ensure that we leave these particular pages executable. Signed-off-by: Alexander Graf --- arch/powerpc/include/asm/sections.h | 11 +++++++++++ arch/powerpc/kernel/kvm.c | 2 +- arch/powerpc/mm/hash_utils_64.c | 4 ++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/include/asm/sections.h b/arch/powerpc/include/asm/sections.h index d0e784e0ff48..521790330672 100644 --- a/arch/powerpc/include/asm/sections.h +++ b/arch/powerpc/include/asm/sections.h @@ -39,6 +39,17 @@ static inline int overlaps_kernel_text(unsigned long start, unsigned long end) (unsigned long)_stext < end; } +static inline int overlaps_kvm_tmp(unsigned long start, unsigned long end) +{ +#ifdef CONFIG_KVM_GUEST + extern char kvm_tmp[]; + return start < (unsigned long)kvm_tmp && + (unsigned long)&kvm_tmp[1024 * 1024] < end; +#else + return 0; +#endif +} + #undef dereference_function_descriptor static inline void *dereference_function_descriptor(void *ptr) { diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c index 6a0175297b0d..dd8695f6cb6d 100644 --- a/arch/powerpc/kernel/kvm.c +++ b/arch/powerpc/kernel/kvm.c @@ -74,7 +74,7 @@ #define KVM_INST_MTSRIN 0x7c0001e4 static bool kvm_patching_worked = true; -static char kvm_tmp[1024 * 1024]; +char kvm_tmp[1024 * 1024]; static int kvm_tmp_index; static inline void kvm_patch_ins(u32 *inst, u32 new_inst) diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index d766d6ee33fe..06ba83b036d3 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c @@ -207,6 +207,10 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend, if (overlaps_kernel_text(vaddr, vaddr + step)) tprot &= ~HPTE_R_N; + /* Make kvm guest trampolines executable */ + if (overlaps_kvm_tmp(vaddr, vaddr + step)) + tprot &= ~HPTE_R_N; + /* * If relocatable, check if it overlaps interrupt vectors that * are copied down to real 0. For relocatable kernel -- cgit v1.2.3 From cf7eb979116c2568e8bc3b6a7269c7a359864ace Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Sun, 13 Apr 2014 20:44:46 +0200 Subject: ARM: common: edma: Fix xbar mapping This is another great example of trainwreck engineering: commit 2646a0e529 (ARM: edma: Add EDMA crossbar event mux support) added support for using EDMA on peripherals which have no direct EDMA event mapping. The code compiles and does not explode in your face, but that's it. 1) Reading an u16 array from an u32 device tree array simply does not work. Even if the function is named "edma_of_read_u32_to_s16_array". It merily calls of_property_read_u16_array. So the resulting 16bit array will have every other entry = 0. 2) The DT entry for the xbar registers related to xbar has length 0x10 instead of the real length: 0xfd0 - 0xf90 = 0x40. Not a real problem as it does not cross a page boundary, but wrong nevertheless. 3) But none of this matters as the mapping never happens: After reading nonsense edma_of_read_u32_to_s16_array() invalidates the first array entry pair, so nobody can ever notice the braindamage by immediate explosion. Seems the QA criteria for this code was solely not to explode when someone adds edma-xbar-event-map entries to the DT. Goal achieved, congratulations! Not really helpful if someone wants to use edma on a device which requires a xbar mapping. Fix the issues by: - annotating the device tree entry with "/bits/ 16" as documented in the of_property_read_u16_array kernel doc - make the size of the xbar register mapping correct - invalidating the end of the array and not the start This convoluted mess wants to be completely rewritten as there is no point to keep the xbar_chan array memory and the iomapping of the xbar regs around forever. Marking the xbar mapped channels as used should be done right there. But that's a different issue and this patch is small enough to make it work and allows a simple backport for stable. Cc: stable@vger.kernel.org # v3.12+ Signed-off-by: Thomas Gleixner Signed-off-by: Sekhar Nori --- Documentation/devicetree/bindings/dma/ti-edma.txt | 4 +- arch/arm/boot/dts/am33xx.dtsi | 2 +- arch/arm/common/edma.c | 48 +++++++---------------- 3 files changed, 18 insertions(+), 36 deletions(-) diff --git a/Documentation/devicetree/bindings/dma/ti-edma.txt b/Documentation/devicetree/bindings/dma/ti-edma.txt index 9fbbdb783a72..68ff2137bae7 100644 --- a/Documentation/devicetree/bindings/dma/ti-edma.txt +++ b/Documentation/devicetree/bindings/dma/ti-edma.txt @@ -29,6 +29,6 @@ edma: edma@49000000 { dma-channels = <64>; ti,edma-regions = <4>; ti,edma-slots = <256>; - ti,edma-xbar-event-map = <1 12 - 2 13>; + ti,edma-xbar-event-map = /bits/ 16 <1 12 + 2 13>; }; diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi index 9770e35f2536..a23af78586d4 100644 --- a/arch/arm/boot/dts/am33xx.dtsi +++ b/arch/arm/boot/dts/am33xx.dtsi @@ -144,7 +144,7 @@ compatible = "ti,edma3"; ti,hwmods = "tpcc", "tptc0", "tptc1", "tptc2"; reg = <0x49000000 0x10000>, - <0x44e10f90 0x10>; + <0x44e10f90 0x40>; interrupts = <12 13 14>; #dma-cells = <1>; dma-channels = <64>; diff --git a/arch/arm/common/edma.c b/arch/arm/common/edma.c index 41bca32409fc..5339009b3c0c 100644 --- a/arch/arm/common/edma.c +++ b/arch/arm/common/edma.c @@ -1423,55 +1423,38 @@ EXPORT_SYMBOL(edma_clear_event); #if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_DMADEVICES) -static int edma_of_read_u32_to_s16_array(const struct device_node *np, - const char *propname, s16 *out_values, - size_t sz) +static int edma_xbar_event_map(struct device *dev, struct device_node *node, + struct edma_soc_info *pdata, size_t sz) { - int ret; - - ret = of_property_read_u16_array(np, propname, out_values, sz); - if (ret) - return ret; - - /* Terminate it */ - *out_values++ = -1; - *out_values++ = -1; - - return 0; -} - -static int edma_xbar_event_map(struct device *dev, - struct device_node *node, - struct edma_soc_info *pdata, int len) -{ - int ret, i; + const char pname[] = "ti,edma-xbar-event-map"; struct resource res; void __iomem *xbar; - const s16 (*xbar_chans)[2]; + s16 (*xbar_chans)[2]; + size_t nelm = sz / sizeof(s16); u32 shift, offset, mux; + int ret, i; - xbar_chans = devm_kzalloc(dev, - len/sizeof(s16) + 2*sizeof(s16), - GFP_KERNEL); + xbar_chans = devm_kzalloc(dev, (nelm + 2) * sizeof(s16), GFP_KERNEL); if (!xbar_chans) return -ENOMEM; ret = of_address_to_resource(node, 1, &res); if (ret) - return -EIO; + return -ENOMEM; xbar = devm_ioremap(dev, res.start, resource_size(&res)); if (!xbar) return -ENOMEM; - ret = edma_of_read_u32_to_s16_array(node, - "ti,edma-xbar-event-map", - (s16 *)xbar_chans, - len/sizeof(u32)); + ret = of_property_read_u16_array(node, pname, (u16 *)xbar_chans, nelm); if (ret) return -EIO; - for (i = 0; xbar_chans[i][0] != -1; i++) { + /* Invalidate last entry for the other user of this mess */ + nelm >>= 1; + xbar_chans[nelm][0] = xbar_chans[nelm][1] = -1; + + for (i = 0; i < nelm; i++) { shift = (xbar_chans[i][1] & 0x03) << 3; offset = xbar_chans[i][1] & 0xfffffffc; mux = readl(xbar + offset); @@ -1480,8 +1463,7 @@ static int edma_xbar_event_map(struct device *dev, writel(mux, (xbar + offset)); } - pdata->xbar_chans = xbar_chans; - + pdata->xbar_chans = (const s16 (*)[2]) xbar_chans; return 0; } -- cgit v1.2.3 From cfa7c862982b431add7f2b362526bf31372fc7b0 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 29 Apr 2014 11:53:58 +0200 Subject: drm/i915: Sanitize the enable_ppgtt module option once Otherwise we'll end up spamming dmesg on every context creation on snb with vt-d enabled. This regression was introduced in commit 246cbfb5fb9a1ca0997fbb135464c1ff5bb9c549 Author: Ben Widawsky Date: Fri Dec 6 14:11:14 2013 -0800 drm/i915: Reorganize intel_enable_ppgtt As the i915.enable_ppgtt is read-only it cannot be changed after the module is loaded and so we can perform an early sanitization of the values. v2: - Add comment and pimp commit message (Chris) - Use the param consistently (Jani) v3: - Fix init sequence on pre-gen6 by moving the sanitize_ppgtt call to gtt_init. Fixes boot hangs on pre-gen6. - Add a debug output for the sanitize ppgtt mode. References: https://lkml.org/lkml/2014/4/17/599 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=77916 Cc: Alessandro Suardi Cc: Ben Widawsky Cc: Chris Wilson Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_gem_gtt.c | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 62a5c3627b90..154b0f8bb88d 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -34,25 +34,35 @@ static void gen8_setup_private_ppat(struct drm_i915_private *dev_priv); bool intel_enable_ppgtt(struct drm_device *dev, bool full) { - if (i915.enable_ppgtt == 0 || !HAS_ALIASING_PPGTT(dev)) + if (i915.enable_ppgtt == 0) return false; if (i915.enable_ppgtt == 1 && full) return false; + return true; +} + +static int sanitize_enable_ppgtt(struct drm_device *dev, int enable_ppgtt) +{ + if (enable_ppgtt == 0 || !HAS_ALIASING_PPGTT(dev)) + return 0; + + if (enable_ppgtt == 1) + return 1; + + if (enable_ppgtt == 2 && HAS_PPGTT(dev)) + return 2; + #ifdef CONFIG_INTEL_IOMMU /* Disable ppgtt on SNB if VT-d is on. */ if (INTEL_INFO(dev)->gen == 6 && intel_iommu_gfx_mapped) { DRM_INFO("Disabling PPGTT because VT-d is on\n"); - return false; + return 0; } #endif - /* Full ppgtt disabled by default for now due to issues. */ - if (full) - return HAS_PPGTT(dev) && (i915.enable_ppgtt == 2); - else - return HAS_ALIASING_PPGTT(dev); + return HAS_ALIASING_PPGTT(dev) ? 1 : 0; } #define GEN6_PPGTT_PD_ENTRIES 512 @@ -2031,6 +2041,14 @@ int i915_gem_gtt_init(struct drm_device *dev) gtt->base.total >> 20); DRM_DEBUG_DRIVER("GMADR size = %ldM\n", gtt->mappable_end >> 20); DRM_DEBUG_DRIVER("GTT stolen size = %zdM\n", gtt->stolen_size >> 20); + /* + * i915.enable_ppgtt is read-only, so do an early pass to validate the + * user's requested state against the hardware/driver capabilities. We + * do this now so that we can print out any log messages once rather + * than every time we check intel_enable_ppgtt(). + */ + i915.enable_ppgtt = sanitize_enable_ppgtt(dev, i915.enable_ppgtt); + DRM_DEBUG_DRIVER("ppgtt mode: %i\n", i915.enable_ppgtt); return 0; } -- cgit v1.2.3 From fe337ac2839521b360f828b3ebd992d597b1ad16 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Mon, 28 Apr 2014 21:07:31 +0200 Subject: netfilter: ctnetlink: don't add null bindings if no nat requested commit 0eba801b64cc8284d9024c7ece30415a2b981a72 tried to fix a race where nat initialisation can happen after ctnetlink-created conntrack has been created. However, it causes the nat module(s) to be loaded needlessly on systems that are not using NAT. Fortunately, we do not have to create null bindings in that case. conntracks injected via ctnetlink always have the CONFIRMED bit set, which prevents addition of the nat extension in nf_nat_ipv4/6_fn(). We only need to make sure that either no nat extension is added or that we've created both src and dst manips. Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_conntrack_netlink.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index ccc46fa5edbc..58579634427d 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -1336,6 +1336,9 @@ ctnetlink_setup_nat(struct nf_conn *ct, const struct nlattr * const cda[]) #ifdef CONFIG_NF_NAT_NEEDED int ret; + if (!cda[CTA_NAT_DST] && !cda[CTA_NAT_SRC]) + return 0; + ret = ctnetlink_parse_nat_setup(ct, NF_NAT_MANIP_DST, cda[CTA_NAT_DST]); if (ret < 0) -- cgit v1.2.3 From 9bbfd20abe5025adbb0ac75160bd2e41158a9e83 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Tue, 29 Apr 2014 11:00:22 -0300 Subject: drm/i915: don't try DP_LINK_BW_5_4 on HSW ULX Because the docs say ULX doesn't support it on HSW. Reviewed-by: Dave Airlie Signed-off-by: Paulo Zanoni Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_drv.h | 3 +++ drivers/gpu/drm/i915/intel_dp.c | 3 ++- include/drm/i915_pciids.h | 4 ++-- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ec82f6bff122..108e1ec2fa4b 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1954,6 +1954,9 @@ struct drm_i915_cmd_table { #define IS_ULT(dev) (IS_HSW_ULT(dev) || IS_BDW_ULT(dev)) #define IS_HSW_GT3(dev) (IS_HASWELL(dev) && \ ((dev)->pdev->device & 0x00F0) == 0x0020) +/* ULX machines are also considered ULT. */ +#define IS_HSW_ULX(dev) ((dev)->pdev->device == 0x0A0E || \ + (dev)->pdev->device == 0x0A1E) #define IS_PRELIMINARY_HW(intel_info) ((intel_info)->is_preliminary) /* diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index dfa85289f28f..5ca68aa9f237 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -105,7 +105,8 @@ intel_dp_max_link_bw(struct intel_dp *intel_dp) case DP_LINK_BW_2_7: break; case DP_LINK_BW_5_4: /* 1.2 capable displays may advertise higher bw */ - if ((IS_HASWELL(dev) || INTEL_INFO(dev)->gen >= 8) && + if (((IS_HASWELL(dev) && !IS_HSW_ULX(dev)) || + INTEL_INFO(dev)->gen >= 8) && intel_dp->dpcd[DP_DPCD_REV] >= 0x12) max_link_bw = DP_LINK_BW_5_4; else diff --git a/include/drm/i915_pciids.h b/include/drm/i915_pciids.h index 940ece4934ba..012d58fa8ff0 100644 --- a/include/drm/i915_pciids.h +++ b/include/drm/i915_pciids.h @@ -191,8 +191,8 @@ INTEL_VGA_DEVICE(0x0A06, info), /* ULT GT1 mobile */ \ INTEL_VGA_DEVICE(0x0A16, info), /* ULT GT2 mobile */ \ INTEL_VGA_DEVICE(0x0A26, info), /* ULT GT3 mobile */ \ - INTEL_VGA_DEVICE(0x0A0E, info), /* ULT GT1 reserved */ \ - INTEL_VGA_DEVICE(0x0A1E, info), /* ULT GT2 reserved */ \ + INTEL_VGA_DEVICE(0x0A0E, info), /* ULX GT1 mobile */ \ + INTEL_VGA_DEVICE(0x0A1E, info), /* ULX GT2 mobile */ \ INTEL_VGA_DEVICE(0x0A2E, info), /* ULT GT3 reserved */ \ INTEL_VGA_DEVICE(0x0D06, info), /* CRW GT1 mobile */ \ INTEL_VGA_DEVICE(0x0D16, info), /* CRW GT2 mobile */ \ -- cgit v1.2.3 From 91943954e353fa56cc52a8e97346205afb9823ab Mon Sep 17 00:00:00 2001 From: Hui Wang Date: Wed, 30 Apr 2014 11:06:00 +0800 Subject: ALSA: hda - add headset mic detect quirk for a Dell laptop When we plug a 3-ring headset on the Dell machine (VID: 0x10ec0255, SID: 0x1028067e), the headset mic can't be detected, after apply this patch, the headset mic can work well. BugLink: https://bugs.launchpad.net/bugs/1297581 Cc: David Henningsson Cc: stable@vger.kernel.org Signed-off-by: Hui Wang Signed-off-by: Takashi Iwai --- 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 c1952c910339..5f7c765391f1 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4622,6 +4622,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1028, 0x0668, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x0669, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x0674, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1028, 0x067e, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x067f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x15cc, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x15cd, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE), -- cgit v1.2.3 From e813d49d2a477e3b64a9ff32ca7db5737d36cd91 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 7 Apr 2014 08:22:12 -0500 Subject: clk: bcm281xx: don't use unnamed structs or unions The Broadcom Kona clock code, as originally written, made use of unnamed union and struct fields. This is a feature present in C11, and is a GNU extension otherwise. It worked very well for me. Unfortunately, Russell King reported that this feature was not supported in a build environment he used, which meant attempting to build this code failed spectacularly. Add names to these unnamed fields, and update the code accordingly. Reported-by: Russell King Tested-by: Markus Mayer Signed-off-by: Alex Elder Signed-off-by: Mike Turquette --- drivers/clk/bcm/clk-kona-setup.c | 33 +++++++++++---------- drivers/clk/bcm/clk-kona.c | 64 +++++++++++++++++++++------------------- drivers/clk/bcm/clk-kona.h | 28 +++++++++--------- 3 files changed, 64 insertions(+), 61 deletions(-) diff --git a/drivers/clk/bcm/clk-kona-setup.c b/drivers/clk/bcm/clk-kona-setup.c index c7607feb18dd..54a06526f64f 100644 --- a/drivers/clk/bcm/clk-kona-setup.c +++ b/drivers/clk/bcm/clk-kona-setup.c @@ -27,7 +27,7 @@ LIST_HEAD(ccu_list); /* The list of set up CCUs */ static bool clk_requires_trigger(struct kona_clk *bcm_clk) { - struct peri_clk_data *peri = bcm_clk->peri; + struct peri_clk_data *peri = bcm_clk->u.peri; struct bcm_clk_sel *sel; struct bcm_clk_div *div; @@ -63,7 +63,7 @@ static bool peri_clk_data_offsets_valid(struct kona_clk *bcm_clk) u32 limit; BUG_ON(bcm_clk->type != bcm_clk_peri); - peri = bcm_clk->peri; + peri = bcm_clk->u.peri; name = bcm_clk->name; range = bcm_clk->ccu->range; @@ -81,19 +81,19 @@ static bool peri_clk_data_offsets_valid(struct kona_clk *bcm_clk) div = &peri->div; if (divider_exists(div)) { - if (div->offset > limit) { + if (div->u.s.offset > limit) { pr_err("%s: bad divider offset for %s (%u > %u)\n", - __func__, name, div->offset, limit); + __func__, name, div->u.s.offset, limit); return false; } } div = &peri->pre_div; if (divider_exists(div)) { - if (div->offset > limit) { + if (div->u.s.offset > limit) { pr_err("%s: bad pre-divider offset for %s " "(%u > %u)\n", - __func__, name, div->offset, limit); + __func__, name, div->u.s.offset, limit); return false; } } @@ -249,21 +249,22 @@ static bool div_valid(struct bcm_clk_div *div, const char *field_name, { if (divider_is_fixed(div)) { /* Any fixed divider value but 0 is OK */ - if (div->fixed == 0) { + if (div->u.fixed == 0) { pr_err("%s: bad %s fixed value 0 for %s\n", __func__, field_name, clock_name); return false; } return true; } - if (!bitfield_valid(div->shift, div->width, field_name, clock_name)) + if (!bitfield_valid(div->u.s.shift, div->u.s.width, + field_name, clock_name)) return false; if (divider_has_fraction(div)) - if (div->frac_width > div->width) { + if (div->u.s.frac_width > div->u.s.width) { pr_warn("%s: bad %s fraction width for %s (%u > %u)\n", __func__, field_name, clock_name, - div->frac_width, div->width); + div->u.s.frac_width, div->u.s.width); return false; } @@ -278,7 +279,7 @@ static bool div_valid(struct bcm_clk_div *div, const char *field_name, */ static bool kona_dividers_valid(struct kona_clk *bcm_clk) { - struct peri_clk_data *peri = bcm_clk->peri; + struct peri_clk_data *peri = bcm_clk->u.peri; struct bcm_clk_div *div; struct bcm_clk_div *pre_div; u32 limit; @@ -295,7 +296,7 @@ static bool kona_dividers_valid(struct kona_clk *bcm_clk) limit = BITS_PER_BYTE * sizeof(u32); - return div->frac_width + pre_div->frac_width <= limit; + return div->u.s.frac_width + pre_div->u.s.frac_width <= limit; } @@ -328,7 +329,7 @@ peri_clk_data_valid(struct kona_clk *bcm_clk) if (!peri_clk_data_offsets_valid(bcm_clk)) return false; - peri = bcm_clk->peri; + peri = bcm_clk->u.peri; name = bcm_clk->name; gate = &peri->gate; if (gate_exists(gate) && !gate_valid(gate, "gate", name)) @@ -588,12 +589,12 @@ static void bcm_clk_teardown(struct kona_clk *bcm_clk) { switch (bcm_clk->type) { case bcm_clk_peri: - peri_clk_teardown(bcm_clk->data, &bcm_clk->init_data); + peri_clk_teardown(bcm_clk->u.data, &bcm_clk->init_data); break; default: break; } - bcm_clk->data = NULL; + bcm_clk->u.data = NULL; bcm_clk->type = bcm_clk_none; } @@ -644,7 +645,7 @@ struct clk *kona_clk_setup(struct ccu_data *ccu, const char *name, break; } bcm_clk->type = type; - bcm_clk->data = data; + bcm_clk->u.data = data; /* Make sure everything makes sense before we set it up */ if (!kona_clk_valid(bcm_clk)) { diff --git a/drivers/clk/bcm/clk-kona.c b/drivers/clk/bcm/clk-kona.c index e3d339e08309..db11a87449f2 100644 --- a/drivers/clk/bcm/clk-kona.c +++ b/drivers/clk/bcm/clk-kona.c @@ -61,7 +61,7 @@ u64 do_div_round_closest(u64 dividend, unsigned long divisor) /* Convert a divider into the scaled divisor value it represents. */ static inline u64 scaled_div_value(struct bcm_clk_div *div, u32 reg_div) { - return (u64)reg_div + ((u64)1 << div->frac_width); + return (u64)reg_div + ((u64)1 << div->u.s.frac_width); } /* @@ -77,7 +77,7 @@ u64 scaled_div_build(struct bcm_clk_div *div, u32 div_value, u32 billionths) BUG_ON(billionths >= BILLION); combined = (u64)div_value * BILLION + billionths; - combined <<= div->frac_width; + combined <<= div->u.s.frac_width; return do_div_round_closest(combined, BILLION); } @@ -87,7 +87,7 @@ static inline u64 scaled_div_min(struct bcm_clk_div *div) { if (divider_is_fixed(div)) - return (u64)div->fixed; + return (u64)div->u.fixed; return scaled_div_value(div, 0); } @@ -98,9 +98,9 @@ u64 scaled_div_max(struct bcm_clk_div *div) u32 reg_div; if (divider_is_fixed(div)) - return (u64)div->fixed; + return (u64)div->u.fixed; - reg_div = ((u32)1 << div->width) - 1; + reg_div = ((u32)1 << div->u.s.width) - 1; return scaled_div_value(div, reg_div); } @@ -115,7 +115,7 @@ divider(struct bcm_clk_div *div, u64 scaled_div) BUG_ON(scaled_div < scaled_div_min(div)); BUG_ON(scaled_div > scaled_div_max(div)); - return (u32)(scaled_div - ((u64)1 << div->frac_width)); + return (u32)(scaled_div - ((u64)1 << div->u.s.frac_width)); } /* Return a rate scaled for use when dividing by a scaled divisor. */ @@ -125,7 +125,7 @@ scale_rate(struct bcm_clk_div *div, u32 rate) if (divider_is_fixed(div)) return (u64)rate; - return (u64)rate << div->frac_width; + return (u64)rate << div->u.s.frac_width; } /* CCU access */ @@ -398,14 +398,14 @@ static u64 divider_read_scaled(struct ccu_data *ccu, struct bcm_clk_div *div) u32 reg_div; if (divider_is_fixed(div)) - return (u64)div->fixed; + return (u64)div->u.fixed; flags = ccu_lock(ccu); - reg_val = __ccu_read(ccu, div->offset); + reg_val = __ccu_read(ccu, div->u.s.offset); ccu_unlock(ccu, flags); /* Extract the full divider field from the register value */ - reg_div = bitfield_extract(reg_val, div->shift, div->width); + reg_div = bitfield_extract(reg_val, div->u.s.shift, div->u.s.width); /* Return the scaled divisor value it represents */ return scaled_div_value(div, reg_div); @@ -433,16 +433,17 @@ static int __div_commit(struct ccu_data *ccu, struct bcm_clk_gate *gate, * state was defined in the device tree, we just find out * what its current value is rather than updating it. */ - if (div->scaled_div == BAD_SCALED_DIV_VALUE) { - reg_val = __ccu_read(ccu, div->offset); - reg_div = bitfield_extract(reg_val, div->shift, div->width); - div->scaled_div = scaled_div_value(div, reg_div); + if (div->u.s.scaled_div == BAD_SCALED_DIV_VALUE) { + reg_val = __ccu_read(ccu, div->u.s.offset); + reg_div = bitfield_extract(reg_val, div->u.s.shift, + div->u.s.width); + div->u.s.scaled_div = scaled_div_value(div, reg_div); return 0; } /* Convert the scaled divisor to the value we need to record */ - reg_div = divider(div, div->scaled_div); + reg_div = divider(div, div->u.s.scaled_div); /* Clock needs to be enabled before changing the rate */ enabled = __is_clk_gate_enabled(ccu, gate); @@ -452,9 +453,10 @@ static int __div_commit(struct ccu_data *ccu, struct bcm_clk_gate *gate, } /* Replace the divider value and record the result */ - reg_val = __ccu_read(ccu, div->offset); - reg_val = bitfield_replace(reg_val, div->shift, div->width, reg_div); - __ccu_write(ccu, div->offset, reg_val); + reg_val = __ccu_read(ccu, div->u.s.offset); + reg_val = bitfield_replace(reg_val, div->u.s.shift, div->u.s.width, + reg_div); + __ccu_write(ccu, div->u.s.offset, reg_val); /* If the trigger fails we still want to disable the gate */ if (!__clk_trigger(ccu, trig)) @@ -490,11 +492,11 @@ static int divider_write(struct ccu_data *ccu, struct bcm_clk_gate *gate, BUG_ON(divider_is_fixed(div)); - previous = div->scaled_div; + previous = div->u.s.scaled_div; if (previous == scaled_div) return 0; /* No change */ - div->scaled_div = scaled_div; + div->u.s.scaled_div = scaled_div; flags = ccu_lock(ccu); __ccu_write_enable(ccu); @@ -505,7 +507,7 @@ static int divider_write(struct ccu_data *ccu, struct bcm_clk_gate *gate, ccu_unlock(ccu, flags); if (ret) - div->scaled_div = previous; /* Revert the change */ + div->u.s.scaled_div = previous; /* Revert the change */ return ret; @@ -802,7 +804,7 @@ static int selector_write(struct ccu_data *ccu, struct bcm_clk_gate *gate, static int kona_peri_clk_enable(struct clk_hw *hw) { struct kona_clk *bcm_clk = to_kona_clk(hw); - struct bcm_clk_gate *gate = &bcm_clk->peri->gate; + struct bcm_clk_gate *gate = &bcm_clk->u.peri->gate; return clk_gate(bcm_clk->ccu, bcm_clk->name, gate, true); } @@ -810,7 +812,7 @@ static int kona_peri_clk_enable(struct clk_hw *hw) static void kona_peri_clk_disable(struct clk_hw *hw) { struct kona_clk *bcm_clk = to_kona_clk(hw); - struct bcm_clk_gate *gate = &bcm_clk->peri->gate; + struct bcm_clk_gate *gate = &bcm_clk->u.peri->gate; (void)clk_gate(bcm_clk->ccu, bcm_clk->name, gate, false); } @@ -818,7 +820,7 @@ static void kona_peri_clk_disable(struct clk_hw *hw) static int kona_peri_clk_is_enabled(struct clk_hw *hw) { struct kona_clk *bcm_clk = to_kona_clk(hw); - struct bcm_clk_gate *gate = &bcm_clk->peri->gate; + struct bcm_clk_gate *gate = &bcm_clk->u.peri->gate; return is_clk_gate_enabled(bcm_clk->ccu, gate) ? 1 : 0; } @@ -827,7 +829,7 @@ static unsigned long kona_peri_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct kona_clk *bcm_clk = to_kona_clk(hw); - struct peri_clk_data *data = bcm_clk->peri; + struct peri_clk_data *data = bcm_clk->u.peri; return clk_recalc_rate(bcm_clk->ccu, &data->div, &data->pre_div, parent_rate); @@ -837,20 +839,20 @@ static long kona_peri_clk_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *parent_rate) { struct kona_clk *bcm_clk = to_kona_clk(hw); - struct bcm_clk_div *div = &bcm_clk->peri->div; + struct bcm_clk_div *div = &bcm_clk->u.peri->div; if (!divider_exists(div)) return __clk_get_rate(hw->clk); /* Quietly avoid a zero rate */ - return round_rate(bcm_clk->ccu, div, &bcm_clk->peri->pre_div, + return round_rate(bcm_clk->ccu, div, &bcm_clk->u.peri->pre_div, rate ? rate : 1, *parent_rate, NULL); } static int kona_peri_clk_set_parent(struct clk_hw *hw, u8 index) { struct kona_clk *bcm_clk = to_kona_clk(hw); - struct peri_clk_data *data = bcm_clk->peri; + struct peri_clk_data *data = bcm_clk->u.peri; struct bcm_clk_sel *sel = &data->sel; struct bcm_clk_trig *trig; int ret; @@ -884,7 +886,7 @@ static int kona_peri_clk_set_parent(struct clk_hw *hw, u8 index) static u8 kona_peri_clk_get_parent(struct clk_hw *hw) { struct kona_clk *bcm_clk = to_kona_clk(hw); - struct peri_clk_data *data = bcm_clk->peri; + struct peri_clk_data *data = bcm_clk->u.peri; u8 index; index = selector_read_index(bcm_clk->ccu, &data->sel); @@ -897,7 +899,7 @@ static int kona_peri_clk_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { struct kona_clk *bcm_clk = to_kona_clk(hw); - struct peri_clk_data *data = bcm_clk->peri; + struct peri_clk_data *data = bcm_clk->u.peri; struct bcm_clk_div *div = &data->div; u64 scaled_div = 0; int ret; @@ -958,7 +960,7 @@ struct clk_ops kona_peri_clk_ops = { static bool __peri_clk_init(struct kona_clk *bcm_clk) { struct ccu_data *ccu = bcm_clk->ccu; - struct peri_clk_data *peri = bcm_clk->peri; + struct peri_clk_data *peri = bcm_clk->u.peri; const char *name = bcm_clk->name; struct bcm_clk_trig *trig; diff --git a/drivers/clk/bcm/clk-kona.h b/drivers/clk/bcm/clk-kona.h index 5e139adc3dc5..dee690951bb6 100644 --- a/drivers/clk/bcm/clk-kona.h +++ b/drivers/clk/bcm/clk-kona.h @@ -57,7 +57,7 @@ #define divider_exists(div) FLAG_TEST(div, DIV, EXISTS) #define divider_is_fixed(div) FLAG_TEST(div, DIV, FIXED) #define divider_has_fraction(div) (!divider_is_fixed(div) && \ - (div)->frac_width > 0) + (div)->u.s.frac_width > 0) #define selector_exists(sel) ((sel)->width != 0) #define trigger_exists(trig) FLAG_TEST(trig, TRIG, EXISTS) @@ -244,9 +244,9 @@ struct bcm_clk_div { u32 frac_width; /* field fraction width */ u64 scaled_div; /* scaled divider value */ - }; + } s; u32 fixed; /* non-zero fixed divider value */ - }; + } u; u32 flags; /* BCM_CLK_DIV_FLAGS_* below */ }; @@ -263,28 +263,28 @@ struct bcm_clk_div { /* A fixed (non-zero) divider */ #define FIXED_DIVIDER(_value) \ { \ - .fixed = (_value), \ + .u.fixed = (_value), \ .flags = FLAG(DIV, EXISTS)|FLAG(DIV, FIXED), \ } /* A divider with an integral divisor */ #define DIVIDER(_offset, _shift, _width) \ { \ - .offset = (_offset), \ - .shift = (_shift), \ - .width = (_width), \ - .scaled_div = BAD_SCALED_DIV_VALUE, \ + .u.s.offset = (_offset), \ + .u.s.shift = (_shift), \ + .u.s.width = (_width), \ + .u.s.scaled_div = BAD_SCALED_DIV_VALUE, \ .flags = FLAG(DIV, EXISTS), \ } /* A divider whose divisor has an integer and fractional part */ #define FRAC_DIVIDER(_offset, _shift, _width, _frac_width) \ { \ - .offset = (_offset), \ - .shift = (_shift), \ - .width = (_width), \ - .frac_width = (_frac_width), \ - .scaled_div = BAD_SCALED_DIV_VALUE, \ + .u.s.offset = (_offset), \ + .u.s.shift = (_shift), \ + .u.s.width = (_width), \ + .u.s.frac_width = (_frac_width), \ + .u.s.scaled_div = BAD_SCALED_DIV_VALUE, \ .flags = FLAG(DIV, EXISTS), \ } @@ -380,7 +380,7 @@ struct kona_clk { union { void *data; struct peri_clk_data *peri; - }; + } u; }; #define to_kona_clk(_hw) \ container_of(_hw, struct kona_clk, hw) -- cgit v1.2.3 From dd23c2cd38da2c64af381b19795d2c4f115e8ecb Mon Sep 17 00:00:00 2001 From: Maxime COQUELIN Date: Wed, 29 Jan 2014 17:24:06 +0100 Subject: clk: divider: Fix best div calculation for power-of-two and table dividers The divider returned by clk_divider_bestdiv() is likely to be invalid in case of power-of-two and table dividers when CLK_SET_RATE_PARENT flag isn't set. Fixes boot on STiH416 platform. Signed-off-by: Maxime Coquelin Signed-off-by: Mike Turquette [mturquette@linaro.org: trivial merge conflict & updated changelog] --- drivers/clk/clk-divider.c | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index ec22112e569f..4637697c139f 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -144,6 +144,37 @@ static bool _is_valid_div(struct clk_divider *divider, unsigned int div) return true; } +static int _round_up_table(const struct clk_div_table *table, int div) +{ + const struct clk_div_table *clkt; + int up = _get_table_maxdiv(table); + + for (clkt = table; clkt->div; clkt++) { + if (clkt->div == div) + return clkt->div; + else if (clkt->div < div) + continue; + + if ((clkt->div - div) < (up - div)) + up = clkt->div; + } + + return up; +} + +static int _div_round_up(struct clk_divider *divider, + unsigned long parent_rate, unsigned long rate) +{ + int div = DIV_ROUND_UP(parent_rate, rate); + + if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) + div = __roundup_pow_of_two(div); + if (divider->table) + div = _round_up_table(divider->table, div); + + return div; +} + static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate, unsigned long *best_parent_rate) { @@ -159,7 +190,7 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate, if (!(__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT)) { parent_rate = *best_parent_rate; - bestdiv = DIV_ROUND_UP(parent_rate, rate); + bestdiv = _div_round_up(divider, parent_rate, rate); bestdiv = bestdiv == 0 ? 1 : bestdiv; bestdiv = bestdiv > maxdiv ? maxdiv : bestdiv; return bestdiv; @@ -219,6 +250,10 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, u32 val; div = DIV_ROUND_UP(parent_rate, rate); + + if (!_is_valid_div(divider, div)) + return -EINVAL; + value = _get_val(divider, div); if (value > div_mask(divider)) -- cgit v1.2.3 From a30d27ed739b2c6662f07c76e5deea7bc916bd12 Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Mon, 14 Apr 2014 07:59:32 -0500 Subject: clk: socfpga: fix clock driver for 3.15 commit [1771b10d6 clk: respect the clock dependencies in of_clk_init] exposed a flaw in the socfpga clock driver and prevents the platform from booting on 3.15-rc1. Because the "altr,clk-mgr" is not really a clock, it should not be using CLK_OF_DECLARE, instead we should be mapping the clk-mgr's base address one of the functional clock init function. Use the socfpga_pll_init function to map the clk_mgr_base_addr as this clock should always be initialized first. Signed-off-by: Dinh Nguyen Tested-by: Pavel Machek --- drivers/clk/socfpga/clk-pll.c | 7 +++++++ drivers/clk/socfpga/clk.c | 23 +++-------------------- 2 files changed, 10 insertions(+), 20 deletions(-) diff --git a/drivers/clk/socfpga/clk-pll.c b/drivers/clk/socfpga/clk-pll.c index 88dafb5e9627..de6da957a09d 100644 --- a/drivers/clk/socfpga/clk-pll.c +++ b/drivers/clk/socfpga/clk-pll.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "clk.h" @@ -43,6 +44,8 @@ #define to_socfpga_clk(p) container_of(p, struct socfpga_pll, hw.hw) +void __iomem *clk_mgr_base_addr; + static unsigned long clk_pll_recalc_rate(struct clk_hw *hwclk, unsigned long parent_rate) { @@ -87,6 +90,7 @@ static __init struct clk *__socfpga_pll_init(struct device_node *node, const char *clk_name = node->name; const char *parent_name[SOCFPGA_MAX_PARENTS]; struct clk_init_data init; + struct device_node *clkmgr_np; int rc; int i = 0; @@ -96,6 +100,9 @@ static __init struct clk *__socfpga_pll_init(struct device_node *node, if (WARN_ON(!pll_clk)) return NULL; + clkmgr_np = of_find_compatible_node(NULL, NULL, "altr,clk-mgr"); + clk_mgr_base_addr = of_iomap(clkmgr_np, 0); + BUG_ON(!clk_mgr_base_addr); pll_clk->hw.reg = clk_mgr_base_addr + reg; of_property_read_string(node, "clock-output-names", &clk_name); diff --git a/drivers/clk/socfpga/clk.c b/drivers/clk/socfpga/clk.c index 35a960a993f9..43db947e5f0e 100644 --- a/drivers/clk/socfpga/clk.c +++ b/drivers/clk/socfpga/clk.c @@ -17,28 +17,11 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -#include -#include -#include -#include #include -#include #include "clk.h" -void __iomem *clk_mgr_base_addr; - -static const struct of_device_id socfpga_child_clocks[] __initconst = { - { .compatible = "altr,socfpga-pll-clock", socfpga_pll_init, }, - { .compatible = "altr,socfpga-perip-clk", socfpga_periph_init, }, - { .compatible = "altr,socfpga-gate-clk", socfpga_gate_init, }, - {}, -}; - -static void __init socfpga_clkmgr_init(struct device_node *node) -{ - clk_mgr_base_addr = of_iomap(node, 0); - of_clk_init(socfpga_child_clocks); -} -CLK_OF_DECLARE(socfpga_mgr, "altr,clk-mgr", socfpga_clkmgr_init); +CLK_OF_DECLARE(socfpga_pll_clk, "altr,socfpga-pll-clock", socfpga_pll_init); +CLK_OF_DECLARE(socfpga_perip_clk, "altr,socfpga-perip-clk", socfpga_periph_init); +CLK_OF_DECLARE(socfpga_gate_clk, "altr,socfpga-gate-clk", socfpga_gate_init); -- cgit v1.2.3 From 293ba3b4a4fd54891b900f2911d1a57e1ed4a843 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Fri, 18 Apr 2014 16:29:42 -0700 Subject: clk: Fix double free due to devm_clk_register() Now that clk_unregister() frees the struct clk we're unregistering we'll free memory twice: first we'll call kfree() in __clk_release() with an address kmalloc doesn't know about and second we'll call kfree() in the devres layer. Remove the allocation of struct clk in devm_clk_register() and let clk_release() handle it. This fixes slab errors like: ============================================================================= BUG kmalloc-128 (Not tainted): Invalid object pointer 0xed08e8d0 ----------------------------------------------------------------------------- Disabling lock debugging due to kernel taint INFO: Slab 0xeec503f8 objects=25 used=15 fp=0xed08ea00 flags=0x4081 CPU: 2 PID: 73 Comm: rmmod Tainted: G B 3.14.0-11032-g526e9c764381 #34 [] (unwind_backtrace) from [] (show_stack+0x10/0x14) [] (show_stack) from [] (dump_stack+0x70/0xbc) [] (dump_stack) from [] (slab_err+0x74/0x84) [] (slab_err) from [] (free_debug_processing+0x2cc/0x31c) [] (free_debug_processing) from [] (__slab_free+0x38/0x41c) [] (__slab_free) from [] (clk_unregister+0xd4/0x140) [] (clk_unregister) from [] (release_nodes+0x164/0x1d8) [] (release_nodes) from [] (__device_release_driver+0x60/0xb0) [] (__device_release_driver) from [] (driver_detach+0xb4/0xb8) [] (driver_detach) from [] (bus_remove_driver+0x5c/0xc4) [] (bus_remove_driver) from [] (SyS_delete_module+0x148/0x1d8) [] (SyS_delete_module) from [] (ret_fast_syscall+0x0/0x48) FIX kmalloc-128: Object at 0xed08e8d0 not freed Fixes: fcb0ee6a3d33 (clk: Implement clk_unregister) Cc: Jiada Wang Cc: Sylwester Nawrocki Cc: Kyungmin Park Signed-off-by: Stephen Boyd Signed-off-by: Mike Turquette Cc: stable@vger.kernel.org --- drivers/clk/clk.c | 71 +++++++++++++++++++++++-------------------------------- 1 file changed, 30 insertions(+), 41 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index dff0373f53c1..f71093bf83ab 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -1984,9 +1984,28 @@ struct clk *__clk_register(struct device *dev, struct clk_hw *hw) } EXPORT_SYMBOL_GPL(__clk_register); -static int _clk_register(struct device *dev, struct clk_hw *hw, struct clk *clk) +/** + * clk_register - allocate a new clock, register it and return an opaque cookie + * @dev: device that is registering this clock + * @hw: link to hardware-specific clock data + * + * clk_register is the primary interface for populating the clock tree with new + * clock nodes. It returns a pointer to the newly allocated struct clk which + * cannot be dereferenced by driver code but may be used in conjuction with the + * rest of the clock API. In the event of an error clk_register will return an + * error code; drivers must test for an error code after calling clk_register. + */ +struct clk *clk_register(struct device *dev, struct clk_hw *hw) { int i, ret; + struct clk *clk; + + clk = kzalloc(sizeof(*clk), GFP_KERNEL); + if (!clk) { + pr_err("%s: could not allocate clk\n", __func__); + ret = -ENOMEM; + goto fail_out; + } clk->name = kstrdup(hw->init->name, GFP_KERNEL); if (!clk->name) { @@ -2026,7 +2045,7 @@ static int _clk_register(struct device *dev, struct clk_hw *hw, struct clk *clk) ret = __clk_init(dev, clk); if (!ret) - return 0; + return clk; fail_parent_names_copy: while (--i >= 0) @@ -2035,36 +2054,6 @@ fail_parent_names_copy: fail_parent_names: kfree(clk->name); fail_name: - return ret; -} - -/** - * clk_register - allocate a new clock, register it and return an opaque cookie - * @dev: device that is registering this clock - * @hw: link to hardware-specific clock data - * - * clk_register is the primary interface for populating the clock tree with new - * clock nodes. It returns a pointer to the newly allocated struct clk which - * cannot be dereferenced by driver code but may be used in conjuction with the - * rest of the clock API. In the event of an error clk_register will return an - * error code; drivers must test for an error code after calling clk_register. - */ -struct clk *clk_register(struct device *dev, struct clk_hw *hw) -{ - int ret; - struct clk *clk; - - clk = kzalloc(sizeof(*clk), GFP_KERNEL); - if (!clk) { - pr_err("%s: could not allocate clk\n", __func__); - ret = -ENOMEM; - goto fail_out; - } - - ret = _clk_register(dev, hw, clk); - if (!ret) - return clk; - kfree(clk); fail_out: return ERR_PTR(ret); @@ -2173,7 +2162,7 @@ EXPORT_SYMBOL_GPL(clk_unregister); static void devm_clk_release(struct device *dev, void *res) { - clk_unregister(res); + clk_unregister(*(struct clk **)res); } /** @@ -2188,18 +2177,18 @@ static void devm_clk_release(struct device *dev, void *res) struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw) { struct clk *clk; - int ret; + struct clk **clkp; - clk = devres_alloc(devm_clk_release, sizeof(*clk), GFP_KERNEL); - if (!clk) + clkp = devres_alloc(devm_clk_release, sizeof(*clkp), GFP_KERNEL); + if (!clkp) return ERR_PTR(-ENOMEM); - ret = _clk_register(dev, hw, clk); - if (!ret) { - devres_add(dev, clk); + clk = clk_register(dev, hw); + if (!IS_ERR(clk)) { + *clkp = clk; + devres_add(dev, clkp); } else { - devres_free(clk); - clk = ERR_PTR(ret); + devres_free(clkp); } return clk; -- cgit v1.2.3 From 874f224cc52d64c912087e68e3724be95ad80ee7 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Fri, 18 Apr 2014 16:29:43 -0700 Subject: clk: Fix slab corruption in clk_unregister() When a clock is unregsitered, we iterate over the list of children and reparent them to NULL (i.e. orphan list). While iterating the list, we should use the safe iterators because the children list for this clock is changing when we reparent the children to NULL. Failure to iterate safely can lead to slab corruption like this: ============================================================================= BUG kmalloc-128 (Not tainted): Poison overwritten ----------------------------------------------------------------------------- Disabling lock debugging due to kernel taint INFO: 0xed0c4900-0xed0c4903. First byte 0x0 instead of 0x6b INFO: Allocated in clk_register+0x20/0x1bc age=297 cpu=2 pid=70 __slab_alloc.isra.39.constprop.42+0x410/0x454 kmem_cache_alloc_trace+0x200/0x24c clk_register+0x20/0x1bc devm_clk_register+0x34/0x68 0xbf0000f0 platform_drv_probe+0x18/0x48 driver_probe_device+0x94/0x360 __driver_attach+0x94/0x98 bus_for_each_dev+0x54/0x88 bus_add_driver+0xe8/0x204 driver_register+0x78/0xf4 do_one_initcall+0xc4/0x17c load_module+0x19ac/0x2294 SyS_init_module+0xa4/0x110 ret_fast_syscall+0x0/0x48 INFO: Freed in clk_unregister+0xd4/0x140 age=23 cpu=2 pid=73 __slab_free+0x38/0x41c clk_unregister+0xd4/0x140 release_nodes+0x164/0x1d8 __device_release_driver+0x60/0xb0 driver_detach+0xb4/0xb8 bus_remove_driver+0x5c/0xc4 SyS_delete_module+0x148/0x1d8 ret_fast_syscall+0x0/0x48 INFO: Slab 0xeec50b90 objects=25 used=0 fp=0xed0c5400 flags=0x4080 INFO: Object 0xed0c48c0 @offset=2240 fp=0xed0c4a00 Bytes b4 ed0c48b0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a ZZZZZZZZZZZZZZZZ Object ed0c48c0: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b kkkkkkkkkkkkkkkk Object ed0c48d0: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b kkkkkkkkkkkkkkkk Object ed0c48e0: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b kkkkkkkkkkkkkkkk Object ed0c48f0: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b kkkkkkkkkkkkkkkk Object ed0c4900: 00 00 00 00 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b ....kkkkkkkkkkkk Object ed0c4910: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b kkkkkkkkkkkkkkkk Object ed0c4920: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b kkkkkkkkkkkkkkkk Object ed0c4930: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b a5 kkkkkkkkkkkkkkk. Redzone ed0c4940: bb bb bb bb .... Padding ed0c49e8: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a ZZZZZZZZZZZZZZZZ Padding ed0c49f8: 5a 5a 5a 5a 5a 5a 5a 5a ZZZZZZZZ CPU: 3 PID: 75 Comm: mdev Tainted: G B 3.14.0-11033-g2054ba5ca781 #35 [] (unwind_backtrace) from [] (show_stack+0x10/0x14) [] (show_stack) from [] (dump_stack+0x70/0xbc) [] (dump_stack) from [] (check_bytes_and_report+0xbc/0x100) [] (check_bytes_and_report) from [] (check_object+0x18c/0x218) [] (check_object) from [] (__free_slab+0x104/0x144) [] (__free_slab) from [] (__slab_free+0x3dc/0x41c) [] (__slab_free) from [] (load_elf_binary+0x88/0x12b4) [] (load_elf_binary) from [] (search_binary_handler+0x78/0x18c) [] (search_binary_handler) from [] (do_execve+0x490/0x5dc) [] (do_execve) from [] (____call_usermodehelper+0x134/0x168) [] (____call_usermodehelper) from [] (ret_from_fork+0x14/0x2c) FIX kmalloc-128: Restoring 0xed0c4900-0xed0c4903=0x6b Fixes: fcb0ee6a3d33 (clk: Implement clk_unregister) Cc: Jiada Wang Cc: Sylwester Nawrocki Cc: Kyungmin Park Signed-off-by: Stephen Boyd Signed-off-by: Mike Turquette Cc: stable@vger.kernel.org --- drivers/clk/clk.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index f71093bf83ab..7cf2c093cc54 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -2140,9 +2140,10 @@ void clk_unregister(struct clk *clk) if (!hlist_empty(&clk->children)) { struct clk *child; + struct hlist_node *t; /* Reparent all children to the orphan list. */ - hlist_for_each_entry(child, &clk->children, child_node) + hlist_for_each_entry_safe(child, t, &clk->children, child_node) clk_set_parent(child, NULL); } -- cgit v1.2.3 From 28c015a9daabe4ed3aeb0ccf669a3f1c2b8b81d5 Mon Sep 17 00:00:00 2001 From: Murali Karicheri Date: Thu, 20 Mar 2014 22:08:32 +0200 Subject: mtd: davinci-nand: disable subpage write for keystone-nand Sub page write doesn't work because of hw issue in controller found on Keystone SOCs. AEMIF controller is also used on DaVinci SOCs which don't seems to have any issue. So add "ti,keysone-nand" compatible to nand driver in order to set NAND_NO_SUBPAGE_WRITE option. Cc: Warner Losh Signed-off-by: Murali Karicheri Signed-off-by: Ivan Khoronzhuk Acked-by: Santosh Shilimkar Signed-off-by: Brian Norris --- drivers/mtd/nand/davinci_nand.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c index 4615d79fc93f..b922c8efcf40 100644 --- a/drivers/mtd/nand/davinci_nand.c +++ b/drivers/mtd/nand/davinci_nand.c @@ -523,6 +523,7 @@ static struct nand_ecclayout hwecc4_2048 = { #if defined(CONFIG_OF) static const struct of_device_id davinci_nand_of_match[] = { {.compatible = "ti,davinci-nand", }, + {.compatible = "ti,keystone-nand", }, {}, }; MODULE_DEVICE_TABLE(of, davinci_nand_of_match); @@ -581,6 +582,11 @@ static struct davinci_nand_pdata of_property_read_bool(pdev->dev.of_node, "ti,davinci-nand-use-bbt")) pdata->bbt_options = NAND_BBT_USE_FLASH; + + if (of_device_is_compatible(pdev->dev.of_node, + "ti,keystone-nand")) { + pdata->options |= NAND_NO_SUBPAGE_WRITE; + } } return dev_get_platdata(&pdev->dev); -- cgit v1.2.3 From e45187620f9fc103edf68fa5ea78e73033e1668c Mon Sep 17 00:00:00 2001 From: Christian König Date: Thu, 10 Apr 2014 16:11:36 +0200 Subject: drm/radeon/uvd: use lower clocks on old UVD to boot v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some RV7xx generation hardware crashes after you raise the UVD clocks for the first time. Try to avoid this by using the lower clocks to boot these. Workaround for: https://bugzilla.kernel.org/show_bug.cgi?id=71891 v2: lower clocks on IB test as well Signed-off-by: Christian König Reviewed-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/uvd_v1_0.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/uvd_v1_0.c b/drivers/gpu/drm/radeon/uvd_v1_0.c index 0a243f0e5d68..be42c8125203 100644 --- a/drivers/gpu/drm/radeon/uvd_v1_0.c +++ b/drivers/gpu/drm/radeon/uvd_v1_0.c @@ -83,7 +83,10 @@ int uvd_v1_0_init(struct radeon_device *rdev) int r; /* raise clocks while booting up the VCPU */ - radeon_set_uvd_clocks(rdev, 53300, 40000); + if (rdev->family < CHIP_RV740) + radeon_set_uvd_clocks(rdev, 10000, 10000); + else + radeon_set_uvd_clocks(rdev, 53300, 40000); r = uvd_v1_0_start(rdev); if (r) @@ -407,7 +410,10 @@ int uvd_v1_0_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) struct radeon_fence *fence = NULL; int r; - r = radeon_set_uvd_clocks(rdev, 53300, 40000); + if (rdev->family < CHIP_RV740) + r = radeon_set_uvd_clocks(rdev, 10000, 10000); + else + r = radeon_set_uvd_clocks(rdev, 53300, 40000); if (r) { DRM_ERROR("radeon: failed to raise UVD clocks (%d).\n", r); return r; -- cgit v1.2.3 From f5d636d2a74b755879feec35e14a259de52ccc07 Mon Sep 17 00:00:00 2001 From: Christian König Date: Wed, 23 Apr 2014 20:46:06 +0200 Subject: drm/radeon: use pflip irq on R600+ v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Testing the update pending bit directly after issuing an update is nonsense cause depending on the pixel clock the CRTC needs a bit of time to execute the flip even when we are in the VBLANK period. This is just a non invasive patch to solve the problem at hand, a more complete and cleaner solution should follow in the next merge window. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=76564 v2: fix source IDs for CRTC2-6 Signed-off-by: Christian König Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/cik.c | 76 +++++++++++++++++++++++++++++++++ drivers/gpu/drm/radeon/cikd.h | 9 ++++ drivers/gpu/drm/radeon/evergreen.c | 28 +++++++++--- drivers/gpu/drm/radeon/r600.c | 13 ++++-- drivers/gpu/drm/radeon/radeon.h | 6 +++ drivers/gpu/drm/radeon/radeon_display.c | 4 ++ drivers/gpu/drm/radeon/si.c | 28 +++++++++--- 7 files changed, 147 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 199eb194716f..421c6084cbfc 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -6693,6 +6693,19 @@ static void cik_disable_interrupt_state(struct radeon_device *rdev) WREG32(LB_INTERRUPT_MASK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); WREG32(LB_INTERRUPT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); } + /* pflip */ + if (rdev->num_crtc >= 2) { + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); + } + if (rdev->num_crtc >= 4) { + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); + } + if (rdev->num_crtc >= 6) { + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); + } /* dac hotplug */ WREG32(DAC_AUTODETECT_INT_CONTROL, 0); @@ -7049,6 +7062,25 @@ int cik_irq_set(struct radeon_device *rdev) WREG32(LB_INTERRUPT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, crtc6); } + if (rdev->num_crtc >= 2) { + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, + GRPH_PFLIP_INT_MASK); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, + GRPH_PFLIP_INT_MASK); + } + if (rdev->num_crtc >= 4) { + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, + GRPH_PFLIP_INT_MASK); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, + GRPH_PFLIP_INT_MASK); + } + if (rdev->num_crtc >= 6) { + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, + GRPH_PFLIP_INT_MASK); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, + GRPH_PFLIP_INT_MASK); + } + WREG32(DC_HPD1_INT_CONTROL, hpd1); WREG32(DC_HPD2_INT_CONTROL, hpd2); WREG32(DC_HPD3_INT_CONTROL, hpd3); @@ -7085,6 +7117,29 @@ static inline void cik_irq_ack(struct radeon_device *rdev) rdev->irq.stat_regs.cik.disp_int_cont5 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE5); rdev->irq.stat_regs.cik.disp_int_cont6 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE6); + rdev->irq.stat_regs.cik.d1grph_int = RREG32(GRPH_INT_STATUS + + EVERGREEN_CRTC0_REGISTER_OFFSET); + rdev->irq.stat_regs.cik.d2grph_int = RREG32(GRPH_INT_STATUS + + EVERGREEN_CRTC1_REGISTER_OFFSET); + if (rdev->num_crtc >= 4) { + rdev->irq.stat_regs.cik.d3grph_int = RREG32(GRPH_INT_STATUS + + EVERGREEN_CRTC2_REGISTER_OFFSET); + rdev->irq.stat_regs.cik.d4grph_int = RREG32(GRPH_INT_STATUS + + EVERGREEN_CRTC3_REGISTER_OFFSET); + } + if (rdev->num_crtc >= 6) { + rdev->irq.stat_regs.cik.d5grph_int = RREG32(GRPH_INT_STATUS + + EVERGREEN_CRTC4_REGISTER_OFFSET); + rdev->irq.stat_regs.cik.d6grph_int = RREG32(GRPH_INT_STATUS + + EVERGREEN_CRTC5_REGISTER_OFFSET); + } + + if (rdev->irq.stat_regs.cik.d1grph_int & GRPH_PFLIP_INT_OCCURRED) + WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, + GRPH_PFLIP_INT_CLEAR); + if (rdev->irq.stat_regs.cik.d2grph_int & GRPH_PFLIP_INT_OCCURRED) + WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, + GRPH_PFLIP_INT_CLEAR); if (rdev->irq.stat_regs.cik.disp_int & LB_D1_VBLANK_INTERRUPT) WREG32(LB_VBLANK_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, VBLANK_ACK); if (rdev->irq.stat_regs.cik.disp_int & LB_D1_VLINE_INTERRUPT) @@ -7095,6 +7150,12 @@ static inline void cik_irq_ack(struct radeon_device *rdev) WREG32(LB_VLINE_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, VLINE_ACK); if (rdev->num_crtc >= 4) { + if (rdev->irq.stat_regs.cik.d3grph_int & GRPH_PFLIP_INT_OCCURRED) + WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, + GRPH_PFLIP_INT_CLEAR); + if (rdev->irq.stat_regs.cik.d4grph_int & GRPH_PFLIP_INT_OCCURRED) + WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, + GRPH_PFLIP_INT_CLEAR); if (rdev->irq.stat_regs.cik.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT) WREG32(LB_VBLANK_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, VBLANK_ACK); if (rdev->irq.stat_regs.cik.disp_int_cont2 & LB_D3_VLINE_INTERRUPT) @@ -7106,6 +7167,12 @@ static inline void cik_irq_ack(struct radeon_device *rdev) } if (rdev->num_crtc >= 6) { + if (rdev->irq.stat_regs.cik.d5grph_int & GRPH_PFLIP_INT_OCCURRED) + WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, + GRPH_PFLIP_INT_CLEAR); + if (rdev->irq.stat_regs.cik.d6grph_int & GRPH_PFLIP_INT_OCCURRED) + WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, + GRPH_PFLIP_INT_CLEAR); if (rdev->irq.stat_regs.cik.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT) WREG32(LB_VBLANK_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, VBLANK_ACK); if (rdev->irq.stat_regs.cik.disp_int_cont4 & LB_D5_VLINE_INTERRUPT) @@ -7457,6 +7524,15 @@ restart_ih: break; } break; + case 8: /* D1 page flip */ + case 10: /* D2 page flip */ + case 12: /* D3 page flip */ + case 14: /* D4 page flip */ + case 16: /* D5 page flip */ + case 18: /* D6 page flip */ + DRM_DEBUG("IH: D%d flip\n", ((src_id - 8) >> 1) + 1); + radeon_crtc_handle_flip(rdev, (src_id - 8) >> 1); + break; case 42: /* HPD hotplug */ switch (src_data) { case 0: diff --git a/drivers/gpu/drm/radeon/cikd.h b/drivers/gpu/drm/radeon/cikd.h index 213873270d5f..dd7926394a8f 100644 --- a/drivers/gpu/drm/radeon/cikd.h +++ b/drivers/gpu/drm/radeon/cikd.h @@ -888,6 +888,15 @@ # define DC_HPD6_RX_INTERRUPT (1 << 18) #define DISP_INTERRUPT_STATUS_CONTINUE6 0x6780 +/* 0x6858, 0x7458, 0x10058, 0x10c58, 0x11858, 0x12458 */ +#define GRPH_INT_STATUS 0x6858 +# define GRPH_PFLIP_INT_OCCURRED (1 << 0) +# define GRPH_PFLIP_INT_CLEAR (1 << 8) +/* 0x685c, 0x745c, 0x1005c, 0x10c5c, 0x1185c, 0x1245c */ +#define GRPH_INT_CONTROL 0x685c +# define GRPH_PFLIP_INT_MASK (1 << 0) +# define GRPH_PFLIP_INT_TYPE (1 << 8) + #define DAC_AUTODETECT_INT_CONTROL 0x67c8 #define DC_HPD1_INT_STATUS 0x601c diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index b406546440da..0f7a51a3694f 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -4371,7 +4371,6 @@ int evergreen_irq_set(struct radeon_device *rdev) u32 crtc1 = 0, crtc2 = 0, crtc3 = 0, crtc4 = 0, crtc5 = 0, crtc6 = 0; u32 hpd1, hpd2, hpd3, hpd4, hpd5, hpd6; u32 grbm_int_cntl = 0; - u32 grph1 = 0, grph2 = 0, grph3 = 0, grph4 = 0, grph5 = 0, grph6 = 0; u32 afmt1 = 0, afmt2 = 0, afmt3 = 0, afmt4 = 0, afmt5 = 0, afmt6 = 0; u32 dma_cntl, dma_cntl1 = 0; u32 thermal_int = 0; @@ -4554,15 +4553,21 @@ int evergreen_irq_set(struct radeon_device *rdev) WREG32(INT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, crtc6); } - WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, grph1); - WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, grph2); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, + GRPH_PFLIP_INT_MASK); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, + GRPH_PFLIP_INT_MASK); if (rdev->num_crtc >= 4) { - WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, grph3); - WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, grph4); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, + GRPH_PFLIP_INT_MASK); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, + GRPH_PFLIP_INT_MASK); } if (rdev->num_crtc >= 6) { - WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, grph5); - WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, grph6); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, + GRPH_PFLIP_INT_MASK); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, + GRPH_PFLIP_INT_MASK); } WREG32(DC_HPD1_INT_CONTROL, hpd1); @@ -4951,6 +4956,15 @@ restart_ih: break; } break; + case 8: /* D1 page flip */ + case 10: /* D2 page flip */ + case 12: /* D3 page flip */ + case 14: /* D4 page flip */ + case 16: /* D5 page flip */ + case 18: /* D6 page flip */ + DRM_DEBUG("IH: D%d flip\n", ((src_id - 8) >> 1) + 1); + radeon_crtc_handle_flip(rdev, (src_id - 8) >> 1); + break; case 42: /* HPD hotplug */ switch (src_data) { case 0: diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 6e887d004eba..6c4699362bca 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -3505,7 +3505,6 @@ int r600_irq_set(struct radeon_device *rdev) u32 hpd1, hpd2, hpd3, hpd4 = 0, hpd5 = 0, hpd6 = 0; u32 grbm_int_cntl = 0; u32 hdmi0, hdmi1; - u32 d1grph = 0, d2grph = 0; u32 dma_cntl; u32 thermal_int = 0; @@ -3614,8 +3613,8 @@ int r600_irq_set(struct radeon_device *rdev) WREG32(CP_INT_CNTL, cp_int_cntl); WREG32(DMA_CNTL, dma_cntl); WREG32(DxMODE_INT_MASK, mode_int); - WREG32(D1GRPH_INTERRUPT_CONTROL, d1grph); - WREG32(D2GRPH_INTERRUPT_CONTROL, d2grph); + WREG32(D1GRPH_INTERRUPT_CONTROL, DxGRPH_PFLIP_INT_MASK); + WREG32(D2GRPH_INTERRUPT_CONTROL, DxGRPH_PFLIP_INT_MASK); WREG32(GRBM_INT_CNTL, grbm_int_cntl); if (ASIC_IS_DCE3(rdev)) { WREG32(DC_HPD1_INT_CONTROL, hpd1); @@ -3918,6 +3917,14 @@ restart_ih: break; } break; + case 9: /* D1 pflip */ + DRM_DEBUG("IH: D1 flip\n"); + radeon_crtc_handle_flip(rdev, 0); + break; + case 11: /* D2 pflip */ + DRM_DEBUG("IH: D2 flip\n"); + radeon_crtc_handle_flip(rdev, 1); + break; case 19: /* HPD/DAC hotplug */ switch (src_data) { case 0: diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index b58e1afdda76..68528619834a 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -730,6 +730,12 @@ struct cik_irq_stat_regs { u32 disp_int_cont4; u32 disp_int_cont5; u32 disp_int_cont6; + u32 d1grph_int; + u32 d2grph_int; + u32 d3grph_int; + u32 d4grph_int; + u32 d5grph_int; + u32 d6grph_int; }; union radeon_irq_stat_regs { diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 8d99d5ee8014..14bd701e316c 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -284,6 +284,10 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id) u32 update_pending; int vpos, hpos; + /* can happen during initialization */ + if (radeon_crtc == NULL) + return; + spin_lock_irqsave(&rdev->ddev->event_lock, flags); work = radeon_crtc->unpin_work; if (work == NULL || diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index ac708e006180..22a63c98ba14 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -5780,7 +5780,6 @@ int si_irq_set(struct radeon_device *rdev) u32 crtc1 = 0, crtc2 = 0, crtc3 = 0, crtc4 = 0, crtc5 = 0, crtc6 = 0; u32 hpd1 = 0, hpd2 = 0, hpd3 = 0, hpd4 = 0, hpd5 = 0, hpd6 = 0; u32 grbm_int_cntl = 0; - u32 grph1 = 0, grph2 = 0, grph3 = 0, grph4 = 0, grph5 = 0, grph6 = 0; u32 dma_cntl, dma_cntl1; u32 thermal_int = 0; @@ -5919,16 +5918,22 @@ int si_irq_set(struct radeon_device *rdev) } if (rdev->num_crtc >= 2) { - WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, grph1); - WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, grph2); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, + GRPH_PFLIP_INT_MASK); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, + GRPH_PFLIP_INT_MASK); } if (rdev->num_crtc >= 4) { - WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, grph3); - WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, grph4); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, + GRPH_PFLIP_INT_MASK); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, + GRPH_PFLIP_INT_MASK); } if (rdev->num_crtc >= 6) { - WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, grph5); - WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, grph6); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, + GRPH_PFLIP_INT_MASK); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, + GRPH_PFLIP_INT_MASK); } if (!ASIC_IS_NODCE(rdev)) { @@ -6292,6 +6297,15 @@ restart_ih: break; } break; + case 8: /* D1 page flip */ + case 10: /* D2 page flip */ + case 12: /* D3 page flip */ + case 14: /* D4 page flip */ + case 16: /* D5 page flip */ + case 18: /* D6 page flip */ + DRM_DEBUG("IH: D%d flip\n", ((src_id - 8) >> 1) + 1); + radeon_crtc_handle_flip(rdev, (src_id - 8) >> 1); + break; case 42: /* HPD hotplug */ switch (src_data) { case 0: -- cgit v1.2.3 From 695daf1a8e731a4b5b89de89a61f32a4d7ad7094 Mon Sep 17 00:00:00 2001 From: Leo Liu Date: Mon, 28 Apr 2014 09:40:22 -0400 Subject: drm/radeon: check buffer relocation offset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Leo Liu Signed-off-by: Christian König Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/radeon_uvd.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c index 5748bdaeacce..0f96c471c6d8 100644 --- a/drivers/gpu/drm/radeon/radeon_uvd.c +++ b/drivers/gpu/drm/radeon/radeon_uvd.c @@ -465,6 +465,10 @@ static int radeon_uvd_cs_reloc(struct radeon_cs_parser *p, cmd = radeon_get_ib_value(p, p->idx) >> 1; if (cmd < 0x4) { + if (end <= start) { + DRM_ERROR("invalid reloc offset %X!\n", offset); + return -EINVAL; + } if ((end - start) < buf_sizes[cmd]) { DRM_ERROR("buffer (%d) to small (%d / %d)!\n", cmd, (unsigned)(end - start), buf_sizes[cmd]); -- cgit v1.2.3 From 3b333c55485fef0089ae7398906599d000df195e Mon Sep 17 00:00:00 2001 From: Christian König Date: Thu, 24 Apr 2014 18:39:59 +0200 Subject: drm/radeon: avoid high jitter with small frac divs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- drivers/gpu/drm/radeon/radeon_display.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 14bd701e316c..9ff0e2f1be6a 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -830,14 +830,14 @@ static void avivo_reduce_ratio(unsigned *nom, unsigned *den, /* make sure nominator is large enough */ if (*nom < nom_min) { - tmp = (nom_min + *nom - 1) / *nom; + tmp = DIV_ROUND_UP(nom_min, *nom); *nom *= tmp; *den *= tmp; } /* make sure the denominator is large enough */ if (*den < den_min) { - tmp = (den_min + *den - 1) / *den; + tmp = DIV_ROUND_UP(den_min, *den); *nom *= tmp; *den *= tmp; } @@ -997,6 +997,16 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll, /* this also makes sure that the reference divider is large enough */ avivo_reduce_ratio(&fb_div, &ref_div, fb_div_min, ref_div_min); + /* avoid high jitter with small fractional dividers */ + if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV && (fb_div % 10)) { + fb_div_min = max(fb_div_min, (9 - (fb_div % 10)) * 20 + 60); + if (fb_div < fb_div_min) { + unsigned tmp = DIV_ROUND_UP(fb_div_min, fb_div); + fb_div *= tmp; + ref_div *= tmp; + } + } + /* and finally save the result */ if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV) { *fb_div_p = fb_div / 10; -- cgit v1.2.3 From aa019b791a3e138ca0eaa38e72b4ea97d482a7bc Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 30 Apr 2014 09:27:15 -0400 Subject: drm/radeon/dp: check for errors in dpcd reads MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Check to make sure the transaction succeeded before using the register value. Fixes occasional link training problems. Noticed-by: Sergei Antonov Signed-off-by: Alex Deucher Signed-off-by: Christian König --- drivers/gpu/drm/radeon/atombios_dp.c | 44 ++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c index bc0119fb6c12..54e4f52549af 100644 --- a/drivers/gpu/drm/radeon/atombios_dp.c +++ b/drivers/gpu/drm/radeon/atombios_dp.c @@ -366,11 +366,11 @@ static void radeon_dp_probe_oui(struct radeon_connector *radeon_connector) if (!(dig_connector->dpcd[DP_DOWN_STREAM_PORT_COUNT] & DP_OUI_SUPPORT)) return; - if (drm_dp_dpcd_read(&radeon_connector->ddc_bus->aux, DP_SINK_OUI, buf, 3)) + if (drm_dp_dpcd_read(&radeon_connector->ddc_bus->aux, DP_SINK_OUI, buf, 3) == 3) DRM_DEBUG_KMS("Sink OUI: %02hx%02hx%02hx\n", buf[0], buf[1], buf[2]); - if (drm_dp_dpcd_read(&radeon_connector->ddc_bus->aux, DP_BRANCH_OUI, buf, 3)) + if (drm_dp_dpcd_read(&radeon_connector->ddc_bus->aux, DP_BRANCH_OUI, buf, 3) == 3) DRM_DEBUG_KMS("Branch OUI: %02hx%02hx%02hx\n", buf[0], buf[1], buf[2]); } @@ -419,21 +419,23 @@ int radeon_dp_get_panel_mode(struct drm_encoder *encoder, if (dp_bridge != ENCODER_OBJECT_ID_NONE) { /* DP bridge chips */ - drm_dp_dpcd_readb(&radeon_connector->ddc_bus->aux, - DP_EDP_CONFIGURATION_CAP, &tmp); - if (tmp & 1) - panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; - else if ((dp_bridge == ENCODER_OBJECT_ID_NUTMEG) || - (dp_bridge == ENCODER_OBJECT_ID_TRAVIS)) - panel_mode = DP_PANEL_MODE_INTERNAL_DP1_MODE; - else - panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE; + if (drm_dp_dpcd_readb(&radeon_connector->ddc_bus->aux, + DP_EDP_CONFIGURATION_CAP, &tmp) == 1) { + if (tmp & 1) + panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; + else if ((dp_bridge == ENCODER_OBJECT_ID_NUTMEG) || + (dp_bridge == ENCODER_OBJECT_ID_TRAVIS)) + panel_mode = DP_PANEL_MODE_INTERNAL_DP1_MODE; + else + panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE; + } } else if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { /* eDP */ - drm_dp_dpcd_readb(&radeon_connector->ddc_bus->aux, - DP_EDP_CONFIGURATION_CAP, &tmp); - if (tmp & 1) - panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; + if (drm_dp_dpcd_readb(&radeon_connector->ddc_bus->aux, + DP_EDP_CONFIGURATION_CAP, &tmp) == 1) { + if (tmp & 1) + panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; + } } return panel_mode; @@ -809,11 +811,15 @@ void radeon_dp_link_train(struct drm_encoder *encoder, else dp_info.enc_id |= ATOM_DP_CONFIG_LINK_A; - drm_dp_dpcd_readb(&radeon_connector->ddc_bus->aux, DP_MAX_LANE_COUNT, &tmp); - if (ASIC_IS_DCE5(rdev) && (tmp & DP_TPS3_SUPPORTED)) - dp_info.tp3_supported = true; - else + if (drm_dp_dpcd_readb(&radeon_connector->ddc_bus->aux, DP_MAX_LANE_COUNT, &tmp) + == 1) { + if (ASIC_IS_DCE5(rdev) && (tmp & DP_TPS3_SUPPORTED)) + dp_info.tp3_supported = true; + else + dp_info.tp3_supported = false; + } else { dp_info.tp3_supported = false; + } memcpy(dp_info.dpcd, dig_connector->dpcd, DP_RECEIVER_CAP_SIZE); dp_info.rdev = rdev; -- cgit v1.2.3 From e6a623460e5fc960ac3ee9f946d3106233fd28d8 Mon Sep 17 00:00:00 2001 From: Salva Peiró Date: Wed, 30 Apr 2014 19:48:02 +0200 Subject: [media] media-device: fix infoleak in ioctl media_enum_entities() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes CVE-2014-1739. Signed-off-by: Salva Peiró Acked-by: Laurent Pinchart Cc: stable@vger.kernel.org Signed-off-by: Mauro Carvalho Chehab --- drivers/media/media-device.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c index d5a7a135f75d..703560fa5e73 100644 --- a/drivers/media/media-device.c +++ b/drivers/media/media-device.c @@ -93,6 +93,7 @@ static long media_device_enum_entities(struct media_device *mdev, struct media_entity *ent; struct media_entity_desc u_ent; + memset(&u_ent, 0, sizeof(u_ent)); if (copy_from_user(&u_ent.id, &uent->id, sizeof(u_ent.id))) return -EFAULT; -- cgit v1.2.3 From 84e108fc7b23310fb6d93a657e47181d64ab6e93 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 28 Apr 2014 11:44:36 -0700 Subject: ARM: sunxi: Enable GMAC in sunxi_defconfig Since the support of the GMAC has been merged, we're using it as the ethernet controller on the A20 devices. However, sunxi_defconfig wasn't selecting it hence breaking the NFS boot. Signed-off-by: Maxime Ripard --- arch/arm/configs/sunxi_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/configs/sunxi_defconfig b/arch/arm/configs/sunxi_defconfig index b5df4a511b0a..81ba78eaf54a 100644 --- a/arch/arm/configs/sunxi_defconfig +++ b/arch/arm/configs/sunxi_defconfig @@ -37,7 +37,7 @@ CONFIG_SUN4I_EMAC=y # CONFIG_NET_VENDOR_NATSEMI is not set # CONFIG_NET_VENDOR_SEEQ is not set # CONFIG_NET_VENDOR_SMSC is not set -# CONFIG_NET_VENDOR_STMICRO is not set +CONFIG_STMMAC_ETH=y # CONFIG_NET_VENDOR_WIZNET is not set # CONFIG_WLAN is not set CONFIG_SERIAL_8250=y -- cgit v1.2.3 From a3d0b1218d351c6e6f3cea36abe22236a08cb246 Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Wed, 26 Mar 2014 19:37:21 -0400 Subject: drm/nouveau/acpi: allow non-optimus setups to load vbios from acpi There appear to be a crop of new hardware where the vbios is not available from PROM/PRAMIN, but there is a valid _ROM method in ACPI. The data read from PCIROM almost invariably contains invalid instructions (still has the x86 opcodes), which makes this a low-risk way to try to obtain a valid vbios image. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=76475 Signed-off-by: Ilia Mirkin Cc: # v2.6.35+ Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_acpi.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c index 83face3f608f..279206997e5c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c @@ -389,9 +389,6 @@ bool nouveau_acpi_rom_supported(struct pci_dev *pdev) acpi_status status; acpi_handle dhandle, rom_handle; - if (!nouveau_dsm_priv.dsm_detected && !nouveau_dsm_priv.optimus_detected) - return false; - dhandle = ACPI_HANDLE(&pdev->dev); if (!dhandle) return false; -- cgit v1.2.3 From ce23b234d157f1dfea098fcc77cb5b6887d10df2 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 31 Mar 2014 13:25:09 +1000 Subject: drm/nouveau/bios: fix shadowing from PROM on big-endian systems Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/subdev/bios/base.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c index e9df94f96d78..3de7d818be76 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c @@ -168,7 +168,8 @@ nouveau_bios_shadow_prom(struct nouveau_bios *bios) */ i = 16; do { - if ((nv_rd32(bios, 0x300000) & 0xffff) == 0xaa55) + u32 data = le32_to_cpu(nv_rd32(bios, 0x300000)) & 0xffff; + if (data == 0xaa55) break; } while (i--); @@ -176,14 +177,15 @@ nouveau_bios_shadow_prom(struct nouveau_bios *bios) goto out; /* read entire bios image to system memory */ - bios->size = ((nv_rd32(bios, 0x300000) >> 16) & 0xff) * 512; + bios->size = (le32_to_cpu(nv_rd32(bios, 0x300000)) >> 16) & 0xff; + bios->size = bios->size * 512; if (!bios->size) goto out; bios->data = kmalloc(bios->size, GFP_KERNEL); if (bios->data) { - for (i = 0; i < bios->size; i+=4) - nv_wo32(bios, i, nv_rd32(bios, 0x300000 + i)); + for (i = 0; i < bios->size; i += 4) + ((u32 *)bios->data)[i/4] = nv_rd32(bios, 0x300000 + i); } /* check the PCI record header */ -- cgit v1.2.3 From 806cbc5026933a781b66adecf6d1658fde9138e6 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 1 May 2014 13:58:05 +0200 Subject: drm/nouveau: fix another lock unbalance in nouveau_crtc_page_flip Fixes a regression introduced by 060810d7abaabca "drm/nouveau: fix locking issues in page flipping paths". chan->cli->mutex is unlocked a second time in the fail_unreserve path, fix this by moving mutex_unlock down. Cc: stable@vger.kernel.org # v3.11+ Signed-off-by: Maarten Lankhorst Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index b1547b032150..72e1571393e5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -764,9 +764,9 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, } ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence); - mutex_unlock(&chan->cli->mutex); if (ret) goto fail_unreserve; + mutex_unlock(&chan->cli->mutex); /* Update the crtc struct and cleanup */ crtc->fb = fb; -- cgit v1.2.3 From c7e74306632c71398ce6db878cd316cb43072ffb Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 2 May 2014 16:21:45 +1000 Subject: drm/gm107/gr: bump attrib cb size quite a bit When initially looking at traces, missed the fact the binary driver was using large pages. Fixes page faults when launching geometry shaders. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/engine/graph/ctxgm107.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxgm107.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxgm107.c index 1dc37b1ddbfa..b0d0fb2f4d08 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxgm107.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxgm107.c @@ -863,7 +863,7 @@ gm107_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info) { mmio_data(0x003000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS); mmio_data(0x008000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS); - mmio_data(0x060000, 0x1000, NV_MEM_ACCESS_RW); + mmio_data(0x200000, 0x1000, NV_MEM_ACCESS_RW); mmio_list(0x40800c, 0x00000000, 8, 1); mmio_list(0x408010, 0x80000000, 0, 0); @@ -877,6 +877,8 @@ gm107_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info) mmio_list(0x418e24, 0x00000000, 8, 0); mmio_list(0x418e28, 0x80000030, 0, 0); + mmio_list(0x4064c8, 0x018002c0, 0, 0); + mmio_list(0x418810, 0x80000000, 12, 2); mmio_list(0x419848, 0x10000000, 12, 2); mmio_list(0x419c2c, 0x10000000, 12, 2); -- cgit v1.2.3 From b7a7723513dc89f83d6df13206df55d4dc26e825 Mon Sep 17 00:00:00 2001 From: Sander Eikelenboom Date: Fri, 2 May 2014 15:09:27 +0200 Subject: ALSA: usb-audio: Prevent printk ratelimiting from spamming kernel log while DEBUG not defined This (widely used) construction: if(printk_ratelimit()) dev_dbg() Causes the ratelimiting to spam the kernel log with the "callbacks suppressed" message below, even while the dev_dbg it is supposed to rate limit wouldn't print anything because DEBUG is not defined for this device. [ 533.803964] retire_playback_urb: 852 callbacks suppressed [ 538.807930] retire_playback_urb: 852 callbacks suppressed [ 543.811897] retire_playback_urb: 852 callbacks suppressed [ 548.815745] retire_playback_urb: 852 callbacks suppressed [ 553.819826] retire_playback_urb: 852 callbacks suppressed So use dev_dbg_ratelimited() instead of this construction. Signed-off-by: Sander Eikelenboom Signed-off-by: Takashi Iwai --- sound/usb/pcm.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 131336d40492..c62a1659106d 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -1501,9 +1501,8 @@ static void retire_playback_urb(struct snd_usb_substream *subs, * The error should be lower than 2ms since the estimate relies * on two reads of a counter updated every ms. */ - if (printk_ratelimit() && - abs(est_delay - subs->last_delay) * 1000 > runtime->rate * 2) - dev_dbg(&subs->dev->dev, + if (abs(est_delay - subs->last_delay) * 1000 > runtime->rate * 2) + dev_dbg_ratelimited(&subs->dev->dev, "delay: estimated %d, actual %d\n", est_delay, subs->last_delay); -- cgit v1.2.3 From 1c53e7253ed8769a00afa0f06777d731dbe1ba6f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 2 May 2014 18:14:42 +0200 Subject: ALSA: usb-audio: Save mixer status only once at suspend The suspend callback of usb-audio driver may be called multiple times per suspend when multiple USB interfaces are bound to a single sound card instance. In such a case, it's superfluous to save the mixer values multiple times. This patch fixes it by checking the counter. Signed-off-by: Takashi Iwai --- sound/usb/card.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/usb/card.c b/sound/usb/card.c index 893d5a1afc3c..e769d3977716 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -695,8 +695,9 @@ static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message) chip->autosuspended = 1; } - list_for_each_entry(mixer, &chip->mixer_list, list) - snd_usb_mixer_suspend(mixer); + if (chip->num_suspended_intf == 1) + list_for_each_entry(mixer, &chip->mixer_list, list) + snd_usb_mixer_suspend(mixer); return 0; } -- cgit v1.2.3 From 1ee23fe07ee83a38ecee927e701f762888ada942 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 2 May 2014 18:17:06 +0200 Subject: ALSA: usb-audio: Fix deadlocks at resuming The recent addition of the USB audio mixer suspend/resume may lead to deadlocks when the driver tries to call usb_autopm_get_interface() recursively, since the function tries to sync with the finish of the other calls. For avoiding it, introduce a flag indicating the resume operation and avoids the recursive usb_autopm_get_interface() calls during the resume. Reported-and-tested-by: Bryan Quigley Signed-off-by: Takashi Iwai --- sound/usb/card.c | 7 +++++-- sound/usb/usbaudio.h | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/sound/usb/card.c b/sound/usb/card.c index e769d3977716..c3b5b7dca1c3 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -651,7 +651,7 @@ int snd_usb_autoresume(struct snd_usb_audio *chip) int err = -ENODEV; down_read(&chip->shutdown_rwsem); - if (chip->probing) + if (chip->probing && chip->in_pm) err = 0; else if (!chip->shutdown) err = usb_autopm_get_interface(chip->pm_intf); @@ -663,7 +663,7 @@ int snd_usb_autoresume(struct snd_usb_audio *chip) void snd_usb_autosuspend(struct snd_usb_audio *chip) { down_read(&chip->shutdown_rwsem); - if (!chip->shutdown && !chip->probing) + if (!chip->shutdown && !chip->probing && !chip->in_pm) usb_autopm_put_interface(chip->pm_intf); up_read(&chip->shutdown_rwsem); } @@ -712,6 +712,8 @@ static int __usb_audio_resume(struct usb_interface *intf, bool reset_resume) return 0; if (--chip->num_suspended_intf) return 0; + + chip->in_pm = 1; /* * ALSA leaves material resumption to user space * we just notify and restart the mixers @@ -727,6 +729,7 @@ static int __usb_audio_resume(struct usb_interface *intf, bool reset_resume) chip->autosuspended = 0; err_out: + chip->in_pm = 0; return err; } diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index 25c4c7e217de..91d0380431b4 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -40,6 +40,7 @@ struct snd_usb_audio { struct rw_semaphore shutdown_rwsem; unsigned int shutdown:1; unsigned int probing:1; + unsigned int in_pm:1; unsigned int autosuspended:1; unsigned int txfr_quirk:1; /* Subframe boundaries on transfers */ -- cgit v1.2.3 From 7040b6d1febfdbd9c1595efb751d492cd2503f96 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Thu, 1 May 2014 12:20:22 +0200 Subject: ALSA: usb-audio: work around corrupted TEAC UD-H01 feedback data The TEAC UD-H01 firmware sends wrong feedback frequency values, thus causing the PC to send the samples at a wrong rate, which results in clicks and crackles in the output. Add a workaround to detect and fix the corruption. Signed-off-by: Clemens Ladisch [mick37@gmx.de: use sender->udh01_fb_quirk rather than ep->udh01_fb_quirk in snd_usb_handle_sync_urb()] Reported-and-tested-by: Mick Reported-and-tested-by: Andrea Messa Cc: Signed-off-by: Takashi Iwai --- sound/usb/card.h | 1 + sound/usb/endpoint.c | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/sound/usb/card.h b/sound/usb/card.h index 9867ab866857..97acb906acc2 100644 --- a/sound/usb/card.h +++ b/sound/usb/card.h @@ -92,6 +92,7 @@ struct snd_usb_endpoint { unsigned int curframesize; /* current packet size in frames (for capture) */ unsigned int syncmaxsize; /* sync endpoint packet size */ unsigned int fill_max:1; /* fill max packet size always */ + unsigned int udh01_fb_quirk:1; /* corrupted feedback data */ unsigned int datainterval; /* log_2 of data packet interval */ unsigned int syncinterval; /* P for adaptive mode, 0 otherwise */ unsigned char silence_value; diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index e70a87e0d9fe..289f582c9130 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -471,6 +471,10 @@ struct snd_usb_endpoint *snd_usb_add_endpoint(struct snd_usb_audio *chip, ep->syncinterval = 3; ep->syncmaxsize = le16_to_cpu(get_endpoint(alts, 1)->wMaxPacketSize); + + if (chip->usb_id == USB_ID(0x0644, 0x8038) /* TEAC UD-H01 */ && + ep->syncmaxsize == 4) + ep->udh01_fb_quirk = 1; } list_add_tail(&ep->list, &chip->ep_list); @@ -1105,7 +1109,16 @@ void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep, if (f == 0) return; - if (unlikely(ep->freqshift == INT_MIN)) { + if (unlikely(sender->udh01_fb_quirk)) { + /* + * The TEAC UD-H01 firmware sometimes changes the feedback value + * by +/- 0x1.0000. + */ + if (f < ep->freqn - 0x8000) + f += 0x10000; + else if (f > ep->freqn + 0x8000) + f -= 0x10000; + } else if (unlikely(ep->freqshift == INT_MIN)) { /* * The first time we see a feedback value, determine its format * by shifting it left or right until it matches the nominal -- cgit v1.2.3 From 48695f3d4e7abbfb8fbba45397dce4d5fc0ccfed Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Fri, 2 May 2014 16:56:27 +0100 Subject: ASoC: Intel: Fix block allocation so we only allocate blocks once. Make sure we dont alloc blocks twice with requests spanning more than one block. Signed-off-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/intel/sst-firmware.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sound/soc/intel/sst-firmware.c b/sound/soc/intel/sst-firmware.c index f7687107cf7f..c4e7126ebc06 100644 --- a/sound/soc/intel/sst-firmware.c +++ b/sound/soc/intel/sst-firmware.c @@ -376,10 +376,6 @@ static int block_alloc_fixed(struct sst_module *module, if (err < 0) return -ENOMEM; - /* add block */ - block->data_type = data->data_type; - list_move(&block->list, &dsp->used_block_list); - list_add(&block->module_list, &module->block_list); return 0; } -- cgit v1.2.3 From 84fbdd58614e35108ece5c79ada33443dbcdaf37 Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Fri, 2 May 2014 16:56:29 +0100 Subject: ASoC: Intel: Fix allocated block list usage when adding blocks. Make sure we add the allocated blocks to the modules list of blocks. Signed-off-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/intel/sst-firmware.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/intel/sst-firmware.c b/sound/soc/intel/sst-firmware.c index c4e7126ebc06..5fed75cef64f 100644 --- a/sound/soc/intel/sst-firmware.c +++ b/sound/soc/intel/sst-firmware.c @@ -202,6 +202,9 @@ static int block_alloc_contiguous(struct sst_module *module, size -= block->size; } + list_for_each_entry(block, &tmp, list) + list_add(&block->module_list, &module->block_list); + list_splice(&tmp, &dsp->used_block_list); return 0; } -- cgit v1.2.3 From 0b708c87f66a15190fb43661c2320fd48c4dc6c8 Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Fri, 2 May 2014 16:56:30 +0100 Subject: ASoC: Intel: Fix Haswell/Broadwell DSP page table creation. Fix page table creation on Haswell and Broadwell to remove unsafe virt_to_phys mappings and use more portable SG buffer. Use audio buffer APIs to allocate DMA buffers. Signed-off-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/intel/sst-haswell-pcm.c | 58 +++++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/sound/soc/intel/sst-haswell-pcm.c b/sound/soc/intel/sst-haswell-pcm.c index 0a32dd13a23d..dc53f501c64c 100644 --- a/sound/soc/intel/sst-haswell-pcm.c +++ b/sound/soc/intel/sst-haswell-pcm.c @@ -107,7 +107,7 @@ struct hsw_priv_data { struct sst_hsw *hsw; /* page tables */ - unsigned char *pcm_pg[HSW_PCM_COUNT][2]; + struct snd_dma_buffer dmab[HSW_PCM_COUNT][2]; /* DAI data */ struct hsw_pcm_data pcm[HSW_PCM_COUNT]; @@ -273,28 +273,26 @@ static const struct snd_kcontrol_new hsw_volume_controls[] = { }; /* Create DMA buffer page table for DSP */ -static int create_adsp_page_table(struct hsw_priv_data *pdata, - struct snd_soc_pcm_runtime *rtd, - unsigned char *dma_area, size_t size, int pcm, int stream) +static int create_adsp_page_table(struct snd_pcm_substream *substream, + struct hsw_priv_data *pdata, struct snd_soc_pcm_runtime *rtd, + unsigned char *dma_area, size_t size, int pcm) { - int i, pages; + struct snd_dma_buffer *dmab = snd_pcm_get_dma_buf(substream); + int i, pages, stream = substream->stream; - if (size % PAGE_SIZE) - pages = (size / PAGE_SIZE) + 1; - else - pages = size / PAGE_SIZE; + pages = snd_sgbuf_aligned_pages(size); dev_dbg(rtd->dev, "generating page table for %p size 0x%zu pages %d\n", dma_area, size, pages); for (i = 0; i < pages; i++) { u32 idx = (((i << 2) + i)) >> 1; - u32 pfn = (virt_to_phys(dma_area + i * PAGE_SIZE)) >> PAGE_SHIFT; + u32 pfn = snd_sgbuf_get_addr(dmab, i * PAGE_SIZE) >> PAGE_SHIFT; u32 *pg_table; dev_dbg(rtd->dev, "pfn i %i idx %d pfn %x\n", i, idx, pfn); - pg_table = (u32*)(pdata->pcm_pg[pcm][stream] + idx); + pg_table = (u32 *)(pdata->dmab[pcm][stream].area + idx); if (i & 1) *pg_table |= (pfn << 4); @@ -317,6 +315,7 @@ static int hsw_pcm_hw_params(struct snd_pcm_substream *substream, struct sst_hsw *hsw = pdata->hsw; struct sst_module *module_data; struct sst_dsp *dsp; + struct snd_dma_buffer *dmab; enum sst_hsw_stream_type stream_type; enum sst_hsw_stream_path_id path_id; u32 rate, bits, map, pages, module_id; @@ -416,8 +415,10 @@ static int hsw_pcm_hw_params(struct snd_pcm_substream *substream, return ret; } - ret = create_adsp_page_table(pdata, rtd, runtime->dma_area, - runtime->dma_bytes, rtd->cpu_dai->id, substream->stream); + dmab = snd_pcm_get_dma_buf(substream); + + ret = create_adsp_page_table(substream, pdata, rtd, runtime->dma_area, + runtime->dma_bytes, rtd->cpu_dai->id); if (ret < 0) return ret; @@ -430,9 +431,9 @@ static int hsw_pcm_hw_params(struct snd_pcm_substream *substream, pages = runtime->dma_bytes / PAGE_SIZE; ret = sst_hsw_stream_buffer(hsw, pcm_data->stream, - virt_to_phys(pdata->pcm_pg[rtd->cpu_dai->id][substream->stream]), + pdata->dmab[rtd->cpu_dai->id][substream->stream].addr, pages, runtime->dma_bytes, 0, - (u32)(virt_to_phys(runtime->dma_area) >> PAGE_SHIFT)); + snd_sgbuf_get_addr(dmab, 0) >> PAGE_SHIFT); if (ret < 0) { dev_err(rtd->dev, "error: failed to set DMA buffer %d\n", ret); return ret; @@ -621,7 +622,7 @@ static struct snd_pcm_ops hsw_pcm_ops = { .hw_free = hsw_pcm_hw_free, .trigger = hsw_pcm_trigger, .pointer = hsw_pcm_pointer, - .mmap = snd_pcm_lib_default_mmap, + .page = snd_pcm_sgbuf_ops_page, }; static void hsw_pcm_free(struct snd_pcm *pcm) @@ -641,7 +642,7 @@ static int hsw_pcm_new(struct snd_soc_pcm_runtime *rtd) if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream || pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { ret = snd_pcm_lib_preallocate_pages_for_all(pcm, - SNDRV_DMA_TYPE_DEV, + SNDRV_DMA_TYPE_DEV_SG, rtd->card->dev, hsw_pcm_hardware.buffer_bytes_max, hsw_pcm_hardware.buffer_bytes_max); @@ -742,7 +743,8 @@ static int hsw_pcm_probe(struct snd_soc_platform *platform) { struct sst_pdata *pdata = dev_get_platdata(platform->dev); struct hsw_priv_data *priv_data; - int i; + struct device *dma_dev = pdata->dma_dev; + int i, ret = 0; if (!pdata) return -ENODEV; @@ -758,15 +760,17 @@ static int hsw_pcm_probe(struct snd_soc_platform *platform) /* playback */ if (hsw_dais[i].playback.channels_min) { - priv_data->pcm_pg[i][0] = kzalloc(PAGE_SIZE, GFP_DMA); - if (priv_data->pcm_pg[i][0] == NULL) + ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dma_dev, + PAGE_SIZE, &priv_data->dmab[i][0]); + if (ret < 0) goto err; } /* capture */ if (hsw_dais[i].capture.channels_min) { - priv_data->pcm_pg[i][1] = kzalloc(PAGE_SIZE, GFP_DMA); - if (priv_data->pcm_pg[i][1] == NULL) + ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dma_dev, + PAGE_SIZE, &priv_data->dmab[i][1]); + if (ret < 0) goto err; } } @@ -776,11 +780,11 @@ static int hsw_pcm_probe(struct snd_soc_platform *platform) err: for (;i >= 0; i--) { if (hsw_dais[i].playback.channels_min) - kfree(priv_data->pcm_pg[i][0]); + snd_dma_free_pages(&priv_data->dmab[i][0]); if (hsw_dais[i].capture.channels_min) - kfree(priv_data->pcm_pg[i][1]); + snd_dma_free_pages(&priv_data->dmab[i][1]); } - return -ENOMEM; + return ret; } static int hsw_pcm_remove(struct snd_soc_platform *platform) @@ -791,9 +795,9 @@ static int hsw_pcm_remove(struct snd_soc_platform *platform) for (i = 0; i < ARRAY_SIZE(hsw_dais); i++) { if (hsw_dais[i].playback.channels_min) - kfree(priv_data->pcm_pg[i][0]); + snd_dma_free_pages(&priv_data->dmab[i][0]); if (hsw_dais[i].capture.channels_min) - kfree(priv_data->pcm_pg[i][1]); + snd_dma_free_pages(&priv_data->dmab[i][1]); } return 0; -- cgit v1.2.3 From 10df350977b15d44dba0b3b44e3da7989711cb8d Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Fri, 2 May 2014 16:56:31 +0100 Subject: ASoC: Intel: Fix Audio DSP usage when IOMMU is enabled. The Intel IOMMU requires that the ACPI device is used to allocate all DMA memory buffers. This means we need to pass the DMA device pointer into child component devices that allocate DMA memory. We also only set the DMA mask for the ACPI device now instead of for each component device. Signed-off-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/intel/sst-acpi.c | 1 + sound/soc/intel/sst-dsp-priv.h | 1 + sound/soc/intel/sst-dsp.c | 1 + sound/soc/intel/sst-dsp.h | 1 + sound/soc/intel/sst-firmware.c | 10 ++-------- sound/soc/intel/sst-haswell-dsp.c | 4 ++-- sound/soc/intel/sst-haswell-pcm.c | 9 ++++----- 7 files changed, 12 insertions(+), 15 deletions(-) diff --git a/sound/soc/intel/sst-acpi.c b/sound/soc/intel/sst-acpi.c index 5d06eecb6198..18aee77f8d4a 100644 --- a/sound/soc/intel/sst-acpi.c +++ b/sound/soc/intel/sst-acpi.c @@ -138,6 +138,7 @@ static int sst_acpi_probe(struct platform_device *pdev) sst_pdata = &sst_acpi->sst_pdata; sst_pdata->id = desc->sst_id; + sst_pdata->dma_dev = dev; sst_acpi->desc = desc; sst_acpi->mach = mach; diff --git a/sound/soc/intel/sst-dsp-priv.h b/sound/soc/intel/sst-dsp-priv.h index 30ca14a6a835..401213455497 100644 --- a/sound/soc/intel/sst-dsp-priv.h +++ b/sound/soc/intel/sst-dsp-priv.h @@ -228,6 +228,7 @@ struct sst_dsp { spinlock_t spinlock; /* IPC locking */ struct mutex mutex; /* DSP FW lock */ struct device *dev; + struct device *dma_dev; void *thread_context; int irq; u32 id; diff --git a/sound/soc/intel/sst-dsp.c b/sound/soc/intel/sst-dsp.c index 0c129fd85ecf..0b715b20a2d7 100644 --- a/sound/soc/intel/sst-dsp.c +++ b/sound/soc/intel/sst-dsp.c @@ -337,6 +337,7 @@ struct sst_dsp *sst_dsp_new(struct device *dev, spin_lock_init(&sst->spinlock); mutex_init(&sst->mutex); sst->dev = dev; + sst->dma_dev = pdata->dma_dev; sst->thread_context = sst_dev->thread_context; sst->sst_dev = sst_dev; sst->id = pdata->id; diff --git a/sound/soc/intel/sst-dsp.h b/sound/soc/intel/sst-dsp.h index 74052b59485c..e44423be66c4 100644 --- a/sound/soc/intel/sst-dsp.h +++ b/sound/soc/intel/sst-dsp.h @@ -169,6 +169,7 @@ struct sst_pdata { u32 dma_base; u32 dma_size; int dma_engine; + struct device *dma_dev; /* DSP */ u32 id; diff --git a/sound/soc/intel/sst-firmware.c b/sound/soc/intel/sst-firmware.c index 5fed75cef64f..c38cfda8003c 100644 --- a/sound/soc/intel/sst-firmware.c +++ b/sound/soc/intel/sst-firmware.c @@ -57,14 +57,8 @@ struct sst_fw *sst_fw_new(struct sst_dsp *dsp, sst_fw->private = private; sst_fw->size = fw->size; - err = dma_coerce_mask_and_coherent(dsp->dev, DMA_BIT_MASK(32)); - if (err < 0) { - kfree(sst_fw); - return NULL; - } - /* allocate DMA buffer to store FW data */ - sst_fw->dma_buf = dma_alloc_coherent(dsp->dev, sst_fw->size, + sst_fw->dma_buf = dma_alloc_coherent(dsp->dma_dev, sst_fw->size, &sst_fw->dmable_fw_paddr, GFP_DMA | GFP_KERNEL); if (!sst_fw->dma_buf) { dev_err(dsp->dev, "error: DMA alloc failed\n"); @@ -106,7 +100,7 @@ void sst_fw_free(struct sst_fw *sst_fw) list_del(&sst_fw->list); mutex_unlock(&dsp->mutex); - dma_free_coherent(dsp->dev, sst_fw->size, sst_fw->dma_buf, + dma_free_coherent(dsp->dma_dev, sst_fw->size, sst_fw->dma_buf, sst_fw->dmable_fw_paddr); kfree(sst_fw); } diff --git a/sound/soc/intel/sst-haswell-dsp.c b/sound/soc/intel/sst-haswell-dsp.c index f5ebf36af889..535f517629fd 100644 --- a/sound/soc/intel/sst-haswell-dsp.c +++ b/sound/soc/intel/sst-haswell-dsp.c @@ -433,7 +433,7 @@ static int hsw_init(struct sst_dsp *sst, struct sst_pdata *pdata) int ret = -ENODEV, i, j, region_count; u32 offset, size; - dev = sst->dev; + dev = sst->dma_dev; switch (sst->id) { case SST_DEV_ID_LYNX_POINT: @@ -466,7 +466,7 @@ static int hsw_init(struct sst_dsp *sst, struct sst_pdata *pdata) return ret; } - ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32)); + ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(31)); if (ret) return ret; diff --git a/sound/soc/intel/sst-haswell-pcm.c b/sound/soc/intel/sst-haswell-pcm.c index dc53f501c64c..ba585a75878d 100644 --- a/sound/soc/intel/sst-haswell-pcm.c +++ b/sound/soc/intel/sst-haswell-pcm.c @@ -633,17 +633,16 @@ static void hsw_pcm_free(struct snd_pcm *pcm) static int hsw_pcm_new(struct snd_soc_pcm_runtime *rtd) { struct snd_pcm *pcm = rtd->pcm; + struct snd_soc_platform *platform = rtd->platform; + struct sst_pdata *pdata = dev_get_platdata(platform->dev); + struct device *dev = pdata->dma_dev; int ret = 0; - ret = dma_coerce_mask_and_coherent(rtd->card->dev, DMA_BIT_MASK(32)); - if (ret) - return ret; - if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream || pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { ret = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, - rtd->card->dev, + dev, hsw_pcm_hardware.buffer_bytes_max, hsw_pcm_hardware.buffer_bytes_max); if (ret) { -- cgit v1.2.3 From 916152c48848290a8aba5cf4dd16c2a8a888e11c Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Fri, 2 May 2014 16:56:32 +0100 Subject: ASoC: Intel: Fix allow hw_params to be called more than once. hw_params() can be called multiple times. Make sure we release the DSP stream that was allocated on previous hw_params() calls before allocating a new DSP stream. Signed-off-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/intel/sst-haswell-pcm.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/sound/soc/intel/sst-haswell-pcm.c b/sound/soc/intel/sst-haswell-pcm.c index ba585a75878d..50fea077898b 100644 --- a/sound/soc/intel/sst-haswell-pcm.c +++ b/sound/soc/intel/sst-haswell-pcm.c @@ -99,6 +99,7 @@ struct hsw_pcm_data { struct snd_compr_stream *cstream; unsigned int wpos; struct mutex mutex; + bool allocated; }; /* private data for the driver */ @@ -113,6 +114,8 @@ struct hsw_priv_data { struct hsw_pcm_data pcm[HSW_PCM_COUNT]; }; +static u32 hsw_notify_pointer(struct sst_hsw_stream *stream, void *data); + static inline u32 hsw_mixer_to_ipc(unsigned int value) { if (value >= ARRAY_SIZE(volume_map)) @@ -322,6 +325,29 @@ static int hsw_pcm_hw_params(struct snd_pcm_substream *substream, u8 channels; int ret; + /* check if we are being called a subsequent time */ + if (pcm_data->allocated) { + ret = sst_hsw_stream_reset(hsw, pcm_data->stream); + if (ret < 0) + dev_dbg(rtd->dev, "error: reset stream failed %d\n", + ret); + + ret = sst_hsw_stream_free(hsw, pcm_data->stream); + if (ret < 0) { + dev_dbg(rtd->dev, "error: free stream failed %d\n", + ret); + return ret; + } + pcm_data->allocated = false; + + pcm_data->stream = sst_hsw_stream_new(hsw, rtd->cpu_dai->id, + hsw_notify_pointer, pcm_data); + if (pcm_data->stream == NULL) { + dev_err(rtd->dev, "error: failed to create stream\n"); + return -EINVAL; + } + } + /* stream direction */ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) path_id = SST_HSW_STREAM_PATH_SSP0_OUT; @@ -475,6 +501,7 @@ static int hsw_pcm_hw_params(struct snd_pcm_substream *substream, dev_err(rtd->dev, "error: failed to commit stream %d\n", ret); return ret; } + pcm_data->allocated = true; ret = sst_hsw_stream_pause(hsw, pcm_data->stream, 1); if (ret < 0) @@ -607,6 +634,7 @@ static int hsw_pcm_close(struct snd_pcm_substream *substream) dev_dbg(rtd->dev, "error: free stream failed %d\n", ret); goto out; } + pcm_data->allocated = 0; pcm_data->stream = NULL; out: -- cgit v1.2.3 From 51b4e24f383c84ed927fef348072b6dc65b9816d Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Fri, 2 May 2014 16:56:33 +0100 Subject: ASoC: Intel: Fix stream position pointer. Read the stream offset and presentation position from DSP memory rather than using the old estimated position. This fixes timing issues with pulseaudio. Signed-off-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/intel/sst-haswell-ipc.c | 22 ++++++++++++++++++++-- sound/soc/intel/sst-haswell-ipc.h | 4 +++- sound/soc/intel/sst-haswell-pcm.c | 10 ++++++---- 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/sound/soc/intel/sst-haswell-ipc.c b/sound/soc/intel/sst-haswell-ipc.c index 5bcf5963a0ba..e7996b39a484 100644 --- a/sound/soc/intel/sst-haswell-ipc.c +++ b/sound/soc/intel/sst-haswell-ipc.c @@ -1547,10 +1547,28 @@ int sst_hsw_stream_reset(struct sst_hsw *hsw, struct sst_hsw_stream *stream) } /* Stream pointer positions */ -int sst_hsw_get_dsp_position(struct sst_hsw *hsw, +u32 sst_hsw_get_dsp_position(struct sst_hsw *hsw, struct sst_hsw_stream *stream) { - return stream->rpos.position; + u32 rpos; + + sst_dsp_read(hsw->dsp, &rpos, + stream->reply.read_position_register_address, sizeof(rpos)); + + return rpos; +} + +/* Stream presentation (monotonic) positions */ +u64 sst_hsw_get_dsp_presentation_position(struct sst_hsw *hsw, + struct sst_hsw_stream *stream) +{ + u64 ppos; + + sst_dsp_read(hsw->dsp, &ppos, + stream->reply.presentation_position_register_address, + sizeof(ppos)); + + return ppos; } int sst_hsw_stream_set_write_position(struct sst_hsw *hsw, diff --git a/sound/soc/intel/sst-haswell-ipc.h b/sound/soc/intel/sst-haswell-ipc.h index d517929ccc38..2ac194a6d04b 100644 --- a/sound/soc/intel/sst-haswell-ipc.h +++ b/sound/soc/intel/sst-haswell-ipc.h @@ -464,7 +464,9 @@ int sst_hsw_stream_get_write_pos(struct sst_hsw *hsw, struct sst_hsw_stream *stream, u32 *position); int sst_hsw_stream_set_write_position(struct sst_hsw *hsw, struct sst_hsw_stream *stream, u32 stage_id, u32 position); -int sst_hsw_get_dsp_position(struct sst_hsw *hsw, +u32 sst_hsw_get_dsp_position(struct sst_hsw *hsw, + struct sst_hsw_stream *stream); +u64 sst_hsw_get_dsp_presentation_position(struct sst_hsw *hsw, struct sst_hsw_stream *stream); /* HW port config */ diff --git a/sound/soc/intel/sst-haswell-pcm.c b/sound/soc/intel/sst-haswell-pcm.c index 50fea077898b..8c6bd33dd375 100644 --- a/sound/soc/intel/sst-haswell-pcm.c +++ b/sound/soc/intel/sst-haswell-pcm.c @@ -569,12 +569,14 @@ static snd_pcm_uframes_t hsw_pcm_pointer(struct snd_pcm_substream *substream) struct hsw_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(rtd); struct sst_hsw *hsw = pdata->hsw; snd_pcm_uframes_t offset; + uint64_t ppos; + u32 position = sst_hsw_get_dsp_position(hsw, pcm_data->stream); - offset = bytes_to_frames(runtime, - sst_hsw_get_dsp_position(hsw, pcm_data->stream)); + offset = bytes_to_frames(runtime, position); + ppos = sst_hsw_get_dsp_presentation_position(hsw, pcm_data->stream); - dev_dbg(rtd->dev, "PCM: DMA pointer %zu bytes\n", - frames_to_bytes(runtime, (u32)offset)); + dev_dbg(rtd->dev, "PCM: DMA pointer %du bytes, pos %llu\n", + position, ppos); return offset; } -- cgit v1.2.3 From 2de440f59ca9615c92820d165d5e59756e54026b Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 2 May 2014 06:29:34 +0200 Subject: spi: core: Protect DMA code by #ifdef CONFIG_HAS_DMA If NO_DMA=y: drivers/built-in.o: In function `spi_map_buf': spi.c:(.text+0x21bc60): undefined reference to `dma_map_sg' drivers/built-in.o: In function `spi_unmap_buf.isra.33': spi.c:(.text+0x21c32e): undefined reference to `dma_unmap_sg' make[3]: *** [vmlinux] Error 1 Protect the DMA code by #ifdef CONFIG_HAS_DMA to fix this: - Extract __spi_map_msg() from spi_map_msg(), - Provide dummy definitions of __spi_map_msg() and spi_unmap_msg() if !CONFIG_HAS_DMA. Signed-off-by: Geert Uytterhoeven Signed-off-by: Mark Brown --- drivers/spi/spi.c | 109 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 65 insertions(+), 44 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 1534fa1dac34..6046dcd7487e 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -580,6 +580,7 @@ static void spi_set_cs(struct spi_device *spi, bool enable) spi->master->set_cs(spi, !enable); } +#ifdef CONFIG_HAS_DMA static int spi_map_buf(struct spi_master *master, struct device *dev, struct sg_table *sgt, void *buf, size_t len, enum dma_data_direction dir) @@ -637,55 +638,12 @@ static void spi_unmap_buf(struct spi_master *master, struct device *dev, } } -static int spi_map_msg(struct spi_master *master, struct spi_message *msg) +static int __spi_map_msg(struct spi_master *master, struct spi_message *msg) { struct device *tx_dev, *rx_dev; struct spi_transfer *xfer; - void *tmp; - unsigned int max_tx, max_rx; int ret; - if (master->flags & (SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX)) { - max_tx = 0; - max_rx = 0; - - list_for_each_entry(xfer, &msg->transfers, transfer_list) { - if ((master->flags & SPI_MASTER_MUST_TX) && - !xfer->tx_buf) - max_tx = max(xfer->len, max_tx); - if ((master->flags & SPI_MASTER_MUST_RX) && - !xfer->rx_buf) - max_rx = max(xfer->len, max_rx); - } - - if (max_tx) { - tmp = krealloc(master->dummy_tx, max_tx, - GFP_KERNEL | GFP_DMA); - if (!tmp) - return -ENOMEM; - master->dummy_tx = tmp; - memset(tmp, 0, max_tx); - } - - if (max_rx) { - tmp = krealloc(master->dummy_rx, max_rx, - GFP_KERNEL | GFP_DMA); - if (!tmp) - return -ENOMEM; - master->dummy_rx = tmp; - } - - if (max_tx || max_rx) { - list_for_each_entry(xfer, &msg->transfers, - transfer_list) { - if (!xfer->tx_buf) - xfer->tx_buf = master->dummy_tx; - if (!xfer->rx_buf) - xfer->rx_buf = master->dummy_rx; - } - } - } - if (!master->can_dma) return 0; @@ -742,6 +700,69 @@ static int spi_unmap_msg(struct spi_master *master, struct spi_message *msg) return 0; } +#else /* !CONFIG_HAS_DMA */ +static inline int __spi_map_msg(struct spi_master *master, + struct spi_message *msg) +{ + return 0; +} + +static inline int spi_unmap_msg(struct spi_master *master, + struct spi_message *msg) +{ + return 0; +} +#endif /* !CONFIG_HAS_DMA */ + +static int spi_map_msg(struct spi_master *master, struct spi_message *msg) +{ + struct spi_transfer *xfer; + void *tmp; + unsigned int max_tx, max_rx; + + if (master->flags & (SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX)) { + max_tx = 0; + max_rx = 0; + + list_for_each_entry(xfer, &msg->transfers, transfer_list) { + if ((master->flags & SPI_MASTER_MUST_TX) && + !xfer->tx_buf) + max_tx = max(xfer->len, max_tx); + if ((master->flags & SPI_MASTER_MUST_RX) && + !xfer->rx_buf) + max_rx = max(xfer->len, max_rx); + } + + if (max_tx) { + tmp = krealloc(master->dummy_tx, max_tx, + GFP_KERNEL | GFP_DMA); + if (!tmp) + return -ENOMEM; + master->dummy_tx = tmp; + memset(tmp, 0, max_tx); + } + + if (max_rx) { + tmp = krealloc(master->dummy_rx, max_rx, + GFP_KERNEL | GFP_DMA); + if (!tmp) + return -ENOMEM; + master->dummy_rx = tmp; + } + + if (max_tx || max_rx) { + list_for_each_entry(xfer, &msg->transfers, + transfer_list) { + if (!xfer->tx_buf) + xfer->tx_buf = master->dummy_tx; + if (!xfer->rx_buf) + xfer->rx_buf = master->dummy_rx; + } + } + } + + return __spi_map_msg(master, msg); +} /* * spi_transfer_one_message - Default implementation of transfer_one_message() -- cgit v1.2.3 From 5f35eb0e29ca26da82febe49d7698dbeb8882ea0 Mon Sep 17 00:00:00 2001 From: Dave Young Date: Thu, 1 May 2014 21:15:48 +0800 Subject: x86/efi: earlyprintk=efi,keep fix earlyprintk=efi,keep will cause kernel hangs while freeing initmem like below: VFS: Mounted root (ext4 filesystem) readonly on device 254:2. devtmpfs: mounted Freeing unused kernel memory: 880K (ffffffff817d4000 - ffffffff818b0000) It is caused by efi earlyprintk use __init function which will be freed later. Such as early_efi_write is marked as __init, also it will use early_ioremap which is init function as well. To fix this issue, I added early initcall early_efi_map_fb which maps the whole efi fb for later use. OTOH, adding a wrapper function early_efi_map which calls early_ioremap before ioremap is available. With this patch applied efi boot ok with earlyprintk=efi,keep console=efi Signed-off-by: Dave Young Signed-off-by: Matt Fleming --- arch/x86/platform/efi/early_printk.c | 83 +++++++++++++++++++++++++++--------- 1 file changed, 64 insertions(+), 19 deletions(-) diff --git a/arch/x86/platform/efi/early_printk.c b/arch/x86/platform/efi/early_printk.c index 81b506d5befd..524142117296 100644 --- a/arch/x86/platform/efi/early_printk.c +++ b/arch/x86/platform/efi/early_printk.c @@ -14,48 +14,92 @@ static const struct font_desc *font; static u32 efi_x, efi_y; +static void *efi_fb; +static bool early_efi_keep; -static __init void early_efi_clear_scanline(unsigned int y) +/* + * efi earlyprintk need use early_ioremap to map the framebuffer. + * But early_ioremap is not usable for earlyprintk=efi,keep, ioremap should + * be used instead. ioremap will be available after paging_init() which is + * earlier than initcall callbacks. Thus adding this early initcall function + * early_efi_map_fb to map the whole efi framebuffer. + */ +static __init int early_efi_map_fb(void) { - unsigned long base, *dst; - u16 len; + unsigned long base, size; + + if (!early_efi_keep) + return 0; base = boot_params.screen_info.lfb_base; - len = boot_params.screen_info.lfb_linelength; + size = boot_params.screen_info.lfb_size; + efi_fb = ioremap(base, size); + + return efi_fb ? 0 : -ENOMEM; +} +early_initcall(early_efi_map_fb); + +/* + * early_efi_map maps efi framebuffer region [start, start + len -1] + * In case earlyprintk=efi,keep we have the whole framebuffer mapped already + * so just return the offset efi_fb + start. + */ +static __init_refok void *early_efi_map(unsigned long start, unsigned long len) +{ + unsigned long base; + + base = boot_params.screen_info.lfb_base; + + if (efi_fb) + return (efi_fb + start); + else + return early_ioremap(base + start, len); +} - dst = early_ioremap(base + y*len, len); +static __init_refok void early_efi_unmap(void *addr, unsigned long len) +{ + if (!efi_fb) + early_iounmap(addr, len); +} + +static void early_efi_clear_scanline(unsigned int y) +{ + unsigned long *dst; + u16 len; + + len = boot_params.screen_info.lfb_linelength; + dst = early_efi_map(y*len, len); if (!dst) return; memset(dst, 0, len); - early_iounmap(dst, len); + early_efi_unmap(dst, len); } -static __init void early_efi_scroll_up(void) +static void early_efi_scroll_up(void) { - unsigned long base, *dst, *src; + unsigned long *dst, *src; u16 len; u32 i, height; - base = boot_params.screen_info.lfb_base; len = boot_params.screen_info.lfb_linelength; height = boot_params.screen_info.lfb_height; for (i = 0; i < height - font->height; i++) { - dst = early_ioremap(base + i*len, len); + dst = early_efi_map(i*len, len); if (!dst) return; - src = early_ioremap(base + (i + font->height) * len, len); + src = early_efi_map((i + font->height) * len, len); if (!src) { - early_iounmap(dst, len); + early_efi_unmap(dst, len); return; } memmove(dst, src, len); - early_iounmap(src, len); - early_iounmap(dst, len); + early_efi_unmap(src, len); + early_efi_unmap(dst, len); } } @@ -79,16 +123,14 @@ static void early_efi_write_char(u32 *dst, unsigned char c, unsigned int h) } } -static __init void +static void early_efi_write(struct console *con, const char *str, unsigned int num) { struct screen_info *si; - unsigned long base; unsigned int len; const char *s; void *dst; - base = boot_params.screen_info.lfb_base; si = &boot_params.screen_info; len = si->lfb_linelength; @@ -109,7 +151,7 @@ early_efi_write(struct console *con, const char *str, unsigned int num) for (h = 0; h < font->height; h++) { unsigned int n, x; - dst = early_ioremap(base + (efi_y + h) * len, len); + dst = early_efi_map((efi_y + h) * len, len); if (!dst) return; @@ -123,7 +165,7 @@ early_efi_write(struct console *con, const char *str, unsigned int num) s++; } - early_iounmap(dst, len); + early_efi_unmap(dst, len); } num -= count; @@ -179,6 +221,9 @@ static __init int early_efi_setup(struct console *con, char *options) for (i = 0; i < (yres - efi_y) / font->height; i++) early_efi_scroll_up(); + /* early_console_register will unset CON_BOOT in case ,keep */ + if (!(con->flags & CON_BOOT)) + early_efi_keep = true; return 0; } -- cgit v1.2.3 From 3d89e141bbf8619f3db97c38e33cb6d7a563614d Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 3 May 2014 10:57:57 +0800 Subject: spi: qup: Fix return value checking for pm_runtime_get_sync() pm_runtime_get_sync() returns 1 if !CONFIG_PM_RUNTIME. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/spi/spi-qup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-qup.c b/drivers/spi/spi-qup.c index b032e8885e24..78c66e3c53ed 100644 --- a/drivers/spi/spi-qup.c +++ b/drivers/spi/spi-qup.c @@ -734,7 +734,7 @@ static int spi_qup_remove(struct platform_device *pdev) int ret; ret = pm_runtime_get_sync(&pdev->dev); - if (ret) + if (ret < 0) return ret; ret = spi_qup_set_state(controller, QUP_STATE_RESET); -- cgit v1.2.3 From c3676d5ceff213cba35af5ee5f320d2e8dc48cdf Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 1 May 2014 10:47:52 -0700 Subject: spi: core: Don't destroy master queue if we fail to create it If we fail to create the master queue for some reason we should not attempt to clean it up since attempting to stop a kthread that was not created will hang and it's just generally bad practice. Unfortunately at present we call spi_destroy_queue() even in cases where the creation fails. Fix this by fixing the error handling in spi_master_initialize_queue() so that we only flag the master as queued or destroy the queue if creation succeeded. The change to the flag is done since the general master cleanup uses this to destroy the queue. Reported-by: Ricardo Ribalda Delgado Signed-off-by: Mark Brown Acked-by: Geert Uytterhoeven --- drivers/spi/spi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 6046dcd7487e..939edf473235 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1172,7 +1172,6 @@ static int spi_master_initialize_queue(struct spi_master *master) { int ret; - master->queued = true; master->transfer = spi_queued_transfer; if (!master->transfer_one_message) master->transfer_one_message = spi_transfer_one_message; @@ -1183,6 +1182,7 @@ static int spi_master_initialize_queue(struct spi_master *master) dev_err(&master->dev, "problem initializing queue\n"); goto err_init_queue; } + master->queued = true; ret = spi_start_queue(master); if (ret) { dev_err(&master->dev, "problem starting queue\n"); @@ -1192,8 +1192,8 @@ static int spi_master_initialize_queue(struct spi_master *master) return 0; err_start_queue: -err_init_queue: spi_destroy_queue(master); +err_init_queue: return ret; } -- cgit v1.2.3 From 895162b1101b3ea5db08ca6822ae9672717efec0 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Fri, 2 May 2014 15:32:16 +0200 Subject: netfilter: ipv4: defrag: set local_df flag on defragmented skb else we may fail to forward skb even if original fragments do fit outgoing link mtu: 1. remote sends 2k packets in two 1000 byte frags, DF set 2. we want to forward but only see '2k > mtu and DF set' 3. we then send icmp error saying that outgoing link is 1500 But original sender never sent a packet that would not fit the outgoing link. Setting local_df makes outgoing path test size vs. IPCB(skb)->frag_max_size, so we will still send the correct error in case the largest original size did not fit outgoing link mtu. Reported-by: Maxime Bizon Suggested-by: Maxime Bizon Fixes: 5f2d04f1f9 (ipv4: fix path MTU discovery with connection tracking) Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- net/ipv4/netfilter/nf_defrag_ipv4.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/ipv4/netfilter/nf_defrag_ipv4.c b/net/ipv4/netfilter/nf_defrag_ipv4.c index 12e13bd82b5b..f40f321b41fc 100644 --- a/net/ipv4/netfilter/nf_defrag_ipv4.c +++ b/net/ipv4/netfilter/nf_defrag_ipv4.c @@ -22,7 +22,6 @@ #endif #include -/* Returns new sk_buff, or NULL */ static int nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user) { int err; @@ -33,8 +32,10 @@ static int nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user) err = ip_defrag(skb, user); local_bh_enable(); - if (!err) + if (!err) { ip_send_check(ip_hdr(skb)); + skb->local_df = 1; + } return err; } -- cgit v1.2.3 From ecd15dd7e45f3683fa8142b9f2c015dfaa0c243d Mon Sep 17 00:00:00 2001 From: Denys Fedoryshchenko Date: Sun, 4 May 2014 13:35:37 +0200 Subject: netfilter: nfnetlink: Fix use after free when it fails to process batch This bug manifests when calling the nft command line tool without nf_tables kernel support. kernel message: [ 44.071555] Netfilter messages via NETLINK v0.30. [ 44.072253] BUG: unable to handle kernel NULL pointer dereference at 0000000000000119 [ 44.072264] IP: [] netlink_getsockbyportid+0xf/0x70 [ 44.072272] PGD 7f2b74067 PUD 7f2b73067 PMD 0 [ 44.072277] Oops: 0000 [#1] SMP [...] [ 44.072369] Call Trace: [ 44.072373] [] netlink_unicast+0x91/0x200 [ 44.072377] [] netlink_ack+0x99/0x110 [ 44.072381] [] nfnetlink_rcv+0x3c1/0x408 [nfnetlink] [ 44.072385] [] netlink_unicast+0xf3/0x200 [ 44.072389] [] netlink_sendmsg+0x2ff/0x740 [ 44.072394] [] ? __mmdrop+0x62/0x90 [ 44.072398] [] sock_sendmsg+0x8b/0xc0 [ 44.072403] [] ? copy_user_enhanced_fast_string+0x5/0x10 [ 44.072406] [] ? move_addr_to_kernel+0x2c/0x50 [ 44.072410] [] ___sys_sendmsg+0x3c3/0x3d0 [ 44.072415] [] ? handle_mm_fault+0xa9a/0xc60 [ 44.072420] [] ? mmap_region+0x166/0x5a0 [ 44.072424] [] ? __do_page_fault+0x1dc/0x510 [ 44.072428] [] ? apparmor_capable+0x1c/0x60 [ 44.072435] [] ? _raw_spin_unlock_bh+0x1a/0x20 [ 44.072439] [] ? release_sock+0x106/0x150 [ 44.072443] [] __sys_sendmsg+0x42/0x80 [ 44.072446] [] SyS_sendmsg+0x12/0x20 [ 44.072450] [] system_call_fastpath+0x1a/0x1f Signed-off-by: Denys Fedoryshchenko Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nfnetlink.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c index e009087620e3..23ef77c60fff 100644 --- a/net/netfilter/nfnetlink.c +++ b/net/netfilter/nfnetlink.c @@ -256,15 +256,15 @@ replay: #endif { nfnl_unlock(subsys_id); - kfree_skb(nskb); - return netlink_ack(skb, nlh, -EOPNOTSUPP); + netlink_ack(skb, nlh, -EOPNOTSUPP); + return kfree_skb(nskb); } } if (!ss->commit || !ss->abort) { nfnl_unlock(subsys_id); - kfree_skb(nskb); - return netlink_ack(skb, nlh, -EOPNOTSUPP); + netlink_ack(skb, nlh, -EOPNOTSUPP); + return kfree_skb(skb); } while (skb->len >= nlmsg_total_size(0)) { -- cgit v1.2.3 From 24a9ad5b82929cdeaff70018d82263de0c34c45d Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Sun, 4 May 2014 21:48:05 +0800 Subject: ahci: imx: add namespace for register enums Update register enums a little bit to add proper namespace prefix, and have the names match i.MX reference manual. Signed-off-by: Shawn Guo Signed-off-by: Tejun Heo --- drivers/ata/ahci_imx.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c index 497c7abe1c7d..776757634e90 100644 --- a/drivers/ata/ahci_imx.c +++ b/drivers/ata/ahci_imx.c @@ -29,9 +29,11 @@ #include "ahci.h" enum { - PORT_PHY_CTL = 0x178, /* Port0 PHY Control */ - PORT_PHY_CTL_PDDQ_LOC = 0x100000, /* PORT_PHY_CTL bits */ - HOST_TIMER1MS = 0xe0, /* Timer 1-ms */ + /* Timer 1-ms Register */ + IMX_TIMER1MS = 0x00e0, + /* Port0 PHY Control Register */ + IMX_P0PHYCR = 0x0178, + IMX_P0PHYCR_TEST_PDDQ = 1 << 20, }; enum ahci_imx_type { @@ -156,8 +158,8 @@ static void ahci_imx_error_handler(struct ata_port *ap) * without full reset once the pddq mode is enabled making it * impossible to use as part of libata LPM. */ - reg_val = readl(mmio + PORT_PHY_CTL); - writel(reg_val | PORT_PHY_CTL_PDDQ_LOC, mmio + PORT_PHY_CTL); + reg_val = readl(mmio + IMX_P0PHYCR); + writel(reg_val | IMX_P0PHYCR_TEST_PDDQ, mmio + IMX_P0PHYCR); imx_sata_disable(hpriv); imxpriv->no_device = true; } @@ -248,7 +250,7 @@ static int imx_ahci_probe(struct platform_device *pdev) /* * Configure the HWINIT bits of the HOST_CAP and HOST_PORTS_IMPL, - * and IP vendor specific register HOST_TIMER1MS. + * and IP vendor specific register IMX_TIMER1MS. * Configure CAP_SSS (support stagered spin up). * Implement the port0. * Get the ahb clock rate, and configure the TIMER1MS register. @@ -265,7 +267,7 @@ static int imx_ahci_probe(struct platform_device *pdev) } reg_val = clk_get_rate(imxpriv->ahb_clk) / 1000; - writel(reg_val, hpriv->mmio + HOST_TIMER1MS); + writel(reg_val, hpriv->mmio + IMX_TIMER1MS); ret = ahci_platform_init_host(pdev, hpriv, &ahci_imx_port_info, 0, 0); if (ret) -- cgit v1.2.3 From e783c51cce94521c10e599e991acdcfd9a996c4a Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Sun, 4 May 2014 21:48:06 +0800 Subject: ahci: imx: software workaround for phy reset issue in resume When suspending imx6q systems which have rootfs on SATA, the following error will likely be seen in resume. The SATA link will fail to come up, and it results in an unusable system across the suspend/resume cycle. $ echo mem > /sys/power/state PM: Syncing filesystems ... done. PM: Preparing system for mem sleep Freezing user space processes ... (elapsed 0.002 seconds) done. Freezing remaining freezable tasks ... (elapsed 0.002 seconds) done. PM: Entering mem sleep sd 0:0:0:0: [sda] Synchronizing SCSI cache sd 0:0:0:0: [sda] Stopping disk PM: suspend of devices complete after 61.914 msecs PM: suspend devices took 0.070 seconds PM: late suspend of devices complete after 4.906 msecs PM: noirq suspend of devices complete after 4.521 msecs Disabling non-boot CPUs ... CPU1: shutdown CPU2: shutdown CPU3: shutdown Enabling non-boot CPUs ... CPU1: Booted secondary processor CPU1 is up CPU2: Booted secondary processor CPU2 is up CPU3: Booted secondary processor CPU3 is up PM: noirq resume of devices complete after 10.486 msecs PM: early resume of devices complete after 4.679 msecs sd 0:0:0:0: [sda] Starting disk PM: resume of devices complete after 22.674 msecs PM: resume devices took 0.030 seconds PM: Finishing wakeup. Restarting tasks ... done. $ ata1: SATA link down (SStatus 1 SControl 300) ata1: SATA link down (SStatus 1 SControl 300) ata1: limiting SATA link speed to 1.5 Gbps ata1: SATA link down (SStatus 1 SControl 310) ata1.00: disabled ata1: exception Emask 0x10 SAct 0x0 SErr 0x4040000 action 0xe frozen t4 ata1: irq_stat 0x00000040, connection status changed ata1: SError: { CommWake DevExch } ata1: hard resetting link sd 0:0:0:0: rejecting I/O to offline device sd 0:0:0:0: killing request sd 0:0:0:0: rejecting I/O to offline device Aborting journal on device sda2-8. sd 0:0:0:0: rejecting I/O to offline device EXT4-fs warning (device sda2): ext4_end_bio:317: I/O error writing to inode 132577 (offset 0 size 0 starting block 26235) Buffer I/O error on device sda2, logical block 10169 ... It's caused by a silicon issue that SATA phy does not get reset by controller when coming back from LPM. The patch adds a software workaround for this issue. It enforces a software reset on SATA phy in imx_sata_enable() function, so that we can ensure SATA link will come up properly in both power-on and resume. The software reset is implemented by writing phy reset register through the phy control register bus interface. Functions imx_phy_reg_[addressing|write|read]() implement this bus interface, while imx_sata_phy_reset() performs the actually reset operation. Signed-off-by: Richard Zhu Signed-off-by: Shawn Guo Signed-off-by: Tejun Heo --- drivers/ata/ahci_imx.c | 161 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 161 insertions(+) diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c index 776757634e90..5824d99e63fd 100644 --- a/drivers/ata/ahci_imx.c +++ b/drivers/ata/ahci_imx.c @@ -34,6 +34,20 @@ enum { /* Port0 PHY Control Register */ IMX_P0PHYCR = 0x0178, IMX_P0PHYCR_TEST_PDDQ = 1 << 20, + IMX_P0PHYCR_CR_READ = 1 << 19, + IMX_P0PHYCR_CR_WRITE = 1 << 18, + IMX_P0PHYCR_CR_CAP_DATA = 1 << 17, + IMX_P0PHYCR_CR_CAP_ADDR = 1 << 16, + /* Port0 PHY Status Register */ + IMX_P0PHYSR = 0x017c, + IMX_P0PHYSR_CR_ACK = 1 << 18, + IMX_P0PHYSR_CR_DATA_OUT = 0xffff << 0, + /* Lane0 Output Status Register */ + IMX_LANE0_OUT_STAT = 0x2003, + IMX_LANE0_OUT_STAT_RX_PLL_STATE = 1 << 1, + /* Clock Reset Register */ + IMX_CLOCK_RESET = 0x7f3f, + IMX_CLOCK_RESET_RESET = 1 << 0, }; enum ahci_imx_type { @@ -56,9 +70,149 @@ MODULE_PARM_DESC(hotplug, "AHCI IMX hot-plug support (0=Don't support, 1=support static void ahci_imx_host_stop(struct ata_host *host); +static int imx_phy_crbit_assert(void __iomem *mmio, u32 bit, bool assert) +{ + int timeout = 10; + u32 crval; + u32 srval; + + /* Assert or deassert the bit */ + crval = readl(mmio + IMX_P0PHYCR); + if (assert) + crval |= bit; + else + crval &= ~bit; + writel(crval, mmio + IMX_P0PHYCR); + + /* Wait for the cr_ack signal */ + do { + srval = readl(mmio + IMX_P0PHYSR); + if ((assert ? srval : ~srval) & IMX_P0PHYSR_CR_ACK) + break; + usleep_range(100, 200); + } while (--timeout); + + return timeout ? 0 : -ETIMEDOUT; +} + +static int imx_phy_reg_addressing(u16 addr, void __iomem *mmio) +{ + u32 crval = addr; + int ret; + + /* Supply the address on cr_data_in */ + writel(crval, mmio + IMX_P0PHYCR); + + /* Assert the cr_cap_addr signal */ + ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_CAP_ADDR, true); + if (ret) + return ret; + + /* Deassert cr_cap_addr */ + ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_CAP_ADDR, false); + if (ret) + return ret; + + return 0; +} + +static int imx_phy_reg_write(u16 val, void __iomem *mmio) +{ + u32 crval = val; + int ret; + + /* Supply the data on cr_data_in */ + writel(crval, mmio + IMX_P0PHYCR); + + /* Assert the cr_cap_data signal */ + ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_CAP_DATA, true); + if (ret) + return ret; + + /* Deassert cr_cap_data */ + ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_CAP_DATA, false); + if (ret) + return ret; + + if (val & IMX_CLOCK_RESET_RESET) { + /* + * In case we're resetting the phy, it's unable to acknowledge, + * so we return immediately here. + */ + crval |= IMX_P0PHYCR_CR_WRITE; + writel(crval, mmio + IMX_P0PHYCR); + goto out; + } + + /* Assert the cr_write signal */ + ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_WRITE, true); + if (ret) + return ret; + + /* Deassert cr_write */ + ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_WRITE, false); + if (ret) + return ret; + +out: + return 0; +} + +static int imx_phy_reg_read(u16 *val, void __iomem *mmio) +{ + int ret; + + /* Assert the cr_read signal */ + ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_READ, true); + if (ret) + return ret; + + /* Capture the data from cr_data_out[] */ + *val = readl(mmio + IMX_P0PHYSR) & IMX_P0PHYSR_CR_DATA_OUT; + + /* Deassert cr_read */ + ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_READ, false); + if (ret) + return ret; + + return 0; +} + +static int imx_sata_phy_reset(struct ahci_host_priv *hpriv) +{ + void __iomem *mmio = hpriv->mmio; + int timeout = 10; + u16 val; + int ret; + + /* Reset SATA PHY by setting RESET bit of PHY register CLOCK_RESET */ + ret = imx_phy_reg_addressing(IMX_CLOCK_RESET, mmio); + if (ret) + return ret; + ret = imx_phy_reg_write(IMX_CLOCK_RESET_RESET, mmio); + if (ret) + return ret; + + /* Wait for PHY RX_PLL to be stable */ + do { + usleep_range(100, 200); + ret = imx_phy_reg_addressing(IMX_LANE0_OUT_STAT, mmio); + if (ret) + return ret; + ret = imx_phy_reg_read(&val, mmio); + if (ret) + return ret; + if (val & IMX_LANE0_OUT_STAT_RX_PLL_STATE) + break; + } while (--timeout); + + return timeout ? 0 : -ETIMEDOUT; +} + static int imx_sata_enable(struct ahci_host_priv *hpriv) { struct imx_ahci_priv *imxpriv = hpriv->plat_data; + struct device *dev = &imxpriv->ahci_pdev->dev; int ret; if (imxpriv->no_device) @@ -103,6 +257,12 @@ static int imx_sata_enable(struct ahci_host_priv *hpriv) regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13, IMX6Q_GPR13_SATA_MPLL_CLK_EN, IMX6Q_GPR13_SATA_MPLL_CLK_EN); + + ret = imx_sata_phy_reset(hpriv); + if (ret) { + dev_err(dev, "failed to reset phy: %d\n", ret); + goto disable_regulator; + } } usleep_range(1000, 2000); @@ -219,6 +379,7 @@ static int imx_ahci_probe(struct platform_device *pdev) if (!imxpriv) return -ENOMEM; + imxpriv->ahci_pdev = pdev; imxpriv->no_device = false; imxpriv->first_time = true; imxpriv->type = (enum ahci_imx_type)of_id->data; -- cgit v1.2.3 From f5f3cf6f7e49b9529fc00a2c4629fa92cf2755fe Mon Sep 17 00:00:00 2001 From: Aristeu Rozanski Date: Thu, 24 Apr 2014 15:33:21 -0400 Subject: device_cgroup: fix the comment format for recently added functions Moving more extensive explanations to the end of the comment. Cc: Li Zefan Signed-off-by: Aristeu Rozanski Acked-by: Serge Hallyn Signed-off-by: Tejun Heo --- security/device_cgroup.c | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/security/device_cgroup.c b/security/device_cgroup.c index b9048dc46b1a..6b1266dd92bb 100644 --- a/security/device_cgroup.c +++ b/security/device_cgroup.c @@ -306,17 +306,17 @@ static int devcgroup_seq_show(struct seq_file *m, void *v) } /** - * match_exception - iterates the exception list trying to match a rule - * based on type, major, minor and access type. It is - * considered a match if an exception is found that - * will contain the entire range of provided parameters. + * match_exception - iterates the exception list trying to find a complete match * @exceptions: list of exceptions * @type: device type (DEV_BLOCK or DEV_CHAR) * @major: device file major number, ~0 to match all * @minor: device file minor number, ~0 to match all * @access: permission mask (ACC_READ, ACC_WRITE, ACC_MKNOD) * - * returns: true in case it matches an exception completely + * It is considered a complete match if an exception is found that will + * contain the entire range of provided parameters. + * + * Return: true in case it matches an exception completely */ static bool match_exception(struct list_head *exceptions, short type, u32 major, u32 minor, short access) @@ -341,20 +341,19 @@ static bool match_exception(struct list_head *exceptions, short type, } /** - * match_exception_partial - iterates the exception list trying to match a rule - * based on type, major, minor and access type. It is - * considered a match if an exception's range is - * found to contain *any* of the devices specified by - * provided parameters. This is used to make sure no - * extra access is being granted that is forbidden by - * any of the exception list. + * match_exception_partial - iterates the exception list trying to find a partial match * @exceptions: list of exceptions * @type: device type (DEV_BLOCK or DEV_CHAR) * @major: device file major number, ~0 to match all * @minor: device file minor number, ~0 to match all * @access: permission mask (ACC_READ, ACC_WRITE, ACC_MKNOD) * - * returns: true in case the provided range mat matches an exception completely + * It is considered a partial match if an exception's range is found to + * contain *any* of the devices specified by provided parameters. This is + * used to make sure no extra access is being granted that is forbidden by + * any of the exception list. + * + * Return: true in case the provided range mat matches an exception completely */ static bool match_exception_partial(struct list_head *exceptions, short type, u32 major, u32 minor, short access) @@ -387,13 +386,13 @@ static bool match_exception_partial(struct list_head *exceptions, short type, } /** - * verify_new_ex - verifies if a new exception is part of what is allowed - * by a dev cgroup based on the default policy + - * exceptions. This is used to make sure a child cgroup - * won't have more privileges than its parent + * verify_new_ex - verifies if a new exception is allowed by parent cgroup's permissions * @dev_cgroup: dev cgroup to be tested against * @refex: new exception * @behavior: behavior of the exception's dev_cgroup + * + * This is used to make sure a child cgroup won't have more privileges + * than its parent */ static bool verify_new_ex(struct dev_cgroup *dev_cgroup, struct dev_exception_item *refex, -- cgit v1.2.3 From 3cf0b0311e746a26dcc7c0b5ba0756f61d636a33 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 3 May 2014 23:27:00 +0300 Subject: agp: info leak in agpioc_info_wrap() On 64 bit systems the agp_info struct has a 4 byte hole between ->agp_mode and ->aper_base. We need to clear it to avoid disclosing stack information to userspace. Signed-off-by: Dan Carpenter Signed-off-by: Dave Airlie --- drivers/char/agp/frontend.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/char/agp/frontend.c b/drivers/char/agp/frontend.c index 8121b4c70ede..b29703324e94 100644 --- a/drivers/char/agp/frontend.c +++ b/drivers/char/agp/frontend.c @@ -730,6 +730,7 @@ static int agpioc_info_wrap(struct agp_file_private *priv, void __user *arg) agp_copy_info(agp_bridge, &kerninfo); + memset(&userinfo, 0, sizeof(userinfo)); userinfo.version.major = kerninfo.version.major; userinfo.version.minor = kerninfo.version.minor; userinfo.bridge_id = kerninfo.device->vendor | -- cgit v1.2.3 From 788296b2d19d16ec33aba0a5ad1544d50bb58601 Mon Sep 17 00:00:00 2001 From: Sebastian Hesselbarth Date: Wed, 30 Apr 2014 14:56:28 +0200 Subject: ARM: dts: kirkwood: fix mislocated pcie-controller nodes Commit 54397d85349f ("ARM: kirkwood: Relocate PCIe device tree nodes") moved the pcie-controller nodes for the Kirkwood SoCs to the mbus bus node. For some reason, two boards were not properly converted and have their pci-controller nodes still in the ocp bus node. As the corresponding SoC pcie-controller does not exist anymore, it is likely that pcie is broken on those boards since above commit. Fix it by moving the pcie related nodes to the correct location. Signed-off-by: Sebastian Hesselbarth Fixes: 54397d85349f ("ARM: kirkwood: Relocate PCIe device tree nodes") Cc: # v3.12+ Acked-by: Andrew Lunn Link: https://lkml.kernel.org/r/1398862602-29595-2-git-send-email-sebastian.hesselbarth@gmail.com Signed-off-by: Jason Cooper --- arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts | 18 ++++++++++-------- arch/arm/boot/dts/kirkwood-nsa310-common.dtsi | 18 ++++++++++-------- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts b/arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts index 2cb0dc529165..4bf358c28be2 100644 --- a/arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts +++ b/arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts @@ -30,6 +30,16 @@ bootargs = "console=ttyS0,115200n8 earlyprintk"; }; + mbus { + pcie-controller { + status = "okay"; + + pcie@1,0 { + status = "okay"; + }; + }; + }; + ocp@f1000000 { pinctrl@10000 { pmx_usb_led: pmx-usb-led { @@ -73,14 +83,6 @@ ehci@50000 { status = "okay"; }; - - pcie-controller { - status = "okay"; - - pcie@1,0 { - status = "okay"; - }; - }; }; gpio-leds { diff --git a/arch/arm/boot/dts/kirkwood-nsa310-common.dtsi b/arch/arm/boot/dts/kirkwood-nsa310-common.dtsi index aa78c2d11fe7..e2cc85cc3b87 100644 --- a/arch/arm/boot/dts/kirkwood-nsa310-common.dtsi +++ b/arch/arm/boot/dts/kirkwood-nsa310-common.dtsi @@ -4,6 +4,16 @@ / { model = "ZyXEL NSA310"; + mbus { + pcie-controller { + status = "okay"; + + pcie@1,0 { + status = "okay"; + }; + }; + }; + ocp@f1000000 { pinctrl: pinctrl@10000 { @@ -26,14 +36,6 @@ status = "okay"; nr-ports = <2>; }; - - pcie-controller { - status = "okay"; - - pcie@1,0 { - status = "okay"; - }; - }; }; gpio_poweroff { -- cgit v1.2.3 From c99d609a16506602a7398eea7d12b13513f3d889 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Mon, 5 May 2014 16:18:37 +1000 Subject: xfs: fully support v5 format filesystems We have had this code in the kernel for over a year now and have shaken all the known issues out of the code over the past few releases. It's now time to remove the experimental warnings during mount and fully support the new filesystem format in production systems. Remove the experimental warning, and add a version number to the initial "mounting filesystem" message to tell use what type of filesystem is being mounted. Also, remove the temporary inode cluster size output at mount time now we know that this code works fine. Signed-off-by: Dave Chinner Reviewed-by: Brian Foster Signed-off-by: Dave Chinner --- fs/xfs/xfs_log.c | 10 ++++++---- fs/xfs/xfs_mount.c | 2 -- fs/xfs/xfs_sb.c | 4 ---- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 08624dc67317..a5f8bd9899d3 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c @@ -616,11 +616,13 @@ xfs_log_mount( int error = 0; int min_logfsbs; - if (!(mp->m_flags & XFS_MOUNT_NORECOVERY)) - xfs_notice(mp, "Mounting Filesystem"); - else { + if (!(mp->m_flags & XFS_MOUNT_NORECOVERY)) { + xfs_notice(mp, "Mounting V%d Filesystem", + XFS_SB_VERSION_NUM(&mp->m_sb)); + } else { xfs_notice(mp, -"Mounting filesystem in no-recovery mode. Filesystem will be inconsistent."); +"Mounting V%d filesystem in no-recovery mode. Filesystem will be inconsistent.", + XFS_SB_VERSION_NUM(&mp->m_sb)); ASSERT(mp->m_flags & XFS_MOUNT_RDONLY); } diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 993cb19e7d39..944f3d9456a8 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -743,8 +743,6 @@ xfs_mountfs( new_size *= mp->m_sb.sb_inodesize / XFS_DINODE_MIN_SIZE; if (mp->m_sb.sb_inoalignmt >= XFS_B_TO_FSBT(mp, new_size)) mp->m_inode_cluster_size = new_size; - xfs_info(mp, "Using inode cluster size of %d bytes", - mp->m_inode_cluster_size); } /* diff --git a/fs/xfs/xfs_sb.c b/fs/xfs/xfs_sb.c index 0c0e41bbe4e3..8baf61afae1d 100644 --- a/fs/xfs/xfs_sb.c +++ b/fs/xfs/xfs_sb.c @@ -201,10 +201,6 @@ xfs_mount_validate_sb( * write validation, we don't need to check feature masks. */ if (check_version && XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) { - xfs_alert(mp, -"Version 5 superblock detected. This kernel has EXPERIMENTAL support enabled!\n" -"Use of these features in this kernel is at your own risk!"); - if (xfs_sb_has_compat_feature(sbp, XFS_SB_FEAT_COMPAT_UNKNOWN)) { xfs_warn(mp, -- cgit v1.2.3 From f4ebddf9abb1fb0add1ce8e9c0bc414f1c17d81d Mon Sep 17 00:00:00 2001 From: Henning Rogge Date: Thu, 1 May 2014 10:03:46 +0200 Subject: mac80211: Fix mac80211 station info rx bitrate for IBSS mode Filter out incoming multicast packages before applying their bitrate to the rx bitrate station info field to prevent them from setting the rx bitrate to the basic multicast rate. Signed-off-by: Henning Rogge Signed-off-by: Johannes Berg --- net/mac80211/rx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 216c45b949e5..2b608b2b70ec 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1231,7 +1231,8 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) if (ether_addr_equal(bssid, rx->sdata->u.ibss.bssid) && test_sta_flag(sta, WLAN_STA_AUTHORIZED)) { sta->last_rx = jiffies; - if (ieee80211_is_data(hdr->frame_control)) { + if (ieee80211_is_data(hdr->frame_control) && + !is_multicast_ether_addr(hdr->addr1)) { sta->last_rx_rate_idx = status->rate_idx; sta->last_rx_rate_flag = status->flag; sta->last_rx_rate_vht_flag = status->vht_flag; -- cgit v1.2.3 From c1fbb258846dfc425507a093922d2d001e54c3ea Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 30 Apr 2014 15:58:13 +0300 Subject: cfg80211: free sme on connection failures cfg80211 is notified about connection failures by __cfg80211_connect_result() call. However, this function currently does not free cfg80211 sme. This results in hanging connection attempts in some cases e.g. when mac80211 authentication attempt is denied, we have this function call: ieee80211_rx_mgmt_auth() -> cfg80211_rx_mlme_mgmt() -> cfg80211_process_auth() -> cfg80211_sme_rx_auth() -> __cfg80211_connect_result() but cfg80211_sme_free() is never get called. Fixes: ceca7b712 ("cfg80211: separate internal SME implementation") Cc: stable@vger.kernel.org (3.10+) Signed-off-by: Eliad Peller Signed-off-by: Johannes Berg --- net/wireless/sme.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/wireless/sme.c b/net/wireless/sme.c index acdcb4a81817..3546a77033de 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c @@ -234,7 +234,6 @@ void cfg80211_conn_work(struct work_struct *work) NULL, 0, NULL, 0, WLAN_STATUS_UNSPECIFIED_FAILURE, false, NULL); - cfg80211_sme_free(wdev); } wdev_unlock(wdev); } @@ -648,6 +647,7 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, cfg80211_unhold_bss(bss_from_pub(bss)); cfg80211_put_bss(wdev->wiphy, bss); } + cfg80211_sme_free(wdev); return; } -- cgit v1.2.3 From 792e6aa7a15ea0fb16f8687e93caede1ea9118c7 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 30 Apr 2014 16:14:23 +0300 Subject: cfg80211: add cfg80211_sched_scan_stopped_rtnl Add locked-version for cfg80211_sched_scan_stopped. This is used for some users that might want to call it when rtnl is already locked. Fixes: d43c6b6 ("mac80211: reschedule sched scan after HW restart") Cc: stable@vger.kernel.org (3.14+) Signed-off-by: Eliad Peller Signed-off-by: Johannes Berg --- include/net/cfg80211.h | 12 ++++++++++++ net/wireless/scan.c | 12 ++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index f3539a15c411..f856e5a746fa 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -3668,6 +3668,18 @@ void cfg80211_sched_scan_results(struct wiphy *wiphy); */ void cfg80211_sched_scan_stopped(struct wiphy *wiphy); +/** + * cfg80211_sched_scan_stopped_rtnl - notify that the scheduled scan has stopped + * + * @wiphy: the wiphy on which the scheduled scan stopped + * + * The driver can call this function to inform cfg80211 that the + * scheduled scan had to be stopped, for whatever reason. The driver + * is then called back via the sched_scan_stop operation when done. + * This function should be called with rtnl locked. + */ +void cfg80211_sched_scan_stopped_rtnl(struct wiphy *wiphy); + /** * cfg80211_inform_bss_width_frame - inform cfg80211 of a received BSS frame * diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 7d09a712cb1f..88f108edfb58 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -284,14 +284,22 @@ void cfg80211_sched_scan_results(struct wiphy *wiphy) } EXPORT_SYMBOL(cfg80211_sched_scan_results); -void cfg80211_sched_scan_stopped(struct wiphy *wiphy) +void cfg80211_sched_scan_stopped_rtnl(struct wiphy *wiphy) { struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); + ASSERT_RTNL(); + trace_cfg80211_sched_scan_stopped(wiphy); - rtnl_lock(); __cfg80211_stop_sched_scan(rdev, true); +} +EXPORT_SYMBOL(cfg80211_sched_scan_stopped_rtnl); + +void cfg80211_sched_scan_stopped(struct wiphy *wiphy) +{ + rtnl_lock(); + cfg80211_sched_scan_stopped_rtnl(wiphy); rtnl_unlock(); } EXPORT_SYMBOL(cfg80211_sched_scan_stopped); -- cgit v1.2.3 From e669ba2d06c6195662601956454ac959892f0762 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 30 Apr 2014 16:14:24 +0300 Subject: mac80211: fix nested rtnl locking on ieee80211_reconfig ieee80211_reconfig already holds rtnl, so calling cfg80211_sched_scan_stopped results in deadlock. Use the rtnl-version of this function instead. Fixes: d43c6b6 ("mac80211: reschedule sched scan after HW restart") Cc: stable@vger.kernel.org (3.14+) Signed-off-by: Eliad Peller Signed-off-by: Johannes Berg --- net/mac80211/util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 275c94f995f7..3c365837e910 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -1780,7 +1780,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) mutex_unlock(&local->mtx); if (sched_scan_stopped) - cfg80211_sched_scan_stopped(local->hw.wiphy); + cfg80211_sched_scan_stopped_rtnl(local->hw.wiphy); /* * If this is for hw restart things are still running. -- cgit v1.2.3 From 19e4ec525b37cdecbdb4f86edaae7f56a67339ee Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Wed, 30 Apr 2014 17:48:40 -0400 Subject: HID: core: fix computation of the report size The extra seven bits are only required when allocating the report buffer. We can not use those extra bytes for the length of the report in the generic implementation of .request because the device might (will) refuse the set_report command. This has been verified on the Atmel touchpad found on the Samsung Ativ 9 plus, which uses hid-multitouch and HID over I2C. Without this fix, the device refuses to switch to the multitouch mode, and it becomes unresponsive from the user point of view. Actually, this has been discussed during the initial submission of the commit 4fa5a7f76cc7b6ac87f57741edd2b124851d119f, see https://patchwork.kernel.org/patch/3621751/ Unfortunately, I completely forgot about it later. Reported-by: Matthias Bayer Signed-off-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 10a2c0866459..da52279de939 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1253,7 +1253,8 @@ EXPORT_SYMBOL_GPL(hid_output_report); static int hid_report_len(struct hid_report *report) { - return ((report->size - 1) >> 3) + 1 + (report->id > 0) + 7; + /* equivalent to DIV_ROUND_UP(report->size, 8) + !!(report->id > 0) */ + return ((report->size - 1) >> 3) + 1 + (report->id > 0); } /* @@ -1266,7 +1267,7 @@ u8 *hid_alloc_report_buf(struct hid_report *report, gfp_t flags) * of implement() working on 8 byte chunks */ - int len = hid_report_len(report); + int len = hid_report_len(report) + 7; return kmalloc(len, flags); } -- cgit v1.2.3 From 2f433083e854ec72c19dc9b0e1cebcc8e230fd75 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 2 May 2014 19:48:13 +0200 Subject: HID: add NO_INIT_REPORTS quirk for Synaptics Touch Pad V 103S This touchpad seriously dislikes init reports, not only timeing out, but also refusing to work after this. Cc: stable@vger.kernel.org Reported-and-tested-by: Vincent Fortier Signed-off-by: Hans de Goede Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-ids.h | 1 + drivers/hid/usbhid/hid-quirks.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index e7e44f53db59..5c75774cdaf2 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -837,6 +837,7 @@ #define USB_DEVICE_ID_SYNAPTICS_LTS2 0x1d10 #define USB_DEVICE_ID_SYNAPTICS_HD 0x0ac3 #define USB_DEVICE_ID_SYNAPTICS_QUAD_HD 0x1ac3 +#define USB_DEVICE_ID_SYNAPTICS_TP_V103 0x5710 #define USB_VENDOR_ID_THINGM 0x27b8 #define USB_DEVICE_ID_BLINK1 0x01ed diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index dbd83878ff99..8e4ddb369883 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -119,6 +119,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_LTS2, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_HD, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_QUAD_HD, HID_QUIRK_NO_INIT_REPORTS }, + { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_TP_V103, HID_QUIRK_NO_INIT_REPORTS }, { 0, 0 } }; -- cgit v1.2.3 From 7c3d5ab1f35f5475b1a1fbe74143683cfc092d33 Mon Sep 17 00:00:00 2001 From: Vasily Averin Date: Sat, 3 May 2014 03:14:04 +0400 Subject: ipv4: fix "conntrack zones" support for defrag user check in ip_expire Defrag user check in ip_expire was not updated after adding support for "conntrack zones". This bug manifests as a RFC violation, since the router will send the icmp time exceeeded message when using conntrack zones. Signed-off-by: Vasily Averin Signed-off-by: Pablo Neira Ayuso --- net/ipv4/ip_fragment.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index c10a3ce5cbff..ed32313e307c 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c @@ -232,8 +232,9 @@ static void ip_expire(unsigned long arg) * "Fragment Reassembly Timeout" message, per RFC792. */ if (qp->user == IP_DEFRAG_AF_PACKET || - (qp->user == IP_DEFRAG_CONNTRACK_IN && - skb_rtable(head)->rt_type != RTN_LOCAL)) + ((qp->user >= IP_DEFRAG_CONNTRACK_IN) && + (qp->user <= __IP_DEFRAG_CONNTRACK_IN_END) && + (skb_rtable(head)->rt_type != RTN_LOCAL))) goto out_rcu_unlock; -- cgit v1.2.3 From aff09ce303f83bd370772349238482ae422a2341 Mon Sep 17 00:00:00 2001 From: Vasily Averin Date: Mon, 5 May 2014 00:17:48 +0400 Subject: bridge: superfluous skb->nfct check in br_nf_dev_queue_xmit Currently bridge can silently drop ipv4 fragments. If node have loaded nf_defrag_ipv4 module but have no nf_conntrack_ipv4, br_nf_pre_routing defragments incoming ipv4 fragments but nfct check in br_nf_dev_queue_xmit does not allow re-fragment combined packet back, and therefore it is dropped in br_dev_queue_push_xmit without incrementing of any failcounters It seems the only way to hit the ip_fragment code in the bridge xmit path is to have a fragment list whose reassembled fragments go over the mtu. This only happens if nf_defrag is enabled. Thanks to Florian Westphal for providing feedback to clarify this. Defragmentation ipv4 is required not only in conntracks but at least in TPROXY target and socket match, therefore #ifdef is changed from NF_CONNTRACK_IPV4 to NF_DEFRAG_IPV4 Signed-off-by: Vasily Averin Signed-off-by: Pablo Neira Ayuso --- net/bridge/br_netfilter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 80e1b0f60a30..2acf7fa1fec6 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c @@ -859,12 +859,12 @@ static unsigned int br_nf_forward_arp(const struct nf_hook_ops *ops, return NF_STOLEN; } -#if IS_ENABLED(CONFIG_NF_CONNTRACK_IPV4) +#if IS_ENABLED(CONFIG_NF_DEFRAG_IPV4) static int br_nf_dev_queue_xmit(struct sk_buff *skb) { int ret; - if (skb->nfct != NULL && skb->protocol == htons(ETH_P_IP) && + if (skb->protocol == htons(ETH_P_IP) && skb->len + nf_bridge_mtu_reduction(skb) > skb->dev->mtu && !skb_is_gso(skb)) { if (br_parse_ip_options(skb)) -- cgit v1.2.3 From f06ab794af7055d0949b09885f79f8b493deec64 Mon Sep 17 00:00:00 2001 From: Anssi Hannula Date: Mon, 5 May 2014 02:38:43 +0300 Subject: ALSA: hda - hdmi: Set converter channel count even without sink Since commit 1df5a06a ("ALSA: hda - hdmi: Fix programmed active channel count") channel count is no longer being set if monitor_present is 0. This is because setting the count was moved after the CA value is determined, which is only after the monitor_present check in hdmi_setup_audio_infoframe(). Unfortunately, in some cases, such as with a non-spec-compliant codec or with a problematic video driver, monitor_present is always 0. As a specific example, this seems to happen with gen1 ATV (SiI1390 codec), causing left-channel-only stereo playback (multi-channel playback has apparently never worked with this codec despite it reporting 8 channels, reason unknown). Simply setting converter channel count without setting the pin infoframe and channel mapping as well does not theoretically make much sense as this will just mean they are out-of-sync and multichannel playback will have a wrong channel mapping. However, adding back just setting the converter channel count even in no-monitor case is the safest change which at least fixes the stereo playback regression on SiI1390 codec. Do that. Signed-off-by: Anssi Hannula Reported-by: Stephan Raue Tested-by: Stephan Raue Cc: # 3.12+ Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 0cb5b89cd0c8..1edbb9c47c2d 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -1127,8 +1127,10 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, AMP_OUT_UNMUTE); eld = &per_pin->sink_eld; - if (!eld->monitor_present) + if (!eld->monitor_present) { + hdmi_set_channel_count(codec, per_pin->cvt_nid, channels); return; + } if (!non_pcm && per_pin->chmap_set) ca = hdmi_manual_channel_allocation(channels, per_pin->chmap); -- cgit v1.2.3 From d2c2b11cfa134f4fbdcc34088824da26a084d8de Mon Sep 17 00:00:00 2001 From: Aristeu Rozanski Date: Mon, 5 May 2014 11:18:59 -0400 Subject: device_cgroup: check if exception removal is allowed [PATCH v3 1/2] device_cgroup: check if exception removal is allowed When the device cgroup hierarchy was introduced in bd2953ebbb53 - devcg: propagate local changes down the hierarchy a specific case was overlooked. Consider the hierarchy bellow: A default policy: ALLOW, exceptions will deny access \ B default policy: ALLOW, exceptions will deny access There's no need to verify when an new exception is added to B because in this case exceptions will deny access to further devices, which is always fine. Hierarchy in device cgroup only makes sure B won't have more access than A. But when an exception is removed (by writing devices.allow), it isn't checked if the user is in fact removing an inherited exception from A, thus giving more access to B. Example: # echo 'a' >A/devices.allow # echo 'c 1:3 rw' >A/devices.deny # echo $$ >A/B/tasks # echo >/dev/null -bash: /dev/null: Operation not permitted # echo 'c 1:3 w' >A/B/devices.allow # echo >/dev/null # This shouldn't be allowed and this patch fixes it by making sure to never allow exceptions in this case to be removed if the exception is partially or fully present on the parent. v3: missing '*' in function description v2: improved log message and formatting fixes Cc: cgroups@vger.kernel.org Cc: Li Zefan Cc: stable@vger.kernel.org Signed-off-by: Aristeu Rozanski Acked-by: Serge Hallyn Signed-off-by: Tejun Heo --- security/device_cgroup.c | 41 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/security/device_cgroup.c b/security/device_cgroup.c index 6b1266dd92bb..9134dbf70d3e 100644 --- a/security/device_cgroup.c +++ b/security/device_cgroup.c @@ -462,6 +462,37 @@ static int parent_has_perm(struct dev_cgroup *childcg, return verify_new_ex(parent, ex, childcg->behavior); } +/** + * parent_allows_removal - verify if it's ok to remove an exception + * @childcg: child cgroup from where the exception will be removed + * @ex: exception being removed + * + * When removing an exception in cgroups with default ALLOW policy, it must + * be checked if removing it will give the child cgroup more access than the + * parent. + * + * Return: true if it's ok to remove exception, false otherwise + */ +static bool parent_allows_removal(struct dev_cgroup *childcg, + struct dev_exception_item *ex) +{ + struct dev_cgroup *parent = css_to_devcgroup(css_parent(&childcg->css)); + + if (!parent) + return true; + + /* It's always allowed to remove access to devices */ + if (childcg->behavior == DEVCG_DEFAULT_DENY) + return true; + + /* + * Make sure you're not removing part or a whole exception existing in + * the parent cgroup + */ + return !match_exception_partial(&parent->exceptions, ex->type, + ex->major, ex->minor, ex->access); +} + /** * may_allow_all - checks if it's possible to change the behavior to * allow based on parent's rules. @@ -697,17 +728,21 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup, switch (filetype) { case DEVCG_ALLOW: - if (!parent_has_perm(devcgroup, &ex)) - return -EPERM; /* * If the default policy is to allow by default, try to remove * an matching exception instead. And be silent about it: we * don't want to break compatibility */ if (devcgroup->behavior == DEVCG_DEFAULT_ALLOW) { + /* Check if the parent allows removing it first */ + if (!parent_allows_removal(devcgroup, &ex)) + return -EPERM; dev_exception_rm(devcgroup, &ex); - return 0; + break; } + + if (!parent_has_perm(devcgroup, &ex)) + return -EPERM; rc = dev_exception_add(devcgroup, &ex); break; case DEVCG_DENY: -- cgit v1.2.3 From 36c38fb7144aa941dc072ba8f58b2dbe509c0345 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 5 May 2014 12:37:30 -0400 Subject: blkcg: use trylock on blkcg_pol_mutex in blkcg_reset_stats() During the recent conversion of cgroup to kernfs, cgroup_tree_mutex which nests above both the kernfs s_active protection and cgroup_mutex is added to synchronize cgroup file type operations as cgroup_mutex needed to be grabbed from some file operations and thus can't be put above s_active protection. While this arrangement mostly worked for cgroup, this triggered the following lockdep warning. ====================================================== [ INFO: possible circular locking dependency detected ] 3.15.0-rc3-next-20140430-sasha-00016-g4e281fa-dirty #429 Tainted: G W ------------------------------------------------------- trinity-c173/9024 is trying to acquire lock: (blkcg_pol_mutex){+.+.+.}, at: blkcg_reset_stats (include/linux/spinlock.h:328 block/blk-cgroup.c:455) but task is already holding lock: (s_active#89){++++.+}, at: kernfs_fop_write (fs/kernfs/file.c:283) which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #2 (s_active#89){++++.+}: lock_acquire (arch/x86/include/asm/current.h:14 kernel/locking/lockdep.c:3602) __kernfs_remove (arch/x86/include/asm/atomic.h:27 fs/kernfs/dir.c:352 fs/kernfs/dir.c:1024) kernfs_remove_by_name_ns (fs/kernfs/dir.c:1219) cgroup_addrm_files (include/linux/kernfs.h:427 kernel/cgroup.c:1074 kernel/cgroup.c:2899) cgroup_clear_dir (kernel/cgroup.c:1092 (discriminator 2)) rebind_subsystems (kernel/cgroup.c:1144) cgroup_setup_root (kernel/cgroup.c:1568) cgroup_mount (kernel/cgroup.c:1716) mount_fs (fs/super.c:1094) vfs_kern_mount (fs/namespace.c:899) do_mount (fs/namespace.c:2238 fs/namespace.c:2561) SyS_mount (fs/namespace.c:2758 fs/namespace.c:2729) tracesys (arch/x86/kernel/entry_64.S:746) -> #1 (cgroup_tree_mutex){+.+.+.}: lock_acquire (arch/x86/include/asm/current.h:14 kernel/locking/lockdep.c:3602) mutex_lock_nested (kernel/locking/mutex.c:486 kernel/locking/mutex.c:587) cgroup_add_cftypes (include/linux/list.h:76 kernel/cgroup.c:3040) blkcg_policy_register (block/blk-cgroup.c:1106) throtl_init (block/blk-throttle.c:1694) do_one_initcall (init/main.c:789) kernel_init_freeable (init/main.c:854 init/main.c:863 init/main.c:882 init/main.c:1003) kernel_init (init/main.c:935) ret_from_fork (arch/x86/kernel/entry_64.S:552) -> #0 (blkcg_pol_mutex){+.+.+.}: __lock_acquire (kernel/locking/lockdep.c:1840 kernel/locking/lockdep.c:1945 kernel/locking/lockdep.c:2131 kernel/locking/lockdep.c:3182) lock_acquire (arch/x86/include/asm/current.h:14 kernel/locking/lockdep.c:3602) mutex_lock_nested (kernel/locking/mutex.c:486 kernel/locking/mutex.c:587) blkcg_reset_stats (include/linux/spinlock.h:328 block/blk-cgroup.c:455) cgroup_file_write (kernel/cgroup.c:2714) kernfs_fop_write (fs/kernfs/file.c:295) vfs_write (fs/read_write.c:532) SyS_write (fs/read_write.c:584 fs/read_write.c:576) tracesys (arch/x86/kernel/entry_64.S:746) other info that might help us debug this: Chain exists of: blkcg_pol_mutex --> cgroup_tree_mutex --> s_active#89 Possible unsafe locking scenario: CPU0 CPU1 ---- ---- lock(s_active#89); lock(cgroup_tree_mutex); lock(s_active#89); lock(blkcg_pol_mutex); *** DEADLOCK *** 4 locks held by trinity-c173/9024: #0: (&f->f_pos_lock){+.+.+.}, at: __fdget_pos (fs/file.c:714) #1: (sb_writers#18){.+.+.+}, at: vfs_write (include/linux/fs.h:2255 fs/read_write.c:530) #2: (&of->mutex){+.+.+.}, at: kernfs_fop_write (fs/kernfs/file.c:283) #3: (s_active#89){++++.+}, at: kernfs_fop_write (fs/kernfs/file.c:283) stack backtrace: CPU: 3 PID: 9024 Comm: trinity-c173 Tainted: G W 3.15.0-rc3-next-20140430-sasha-00016-g4e281fa-dirty #429 ffffffff919687b0 ffff8805f6373bb8 ffffffff8e52cdbb 0000000000000002 ffffffff919d8400 ffff8805f6373c08 ffffffff8e51fb88 0000000000000004 ffff8805f6373c98 ffff8805f6373c08 ffff88061be70d98 ffff88061be70dd0 Call Trace: dump_stack (lib/dump_stack.c:52) print_circular_bug (kernel/locking/lockdep.c:1216) __lock_acquire (kernel/locking/lockdep.c:1840 kernel/locking/lockdep.c:1945 kernel/locking/lockdep.c:2131 kernel/locking/lockdep.c:3182) lock_acquire (arch/x86/include/asm/current.h:14 kernel/locking/lockdep.c:3602) mutex_lock_nested (kernel/locking/mutex.c:486 kernel/locking/mutex.c:587) blkcg_reset_stats (include/linux/spinlock.h:328 block/blk-cgroup.c:455) cgroup_file_write (kernel/cgroup.c:2714) kernfs_fop_write (fs/kernfs/file.c:295) vfs_write (fs/read_write.c:532) SyS_write (fs/read_write.c:584 fs/read_write.c:576) This is a highly unlikely but valid circular dependency between "echo 1 > blkcg.reset_stats" and cfq module [un]loading. cgroup is going through further locking update which will remove this complication but for now let's use trylock on blkcg_pol_mutex and retry the file operation if the trylock fails. Signed-off-by: Tejun Heo Reported-by: Sasha Levin References: http://lkml.kernel.org/g/5363C04B.4010400@oracle.com --- block/blk-cgroup.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c index e4a4145926f6..1039fb9ff5f5 100644 --- a/block/blk-cgroup.c +++ b/block/blk-cgroup.c @@ -451,7 +451,20 @@ static int blkcg_reset_stats(struct cgroup_subsys_state *css, struct blkcg_gq *blkg; int i; - mutex_lock(&blkcg_pol_mutex); + /* + * XXX: We invoke cgroup_add/rm_cftypes() under blkcg_pol_mutex + * which ends up putting cgroup's internal cgroup_tree_mutex under + * it; however, cgroup_tree_mutex is nested above cgroup file + * active protection and grabbing blkcg_pol_mutex from a cgroup + * file operation creates a possible circular dependency. cgroup + * internal locking is planned to go through further simplification + * and this issue should go away soon. For now, let's trylock + * blkcg_pol_mutex and restart the write on failure. + * + * http://lkml.kernel.org/g/5363C04B.4010400@oracle.com + */ + if (!mutex_trylock(&blkcg_pol_mutex)) + return restart_syscall(); spin_lock_irq(&blkcg->lock); /* -- cgit v1.2.3 From 36189cc3cd57ab0f1cd75241f93fe01de928ac06 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 5 May 2014 09:36:43 -0700 Subject: Input: elantech - fix touchpad initialization on Gigabyte U2442 The hw_version 3 Elantech touchpad on the Gigabyte U2442 does not accept 0x0b as initialization value for r10, this stand-alone version of the driver: http://planet76.com/drivers/elantech/psmouse-elantech-v6.tar.bz2 Uses 0x03 which does work, so this means not setting bit 3 of r10 which sets: "Enable Real H/W Resolution In Absolute mode" Which will result in half the x and y resolution we get with that bit set, so simply not setting it everywhere is not a solution. We've been unable to find a way to identify touchpads where setting the bit will fail, so this patch uses a dmi based blacklist for this. https://bugzilla.kernel.org/show_bug.cgi?id=61151 Cc: stable@vger.kernel.org Reported-by: Philipp Wolfer Tested-by: Philipp Wolfer Signed-off-by: Hans de Goede Signed-off-by: Dmitry Torokhov --- Documentation/input/elantech.txt | 5 ++++- drivers/input/mouse/elantech.c | 26 +++++++++++++++++++++++++- drivers/input/mouse/elantech.h | 1 + 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/Documentation/input/elantech.txt b/Documentation/input/elantech.txt index 5602eb71ad5d..e1ae127ed099 100644 --- a/Documentation/input/elantech.txt +++ b/Documentation/input/elantech.txt @@ -504,9 +504,12 @@ byte 5: * reg_10 bit 7 6 5 4 3 2 1 0 - 0 0 0 0 0 0 0 A + 0 0 0 0 R F T A A: 1 = enable absolute tracking + T: 1 = enable two finger mode auto correct + F: 1 = disable ABS Position Filter + R: 1 = enable real hardware resolution 6.2 Native absolute mode 6 byte packet format ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index 088d3541c7d3..b96e978a37b7 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -11,6 +11,7 @@ */ #include +#include #include #include #include @@ -831,7 +832,11 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse) break; case 3: - etd->reg_10 = 0x0b; + if (etd->set_hw_resolution) + etd->reg_10 = 0x0b; + else + etd->reg_10 = 0x03; + if (elantech_write_reg(psmouse, 0x10, etd->reg_10)) rc = -1; @@ -1330,6 +1335,22 @@ static int elantech_reconnect(struct psmouse *psmouse) return 0; } +/* + * Some hw_version 3 models go into error state when we try to set bit 3 of r10 + */ +static const struct dmi_system_id no_hw_res_dmi_table[] = { +#if defined(CONFIG_DMI) && defined(CONFIG_X86) + { + /* Gigabyte U2442 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), + DMI_MATCH(DMI_PRODUCT_NAME, "U2442"), + }, + }, +#endif + { } +}; + /* * determine hardware version and set some properties according to it. */ @@ -1390,6 +1411,9 @@ static int elantech_set_properties(struct elantech_data *etd) */ etd->crc_enabled = ((etd->fw_version & 0x4000) == 0x4000); + /* Enable real hardware resolution on hw_version 3 ? */ + etd->set_hw_resolution = !dmi_check_system(no_hw_res_dmi_table); + return 0; } diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h index 036a04abaef7..9e0e2a1f340d 100644 --- a/drivers/input/mouse/elantech.h +++ b/drivers/input/mouse/elantech.h @@ -130,6 +130,7 @@ struct elantech_data { bool jumpy_cursor; bool reports_pressure; bool crc_enabled; + bool set_hw_resolution; unsigned char hw_version; unsigned int fw_version; unsigned int single_finger_reports; -- cgit v1.2.3 From e9024f0ba38a994c805743bc523693c5c7d7ccbc Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Mon, 5 May 2014 13:20:23 +0100 Subject: ASoC: Intel: Fix check for pdata usage before dereference. This patch fixes the following dereference check ordering. sound/soc/intel/sst-haswell-pcm.c:749 hsw_pcm_probe() warn: variable dereferenced before check 'pdata' (see line 746) git remote add asoc git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git git remote update asoc git checkout 0b708c87f66a15190fb43661c2320fd48c4dc6c8 vim +/pdata +749 sound/soc/intel/sst-haswell-pcm.c a4b12990 Mark Brown 2014-03-12 740 }; a4b12990 Mark Brown 2014-03-12 741 a4b12990 Mark Brown 2014-03-12 742 static int hsw_pcm_probe(struct snd_soc_platform *platform) a4b12990 Mark Brown 2014-03-12 743 { a4b12990 Mark Brown 2014-03-12 744 struct sst_pdata *pdata = dev_get_platdata(platform->dev); a4b12990 Mark Brown 2014-03-12 745 struct hsw_priv_data *priv_data; 0b708c87 Liam Girdwood 2014-05-02 @746 struct device *dma_dev = pdata->dma_dev; 0b708c87 Liam Girdwood 2014-05-02 747 int i, ret = 0; a4b12990 Mark Brown 2014-03-12 748 a4b12990 Mark Brown 2014-03-12 @749 if (!pdata) a4b12990 Mark Brown 2014-03-12 750 return -ENODEV; a4b12990 Mark Brown 2014-03-12 751 a4b12990 Mark Brown 2014-03-12 752 priv_data = devm_kzalloc(platform->dev, sizeof(*priv_data), GFP_KERNEL); Reported-by: Dan Carpenter Signed-off-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/intel/sst-haswell-pcm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/soc/intel/sst-haswell-pcm.c b/sound/soc/intel/sst-haswell-pcm.c index 8c6bd33dd375..9d5f64a583a3 100644 --- a/sound/soc/intel/sst-haswell-pcm.c +++ b/sound/soc/intel/sst-haswell-pcm.c @@ -772,12 +772,14 @@ static int hsw_pcm_probe(struct snd_soc_platform *platform) { struct sst_pdata *pdata = dev_get_platdata(platform->dev); struct hsw_priv_data *priv_data; - struct device *dma_dev = pdata->dma_dev; + struct device *dma_dev; int i, ret = 0; if (!pdata) return -ENODEV; + dma_dev = pdata->dma_dev; + priv_data = devm_kzalloc(platform->dev, sizeof(*priv_data), GFP_KERNEL); priv_data->hsw = pdata->dsp; snd_soc_platform_set_drvdata(platform, priv_data); -- cgit v1.2.3 From d540e43b0ab134b22f015f725ce6e070d12b0244 Mon Sep 17 00:00:00 2001 From: Brian Foster Date: Tue, 6 May 2014 07:34:28 +1000 Subject: xfs: initialize default acls for ->tmpfile() The current tmpfile handler does not initialize default ACLs. Doing so within xfs_vn_tmpfile() makes it roughly equivalent to xfs_vn_mknod(), which is already used as a common create handler. xfs_vn_mknod() does not currently have a mechanism to determine whether to link the file into the namespace. Therefore, further abstract xfs_vn_mknod() into a new xfs_generic_create() handler with a tmpfile parameter. This new handler calls xfs_create_tmpfile() and d_tmpfile() on the dentry when called via ->tmpfile(). Signed-off-by: Brian Foster Reviewed-by: Dave Chinner Signed-off-by: Dave Chinner --- fs/xfs/xfs_iops.c | 55 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 29 insertions(+), 26 deletions(-) diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index ef1ca010f417..301ecbfcc0be 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -124,15 +124,15 @@ xfs_cleanup_inode( xfs_dentry_to_name(&teardown, dentry, 0); xfs_remove(XFS_I(dir), &teardown, XFS_I(inode)); - iput(inode); } STATIC int -xfs_vn_mknod( +xfs_generic_create( struct inode *dir, struct dentry *dentry, umode_t mode, - dev_t rdev) + dev_t rdev, + bool tmpfile) /* unnamed file */ { struct inode *inode; struct xfs_inode *ip = NULL; @@ -156,8 +156,12 @@ xfs_vn_mknod( if (error) return error; - xfs_dentry_to_name(&name, dentry, mode); - error = xfs_create(XFS_I(dir), &name, mode, rdev, &ip); + if (!tmpfile) { + xfs_dentry_to_name(&name, dentry, mode); + error = xfs_create(XFS_I(dir), &name, mode, rdev, &ip); + } else { + error = xfs_create_tmpfile(XFS_I(dir), dentry, mode, &ip); + } if (unlikely(error)) goto out_free_acl; @@ -180,7 +184,11 @@ xfs_vn_mknod( } #endif - d_instantiate(dentry, inode); + if (tmpfile) + d_tmpfile(dentry, inode); + else + d_instantiate(dentry, inode); + out_free_acl: if (default_acl) posix_acl_release(default_acl); @@ -189,10 +197,22 @@ xfs_vn_mknod( return -error; out_cleanup_inode: - xfs_cleanup_inode(dir, inode, dentry); + if (!tmpfile) + xfs_cleanup_inode(dir, inode, dentry); + iput(inode); goto out_free_acl; } +STATIC int +xfs_vn_mknod( + struct inode *dir, + struct dentry *dentry, + umode_t mode, + dev_t rdev) +{ + return xfs_generic_create(dir, dentry, mode, rdev, false); +} + STATIC int xfs_vn_create( struct inode *dir, @@ -353,6 +373,7 @@ xfs_vn_symlink( out_cleanup_inode: xfs_cleanup_inode(dir, inode, dentry); + iput(inode); out: return -error; } @@ -1053,25 +1074,7 @@ xfs_vn_tmpfile( struct dentry *dentry, umode_t mode) { - int error; - struct xfs_inode *ip; - struct inode *inode; - - error = xfs_create_tmpfile(XFS_I(dir), dentry, mode, &ip); - if (unlikely(error)) - return -error; - - inode = VFS_I(ip); - - error = xfs_init_security(inode, dir, &dentry->d_name); - if (unlikely(error)) { - iput(inode); - return -error; - } - - d_tmpfile(dentry, inode); - - return 0; + return xfs_generic_create(dir, dentry, mode, 0, true); } static const struct inode_operations xfs_inode_operations = { -- cgit v1.2.3 From 8275cdd0e7ac550dcce2b3ef6d2fb3b808c1ae59 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Tue, 6 May 2014 07:37:31 +1000 Subject: xfs: remote attribute overwrite causes transaction overrun Commit e461fcb ("xfs: remote attribute lookups require the value length") passes the remote attribute length in the xfs_da_args structure on lookup so that CRC calculations and validity checking can be performed correctly by related code. This, unfortunately has the side effect of changing the args->valuelen parameter in cases where it shouldn't. That is, when we replace a remote attribute, the incoming replacement stores the value and length in args->value and args->valuelen, but then the lookup which finds the existing remote attribute overwrites args->valuelen with the length of the remote attribute being replaced. Hence when we go to create the new attribute, we create it of the size of the existing remote attribute, not the size it is supposed to be. When the new attribute is much smaller than the old attribute, this results in a transaction overrun and an ASSERT() failure on a debug kernel: XFS: Assertion failed: tp->t_blk_res_used <= tp->t_blk_res, file: fs/xfs/xfs_trans.c, line: 331 Fix this by keeping the remote attribute value length separate to the attribute value length in the xfs_da_args structure. The enables us to pass the length of the remote attribute to be removed without overwriting the new attribute's length. Also, ensure that when we save remote block contexts for a later rename we zero the original state variables so that we don't confuse the state of the attribute to be removes with the state of the new attribute that we just added. [Spotted by Brain Foster.] Signed-off-by: Dave Chinner Reviewed-by: Brian Foster Signed-off-by: Dave Chinner --- fs/xfs/xfs_attr.c | 24 +++++++++++++++++++++++- fs/xfs/xfs_attr_leaf.c | 21 +++++++++++---------- fs/xfs/xfs_attr_list.c | 1 + fs/xfs/xfs_attr_remote.c | 8 +++++--- fs/xfs/xfs_da_btree.h | 2 ++ 5 files changed, 42 insertions(+), 14 deletions(-) diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c index 01b6a0102fbd..abda1124a70f 100644 --- a/fs/xfs/xfs_attr.c +++ b/fs/xfs/xfs_attr.c @@ -213,7 +213,7 @@ xfs_attr_calc_size( * Out of line attribute, cannot double split, but * make room for the attribute value itself. */ - uint dblocks = XFS_B_TO_FSB(mp, valuelen); + uint dblocks = xfs_attr3_rmt_blocks(mp, valuelen); nblks += dblocks; nblks += XFS_NEXTENTADD_SPACE_RES(mp, dblocks, XFS_ATTR_FORK); } @@ -698,11 +698,22 @@ xfs_attr_leaf_addname(xfs_da_args_t *args) trace_xfs_attr_leaf_replace(args); + /* save the attribute state for later removal*/ args->op_flags |= XFS_DA_OP_RENAME; /* an atomic rename */ args->blkno2 = args->blkno; /* set 2nd entry info*/ args->index2 = args->index; args->rmtblkno2 = args->rmtblkno; args->rmtblkcnt2 = args->rmtblkcnt; + args->rmtvaluelen2 = args->rmtvaluelen; + + /* + * clear the remote attr state now that it is saved so that the + * values reflect the state of the attribute we are about to + * add, not the attribute we just found and will remove later. + */ + args->rmtblkno = 0; + args->rmtblkcnt = 0; + args->rmtvaluelen = 0; } /* @@ -794,6 +805,7 @@ xfs_attr_leaf_addname(xfs_da_args_t *args) args->blkno = args->blkno2; args->rmtblkno = args->rmtblkno2; args->rmtblkcnt = args->rmtblkcnt2; + args->rmtvaluelen = args->rmtvaluelen2; if (args->rmtblkno) { error = xfs_attr_rmtval_remove(args); if (error) @@ -999,13 +1011,22 @@ restart: trace_xfs_attr_node_replace(args); + /* save the attribute state for later removal*/ args->op_flags |= XFS_DA_OP_RENAME; /* atomic rename op */ args->blkno2 = args->blkno; /* set 2nd entry info*/ args->index2 = args->index; args->rmtblkno2 = args->rmtblkno; args->rmtblkcnt2 = args->rmtblkcnt; + args->rmtvaluelen2 = args->rmtvaluelen; + + /* + * clear the remote attr state now that it is saved so that the + * values reflect the state of the attribute we are about to + * add, not the attribute we just found and will remove later. + */ args->rmtblkno = 0; args->rmtblkcnt = 0; + args->rmtvaluelen = 0; } retval = xfs_attr3_leaf_add(blk->bp, state->args); @@ -1133,6 +1154,7 @@ restart: args->blkno = args->blkno2; args->rmtblkno = args->rmtblkno2; args->rmtblkcnt = args->rmtblkcnt2; + args->rmtvaluelen = args->rmtvaluelen2; if (args->rmtblkno) { error = xfs_attr_rmtval_remove(args); if (error) diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c index fe9587fab17a..511c283459b1 100644 --- a/fs/xfs/xfs_attr_leaf.c +++ b/fs/xfs/xfs_attr_leaf.c @@ -1229,6 +1229,7 @@ xfs_attr3_leaf_add_work( name_rmt->valueblk = 0; args->rmtblkno = 1; args->rmtblkcnt = xfs_attr3_rmt_blocks(mp, args->valuelen); + args->rmtvaluelen = args->valuelen; } xfs_trans_log_buf(args->trans, bp, XFS_DA_LOGRANGE(leaf, xfs_attr3_leaf_name(leaf, args->index), @@ -2167,11 +2168,11 @@ xfs_attr3_leaf_lookup_int( if (!xfs_attr_namesp_match(args->flags, entry->flags)) continue; args->index = probe; - args->valuelen = be32_to_cpu(name_rmt->valuelen); + args->rmtvaluelen = be32_to_cpu(name_rmt->valuelen); args->rmtblkno = be32_to_cpu(name_rmt->valueblk); args->rmtblkcnt = xfs_attr3_rmt_blocks( args->dp->i_mount, - args->valuelen); + args->rmtvaluelen); return XFS_ERROR(EEXIST); } } @@ -2220,19 +2221,19 @@ xfs_attr3_leaf_getvalue( name_rmt = xfs_attr3_leaf_name_remote(leaf, args->index); ASSERT(name_rmt->namelen == args->namelen); ASSERT(memcmp(args->name, name_rmt->name, args->namelen) == 0); - valuelen = be32_to_cpu(name_rmt->valuelen); + args->rmtvaluelen = be32_to_cpu(name_rmt->valuelen); args->rmtblkno = be32_to_cpu(name_rmt->valueblk); args->rmtblkcnt = xfs_attr3_rmt_blocks(args->dp->i_mount, - valuelen); + args->rmtvaluelen); if (args->flags & ATTR_KERNOVAL) { - args->valuelen = valuelen; + args->valuelen = args->rmtvaluelen; return 0; } - if (args->valuelen < valuelen) { - args->valuelen = valuelen; + if (args->valuelen < args->rmtvaluelen) { + args->valuelen = args->rmtvaluelen; return XFS_ERROR(ERANGE); } - args->valuelen = valuelen; + args->valuelen = args->rmtvaluelen; } return 0; } @@ -2519,7 +2520,7 @@ xfs_attr3_leaf_clearflag( ASSERT((entry->flags & XFS_ATTR_LOCAL) == 0); name_rmt = xfs_attr3_leaf_name_remote(leaf, args->index); name_rmt->valueblk = cpu_to_be32(args->rmtblkno); - name_rmt->valuelen = cpu_to_be32(args->valuelen); + name_rmt->valuelen = cpu_to_be32(args->rmtvaluelen); xfs_trans_log_buf(args->trans, bp, XFS_DA_LOGRANGE(leaf, name_rmt, sizeof(*name_rmt))); } @@ -2677,7 +2678,7 @@ xfs_attr3_leaf_flipflags( ASSERT((entry1->flags & XFS_ATTR_LOCAL) == 0); name_rmt = xfs_attr3_leaf_name_remote(leaf1, args->index); name_rmt->valueblk = cpu_to_be32(args->rmtblkno); - name_rmt->valuelen = cpu_to_be32(args->valuelen); + name_rmt->valuelen = cpu_to_be32(args->rmtvaluelen); xfs_trans_log_buf(args->trans, bp1, XFS_DA_LOGRANGE(leaf1, name_rmt, sizeof(*name_rmt))); } diff --git a/fs/xfs/xfs_attr_list.c b/fs/xfs/xfs_attr_list.c index 01db96f60cf0..833fe5d98d80 100644 --- a/fs/xfs/xfs_attr_list.c +++ b/fs/xfs/xfs_attr_list.c @@ -447,6 +447,7 @@ xfs_attr3_leaf_list_int( args.dp = context->dp; args.whichfork = XFS_ATTR_FORK; args.valuelen = valuelen; + args.rmtvaluelen = valuelen; args.value = kmem_alloc(valuelen, KM_SLEEP | KM_NOFS); args.rmtblkno = be32_to_cpu(name_rmt->valueblk); args.rmtblkcnt = xfs_attr3_rmt_blocks( diff --git a/fs/xfs/xfs_attr_remote.c b/fs/xfs/xfs_attr_remote.c index 6e37823e2932..d2e6e948cec7 100644 --- a/fs/xfs/xfs_attr_remote.c +++ b/fs/xfs/xfs_attr_remote.c @@ -337,7 +337,7 @@ xfs_attr_rmtval_get( struct xfs_buf *bp; xfs_dablk_t lblkno = args->rmtblkno; __uint8_t *dst = args->value; - int valuelen = args->valuelen; + int valuelen; int nmap; int error; int blkcnt = args->rmtblkcnt; @@ -347,7 +347,9 @@ xfs_attr_rmtval_get( trace_xfs_attr_rmtval_get(args); ASSERT(!(args->flags & ATTR_KERNOVAL)); + ASSERT(args->rmtvaluelen == args->valuelen); + valuelen = args->rmtvaluelen; while (valuelen > 0) { nmap = ATTR_RMTVALUE_MAPSIZE; error = xfs_bmapi_read(args->dp, (xfs_fileoff_t)lblkno, @@ -415,7 +417,7 @@ xfs_attr_rmtval_set( * attributes have headers, we can't just do a straight byte to FSB * conversion and have to take the header space into account. */ - blkcnt = xfs_attr3_rmt_blocks(mp, args->valuelen); + blkcnt = xfs_attr3_rmt_blocks(mp, args->rmtvaluelen); error = xfs_bmap_first_unused(args->trans, args->dp, blkcnt, &lfileoff, XFS_ATTR_FORK); if (error) @@ -480,7 +482,7 @@ xfs_attr_rmtval_set( */ lblkno = args->rmtblkno; blkcnt = args->rmtblkcnt; - valuelen = args->valuelen; + valuelen = args->rmtvaluelen; while (valuelen > 0) { struct xfs_buf *bp; xfs_daddr_t dblkno; diff --git a/fs/xfs/xfs_da_btree.h b/fs/xfs/xfs_da_btree.h index 6e95ea79f5d7..201c6091d26a 100644 --- a/fs/xfs/xfs_da_btree.h +++ b/fs/xfs/xfs_da_btree.h @@ -60,10 +60,12 @@ typedef struct xfs_da_args { int index; /* index of attr of interest in blk */ xfs_dablk_t rmtblkno; /* remote attr value starting blkno */ int rmtblkcnt; /* remote attr value block count */ + int rmtvaluelen; /* remote attr value length in bytes */ xfs_dablk_t blkno2; /* blkno of 2nd attr leaf of interest */ int index2; /* index of 2nd attr in blk */ xfs_dablk_t rmtblkno2; /* remote attr value starting blkno */ int rmtblkcnt2; /* remote attr value block count */ + int rmtvaluelen2; /* remote attr value length in bytes */ int op_flags; /* operation flags */ enum xfs_dacmp cmpresult; /* name compare result for lookups */ } xfs_da_args_t; -- cgit v1.2.3 From ac008fe0a3236729751ccde655c215b436dfdaeb Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 5 May 2014 15:23:35 -0700 Subject: x86, build: Don't get confused by local symbols arch/x86/crypto/sha1_avx2_x86_64_asm.S introduced _end as a local symbol, which broke the build under certain circumstances. Although the wisdom of _end as a local symbol can definitely be questioned, the build should not break for that reason. Thus, filter the output of nm to only get global symbols of appropriate type. Reported-by: Andy Lutomirski Cc: Chandramouli Narayanan Cc: Herbert Xu Signed-off-by: H. Peter Anvin Link: http://lkml.kernel.org/n/tip-uxm3j3w3odglcwhafwq5tjqu@git.kernel.org --- arch/x86/boot/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile index abb9eba61b50..dbe8dd2fe247 100644 --- a/arch/x86/boot/Makefile +++ b/arch/x86/boot/Makefile @@ -71,7 +71,7 @@ $(obj)/vmlinux.bin: $(obj)/compressed/vmlinux FORCE SETUP_OBJS = $(addprefix $(obj)/,$(setup-y)) -sed-voffset := -e 's/^\([0-9a-fA-F]*\) . \(_text\|_end\)$$/\#define VO_\2 0x\1/p' +sed-voffset := -e 's/^\([0-9a-fA-F]*\) [ABCDGRSTVW] \(_text\|_end\)$$/\#define VO_\2 0x\1/p' quiet_cmd_voffset = VOFFSET $@ cmd_voffset = $(NM) $< | sed -n $(sed-voffset) > $@ @@ -80,7 +80,7 @@ targets += voffset.h $(obj)/voffset.h: vmlinux FORCE $(call if_changed,voffset) -sed-zoffset := -e 's/^\([0-9a-fA-F]*\) . \(startup_32\|startup_64\|efi32_stub_entry\|efi64_stub_entry\|efi_pe_entry\|input_data\|_end\|z_.*\)$$/\#define ZO_\2 0x\1/p' +sed-zoffset := -e 's/^\([0-9a-fA-F]*\) [ABCDGRSTVW] \(startup_32\|startup_64\|efi32_stub_entry\|efi64_stub_entry\|efi_pe_entry\|input_data\|_end\|z_.*\)$$/\#define ZO_\2 0x\1/p' quiet_cmd_zoffset = ZOFFSET $@ cmd_zoffset = $(NM) $< | sed -n $(sed-zoffset) > $@ -- cgit v1.2.3 From 825747bb85634a2a7b7dce4e373831e211ab1644 Mon Sep 17 00:00:00 2001 From: "Peter F. Patel-Schneider" Date: Mon, 5 May 2014 15:55:32 -0700 Subject: HID: sensor-hub: Add in quirk for sensor hub in Lenovo Ideapad Yogas The sensor hub in Lenovo Yogas needs the enumeration quirk. I've been running the patch for over a month with no problems, whereas the unpatched drivers reliably mis-initialized the sensors. Signed-off-by: Peter F. Patel-Schneider Acked-by: Srinivas Pandruvada Signed-off-by: Jiri Kosina --- drivers/hid/hid-ids.h | 3 +++ drivers/hid/hid-sensor-hub.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 5c75774cdaf2..34bb2205d2ea 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -839,6 +839,9 @@ #define USB_DEVICE_ID_SYNAPTICS_QUAD_HD 0x1ac3 #define USB_DEVICE_ID_SYNAPTICS_TP_V103 0x5710 +#define USB_VENDOR_ID_TEXAS_INSTRUMENTS 0x2047 +#define USB_DEVICE_ID_TEXAS_INSTRUMENTS_LENOVO_YOGA 0x0855 + #define USB_VENDOR_ID_THINGM 0x27b8 #define USB_DEVICE_ID_BLINK1 0x01ed diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c index af8244b1c1f4..be14b5690e94 100644 --- a/drivers/hid/hid-sensor-hub.c +++ b/drivers/hid/hid-sensor-hub.c @@ -708,6 +708,9 @@ static const struct hid_device_id sensor_hub_devices[] = { { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_STM_0, USB_DEVICE_ID_STM_HID_SENSOR), .driver_data = HID_SENSOR_HUB_ENUM_QUIRK}, + { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_TEXAS_INSTRUMENTS, + USB_DEVICE_ID_TEXAS_INSTRUMENTS_LENOVO_YOGA), + .driver_data = HID_SENSOR_HUB_ENUM_QUIRK}, { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, HID_ANY_ID, HID_ANY_ID) }, { } -- cgit v1.2.3 From 3adc1beacdbc1d6c4be99ecc2f87eac1c1e6f857 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Fri, 2 May 2014 00:44:36 +0200 Subject: asmlinkage: Revert "lto: Make asmlinkage __visible" As requested by Linus, revert adding __visible to asmlinkage. Instead we add __visible explicitely to all the symbols that need it. This reverts commit 128ea04a9885af9629059e631ddf0cab4815b589. Link: http://lkml.kernel.org/r/1398984278-29319-2-git-send-email-andi@firstfloor.org Signed-off-by: H. Peter Anvin --- include/linux/linkage.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/linkage.h b/include/linux/linkage.h index 34a513a2727b..a6a42dd02466 100644 --- a/include/linux/linkage.h +++ b/include/linux/linkage.h @@ -12,9 +12,9 @@ #endif #ifdef __cplusplus -#define CPP_ASMLINKAGE extern "C" __visible +#define CPP_ASMLINKAGE extern "C" #else -#define CPP_ASMLINKAGE __visible +#define CPP_ASMLINKAGE #endif #ifndef asmlinkage -- cgit v1.2.3 From 2605fc216fa492f9e7c488bdc7f687cd6dcc703b Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Fri, 2 May 2014 00:44:37 +0200 Subject: asmlinkage, x86: Add explicit __visible to arch/x86/* As requested by Linus add explicit __visible to the asmlinkage users. This marks all functions visible to assembler. Tree sweep for arch/x86/* Signed-off-by: Andi Kleen Link: http://lkml.kernel.org/r/1398984278-29319-3-git-send-email-andi@firstfloor.org Signed-off-by: H. Peter Anvin --- arch/x86/boot/compressed/misc.c | 2 +- arch/x86/kernel/acpi/sleep.c | 2 +- arch/x86/kernel/apic/io_apic.c | 2 +- arch/x86/kernel/cpu/mcheck/therm_throt.c | 4 ++-- arch/x86/kernel/cpu/mcheck/threshold.c | 4 ++-- arch/x86/kernel/head32.c | 2 +- arch/x86/kernel/head64.c | 2 +- arch/x86/kernel/process_64.c | 2 +- arch/x86/kernel/smp.c | 2 +- arch/x86/kernel/traps.c | 6 +++--- arch/x86/kernel/vsmp_64.c | 6 +++--- arch/x86/kvm/x86.c | 2 +- arch/x86/lguest/boot.c | 4 ++-- arch/x86/math-emu/errors.c | 16 ++++++++-------- arch/x86/platform/olpc/olpc-xo1-pm.c | 2 +- arch/x86/power/hibernate_64.c | 2 +- arch/x86/xen/enlighten.c | 2 +- arch/x86/xen/irq.c | 6 +++--- 18 files changed, 34 insertions(+), 34 deletions(-) diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c index 17684615374b..57ab74df7eea 100644 --- a/arch/x86/boot/compressed/misc.c +++ b/arch/x86/boot/compressed/misc.c @@ -354,7 +354,7 @@ static void parse_elf(void *output) free(phdrs); } -asmlinkage void *decompress_kernel(void *rmode, memptr heap, +asmlinkage __visible void *decompress_kernel(void *rmode, memptr heap, unsigned char *input_data, unsigned long input_len, unsigned char *output, diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c index 3a2ae4c88948..31368207837c 100644 --- a/arch/x86/kernel/acpi/sleep.c +++ b/arch/x86/kernel/acpi/sleep.c @@ -31,7 +31,7 @@ static char temp_stack[4096]; * * Wrapper around acpi_enter_sleep_state() to be called by assmebly. */ -acpi_status asmlinkage x86_acpi_enter_sleep_state(u8 state) +acpi_status asmlinkage __visible x86_acpi_enter_sleep_state(u8 state) { return acpi_enter_sleep_state(state); } diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index d23aa82e7a7b..992060e09897 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -2189,7 +2189,7 @@ void send_cleanup_vector(struct irq_cfg *cfg) cfg->move_in_progress = 0; } -asmlinkage void smp_irq_move_cleanup_interrupt(void) +asmlinkage __visible void smp_irq_move_cleanup_interrupt(void) { unsigned vector, me; diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c index d921b7ee6595..36a1bb6d1ee0 100644 --- a/arch/x86/kernel/cpu/mcheck/therm_throt.c +++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c @@ -429,14 +429,14 @@ static inline void __smp_thermal_interrupt(void) smp_thermal_vector(); } -asmlinkage void smp_thermal_interrupt(struct pt_regs *regs) +asmlinkage __visible void smp_thermal_interrupt(struct pt_regs *regs) { entering_irq(); __smp_thermal_interrupt(); exiting_ack_irq(); } -asmlinkage void smp_trace_thermal_interrupt(struct pt_regs *regs) +asmlinkage __visible void smp_trace_thermal_interrupt(struct pt_regs *regs) { entering_irq(); trace_thermal_apic_entry(THERMAL_APIC_VECTOR); diff --git a/arch/x86/kernel/cpu/mcheck/threshold.c b/arch/x86/kernel/cpu/mcheck/threshold.c index fe6b1c86645b..7245980186ee 100644 --- a/arch/x86/kernel/cpu/mcheck/threshold.c +++ b/arch/x86/kernel/cpu/mcheck/threshold.c @@ -24,14 +24,14 @@ static inline void __smp_threshold_interrupt(void) mce_threshold_vector(); } -asmlinkage void smp_threshold_interrupt(void) +asmlinkage __visible void smp_threshold_interrupt(void) { entering_irq(); __smp_threshold_interrupt(); exiting_ack_irq(); } -asmlinkage void smp_trace_threshold_interrupt(void) +asmlinkage __visible void smp_trace_threshold_interrupt(void) { entering_irq(); trace_threshold_apic_entry(THRESHOLD_APIC_VECTOR); diff --git a/arch/x86/kernel/head32.c b/arch/x86/kernel/head32.c index c61a14a4a310..d6c1b9836995 100644 --- a/arch/x86/kernel/head32.c +++ b/arch/x86/kernel/head32.c @@ -29,7 +29,7 @@ static void __init i386_default_early_setup(void) reserve_ebda_region(); } -asmlinkage void __init i386_start_kernel(void) +asmlinkage __visible void __init i386_start_kernel(void) { sanitize_boot_params(&boot_params); diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c index 85126ccbdf6b..068054f4bf20 100644 --- a/arch/x86/kernel/head64.c +++ b/arch/x86/kernel/head64.c @@ -137,7 +137,7 @@ static void __init copy_bootdata(char *real_mode_data) } } -asmlinkage void __init x86_64_start_kernel(char * real_mode_data) +asmlinkage __visible void __init x86_64_start_kernel(char * real_mode_data) { int i; diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 9c0280f93d05..898d077617a9 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -52,7 +52,7 @@ asmlinkage extern void ret_from_fork(void); -asmlinkage DEFINE_PER_CPU(unsigned long, old_rsp); +__visible DEFINE_PER_CPU(unsigned long, old_rsp); /* Prints also some state that isn't saved in the pt_regs */ void __show_regs(struct pt_regs *regs, int all) diff --git a/arch/x86/kernel/smp.c b/arch/x86/kernel/smp.c index 7c3a5a61f2e4..be8e1bde07aa 100644 --- a/arch/x86/kernel/smp.c +++ b/arch/x86/kernel/smp.c @@ -168,7 +168,7 @@ static int smp_stop_nmi_callback(unsigned int val, struct pt_regs *regs) * this function calls the 'stop' function on all other CPUs in the system. */ -asmlinkage void smp_reboot_interrupt(void) +asmlinkage __visible void smp_reboot_interrupt(void) { ack_APIC_irq(); irq_enter(); diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 57409f6b8c62..f73b5d435bdc 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -357,7 +357,7 @@ exit: * for scheduling or signal handling. The actual stack switch is done in * entry.S */ -asmlinkage __kprobes struct pt_regs *sync_regs(struct pt_regs *eregs) +asmlinkage __visible __kprobes struct pt_regs *sync_regs(struct pt_regs *eregs) { struct pt_regs *regs = eregs; /* Did already sync */ @@ -601,11 +601,11 @@ do_spurious_interrupt_bug(struct pt_regs *regs, long error_code) #endif } -asmlinkage void __attribute__((weak)) smp_thermal_interrupt(void) +asmlinkage __visible void __attribute__((weak)) smp_thermal_interrupt(void) { } -asmlinkage void __attribute__((weak)) smp_threshold_interrupt(void) +asmlinkage __visible void __attribute__((weak)) smp_threshold_interrupt(void) { } diff --git a/arch/x86/kernel/vsmp_64.c b/arch/x86/kernel/vsmp_64.c index 5edc34b5b951..b99b9ad8540c 100644 --- a/arch/x86/kernel/vsmp_64.c +++ b/arch/x86/kernel/vsmp_64.c @@ -36,7 +36,7 @@ static int irq_routing_comply = 1; * and vice versa. */ -asmlinkage unsigned long vsmp_save_fl(void) +asmlinkage __visible unsigned long vsmp_save_fl(void) { unsigned long flags = native_save_fl(); @@ -56,7 +56,7 @@ __visible void vsmp_restore_fl(unsigned long flags) } PV_CALLEE_SAVE_REGS_THUNK(vsmp_restore_fl); -asmlinkage void vsmp_irq_disable(void) +asmlinkage __visible void vsmp_irq_disable(void) { unsigned long flags = native_save_fl(); @@ -64,7 +64,7 @@ asmlinkage void vsmp_irq_disable(void) } PV_CALLEE_SAVE_REGS_THUNK(vsmp_irq_disable); -asmlinkage void vsmp_irq_enable(void) +asmlinkage __visible void vsmp_irq_enable(void) { unsigned long flags = native_save_fl(); diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 8b8fc0b792ba..b6c0bacca9bd 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -280,7 +280,7 @@ int kvm_set_apic_base(struct kvm_vcpu *vcpu, struct msr_data *msr_info) } EXPORT_SYMBOL_GPL(kvm_set_apic_base); -asmlinkage void kvm_spurious_fault(void) +asmlinkage __visible void kvm_spurious_fault(void) { /* Fault while not rebooting. We want the trace. */ BUG(); diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c index ad1fb5f53925..aae94132bc24 100644 --- a/arch/x86/lguest/boot.c +++ b/arch/x86/lguest/boot.c @@ -233,13 +233,13 @@ static void lguest_end_context_switch(struct task_struct *next) * flags word contains all kind of stuff, but in practice Linux only cares * about the interrupt flag. Our "save_flags()" just returns that. */ -asmlinkage unsigned long lguest_save_fl(void) +asmlinkage __visible unsigned long lguest_save_fl(void) { return lguest_data.irq_enabled; } /* Interrupts go off... */ -asmlinkage void lguest_irq_disable(void) +asmlinkage __visible void lguest_irq_disable(void) { lguest_data.irq_enabled = 0; } diff --git a/arch/x86/math-emu/errors.c b/arch/x86/math-emu/errors.c index a5449089cd9f..9e6545f269e5 100644 --- a/arch/x86/math-emu/errors.c +++ b/arch/x86/math-emu/errors.c @@ -302,7 +302,7 @@ static struct { 0x242 in div_Xsig.S */ -asmlinkage void FPU_exception(int n) +asmlinkage __visible void FPU_exception(int n) { int i, int_type; @@ -492,7 +492,7 @@ int real_2op_NaN(FPU_REG const *b, u_char tagb, /* Invalid arith operation on Valid registers */ /* Returns < 0 if the exception is unmasked */ -asmlinkage int arith_invalid(int deststnr) +asmlinkage __visible int arith_invalid(int deststnr) { EXCEPTION(EX_Invalid); @@ -507,7 +507,7 @@ asmlinkage int arith_invalid(int deststnr) } /* Divide a finite number by zero */ -asmlinkage int FPU_divide_by_zero(int deststnr, u_char sign) +asmlinkage __visible int FPU_divide_by_zero(int deststnr, u_char sign) { FPU_REG *dest = &st(deststnr); int tag = TAG_Valid; @@ -539,7 +539,7 @@ int set_precision_flag(int flags) } /* This may be called often, so keep it lean */ -asmlinkage void set_precision_flag_up(void) +asmlinkage __visible void set_precision_flag_up(void) { if (control_word & CW_Precision) partial_status |= (SW_Precision | SW_C1); /* The masked response */ @@ -548,7 +548,7 @@ asmlinkage void set_precision_flag_up(void) } /* This may be called often, so keep it lean */ -asmlinkage void set_precision_flag_down(void) +asmlinkage __visible void set_precision_flag_down(void) { if (control_word & CW_Precision) { /* The masked response */ partial_status &= ~SW_C1; @@ -557,7 +557,7 @@ asmlinkage void set_precision_flag_down(void) EXCEPTION(EX_Precision); } -asmlinkage int denormal_operand(void) +asmlinkage __visible int denormal_operand(void) { if (control_word & CW_Denormal) { /* The masked response */ partial_status |= SW_Denorm_Op; @@ -568,7 +568,7 @@ asmlinkage int denormal_operand(void) } } -asmlinkage int arith_overflow(FPU_REG *dest) +asmlinkage __visible int arith_overflow(FPU_REG *dest) { int tag = TAG_Valid; @@ -596,7 +596,7 @@ asmlinkage int arith_overflow(FPU_REG *dest) } -asmlinkage int arith_underflow(FPU_REG *dest) +asmlinkage __visible int arith_underflow(FPU_REG *dest) { int tag = TAG_Valid; diff --git a/arch/x86/platform/olpc/olpc-xo1-pm.c b/arch/x86/platform/olpc/olpc-xo1-pm.c index ff0174dda810..a9acde72d4ed 100644 --- a/arch/x86/platform/olpc/olpc-xo1-pm.c +++ b/arch/x86/platform/olpc/olpc-xo1-pm.c @@ -75,7 +75,7 @@ static int xo1_power_state_enter(suspend_state_t pm_state) return 0; } -asmlinkage int xo1_do_sleep(u8 sleep_state) +asmlinkage __visible int xo1_do_sleep(u8 sleep_state) { void *pgd_addr = __va(read_cr3()); diff --git a/arch/x86/power/hibernate_64.c b/arch/x86/power/hibernate_64.c index 304fca20d96e..35e2bb6c0f37 100644 --- a/arch/x86/power/hibernate_64.c +++ b/arch/x86/power/hibernate_64.c @@ -23,7 +23,7 @@ extern __visible const void __nosave_begin, __nosave_end; /* Defined in hibernate_asm_64.S */ -extern asmlinkage int restore_image(void); +extern asmlinkage __visible int restore_image(void); /* * Address to jump to in the last phase of restore in order to get to the image diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 201d09a7c46b..c34bfc4bbe7f 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -1515,7 +1515,7 @@ static void __init xen_pvh_early_guest_init(void) } /* First C function to be called on Xen boot */ -asmlinkage void __init xen_start_kernel(void) +asmlinkage __visible void __init xen_start_kernel(void) { struct physdev_set_iopl set_iopl; int rc; diff --git a/arch/x86/xen/irq.c b/arch/x86/xen/irq.c index 08f763de26fe..a1207cb6472a 100644 --- a/arch/x86/xen/irq.c +++ b/arch/x86/xen/irq.c @@ -23,7 +23,7 @@ void xen_force_evtchn_callback(void) (void)HYPERVISOR_xen_version(0, NULL); } -asmlinkage unsigned long xen_save_fl(void) +asmlinkage __visible unsigned long xen_save_fl(void) { struct vcpu_info *vcpu; unsigned long flags; @@ -63,7 +63,7 @@ __visible void xen_restore_fl(unsigned long flags) } PV_CALLEE_SAVE_REGS_THUNK(xen_restore_fl); -asmlinkage void xen_irq_disable(void) +asmlinkage __visible void xen_irq_disable(void) { /* There's a one instruction preempt window here. We need to make sure we're don't switch CPUs between getting the vcpu @@ -74,7 +74,7 @@ asmlinkage void xen_irq_disable(void) } PV_CALLEE_SAVE_REGS_THUNK(xen_irq_disable); -asmlinkage void xen_irq_enable(void) +asmlinkage __visible void xen_irq_enable(void) { struct vcpu_info *vcpu; -- cgit v1.2.3 From 722a9f9299ca720a3f14660e7c0dce7b76a9cb42 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Fri, 2 May 2014 00:44:38 +0200 Subject: asmlinkage: Add explicit __visible to drivers/*, lib/*, kernel/* As requested by Linus add explicit __visible to the asmlinkage users. This marks functions visible to assembler. Tree sweep for rest of tree. Signed-off-by: Andi Kleen Link: http://lkml.kernel.org/r/1398984278-29319-4-git-send-email-andi@firstfloor.org Signed-off-by: H. Peter Anvin --- drivers/pnp/pnpbios/bioscalls.c | 2 +- init/main.c | 2 +- kernel/context_tracking.c | 2 +- kernel/locking/lockdep.c | 2 +- kernel/power/snapshot.c | 2 +- kernel/printk/printk.c | 4 ++-- kernel/sched/core.c | 10 +++++----- kernel/softirq.c | 4 ++-- lib/dump_stack.c | 4 ++-- 9 files changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/pnp/pnpbios/bioscalls.c b/drivers/pnp/pnpbios/bioscalls.c index deb7f4bcdb7b..438d4c72c7b3 100644 --- a/drivers/pnp/pnpbios/bioscalls.c +++ b/drivers/pnp/pnpbios/bioscalls.c @@ -37,7 +37,7 @@ __visible struct { * kernel begins at offset 3GB... */ -asmlinkage void pnp_bios_callfunc(void); +asmlinkage __visible void pnp_bios_callfunc(void); __asm__(".text \n" __ALIGN_STR "\n" diff --git a/init/main.c b/init/main.c index 9c7fd4c9249f..48655ceb66f4 100644 --- a/init/main.c +++ b/init/main.c @@ -476,7 +476,7 @@ static void __init mm_init(void) vmalloc_init(); } -asmlinkage void __init start_kernel(void) +asmlinkage __visible void __init start_kernel(void) { char * command_line; extern const struct kernel_param __start___param[], __stop___param[]; diff --git a/kernel/context_tracking.c b/kernel/context_tracking.c index 6cb20d2e7ee0..019d45008448 100644 --- a/kernel/context_tracking.c +++ b/kernel/context_tracking.c @@ -120,7 +120,7 @@ void context_tracking_user_enter(void) * instead of preempt_schedule() to exit user context if needed before * calling the scheduler. */ -asmlinkage void __sched notrace preempt_schedule_context(void) +asmlinkage __visible void __sched notrace preempt_schedule_context(void) { enum ctx_state prev_ctx; diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c index b0e9467922e1..d24e4339b46d 100644 --- a/kernel/locking/lockdep.c +++ b/kernel/locking/lockdep.c @@ -4188,7 +4188,7 @@ void debug_show_held_locks(struct task_struct *task) } EXPORT_SYMBOL_GPL(debug_show_held_locks); -asmlinkage void lockdep_sys_exit(void) +asmlinkage __visible void lockdep_sys_exit(void) { struct task_struct *curr = current; diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c index 18fb7a2fb14b..1ea328aafdc9 100644 --- a/kernel/power/snapshot.c +++ b/kernel/power/snapshot.c @@ -1586,7 +1586,7 @@ swsusp_alloc(struct memory_bitmap *orig_bm, struct memory_bitmap *copy_bm, return -ENOMEM; } -asmlinkage int swsusp_save(void) +asmlinkage __visible int swsusp_save(void) { unsigned int nr_pages, nr_highmem; diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index a45b50962295..7228258b85ec 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -1674,7 +1674,7 @@ EXPORT_SYMBOL(printk_emit); * * See the vsnprintf() documentation for format string extensions over C99. */ -asmlinkage int printk(const char *fmt, ...) +asmlinkage __visible int printk(const char *fmt, ...) { va_list args; int r; @@ -1737,7 +1737,7 @@ void early_vprintk(const char *fmt, va_list ap) } } -asmlinkage void early_printk(const char *fmt, ...) +asmlinkage __visible void early_printk(const char *fmt, ...) { va_list ap; diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 268a45ea238c..d9d8ece46a15 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -2192,7 +2192,7 @@ static inline void post_schedule(struct rq *rq) * schedule_tail - first thing a freshly forked thread must call. * @prev: the thread we just switched away from. */ -asmlinkage void schedule_tail(struct task_struct *prev) +asmlinkage __visible void schedule_tail(struct task_struct *prev) __releases(rq->lock) { struct rq *rq = this_rq(); @@ -2741,7 +2741,7 @@ static inline void sched_submit_work(struct task_struct *tsk) blk_schedule_flush_plug(tsk); } -asmlinkage void __sched schedule(void) +asmlinkage __visible void __sched schedule(void) { struct task_struct *tsk = current; @@ -2751,7 +2751,7 @@ asmlinkage void __sched schedule(void) EXPORT_SYMBOL(schedule); #ifdef CONFIG_CONTEXT_TRACKING -asmlinkage void __sched schedule_user(void) +asmlinkage __visible void __sched schedule_user(void) { /* * If we come here after a random call to set_need_resched(), @@ -2783,7 +2783,7 @@ void __sched schedule_preempt_disabled(void) * off of preempt_enable. Kernel preemptions off return from interrupt * occur there and call schedule directly. */ -asmlinkage void __sched notrace preempt_schedule(void) +asmlinkage __visible void __sched notrace preempt_schedule(void) { /* * If there is a non-zero preempt_count or interrupts are disabled, @@ -2813,7 +2813,7 @@ EXPORT_SYMBOL(preempt_schedule); * Note, that this is called and return with irqs disabled. This will * protect us against recursive calling from irq. */ -asmlinkage void __sched preempt_schedule_irq(void) +asmlinkage __visible void __sched preempt_schedule_irq(void) { enum ctx_state prev_state; diff --git a/kernel/softirq.c b/kernel/softirq.c index 33e4648ae0e7..92f24f5e8d52 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c @@ -223,7 +223,7 @@ static inline bool lockdep_softirq_start(void) { return false; } static inline void lockdep_softirq_end(bool in_hardirq) { } #endif -asmlinkage void __do_softirq(void) +asmlinkage __visible void __do_softirq(void) { unsigned long end = jiffies + MAX_SOFTIRQ_TIME; unsigned long old_flags = current->flags; @@ -299,7 +299,7 @@ restart: tsk_restore_flags(current, old_flags, PF_MEMALLOC); } -asmlinkage void do_softirq(void) +asmlinkage __visible void do_softirq(void) { __u32 pending; unsigned long flags; diff --git a/lib/dump_stack.c b/lib/dump_stack.c index f23b63f0a1c3..6745c6230db3 100644 --- a/lib/dump_stack.c +++ b/lib/dump_stack.c @@ -23,7 +23,7 @@ static void __dump_stack(void) #ifdef CONFIG_SMP static atomic_t dump_lock = ATOMIC_INIT(-1); -asmlinkage void dump_stack(void) +asmlinkage __visible void dump_stack(void) { int was_locked; int old; @@ -55,7 +55,7 @@ retry: preempt_enable(); } #else -asmlinkage void dump_stack(void) +asmlinkage __visible void dump_stack(void) { __dump_stack(); } -- cgit v1.2.3 From d48dc067450d84324067f4472dc0b169e9af4454 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Wed, 30 Apr 2014 10:05:40 +0800 Subject: ACPICA: Tables: Fix invalid pointer accesses in acpi_tb_parse_root_table(). Linux XSDT validation mechanism backport has introduced a regreession: Commit: 671cc68dc61f029d44b43a681356078e02d8dab8 Subject: ACPICA: Back port and refine validation of the XSDT root table. There is a pointer still accessed after unmapping. This patch fixes this issue. Lv Zheng. Fixes: 671cc68dc61f (ACPICA: Back port and refine validation of the XSDT root table.) References: https://bugzilla.kernel.org/show_bug.cgi?id=73911 References: https://bugs.archlinux.org/task/39811 Signed-off-by: Lv Zheng Reported-and-tested-by: Bruce Chiarelli Reported-and-tested-by: Spyros Stathopoulos Signed-off-by: Bob Moore Cc: 3.14+ # 3.14+ Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/tbutils.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c index a4702eee91a8..9fb85f38de90 100644 --- a/drivers/acpi/acpica/tbutils.c +++ b/drivers/acpi/acpica/tbutils.c @@ -461,6 +461,7 @@ acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address) u32 table_count; struct acpi_table_header *table; acpi_physical_address address; + acpi_physical_address rsdt_address; u32 length; u8 *table_entry; acpi_status status; @@ -488,11 +489,14 @@ acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address) * as per the ACPI specification. */ address = (acpi_physical_address) rsdp->xsdt_physical_address; + rsdt_address = + (acpi_physical_address) rsdp->rsdt_physical_address; table_entry_size = ACPI_XSDT_ENTRY_SIZE; } else { /* Root table is an RSDT (32-bit physical addresses) */ address = (acpi_physical_address) rsdp->rsdt_physical_address; + rsdt_address = address; table_entry_size = ACPI_RSDT_ENTRY_SIZE; } @@ -515,8 +519,7 @@ acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address) /* Fall back to the RSDT */ - address = - (acpi_physical_address) rsdp->rsdt_physical_address; + address = rsdt_address; table_entry_size = ACPI_RSDT_ENTRY_SIZE; } } -- cgit v1.2.3 From cc13b1d1500656a20e41960668f3392dda9fa6e2 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 5 May 2014 13:34:37 +1000 Subject: md/raid10: call wait_barrier() for each request submitted. wait_barrier() includes a counter, so we must call it precisely once (unless balanced by allow_barrier()) for each request submitted. Since commit 20d0189b1012a37d2533a87fb451f7852f2418d1 block: Introduce new bio_split() in 3.14-rc1, we don't call it for the extra requests generated when we need to split a bio. When this happens the counter goes negative, any resync/recovery will never start, and "mdadm --stop" will hang. Reported-by: Chris Murphy Fixes: 20d0189b1012a37d2533a87fb451f7852f2418d1 Cc: stable@vger.kernel.org (3.14+) Cc: Kent Overstreet Signed-off-by: NeilBrown --- drivers/md/raid10.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 33fc408e5eac..cb882aae9e20 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -1172,6 +1172,13 @@ static void __make_request(struct mddev *mddev, struct bio *bio) int max_sectors; int sectors; + /* + * Register the new request and wait if the reconstruction + * thread has put up a bar for new requests. + * Continue immediately if no resync is active currently. + */ + wait_barrier(conf); + sectors = bio_sectors(bio); while (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) && bio->bi_iter.bi_sector < conf->reshape_progress && @@ -1552,12 +1559,6 @@ static void make_request(struct mddev *mddev, struct bio *bio) md_write_start(mddev, bio); - /* - * Register the new request and wait if the reconstruction - * thread has put up a bar for new requests. - * Continue immediately if no resync is active currently. - */ - wait_barrier(conf); do { -- cgit v1.2.3 From 0f62fb220aa4ebabe8547d3a9ce4a16d3c045f21 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 6 May 2014 09:36:08 +1000 Subject: md: avoid possible spinning md thread at shutdown. If an md array with externally managed metadata (e.g. DDF or IMSM) is in use, then we should not set safemode==2 at shutdown because: 1/ this is ineffective: user-space need to be involved in any 'safemode' handling, 2/ The safemode management code doesn't cope with safemode==2 on external metadata and md_check_recover enters an infinite loop. Even at shutdown, an infinite-looping process can be problematic, so this could cause shutdown to hang. Cc: stable@vger.kernel.org (any kernel) Signed-off-by: NeilBrown --- drivers/md/md.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index 8fda38d23e38..237b7e0ddc7a 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -8516,7 +8516,8 @@ static int md_notify_reboot(struct notifier_block *this, if (mddev_trylock(mddev)) { if (mddev->pers) __md_stop_writes(mddev); - mddev->safemode = 2; + if (mddev->persistent) + mddev->safemode = 2; mddev_unlock(mddev); } need_delay = 1; -- cgit v1.2.3 From e2a7c3d7812369daae56f069eab2e8f3e548d231 Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Sun, 4 May 2014 11:07:24 +0800 Subject: ACPI: Revert "ACPI: Remove CONFIG_ACPI_PROCFS_POWER and cm_sbsc.c" The commit 1e2d9cd and 7d7ee95 remove ACPI Proc Battery directory and breaks some old userspace tools. This patch is to revert 7d7ee95. Fixes: 7d7ee958867a (ACPI: Remove CONFIG_ACPI_PROCFS_POWER and cm_sbsc.c) Cc: 3.13+ # 3.13+ Signed-off-by: Lan Tianyu Signed-off-by: Rafael J. Wysocki --- drivers/acpi/Kconfig | 17 ++++++++ drivers/acpi/Makefile | 1 + drivers/acpi/cm_sbs.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 123 insertions(+) create mode 100644 drivers/acpi/cm_sbs.c diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index ab686b310100..c0160bb451e9 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -47,6 +47,23 @@ config ACPI_SLEEP depends on SUSPEND || HIBERNATION default y +config ACPI_PROCFS_POWER + bool "Deprecated power /proc/acpi directories" + depends on PROC_FS + help + For backwards compatibility, this option allows + deprecated power /proc/acpi/ directories to exist, even when + they have been replaced by functions in /sys. + The deprecated directories (and their replacements) include: + /proc/acpi/battery/* (/sys/class/power_supply/*) + /proc/acpi/ac_adapter/* (sys/class/power_supply/*) + This option has no effect on /proc/acpi/ directories + and functions, which do not yet exist in /sys + This option, together with the proc directories, will be + deleted in 2.6.39. + + Say N to delete power /proc/acpi/ directories that have moved to /sys/ + config ACPI_EC_DEBUGFS tristate "EC read/write access through /sys/kernel/debug/ec" default n diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 0331f91d56e6..bce34afadcd0 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -47,6 +47,7 @@ acpi-y += sysfs.o acpi-$(CONFIG_X86) += acpi_cmos_rtc.o acpi-$(CONFIG_DEBUG_FS) += debugfs.o acpi-$(CONFIG_ACPI_NUMA) += numa.o +acpi-$(CONFIG_ACPI_PROCFS_POWER) += cm_sbs.o ifdef CONFIG_ACPI_VIDEO acpi-y += video_detect.o endif diff --git a/drivers/acpi/cm_sbs.c b/drivers/acpi/cm_sbs.c new file mode 100644 index 000000000000..6c9ee68e46fb --- /dev/null +++ b/drivers/acpi/cm_sbs.c @@ -0,0 +1,105 @@ +/* + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PREFIX "ACPI: " + +ACPI_MODULE_NAME("cm_sbs"); +#define ACPI_AC_CLASS "ac_adapter" +#define ACPI_BATTERY_CLASS "battery" +#define _COMPONENT ACPI_SBS_COMPONENT +static struct proc_dir_entry *acpi_ac_dir; +static struct proc_dir_entry *acpi_battery_dir; + +static DEFINE_MUTEX(cm_sbs_mutex); + +static int lock_ac_dir_cnt; +static int lock_battery_dir_cnt; + +struct proc_dir_entry *acpi_lock_ac_dir(void) +{ + mutex_lock(&cm_sbs_mutex); + if (!acpi_ac_dir) + acpi_ac_dir = proc_mkdir(ACPI_AC_CLASS, acpi_root_dir); + if (acpi_ac_dir) { + lock_ac_dir_cnt++; + } else { + printk(KERN_ERR PREFIX + "Cannot create %s\n", ACPI_AC_CLASS); + } + mutex_unlock(&cm_sbs_mutex); + return acpi_ac_dir; +} +EXPORT_SYMBOL(acpi_lock_ac_dir); + +void acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir_param) +{ + mutex_lock(&cm_sbs_mutex); + if (acpi_ac_dir_param) + lock_ac_dir_cnt--; + if (lock_ac_dir_cnt == 0 && acpi_ac_dir_param && acpi_ac_dir) { + remove_proc_entry(ACPI_AC_CLASS, acpi_root_dir); + acpi_ac_dir = NULL; + } + mutex_unlock(&cm_sbs_mutex); +} +EXPORT_SYMBOL(acpi_unlock_ac_dir); + +struct proc_dir_entry *acpi_lock_battery_dir(void) +{ + mutex_lock(&cm_sbs_mutex); + if (!acpi_battery_dir) { + acpi_battery_dir = + proc_mkdir(ACPI_BATTERY_CLASS, acpi_root_dir); + } + if (acpi_battery_dir) { + lock_battery_dir_cnt++; + } else { + printk(KERN_ERR PREFIX + "Cannot create %s\n", ACPI_BATTERY_CLASS); + } + mutex_unlock(&cm_sbs_mutex); + return acpi_battery_dir; +} +EXPORT_SYMBOL(acpi_lock_battery_dir); + +void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir_param) +{ + mutex_lock(&cm_sbs_mutex); + if (acpi_battery_dir_param) + lock_battery_dir_cnt--; + if (lock_battery_dir_cnt == 0 && acpi_battery_dir_param + && acpi_battery_dir) { + remove_proc_entry(ACPI_BATTERY_CLASS, acpi_root_dir); + acpi_battery_dir = NULL; + } + mutex_unlock(&cm_sbs_mutex); + return; +} +EXPORT_SYMBOL(acpi_unlock_battery_dir); -- cgit v1.2.3 From 3a670cc79342c36d308decd5f90351830ed1685c Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Sun, 4 May 2014 11:07:25 +0800 Subject: ACPI: Revert "ACPI / Battery: Remove battery's proc directory" The commit 1e2d9cd and 7d7ee95 remove ACPI Proc Battery directory and breaks some old userspace tools. This patch is to revert commit 1e2d9cd. Fixes: 1e2d9cdfb449 (ACPI / Battery: Remove battery's proc directory) Cc: 3.13+ # 3.13+ Signed-off-by: Lan Tianyu Signed-off-by: Rafael J. Wysocki --- drivers/acpi/battery.c | 329 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 328 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 9a2c63b20050..6e7b2a12860d 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -36,6 +36,12 @@ #include #include +#ifdef CONFIG_ACPI_PROCFS_POWER +#include +#include +#include +#endif + #include #include @@ -64,6 +70,19 @@ static unsigned int cache_time = 1000; module_param(cache_time, uint, 0644); MODULE_PARM_DESC(cache_time, "cache time in milliseconds"); +#ifdef CONFIG_ACPI_PROCFS_POWER +extern struct proc_dir_entry *acpi_lock_battery_dir(void); +extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); + +enum acpi_battery_files { + info_tag = 0, + state_tag, + alarm_tag, + ACPI_BATTERY_NUMFILES, +}; + +#endif + static const struct acpi_device_id battery_device_ids[] = { {"PNP0C0A", 0}, {"", 0}, @@ -299,6 +318,14 @@ static enum power_supply_property energy_battery_props[] = { POWER_SUPPLY_PROP_SERIAL_NUMBER, }; +#ifdef CONFIG_ACPI_PROCFS_POWER +inline char *acpi_battery_units(struct acpi_battery *battery) +{ + return (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA) ? + "mA" : "mW"; +} +#endif + /* -------------------------------------------------------------------------- Battery Management -------------------------------------------------------------------------- */ @@ -716,6 +743,279 @@ static void acpi_battery_refresh(struct acpi_battery *battery) sysfs_add_battery(battery); } +/* -------------------------------------------------------------------------- + FS Interface (/proc) + -------------------------------------------------------------------------- */ + +#ifdef CONFIG_ACPI_PROCFS_POWER +static struct proc_dir_entry *acpi_battery_dir; + +static int acpi_battery_print_info(struct seq_file *seq, int result) +{ + struct acpi_battery *battery = seq->private; + + if (result) + goto end; + + seq_printf(seq, "present: %s\n", + acpi_battery_present(battery) ? "yes" : "no"); + if (!acpi_battery_present(battery)) + goto end; + if (battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN) + seq_printf(seq, "design capacity: unknown\n"); + else + seq_printf(seq, "design capacity: %d %sh\n", + battery->design_capacity, + acpi_battery_units(battery)); + + if (battery->full_charge_capacity == ACPI_BATTERY_VALUE_UNKNOWN) + seq_printf(seq, "last full capacity: unknown\n"); + else + seq_printf(seq, "last full capacity: %d %sh\n", + battery->full_charge_capacity, + acpi_battery_units(battery)); + + seq_printf(seq, "battery technology: %srechargeable\n", + (!battery->technology)?"non-":""); + + if (battery->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN) + seq_printf(seq, "design voltage: unknown\n"); + else + seq_printf(seq, "design voltage: %d mV\n", + battery->design_voltage); + seq_printf(seq, "design capacity warning: %d %sh\n", + battery->design_capacity_warning, + acpi_battery_units(battery)); + seq_printf(seq, "design capacity low: %d %sh\n", + battery->design_capacity_low, + acpi_battery_units(battery)); + seq_printf(seq, "cycle count: %i\n", battery->cycle_count); + seq_printf(seq, "capacity granularity 1: %d %sh\n", + battery->capacity_granularity_1, + acpi_battery_units(battery)); + seq_printf(seq, "capacity granularity 2: %d %sh\n", + battery->capacity_granularity_2, + acpi_battery_units(battery)); + seq_printf(seq, "model number: %s\n", battery->model_number); + seq_printf(seq, "serial number: %s\n", battery->serial_number); + seq_printf(seq, "battery type: %s\n", battery->type); + seq_printf(seq, "OEM info: %s\n", battery->oem_info); + end: + if (result) + seq_printf(seq, "ERROR: Unable to read battery info\n"); + return result; +} + +static int acpi_battery_print_state(struct seq_file *seq, int result) +{ + struct acpi_battery *battery = seq->private; + + if (result) + goto end; + + seq_printf(seq, "present: %s\n", + acpi_battery_present(battery) ? "yes" : "no"); + if (!acpi_battery_present(battery)) + goto end; + + seq_printf(seq, "capacity state: %s\n", + (battery->state & 0x04) ? "critical" : "ok"); + if ((battery->state & 0x01) && (battery->state & 0x02)) + seq_printf(seq, + "charging state: charging/discharging\n"); + else if (battery->state & 0x01) + seq_printf(seq, "charging state: discharging\n"); + else if (battery->state & 0x02) + seq_printf(seq, "charging state: charging\n"); + else + seq_printf(seq, "charging state: charged\n"); + + if (battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN) + seq_printf(seq, "present rate: unknown\n"); + else + seq_printf(seq, "present rate: %d %s\n", + battery->rate_now, acpi_battery_units(battery)); + + if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN) + seq_printf(seq, "remaining capacity: unknown\n"); + else + seq_printf(seq, "remaining capacity: %d %sh\n", + battery->capacity_now, acpi_battery_units(battery)); + if (battery->voltage_now == ACPI_BATTERY_VALUE_UNKNOWN) + seq_printf(seq, "present voltage: unknown\n"); + else + seq_printf(seq, "present voltage: %d mV\n", + battery->voltage_now); + end: + if (result) + seq_printf(seq, "ERROR: Unable to read battery state\n"); + + return result; +} + +static int acpi_battery_print_alarm(struct seq_file *seq, int result) +{ + struct acpi_battery *battery = seq->private; + + if (result) + goto end; + + if (!acpi_battery_present(battery)) { + seq_printf(seq, "present: no\n"); + goto end; + } + seq_printf(seq, "alarm: "); + if (!battery->alarm) + seq_printf(seq, "unsupported\n"); + else + seq_printf(seq, "%u %sh\n", battery->alarm, + acpi_battery_units(battery)); + end: + if (result) + seq_printf(seq, "ERROR: Unable to read battery alarm\n"); + return result; +} + +static ssize_t acpi_battery_write_alarm(struct file *file, + const char __user * buffer, + size_t count, loff_t * ppos) +{ + int result = 0; + char alarm_string[12] = { '\0' }; + struct seq_file *m = file->private_data; + struct acpi_battery *battery = m->private; + + if (!battery || (count > sizeof(alarm_string) - 1)) + return -EINVAL; + if (!acpi_battery_present(battery)) { + result = -ENODEV; + goto end; + } + if (copy_from_user(alarm_string, buffer, count)) { + result = -EFAULT; + goto end; + } + alarm_string[count] = '\0'; + battery->alarm = simple_strtol(alarm_string, NULL, 0); + result = acpi_battery_set_alarm(battery); + end: + if (!result) + return count; + return result; +} + +typedef int(*print_func)(struct seq_file *seq, int result); + +static print_func acpi_print_funcs[ACPI_BATTERY_NUMFILES] = { + acpi_battery_print_info, + acpi_battery_print_state, + acpi_battery_print_alarm, +}; + +static int acpi_battery_read(int fid, struct seq_file *seq) +{ + struct acpi_battery *battery = seq->private; + int result = acpi_battery_update(battery); + return acpi_print_funcs[fid](seq, result); +} + +#define DECLARE_FILE_FUNCTIONS(_name) \ +static int acpi_battery_read_##_name(struct seq_file *seq, void *offset) \ +{ \ + return acpi_battery_read(_name##_tag, seq); \ +} \ +static int acpi_battery_##_name##_open_fs(struct inode *inode, struct file *file) \ +{ \ + return single_open(file, acpi_battery_read_##_name, PDE_DATA(inode)); \ +} + +DECLARE_FILE_FUNCTIONS(info); +DECLARE_FILE_FUNCTIONS(state); +DECLARE_FILE_FUNCTIONS(alarm); + +#undef DECLARE_FILE_FUNCTIONS + +#define FILE_DESCRIPTION_RO(_name) \ + { \ + .name = __stringify(_name), \ + .mode = S_IRUGO, \ + .ops = { \ + .open = acpi_battery_##_name##_open_fs, \ + .read = seq_read, \ + .llseek = seq_lseek, \ + .release = single_release, \ + .owner = THIS_MODULE, \ + }, \ + } + +#define FILE_DESCRIPTION_RW(_name) \ + { \ + .name = __stringify(_name), \ + .mode = S_IFREG | S_IRUGO | S_IWUSR, \ + .ops = { \ + .open = acpi_battery_##_name##_open_fs, \ + .read = seq_read, \ + .llseek = seq_lseek, \ + .write = acpi_battery_write_##_name, \ + .release = single_release, \ + .owner = THIS_MODULE, \ + }, \ + } + +static const struct battery_file { + struct file_operations ops; + umode_t mode; + const char *name; +} acpi_battery_file[] = { + FILE_DESCRIPTION_RO(info), + FILE_DESCRIPTION_RO(state), + FILE_DESCRIPTION_RW(alarm), +}; + +#undef FILE_DESCRIPTION_RO +#undef FILE_DESCRIPTION_RW + +static int acpi_battery_add_fs(struct acpi_device *device) +{ + struct proc_dir_entry *entry = NULL; + int i; + + printk(KERN_WARNING PREFIX "Deprecated procfs I/F for battery is loaded," + " please retry with CONFIG_ACPI_PROCFS_POWER cleared\n"); + if (!acpi_device_dir(device)) { + acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), + acpi_battery_dir); + if (!acpi_device_dir(device)) + return -ENODEV; + } + + for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i) { + entry = proc_create_data(acpi_battery_file[i].name, + acpi_battery_file[i].mode, + acpi_device_dir(device), + &acpi_battery_file[i].ops, + acpi_driver_data(device)); + if (!entry) + return -ENODEV; + } + return 0; +} + +static void acpi_battery_remove_fs(struct acpi_device *device) +{ + int i; + if (!acpi_device_dir(device)) + return; + for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i) + remove_proc_entry(acpi_battery_file[i].name, + acpi_device_dir(device)); + + remove_proc_entry(acpi_device_bid(device), acpi_battery_dir); + acpi_device_dir(device) = NULL; +} + +#endif + /* -------------------------------------------------------------------------- Driver Interface -------------------------------------------------------------------------- */ @@ -790,6 +1090,15 @@ static int acpi_battery_add(struct acpi_device *device) result = acpi_battery_update(battery); if (result) goto fail; +#ifdef CONFIG_ACPI_PROCFS_POWER + result = acpi_battery_add_fs(device); +#endif + if (result) { +#ifdef CONFIG_ACPI_PROCFS_POWER + acpi_battery_remove_fs(device); +#endif + goto fail; + } printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n", ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device), @@ -816,6 +1125,9 @@ static int acpi_battery_remove(struct acpi_device *device) return -EINVAL; battery = acpi_driver_data(device); unregister_pm_notifier(&battery->pm_nb); +#ifdef CONFIG_ACPI_PROCFS_POWER + acpi_battery_remove_fs(device); +#endif sysfs_remove_battery(battery); mutex_destroy(&battery->lock); mutex_destroy(&battery->sysfs_lock); @@ -866,7 +1178,19 @@ static void __init acpi_battery_init_async(void *unused, async_cookie_t cookie) if (dmi_check_system(bat_dmi_table)) battery_bix_broken_package = 1; - acpi_bus_register_driver(&acpi_battery_driver); + +#ifdef CONFIG_ACPI_PROCFS_POWER + acpi_battery_dir = acpi_lock_battery_dir(); + if (!acpi_battery_dir) + return; +#endif + if (acpi_bus_register_driver(&acpi_battery_driver) < 0) { +#ifdef CONFIG_ACPI_PROCFS_POWER + acpi_unlock_battery_dir(acpi_battery_dir); +#endif + return; + } + return; } static int __init acpi_battery_init(void) @@ -878,6 +1202,9 @@ static int __init acpi_battery_init(void) static void __exit acpi_battery_exit(void) { acpi_bus_unregister_driver(&acpi_battery_driver); +#ifdef CONFIG_ACPI_PROCFS_POWER + acpi_unlock_battery_dir(acpi_battery_dir); +#endif } module_init(acpi_battery_init); -- cgit v1.2.3 From 43d9490244254d2d6adb0f3c6275c7b8d032a2dd Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 5 May 2014 11:38:08 +0200 Subject: ACPI / video: Add use_native_backlight quirks for more systems ThinkPad T430: extend the T430s entry to also cover the T430 (note we also have another entry for T430's with a different DMI_PRODUCT_VERSION). ThinkPad T430 Reported-and-tested-by: edm References: https://bugzilla.kernel.org/show_bug.cgi?id=51231 Thinkpad T530 Reported-and-tested-by: Balint Szigeti References: https://bugzilla.redhat.com/show_bug.cgi?id=1089545 Acer Aspire 5742G Reported-and-tested-by: AnAkkk References: https://bugzilla.kernel.org/show_bug.cgi?id=35622 Cc: All applicable Signed-off-by: Hans de Goede Signed-off-by: Rafael J. Wysocki --- drivers/acpi/video.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 8b6990e417ec..88393899a0bc 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -457,10 +457,10 @@ static struct dmi_system_id video_dmi_table[] __initdata = { }, { .callback = video_set_use_native_backlight, - .ident = "ThinkPad T430s", + .ident = "ThinkPad T430 and T430s", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T430s"), + DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T430"), }, }, { @@ -471,6 +471,14 @@ static struct dmi_system_id video_dmi_table[] __initdata = { DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X230"), }, }, + { + .callback = video_set_use_native_backlight, + .ident = "ThinkPad T530", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T530"), + }, + }, { .callback = video_set_use_native_backlight, .ident = "ThinkPad X1 Carbon", @@ -511,6 +519,14 @@ static struct dmi_system_id video_dmi_table[] __initdata = { DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5733Z"), }, }, + { + .callback = video_set_use_native_backlight, + .ident = "Acer Aspire 5742G", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5742G"), + }, + }, { .callback = video_set_use_native_backlight, .ident = "Acer Aspire V5-431", -- cgit v1.2.3 From edb666f07e539d92f63284213d72083ed8ac05ea Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Tue, 29 Apr 2014 08:23:03 +0200 Subject: xfrm6: Properly handle unsupported protocols We don't catch the case if an unsupported protocol is submitted to the xfrm6 protocol handlers, this can lead to NULL pointer dereferences. Fix this by adding the appropriate checks. Fixes: 7e14ea15 ("xfrm6: Add IPsec protocol multiplexer") Signed-off-by: Steffen Klassert --- net/ipv6/xfrm6_protocol.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/net/ipv6/xfrm6_protocol.c b/net/ipv6/xfrm6_protocol.c index 6ab989c486f7..54d13f8dbbae 100644 --- a/net/ipv6/xfrm6_protocol.c +++ b/net/ipv6/xfrm6_protocol.c @@ -50,6 +50,10 @@ int xfrm6_rcv_cb(struct sk_buff *skb, u8 protocol, int err) { int ret; struct xfrm6_protocol *handler; + struct xfrm6_protocol __rcu **head = proto_handlers(protocol); + + if (!head) + return 0; for_each_protocol_rcu(*proto_handlers(protocol), handler) if ((ret = handler->cb_handler(skb, err)) <= 0) @@ -184,10 +188,12 @@ int xfrm6_protocol_register(struct xfrm6_protocol *handler, struct xfrm6_protocol __rcu **pprev; struct xfrm6_protocol *t; bool add_netproto = false; - int ret = -EEXIST; int priority = handler->priority; + if (!proto_handlers(protocol) || !netproto(protocol)) + return -EINVAL; + mutex_lock(&xfrm6_protocol_mutex); if (!rcu_dereference_protected(*proto_handlers(protocol), @@ -230,6 +236,9 @@ int xfrm6_protocol_deregister(struct xfrm6_protocol *handler, struct xfrm6_protocol *t; int ret = -ENOENT; + if (!proto_handlers(protocol) || !netproto(protocol)) + return -EINVAL; + mutex_lock(&xfrm6_protocol_mutex); for (pprev = proto_handlers(protocol); -- cgit v1.2.3 From e9d14aeb3005fc09a937ca419c08b3c612a76a90 Mon Sep 17 00:00:00 2001 From: Michel Dänzer Date: Tue, 22 Apr 2014 16:53:52 +0900 Subject: drm/radeon: Fix num_banks calculation for SI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The way the tile mode array index was calculated only makes sense for the CIK specific macrotile mode array. For SI, we need to use one of the tile mode array indices reserved for displayable surfaces. This happened to result in correct display most if not all of the time because most of the SI tiling modes use the same number of banks. Signed-off-by: Michel Dänzer Reviewed-by: Alex Deucher Signed-off-by: Christian König --- drivers/gpu/drm/radeon/atombios_crtc.c | 46 +++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index fb187c78978f..229be38cc6ca 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -1177,27 +1177,43 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, /* Set NUM_BANKS. */ if (rdev->family >= CHIP_TAHITI) { - unsigned tileb, index, num_banks, tile_split_bytes; + unsigned index, num_banks; - /* Calculate the macrotile mode index. */ - tile_split_bytes = 64 << tile_split; - tileb = 8 * 8 * target_fb->bits_per_pixel / 8; - tileb = min(tile_split_bytes, tileb); + if (rdev->family >= CHIP_BONAIRE) { + unsigned tileb, tile_split_bytes; - for (index = 0; tileb > 64; index++) { - tileb >>= 1; - } + /* Calculate the macrotile mode index. */ + tile_split_bytes = 64 << tile_split; + tileb = 8 * 8 * target_fb->bits_per_pixel / 8; + tileb = min(tile_split_bytes, tileb); - if (index >= 16) { - DRM_ERROR("Wrong screen bpp (%u) or tile split (%u)\n", - target_fb->bits_per_pixel, tile_split); - return -EINVAL; - } + for (index = 0; tileb > 64; index++) + tileb >>= 1; + + if (index >= 16) { + DRM_ERROR("Wrong screen bpp (%u) or tile split (%u)\n", + target_fb->bits_per_pixel, tile_split); + return -EINVAL; + } - if (rdev->family >= CHIP_BONAIRE) num_banks = (rdev->config.cik.macrotile_mode_array[index] >> 6) & 0x3; - else + } else { + switch (target_fb->bits_per_pixel) { + case 8: + index = 10; + break; + case 16: + index = SI_TILE_MODE_COLOR_2D_SCANOUT_16BPP; + break; + default: + case 32: + index = SI_TILE_MODE_COLOR_2D_SCANOUT_32BPP; + break; + } + num_banks = (rdev->config.si.tile_mode_array[index] >> 20) & 0x3; + } + fb_format |= EVERGREEN_GRPH_NUM_BANKS(num_banks); } else { /* NI and older. */ -- cgit v1.2.3 From aa4c8b36e5fcf70ba5ec7d175da19dac4a33c51a Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 24 Apr 2014 13:29:14 +0200 Subject: drm/radeon: drm/radeon: add missing radeon_semaphore_free to error path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It would appear this bug has been copy/pasted many times without being noticed. Signed-off-by: Maarten Lankhorst Signed-off-by: Christian König Reviewed-by: Alex Deucher --- drivers/gpu/drm/radeon/cik.c | 1 + drivers/gpu/drm/radeon/cik_sdma.c | 1 + drivers/gpu/drm/radeon/evergreen_dma.c | 1 + drivers/gpu/drm/radeon/r600.c | 1 + drivers/gpu/drm/radeon/r600_dma.c | 1 + drivers/gpu/drm/radeon/rv770_dma.c | 1 + drivers/gpu/drm/radeon/si_dma.c | 1 + 7 files changed, 7 insertions(+) diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 421c6084cbfc..5143e0bf2172 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -3702,6 +3702,7 @@ int cik_copy_cpdma(struct radeon_device *rdev, r = radeon_fence_emit(rdev, fence, ring->idx); if (r) { radeon_ring_unlock_undo(rdev, ring); + radeon_semaphore_free(rdev, &sem, NULL); return r; } diff --git a/drivers/gpu/drm/radeon/cik_sdma.c b/drivers/gpu/drm/radeon/cik_sdma.c index f7e46cf682af..72e464c79a88 100644 --- a/drivers/gpu/drm/radeon/cik_sdma.c +++ b/drivers/gpu/drm/radeon/cik_sdma.c @@ -562,6 +562,7 @@ int cik_copy_dma(struct radeon_device *rdev, r = radeon_fence_emit(rdev, fence, ring->idx); if (r) { radeon_ring_unlock_undo(rdev, ring); + radeon_semaphore_free(rdev, &sem, NULL); return r; } diff --git a/drivers/gpu/drm/radeon/evergreen_dma.c b/drivers/gpu/drm/radeon/evergreen_dma.c index 287fe966d7de..478caefe0fef 100644 --- a/drivers/gpu/drm/radeon/evergreen_dma.c +++ b/drivers/gpu/drm/radeon/evergreen_dma.c @@ -151,6 +151,7 @@ int evergreen_copy_dma(struct radeon_device *rdev, r = radeon_fence_emit(rdev, fence, ring->idx); if (r) { radeon_ring_unlock_undo(rdev, ring); + radeon_semaphore_free(rdev, &sem, NULL); return r; } diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 6c4699362bca..bbc189fd3ddc 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -2839,6 +2839,7 @@ int r600_copy_cpdma(struct radeon_device *rdev, r = radeon_fence_emit(rdev, fence, ring->idx); if (r) { radeon_ring_unlock_undo(rdev, ring); + radeon_semaphore_free(rdev, &sem, NULL); return r; } diff --git a/drivers/gpu/drm/radeon/r600_dma.c b/drivers/gpu/drm/radeon/r600_dma.c index 53fcb28f5578..4969cef44a19 100644 --- a/drivers/gpu/drm/radeon/r600_dma.c +++ b/drivers/gpu/drm/radeon/r600_dma.c @@ -489,6 +489,7 @@ int r600_copy_dma(struct radeon_device *rdev, r = radeon_fence_emit(rdev, fence, ring->idx); if (r) { radeon_ring_unlock_undo(rdev, ring); + radeon_semaphore_free(rdev, &sem, NULL); return r; } diff --git a/drivers/gpu/drm/radeon/rv770_dma.c b/drivers/gpu/drm/radeon/rv770_dma.c index aca8cbe8a335..bbf2e076ee45 100644 --- a/drivers/gpu/drm/radeon/rv770_dma.c +++ b/drivers/gpu/drm/radeon/rv770_dma.c @@ -86,6 +86,7 @@ int rv770_copy_dma(struct radeon_device *rdev, r = radeon_fence_emit(rdev, fence, ring->idx); if (r) { radeon_ring_unlock_undo(rdev, ring); + radeon_semaphore_free(rdev, &sem, NULL); return r; } diff --git a/drivers/gpu/drm/radeon/si_dma.c b/drivers/gpu/drm/radeon/si_dma.c index cf0fdad8c278..de0ca070122f 100644 --- a/drivers/gpu/drm/radeon/si_dma.c +++ b/drivers/gpu/drm/radeon/si_dma.c @@ -213,6 +213,7 @@ int si_copy_dma(struct radeon_device *rdev, r = radeon_fence_emit(rdev, fence, ring->idx); if (r) { radeon_ring_unlock_undo(rdev, ring); + radeon_semaphore_free(rdev, &sem, NULL); return r; } -- cgit v1.2.3 From cde10122dc126a223e783f0b40bdb08cc332ab17 Mon Sep 17 00:00:00 2001 From: Christian König Date: Fri, 2 May 2014 14:27:42 +0200 Subject: drm/radeon: check that we have a clock before PLL setup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Partially fixes: https://bugzilla.kernel.org/show_bug.cgi?id=75211 Signed-off-by: Christian König --- drivers/gpu/drm/radeon/atombios_crtc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 229be38cc6ca..b7983aaee445 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -1901,6 +1901,9 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc, (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) is_tvcv = true; + if (!radeon_crtc->adjusted_clock) + return -EINVAL; + atombios_crtc_set_pll(crtc, adjusted_mode); if (ASIC_IS_DCE4(rdev)) -- cgit v1.2.3 From cbe655137aa8f644f4985021a1e1e65df1d28fa8 Mon Sep 17 00:00:00 2001 From: Christian König Date: Thu, 1 May 2014 19:00:41 +0200 Subject: drm/radeon: lower the ref * post PLL maximum MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=75241 Signed-off-by: Christian König --- drivers/gpu/drm/radeon/radeon_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 9ff0e2f1be6a..408b6ac53f0b 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -862,7 +862,7 @@ static void avivo_get_fb_ref_div(unsigned nom, unsigned den, unsigned post_div, unsigned *fb_div, unsigned *ref_div) { /* limit reference * post divider to a maximum */ - ref_div_max = min(210 / post_div, ref_div_max); + ref_div_max = min(128 / post_div, ref_div_max); /* get matching reference and feedback divider */ *ref_div = min(max(DIV_ROUND_CLOSEST(den, post_div), 1u), ref_div_max); -- cgit v1.2.3 From b0a9f22a182487996e530b38e07f02d8ea0bc3cc Mon Sep 17 00:00:00 2001 From: Samuel Li Date: Wed, 30 Apr 2014 18:40:48 -0400 Subject: drm/radeon: add Mullins chip family MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mullins is a new CI-based APU. Signed-off-by: Samuel Li Signed-off-by: Alex Deucher Signed-off-by: Christian König --- drivers/gpu/drm/radeon/radeon_asic.c | 1 + drivers/gpu/drm/radeon/radeon_device.c | 1 + drivers/gpu/drm/radeon/radeon_family.h | 1 + 3 files changed, 3 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index b8a24a75d4ff..be20e62dac83 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c @@ -2516,6 +2516,7 @@ int radeon_asic_init(struct radeon_device *rdev) break; case CHIP_KAVERI: case CHIP_KABINI: + case CHIP_MULLINS: rdev->asic = &kv_asic; /* set num crtcs */ if (rdev->family == CHIP_KAVERI) { diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 511fe26198e4..0e770bbf7e29 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -99,6 +99,7 @@ static const char radeon_family_name[][16] = { "KAVERI", "KABINI", "HAWAII", + "MULLINS", "LAST", }; diff --git a/drivers/gpu/drm/radeon/radeon_family.h b/drivers/gpu/drm/radeon/radeon_family.h index 9da5da4ffd17..4b7b87f71a63 100644 --- a/drivers/gpu/drm/radeon/radeon_family.h +++ b/drivers/gpu/drm/radeon/radeon_family.h @@ -97,6 +97,7 @@ enum radeon_family { CHIP_KAVERI, CHIP_KABINI, CHIP_HAWAII, + CHIP_MULLINS, CHIP_LAST, }; -- cgit v1.2.3 From f73a9e837286bb67c54701441cb51c54aa4abd6a Mon Sep 17 00:00:00 2001 From: Samuel Li Date: Wed, 30 Apr 2014 18:40:49 -0400 Subject: drm/radeon: update cik init for Mullins. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also add golden registers, update firmware loading functions. Signed-off-by: Samuel Li Signed-off-by: Alex Deucher Signed-off-by: Christian König --- drivers/gpu/drm/radeon/cik.c | 71 +++++++++++++++++++++++++++++++++++ drivers/gpu/drm/radeon/radeon_ucode.h | 1 + 2 files changed, 72 insertions(+) diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 5143e0bf2172..d2fd98968085 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -63,6 +63,12 @@ MODULE_FIRMWARE("radeon/KABINI_ce.bin"); MODULE_FIRMWARE("radeon/KABINI_mec.bin"); MODULE_FIRMWARE("radeon/KABINI_rlc.bin"); MODULE_FIRMWARE("radeon/KABINI_sdma.bin"); +MODULE_FIRMWARE("radeon/MULLINS_pfp.bin"); +MODULE_FIRMWARE("radeon/MULLINS_me.bin"); +MODULE_FIRMWARE("radeon/MULLINS_ce.bin"); +MODULE_FIRMWARE("radeon/MULLINS_mec.bin"); +MODULE_FIRMWARE("radeon/MULLINS_rlc.bin"); +MODULE_FIRMWARE("radeon/MULLINS_sdma.bin"); extern int r600_ih_ring_alloc(struct radeon_device *rdev); extern void r600_ih_ring_fini(struct radeon_device *rdev); @@ -1473,6 +1479,43 @@ static const u32 hawaii_mgcg_cgcg_init[] = 0xd80c, 0xff000ff0, 0x00000100 }; +static const u32 godavari_golden_registers[] = +{ + 0x55e4, 0xff607fff, 0xfc000100, + 0x6ed8, 0x00010101, 0x00010000, + 0x9830, 0xffffffff, 0x00000000, + 0x98302, 0xf00fffff, 0x00000400, + 0x6130, 0xffffffff, 0x00010000, + 0x5bb0, 0x000000f0, 0x00000070, + 0x5bc0, 0xf0311fff, 0x80300000, + 0x98f8, 0x73773777, 0x12010001, + 0x98fc, 0xffffffff, 0x00000010, + 0x8030, 0x00001f0f, 0x0000100a, + 0x2f48, 0x73773777, 0x12010001, + 0x2408, 0x000fffff, 0x000c007f, + 0x8a14, 0xf000003f, 0x00000007, + 0x8b24, 0xffffffff, 0x00ff0fff, + 0x30a04, 0x0000ff0f, 0x00000000, + 0x28a4c, 0x07ffffff, 0x06000000, + 0x4d8, 0x00000fff, 0x00000100, + 0xd014, 0x00010000, 0x00810001, + 0xd814, 0x00010000, 0x00810001, + 0x3e78, 0x00000001, 0x00000002, + 0xc768, 0x00000008, 0x00000008, + 0xc770, 0x00000f00, 0x00000800, + 0xc774, 0x00000f00, 0x00000800, + 0xc798, 0x00ffffff, 0x00ff7fbf, + 0xc79c, 0x00ffffff, 0x00ff7faf, + 0x8c00, 0x000000ff, 0x00000001, + 0x214f8, 0x01ff01ff, 0x00000002, + 0x21498, 0x007ff800, 0x00200000, + 0x2015c, 0xffffffff, 0x00000f40, + 0x88c4, 0x001f3ae3, 0x00000082, + 0x88d4, 0x0000001f, 0x00000010, + 0x30934, 0xffffffff, 0x00000000 +}; + + static void cik_init_golden_registers(struct radeon_device *rdev) { switch (rdev->family) { @@ -1504,6 +1547,20 @@ static void cik_init_golden_registers(struct radeon_device *rdev) kalindi_golden_spm_registers, (const u32)ARRAY_SIZE(kalindi_golden_spm_registers)); break; + case CHIP_MULLINS: + radeon_program_register_sequence(rdev, + kalindi_mgcg_cgcg_init, + (const u32)ARRAY_SIZE(kalindi_mgcg_cgcg_init)); + radeon_program_register_sequence(rdev, + godavari_golden_registers, + (const u32)ARRAY_SIZE(godavari_golden_registers)); + radeon_program_register_sequence(rdev, + kalindi_golden_common_registers, + (const u32)ARRAY_SIZE(kalindi_golden_common_registers)); + radeon_program_register_sequence(rdev, + kalindi_golden_spm_registers, + (const u32)ARRAY_SIZE(kalindi_golden_spm_registers)); + break; case CHIP_KAVERI: radeon_program_register_sequence(rdev, spectre_mgcg_cgcg_init, @@ -1834,6 +1891,15 @@ static int cik_init_microcode(struct radeon_device *rdev) rlc_req_size = KB_RLC_UCODE_SIZE * 4; sdma_req_size = CIK_SDMA_UCODE_SIZE * 4; break; + case CHIP_MULLINS: + chip_name = "MULLINS"; + pfp_req_size = CIK_PFP_UCODE_SIZE * 4; + me_req_size = CIK_ME_UCODE_SIZE * 4; + ce_req_size = CIK_CE_UCODE_SIZE * 4; + mec_req_size = CIK_MEC_UCODE_SIZE * 4; + rlc_req_size = ML_RLC_UCODE_SIZE * 4; + sdma_req_size = CIK_SDMA_UCODE_SIZE * 4; + break; default: BUG(); } @@ -3272,6 +3338,7 @@ static void cik_gpu_init(struct radeon_device *rdev) gb_addr_config = BONAIRE_GB_ADDR_CONFIG_GOLDEN; break; case CHIP_KABINI: + case CHIP_MULLINS: default: rdev->config.cik.max_shader_engines = 1; rdev->config.cik.max_tile_pipes = 2; @@ -5801,6 +5868,9 @@ static int cik_rlc_resume(struct radeon_device *rdev) case CHIP_KABINI: size = KB_RLC_UCODE_SIZE; break; + case CHIP_MULLINS: + size = ML_RLC_UCODE_SIZE; + break; } cik_rlc_stop(rdev); @@ -6549,6 +6619,7 @@ void cik_get_csb_buffer(struct radeon_device *rdev, volatile u32 *buffer) buffer[count++] = cpu_to_le32(0x00000000); break; case CHIP_KABINI: + case CHIP_MULLINS: buffer[count++] = cpu_to_le32(0x00000000); /* XXX */ buffer[count++] = cpu_to_le32(0x00000000); break; diff --git a/drivers/gpu/drm/radeon/radeon_ucode.h b/drivers/gpu/drm/radeon/radeon_ucode.h index 58d12938c0b8..4e7c3269b183 100644 --- a/drivers/gpu/drm/radeon/radeon_ucode.h +++ b/drivers/gpu/drm/radeon/radeon_ucode.h @@ -52,6 +52,7 @@ #define BONAIRE_RLC_UCODE_SIZE 2048 #define KB_RLC_UCODE_SIZE 2560 #define KV_RLC_UCODE_SIZE 2560 +#define ML_RLC_UCODE_SIZE 2560 /* MC */ #define BTC_MC_UCODE_SIZE 6024 -- cgit v1.2.3 From 3f6f0737ba8e9a1bbd47b8cd221386c39c76cd6a Mon Sep 17 00:00:00 2001 From: Samuel Li Date: Wed, 30 Apr 2014 18:40:50 -0400 Subject: drm/radeon: add Mullins UVD support. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Has same version of UVD as other CIK parts. Signed-off-by: Samuel Li Signed-off-by: Alex Deucher Signed-off-by: Christian König --- drivers/gpu/drm/radeon/radeon_uvd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c index 0f96c471c6d8..1b65ae2433cd 100644 --- a/drivers/gpu/drm/radeon/radeon_uvd.c +++ b/drivers/gpu/drm/radeon/radeon_uvd.c @@ -99,6 +99,7 @@ int radeon_uvd_init(struct radeon_device *rdev) case CHIP_KABINI: case CHIP_KAVERI: case CHIP_HAWAII: + case CHIP_MULLINS: fw_name = FIRMWARE_BONAIRE; break; -- cgit v1.2.3 From 7d032a4b8d460397b6e4a3f343a59fdd1bd5a487 Mon Sep 17 00:00:00 2001 From: Samuel Li Date: Wed, 30 Apr 2014 18:40:51 -0400 Subject: drm/radeon: add Mullins dpm support. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Generic dpm support similar to Kabini. Mullins specific features will be worked on later. Signed-off-by: Samuel Li Signed-off-by: Alex Deucher Signed-off-by: Christian König --- drivers/gpu/drm/radeon/kv_dpm.c | 20 ++++++++++---------- drivers/gpu/drm/radeon/radeon_pm.c | 1 + 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/radeon/kv_dpm.c b/drivers/gpu/drm/radeon/kv_dpm.c index 16ec9d56a234..6666370e58fa 100644 --- a/drivers/gpu/drm/radeon/kv_dpm.c +++ b/drivers/gpu/drm/radeon/kv_dpm.c @@ -639,7 +639,7 @@ static int kv_force_lowest_valid(struct radeon_device *rdev) static int kv_unforce_levels(struct radeon_device *rdev) { - if (rdev->family == CHIP_KABINI) + if (rdev->family == CHIP_KABINI || rdev->family == CHIP_MULLINS) return kv_notify_message_to_smu(rdev, PPSMC_MSG_NoForcedLevel); else return kv_set_enabled_levels(rdev); @@ -1617,7 +1617,7 @@ static void kv_dpm_powergate_acp(struct radeon_device *rdev, bool gate) if (pi->acp_power_gated == gate) return; - if (rdev->family == CHIP_KABINI) + if (rdev->family == CHIP_KABINI || rdev->family == CHIP_MULLINS) return; pi->acp_power_gated = gate; @@ -1786,7 +1786,7 @@ int kv_dpm_set_power_state(struct radeon_device *rdev) } } - if (rdev->family == CHIP_KABINI) { + if (rdev->family == CHIP_KABINI || rdev->family == CHIP_MULLINS) { if (pi->enable_dpm) { kv_set_valid_clock_range(rdev, new_ps); kv_update_dfs_bypass_settings(rdev, new_ps); @@ -1862,7 +1862,7 @@ void kv_dpm_reset_asic(struct radeon_device *rdev) { struct kv_power_info *pi = kv_get_pi(rdev); - if (rdev->family == CHIP_KABINI) { + if (rdev->family == CHIP_KABINI || rdev->family == CHIP_MULLINS) { kv_force_lowest_valid(rdev); kv_init_graphics_levels(rdev); kv_program_bootup_state(rdev); @@ -1941,7 +1941,7 @@ static int kv_force_dpm_highest(struct radeon_device *rdev) break; } - if (rdev->family == CHIP_KABINI) + if (rdev->family == CHIP_KABINI || rdev->family == CHIP_MULLINS) return kv_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_DPM_ForceState, i); else return kv_set_enabled_level(rdev, i); @@ -1961,7 +1961,7 @@ static int kv_force_dpm_lowest(struct radeon_device *rdev) break; } - if (rdev->family == CHIP_KABINI) + if (rdev->family == CHIP_KABINI || rdev->family == CHIP_MULLINS) return kv_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_DPM_ForceState, i); else return kv_set_enabled_level(rdev, i); @@ -2118,7 +2118,7 @@ static void kv_apply_state_adjust_rules(struct radeon_device *rdev, else pi->battery_state = false; - if (rdev->family == CHIP_KABINI) { + if (rdev->family == CHIP_KABINI || rdev->family == CHIP_MULLINS) { ps->dpm0_pg_nb_ps_lo = 0x1; ps->dpm0_pg_nb_ps_hi = 0x0; ps->dpmx_nb_ps_lo = 0x1; @@ -2179,7 +2179,7 @@ static int kv_calculate_nbps_level_settings(struct radeon_device *rdev) if (pi->lowest_valid > pi->highest_valid) return -EINVAL; - if (rdev->family == CHIP_KABINI) { + if (rdev->family == CHIP_KABINI || rdev->family == CHIP_MULLINS) { for (i = pi->lowest_valid; i <= pi->highest_valid; i++) { pi->graphics_level[i].GnbSlow = 1; pi->graphics_level[i].ForceNbPs1 = 0; @@ -2324,7 +2324,7 @@ static void kv_program_nbps_index_settings(struct radeon_device *rdev, struct kv_power_info *pi = kv_get_pi(rdev); u32 nbdpmconfig1; - if (rdev->family == CHIP_KABINI) + if (rdev->family == CHIP_KABINI || rdev->family == CHIP_MULLINS) return; if (pi->sys_info.nb_dpm_enable) { @@ -2631,7 +2631,7 @@ int kv_dpm_init(struct radeon_device *rdev) pi->sram_end = SMC_RAM_END; - if (rdev->family == CHIP_KABINI) + if (rdev->family == CHIP_KABINI || rdev->family == CHIP_MULLINS) pi->high_voltage_t = 4001; pi->enable_nb_dpm = true; diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index 6fac8efe8340..f30b8426eee2 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -1300,6 +1300,7 @@ int radeon_pm_init(struct radeon_device *rdev) case CHIP_KABINI: case CHIP_KAVERI: case CHIP_HAWAII: + case CHIP_MULLINS: /* DPM requires the RLC, RV770+ dGPU requires SMC */ if (!rdev->rlc_fw) rdev->pm.pm_method = PM_METHOD_PROFILE; -- cgit v1.2.3 From 47f5c7461660b6b550018b83b5b98e330b2d0f7e Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 30 Apr 2014 18:40:52 -0400 Subject: drm/radeon: dpm updates for KV/KB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Use vddc/sclk dep table for voltage if available - Fix UVD DPM setup - Patch voltage tables properly for non-UVD blocks - Fix DPM + UVD/VCE on Mullins Signed-off-by: Alex Deucher Signed-off-by: Christian König --- drivers/gpu/drm/radeon/kv_dpm.c | 117 +++++++++++++++++++++++++++++++++------- 1 file changed, 97 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/radeon/kv_dpm.c b/drivers/gpu/drm/radeon/kv_dpm.c index 6666370e58fa..3f6e817d97ee 100644 --- a/drivers/gpu/drm/radeon/kv_dpm.c +++ b/drivers/gpu/drm/radeon/kv_dpm.c @@ -546,6 +546,52 @@ static int kv_set_divider_value(struct radeon_device *rdev, return 0; } +static u32 kv_convert_vid2_to_vid7(struct radeon_device *rdev, + struct sumo_vid_mapping_table *vid_mapping_table, + u32 vid_2bit) +{ + struct radeon_clock_voltage_dependency_table *vddc_sclk_table = + &rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk; + u32 i; + + if (vddc_sclk_table && vddc_sclk_table->count) { + if (vid_2bit < vddc_sclk_table->count) + return vddc_sclk_table->entries[vid_2bit].v; + else + return vddc_sclk_table->entries[vddc_sclk_table->count - 1].v; + } else { + for (i = 0; i < vid_mapping_table->num_entries; i++) { + if (vid_mapping_table->entries[i].vid_2bit == vid_2bit) + return vid_mapping_table->entries[i].vid_7bit; + } + return vid_mapping_table->entries[vid_mapping_table->num_entries - 1].vid_7bit; + } +} + +static u32 kv_convert_vid7_to_vid2(struct radeon_device *rdev, + struct sumo_vid_mapping_table *vid_mapping_table, + u32 vid_7bit) +{ + struct radeon_clock_voltage_dependency_table *vddc_sclk_table = + &rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk; + u32 i; + + if (vddc_sclk_table && vddc_sclk_table->count) { + for (i = 0; i < vddc_sclk_table->count; i++) { + if (vddc_sclk_table->entries[i].v == vid_7bit) + return i; + } + return vddc_sclk_table->count - 1; + } else { + for (i = 0; i < vid_mapping_table->num_entries; i++) { + if (vid_mapping_table->entries[i].vid_7bit == vid_7bit) + return vid_mapping_table->entries[i].vid_2bit; + } + + return vid_mapping_table->entries[vid_mapping_table->num_entries - 1].vid_2bit; + } +} + static u16 kv_convert_8bit_index_to_voltage(struct radeon_device *rdev, u16 voltage) { @@ -556,9 +602,9 @@ static u16 kv_convert_2bit_index_to_voltage(struct radeon_device *rdev, u32 vid_2bit) { struct kv_power_info *pi = kv_get_pi(rdev); - u32 vid_8bit = sumo_convert_vid2_to_vid7(rdev, - &pi->sys_info.vid_mapping_table, - vid_2bit); + u32 vid_8bit = kv_convert_vid2_to_vid7(rdev, + &pi->sys_info.vid_mapping_table, + vid_2bit); return kv_convert_8bit_index_to_voltage(rdev, (u16)vid_8bit); } @@ -1362,13 +1408,20 @@ static int kv_update_uvd_dpm(struct radeon_device *rdev, bool gate) struct radeon_uvd_clock_voltage_dependency_table *table = &rdev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table; int ret; + u32 mask; if (!gate) { - if (!pi->caps_uvd_dpm || table->count || pi->caps_stable_p_state) + if (table->count) pi->uvd_boot_level = table->count - 1; else pi->uvd_boot_level = 0; + if (!pi->caps_uvd_dpm || pi->caps_stable_p_state) { + mask = 1 << pi->uvd_boot_level; + } else { + mask = 0x1f; + } + ret = kv_copy_bytes_to_smc(rdev, pi->dpm_table_start + offsetof(SMU7_Fusion_DpmTable, UvdBootLevel), @@ -1377,11 +1430,9 @@ static int kv_update_uvd_dpm(struct radeon_device *rdev, bool gate) if (ret) return ret; - if (!pi->caps_uvd_dpm || - pi->caps_stable_p_state) - kv_send_msg_to_smc_with_parameter(rdev, - PPSMC_MSG_UVDDPM_SetEnabledMask, - (1 << pi->uvd_boot_level)); + kv_send_msg_to_smc_with_parameter(rdev, + PPSMC_MSG_UVDDPM_SetEnabledMask, + mask); } return kv_enable_uvd_dpm(rdev, !gate); @@ -1812,6 +1863,8 @@ int kv_dpm_set_power_state(struct radeon_device *rdev) return ret; } kv_update_sclk_t(rdev); + if (rdev->family == CHIP_MULLINS) + kv_enable_nb_dpm(rdev); } } else { if (pi->enable_dpm) { @@ -1901,14 +1954,41 @@ static void kv_construct_max_power_limits_table(struct radeon_device *rdev, static void kv_patch_voltage_values(struct radeon_device *rdev) { int i; - struct radeon_uvd_clock_voltage_dependency_table *table = + struct radeon_uvd_clock_voltage_dependency_table *uvd_table = &rdev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table; + struct radeon_vce_clock_voltage_dependency_table *vce_table = + &rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table; + struct radeon_clock_voltage_dependency_table *samu_table = + &rdev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table; + struct radeon_clock_voltage_dependency_table *acp_table = + &rdev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table; + + if (uvd_table->count) { + for (i = 0; i < uvd_table->count; i++) + uvd_table->entries[i].v = + kv_convert_8bit_index_to_voltage(rdev, + uvd_table->entries[i].v); + } + + if (vce_table->count) { + for (i = 0; i < vce_table->count; i++) + vce_table->entries[i].v = + kv_convert_8bit_index_to_voltage(rdev, + vce_table->entries[i].v); + } - if (table->count) { - for (i = 0; i < table->count; i++) - table->entries[i].v = + if (samu_table->count) { + for (i = 0; i < samu_table->count; i++) + samu_table->entries[i].v = kv_convert_8bit_index_to_voltage(rdev, - table->entries[i].v); + samu_table->entries[i].v); + } + + if (acp_table->count) { + for (i = 0; i < acp_table->count; i++) + acp_table->entries[i].v = + kv_convert_8bit_index_to_voltage(rdev, + acp_table->entries[i].v); } } @@ -2253,9 +2333,9 @@ static void kv_init_graphics_levels(struct radeon_device *rdev) break; kv_set_divider_value(rdev, i, table->entries[i].clk); - vid_2bit = sumo_convert_vid7_to_vid2(rdev, - &pi->sys_info.vid_mapping_table, - table->entries[i].v); + vid_2bit = kv_convert_vid7_to_vid2(rdev, + &pi->sys_info.vid_mapping_table, + table->entries[i].v); kv_set_vid(rdev, i, vid_2bit); kv_set_at(rdev, i, pi->at[i]); kv_dpm_power_level_enabled_for_throttle(rdev, i, true); @@ -2631,9 +2711,6 @@ int kv_dpm_init(struct radeon_device *rdev) pi->sram_end = SMC_RAM_END; - if (rdev->family == CHIP_KABINI || rdev->family == CHIP_MULLINS) - pi->high_voltage_t = 4001; - pi->enable_nb_dpm = true; pi->caps_power_containment = true; -- cgit v1.2.3 From b214f2a4ba415dcad40fcc7c195d0a402f8211de Mon Sep 17 00:00:00 2001 From: Samuel Li Date: Wed, 30 Apr 2014 18:40:53 -0400 Subject: drm/radeon: modesetting updates for Mullins. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Uses the same code as Kabini. Signed-off-by: Samuel Li Signed-off-by: Alex Deucher Signed-off-by: Christian König --- drivers/gpu/drm/radeon/atombios_crtc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index b7983aaee445..c31c12b4e666 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -1736,8 +1736,9 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc) } /* otherwise, pick one of the plls */ if ((rdev->family == CHIP_KAVERI) || - (rdev->family == CHIP_KABINI)) { - /* KB/KV has PPLL1 and PPLL2 */ + (rdev->family == CHIP_KABINI) || + (rdev->family == CHIP_MULLINS)) { + /* KB/KV/ML has PPLL1 and PPLL2 */ pll_in_use = radeon_get_pll_use_mask(crtc); if (!(pll_in_use & (1 << ATOM_PPLL2))) return ATOM_PPLL2; -- cgit v1.2.3 From 428beddd0236842c6e8f4aabe9597763c2ae9a3b Mon Sep 17 00:00:00 2001 From: Leo Liu Date: Wed, 30 Apr 2014 18:40:54 -0400 Subject: drm/radeon: add Mullins VCE support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit VCE 2.0 just like the other CIK parts. Signed-off-by: Leo Liu Signed-off-by: Alex Deucher Signed-off-by: Christian König --- drivers/gpu/drm/radeon/radeon_vce.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/radeon/radeon_vce.c b/drivers/gpu/drm/radeon/radeon_vce.c index ced53dd03e7c..f73324c81491 100644 --- a/drivers/gpu/drm/radeon/radeon_vce.c +++ b/drivers/gpu/drm/radeon/radeon_vce.c @@ -66,6 +66,7 @@ int radeon_vce_init(struct radeon_device *rdev) case CHIP_BONAIRE: case CHIP_KAVERI: case CHIP_KABINI: + case CHIP_MULLINS: fw_name = FIRMWARE_BONAIRE; break; -- cgit v1.2.3 From 573471c1374e6a54a78efc1d1c047733981c99e2 Mon Sep 17 00:00:00 2001 From: Samuel Li Date: Wed, 30 Apr 2014 18:40:55 -0400 Subject: drm/radeon: add pci ids for Mullins MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Samuel Li Signed-off-by: Alex Deucher Signed-off-by: Christian König --- include/drm/drm_pciids.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h index 49376aec2fbb..6dfd64b3a604 100644 --- a/include/drm/drm_pciids.h +++ b/include/drm/drm_pciids.h @@ -637,6 +637,22 @@ {0x1002, 0x983d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x983e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x983f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x9850, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x9851, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x9852, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x9853, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x9854, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x9855, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x9856, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x9857, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x9858, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x9859, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x985A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x985B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x985C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x985D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x985E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x985F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x9900, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x9901, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x9903, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ -- cgit v1.2.3 From 5694c93e6c4954fa9424c215f75eeb919bddad64 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Fri, 18 Apr 2014 14:43:56 -0400 Subject: NFSd: Move default initialisers from create_client() to alloc_client() Aside from making it clearer what is non-trivial in create_client(), it also fixes a bug whereby we can call free_client() before idr_init() has been called. Signed-off-by: Trond Myklebust Cc: stable@vger.kernel.org Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4state.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 3ba65979a3cd..230d21cb1717 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -1078,6 +1078,18 @@ static struct nfs4_client *alloc_client(struct xdr_netobj name) return NULL; } clp->cl_name.len = name.len; + INIT_LIST_HEAD(&clp->cl_sessions); + idr_init(&clp->cl_stateids); + atomic_set(&clp->cl_refcount, 0); + clp->cl_cb_state = NFSD4_CB_UNKNOWN; + INIT_LIST_HEAD(&clp->cl_idhash); + INIT_LIST_HEAD(&clp->cl_openowners); + INIT_LIST_HEAD(&clp->cl_delegations); + INIT_LIST_HEAD(&clp->cl_lru); + INIT_LIST_HEAD(&clp->cl_callbacks); + INIT_LIST_HEAD(&clp->cl_revoked); + spin_lock_init(&clp->cl_lock); + rpc_init_wait_queue(&clp->cl_cb_waitq, "Backchannel slot table"); return clp; } @@ -1347,7 +1359,6 @@ static struct nfs4_client *create_client(struct xdr_netobj name, if (clp == NULL) return NULL; - INIT_LIST_HEAD(&clp->cl_sessions); ret = copy_cred(&clp->cl_cred, &rqstp->rq_cred); if (ret) { spin_lock(&nn->client_lock); @@ -1355,20 +1366,9 @@ static struct nfs4_client *create_client(struct xdr_netobj name, spin_unlock(&nn->client_lock); return NULL; } - idr_init(&clp->cl_stateids); - atomic_set(&clp->cl_refcount, 0); - clp->cl_cb_state = NFSD4_CB_UNKNOWN; - INIT_LIST_HEAD(&clp->cl_idhash); - INIT_LIST_HEAD(&clp->cl_openowners); - INIT_LIST_HEAD(&clp->cl_delegations); - INIT_LIST_HEAD(&clp->cl_lru); - INIT_LIST_HEAD(&clp->cl_callbacks); - INIT_LIST_HEAD(&clp->cl_revoked); - spin_lock_init(&clp->cl_lock); nfsd4_init_callback(&clp->cl_cb_null); clp->cl_time = get_seconds(); clear_bit(0, &clp->cl_cb_slot_busy); - rpc_init_wait_queue(&clp->cl_cb_waitq, "Backchannel slot table"); copy_verf(clp, verf); rpc_copy_addr((struct sockaddr *) &clp->cl_addr, sa); gen_confirm(clp); -- cgit v1.2.3 From 4cb57e3032d4e4bf5e97780e9907da7282b02b0c Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Fri, 18 Apr 2014 14:43:57 -0400 Subject: NFSd: call rpc_destroy_wait_queue() from free_client() Mainly to ensure that we don't leave any hanging timers. Signed-off-by: Trond Myklebust Cc: stable@vger.kernel.org Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4state.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 230d21cb1717..32b699bebb9c 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -1107,6 +1107,7 @@ free_client(struct nfs4_client *clp) WARN_ON_ONCE(atomic_read(&ses->se_ref)); free_session(ses); } + rpc_destroy_wait_queue(&clp->cl_cb_waitq); free_svc_cred(&clp->cl_cred); kfree(clp->cl_name.data); idr_destroy(&clp->cl_stateids); -- cgit v1.2.3 From 0fed2bcf17d2a049c079ffd2b7bc4caca4b7f906 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sun, 13 Apr 2014 22:55:27 +0300 Subject: iwlwifi: mvm: BT Coex - fix validity flags during init The commit below introduced a bug in the validity bits in init. Due to that, all the Coex mechanism stopped sending kills to the BT side. Fix that. Fixes: b9fae2d54c9f ("iwlwifi: mvm: BT Coex add support for Co-running block") Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/coex.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/coex.c b/drivers/net/wireless/iwlwifi/mvm/coex.c index fa858d548d13..0489314425cb 100644 --- a/drivers/net/wireless/iwlwifi/mvm/coex.c +++ b/drivers/net/wireless/iwlwifi/mvm/coex.c @@ -611,14 +611,14 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm) bt_cmd->flags |= cpu_to_le32(BT_COEX_SYNC2SCO); if (IWL_MVM_BT_COEX_CORUNNING) { - bt_cmd->valid_bit_msk = cpu_to_le32(BT_VALID_CORUN_LUT_20 | - BT_VALID_CORUN_LUT_40); + bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_CORUN_LUT_20 | + BT_VALID_CORUN_LUT_40); bt_cmd->flags |= cpu_to_le32(BT_COEX_CORUNNING); } if (IWL_MVM_BT_COEX_MPLUT) { bt_cmd->flags |= cpu_to_le32(BT_COEX_MPLUT); - bt_cmd->valid_bit_msk = cpu_to_le32(BT_VALID_MULTI_PRIO_LUT); + bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_MULTI_PRIO_LUT); } if (mvm->cfg->bt_shared_single_ant) -- cgit v1.2.3 From 8e96440e8d42da0dab02cae125ea59e2b64c77fe Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Tue, 6 May 2014 20:35:10 +0300 Subject: iwlwifi: mvm: rs - s/CPTCFG/CONFIG My bad - I forgot to update this when sending the patch upstream. Fixes: 87d5e4155c00 ("iwlwifi: mvm: rs: reinit rs if no tx for a long time") Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/rs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 9f52c5b3f0ec..e1c838899363 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c @@ -1010,7 +1010,7 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband, return; } -#ifdef CPTCFG_MAC80211_DEBUGFS +#ifdef CONFIG_MAC80211_DEBUGFS /* Disable last tx check if we are debugging with fixed rate */ if (lq_sta->dbg_fixed_rate) { IWL_DEBUG_RATE(mvm, "Fixed rate. avoid rate scaling\n"); -- cgit v1.2.3 From bd5e4744a6ca64299b57a2682c720d00a475a734 Mon Sep 17 00:00:00 2001 From: David Spinadel Date: Thu, 24 Apr 2014 13:15:29 +0300 Subject: iwlwifi: mvm: do no sched scan while associated Currently the FW doesn't support sched scan while associated, Prevent it. Signed-off-by: David Spinadel Reviewed-by: Johannes Berg Reviewed-by: Luciano Coelho Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/mac80211.c | 5 +++++ drivers/net/wireless/iwlwifi/mvm/mvm.h | 3 +++ drivers/net/wireless/iwlwifi/mvm/utils.c | 19 +++++++++++++++++++ 3 files changed, 27 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index f0cebf12c7b8..593f723a74c4 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -1807,6 +1807,11 @@ static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw, mutex_lock(&mvm->mutex); + if (iwl_mvm_is_associated(mvm)) { + ret = -EBUSY; + goto out; + } + switch (mvm->scan_status) { case IWL_MVM_SCAN_OS: IWL_DEBUG_SCAN(mvm, "Stopping previous scan for sched_scan\n"); diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index d564233a65da..84c75a1b267e 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h @@ -1003,6 +1003,9 @@ static inline bool iwl_mvm_vif_low_latency(struct iwl_mvm_vif *mvmvif) return mvmvif->low_latency; } +/* Assoc status */ +bool iwl_mvm_is_associated(struct iwl_mvm *mvm); + /* Thermal management and CT-kill */ void iwl_mvm_tt_tx_backoff(struct iwl_mvm *mvm, u32 backoff); void iwl_mvm_tt_handler(struct iwl_mvm *mvm); diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c index d619851745a1..6fdbef9696d8 100644 --- a/drivers/net/wireless/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/iwlwifi/mvm/utils.c @@ -644,3 +644,22 @@ bool iwl_mvm_low_latency(struct iwl_mvm *mvm) return result; } + +static void iwl_mvm_assoc_iter(void *_data, u8 *mac, struct ieee80211_vif *vif) +{ + bool *assoc = _data; + + if (vif->bss_conf.assoc) + *assoc = true; +} + +bool iwl_mvm_is_associated(struct iwl_mvm *mvm) +{ + bool assoc = false; + + ieee80211_iterate_active_interfaces_atomic( + mvm->hw, IEEE80211_IFACE_ITER_NORMAL, + iwl_mvm_assoc_iter, &assoc); + + return assoc; +} -- cgit v1.2.3 From 4c88d7f9b0d5fb0588c3386be62115cc2eaa8f9f Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 23 Apr 2014 14:49:17 +0200 Subject: genirq: Provide irq_force_affinity fallback for non-SMP Patch 01f8fa4f01d "genirq: Allow forcing cpu affinity of interrupts" added an irq_force_affinity() function, and 30ccf03b4a6 "clocksource: Exynos_mct: Use irq_force_affinity() in cpu bringup" subsequently uses it. However, the driver can be used with CONFIG_SMP disabled, but the function declaration is only available for CONFIG_SMP, leading to this build error: drivers/clocksource/exynos_mct.c:431:3: error: implicit declaration of function 'irq_force_affinity' [-Werror=implicit-function-declaration] irq_force_affinity(mct_irqs[MCT_L0_IRQ + cpu], cpumask_of(cpu)); This patch introduces a dummy helper function for the non-SMP case that always returns success, to get rid of the build error. Since the patches causing the problem are marked for stable backports, this one should be as well. Signed-off-by: Arnd Bergmann Cc: Krzysztof Kozlowski Acked-by: Kukjin Kim Cc: stable@vger.kernel.org Link: http://lkml.kernel.org/r/5619084.0zmrrIUZLV@wuerfel Signed-off-by: Thomas Gleixner --- include/linux/interrupt.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index 97ac926c78a7..051c85032f48 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h @@ -272,6 +272,11 @@ static inline int irq_set_affinity(unsigned int irq, const struct cpumask *m) return -EINVAL; } +static inline int irq_force_affinity(unsigned int irq, const struct cpumask *cpumask) +{ + return 0; +} + static inline int irq_can_set_affinity(unsigned int irq) { return 0; -- cgit v1.2.3 From e5c460f46ae7ee94831cb55cb980f942aa9e5a85 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 6 May 2014 21:27:37 -0700 Subject: sparc64: Don't bark so loudly about 32-bit tasks generating 64-bit fault addresses. This was found using Dave Jone's trinity tool. When a user process which is 32-bit performs a load or a store, the cpu chops off the top 32-bits of the effective address before translating it. This is because we run 32-bit tasks with the PSTATE_AM (address masking) bit set. We can't run the kernel with that bit set, so when the kernel accesses userspace no address masking occurs. Since a 32-bit process will have no mappings in that region we will properly fault, so we don't try to handle this using access_ok(), which can safely just be a NOP on sparc64. Real faults from 32-bit processes should never generate such addresses so a bug check was added long ago, and it barks in the logs if this happens. But it also barks when a kernel user access causes this condition, and that _can_ happen. For example, if a pointer passed into a system call is "0xfffffffc" and the kernel access 4 bytes offset from that pointer. Just handle such faults normally via the exception entries. Signed-off-by: David S. Miller --- arch/sparc/mm/fault_64.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/arch/sparc/mm/fault_64.c b/arch/sparc/mm/fault_64.c index a8ff0d1a3b69..4ced3fc66130 100644 --- a/arch/sparc/mm/fault_64.c +++ b/arch/sparc/mm/fault_64.c @@ -281,18 +281,6 @@ static void noinline __kprobes bogus_32bit_fault_tpc(struct pt_regs *regs) show_regs(regs); } -static void noinline __kprobes bogus_32bit_fault_address(struct pt_regs *regs, - unsigned long addr) -{ - static int times; - - if (times++ < 10) - printk(KERN_ERR "FAULT[%s:%d]: 32-bit process " - "reports 64-bit fault address [%lx]\n", - current->comm, current->pid, addr); - show_regs(regs); -} - asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) { enum ctx_state prev_state = exception_enter(); @@ -322,10 +310,8 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) goto intr_or_no_mm; } } - if (unlikely((address >> 32) != 0)) { - bogus_32bit_fault_address(regs, address); + if (unlikely((address >> 32) != 0)) goto intr_or_no_mm; - } } if (regs->tstate & TSTATE_PRIV) { -- cgit v1.2.3 From 2b39aab18a84b2fa348d42d894ef986b290d67a0 Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Fri, 2 May 2014 16:56:28 +0100 Subject: ASoC: Intel: Fix block offset calculations. Block offset calculations are done in the contiguous allocator so are not required here. Signed-off-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/intel/sst-firmware.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/sound/soc/intel/sst-firmware.c b/sound/soc/intel/sst-firmware.c index c38cfda8003c..928f228c38e7 100644 --- a/sound/soc/intel/sst-firmware.c +++ b/sound/soc/intel/sst-firmware.c @@ -244,8 +244,7 @@ static int block_alloc(struct sst_module *module, /* do we span > 1 blocks */ if (data->size > block->size) { ret = block_alloc_contiguous(module, data, - block->offset + block->size, - data->size - block->size); + block->offset, data->size); if (ret == 0) return ret; } @@ -341,7 +340,7 @@ static int block_alloc_fixed(struct sst_module *module, err = block_alloc_contiguous(module, data, block->offset + block->size, - data->size - block->size + data->offset - block->offset); + data->size - block->size); if (err < 0) return -ENOMEM; @@ -368,8 +367,7 @@ static int block_alloc_fixed(struct sst_module *module, if (data->offset >= block->offset && data->offset < block_end) { err = block_alloc_contiguous(module, data, - block->offset + block->size, - data->size - block->size); + block->offset, data->size); if (err < 0) return -ENOMEM; -- cgit v1.2.3 From aadca6fa4068ad1f92c492bc8507b7ed350825a2 Mon Sep 17 00:00:00 2001 From: Christian Gmeiner Date: Wed, 7 May 2014 09:01:54 +0200 Subject: x86/reboot: Add reboot quirk for Certec BPC600 Certec BPC600 needs reboot=pci to actually reboot. Signed-off-by: Christian Gmeiner Cc: Matthew Garrett Cc: Li Aubrey Cc: Andrew Morton Cc: Dave Jones Cc: Fenghua Yu Cc: Linus Torvalds Link: http://lkml.kernel.org/r/1399446114-2147-1-git-send-email-christian.gmeiner@gmail.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/reboot.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index 3399d3a99730..52b1157c53eb 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -191,6 +191,16 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = { }, }, + /* Certec */ + { /* Handle problems with rebooting on Certec BPC600 */ + .callback = set_pci_reboot, + .ident = "Certec BPC600", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Certec"), + DMI_MATCH(DMI_PRODUCT_NAME, "BPC600"), + }, + }, + /* Dell */ { /* Handle problems with rebooting on Dell DXP061 */ .callback = set_bios_reboot, -- cgit v1.2.3 From 2d513868e2a33e1d5315490ef4c861ee65babd65 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 2 May 2014 23:26:24 +0200 Subject: sched: Sanitize irq accounting madness Russell reported, that irqtime_account_idle_ticks() takes ages due to: for (i = 0; i < ticks; i++) irqtime_account_process_tick(current, 0, rq); It's sad, that this code was written way _AFTER_ the NOHZ idle functionality was available. I charge myself guitly for not paying attention when that crap got merged with commit abb74cefa ("sched: Export ns irqtimes through /proc/stat") So instead of looping nr_ticks times just apply the whole thing at once. As a side note: The whole cputime_t vs. u64 business in that context wants to be cleaned up as well. There is no point in having all these back and forth conversions. Lets standardise on u64 nsec for all kernel internal accounting and be done with it. Everything else does not make sense at all for fine grained accounting. Frederic, can you please take care of that? Reported-by: Russell King Signed-off-by: Thomas Gleixner Reviewed-by: Paul E. McKenney Signed-off-by: Peter Zijlstra Cc: Venkatesh Pallipadi Cc: Shaun Ruffell Cc: stable@vger.kernel.org Link: http://lkml.kernel.org/r/alpine.DEB.2.02.1405022307000.6261@ionos.tec.linutronix.de Signed-off-by: Ingo Molnar --- kernel/sched/cputime.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/kernel/sched/cputime.c b/kernel/sched/cputime.c index a95097cb4591..72fdf06ef865 100644 --- a/kernel/sched/cputime.c +++ b/kernel/sched/cputime.c @@ -332,50 +332,50 @@ out: * softirq as those do not count in task exec_runtime any more. */ static void irqtime_account_process_tick(struct task_struct *p, int user_tick, - struct rq *rq) + struct rq *rq, int ticks) { - cputime_t one_jiffy_scaled = cputime_to_scaled(cputime_one_jiffy); + cputime_t scaled = cputime_to_scaled(cputime_one_jiffy); + u64 cputime = (__force u64) cputime_one_jiffy; u64 *cpustat = kcpustat_this_cpu->cpustat; if (steal_account_process_tick()) return; + cputime *= ticks; + scaled *= ticks; + if (irqtime_account_hi_update()) { - cpustat[CPUTIME_IRQ] += (__force u64) cputime_one_jiffy; + cpustat[CPUTIME_IRQ] += cputime; } else if (irqtime_account_si_update()) { - cpustat[CPUTIME_SOFTIRQ] += (__force u64) cputime_one_jiffy; + cpustat[CPUTIME_SOFTIRQ] += cputime; } else if (this_cpu_ksoftirqd() == p) { /* * ksoftirqd time do not get accounted in cpu_softirq_time. * So, we have to handle it separately here. * Also, p->stime needs to be updated for ksoftirqd. */ - __account_system_time(p, cputime_one_jiffy, one_jiffy_scaled, - CPUTIME_SOFTIRQ); + __account_system_time(p, cputime, scaled, CPUTIME_SOFTIRQ); } else if (user_tick) { - account_user_time(p, cputime_one_jiffy, one_jiffy_scaled); + account_user_time(p, cputime, scaled); } else if (p == rq->idle) { - account_idle_time(cputime_one_jiffy); + account_idle_time(cputime); } else if (p->flags & PF_VCPU) { /* System time or guest time */ - account_guest_time(p, cputime_one_jiffy, one_jiffy_scaled); + account_guest_time(p, cputime, scaled); } else { - __account_system_time(p, cputime_one_jiffy, one_jiffy_scaled, - CPUTIME_SYSTEM); + __account_system_time(p, cputime, scaled, CPUTIME_SYSTEM); } } static void irqtime_account_idle_ticks(int ticks) { - int i; struct rq *rq = this_rq(); - for (i = 0; i < ticks; i++) - irqtime_account_process_tick(current, 0, rq); + irqtime_account_process_tick(current, 0, rq, ticks); } #else /* CONFIG_IRQ_TIME_ACCOUNTING */ static inline void irqtime_account_idle_ticks(int ticks) {} static inline void irqtime_account_process_tick(struct task_struct *p, int user_tick, - struct rq *rq) {} + struct rq *rq, int nr_ticks) {} #endif /* CONFIG_IRQ_TIME_ACCOUNTING */ /* @@ -464,7 +464,7 @@ void account_process_tick(struct task_struct *p, int user_tick) return; if (sched_clock_irqtime) { - irqtime_account_process_tick(p, user_tick, rq); + irqtime_account_process_tick(p, user_tick, rq, 1); return; } -- cgit v1.2.3 From 5bfd126e80dca70431aef8fdbc1cf14535f3c338 Mon Sep 17 00:00:00 2001 From: Juri Lelli Date: Tue, 15 Apr 2014 13:49:04 +0200 Subject: sched/deadline: Fix sched_yield() behavior yield_task_dl() is broken: o it forces current to be throttled setting its runtime to zero; o it sets current's dl_se->dl_new to one, expecting that dl_task_timer() will queue it back with proper parameters at replenish time. Unfortunately, dl_task_timer() has this check at the very beginning: if (!dl_task(p) || dl_se->dl_new) goto unlock; So, it just bails out and the task is never replenished. It actually yielded forever. To fix this, introduce a new flag indicating that the task properly yielded the CPU before its current runtime expired. While this is a little overdoing at the moment, the flag would be useful in the future to discriminate between "good" jobs (of which remaining runtime could be reclaimed, i.e. recycled) and "bad" jobs (for which dl_throttled task has been set) that needed to be stopped. Reported-by: yjay.kim Signed-off-by: Juri Lelli Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/20140429103953.e68eba1b2ac3309214e3dc5a@gmail.com Signed-off-by: Ingo Molnar --- include/linux/sched.h | 7 +++++-- kernel/sched/core.c | 1 + kernel/sched/deadline.c | 5 +++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index 25f54c79f757..2a4298fb0d85 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1153,9 +1153,12 @@ struct sched_dl_entity { * * @dl_boosted tells if we are boosted due to DI. If so we are * outside bandwidth enforcement mechanism (but only until we - * exit the critical section). + * exit the critical section); + * + * @dl_yielded tells if task gave up the cpu before consuming + * all its available runtime during the last job. */ - int dl_throttled, dl_new, dl_boosted; + int dl_throttled, dl_new, dl_boosted, dl_yielded; /* * Bandwidth enforcement timer. Each -deadline task has its diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 9fe2190005cb..e62c65a12d5b 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -3124,6 +3124,7 @@ __setparam_dl(struct task_struct *p, const struct sched_attr *attr) dl_se->dl_bw = to_ratio(dl_se->dl_period, dl_se->dl_runtime); dl_se->dl_throttled = 0; dl_se->dl_new = 1; + dl_se->dl_yielded = 0; } static void __setscheduler_params(struct task_struct *p, diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c index b08095786cb8..800e99b99075 100644 --- a/kernel/sched/deadline.c +++ b/kernel/sched/deadline.c @@ -528,6 +528,7 @@ static enum hrtimer_restart dl_task_timer(struct hrtimer *timer) sched_clock_tick(); update_rq_clock(rq); dl_se->dl_throttled = 0; + dl_se->dl_yielded = 0; if (p->on_rq) { enqueue_task_dl(rq, p, ENQUEUE_REPLENISH); if (task_has_dl_policy(rq->curr)) @@ -893,10 +894,10 @@ static void yield_task_dl(struct rq *rq) * We make the task go to sleep until its current deadline by * forcing its runtime to zero. This way, update_curr_dl() stops * it and the bandwidth timer will wake it up and will give it - * new scheduling parameters (thanks to dl_new=1). + * new scheduling parameters (thanks to dl_yielded=1). */ if (p->dl.runtime > 0) { - rq->curr->dl.dl_new = 1; + rq->curr->dl.dl_yielded = 1; p->dl.runtime = 0; } update_curr_dl(rq); -- cgit v1.2.3 From 6a7cd273dc4bc3246f37ebe874754a54ccb29141 Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Thu, 17 Apr 2014 10:05:02 +0800 Subject: sched/deadline: Fix memory leak Free cpudl->free_cpus allocated in cpudl_init(). Signed-off-by: Li Zefan Acked-by: Juri Lelli Signed-off-by: Peter Zijlstra Cc: # 3.14+ Link: http://lkml.kernel.org/r/534F36CE.2000409@huawei.com Signed-off-by: Ingo Molnar --- kernel/sched/cpudeadline.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/kernel/sched/cpudeadline.c b/kernel/sched/cpudeadline.c index 5b9bb42b2d47..ab001b5d5048 100644 --- a/kernel/sched/cpudeadline.c +++ b/kernel/sched/cpudeadline.c @@ -210,7 +210,5 @@ int cpudl_init(struct cpudl *cp) */ void cpudl_cleanup(struct cpudl *cp) { - /* - * nothing to do for the moment - */ + free_cpumask_var(cp->free_cpus); } -- cgit v1.2.3 From 6227cb00cc120f9a43ce8313bb0475ddabcb7d01 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Red Hat)" Date: Sun, 13 Apr 2014 09:34:53 -0400 Subject: sched: Use CPUPRI_NR_PRIORITIES instead of MAX_RT_PRIO in cpupri check The check at the beginning of cpupri_find() makes sure that the task_pri variable does not exceed the cp->pri_to_cpu array length. But that length is CPUPRI_NR_PRIORITIES not MAX_RT_PRIO, where it will miss the last two priorities in that array. As task_pri is computed from convert_prio() which should never be bigger than CPUPRI_NR_PRIORITIES, if the check should cause a panic if it is hit. Reported-by: Mike Galbraith Signed-off-by: Steven Rostedt Signed-off-by: Peter Zijlstra Cc: stable@vger.kernel.org Link: http://lkml.kernel.org/r/1397015410.5212.13.camel@marge.simpson.net Signed-off-by: Ingo Molnar --- kernel/sched/cpupri.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/kernel/sched/cpupri.c b/kernel/sched/cpupri.c index 8b836b376d91..3031bac8aa3e 100644 --- a/kernel/sched/cpupri.c +++ b/kernel/sched/cpupri.c @@ -70,8 +70,7 @@ int cpupri_find(struct cpupri *cp, struct task_struct *p, int idx = 0; int task_pri = convert_prio(p->prio); - if (task_pri >= MAX_RT_PRIO) - return 0; + BUG_ON(task_pri >= CPUPRI_NR_PRIORITIES); for (idx = 0; idx < task_pri; idx++) { struct cpupri_vec *vec = &cp->pri_to_cpu[idx]; -- cgit v1.2.3 From 6ccdc84b81a0a6c09a7f0427761d2f8cecfc2218 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Thu, 24 Apr 2014 12:00:47 +0200 Subject: sched: Skip double execution of pick_next_task_fair() Tim wrote: "The current code will call pick_next_task_fair a second time in the slow path if we did not pull any task in our first try. This is really unnecessary as we already know no task can be pulled and it doubles the delay for the cpu to enter idle. We instrumented some network workloads and that saw that pick_next_task_fair is frequently called twice before a cpu enters idle. The call to pick_next_task_fair can add non trivial latency as it calls load_balance which runs find_busiest_group on an hierarchy of sched domains spanning the cpus for a large system. For some 4 socket systems, we saw almost 0.25 msec spent per call of pick_next_task_fair before a cpu can be idled." Optimize the second call away for the common case and document the dependency. Reported-by: Tim Chen Signed-off-by: Peter Zijlstra Cc: Linus Torvalds Cc: Len Brown Link: http://lkml.kernel.org/r/20140424100047.GP11096@twins.programming.kicks-ass.net Signed-off-by: Ingo Molnar --- kernel/sched/core.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index e62c65a12d5b..28921ec91b3d 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -2592,8 +2592,14 @@ pick_next_task(struct rq *rq, struct task_struct *prev) if (likely(prev->sched_class == class && rq->nr_running == rq->cfs.h_nr_running)) { p = fair_sched_class.pick_next_task(rq, prev); - if (likely(p && p != RETRY_TASK)) - return p; + if (unlikely(p == RETRY_TASK)) + goto again; + + /* assumes fair_sched_class->next == idle_sched_class */ + if (unlikely(!p)) + p = idle_sched_class.pick_next_task(rq, prev); + + return p; } again: -- cgit v1.2.3 From 0e5b5337f0da073e1f17aec3c322ea7826975d0d Mon Sep 17 00:00:00 2001 From: Jason Low Date: Mon, 28 Apr 2014 15:45:54 -0700 Subject: sched: Fix updating rq->max_idle_balance_cost and rq->next_balance in idle_balance() The following commit: e5fc66119ec9 ("sched: Fix race in idle_balance()") can potentially cause rq->max_idle_balance_cost to not be updated, even when load_balance(NEWLY_IDLE) is attempted and the per-sd max cost value is updated. Preeti noticed a similar issue with updating rq->next_balance. In this patch, we fix this by making sure we still check/update those values even if a task gets enqueued while browsing the domains. Signed-off-by: Jason Low Reviewed-by: Preeti U Murthy Signed-off-by: Peter Zijlstra Cc: morten.rasmussen@arm.com Cc: aswin@hp.com Cc: daniel.lezcano@linaro.org Cc: alex.shi@linaro.org Cc: efault@gmx.de Cc: vincent.guittot@linaro.org Link: http://lkml.kernel.org/r/1398725155-7591-2-git-send-email-jason.low2@hp.com Signed-off-by: Ingo Molnar --- kernel/sched/fair.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 7570dd969c28..0fdb96de81a5 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -6653,6 +6653,7 @@ static int idle_balance(struct rq *this_rq) int this_cpu = this_rq->cpu; idle_enter_fair(this_rq); + /* * We must set idle_stamp _before_ calling idle_balance(), such that we * measure the duration of idle_balance() as idle time. @@ -6705,14 +6706,16 @@ static int idle_balance(struct rq *this_rq) raw_spin_lock(&this_rq->lock); + if (curr_cost > this_rq->max_idle_balance_cost) + this_rq->max_idle_balance_cost = curr_cost; + /* - * While browsing the domains, we released the rq lock. - * A task could have be enqueued in the meantime + * While browsing the domains, we released the rq lock, a task could + * have been enqueued in the meantime. Since we're not going idle, + * pretend we pulled a task. */ - if (this_rq->cfs.h_nr_running && !pulled_task) { + if (this_rq->cfs.h_nr_running && !pulled_task) pulled_task = 1; - goto out; - } if (pulled_task || time_after(jiffies, this_rq->next_balance)) { /* @@ -6722,9 +6725,6 @@ static int idle_balance(struct rq *this_rq) this_rq->next_balance = next_balance; } - if (curr_cost > this_rq->max_idle_balance_cost) - this_rq->max_idle_balance_cost = curr_cost; - out: /* Is there a task of a high priority class? */ if (this_rq->nr_running != this_rq->cfs.h_nr_running && -- cgit v1.2.3 From 2b4cfe64dee0d84506b951d81bf55d9891744d25 Mon Sep 17 00:00:00 2001 From: Jason Low Date: Wed, 23 Apr 2014 18:30:34 -0700 Subject: sched/numa: Initialize newidle balance stats in sd_numa_init() Also initialize the per-sd variables for newidle load balancing in sd_numa_init(). Signed-off-by: Jason Low Acked-by: morten.rasmussen@arm.com Cc: daniel.lezcano@linaro.org Cc: alex.shi@linaro.org Cc: preeti@linux.vnet.ibm.com Cc: efault@gmx.de Cc: vincent.guittot@linaro.org Cc: aswin@hp.com Cc: chegu_vinod@hp.com Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1398303035-18255-3-git-send-email-jason.low2@hp.com Signed-off-by: Ingo Molnar --- kernel/sched/core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 28921ec91b3d..13584f1cccfc 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -6026,6 +6026,8 @@ sd_numa_init(struct sched_domain_topology_level *tl, int cpu) , .last_balance = jiffies, .balance_interval = sd_weight, + .max_newidle_lb_cost = 0, + .next_decay_max_lb_cost = jiffies, }; SD_INIT_NAME(sd, NUMA); sd->private = &tl->data; -- cgit v1.2.3 From 97977f7576a89cb9436c000ae703c0d515e748ac Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 7 May 2014 10:56:24 +0300 Subject: dmaengine: dw: went back to plain {request,free}_irq() calls The commit dbde5c29 "dw_dmac: use devm_* functions to simplify code" turns probe function to use devm_* helpers and simultaneously brings a regression. We need to ensure irq is disabled, followed by ensuring that don't schedule any more tasklets and then its safe to use tasklet_kill(). The free_irq() will ensure that the irq is disabled and also wait till all scheduled interrupts are executed by invoking synchronize_irq(). So we need to only do tasklet_kill() after invoking free_irq(). Signed-off-by: Andy Shevchenko Cc: stable@vger.kernel.org # v3.11+ Signed-off-by: Vinod Koul --- drivers/dma/dw/core.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c index cfdbb92aae1d..7a740769c2fa 100644 --- a/drivers/dma/dw/core.c +++ b/drivers/dma/dw/core.c @@ -1548,11 +1548,6 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata) /* Disable BLOCK interrupts as well */ channel_clear_bit(dw, MASK.BLOCK, dw->all_chan_mask); - err = devm_request_irq(chip->dev, chip->irq, dw_dma_interrupt, - IRQF_SHARED, "dw_dmac", dw); - if (err) - return err; - /* Create a pool of consistent memory blocks for hardware descriptors */ dw->desc_pool = dmam_pool_create("dw_dmac_desc_pool", chip->dev, sizeof(struct dw_desc), 4, 0); @@ -1563,6 +1558,11 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata) tasklet_init(&dw->tasklet, dw_dma_tasklet, (unsigned long)dw); + err = request_irq(chip->irq, dw_dma_interrupt, IRQF_SHARED, + "dw_dmac", dw); + if (err) + return err; + INIT_LIST_HEAD(&dw->dma.channels); for (i = 0; i < nr_channels; i++) { struct dw_dma_chan *dwc = &dw->chan[i]; @@ -1667,6 +1667,7 @@ int dw_dma_remove(struct dw_dma_chip *chip) dw_dma_off(dw); dma_async_device_unregister(&dw->dma); + free_irq(chip->irq, dw); tasklet_kill(&dw->tasklet); list_for_each_entry_safe(dwc, _dwc, &dw->dma.channels, -- cgit v1.2.3 From 696dfd95ba9838327a7013e5988ff3ba60dcc8c8 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 7 May 2014 11:20:54 +0200 Subject: KVM: vmx: disable APIC virtualization in nested guests While running a nested guest, we should disable APIC virtualization controls (virtualized APIC register accesses, virtual interrupt delivery and posted interrupts), because we do not expose them to the nested guest. Reported-by: Hu Yaohui Suggested-by: Abel Gordon Signed-off-by: Paolo Bonzini --- arch/x86/kvm/vmx.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 33e8c028842f..138ceffc6377 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -7778,7 +7778,8 @@ static void prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12) exec_control = vmcs12->pin_based_vm_exec_control; exec_control |= vmcs_config.pin_based_exec_ctrl; - exec_control &= ~PIN_BASED_VMX_PREEMPTION_TIMER; + exec_control &= ~(PIN_BASED_VMX_PREEMPTION_TIMER | + PIN_BASED_POSTED_INTR); vmcs_write32(PIN_BASED_VM_EXEC_CONTROL, exec_control); vmx->nested.preemption_timer_expired = false; @@ -7815,7 +7816,9 @@ static void prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12) if (!vmx->rdtscp_enabled) exec_control &= ~SECONDARY_EXEC_RDTSCP; /* Take the following fields only from vmcs12 */ - exec_control &= ~SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES; + exec_control &= ~(SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | + SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | + SECONDARY_EXEC_APIC_REGISTER_VIRT); if (nested_cpu_has(vmcs12, CPU_BASED_ACTIVATE_SECONDARY_CONTROLS)) exec_control |= vmcs12->secondary_vm_exec_control; -- cgit v1.2.3 From eeb6324dd6668b05192708916f2a4bc463f382ca Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Tue, 6 May 2014 14:56:50 +0300 Subject: drm/i915: consider the source max DP lane count too Even if the panel claims it can support 4 lanes, there's the possibility that the HW can't, so consider this while selecting the max lane count. Reviewed-by: Damien Lespiau Signed-off-by: Paulo Zanoni Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_dp.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 5ca68aa9f237..115662c2f048 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -121,6 +121,22 @@ intel_dp_max_link_bw(struct intel_dp *intel_dp) return max_link_bw; } +static u8 intel_dp_max_lane_count(struct intel_dp *intel_dp) +{ + struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); + struct drm_device *dev = intel_dig_port->base.base.dev; + u8 source_max, sink_max; + + source_max = 4; + if (HAS_DDI(dev) && intel_dig_port->port == PORT_A && + (intel_dig_port->saved_port_bits & DDI_A_4_LANES) == 0) + source_max = 2; + + sink_max = drm_dp_max_lane_count(intel_dp->dpcd); + + return min(source_max, sink_max); +} + /* * The units on the numbers in the next two are... bizarre. Examples will * make it clearer; this one parallels an example in the eDP spec. @@ -171,7 +187,7 @@ intel_dp_mode_valid(struct drm_connector *connector, } max_link_clock = drm_dp_bw_code_to_link_rate(intel_dp_max_link_bw(intel_dp)); - max_lanes = drm_dp_max_lane_count(intel_dp->dpcd); + max_lanes = intel_dp_max_lane_count(intel_dp); max_rate = intel_dp_max_data_rate(max_link_clock, max_lanes); mode_rate = intel_dp_link_required(target_clock, 18); @@ -751,7 +767,7 @@ intel_dp_compute_config(struct intel_encoder *encoder, struct intel_crtc *intel_crtc = encoder->new_crtc; struct intel_connector *intel_connector = intel_dp->attached_connector; int lane_count, clock; - int max_lane_count = drm_dp_max_lane_count(intel_dp->dpcd); + int max_lane_count = intel_dp_max_lane_count(intel_dp); /* Conveniently, the link BW constants become indices with a shift...*/ int max_clock = intel_dp_max_link_bw(intel_dp) >> 3; int bpp, mode_rate; -- cgit v1.2.3 From e13e2b2c468bc54e872ad68126411d6a3f77001a Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 6 May 2014 14:56:51 +0300 Subject: drm/i915: clean up VBT eDP link param decoding Use defines, do not set anything if VBT has values unknown to us. Reviewed-by: Damien Lespiau Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_bios.c | 52 ++++++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index fa486c5fbb02..aff4a113cda3 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -560,47 +560,71 @@ parse_edp(struct drm_i915_private *dev_priv, struct bdb_header *bdb) dev_priv->vbt.edp_pps = *edp_pps; - dev_priv->vbt.edp_rate = edp_link_params->rate ? DP_LINK_BW_2_7 : - DP_LINK_BW_1_62; + switch (edp_link_params->rate) { + case EDP_RATE_1_62: + dev_priv->vbt.edp_rate = DP_LINK_BW_1_62; + break; + case EDP_RATE_2_7: + dev_priv->vbt.edp_rate = DP_LINK_BW_2_7; + break; + default: + DRM_DEBUG_KMS("VBT has unknown eDP link rate value %u\n", + edp_link_params->rate); + break; + } + switch (edp_link_params->lanes) { - case 0: + case EDP_LANE_1: dev_priv->vbt.edp_lanes = 1; break; - case 1: + case EDP_LANE_2: dev_priv->vbt.edp_lanes = 2; break; - case 3: - default: + case EDP_LANE_4: dev_priv->vbt.edp_lanes = 4; break; + default: + DRM_DEBUG_KMS("VBT has unknown eDP lane count value %u\n", + edp_link_params->lanes); + break; } + switch (edp_link_params->preemphasis) { - case 0: + case EDP_PREEMPHASIS_NONE: dev_priv->vbt.edp_preemphasis = DP_TRAIN_PRE_EMPHASIS_0; break; - case 1: + case EDP_PREEMPHASIS_3_5dB: dev_priv->vbt.edp_preemphasis = DP_TRAIN_PRE_EMPHASIS_3_5; break; - case 2: + case EDP_PREEMPHASIS_6dB: dev_priv->vbt.edp_preemphasis = DP_TRAIN_PRE_EMPHASIS_6; break; - case 3: + case EDP_PREEMPHASIS_9_5dB: dev_priv->vbt.edp_preemphasis = DP_TRAIN_PRE_EMPHASIS_9_5; break; + default: + DRM_DEBUG_KMS("VBT has unknown eDP pre-emphasis value %u\n", + edp_link_params->preemphasis); + break; } + switch (edp_link_params->vswing) { - case 0: + case EDP_VSWING_0_4V: dev_priv->vbt.edp_vswing = DP_TRAIN_VOLTAGE_SWING_400; break; - case 1: + case EDP_VSWING_0_6V: dev_priv->vbt.edp_vswing = DP_TRAIN_VOLTAGE_SWING_600; break; - case 2: + case EDP_VSWING_0_8V: dev_priv->vbt.edp_vswing = DP_TRAIN_VOLTAGE_SWING_800; break; - case 3: + case EDP_VSWING_1_2V: dev_priv->vbt.edp_vswing = DP_TRAIN_VOLTAGE_SWING_1200; break; + default: + DRM_DEBUG_KMS("VBT has unknown eDP voltage swing value %u\n", + edp_link_params->vswing); + break; } } -- cgit v1.2.3 From 56071a207602a451f0c46d3dcc8379b59ef576e2 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 6 May 2014 14:56:52 +0300 Subject: drm/i915: use lane count and link rate from VBT as minimums for eDP Most likely the minimums for both should be enough for enabling the native resolution on the eDP, and we'll end up using the predetermined optimal link config for the panel. v2: Add debug prints. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=73539 Tested-by: Markus Blank-Burian Reviewed-by: Damien Lespiau Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_dp.c | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 115662c2f048..8233f2aea665 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -767,8 +767,10 @@ intel_dp_compute_config(struct intel_encoder *encoder, struct intel_crtc *intel_crtc = encoder->new_crtc; struct intel_connector *intel_connector = intel_dp->attached_connector; int lane_count, clock; + int min_lane_count = 1; int max_lane_count = intel_dp_max_lane_count(intel_dp); /* Conveniently, the link BW constants become indices with a shift...*/ + int min_clock = 0; int max_clock = intel_dp_max_link_bw(intel_dp) >> 3; int bpp, mode_rate; static int bws[] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7, DP_LINK_BW_5_4 }; @@ -801,19 +803,33 @@ intel_dp_compute_config(struct intel_encoder *encoder, /* Walk through all bpp values. Luckily they're all nicely spaced with 2 * bpc in between. */ bpp = pipe_config->pipe_bpp; - if (is_edp(intel_dp) && dev_priv->vbt.edp_bpp && - dev_priv->vbt.edp_bpp < bpp) { - DRM_DEBUG_KMS("clamping bpp for eDP panel to BIOS-provided %i\n", - dev_priv->vbt.edp_bpp); - bpp = dev_priv->vbt.edp_bpp; + if (is_edp(intel_dp)) { + if (dev_priv->vbt.edp_bpp && dev_priv->vbt.edp_bpp < bpp) { + DRM_DEBUG_KMS("clamping bpp for eDP panel to BIOS-provided %i\n", + dev_priv->vbt.edp_bpp); + bpp = dev_priv->vbt.edp_bpp; + } + + if (dev_priv->vbt.edp_lanes) { + min_lane_count = min(dev_priv->vbt.edp_lanes, + max_lane_count); + DRM_DEBUG_KMS("using min %u lanes per VBT\n", + min_lane_count); + } + + if (dev_priv->vbt.edp_rate) { + min_clock = min(dev_priv->vbt.edp_rate >> 3, max_clock); + DRM_DEBUG_KMS("using min %02x link bw per VBT\n", + bws[min_clock]); + } } for (; bpp >= 6*3; bpp -= 2*3) { mode_rate = intel_dp_link_required(adjusted_mode->crtc_clock, bpp); - for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) { - for (clock = 0; clock <= max_clock; clock++) { + for (lane_count = min_lane_count; lane_count <= max_lane_count; lane_count <<= 1) { + for (clock = min_clock; clock <= max_clock; clock++) { link_clock = drm_dp_bw_code_to_link_rate(bws[clock]); link_avail = intel_dp_max_data_rate(link_clock, lane_count); -- cgit v1.2.3 From e4c610fe051579ba0a1fadf339905b0231c6ef94 Mon Sep 17 00:00:00 2001 From: Egbert Eich Date: Fri, 11 Apr 2014 19:07:44 +0200 Subject: drm/i915/SDVO: For sysfs link put directory and target in correct order When linking the i2c sysfs file into the connector's directory pass directory and link target in the right order. This code was introduced with: commit 931c1c26983b4f84e33b78579fc8d57e4a14c6b4 Author: Imre Deak Date: Tue Feb 11 17:12:51 2014 +0200 drm/i915: sdvo: add i2c sysfs symlink to the connector's directory This is the same what we do for DP connectors, so make things more consistent. Signed-off-by: Egbert Eich Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_sdvo.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index d27155adf5db..46be00d66df3 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -2424,8 +2424,8 @@ intel_sdvo_connector_init(struct intel_sdvo_connector *connector, if (ret < 0) goto err1; - ret = sysfs_create_link(&encoder->ddc.dev.kobj, - &drm_connector->kdev->kobj, + ret = sysfs_create_link(&drm_connector->kdev->kobj, + &encoder->ddc.dev.kobj, encoder->ddc.dev.kobj.name); if (ret < 0) goto err2; -- cgit v1.2.3 From a6f9bf4d2f965b862b95213303d154e02957eed8 Mon Sep 17 00:00:00 2001 From: Levente Kurusa Date: Tue, 6 May 2014 15:57:48 +0200 Subject: libata: clean up ZPODD when a port is detached When a ZPODD device is unbound via sysfs, the ACPI notify handler is not removed. This causes panics as observed in Bug #74601. The panic only happens when the wake happens from outside the kernel (i.e. inserting a media or pressing a button). Add a loop to ata_port_detach which loops through the port's devices and checks if zpodd is enabled, if so call zpodd_exit. Cc: stable@vger.kernel.org Reviewed-by: Aaron Lu Signed-off-by: Levente Kurusa Signed-off-by: Tejun Heo --- drivers/ata/libata-core.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 73c5d0410d47..886d4d3d63a3 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -6314,6 +6314,8 @@ int ata_host_activate(struct ata_host *host, int irq, static void ata_port_detach(struct ata_port *ap) { unsigned long flags; + struct ata_link *link; + struct ata_device *dev; if (!ap->ops->error_handler) goto skip_eh; @@ -6333,6 +6335,13 @@ static void ata_port_detach(struct ata_port *ap) cancel_delayed_work_sync(&ap->hotplug_task); skip_eh: + /* clean up zpodd on port removal */ + ata_for_each_link(link, ap, HOST_FIRST) { + ata_for_each_dev(dev, link, ALL) { + if (zpodd_dev_enabled(dev)) + zpodd_exit(dev); + } + } if (ap->pmp_link) { int i; for (i = 0; i < SATA_PMP_MAX_PORTS; i++) -- cgit v1.2.3 From 34e0a1e1563809a07371f44c6e4c3e216dc8684d Mon Sep 17 00:00:00 2001 From: Paul Handrigan Date: Wed, 7 May 2014 09:49:36 -0500 Subject: ASoC: Update Cirrus Logic CODEC maintainers. Remove Timur Tabi as maintainer for CS4270 codec. I would like to thank Timur for his work on maintaining this driver. Signed-off-by: Paul Handrigan Signed-off-by: Mark Brown --- MAINTAINERS | 6 ------ 1 file changed, 6 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 6dc67b1fdb50..8f46182ef910 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2245,12 +2245,6 @@ L: linux-usb@vger.kernel.org S: Maintained F: drivers/usb/host/ohci-ep93xx.c -CIRRUS LOGIC CS4270 SOUND DRIVER -M: Timur Tabi -L: alsa-devel@alsa-project.org (moderated for non-subscribers) -S: Odd Fixes -F: sound/soc/codecs/cs4270* - CIRRUS LOGIC AUDIO CODEC DRIVERS M: Brian Austin M: Paul Handrigan -- cgit v1.2.3 From 4f4178f3bb1f470d7fb863ec531e08e20a0fd51c Mon Sep 17 00:00:00 2001 From: Bjørn Mork Date: Sat, 3 May 2014 16:12:47 +0200 Subject: net: cdc_mbim: __vlan_find_dev_deep need rcu_read_lock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes this warning introduced by commit 5b8f15f78e6f ("net: cdc_mbim: handle IPv6 Neigbor Solicitations"): =============================== [ INFO: suspicious RCU usage. ] 3.15.0-rc3 #213 Tainted: G W O ------------------------------- net/8021q/vlan_core.c:69 suspicious rcu_dereference_check() usage! other info that might help us debug this: rcu_scheduler_active = 1, debug_locks = 1 no locks held by ksoftirqd/0/3. stack backtrace: CPU: 0 PID: 3 Comm: ksoftirqd/0 Tainted: G W O 3.15.0-rc3 #213 Hardware name: LENOVO 2776LEG/2776LEG, BIOS 6EET55WW (3.15 ) 12/19/2011 0000000000000001 ffff880232533bf0 ffffffff813a5ee6 0000000000000006 ffff880232530090 ffff880232533c20 ffffffff81076b94 0000000000000081 0000000000000000 ffff8802085ac000 ffff88007fc8ea00 ffff880232533c50 Call Trace: [] dump_stack+0x4e/0x68 [] lockdep_rcu_suspicious+0xfa/0x103 [] __vlan_find_dev_deep+0x54/0x94 [] cdc_mbim_rx_fixup+0x379/0x66a [cdc_mbim] [] ? _raw_spin_unlock_irqrestore+0x3a/0x49 [] ? trace_hardirqs_on_caller+0x192/0x1a1 [] usbnet_bh+0x59/0x287 [usbnet] [] tasklet_action+0xbb/0xcd [] __do_softirq+0x14c/0x30d [] run_ksoftirqd+0x1f/0x50 [] smpboot_thread_fn+0x172/0x18e [] ? SyS_setgroups+0xdf/0xdf [] kthread+0xb5/0xbd [] ? __wait_for_common+0x13b/0x170 [] ? __kthread_parkme+0x5c/0x5c [] ret_from_fork+0x7c/0xb0 [] ? __kthread_parkme+0x5c/0x5c Fixes: 5b8f15f78e6f ("net: cdc_mbim: handle IPv6 Neigbor Solicitations") Signed-off-by: Bjørn Mork Signed-off-by: David S. Miller --- drivers/net/usb/cdc_mbim.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/drivers/net/usb/cdc_mbim.c b/drivers/net/usb/cdc_mbim.c index c9f3281506af..13f7705fd679 100644 --- a/drivers/net/usb/cdc_mbim.c +++ b/drivers/net/usb/cdc_mbim.c @@ -204,17 +204,23 @@ static void do_neigh_solicit(struct usbnet *dev, u8 *buf, u16 tci) return; /* need to send the NA on the VLAN dev, if any */ - if (tci) + rcu_read_lock(); + if (tci) { netdev = __vlan_find_dev_deep(dev->net, htons(ETH_P_8021Q), tci); - else + if (!netdev) { + rcu_read_unlock(); + return; + } + } else { netdev = dev->net; - if (!netdev) - return; + } + dev_hold(netdev); + rcu_read_unlock(); in6_dev = in6_dev_get(netdev); if (!in6_dev) - return; + goto out; is_router = !!in6_dev->cnf.forwarding; in6_dev_put(in6_dev); @@ -224,6 +230,8 @@ static void do_neigh_solicit(struct usbnet *dev, u8 *buf, u16 tci) true /* solicited */, false /* override */, true /* inc_opt */); +out: + dev_put(netdev); } static bool is_neigh_solicit(u8 *buf, size_t len) -- cgit v1.2.3 From ca6c5d4ad216d5942ae544bbf02503041bd802aa Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Sun, 4 May 2014 23:24:31 +0200 Subject: net: ipv4: ip_forward: fix inverted local_df test local_df means 'ignore DF bit if set', so if its set we're allowed to perform ip fragmentation. This wasn't noticed earlier because the output path also drops such skbs (and emits needed icmp error) and because netfilter ip defrag did not set local_df until couple of days ago. Only difference is that DF-packets-larger-than MTU now discarded earlier (f.e. we avoid pointless netfilter postrouting trip). While at it, drop the repeated test ip_exceeds_mtu, checking it once is enough... Fixes: fe6cc55f3a9 ("net: ip, ipv6: handle gso skbs in forwarding path") Signed-off-by: Florian Westphal Signed-off-by: David S. Miller --- net/ipv4/ip_forward.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c index be8abe73bb9f..c29ae8371e44 100644 --- a/net/ipv4/ip_forward.c +++ b/net/ipv4/ip_forward.c @@ -42,12 +42,12 @@ static bool ip_may_fragment(const struct sk_buff *skb) { return unlikely((ip_hdr(skb)->frag_off & htons(IP_DF)) == 0) || - !skb->local_df; + skb->local_df; } static bool ip_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu) { - if (skb->len <= mtu || skb->local_df) + if (skb->len <= mtu) return false; if (skb_is_gso(skb) && skb_gso_network_seglen(skb) <= mtu) -- cgit v1.2.3 From 418a31561d594a2b636c1e2fa94ecd9e1245abb1 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Mon, 5 May 2014 00:03:34 +0200 Subject: net: ipv6: send pkttoobig immediately if orig frag size > mtu If conntrack defragments incoming ipv6 frags it stores largest original frag size in ip6cb and sets ->local_df. We must thus first test the largest original frag size vs. mtu, and not vice versa. Without this patch PKTTOOBIG is still generated in ip6_fragment() later in the stack, but 1) IPSTATS_MIB_INTOOBIGERRORS won't increment 2) packet did (needlessly) traverse netfilter postrouting hook. Fixes: fe6cc55f3a9 ("net: ip, ipv6: handle gso skbs in forwarding path") Signed-off-by: Florian Westphal Signed-off-by: David S. Miller --- net/ipv6/ip6_output.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 40e7581374f7..31a38bde69ef 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -344,12 +344,16 @@ static unsigned int ip6_dst_mtu_forward(const struct dst_entry *dst) static bool ip6_pkt_too_big(const struct sk_buff *skb, unsigned int mtu) { - if (skb->len <= mtu || skb->local_df) + if (skb->len <= mtu) return false; + /* ipv6 conntrack defrag sets max_frag_size + local_df */ if (IP6CB(skb)->frag_max_size && IP6CB(skb)->frag_max_size > mtu) return true; + if (skb->local_df) + return false; + if (skb_is_gso(skb) && skb_gso_network_seglen(skb) <= mtu) return false; -- cgit v1.2.3 From c7ba65d7b64984ff371cb5630b36af23506c50d5 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Mon, 5 May 2014 15:00:43 +0200 Subject: net: ip: push gso skb forwarding handling down the stack Doing the segmentation in the forward path has one major drawback: When using virtio, we may process gso udp packets coming from host network stack. In that case, netfilter POSTROUTING will see one packet with udp header followed by multiple ip fragments. Delay the segmentation and do it after POSTROUTING invocation to avoid this. Fixes: fe6cc55f3a9 ("net: ip, ipv6: handle gso skbs in forwarding path") Signed-off-by: Florian Westphal Signed-off-by: David S. Miller --- net/ipv4/ip_forward.c | 50 -------------------------------------------------- net/ipv4/ip_output.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 48 insertions(+), 53 deletions(-) diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c index c29ae8371e44..6f111e48e11c 100644 --- a/net/ipv4/ip_forward.c +++ b/net/ipv4/ip_forward.c @@ -56,53 +56,6 @@ static bool ip_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu) return true; } -static bool ip_gso_exceeds_dst_mtu(const struct sk_buff *skb) -{ - unsigned int mtu; - - if (skb->local_df || !skb_is_gso(skb)) - return false; - - mtu = ip_dst_mtu_maybe_forward(skb_dst(skb), true); - - /* if seglen > mtu, do software segmentation for IP fragmentation on - * output. DF bit cannot be set since ip_forward would have sent - * icmp error. - */ - return skb_gso_network_seglen(skb) > mtu; -} - -/* called if GSO skb needs to be fragmented on forward */ -static int ip_forward_finish_gso(struct sk_buff *skb) -{ - struct dst_entry *dst = skb_dst(skb); - netdev_features_t features; - struct sk_buff *segs; - int ret = 0; - - features = netif_skb_dev_features(skb, dst->dev); - segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK); - if (IS_ERR(segs)) { - kfree_skb(skb); - return -ENOMEM; - } - - consume_skb(skb); - - do { - struct sk_buff *nskb = segs->next; - int err; - - segs->next = NULL; - err = dst_output(segs); - - if (err && ret == 0) - ret = err; - segs = nskb; - } while (segs); - - return ret; -} static int ip_forward_finish(struct sk_buff *skb) { @@ -114,9 +67,6 @@ static int ip_forward_finish(struct sk_buff *skb) if (unlikely(opt->optlen)) ip_forward_options(skb); - if (ip_gso_exceeds_dst_mtu(skb)) - return ip_forward_finish_gso(skb); - return dst_output(skb); } diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 1cbeba5edff9..a52f50187b54 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -211,6 +211,48 @@ static inline int ip_finish_output2(struct sk_buff *skb) return -EINVAL; } +static int ip_finish_output_gso(struct sk_buff *skb) +{ + netdev_features_t features; + struct sk_buff *segs; + int ret = 0; + + /* common case: locally created skb or seglen is <= mtu */ + if (((IPCB(skb)->flags & IPSKB_FORWARDED) == 0) || + skb_gso_network_seglen(skb) <= ip_skb_dst_mtu(skb)) + return ip_finish_output2(skb); + + /* Slowpath - GSO segment length is exceeding the dst MTU. + * + * This can happen in two cases: + * 1) TCP GRO packet, DF bit not set + * 2) skb arrived via virtio-net, we thus get TSO/GSO skbs directly + * from host network stack. + */ + features = netif_skb_features(skb); + segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK); + if (IS_ERR(segs)) { + kfree_skb(skb); + return -ENOMEM; + } + + consume_skb(skb); + + do { + struct sk_buff *nskb = segs->next; + int err; + + segs->next = NULL; + err = ip_fragment(segs, ip_finish_output2); + + if (err && ret == 0) + ret = err; + segs = nskb; + } while (segs); + + return ret; +} + static int ip_finish_output(struct sk_buff *skb) { #if defined(CONFIG_NETFILTER) && defined(CONFIG_XFRM) @@ -220,10 +262,13 @@ static int ip_finish_output(struct sk_buff *skb) return dst_output(skb); } #endif - if (skb->len > ip_skb_dst_mtu(skb) && !skb_is_gso(skb)) + if (skb_is_gso(skb)) + return ip_finish_output_gso(skb); + + if (skb->len > ip_skb_dst_mtu(skb)) return ip_fragment(skb, ip_finish_output2); - else - return ip_finish_output2(skb); + + return ip_finish_output2(skb); } int ip_mc_output(struct sock *sk, struct sk_buff *skb) -- cgit v1.2.3 From c1e756bfcbcac838a86a23f3e4501b556a961e3c Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Mon, 5 May 2014 15:00:44 +0200 Subject: Revert "net: core: introduce netif_skb_dev_features" This reverts commit d206940319c41df4299db75ed56142177bb2e5f6, there are no more callers. Signed-off-by: Florian Westphal Signed-off-by: David S. Miller --- include/linux/netdevice.h | 7 +------ net/core/dev.c | 22 ++++++++++------------ 2 files changed, 11 insertions(+), 18 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 7ed3a3aa6604..20e99efb1ca6 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -3180,12 +3180,7 @@ void netdev_change_features(struct net_device *dev); void netif_stacked_transfer_operstate(const struct net_device *rootdev, struct net_device *dev); -netdev_features_t netif_skb_dev_features(struct sk_buff *skb, - const struct net_device *dev); -static inline netdev_features_t netif_skb_features(struct sk_buff *skb) -{ - return netif_skb_dev_features(skb, skb->dev); -} +netdev_features_t netif_skb_features(struct sk_buff *skb); static inline bool net_gso_ok(netdev_features_t features, int gso_type) { diff --git a/net/core/dev.c b/net/core/dev.c index d2c8a06b3a98..c619b8641337 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2418,7 +2418,7 @@ EXPORT_SYMBOL(netdev_rx_csum_fault); * 2. No high memory really exists on this machine. */ -static int illegal_highdma(const struct net_device *dev, struct sk_buff *skb) +static int illegal_highdma(struct net_device *dev, struct sk_buff *skb) { #ifdef CONFIG_HIGHMEM int i; @@ -2493,38 +2493,36 @@ static int dev_gso_segment(struct sk_buff *skb, netdev_features_t features) } static netdev_features_t harmonize_features(struct sk_buff *skb, - const struct net_device *dev, - netdev_features_t features) + netdev_features_t features) { int tmp; if (skb->ip_summed != CHECKSUM_NONE && !can_checksum_protocol(features, skb_network_protocol(skb, &tmp))) { features &= ~NETIF_F_ALL_CSUM; - } else if (illegal_highdma(dev, skb)) { + } else if (illegal_highdma(skb->dev, skb)) { features &= ~NETIF_F_SG; } return features; } -netdev_features_t netif_skb_dev_features(struct sk_buff *skb, - const struct net_device *dev) +netdev_features_t netif_skb_features(struct sk_buff *skb) { __be16 protocol = skb->protocol; - netdev_features_t features = dev->features; + netdev_features_t features = skb->dev->features; - if (skb_shinfo(skb)->gso_segs > dev->gso_max_segs) + if (skb_shinfo(skb)->gso_segs > skb->dev->gso_max_segs) features &= ~NETIF_F_GSO_MASK; if (protocol == htons(ETH_P_8021Q) || protocol == htons(ETH_P_8021AD)) { struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data; protocol = veh->h_vlan_encapsulated_proto; } else if (!vlan_tx_tag_present(skb)) { - return harmonize_features(skb, dev, features); + return harmonize_features(skb, features); } - features &= (dev->vlan_features | NETIF_F_HW_VLAN_CTAG_TX | + features &= (skb->dev->vlan_features | NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_STAG_TX); if (protocol == htons(ETH_P_8021Q) || protocol == htons(ETH_P_8021AD)) @@ -2532,9 +2530,9 @@ netdev_features_t netif_skb_dev_features(struct sk_buff *skb, NETIF_F_GEN_CSUM | NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_STAG_TX; - return harmonize_features(skb, dev, features); + return harmonize_features(skb, features); } -EXPORT_SYMBOL(netif_skb_dev_features); +EXPORT_SYMBOL(netif_skb_features); int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev, struct netdev_queue *txq) -- cgit v1.2.3 From 76a691d0ab71a244f7582a5b0387728befbdb52f Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Mon, 5 May 2014 14:51:47 -0400 Subject: jme: Fix DMA unmap warning The jme driver forgot to check the return status from pci_map_page in its tx path, causing a dma api warning on unmap. Easy fix, just do the check and augment the tx path to tell the stack that the driver is busy so we re-queue the frame. Signed-off-by: Neil Horman CC: Guo-Fu Tseng CC: "David S. Miller" Signed-off-by: David S. Miller --- drivers/net/ethernet/jme.c | 53 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 47 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c index b0c6050479eb..6e664d9038d6 100644 --- a/drivers/net/ethernet/jme.c +++ b/drivers/net/ethernet/jme.c @@ -1988,7 +1988,7 @@ jme_alloc_txdesc(struct jme_adapter *jme, return idx; } -static void +static int jme_fill_tx_map(struct pci_dev *pdev, struct txdesc *txdesc, struct jme_buffer_info *txbi, @@ -2005,6 +2005,9 @@ jme_fill_tx_map(struct pci_dev *pdev, len, PCI_DMA_TODEVICE); + if (unlikely(pci_dma_mapping_error(pdev, dmaaddr))) + return -EINVAL; + pci_dma_sync_single_for_device(pdev, dmaaddr, len, @@ -2021,9 +2024,30 @@ jme_fill_tx_map(struct pci_dev *pdev, txbi->mapping = dmaaddr; txbi->len = len; + return 0; } -static void +static void jme_drop_tx_map(struct jme_adapter *jme, int startidx, int endidx) +{ + struct jme_ring *txring = &(jme->txring[0]); + struct jme_buffer_info *txbi = txring->bufinf, *ctxbi; + int mask = jme->tx_ring_mask; + int j; + + for (j = startidx ; j < endidx ; ++j) { + ctxbi = txbi + ((startidx + j + 2) & (mask)); + pci_unmap_page(jme->pdev, + ctxbi->mapping, + ctxbi->len, + PCI_DMA_TODEVICE); + + ctxbi->mapping = 0; + ctxbi->len = 0; + } + +} + +static int jme_map_tx_skb(struct jme_adapter *jme, struct sk_buff *skb, int idx) { struct jme_ring *txring = &(jme->txring[0]); @@ -2034,25 +2058,37 @@ jme_map_tx_skb(struct jme_adapter *jme, struct sk_buff *skb, int idx) int mask = jme->tx_ring_mask; const struct skb_frag_struct *frag; u32 len; + int ret = 0; for (i = 0 ; i < nr_frags ; ++i) { frag = &skb_shinfo(skb)->frags[i]; ctxdesc = txdesc + ((idx + i + 2) & (mask)); ctxbi = txbi + ((idx + i + 2) & (mask)); - jme_fill_tx_map(jme->pdev, ctxdesc, ctxbi, + ret = jme_fill_tx_map(jme->pdev, ctxdesc, ctxbi, skb_frag_page(frag), frag->page_offset, skb_frag_size(frag), hidma); + if (ret) { + jme_drop_tx_map(jme, idx, idx+i); + goto out; + } + } len = skb_is_nonlinear(skb) ? skb_headlen(skb) : skb->len; ctxdesc = txdesc + ((idx + 1) & (mask)); ctxbi = txbi + ((idx + 1) & (mask)); - jme_fill_tx_map(jme->pdev, ctxdesc, ctxbi, virt_to_page(skb->data), + ret = jme_fill_tx_map(jme->pdev, ctxdesc, ctxbi, virt_to_page(skb->data), offset_in_page(skb->data), len, hidma); + if (ret) + jme_drop_tx_map(jme, idx, idx+i); + +out: + return ret; } + static int jme_tx_tso(struct sk_buff *skb, __le16 *mss, u8 *flags) { @@ -2131,6 +2167,7 @@ jme_fill_tx_desc(struct jme_adapter *jme, struct sk_buff *skb, int idx) struct txdesc *txdesc; struct jme_buffer_info *txbi; u8 flags; + int ret = 0; txdesc = (struct txdesc *)txring->desc + idx; txbi = txring->bufinf + idx; @@ -2155,7 +2192,10 @@ jme_fill_tx_desc(struct jme_adapter *jme, struct sk_buff *skb, int idx) if (jme_tx_tso(skb, &txdesc->desc1.mss, &flags)) jme_tx_csum(jme, skb, &flags); jme_tx_vlan(skb, &txdesc->desc1.vlan, &flags); - jme_map_tx_skb(jme, skb, idx); + ret = jme_map_tx_skb(jme, skb, idx); + if (ret) + return ret; + txdesc->desc1.flags = flags; /* * Set tx buffer info after telling NIC to send @@ -2228,7 +2268,8 @@ jme_start_xmit(struct sk_buff *skb, struct net_device *netdev) return NETDEV_TX_BUSY; } - jme_fill_tx_desc(jme, skb, idx); + if (jme_fill_tx_desc(jme, skb, idx)) + return NETDEV_TX_BUSY; jwrite32(jme, JME_TXCS, jme->reg_txcs | TXCS_SELECT_QUEUE0 | -- cgit v1.2.3 From 83f7a85f1134c6e914453f5747435415a23d516b Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sun, 13 Apr 2014 16:03:11 +0300 Subject: iwlwifi: pcie: disable interrupts upon PCIe alloc In case RFKILL is in KILL position, the NIC will issue an interrupt straight away. This interrupt won't be sent because it is masked in the hardware. But if our interrupt service routine is called for another reason (SHARED_IRQ), then we'll look at the interrupt cause and service it. This can cause bad things if we are not ready yet. Explicitly clean the interrupt cause register to make sure we won't service anything before we are ready to. Cc: [3.14] Reported-and-tested-by: Alexander Monakov Reviewed-by: Johannes Berg Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/pcie/trans.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index dcfd6d866d09..2365553f1ef7 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c @@ -1749,6 +1749,10 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, * PCI Tx retries from interfering with C3 CPU state */ pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00); + trans->dev = &pdev->dev; + trans_pcie->pci_dev = pdev; + iwl_disable_interrupts(trans); + err = pci_enable_msi(pdev); if (err) { dev_err(&pdev->dev, "pci_enable_msi failed(0X%x)\n", err); @@ -1760,8 +1764,6 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, } } - trans->dev = &pdev->dev; - trans_pcie->pci_dev = pdev; trans->hw_rev = iwl_read32(trans, CSR_HW_REV); trans->hw_id = (pdev->device << 16) + pdev->subsystem_device; snprintf(trans->hw_id_str, sizeof(trans->hw_id_str), @@ -1787,8 +1789,6 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, goto out_pci_disable_msi; } - trans_pcie->inta_mask = CSR_INI_SET_MASK; - if (iwl_pcie_alloc_ict(trans)) goto out_free_cmd_pool; @@ -1800,6 +1800,8 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, goto out_free_ict; } + trans_pcie->inta_mask = CSR_INI_SET_MASK; + return trans; out_free_ict: -- cgit v1.2.3 From d5d2bf3eabb34cc8eaf54db37fdc43f04267985a Mon Sep 17 00:00:00 2001 From: Manish Chopra Date: Tue, 6 May 2014 03:46:48 -0400 Subject: qlcnic: Fix panic while dumping TX queues on TX timeout o In case of non-multi TX queue mode driver does not initialize "crb_intr_mask" pointer and driver was accessing that un-initialized pointer while dumping TX queue. So dump "crb_intr_mask" only when it is initilaized. Signed-off-by: Manish Chopra Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index 0bc914859e38..be789513774c 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c @@ -2943,9 +2943,13 @@ static void qlcnic_dump_tx_rings(struct qlcnic_adapter *adapter) tx_ring->tx_stats.xmit_called, tx_ring->tx_stats.xmit_on, tx_ring->tx_stats.xmit_off); + + if (tx_ring->crb_intr_mask) + netdev_info(netdev, "crb_intr_mask=%d\n", + readl(tx_ring->crb_intr_mask)); + netdev_info(netdev, - "crb_intr_mask=%d, hw_producer=%d, sw_producer=%d sw_consumer=%d, hw_consumer=%d\n", - readl(tx_ring->crb_intr_mask), + "hw_producer=%d, sw_producer=%d sw_consumer=%d, hw_consumer=%d\n", readl(tx_ring->crb_cmd_producer), tx_ring->producer, tx_ring->sw_consumer, le32_to_cpu(*(tx_ring->hw_consumer))); -- cgit v1.2.3 From 84d7ad2c3b8a80888d9a483388ccbd5e5f07438f Mon Sep 17 00:00:00 2001 From: Shahed Shaikh Date: Tue, 6 May 2014 03:46:49 -0400 Subject: qlcnic: Set real_num_{tx|rx}_queues properly Do not set netdev->real_num_tx_queues directly, let netif_set_real_num_tx_queues() take care of it. Do not overwrite netdev->num_tx_queues everytime when driver changes its Tx ring size through ethtool -L and also notify stack to update number of Rx queues. Signed-off-by: Shahed Shaikh Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 16 -------- drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 49 +++++++++++++++++++++++- 2 files changed, 47 insertions(+), 18 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h index 7b52a88923ef..f785d01c7d12 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h @@ -1719,22 +1719,6 @@ static inline u32 qlcnic_tx_avail(struct qlcnic_host_tx_ring *tx_ring) tx_ring->producer; } -static inline int qlcnic_set_real_num_queues(struct qlcnic_adapter *adapter, - struct net_device *netdev) -{ - int err; - - netdev->num_tx_queues = adapter->drv_tx_rings; - netdev->real_num_tx_queues = adapter->drv_tx_rings; - - err = netif_set_real_num_tx_queues(netdev, adapter->drv_tx_rings); - if (err) - netdev_err(netdev, "failed to set %d Tx queues\n", - adapter->drv_tx_rings); - - return err; -} - struct qlcnic_nic_template { int (*config_bridged_mode) (struct qlcnic_adapter *, u32); int (*config_led) (struct qlcnic_adapter *, u32, u32); diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index be789513774c..7e55e88a81bf 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c @@ -2206,6 +2206,31 @@ static void qlcnic_82xx_set_mac_filter_count(struct qlcnic_adapter *adapter) ahw->max_uc_count = count; } +static int qlcnic_set_real_num_queues(struct qlcnic_adapter *adapter, + u8 tx_queues, u8 rx_queues) +{ + struct net_device *netdev = adapter->netdev; + int err = 0; + + if (tx_queues) { + err = netif_set_real_num_tx_queues(netdev, tx_queues); + if (err) { + netdev_err(netdev, "failed to set %d Tx queues\n", + tx_queues); + return err; + } + } + + if (rx_queues) { + err = netif_set_real_num_rx_queues(netdev, rx_queues); + if (err) + netdev_err(netdev, "failed to set %d Rx queues\n", + rx_queues); + } + + return err; +} + int qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev, int pci_using_dac) @@ -2269,7 +2294,8 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev, netdev->priv_flags |= IFF_UNICAST_FLT; netdev->irq = adapter->msix_entries[0].vector; - err = qlcnic_set_real_num_queues(adapter, netdev); + err = qlcnic_set_real_num_queues(adapter, adapter->drv_tx_rings, + adapter->drv_sds_rings); if (err) return err; @@ -3982,12 +4008,21 @@ int qlcnic_validate_rings(struct qlcnic_adapter *adapter, __u32 ring_cnt, int qlcnic_setup_rings(struct qlcnic_adapter *adapter) { struct net_device *netdev = adapter->netdev; + u8 tx_rings, rx_rings; int err; if (test_bit(__QLCNIC_RESETTING, &adapter->state)) return -EBUSY; + tx_rings = adapter->drv_tss_rings; + rx_rings = adapter->drv_rss_rings; + netif_device_detach(netdev); + + err = qlcnic_set_real_num_queues(adapter, tx_rings, rx_rings); + if (err) + goto done; + if (netif_running(netdev)) __qlcnic_down(adapter, netdev); @@ -4007,7 +4042,17 @@ int qlcnic_setup_rings(struct qlcnic_adapter *adapter) return err; } - netif_set_real_num_tx_queues(netdev, adapter->drv_tx_rings); + /* Check if we need to update real_num_{tx|rx}_queues because + * qlcnic_setup_intr() may change Tx/Rx rings size + */ + if ((tx_rings != adapter->drv_tx_rings) || + (rx_rings != adapter->drv_sds_rings)) { + err = qlcnic_set_real_num_queues(adapter, + adapter->drv_tx_rings, + adapter->drv_sds_rings); + if (err) + goto done; + } if (qlcnic_83xx_check(adapter)) { qlcnic_83xx_initialize_nic(adapter, 1); -- cgit v1.2.3 From aeefa1ecfc799b0ea2c4979617f14cecd5cccbfd Mon Sep 17 00:00:00 2001 From: Sergey Popovich Date: Tue, 6 May 2014 18:23:08 +0300 Subject: ipv4: fib_semantics: increment fib_info_cnt after fib_info allocation Increment fib_info_cnt in fib_create_info() right after successfuly alllocating fib_info structure, overwise fib_metrics allocation failure leads to fib_info_cnt incorrectly decremented in free_fib_info(), called on error path from fib_create_info(). Signed-off-by: Sergey Popovich Signed-off-by: David S. Miller --- net/ipv4/fib_semantics.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index 8a043f03c88e..b10cd43a4722 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c @@ -821,13 +821,13 @@ struct fib_info *fib_create_info(struct fib_config *cfg) fi = kzalloc(sizeof(*fi)+nhs*sizeof(struct fib_nh), GFP_KERNEL); if (fi == NULL) goto failure; + fib_info_cnt++; if (cfg->fc_mx) { fi->fib_metrics = kzalloc(sizeof(u32) * RTAX_MAX, GFP_KERNEL); if (!fi->fib_metrics) goto failure; } else fi->fib_metrics = (u32 *) dst_default_metrics; - fib_info_cnt++; fi->fib_net = hold_net(net); fi->fib_protocol = cfg->fc_protocol; -- cgit v1.2.3 From 14262d67fe348018af368a07430fbc06eadeabb1 Mon Sep 17 00:00:00 2001 From: George Spelvin Date: Wed, 7 May 2014 17:05:52 -0400 Subject: x86-64, build: Fix stack protector Makefile breakage with 32-bit userland If you are using a 64-bit kernel with 32-bit userland, then scripts/gcc-x86_64-has-stack-protector.sh invokes 32-bit gcc with -mcmodel=kernel, which produces: :1:0: error: code model 'kernel' not supported in the 32 bit mode and trips the "broken compiler" test at arch/x86/Makefile:120. There are several places a fix is possible, but the following seems cleanest. (But it's minimal; it would also be possible to factor out a bunch of stuff from the two branches of the if.) Signed-off-by: George Spelvin Link: http://lkml.kernel.org/r/20140507210552.7581.qmail@ns.horizon.com Cc: # v3.14 Signed-off-by: H. Peter Anvin --- arch/x86/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/Makefile b/arch/x86/Makefile index ce6ad7e6a7d7..33f71b01fd22 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -79,6 +79,7 @@ else UTS_MACHINE := x86_64 CHECKFLAGS += -D__x86_64__ -m64 + biarch := -m64 KBUILD_AFLAGS += -m64 KBUILD_CFLAGS += -m64 -- cgit v1.2.3 From 23a456f05353035d1a2b3f1b9a92707acdc036e0 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Tue, 6 May 2014 18:52:16 +0200 Subject: net: mdio: of_mdiobus_register(): fall back to mdiobus_register() for !CONFIG_OF If CONFIG_OF is not set, make of_mdiobus_register() call mdiobus_register() instead of returning -ENOSYS. This way, we can just call of_mdiobus_register() from all DT-enabled drivers to handle the compat cases. Signed-off-by: Daniel Mack Suggested-by: Florian Fainelli Acked-by: Florian Fainelli Acked-by: Mugunthan V N Signed-off-by: David S. Miller --- include/linux/of_mdio.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/include/linux/of_mdio.h b/include/linux/of_mdio.h index 6fe8464ed767..881a7c3571f4 100644 --- a/include/linux/of_mdio.h +++ b/include/linux/of_mdio.h @@ -31,7 +31,12 @@ extern struct mii_bus *of_mdio_find_bus(struct device_node *mdio_np); #else /* CONFIG_OF */ static inline int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) { - return -ENOSYS; + /* + * Fall back to the non-DT function to register a bus. + * This way, we don't have to keep compat bits around in drivers. + */ + + return mdiobus_register(mdio); } static inline struct phy_device *of_phy_find_device(struct device_node *phy_np) -- cgit v1.2.3 From b753631b3576bf343151a82513c5d56fcda1e24f Mon Sep 17 00:00:00 2001 From: Edward Lin Date: Wed, 7 May 2014 10:47:24 +0800 Subject: ACPI: blacklist win8 OSI for Dell Inspiron 7737 With win8 capabiltiy, the machine will boot itself immediately after shutdown command has executed. Work around this issue by disabling win8 capcability. This workaround also makes wireless hotkey work. Signed-off-by: Edward Lin Cc: All applicable Signed-off-by: Rafael J. Wysocki --- drivers/acpi/blacklist.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index afec4526c48a..4fc6cf53cd51 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c @@ -314,6 +314,14 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { DMI_MATCH(DMI_PRODUCT_VERSION, "2349D15"), }, }, + { + .callback = dmi_disable_osi_win8, + .ident = "Dell Inspiron 7737", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7737"), + }, + }, /* * BIOS invocation of _OSI(Linux) is almost always a BIOS bug. -- cgit v1.2.3 From f6e6e1b9fee88c90586787b71dc49bb3ce62bb89 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 5 May 2014 11:38:09 +0200 Subject: ACPI / blacklist: Add dmi_enable_osi_linux quirk for Asus EEE PC 1015PX Without this this EEE PC exports a non working WMI interface, with this it exports a working "good old" eeepc_laptop interface, fixing brightness control not working as well as rfkill being stuck in a permanent wireless blocked state. This is not an ideal way to fix this, but various attempts to fix this otherwise have failed, see: References: https://bugzilla.redhat.com/show_bug.cgi?id=1067181 Reported-and-tested-by: lou.cardone@gmail.com Signed-off-by: Hans de Goede Cc: All applicable Signed-off-by: Rafael J. Wysocki --- drivers/acpi/blacklist.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index 4fc6cf53cd51..3d8413d02a97 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c @@ -382,6 +382,19 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T500"), }, }, + /* + * Without this this EEEpc exports a non working WMI interface, with + * this it exports a working "good old" eeepc_laptop interface, fixing + * both brightness control, and rfkill not working. + */ + { + .callback = dmi_enable_osi_linux, + .ident = "Asus EEE PC 1015PX", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "1015PX"), + }, + }, {} }; -- cgit v1.2.3 From 98012849e0cbf980326f8e34d571f4474866a88e Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 6 May 2014 19:18:28 -0700 Subject: ACPI: Revert "ACPI / AC: convert ACPI ac driver to platform bus" Revert commit cc8ef5270734 (ACPI / AC: convert ACPI ac driver to platform bus) that is reported to break thermal management on MacBook Air 2013 with ArchLinux. Fixes: cc8ef5270734 (ACPI / AC: convert ACPI ac driver to platform bus) References: https://bugzilla.kernel.org/show_bug.cgi?id=71711 Cc: Zhang Rui Reported-and-tested-by: Manuel Krause Signed-off-by: Guenter Roeck Cc: 3.13+ # 3.13+ Signed-off-by: Rafael J. Wysocki --- drivers/acpi/ac.c | 117 +++++++++++++++++++++---------------------- drivers/acpi/acpi_platform.c | 1 - 2 files changed, 58 insertions(+), 60 deletions(-) diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index 2c01c1da29ce..c67f6f5ad611 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c @@ -52,11 +52,39 @@ MODULE_AUTHOR("Paul Diefenbaugh"); MODULE_DESCRIPTION("ACPI AC Adapter Driver"); MODULE_LICENSE("GPL"); +static int acpi_ac_add(struct acpi_device *device); +static int acpi_ac_remove(struct acpi_device *device); +static void acpi_ac_notify(struct acpi_device *device, u32 event); + +static const struct acpi_device_id ac_device_ids[] = { + {"ACPI0003", 0}, + {"", 0}, +}; +MODULE_DEVICE_TABLE(acpi, ac_device_ids); + +#ifdef CONFIG_PM_SLEEP +static int acpi_ac_resume(struct device *dev); +#endif +static SIMPLE_DEV_PM_OPS(acpi_ac_pm, NULL, acpi_ac_resume); + static int ac_sleep_before_get_state_ms; +static struct acpi_driver acpi_ac_driver = { + .name = "ac", + .class = ACPI_AC_CLASS, + .ids = ac_device_ids, + .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS, + .ops = { + .add = acpi_ac_add, + .remove = acpi_ac_remove, + .notify = acpi_ac_notify, + }, + .drv.pm = &acpi_ac_pm, +}; + struct acpi_ac { struct power_supply charger; - struct platform_device *pdev; + struct acpi_device * device; unsigned long long state; struct notifier_block battery_nb; }; @@ -69,10 +97,12 @@ struct acpi_ac { static int acpi_ac_get_state(struct acpi_ac *ac) { - acpi_status status; - acpi_handle handle = ACPI_HANDLE(&ac->pdev->dev); + acpi_status status = AE_OK; + + if (!ac) + return -EINVAL; - status = acpi_evaluate_integer(handle, "_PSR", NULL, + status = acpi_evaluate_integer(ac->device->handle, "_PSR", NULL, &ac->state); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, @@ -117,10 +147,9 @@ static enum power_supply_property ac_props[] = { Driver Model -------------------------------------------------------------------------- */ -static void acpi_ac_notify_handler(acpi_handle handle, u32 event, void *data) +static void acpi_ac_notify(struct acpi_device *device, u32 event) { - struct acpi_ac *ac = data; - struct acpi_device *adev; + struct acpi_ac *ac = acpi_driver_data(device); if (!ac) return; @@ -143,11 +172,10 @@ static void acpi_ac_notify_handler(acpi_handle handle, u32 event, void *data) msleep(ac_sleep_before_get_state_ms); acpi_ac_get_state(ac); - adev = ACPI_COMPANION(&ac->pdev->dev); - acpi_bus_generate_netlink_event(adev->pnp.device_class, - dev_name(&ac->pdev->dev), - event, (u32) ac->state); - acpi_notifier_call_chain(adev, event, (u32) ac->state); + acpi_bus_generate_netlink_event(device->pnp.device_class, + dev_name(&device->dev), event, + (u32) ac->state); + acpi_notifier_call_chain(device, event, (u32) ac->state); kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE); } @@ -192,49 +220,39 @@ static struct dmi_system_id ac_dmi_table[] = { {}, }; -static int acpi_ac_probe(struct platform_device *pdev) +static int acpi_ac_add(struct acpi_device *device) { int result = 0; struct acpi_ac *ac = NULL; - struct acpi_device *adev; - if (!pdev) - return -EINVAL; - adev = ACPI_COMPANION(&pdev->dev); - if (!adev) - return -ENODEV; + if (!device) + return -EINVAL; ac = kzalloc(sizeof(struct acpi_ac), GFP_KERNEL); if (!ac) return -ENOMEM; - strcpy(acpi_device_name(adev), ACPI_AC_DEVICE_NAME); - strcpy(acpi_device_class(adev), ACPI_AC_CLASS); - ac->pdev = pdev; - platform_set_drvdata(pdev, ac); + ac->device = device; + strcpy(acpi_device_name(device), ACPI_AC_DEVICE_NAME); + strcpy(acpi_device_class(device), ACPI_AC_CLASS); + device->driver_data = ac; result = acpi_ac_get_state(ac); if (result) goto end; - ac->charger.name = acpi_device_bid(adev); + ac->charger.name = acpi_device_bid(device); ac->charger.type = POWER_SUPPLY_TYPE_MAINS; ac->charger.properties = ac_props; ac->charger.num_properties = ARRAY_SIZE(ac_props); ac->charger.get_property = get_ac_property; - result = power_supply_register(&pdev->dev, &ac->charger); + result = power_supply_register(&ac->device->dev, &ac->charger); if (result) goto end; - result = acpi_install_notify_handler(ACPI_HANDLE(&pdev->dev), - ACPI_ALL_NOTIFY, acpi_ac_notify_handler, ac); - if (result) { - power_supply_unregister(&ac->charger); - goto end; - } printk(KERN_INFO PREFIX "%s [%s] (%s)\n", - acpi_device_name(adev), acpi_device_bid(adev), + acpi_device_name(device), acpi_device_bid(device), ac->state ? "on-line" : "off-line"); ac->battery_nb.notifier_call = acpi_ac_battery_notify; @@ -256,7 +274,7 @@ static int acpi_ac_resume(struct device *dev) if (!dev) return -EINVAL; - ac = platform_get_drvdata(to_platform_device(dev)); + ac = acpi_driver_data(to_acpi_device(dev)); if (!ac) return -EINVAL; @@ -270,19 +288,17 @@ static int acpi_ac_resume(struct device *dev) #else #define acpi_ac_resume NULL #endif -static SIMPLE_DEV_PM_OPS(acpi_ac_pm_ops, NULL, acpi_ac_resume); -static int acpi_ac_remove(struct platform_device *pdev) +static int acpi_ac_remove(struct acpi_device *device) { - struct acpi_ac *ac; + struct acpi_ac *ac = NULL; + - if (!pdev) + if (!device || !acpi_driver_data(device)) return -EINVAL; - acpi_remove_notify_handler(ACPI_HANDLE(&pdev->dev), - ACPI_ALL_NOTIFY, acpi_ac_notify_handler); + ac = acpi_driver_data(device); - ac = platform_get_drvdata(pdev); if (ac->charger.dev) power_supply_unregister(&ac->charger); unregister_acpi_notifier(&ac->battery_nb); @@ -292,23 +308,6 @@ static int acpi_ac_remove(struct platform_device *pdev) return 0; } -static const struct acpi_device_id acpi_ac_match[] = { - { "ACPI0003", 0 }, - { } -}; -MODULE_DEVICE_TABLE(acpi, acpi_ac_match); - -static struct platform_driver acpi_ac_driver = { - .probe = acpi_ac_probe, - .remove = acpi_ac_remove, - .driver = { - .name = "acpi-ac", - .owner = THIS_MODULE, - .pm = &acpi_ac_pm_ops, - .acpi_match_table = ACPI_PTR(acpi_ac_match), - }, -}; - static int __init acpi_ac_init(void) { int result; @@ -316,7 +315,7 @@ static int __init acpi_ac_init(void) if (acpi_disabled) return -ENODEV; - result = platform_driver_register(&acpi_ac_driver); + result = acpi_bus_register_driver(&acpi_ac_driver); if (result < 0) return -ENODEV; @@ -325,7 +324,7 @@ static int __init acpi_ac_init(void) static void __exit acpi_ac_exit(void) { - platform_driver_unregister(&acpi_ac_driver); + acpi_bus_unregister_driver(&acpi_ac_driver); } module_init(acpi_ac_init); module_exit(acpi_ac_exit); diff --git a/drivers/acpi/acpi_platform.c b/drivers/acpi/acpi_platform.c index dbfe49e5fd63..1d4950388fa1 100644 --- a/drivers/acpi/acpi_platform.c +++ b/drivers/acpi/acpi_platform.c @@ -29,7 +29,6 @@ ACPI_MODULE_NAME("platform"); static const struct acpi_device_id acpi_platform_device_ids[] = { { "PNP0D40" }, - { "ACPI0003" }, { "VPC2004" }, { "BCM4752" }, -- cgit v1.2.3 From f10f383d8414bfe3357e24432ed8a26eeb58ffb8 Mon Sep 17 00:00:00 2001 From: Feng Tang Date: Thu, 24 Apr 2014 16:18:17 +0800 Subject: x86/hpet: Make boot_hpet_disable extern HPET on some platform has accuracy problem. Making "boot_hpet_disable" extern so that we can runtime disable the HPET timer by using quirk to check the platform. Signed-off-by: Feng Tang Cc: Clemens Ladisch Cc: John Stultz Cc: Linus Torvalds Link: http://lkml.kernel.org/r/1398327498-13163-1-git-send-email-feng.tang@intel.com Signed-off-by: Ingo Molnar --- arch/x86/include/asm/hpet.h | 1 + arch/x86/kernel/hpet.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/hpet.h b/arch/x86/include/asm/hpet.h index b18df579c0e9..36f7125945e3 100644 --- a/arch/x86/include/asm/hpet.h +++ b/arch/x86/include/asm/hpet.h @@ -63,6 +63,7 @@ /* hpet memory map physical address */ extern unsigned long hpet_address; extern unsigned long force_hpet_address; +extern int boot_hpet_disable; extern u8 hpet_blockid; extern int hpet_force_user; extern u8 hpet_msi_disable; diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index 8d80ae011603..4177bfbc80b0 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c @@ -88,7 +88,7 @@ static inline void hpet_clear_mapping(void) /* * HPET command line enable / disable */ -static int boot_hpet_disable; +int boot_hpet_disable; int hpet_force_user; static int hpet_verbose; -- cgit v1.2.3 From 62187910b0fc7a75cfec9c30fda58ce2f39d689b Mon Sep 17 00:00:00 2001 From: Feng Tang Date: Thu, 24 Apr 2014 16:18:18 +0800 Subject: x86/intel: Add quirk to disable HPET for the Baytrail platform HPET on current Baytrail platform has accuracy problem to be used as reliable clocksource/clockevent, so add a early quirk to disable it. Signed-off-by: Feng Tang Cc: Clemens Ladisch Cc: John Stultz Cc: Linus Torvalds Link: http://lkml.kernel.org/r/1398327498-13163-2-git-send-email-feng.tang@intel.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/early-quirks.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c index 6e2537c32190..6cda0baeac9d 100644 --- a/arch/x86/kernel/early-quirks.c +++ b/arch/x86/kernel/early-quirks.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -530,6 +531,15 @@ static void __init intel_graphics_stolen(int num, int slot, int func) } } +static void __init force_disable_hpet(int num, int slot, int func) +{ +#ifdef CONFIG_HPET_TIMER + boot_hpet_disable = 1; + pr_info("x86/hpet: Will disable the HPET for this platform because it's not reliable\n"); +#endif +} + + #define QFLAG_APPLY_ONCE 0x1 #define QFLAG_APPLIED 0x2 #define QFLAG_DONE (QFLAG_APPLY_ONCE|QFLAG_APPLIED) @@ -567,6 +577,12 @@ static struct chipset early_qrk[] __initdata = { PCI_BASE_CLASS_BRIDGE, 0, intel_remapping_check }, { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA, PCI_ANY_ID, QFLAG_APPLY_ONCE, intel_graphics_stolen }, + /* + * HPET on current version of Baytrail platform has accuracy + * problems, disable it for now: + */ + { PCI_VENDOR_ID_INTEL, 0x0f00, + PCI_CLASS_BRIDGE_HOST, PCI_ANY_ID, 0, force_disable_hpet}, {} }; -- cgit v1.2.3 From 98fcc5762dcecbb264fa4af5a9ae51136858e299 Mon Sep 17 00:00:00 2001 From: Micky Ching Date: Tue, 29 Apr 2014 09:54:54 +0800 Subject: mmc: rtsx: Revert "mmc: rtsx: add support for pre_req and post_req" This reverts commit c42deffd5b53c9e583d83c7964854ede2f12410d. commit did use mutex_unlock() in tasklet, but mutex_unlock() can't be used in tasklet(atomic context). The driver needs to use mutex to avoid concurrency, so we can't use tasklet here, the patch need to be removed. The spinlock host->lock and pcr->lock may deadlock, one way to solve the deadlock is remove host->lock in sd_isr_done_transfer(), but if using workqueue the we can avoid using the spinlock and also avoid the problem. Signed-off-by: Micky Ching Acked-by: Ulf Hansson Signed-off-by: Lee Jones --- drivers/mfd/rtsx_pcr.c | 132 ++++-------- drivers/mmc/host/rtsx_pci_sdmmc.c | 418 +++++++------------------------------- include/linux/mfd/rtsx_common.h | 1 - include/linux/mfd/rtsx_pci.h | 6 - 4 files changed, 109 insertions(+), 448 deletions(-) diff --git a/drivers/mfd/rtsx_pcr.c b/drivers/mfd/rtsx_pcr.c index c9de3d598ea5..1d15735f9ef9 100644 --- a/drivers/mfd/rtsx_pcr.c +++ b/drivers/mfd/rtsx_pcr.c @@ -338,28 +338,58 @@ int rtsx_pci_transfer_data(struct rtsx_pcr *pcr, struct scatterlist *sglist, int num_sg, bool read, int timeout) { struct completion trans_done; - int err = 0, count; + u8 dir; + int err = 0, i, count; long timeleft; unsigned long flags; + struct scatterlist *sg; + enum dma_data_direction dma_dir; + u32 val; + dma_addr_t addr; + unsigned int len; + + dev_dbg(&(pcr->pci->dev), "--> %s: num_sg = %d\n", __func__, num_sg); + + /* don't transfer data during abort processing */ + if (pcr->remove_pci) + return -EINVAL; + + if ((sglist == NULL) || (num_sg <= 0)) + return -EINVAL; - count = rtsx_pci_dma_map_sg(pcr, sglist, num_sg, read); + if (read) { + dir = DEVICE_TO_HOST; + dma_dir = DMA_FROM_DEVICE; + } else { + dir = HOST_TO_DEVICE; + dma_dir = DMA_TO_DEVICE; + } + + count = dma_map_sg(&(pcr->pci->dev), sglist, num_sg, dma_dir); if (count < 1) { dev_err(&(pcr->pci->dev), "scatterlist map failed\n"); return -EINVAL; } dev_dbg(&(pcr->pci->dev), "DMA mapping count: %d\n", count); + val = ((u32)(dir & 0x01) << 29) | TRIG_DMA | ADMA_MODE; + pcr->sgi = 0; + for_each_sg(sglist, sg, count, i) { + addr = sg_dma_address(sg); + len = sg_dma_len(sg); + rtsx_pci_add_sg_tbl(pcr, addr, len, i == count - 1); + } spin_lock_irqsave(&pcr->lock, flags); pcr->done = &trans_done; pcr->trans_result = TRANS_NOT_READY; init_completion(&trans_done); + rtsx_pci_writel(pcr, RTSX_HDBAR, pcr->host_sg_tbl_addr); + rtsx_pci_writel(pcr, RTSX_HDBCTLR, val); spin_unlock_irqrestore(&pcr->lock, flags); - rtsx_pci_dma_transfer(pcr, sglist, count, read); - timeleft = wait_for_completion_interruptible_timeout( &trans_done, msecs_to_jiffies(timeout)); if (timeleft <= 0) { @@ -383,7 +413,7 @@ out: pcr->done = NULL; spin_unlock_irqrestore(&pcr->lock, flags); - rtsx_pci_dma_unmap_sg(pcr, sglist, num_sg, read); + dma_unmap_sg(&(pcr->pci->dev), sglist, num_sg, dma_dir); if ((err < 0) && (err != -ENODEV)) rtsx_pci_stop_cmd(pcr); @@ -395,73 +425,6 @@ out: } EXPORT_SYMBOL_GPL(rtsx_pci_transfer_data); -int rtsx_pci_dma_map_sg(struct rtsx_pcr *pcr, struct scatterlist *sglist, - int num_sg, bool read) -{ - enum dma_data_direction dir = read ? DMA_FROM_DEVICE : DMA_TO_DEVICE; - - if (pcr->remove_pci) - return -EINVAL; - - if ((sglist == NULL) || num_sg < 1) - return -EINVAL; - - return dma_map_sg(&(pcr->pci->dev), sglist, num_sg, dir); -} -EXPORT_SYMBOL_GPL(rtsx_pci_dma_map_sg); - -int rtsx_pci_dma_unmap_sg(struct rtsx_pcr *pcr, struct scatterlist *sglist, - int num_sg, bool read) -{ - enum dma_data_direction dir = read ? DMA_FROM_DEVICE : DMA_TO_DEVICE; - - if (pcr->remove_pci) - return -EINVAL; - - if (sglist == NULL || num_sg < 1) - return -EINVAL; - - dma_unmap_sg(&(pcr->pci->dev), sglist, num_sg, dir); - return num_sg; -} -EXPORT_SYMBOL_GPL(rtsx_pci_dma_unmap_sg); - -int rtsx_pci_dma_transfer(struct rtsx_pcr *pcr, struct scatterlist *sglist, - int sg_count, bool read) -{ - struct scatterlist *sg; - dma_addr_t addr; - unsigned int len; - int i; - u32 val; - u8 dir = read ? DEVICE_TO_HOST : HOST_TO_DEVICE; - unsigned long flags; - - if (pcr->remove_pci) - return -EINVAL; - - if ((sglist == NULL) || (sg_count < 1)) - return -EINVAL; - - val = ((u32)(dir & 0x01) << 29) | TRIG_DMA | ADMA_MODE; - pcr->sgi = 0; - for_each_sg(sglist, sg, sg_count, i) { - addr = sg_dma_address(sg); - len = sg_dma_len(sg); - rtsx_pci_add_sg_tbl(pcr, addr, len, i == sg_count - 1); - } - - spin_lock_irqsave(&pcr->lock, flags); - - rtsx_pci_writel(pcr, RTSX_HDBAR, pcr->host_sg_tbl_addr); - rtsx_pci_writel(pcr, RTSX_HDBCTLR, val); - - spin_unlock_irqrestore(&pcr->lock, flags); - - return 0; -} -EXPORT_SYMBOL_GPL(rtsx_pci_dma_transfer); - int rtsx_pci_read_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len) { int err; @@ -873,8 +836,6 @@ static irqreturn_t rtsx_pci_isr(int irq, void *dev_id) int_reg = rtsx_pci_readl(pcr, RTSX_BIPR); /* Clear interrupt flag */ rtsx_pci_writel(pcr, RTSX_BIPR, int_reg); - dev_dbg(&pcr->pci->dev, "=========== BIPR 0x%8x ==========\n", int_reg); - if ((int_reg & pcr->bier) == 0) { spin_unlock(&pcr->lock); return IRQ_NONE; @@ -905,28 +866,17 @@ static irqreturn_t rtsx_pci_isr(int irq, void *dev_id) } if (int_reg & (NEED_COMPLETE_INT | DELINK_INT)) { - if (int_reg & (TRANS_FAIL_INT | DELINK_INT)) + if (int_reg & (TRANS_FAIL_INT | DELINK_INT)) { pcr->trans_result = TRANS_RESULT_FAIL; - else if (int_reg & TRANS_OK_INT) + if (pcr->done) + complete(pcr->done); + } else if (int_reg & TRANS_OK_INT) { pcr->trans_result = TRANS_RESULT_OK; - - if (pcr->done) - complete(pcr->done); - - if (int_reg & SD_EXIST) { - struct rtsx_slot *slot = &pcr->slots[RTSX_SD_CARD]; - if (slot && slot->done_transfer) - slot->done_transfer(slot->p_dev); - } - - if (int_reg & MS_EXIST) { - struct rtsx_slot *slot = &pcr->slots[RTSX_SD_CARD]; - if (slot && slot->done_transfer) - slot->done_transfer(slot->p_dev); + if (pcr->done) + complete(pcr->done); } } - if (pcr->card_inserted || pcr->card_removed) schedule_delayed_work(&pcr->carddet_work, msecs_to_jiffies(200)); diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c index 5fb994f9a653..0b9ded13a3ae 100644 --- a/drivers/mmc/host/rtsx_pci_sdmmc.c +++ b/drivers/mmc/host/rtsx_pci_sdmmc.c @@ -31,28 +31,14 @@ #include #include -struct realtek_next { - unsigned int sg_count; - s32 cookie; -}; - struct realtek_pci_sdmmc { struct platform_device *pdev; struct rtsx_pcr *pcr; struct mmc_host *mmc; struct mmc_request *mrq; - struct mmc_command *cmd; - struct mmc_data *data; - - spinlock_t lock; - struct timer_list timer; - struct tasklet_struct cmd_tasklet; - struct tasklet_struct data_tasklet; - struct tasklet_struct finish_tasklet; - - u8 rsp_type; - u8 rsp_len; - int sg_count; + + struct mutex host_mutex; + u8 ssc_depth; unsigned int clock; bool vpclk; @@ -62,13 +48,8 @@ struct realtek_pci_sdmmc { int power_state; #define SDMMC_POWER_ON 1 #define SDMMC_POWER_OFF 0 - - struct realtek_next next_data; }; -static int sd_start_multi_rw(struct realtek_pci_sdmmc *host, - struct mmc_request *mrq); - static inline struct device *sdmmc_dev(struct realtek_pci_sdmmc *host) { return &(host->pdev->dev); @@ -105,95 +86,6 @@ static void sd_print_debug_regs(struct realtek_pci_sdmmc *host) #define sd_print_debug_regs(host) #endif /* DEBUG */ -static void sd_isr_done_transfer(struct platform_device *pdev) -{ - struct realtek_pci_sdmmc *host = platform_get_drvdata(pdev); - - spin_lock(&host->lock); - if (host->cmd) - tasklet_schedule(&host->cmd_tasklet); - if (host->data) - tasklet_schedule(&host->data_tasklet); - spin_unlock(&host->lock); -} - -static void sd_request_timeout(unsigned long host_addr) -{ - struct realtek_pci_sdmmc *host = (struct realtek_pci_sdmmc *)host_addr; - unsigned long flags; - - spin_lock_irqsave(&host->lock, flags); - - if (!host->mrq) { - dev_err(sdmmc_dev(host), "error: no request exist\n"); - goto out; - } - - if (host->cmd) - host->cmd->error = -ETIMEDOUT; - if (host->data) - host->data->error = -ETIMEDOUT; - - dev_dbg(sdmmc_dev(host), "timeout for request\n"); - -out: - tasklet_schedule(&host->finish_tasklet); - spin_unlock_irqrestore(&host->lock, flags); -} - -static void sd_finish_request(unsigned long host_addr) -{ - struct realtek_pci_sdmmc *host = (struct realtek_pci_sdmmc *)host_addr; - struct rtsx_pcr *pcr = host->pcr; - struct mmc_request *mrq; - struct mmc_command *cmd; - struct mmc_data *data; - unsigned long flags; - bool any_error; - - spin_lock_irqsave(&host->lock, flags); - - del_timer(&host->timer); - mrq = host->mrq; - if (!mrq) { - dev_err(sdmmc_dev(host), "error: no request need finish\n"); - goto out; - } - - cmd = mrq->cmd; - data = mrq->data; - - any_error = (mrq->sbc && mrq->sbc->error) || - (mrq->stop && mrq->stop->error) || - (cmd && cmd->error) || (data && data->error); - - if (any_error) { - rtsx_pci_stop_cmd(pcr); - sd_clear_error(host); - } - - if (data) { - if (any_error) - data->bytes_xfered = 0; - else - data->bytes_xfered = data->blocks * data->blksz; - - if (!data->host_cookie) - rtsx_pci_dma_unmap_sg(pcr, data->sg, data->sg_len, - data->flags & MMC_DATA_READ); - - } - - host->mrq = NULL; - host->cmd = NULL; - host->data = NULL; - -out: - spin_unlock_irqrestore(&host->lock, flags); - mutex_unlock(&pcr->pcr_mutex); - mmc_request_done(host->mmc, mrq); -} - static int sd_read_data(struct realtek_pci_sdmmc *host, u8 *cmd, u16 byte_cnt, u8 *buf, int buf_len, int timeout) { @@ -311,7 +203,8 @@ static int sd_write_data(struct realtek_pci_sdmmc *host, u8 *cmd, u16 byte_cnt, return 0; } -static void sd_send_cmd(struct realtek_pci_sdmmc *host, struct mmc_command *cmd) +static void sd_send_cmd_get_rsp(struct realtek_pci_sdmmc *host, + struct mmc_command *cmd) { struct rtsx_pcr *pcr = host->pcr; u8 cmd_idx = (u8)cmd->opcode; @@ -319,14 +212,11 @@ static void sd_send_cmd(struct realtek_pci_sdmmc *host, struct mmc_command *cmd) int err = 0; int timeout = 100; int i; + u8 *ptr; + int stat_idx = 0; u8 rsp_type; int rsp_len = 5; - unsigned long flags; - - if (host->cmd) - dev_err(sdmmc_dev(host), "error: cmd already exist\n"); - - host->cmd = cmd; + bool clock_toggled = false; dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD %d, arg = 0x%08x\n", __func__, cmd_idx, arg); @@ -361,8 +251,6 @@ static void sd_send_cmd(struct realtek_pci_sdmmc *host, struct mmc_command *cmd) err = -EINVAL; goto out; } - host->rsp_type = rsp_type; - host->rsp_len = rsp_len; if (rsp_type == SD_RSP_TYPE_R1b) timeout = 3000; @@ -372,6 +260,8 @@ static void sd_send_cmd(struct realtek_pci_sdmmc *host, struct mmc_command *cmd) 0xFF, SD_CLK_TOGGLE_EN); if (err < 0) goto out; + + clock_toggled = true; } rtsx_pci_init_cmd(pcr); @@ -395,60 +285,25 @@ static void sd_send_cmd(struct realtek_pci_sdmmc *host, struct mmc_command *cmd) /* Read data from ping-pong buffer */ for (i = PPBUF_BASE2; i < PPBUF_BASE2 + 16; i++) rtsx_pci_add_cmd(pcr, READ_REG_CMD, (u16)i, 0, 0); + stat_idx = 16; } else if (rsp_type != SD_RSP_TYPE_R0) { /* Read data from SD_CMDx registers */ for (i = SD_CMD0; i <= SD_CMD4; i++) rtsx_pci_add_cmd(pcr, READ_REG_CMD, (u16)i, 0, 0); + stat_idx = 5; } rtsx_pci_add_cmd(pcr, READ_REG_CMD, SD_STAT1, 0, 0); - mod_timer(&host->timer, jiffies + msecs_to_jiffies(timeout)); - - spin_lock_irqsave(&pcr->lock, flags); - pcr->trans_result = TRANS_NOT_READY; - rtsx_pci_send_cmd_no_wait(pcr); - spin_unlock_irqrestore(&pcr->lock, flags); - - return; - -out: - cmd->error = err; - tasklet_schedule(&host->finish_tasklet); -} - -static void sd_get_rsp(unsigned long host_addr) -{ - struct realtek_pci_sdmmc *host = (struct realtek_pci_sdmmc *)host_addr; - struct rtsx_pcr *pcr = host->pcr; - struct mmc_command *cmd; - int i, err = 0, stat_idx; - u8 *ptr, rsp_type; - unsigned long flags; - - spin_lock_irqsave(&host->lock, flags); - - cmd = host->cmd; - host->cmd = NULL; - - if (!cmd) { - dev_err(sdmmc_dev(host), "error: cmd not exist\n"); + err = rtsx_pci_send_cmd(pcr, timeout); + if (err < 0) { + sd_print_debug_regs(host); + sd_clear_error(host); + dev_dbg(sdmmc_dev(host), + "rtsx_pci_send_cmd error (err = %d)\n", err); goto out; } - spin_lock(&pcr->lock); - if (pcr->trans_result == TRANS_NO_DEVICE) - err = -ENODEV; - else if (pcr->trans_result != TRANS_RESULT_OK) - err = -EINVAL; - spin_unlock(&pcr->lock); - - if (err < 0) - goto out; - - rsp_type = host->rsp_type; - stat_idx = host->rsp_len; - if (rsp_type == SD_RSP_TYPE_R0) { err = 0; goto out; @@ -485,106 +340,26 @@ static void sd_get_rsp(unsigned long host_addr) cmd->resp[0]); } - if (cmd == host->mrq->sbc) { - sd_send_cmd(host, host->mrq->cmd); - spin_unlock_irqrestore(&host->lock, flags); - return; - } - - if (cmd == host->mrq->stop) - goto out; - - if (cmd->data) { - sd_start_multi_rw(host, host->mrq); - spin_unlock_irqrestore(&host->lock, flags); - return; - } - out: cmd->error = err; - tasklet_schedule(&host->finish_tasklet); - spin_unlock_irqrestore(&host->lock, flags); -} - -static int sd_pre_dma_transfer(struct realtek_pci_sdmmc *host, - struct mmc_data *data, struct realtek_next *next) -{ - struct rtsx_pcr *pcr = host->pcr; - int read = data->flags & MMC_DATA_READ; - int sg_count = 0; - - if (!next && data->host_cookie && - data->host_cookie != host->next_data.cookie) { - dev_err(sdmmc_dev(host), - "error: invalid cookie data[%d] host[%d]\n", - data->host_cookie, host->next_data.cookie); - data->host_cookie = 0; - } - - if (next || (!next && data->host_cookie != host->next_data.cookie)) - sg_count = rtsx_pci_dma_map_sg(pcr, - data->sg, data->sg_len, read); - else - sg_count = host->next_data.sg_count; - - if (next) { - next->sg_count = sg_count; - if (++next->cookie < 0) - next->cookie = 1; - data->host_cookie = next->cookie; - } - - return sg_count; -} - -static void sdmmc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq, - bool is_first_req) -{ - struct realtek_pci_sdmmc *host = mmc_priv(mmc); - struct mmc_data *data = mrq->data; - - if (data->host_cookie) { - dev_err(sdmmc_dev(host), - "error: descard already cookie data[%d]\n", - data->host_cookie); - data->host_cookie = 0; - } - - dev_dbg(sdmmc_dev(host), "dma sg prepared: %d\n", - sd_pre_dma_transfer(host, data, &host->next_data)); -} - -static void sdmmc_post_req(struct mmc_host *mmc, struct mmc_request *mrq, - int err) -{ - struct realtek_pci_sdmmc *host = mmc_priv(mmc); - struct rtsx_pcr *pcr = host->pcr; - struct mmc_data *data = mrq->data; - int read = data->flags & MMC_DATA_READ; - - rtsx_pci_dma_unmap_sg(pcr, data->sg, data->sg_len, read); - data->host_cookie = 0; + if (err && clock_toggled) + rtsx_pci_write_register(pcr, SD_BUS_STAT, + SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0); } -static int sd_start_multi_rw(struct realtek_pci_sdmmc *host, - struct mmc_request *mrq) +static int sd_rw_multi(struct realtek_pci_sdmmc *host, struct mmc_request *mrq) { struct rtsx_pcr *pcr = host->pcr; struct mmc_host *mmc = host->mmc; struct mmc_card *card = mmc->card; struct mmc_data *data = mrq->data; int uhs = mmc_card_uhs(card); - int read = data->flags & MMC_DATA_READ; + int read = (data->flags & MMC_DATA_READ) ? 1 : 0; u8 cfg2, trans_mode; int err; size_t data_len = data->blksz * data->blocks; - if (host->data) - dev_err(sdmmc_dev(host), "error: data already exist\n"); - - host->data = data; - if (read) { cfg2 = SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_0; @@ -635,54 +410,15 @@ static int sd_start_multi_rw(struct realtek_pci_sdmmc *host, rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, SD_TRANSFER, SD_TRANSFER_END, SD_TRANSFER_END); - mod_timer(&host->timer, jiffies + 10 * HZ); rtsx_pci_send_cmd_no_wait(pcr); - err = rtsx_pci_dma_transfer(pcr, data->sg, host->sg_count, read); - if (err < 0) { - data->error = err; - tasklet_schedule(&host->finish_tasklet); - } - return 0; -} - -static void sd_finish_multi_rw(unsigned long host_addr) -{ - struct realtek_pci_sdmmc *host = (struct realtek_pci_sdmmc *)host_addr; - struct rtsx_pcr *pcr = host->pcr; - struct mmc_data *data; - int err = 0; - unsigned long flags; - - spin_lock_irqsave(&host->lock, flags); - - if (!host->data) { - dev_err(sdmmc_dev(host), "error: no data exist\n"); - goto out; - } - - data = host->data; - host->data = NULL; - - if (pcr->trans_result == TRANS_NO_DEVICE) - err = -ENODEV; - else if (pcr->trans_result != TRANS_RESULT_OK) - err = -EINVAL; - + err = rtsx_pci_transfer_data(pcr, data->sg, data->sg_len, read, 10000); if (err < 0) { - data->error = err; - goto out; - } - - if (!host->mrq->sbc && data->stop) { - sd_send_cmd(host, data->stop); - spin_unlock_irqrestore(&host->lock, flags); - return; + sd_clear_error(host); + return err; } -out: - tasklet_schedule(&host->finish_tasklet); - spin_unlock_irqrestore(&host->lock, flags); + return 0; } static inline void sd_enable_initial_mode(struct realtek_pci_sdmmc *host) @@ -901,13 +637,6 @@ static int sd_tuning_rx(struct realtek_pci_sdmmc *host, u8 opcode) return 0; } -static inline bool sd_use_muti_rw(struct mmc_command *cmd) -{ - return mmc_op_multi(cmd->opcode) || - (cmd->opcode == MMC_READ_SINGLE_BLOCK) || - (cmd->opcode == MMC_WRITE_BLOCK); -} - static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq) { struct realtek_pci_sdmmc *host = mmc_priv(mmc); @@ -916,14 +645,6 @@ static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq) struct mmc_data *data = mrq->data; unsigned int data_size = 0; int err; - unsigned long flags; - - mutex_lock(&pcr->pcr_mutex); - spin_lock_irqsave(&host->lock, flags); - - if (host->mrq) - dev_err(sdmmc_dev(host), "error: request already exist\n"); - host->mrq = mrq; if (host->eject) { cmd->error = -ENOMEDIUM; @@ -936,6 +657,8 @@ static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq) goto finish; } + mutex_lock(&pcr->pcr_mutex); + rtsx_pci_start_run(pcr); rtsx_pci_switch_clock(pcr, host->clock, host->ssc_depth, @@ -944,28 +667,46 @@ static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq) rtsx_pci_write_register(pcr, CARD_SHARE_MODE, CARD_SHARE_MASK, CARD_SHARE_48_SD); + mutex_lock(&host->host_mutex); + host->mrq = mrq; + mutex_unlock(&host->host_mutex); + if (mrq->data) data_size = data->blocks * data->blksz; - if (sd_use_muti_rw(cmd)) - host->sg_count = sd_pre_dma_transfer(host, data, NULL); + if (!data_size || mmc_op_multi(cmd->opcode) || + (cmd->opcode == MMC_READ_SINGLE_BLOCK) || + (cmd->opcode == MMC_WRITE_BLOCK)) { + sd_send_cmd_get_rsp(host, cmd); - if (!data_size || sd_use_muti_rw(cmd)) { - if (mrq->sbc) - sd_send_cmd(host, mrq->sbc); - else - sd_send_cmd(host, cmd); - spin_unlock_irqrestore(&host->lock, flags); + if (!cmd->error && data_size) { + sd_rw_multi(host, mrq); + + if (mmc_op_multi(cmd->opcode) && mrq->stop) + sd_send_cmd_get_rsp(host, mrq->stop); + } } else { - spin_unlock_irqrestore(&host->lock, flags); sd_normal_rw(host, mrq); - tasklet_schedule(&host->finish_tasklet); } - return; + + if (mrq->data) { + if (cmd->error || data->error) + data->bytes_xfered = 0; + else + data->bytes_xfered = data->blocks * data->blksz; + } + + mutex_unlock(&pcr->pcr_mutex); finish: - tasklet_schedule(&host->finish_tasklet); - spin_unlock_irqrestore(&host->lock, flags); + if (cmd->error) + dev_dbg(sdmmc_dev(host), "cmd->error = %d\n", cmd->error); + + mutex_lock(&host->host_mutex); + host->mrq = NULL; + mutex_unlock(&host->host_mutex); + + mmc_request_done(mmc, mrq); } static int sd_set_bus_width(struct realtek_pci_sdmmc *host, @@ -1400,8 +1141,6 @@ out: } static const struct mmc_host_ops realtek_pci_sdmmc_ops = { - .pre_req = sdmmc_pre_req, - .post_req = sdmmc_post_req, .request = sdmmc_request, .set_ios = sdmmc_set_ios, .get_ro = sdmmc_get_ro, @@ -1465,7 +1204,6 @@ static int rtsx_pci_sdmmc_drv_probe(struct platform_device *pdev) struct realtek_pci_sdmmc *host; struct rtsx_pcr *pcr; struct pcr_handle *handle = pdev->dev.platform_data; - unsigned long host_addr; if (!handle) return -ENXIO; @@ -1489,15 +1227,8 @@ static int rtsx_pci_sdmmc_drv_probe(struct platform_device *pdev) pcr->slots[RTSX_SD_CARD].p_dev = pdev; pcr->slots[RTSX_SD_CARD].card_event = rtsx_pci_sdmmc_card_event; - host_addr = (unsigned long)host; - host->next_data.cookie = 1; - setup_timer(&host->timer, sd_request_timeout, host_addr); - tasklet_init(&host->cmd_tasklet, sd_get_rsp, host_addr); - tasklet_init(&host->data_tasklet, sd_finish_multi_rw, host_addr); - tasklet_init(&host->finish_tasklet, sd_finish_request, host_addr); - spin_lock_init(&host->lock); + mutex_init(&host->host_mutex); - pcr->slots[RTSX_SD_CARD].done_transfer = sd_isr_done_transfer; realtek_init_host(host); mmc_add_host(mmc); @@ -1510,8 +1241,6 @@ static int rtsx_pci_sdmmc_drv_remove(struct platform_device *pdev) struct realtek_pci_sdmmc *host = platform_get_drvdata(pdev); struct rtsx_pcr *pcr; struct mmc_host *mmc; - struct mmc_request *mrq; - unsigned long flags; if (!host) return 0; @@ -1519,33 +1248,22 @@ static int rtsx_pci_sdmmc_drv_remove(struct platform_device *pdev) pcr = host->pcr; pcr->slots[RTSX_SD_CARD].p_dev = NULL; pcr->slots[RTSX_SD_CARD].card_event = NULL; - pcr->slots[RTSX_SD_CARD].done_transfer = NULL; mmc = host->mmc; - mrq = host->mrq; - spin_lock_irqsave(&host->lock, flags); + mutex_lock(&host->host_mutex); if (host->mrq) { dev_dbg(&(pdev->dev), "%s: Controller removed during transfer\n", mmc_hostname(mmc)); - if (mrq->sbc) - mrq->sbc->error = -ENOMEDIUM; - if (mrq->cmd) - mrq->cmd->error = -ENOMEDIUM; - if (mrq->stop) - mrq->stop->error = -ENOMEDIUM; - if (mrq->data) - mrq->data->error = -ENOMEDIUM; + rtsx_pci_complete_unfinished_transfer(pcr); - tasklet_schedule(&host->finish_tasklet); + host->mrq->cmd->error = -ENOMEDIUM; + if (host->mrq->stop) + host->mrq->stop->error = -ENOMEDIUM; + mmc_request_done(mmc, host->mrq); } - spin_unlock_irqrestore(&host->lock, flags); - - del_timer_sync(&host->timer); - tasklet_kill(&host->cmd_tasklet); - tasklet_kill(&host->data_tasklet); - tasklet_kill(&host->finish_tasklet); + mutex_unlock(&host->host_mutex); mmc_remove_host(mmc); host->eject = true; diff --git a/include/linux/mfd/rtsx_common.h b/include/linux/mfd/rtsx_common.h index 7c36cc55d2c7..443176ee1ab0 100644 --- a/include/linux/mfd/rtsx_common.h +++ b/include/linux/mfd/rtsx_common.h @@ -45,7 +45,6 @@ struct platform_device; struct rtsx_slot { struct platform_device *p_dev; void (*card_event)(struct platform_device *p_dev); - void (*done_transfer)(struct platform_device *p_dev); }; #endif diff --git a/include/linux/mfd/rtsx_pci.h b/include/linux/mfd/rtsx_pci.h index 8d6bbd609ad9..a3835976f7c6 100644 --- a/include/linux/mfd/rtsx_pci.h +++ b/include/linux/mfd/rtsx_pci.h @@ -943,12 +943,6 @@ void rtsx_pci_send_cmd_no_wait(struct rtsx_pcr *pcr); int rtsx_pci_send_cmd(struct rtsx_pcr *pcr, int timeout); int rtsx_pci_transfer_data(struct rtsx_pcr *pcr, struct scatterlist *sglist, int num_sg, bool read, int timeout); -int rtsx_pci_dma_map_sg(struct rtsx_pcr *pcr, struct scatterlist *sglist, - int num_sg, bool read); -int rtsx_pci_dma_unmap_sg(struct rtsx_pcr *pcr, struct scatterlist *sglist, - int num_sg, bool read); -int rtsx_pci_dma_transfer(struct rtsx_pcr *pcr, struct scatterlist *sglist, - int sg_count, bool read); int rtsx_pci_read_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len); int rtsx_pci_write_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len); int rtsx_pci_card_pull_ctl_enable(struct rtsx_pcr *pcr, int card); -- cgit v1.2.3 From 0b9d46dd7debf8e6dc8614106f1c1909fa8de64d Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Mon, 5 May 2014 22:49:49 +0200 Subject: ACPI / processor: do not mark present at boot but not onlined CPU as onlined acpi_processor_add() assumes that present at boot CPUs are always onlined, it is not so if a CPU failed to become onlined. As result acpi_processor_add() will mark such CPU device as onlined in sysfs and following attempts to online/offline it using /sys/device/system/cpu/cpuX/online attribute will fail. Do not poke into device internals in acpi_processor_add() and touch "struct device { .offline }" attribute, since for CPUs onlined at boot it's set by: topology_init() -> arch_register_cpu() -> register_cpu() before ACPI device tree is parsed, and for hotplugged CPUs it's set when userspace onlines CPU via sysfs. Signed-off-by: Igor Mammedov Acked-by: Toshi Kani Cc: 3.11+ # 3.11+ Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_processor.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c index b06f5f55ada9..52c81c49cc7d 100644 --- a/drivers/acpi/acpi_processor.c +++ b/drivers/acpi/acpi_processor.c @@ -405,7 +405,6 @@ static int acpi_processor_add(struct acpi_device *device, goto err; pr->dev = dev; - dev->offline = pr->flags.need_hotplug_init; /* Trigger the processor driver's .probe() if present. */ if (device_attach(dev) >= 0) -- cgit v1.2.3 From 098507ae3ec2331476fb52e85d4040c1cc6d0ef4 Mon Sep 17 00:00:00 2001 From: Romain Izard Date: Tue, 4 Mar 2014 10:09:39 +0100 Subject: trace: module: Maintain a valid user count The replacement of the 'count' variable by two variables 'incs' and 'decs' to resolve some race conditions during module unloading was done in parallel with some cleanup in the trace subsystem, and was integrated as a merge. Unfortunately, the formula for this replacement was wrong in the tracing code, and the refcount in the traces was not usable as a result. Use 'count = incs - decs' to compute the user count. Link: http://lkml.kernel.org/p/1393924179-9147-1-git-send-email-romain.izard.pro@gmail.com Acked-by: Ingo Molnar Cc: Rusty Russell Cc: Frederic Weisbecker Cc: stable@vger.kernel.org # 2.6.35 Fixes: c1ab9cab7509 "merge conflict resolution" Signed-off-by: Romain Izard Signed-off-by: Steven Rostedt --- include/trace/events/module.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/trace/events/module.h b/include/trace/events/module.h index 11fd51b413de..daa60c739456 100644 --- a/include/trace/events/module.h +++ b/include/trace/events/module.h @@ -80,7 +80,7 @@ DECLARE_EVENT_CLASS(module_refcnt, TP_fast_assign( __entry->ip = ip; - __entry->refcnt = __this_cpu_read(mod->refptr->incs) + __this_cpu_read(mod->refptr->decs); + __entry->refcnt = __this_cpu_read(mod->refptr->incs) - __this_cpu_read(mod->refptr->decs); __assign_str(name, mod->name); ), -- cgit v1.2.3 From 8058bd0faad860e75547cc5cb5d4ade016247a79 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Thu, 8 May 2014 07:47:49 -0400 Subject: tracepoint: Fix use of tracepoint funcs after rcu free Commit de7b2973903c "tracepoint: Use struct pointer instead of name hash for reg/unreg tracepoints" introduces a use after free by calling release_probes on the old struct tracepoint array before the newly allocated array is published with rcu_assign_pointer. There is a race window where tracepoints (RCU readers) can perform a "use-after-grace-period-after-free", which shows up as a GPF in stress-tests. Link: http://lkml.kernel.org/r/53698021.5020108@oracle.com Link: http://lkml.kernel.org/p/1399549669-25465-1-git-send-email-mathieu.desnoyers@efficios.com Reported-by: Sasha Levin CC: Oleg Nesterov CC: Dave Jones Fixes: de7b2973903c "tracepoint: Use struct pointer instead of name hash for reg/unreg tracepoints" Signed-off-by: Mathieu Desnoyers Signed-off-by: Steven Rostedt --- kernel/tracepoint.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/tracepoint.c b/kernel/tracepoint.c index ac5b23cf7212..6620e5837ce2 100644 --- a/kernel/tracepoint.c +++ b/kernel/tracepoint.c @@ -188,7 +188,6 @@ static int tracepoint_add_func(struct tracepoint *tp, WARN_ON_ONCE(1); return PTR_ERR(old); } - release_probes(old); /* * rcu_assign_pointer has a smp_wmb() which makes sure that the new @@ -200,6 +199,7 @@ static int tracepoint_add_func(struct tracepoint *tp, rcu_assign_pointer(tp->funcs, tp_funcs); if (!static_key_enabled(&tp->key)) static_key_slow_inc(&tp->key); + release_probes(old); return 0; } @@ -221,7 +221,6 @@ static int tracepoint_remove_func(struct tracepoint *tp, WARN_ON_ONCE(1); return PTR_ERR(old); } - release_probes(old); if (!tp_funcs) { /* Removed last function */ @@ -232,6 +231,7 @@ static int tracepoint_remove_func(struct tracepoint *tp, static_key_slow_dec(&tp->key); } rcu_assign_pointer(tp->funcs, tp_funcs); + release_probes(old); return 0; } -- cgit v1.2.3 From 3901c1124ec5099254a9396085f7798153a7293f Mon Sep 17 00:00:00 2001 From: Harald Freudenberger Date: Wed, 7 May 2014 16:51:29 +0200 Subject: crypto: s390 - fix aes,des ctr mode concurrency finding. An additional testcase found an issue with the last series of patches applied: the fallback solution may not save the iv value after operation. This very small fix just makes sure the iv is copied back to the walk/desc struct. Cc: # 3.14+ Signed-off-by: Harald Freudenberger Signed-off-by: Herbert Xu --- arch/s390/crypto/aes_s390.c | 3 +++ arch/s390/crypto/des_s390.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/arch/s390/crypto/aes_s390.c b/arch/s390/crypto/aes_s390.c index cf3c0089bef2..23223cd63e54 100644 --- a/arch/s390/crypto/aes_s390.c +++ b/arch/s390/crypto/aes_s390.c @@ -820,6 +820,9 @@ static int ctr_aes_crypt(struct blkcipher_desc *desc, long func, else memcpy(walk->iv, ctrptr, AES_BLOCK_SIZE); spin_unlock(&ctrblk_lock); + } else { + if (!nbytes) + memcpy(walk->iv, ctrptr, AES_BLOCK_SIZE); } /* * final block may be < AES_BLOCK_SIZE, copy only nbytes diff --git a/arch/s390/crypto/des_s390.c b/arch/s390/crypto/des_s390.c index 0a5aac8a9412..7acb77f7ef1a 100644 --- a/arch/s390/crypto/des_s390.c +++ b/arch/s390/crypto/des_s390.c @@ -429,6 +429,9 @@ static int ctr_desall_crypt(struct blkcipher_desc *desc, long func, else memcpy(walk->iv, ctrptr, DES_BLOCK_SIZE); spin_unlock(&ctrblk_lock); + } else { + if (!nbytes) + memcpy(walk->iv, ctrptr, DES_BLOCK_SIZE); } /* final block may be < DES_BLOCK_SIZE, copy only nbytes */ if (nbytes) { -- cgit v1.2.3 From 2af89a3cde1beb88a2c65e0558d828c1a9e4677f Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 8 May 2014 16:56:21 +0200 Subject: ata: pata_at91 only works on sam9 The smc driver used by pata_at91 is at91sam9 specific, so building this driver on another at91 platform results in this error: ERROR: "sam9_smc_configure" [drivers/ata/pata_at91.ko] undefined! ERROR: "sam9_smc_write_mode" [drivers/ata/pata_at91.ko] undefined! ERROR: "sam9_smc_read_mode" [drivers/ata/pata_at91.ko] undefined! This patch changes the Kconfig dependency to ensure it always works. Signed-off-by: Arnd Bergmann Signed-off-by: Tejun Heo Cc: linux-ide@vger.kernel.org Cc: Jean-Christophe Plagniol-Villard Cc: Nicolas Ferre --- drivers/ata/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index c2706047337f..0033fafc470b 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -815,7 +815,7 @@ config PATA_AT32 config PATA_AT91 tristate "PATA support for AT91SAM9260" - depends on ARM && ARCH_AT91 + depends on ARM && SOC_AT91SAM9 help This option enables support for IDE devices on the Atmel AT91SAM9260 SoC. -- cgit v1.2.3 From aa07c713ecfc0522916f3cd57ac628ea6127c0ec Mon Sep 17 00:00:00 2001 From: Kinglong Mee Date: Fri, 18 Apr 2014 20:49:04 +0800 Subject: NFSD: Call ->set_acl with a NULL ACL structure if no entries After setting ACL for directory, I got two problems that caused by the cached zero-length default posix acl. This patch make sure nfsd4_set_nfs4_acl calls ->set_acl with a NULL ACL structure if there are no entries. Thanks for Christoph Hellwig's advice. First problem: ............ hang ........... Second problem: [ 1610.167668] ------------[ cut here ]------------ [ 1610.168320] kernel BUG at /root/nfs/linux/fs/nfsd/nfs4acl.c:239! [ 1610.168320] invalid opcode: 0000 [#1] SMP DEBUG_PAGEALLOC [ 1610.168320] Modules linked in: nfsv4(OE) nfs(OE) nfsd(OE) rpcsec_gss_krb5 fscache ip6t_rpfilter ip6t_REJECT cfg80211 xt_conntrack rfkill ebtable_nat ebtable_broute bridge stp llc ebtable_filter ebtables ip6table_nat nf_conntrack_ipv6 nf_defrag_ipv6 nf_nat_ipv6 ip6table_mangle ip6table_security ip6table_raw ip6table_filter ip6_tables iptable_nat nf_conntrack_ipv4 nf_defrag_ipv4 nf_nat_ipv4 nf_nat nf_conntrack iptable_mangle iptable_security iptable_raw auth_rpcgss nfs_acl snd_intel8x0 ppdev lockd snd_ac97_codec ac97_bus snd_pcm snd_timer e1000 pcspkr parport_pc snd parport serio_raw joydev i2c_piix4 sunrpc(OE) microcode soundcore i2c_core ata_generic pata_acpi [last unloaded: nfsd] [ 1610.168320] CPU: 0 PID: 27397 Comm: nfsd Tainted: G OE 3.15.0-rc1+ #15 [ 1610.168320] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006 [ 1610.168320] task: ffff88005ab653d0 ti: ffff88005a944000 task.ti: ffff88005a944000 [ 1610.168320] RIP: 0010:[] [] _posix_to_nfsv4_one+0x3cd/0x3d0 [nfsd] [ 1610.168320] RSP: 0018:ffff88005a945b00 EFLAGS: 00010293 [ 1610.168320] RAX: 0000000000000001 RBX: ffff88006700bac0 RCX: 0000000000000000 [ 1610.168320] RDX: 0000000000000000 RSI: ffff880067c83f00 RDI: ffff880068233300 [ 1610.168320] RBP: ffff88005a945b48 R08: ffffffff81c64830 R09: 0000000000000000 [ 1610.168320] R10: ffff88004ea85be0 R11: 000000000000f475 R12: ffff880068233300 [ 1610.168320] R13: 0000000000000003 R14: 0000000000000002 R15: ffff880068233300 [ 1610.168320] FS: 0000000000000000(0000) GS:ffff880077800000(0000) knlGS:0000000000000000 [ 1610.168320] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b [ 1610.168320] CR2: 00007f5bcbd3b0b9 CR3: 0000000001c0f000 CR4: 00000000000006f0 [ 1610.168320] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 1610.168320] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 1610.168320] Stack: [ 1610.168320] ffffffff00000000 0000000b67c83500 000000076700bac0 0000000000000000 [ 1610.168320] ffff88006700bac0 ffff880068233300 ffff88005a945c08 0000000000000002 [ 1610.168320] 0000000000000000 ffff88005a945b88 ffffffffa034e2d5 000000065a945b68 [ 1610.168320] Call Trace: [ 1610.168320] [] nfsd4_get_nfs4_acl+0x95/0x150 [nfsd] [ 1610.168320] [] nfsd4_encode_fattr+0x646/0x1e70 [nfsd] [ 1610.168320] [] ? kmemleak_alloc+0x4e/0xb0 [ 1610.168320] [] ? nfsd_setuser_and_check_port+0x52/0x80 [nfsd] [ 1610.168320] [] ? selinux_cred_prepare+0x1b/0x30 [ 1610.168320] [] nfsd4_encode_getattr+0x5a/0x60 [nfsd] [ 1610.168320] [] nfsd4_encode_operation+0x67/0x110 [nfsd] [ 1610.168320] [] nfsd4_proc_compound+0x21d/0x810 [nfsd] [ 1610.168320] [] nfsd_dispatch+0xbb/0x200 [nfsd] [ 1610.168320] [] svc_process_common+0x46d/0x6d0 [sunrpc] [ 1610.168320] [] svc_process+0x103/0x170 [sunrpc] [ 1610.168320] [] nfsd+0xbf/0x130 [nfsd] [ 1610.168320] [] ? nfsd_destroy+0x80/0x80 [nfsd] [ 1610.168320] [] kthread+0xd2/0xf0 [ 1610.168320] [] ? insert_kthread_work+0x40/0x40 [ 1610.168320] [] ret_from_fork+0x7c/0xb0 [ 1610.168320] [] ? insert_kthread_work+0x40/0x40 [ 1610.168320] Code: 78 02 e9 e7 fc ff ff 31 c0 31 d2 31 c9 66 89 45 ce 41 8b 04 24 66 89 55 d0 66 89 4d d2 48 8d 04 80 49 8d 5c 84 04 e9 37 fd ff ff <0f> 0b 90 0f 1f 44 00 00 55 8b 56 08 c7 07 00 00 00 00 8b 46 0c [ 1610.168320] RIP [] _posix_to_nfsv4_one+0x3cd/0x3d0 [nfsd] [ 1610.168320] RSP [ 1610.257313] ---[ end trace 838254e3e352285b ]--- Signed-off-by: Kinglong Mee Cc: stable@vger.kernel.org Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4acl.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c index 6f3f392d48af..b6f46013dddf 100644 --- a/fs/nfsd/nfs4acl.c +++ b/fs/nfsd/nfs4acl.c @@ -402,8 +402,10 @@ sort_pacl(struct posix_acl *pacl) * by uid/gid. */ int i, j; - if (pacl->a_count <= 4) - return; /* no users or groups */ + /* no users or groups */ + if (!pacl || pacl->a_count <= 4) + return; + i = 1; while (pacl->a_entries[i].e_tag == ACL_USER) i++; @@ -530,13 +532,12 @@ posix_state_to_acl(struct posix_acl_state *state, unsigned int flags) /* * ACLs with no ACEs are treated differently in the inheritable - * and effective cases: when there are no inheritable ACEs, we - * set a zero-length default posix acl: + * and effective cases: when there are no inheritable ACEs, + * calls ->set_acl with a NULL ACL structure. */ - if (state->empty && (flags & NFS4_ACL_TYPE_DEFAULT)) { - pacl = posix_acl_alloc(0, GFP_KERNEL); - return pacl ? pacl : ERR_PTR(-ENOMEM); - } + if (state->empty && (flags & NFS4_ACL_TYPE_DEFAULT)) + return NULL; + /* * When there are no effective ACEs, the following will end * up setting a 3-element effective posix ACL with all -- cgit v1.2.3 From 0041898ec19f10e2adf5f1245f32df88d627ae8a Mon Sep 17 00:00:00 2001 From: "S. Lockwood-Childs" Date: Thu, 8 May 2014 13:34:01 -0400 Subject: tools/liblockdep: Build liblockdep from tools/Makefile add targets to build liblockdep with make -C tools liblockdep like the way other stuff under tools/ can be built Signed-off-by: S. Lockwood-Childs Signed-off-by: Sasha Levin --- tools/Makefile | 6 ++++++ tools/lib/lockdep/Makefile | 3 +-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/tools/Makefile b/tools/Makefile index bcae806b0c39..9a617adc6675 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -44,6 +44,9 @@ cpupower: FORCE cgroup firewire hv guest usb virtio vm net: FORCE $(call descend,$@) +liblockdep: FORCE + $(call descend,lib/lockdep) + libapikfs: FORCE $(call descend,lib/api) @@ -91,6 +94,9 @@ cpupower_clean: cgroup_clean hv_clean firewire_clean lguest_clean usb_clean virtio_clean vm_clean net_clean: $(call descend,$(@:_clean=),clean) +liblockdep_clean: + $(call descend,lib/lockdep,clean) + libapikfs_clean: $(call descend,lib/api,clean) diff --git a/tools/lib/lockdep/Makefile b/tools/lib/lockdep/Makefile index cb09d3ff8f58..c70919b5ebe7 100644 --- a/tools/lib/lockdep/Makefile +++ b/tools/lib/lockdep/Makefile @@ -1,8 +1,7 @@ # file format version FILE_VERSION = 1 -MAKEFLAGS += --no-print-directory -LIBLOCKDEP_VERSION=$(shell make -sC ../../.. kernelversion) +LIBLOCKDEP_VERSION=$(shell make --no-print-directory -sC ../../.. kernelversion) # Makefiles suck: This macro sets a default value of $(2) for the # variable named by $(1), unless the variable has been set by -- cgit v1.2.3 From ad3b564deb91c67ff9621255307ed31da870c8f7 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Thu, 8 May 2014 13:55:13 -0400 Subject: tools/liblockdep: Remove all build files when doing make clean We forgot to remove the shared library with the version number when 'make clean' ran, fix the clean pattern. Signed-off-by: Sasha Levin --- tools/lib/lockdep/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/lib/lockdep/Makefile b/tools/lib/lockdep/Makefile index c70919b5ebe7..bba2f5253b6e 100644 --- a/tools/lib/lockdep/Makefile +++ b/tools/lib/lockdep/Makefile @@ -230,7 +230,7 @@ install_lib: all_cmd install: install_lib clean: - $(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES) .*.d + $(RM) *.o *~ $(TARGETS) *.a *liblockdep*.so* $(VERSION_FILES) .*.d $(RM) tags TAGS endif # skip-makefile -- cgit v1.2.3 From b18eb2d779240631a098626cb6841ee2dd34fda0 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 7 May 2014 14:07:32 -0700 Subject: sparc64: Fix huge TSB mapping on pre-UltraSPARC-III cpus. Access to the TSB hash tables during TLB misses requires that there be an atomic 128-bit quad load available so that we fetch a matching TAG and DATA field at the same time. On cpus prior to UltraSPARC-III only virtual address based quad loads are available. UltraSPARC-III and later provide physical address based variants which are easier to use. When we only have virtual address based quad loads available this means that we have to lock the TSB into the TLB at a fixed virtual address on each cpu when it runs that process. We can't just access the PAGE_OFFSET based aliased mapping of these TSBs because we cannot take a recursive TLB miss inside of the TLB miss handler without risking running out of hardware trap levels (some trap combinations can be deep, such as those generated by register window spill and fill traps). Without huge pages it's working perfectly fine, but when the huge TSB got added another chunk of fixed virtual address space was not allocated for this second TSB mapping. So we were mapping both the 8K and 4MB TSBs to the same exact virtual address, causing multiple TLB matches which gives undefined behavior. Signed-off-by: David S. Miller --- arch/sparc/include/asm/pgtable_64.h | 6 ++++-- arch/sparc/mm/tsb.c | 14 +++++++++++++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h index fde5abaac0cc..1a49ffdf9da9 100644 --- a/arch/sparc/include/asm/pgtable_64.h +++ b/arch/sparc/include/asm/pgtable_64.h @@ -24,7 +24,8 @@ /* The kernel image occupies 0x4000000 to 0x6000000 (4MB --> 96MB). * The page copy blockops can use 0x6000000 to 0x8000000. - * The TSB is mapped in the 0x8000000 to 0xa000000 range. + * The 8K TSB is mapped in the 0x8000000 to 0x8400000 range. + * The 4M TSB is mapped in the 0x8400000 to 0x8800000 range. * The PROM resides in an area spanning 0xf0000000 to 0x100000000. * The vmalloc area spans 0x100000000 to 0x200000000. * Since modules need to be in the lowest 32-bits of the address space, @@ -33,7 +34,8 @@ * 0x400000000. */ #define TLBTEMP_BASE _AC(0x0000000006000000,UL) -#define TSBMAP_BASE _AC(0x0000000008000000,UL) +#define TSBMAP_8K_BASE _AC(0x0000000008000000,UL) +#define TSBMAP_4M_BASE _AC(0x0000000008400000,UL) #define MODULES_VADDR _AC(0x0000000010000000,UL) #define MODULES_LEN _AC(0x00000000e0000000,UL) #define MODULES_END _AC(0x00000000f0000000,UL) diff --git a/arch/sparc/mm/tsb.c b/arch/sparc/mm/tsb.c index f5d506fdddad..fe19b81acc09 100644 --- a/arch/sparc/mm/tsb.c +++ b/arch/sparc/mm/tsb.c @@ -133,7 +133,19 @@ static void setup_tsb_params(struct mm_struct *mm, unsigned long tsb_idx, unsign mm->context.tsb_block[tsb_idx].tsb_nentries = tsb_bytes / sizeof(struct tsb); - base = TSBMAP_BASE; + switch (tsb_idx) { + case MM_TSB_BASE: + base = TSBMAP_8K_BASE; + break; +#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE) + case MM_TSB_HUGE: + base = TSBMAP_4M_BASE; + break; +#endif + default: + BUG(); + } + tte = pgprot_val(PAGE_KERNEL_LOCKED); tsb_paddr = __pa(mm->context.tsb_block[tsb_idx].tsb); BUG_ON(tsb_paddr & (tsb_bytes - 1UL)); -- cgit v1.2.3 From a8951d5814e1373807a94f79f7ccec7041325470 Mon Sep 17 00:00:00 2001 From: Sergey Popovich Date: Thu, 8 May 2014 16:22:35 +0300 Subject: netfilter: Fix potential use after free in ip6_route_me_harder() Dst is released one line before we access it again with dst->error. Fixes: 58e35d147128 netfilter: ipv6: propagate routing errors from ip6_route_me_harder() Signed-off-by: Sergey Popovich Signed-off-by: Pablo Neira Ayuso --- net/ipv6/netfilter.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c index 95f3f1da0d7f..d38e6a8d8b9f 100644 --- a/net/ipv6/netfilter.c +++ b/net/ipv6/netfilter.c @@ -30,13 +30,15 @@ int ip6_route_me_harder(struct sk_buff *skb) .daddr = iph->daddr, .saddr = iph->saddr, }; + int err; dst = ip6_route_output(net, skb->sk, &fl6); - if (dst->error) { + err = dst->error; + if (err) { IP6_INC_STATS(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); LIMIT_NETDEBUG(KERN_DEBUG "ip6_route_me_harder: No more route.\n"); dst_release(dst); - return dst->error; + return err; } /* Drop old route. */ -- cgit v1.2.3 From c9d8f1a64225dfcc2f721d73a5984a2444920744 Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Tue, 6 May 2014 11:02:49 -0700 Subject: ipv4: move local_port_range out of CONFIG_SYSCTL When CONFIG_SYSCTL is not set, ip_local_port_range should still work, just that no one can change it. Therefore we should move it out of sysctl_inet.c. Also, rename it to ->ip_local_ports instead. Cc: David S. Miller Cc: Francois Romieu Reported-by: Stefan de Konink Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- include/net/netns/ipv4.h | 2 +- net/ipv4/af_inet.c | 28 ++++++++++++++++++++++++++++ net/ipv4/inet_connection_sock.c | 8 ++++---- net/ipv4/ping.c | 4 ++-- net/ipv4/sysctl_net_ipv4.c | 29 +++++++++++------------------ 5 files changed, 46 insertions(+), 25 deletions(-) diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index 80f500a29498..3d95cd475316 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h @@ -66,7 +66,7 @@ struct netns_ipv4 { int sysctl_icmp_ratemask; int sysctl_icmp_errors_use_inbound_ifaddr; - struct local_ports sysctl_local_ports; + struct local_ports ip_local_ports; int sysctl_tcp_ecn; int sysctl_ip_no_pmtu_disc; diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 8c54870db792..cccc8e487c7e 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -1650,6 +1650,31 @@ static int __init init_ipv4_mibs(void) return register_pernet_subsys(&ipv4_mib_ops); } +static __net_init int inet_init_net(struct net *net) +{ + /* + * Set defaults for local port range + */ + seqlock_init(&net->ipv4.ip_local_ports.lock); + net->ipv4.ip_local_ports.range[0] = 32768; + net->ipv4.ip_local_ports.range[1] = 61000; + return 0; +} + +static __net_exit void inet_exit_net(struct net *net) +{ +} + +static __net_initdata struct pernet_operations af_inet_ops = { + .init = inet_init_net, + .exit = inet_exit_net, +}; + +static int __init init_inet_pernet_ops(void) +{ + return register_pernet_subsys(&af_inet_ops); +} + static int ipv4_proc_init(void); /* @@ -1794,6 +1819,9 @@ static int __init inet_init(void) if (ip_mr_init()) pr_crit("%s: Cannot init ipv4 mroute\n", __func__); #endif + + if (init_inet_pernet_ops()) + pr_crit("%s: Cannot init ipv4 inet pernet ops\n", __func__); /* * Initialise per-cpu ipv4 mibs */ diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 0d1e2cb877ec..a56b8e6e866a 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -37,11 +37,11 @@ void inet_get_local_port_range(struct net *net, int *low, int *high) unsigned int seq; do { - seq = read_seqbegin(&net->ipv4.sysctl_local_ports.lock); + seq = read_seqbegin(&net->ipv4.ip_local_ports.lock); - *low = net->ipv4.sysctl_local_ports.range[0]; - *high = net->ipv4.sysctl_local_ports.range[1]; - } while (read_seqretry(&net->ipv4.sysctl_local_ports.lock, seq)); + *low = net->ipv4.ip_local_ports.range[0]; + *high = net->ipv4.ip_local_ports.range[1]; + } while (read_seqretry(&net->ipv4.ip_local_ports.lock, seq)); } EXPORT_SYMBOL(inet_get_local_port_range); diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index 8210964a9f19..347bdde9a585 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c @@ -240,11 +240,11 @@ static void inet_get_ping_group_range_net(struct net *net, kgid_t *low, unsigned int seq; do { - seq = read_seqbegin(&net->ipv4.sysctl_local_ports.lock); + seq = read_seqbegin(&net->ipv4.ip_local_ports.lock); *low = data[0]; *high = data[1]; - } while (read_seqretry(&net->ipv4.sysctl_local_ports.lock, seq)); + } while (read_seqretry(&net->ipv4.ip_local_ports.lock, seq)); } diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index 44eba052b43d..a116c41b05dd 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -45,10 +45,10 @@ static int ip_ping_group_range_max[] = { GID_T_MAX, GID_T_MAX }; /* Update system visible IP port range */ static void set_local_port_range(struct net *net, int range[2]) { - write_seqlock(&net->ipv4.sysctl_local_ports.lock); - net->ipv4.sysctl_local_ports.range[0] = range[0]; - net->ipv4.sysctl_local_ports.range[1] = range[1]; - write_sequnlock(&net->ipv4.sysctl_local_ports.lock); + write_seqlock(&net->ipv4.ip_local_ports.lock); + net->ipv4.ip_local_ports.range[0] = range[0]; + net->ipv4.ip_local_ports.range[1] = range[1]; + write_sequnlock(&net->ipv4.ip_local_ports.lock); } /* Validate changes from /proc interface. */ @@ -57,7 +57,7 @@ static int ipv4_local_port_range(struct ctl_table *table, int write, size_t *lenp, loff_t *ppos) { struct net *net = - container_of(table->data, struct net, ipv4.sysctl_local_ports.range); + container_of(table->data, struct net, ipv4.ip_local_ports.range); int ret; int range[2]; struct ctl_table tmp = { @@ -90,11 +90,11 @@ static void inet_get_ping_group_range_table(struct ctl_table *table, kgid_t *low container_of(table->data, struct net, ipv4.sysctl_ping_group_range); unsigned int seq; do { - seq = read_seqbegin(&net->ipv4.sysctl_local_ports.lock); + seq = read_seqbegin(&net->ipv4.ip_local_ports.lock); *low = data[0]; *high = data[1]; - } while (read_seqretry(&net->ipv4.sysctl_local_ports.lock, seq)); + } while (read_seqretry(&net->ipv4.ip_local_ports.lock, seq)); } /* Update system visible IP port range */ @@ -103,10 +103,10 @@ static void set_ping_group_range(struct ctl_table *table, kgid_t low, kgid_t hig kgid_t *data = table->data; struct net *net = container_of(table->data, struct net, ipv4.sysctl_ping_group_range); - write_seqlock(&net->ipv4.sysctl_local_ports.lock); + write_seqlock(&net->ipv4.ip_local_ports.lock); data[0] = low; data[1] = high; - write_sequnlock(&net->ipv4.sysctl_local_ports.lock); + write_sequnlock(&net->ipv4.ip_local_ports.lock); } /* Validate changes from /proc interface. */ @@ -819,8 +819,8 @@ static struct ctl_table ipv4_net_table[] = { }, { .procname = "ip_local_port_range", - .maxlen = sizeof(init_net.ipv4.sysctl_local_ports.range), - .data = &init_net.ipv4.sysctl_local_ports.range, + .maxlen = sizeof(init_net.ipv4.ip_local_ports.range), + .data = &init_net.ipv4.ip_local_ports.range, .mode = 0644, .proc_handler = ipv4_local_port_range, }, @@ -865,13 +865,6 @@ static __net_init int ipv4_sysctl_init_net(struct net *net) net->ipv4.sysctl_ping_group_range[0] = make_kgid(&init_user_ns, 1); net->ipv4.sysctl_ping_group_range[1] = make_kgid(&init_user_ns, 0); - /* - * Set defaults for local port range - */ - seqlock_init(&net->ipv4.sysctl_local_ports.lock); - net->ipv4.sysctl_local_ports.range[0] = 32768; - net->ipv4.sysctl_local_ports.range[1] = 61000; - net->ipv4.ipv4_hdr = register_net_sysctl(net, "net/ipv4", table); if (net->ipv4.ipv4_hdr == NULL) goto err_reg; -- cgit v1.2.3 From ba6b918ab234186d3aa1663e296586a1b526b77a Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Tue, 6 May 2014 11:02:50 -0700 Subject: ping: move ping_group_range out of CONFIG_SYSCTL Similarly, when CONFIG_SYSCTL is not set, ping_group_range should still work, just that no one can change it. Therefore we should move it out of sysctl_net_ipv4.c. And, it should not share the same seqlock with ip_local_port_range. BTW, rename it to ->ping_group_range instead. Cc: David S. Miller Cc: Francois Romieu Reported-by: Stefan de Konink Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- include/net/netns/ipv4.h | 7 ++++++- net/ipv4/af_inet.c | 8 ++++++++ net/ipv4/ping.c | 6 +++--- net/ipv4/sysctl_net_ipv4.c | 13 +++---------- 4 files changed, 20 insertions(+), 14 deletions(-) diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index 3d95cd475316..b2704fd0ec80 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h @@ -20,6 +20,11 @@ struct local_ports { int range[2]; }; +struct ping_group_range { + seqlock_t lock; + kgid_t range[2]; +}; + struct netns_ipv4 { #ifdef CONFIG_SYSCTL struct ctl_table_header *forw_hdr; @@ -72,7 +77,7 @@ struct netns_ipv4 { int sysctl_ip_no_pmtu_disc; int sysctl_ip_fwd_use_pmtu; - kgid_t sysctl_ping_group_range[2]; + struct ping_group_range ping_group_range; atomic_t dev_addr_genid; diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index cccc8e487c7e..6d6dd345bc4d 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -1658,6 +1658,14 @@ static __net_init int inet_init_net(struct net *net) seqlock_init(&net->ipv4.ip_local_ports.lock); net->ipv4.ip_local_ports.range[0] = 32768; net->ipv4.ip_local_ports.range[1] = 61000; + + seqlock_init(&net->ipv4.ping_group_range.lock); + /* + * Sane defaults - nobody may create ping sockets. + * Boot scripts should set this to distro-specific group. + */ + net->ipv4.ping_group_range.range[0] = make_kgid(&init_user_ns, 1); + net->ipv4.ping_group_range.range[1] = make_kgid(&init_user_ns, 0); return 0; } diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index 347bdde9a585..044a0ddf6a79 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c @@ -236,15 +236,15 @@ exit: static void inet_get_ping_group_range_net(struct net *net, kgid_t *low, kgid_t *high) { - kgid_t *data = net->ipv4.sysctl_ping_group_range; + kgid_t *data = net->ipv4.ping_group_range.range; unsigned int seq; do { - seq = read_seqbegin(&net->ipv4.ip_local_ports.lock); + seq = read_seqbegin(&net->ipv4.ping_group_range.lock); *low = data[0]; *high = data[1]; - } while (read_seqretry(&net->ipv4.ip_local_ports.lock, seq)); + } while (read_seqretry(&net->ipv4.ping_group_range.lock, seq)); } diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index a116c41b05dd..5cde8f263d40 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -87,7 +87,7 @@ static void inet_get_ping_group_range_table(struct ctl_table *table, kgid_t *low { kgid_t *data = table->data; struct net *net = - container_of(table->data, struct net, ipv4.sysctl_ping_group_range); + container_of(table->data, struct net, ipv4.ping_group_range.range); unsigned int seq; do { seq = read_seqbegin(&net->ipv4.ip_local_ports.lock); @@ -102,7 +102,7 @@ static void set_ping_group_range(struct ctl_table *table, kgid_t low, kgid_t hig { kgid_t *data = table->data; struct net *net = - container_of(table->data, struct net, ipv4.sysctl_ping_group_range); + container_of(table->data, struct net, ipv4.ping_group_range.range); write_seqlock(&net->ipv4.ip_local_ports.lock); data[0] = low; data[1] = high; @@ -805,7 +805,7 @@ static struct ctl_table ipv4_net_table[] = { }, { .procname = "ping_group_range", - .data = &init_net.ipv4.sysctl_ping_group_range, + .data = &init_net.ipv4.ping_group_range.range, .maxlen = sizeof(gid_t)*2, .mode = 0644, .proc_handler = ipv4_ping_group_range, @@ -858,13 +858,6 @@ static __net_init int ipv4_sysctl_init_net(struct net *net) table[i].data += (void *)net - (void *)&init_net; } - /* - * Sane defaults - nobody may create ping sockets. - * Boot scripts should set this to distro-specific group. - */ - net->ipv4.sysctl_ping_group_range[0] = make_kgid(&init_user_ns, 1); - net->ipv4.sysctl_ping_group_range[1] = make_kgid(&init_user_ns, 0); - net->ipv4.ipv4_hdr = register_net_sysctl(net, "net/ipv4", table); if (net->ipv4.ipv4_hdr == NULL) goto err_reg; -- cgit v1.2.3 From 6af55ff52b02d492d45db88df3e461fa51a6f753 Mon Sep 17 00:00:00 2001 From: Darek Marcinkiewicz Date: Tue, 6 May 2014 22:24:50 +0200 Subject: Driver for Beckhoff CX5020 EtherCAT master module. This driver adds support for EtherCAT master module located on CCAT FPGA found on Beckhoff CX series industrial PCs. The driver exposes EtherCAT master as an ethernet interface. EtherCAT is a fieldbus protocol defined on top of ethernet and Beckhoff CX5020 PCs come with built-in EtherCAT master module located on a FPGA, which in turn is connected to a PCI bus. Signed-off-by: Dariusz Marcinkiewicz Signed-off-by: David S. Miller --- drivers/net/ethernet/Kconfig | 12 + drivers/net/ethernet/Makefile | 1 + drivers/net/ethernet/ec_bhf.c | 706 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 719 insertions(+) create mode 100644 drivers/net/ethernet/ec_bhf.c diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig index 39b26fe28d10..d7401017a3f1 100644 --- a/drivers/net/ethernet/Kconfig +++ b/drivers/net/ethernet/Kconfig @@ -35,6 +35,18 @@ source "drivers/net/ethernet/calxeda/Kconfig" source "drivers/net/ethernet/chelsio/Kconfig" source "drivers/net/ethernet/cirrus/Kconfig" source "drivers/net/ethernet/cisco/Kconfig" + +config CX_ECAT + tristate "Beckhoff CX5020 EtherCAT master support" + depends on PCI + ---help--- + Driver for EtherCAT master module located on CCAT FPGA + that can be found on Beckhoff CX5020, and possibly other of CX + Beckhoff CX series industrial PCs. + + To compile this driver as a module, choose M here. The module + will be called ec_bhf. + source "drivers/net/ethernet/davicom/Kconfig" config DNET diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile index 545d0b3b9cb4..35190e36c456 100644 --- a/drivers/net/ethernet/Makefile +++ b/drivers/net/ethernet/Makefile @@ -21,6 +21,7 @@ obj-$(CONFIG_NET_CALXEDA_XGMAC) += calxeda/ obj-$(CONFIG_NET_VENDOR_CHELSIO) += chelsio/ obj-$(CONFIG_NET_VENDOR_CIRRUS) += cirrus/ obj-$(CONFIG_NET_VENDOR_CISCO) += cisco/ +obj-$(CONFIG_CX_ECAT) += ec_bhf.o obj-$(CONFIG_DM9000) += davicom/ obj-$(CONFIG_DNET) += dnet.o obj-$(CONFIG_NET_VENDOR_DEC) += dec/ diff --git a/drivers/net/ethernet/ec_bhf.c b/drivers/net/ethernet/ec_bhf.c new file mode 100644 index 000000000000..4884205e56ee --- /dev/null +++ b/drivers/net/ethernet/ec_bhf.c @@ -0,0 +1,706 @@ + /* + * drivers/net/ethernet/beckhoff/ec_bhf.c + * + * Copyright (C) 2014 Darek Marcinkiewicz + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +/* This is a driver for EtherCAT master module present on CCAT FPGA. + * Those can be found on Bechhoff CX50xx industrial PCs. + */ + +#if 0 +#define DEBUG +#endif +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define TIMER_INTERVAL_NSEC 20000 + +#define INFO_BLOCK_SIZE 0x10 +#define INFO_BLOCK_TYPE 0x0 +#define INFO_BLOCK_REV 0x2 +#define INFO_BLOCK_BLK_CNT 0x4 +#define INFO_BLOCK_TX_CHAN 0x4 +#define INFO_BLOCK_RX_CHAN 0x5 +#define INFO_BLOCK_OFFSET 0x8 + +#define EC_MII_OFFSET 0x4 +#define EC_FIFO_OFFSET 0x8 +#define EC_MAC_OFFSET 0xc + +#define MAC_FRAME_ERR_CNT 0x0 +#define MAC_RX_ERR_CNT 0x1 +#define MAC_CRC_ERR_CNT 0x2 +#define MAC_LNK_LST_ERR_CNT 0x3 +#define MAC_TX_FRAME_CNT 0x10 +#define MAC_RX_FRAME_CNT 0x14 +#define MAC_TX_FIFO_LVL 0x20 +#define MAC_DROPPED_FRMS 0x28 +#define MAC_CONNECTED_CCAT_FLAG 0x78 + +#define MII_MAC_ADDR 0x8 +#define MII_MAC_FILT_FLAG 0xe +#define MII_LINK_STATUS 0xf + +#define FIFO_TX_REG 0x0 +#define FIFO_TX_RESET 0x8 +#define FIFO_RX_REG 0x10 +#define FIFO_RX_ADDR_VALID (1u << 31) +#define FIFO_RX_RESET 0x18 + +#define DMA_CHAN_OFFSET 0x1000 +#define DMA_CHAN_SIZE 0x8 + +#define DMA_WINDOW_SIZE_MASK 0xfffffffc + +static struct pci_device_id ids[] = { + { PCI_DEVICE(0x15ec, 0x5000), }, + { 0, } +}; +MODULE_DEVICE_TABLE(pci, ids); + +struct rx_header { +#define RXHDR_NEXT_ADDR_MASK 0xffffffu +#define RXHDR_NEXT_VALID (1u << 31) + __le32 next; +#define RXHDR_NEXT_RECV_FLAG 0x1 + __le32 recv; +#define RXHDR_LEN_MASK 0xfffu + __le16 len; + __le16 port; + __le32 reserved; + u8 timestamp[8]; +} __packed; + +#define PKT_PAYLOAD_SIZE 0x7e8 +struct rx_desc { + struct rx_header header; + u8 data[PKT_PAYLOAD_SIZE]; +} __packed; + +struct tx_header { + __le16 len; +#define TX_HDR_PORT_0 0x1 +#define TX_HDR_PORT_1 0x2 + u8 port; + u8 ts_enable; +#define TX_HDR_SENT 0x1 + __le32 sent; + u8 timestamp[8]; +} __packed; + +struct tx_desc { + struct tx_header header; + u8 data[PKT_PAYLOAD_SIZE]; +} __packed; + +#define FIFO_SIZE 64 + +static long polling_frequency = TIMER_INTERVAL_NSEC; + +struct bhf_dma { + u8 *buf; + size_t len; + dma_addr_t buf_phys; + + u8 *alloc; + size_t alloc_len; + dma_addr_t alloc_phys; +}; + +struct ec_bhf_priv { + struct net_device *net_dev; + + struct pci_dev *dev; + + void * __iomem io; + void * __iomem dma_io; + + struct hrtimer hrtimer; + + int tx_dma_chan; + int rx_dma_chan; + void * __iomem ec_io; + void * __iomem fifo_io; + void * __iomem mii_io; + void * __iomem mac_io; + + struct bhf_dma rx_buf; + struct rx_desc *rx_descs; + int rx_dnext; + int rx_dcount; + + struct bhf_dma tx_buf; + struct tx_desc *tx_descs; + int tx_dcount; + int tx_dnext; + + u64 stat_rx_bytes; + u64 stat_tx_bytes; +}; + +#define PRIV_TO_DEV(priv) (&(priv)->dev->dev) + +#define ETHERCAT_MASTER_ID 0x14 + +static void ec_bhf_print_status(struct ec_bhf_priv *priv) +{ + struct device *dev = PRIV_TO_DEV(priv); + + dev_dbg(dev, "Frame error counter: %d\n", + ioread8(priv->mac_io + MAC_FRAME_ERR_CNT)); + dev_dbg(dev, "RX error counter: %d\n", + ioread8(priv->mac_io + MAC_RX_ERR_CNT)); + dev_dbg(dev, "CRC error counter: %d\n", + ioread8(priv->mac_io + MAC_CRC_ERR_CNT)); + dev_dbg(dev, "TX frame counter: %d\n", + ioread32(priv->mac_io + MAC_TX_FRAME_CNT)); + dev_dbg(dev, "RX frame counter: %d\n", + ioread32(priv->mac_io + MAC_RX_FRAME_CNT)); + dev_dbg(dev, "TX fifo level: %d\n", + ioread8(priv->mac_io + MAC_TX_FIFO_LVL)); + dev_dbg(dev, "Dropped frames: %d\n", + ioread8(priv->mac_io + MAC_DROPPED_FRMS)); + dev_dbg(dev, "Connected with CCAT slot: %d\n", + ioread8(priv->mac_io + MAC_CONNECTED_CCAT_FLAG)); + dev_dbg(dev, "Link status: %d\n", + ioread8(priv->mii_io + MII_LINK_STATUS)); +} + +static void ec_bhf_reset(struct ec_bhf_priv *priv) +{ + iowrite8(0, priv->mac_io + MAC_FRAME_ERR_CNT); + iowrite8(0, priv->mac_io + MAC_RX_ERR_CNT); + iowrite8(0, priv->mac_io + MAC_CRC_ERR_CNT); + iowrite8(0, priv->mac_io + MAC_LNK_LST_ERR_CNT); + iowrite32(0, priv->mac_io + MAC_TX_FRAME_CNT); + iowrite32(0, priv->mac_io + MAC_RX_FRAME_CNT); + iowrite8(0, priv->mac_io + MAC_DROPPED_FRMS); + + iowrite8(0, priv->fifo_io + FIFO_TX_RESET); + iowrite8(0, priv->fifo_io + FIFO_RX_RESET); + + iowrite8(0, priv->mac_io + MAC_TX_FIFO_LVL); +} + +static void ec_bhf_send_packet(struct ec_bhf_priv *priv, struct tx_desc *desc) +{ + u32 len = le16_to_cpu(desc->header.len) + sizeof(desc->header); + u32 addr = (u8 *)desc - priv->tx_buf.buf; + + iowrite32((ALIGN(len, 8) << 24) | addr, priv->fifo_io + FIFO_TX_REG); + + dev_dbg(PRIV_TO_DEV(priv), "Done sending packet\n"); +} + +static int ec_bhf_desc_sent(struct tx_desc *desc) +{ + return le32_to_cpu(desc->header.sent) & TX_HDR_SENT; +} + +static void ec_bhf_process_tx(struct ec_bhf_priv *priv) +{ + if (unlikely(netif_queue_stopped(priv->net_dev))) { + /* Make sure that we perceive changes to tx_dnext. */ + smp_rmb(); + + if (ec_bhf_desc_sent(&priv->tx_descs[priv->tx_dnext])) + netif_wake_queue(priv->net_dev); + } +} + +static int ec_bhf_pkt_received(struct rx_desc *desc) +{ + return le32_to_cpu(desc->header.recv) & RXHDR_NEXT_RECV_FLAG; +} + +static void ec_bhf_add_rx_desc(struct ec_bhf_priv *priv, struct rx_desc *desc) +{ + iowrite32(FIFO_RX_ADDR_VALID | ((u8 *)(desc) - priv->rx_buf.buf), + priv->fifo_io + FIFO_RX_REG); +} + +static void ec_bhf_process_rx(struct ec_bhf_priv *priv) +{ + struct rx_desc *desc = &priv->rx_descs[priv->rx_dnext]; + struct device *dev = PRIV_TO_DEV(priv); + + while (ec_bhf_pkt_received(desc)) { + int pkt_size = (le16_to_cpu(desc->header.len) & + RXHDR_LEN_MASK) - sizeof(struct rx_header) - 4; + u8 *data = desc->data; + struct sk_buff *skb; + + skb = netdev_alloc_skb_ip_align(priv->net_dev, pkt_size); + dev_dbg(dev, "Received packet, size: %d\n", pkt_size); + + if (skb) { + memcpy(skb_put(skb, pkt_size), data, pkt_size); + skb->protocol = eth_type_trans(skb, priv->net_dev); + dev_dbg(dev, "Protocol type: %x\n", skb->protocol); + + priv->stat_rx_bytes += pkt_size; + + netif_rx(skb); + } else { + dev_err_ratelimited(dev, + "Couldn't allocate a skb_buff for a packet of size %u\n", + pkt_size); + } + + desc->header.recv = 0; + + ec_bhf_add_rx_desc(priv, desc); + + priv->rx_dnext = (priv->rx_dnext + 1) % priv->rx_dcount; + desc = &priv->rx_descs[priv->rx_dnext]; + } + +} + +static enum hrtimer_restart ec_bhf_timer_fun(struct hrtimer *timer) +{ + struct ec_bhf_priv *priv = container_of(timer, struct ec_bhf_priv, + hrtimer); + ec_bhf_process_rx(priv); + ec_bhf_process_tx(priv); + + if (!netif_running(priv->net_dev)) + return HRTIMER_NORESTART; + + hrtimer_forward_now(timer, ktime_set(0, polling_frequency)); + return HRTIMER_RESTART; +} + +static int ec_bhf_setup_offsets(struct ec_bhf_priv *priv) +{ + struct device *dev = PRIV_TO_DEV(priv); + unsigned block_count, i; + void * __iomem ec_info; + + dev_dbg(dev, "Info block:\n"); + dev_dbg(dev, "Type of function: %x\n", (unsigned)ioread16(priv->io)); + dev_dbg(dev, "Revision of function: %x\n", + (unsigned)ioread16(priv->io + INFO_BLOCK_REV)); + + block_count = ioread8(priv->io + INFO_BLOCK_BLK_CNT); + dev_dbg(dev, "Number of function blocks: %x\n", block_count); + + for (i = 0; i < block_count; i++) { + u16 type = ioread16(priv->io + i * INFO_BLOCK_SIZE + + INFO_BLOCK_TYPE); + if (type == ETHERCAT_MASTER_ID) + break; + } + if (i == block_count) { + dev_err(dev, "EtherCAT master with DMA block not found\n"); + return -ENODEV; + } + dev_dbg(dev, "EtherCAT master with DMA block found at pos: %d\n", i); + + ec_info = priv->io + i * INFO_BLOCK_SIZE; + dev_dbg(dev, "EtherCAT master revision: %d\n", + ioread16(ec_info + INFO_BLOCK_REV)); + + priv->tx_dma_chan = ioread8(ec_info + INFO_BLOCK_TX_CHAN); + dev_dbg(dev, "EtherCAT master tx dma channel: %d\n", + priv->tx_dma_chan); + + priv->rx_dma_chan = ioread8(ec_info + INFO_BLOCK_RX_CHAN); + dev_dbg(dev, "EtherCAT master rx dma channel: %d\n", + priv->rx_dma_chan); + + priv->ec_io = priv->io + ioread32(ec_info + INFO_BLOCK_OFFSET); + priv->mii_io = priv->ec_io + ioread32(priv->ec_io + EC_MII_OFFSET); + priv->fifo_io = priv->ec_io + ioread32(priv->ec_io + EC_FIFO_OFFSET); + priv->mac_io = priv->ec_io + ioread32(priv->ec_io + EC_MAC_OFFSET); + + dev_dbg(dev, + "EtherCAT block addres: %p, fifo address: %p, mii address: %p, mac address: %p\n", + priv->ec_io, priv->fifo_io, priv->mii_io, priv->mac_io); + + return 0; +} + +static netdev_tx_t ec_bhf_start_xmit(struct sk_buff *skb, + struct net_device *net_dev) +{ + struct ec_bhf_priv *priv = netdev_priv(net_dev); + struct tx_desc *desc; + unsigned len; + + dev_dbg(PRIV_TO_DEV(priv), "Starting xmit\n"); + + desc = &priv->tx_descs[priv->tx_dnext]; + + skb_copy_and_csum_dev(skb, desc->data); + len = skb->len; + + memset(&desc->header, 0, sizeof(desc->header)); + desc->header.len = cpu_to_le16(len); + desc->header.port = TX_HDR_PORT_0; + + ec_bhf_send_packet(priv, desc); + + priv->tx_dnext = (priv->tx_dnext + 1) % priv->tx_dcount; + + if (!ec_bhf_desc_sent(&priv->tx_descs[priv->tx_dnext])) { + /* Make sure that update updates to tx_dnext are perceived + * by timer routine. + */ + smp_wmb(); + + netif_stop_queue(net_dev); + + dev_dbg(PRIV_TO_DEV(priv), "Stopping netif queue\n"); + ec_bhf_print_status(priv); + } + + priv->stat_tx_bytes += len; + + dev_kfree_skb(skb); + + return NETDEV_TX_OK; +} + +static int ec_bhf_alloc_dma_mem(struct ec_bhf_priv *priv, + struct bhf_dma *buf, + int channel, + int size) +{ + int offset = channel * DMA_CHAN_SIZE + DMA_CHAN_OFFSET; + struct device *dev = PRIV_TO_DEV(priv); + u32 mask; + + iowrite32(0xffffffff, priv->dma_io + offset); + + mask = ioread32(priv->dma_io + offset); + mask &= DMA_WINDOW_SIZE_MASK; + dev_dbg(dev, "Read mask %x for channel %d\n", mask, channel); + + /* We want to allocate a chunk of memory that is: + * - aligned to the mask we just read + * - is of size 2^mask bytes (at most) + * In order to ensure that we will allocate buffer of + * 2 * 2^mask bytes. + */ + buf->len = min_t(int, ~mask + 1, size); + buf->alloc_len = 2 * buf->len; + + dev_dbg(dev, "Allocating %d bytes for channel %d", + (int)buf->alloc_len, channel); + buf->alloc = dma_alloc_coherent(dev, buf->alloc_len, &buf->alloc_phys, + GFP_KERNEL); + if (buf->alloc == NULL) { + dev_info(dev, "Failed to allocate buffer\n"); + return -ENOMEM; + } + + buf->buf_phys = (buf->alloc_phys + buf->len) & mask; + buf->buf = buf->alloc + (buf->buf_phys - buf->alloc_phys); + + iowrite32(0, priv->dma_io + offset + 4); + iowrite32(buf->buf_phys, priv->dma_io + offset); + dev_dbg(dev, "Buffer: %x and read from dev: %x", + (unsigned)buf->buf_phys, ioread32(priv->dma_io + offset)); + + return 0; +} + +static void ec_bhf_setup_tx_descs(struct ec_bhf_priv *priv) +{ + int i = 0; + + priv->tx_dcount = priv->tx_buf.len / sizeof(struct tx_desc); + priv->tx_descs = (struct tx_desc *) priv->tx_buf.buf; + priv->tx_dnext = 0; + + for (i = 0; i < priv->tx_dcount; i++) + priv->tx_descs[i].header.sent = cpu_to_le32(TX_HDR_SENT); +} + +static void ec_bhf_setup_rx_descs(struct ec_bhf_priv *priv) +{ + int i; + + priv->rx_dcount = priv->rx_buf.len / sizeof(struct rx_desc); + priv->rx_descs = (struct rx_desc *) priv->rx_buf.buf; + priv->rx_dnext = 0; + + for (i = 0; i < priv->rx_dcount; i++) { + struct rx_desc *desc = &priv->rx_descs[i]; + u32 next; + + if (i != priv->rx_dcount - 1) + next = (u8 *)(desc + 1) - priv->rx_buf.buf; + else + next = 0; + next |= RXHDR_NEXT_VALID; + desc->header.next = cpu_to_le32(next); + desc->header.recv = 0; + ec_bhf_add_rx_desc(priv, desc); + } +} + +static int ec_bhf_open(struct net_device *net_dev) +{ + struct ec_bhf_priv *priv = netdev_priv(net_dev); + struct device *dev = PRIV_TO_DEV(priv); + int err = 0; + + dev_info(dev, "Opening device\n"); + + ec_bhf_reset(priv); + + err = ec_bhf_alloc_dma_mem(priv, &priv->rx_buf, priv->rx_dma_chan, + FIFO_SIZE * sizeof(struct rx_desc)); + if (err) { + dev_err(dev, "Failed to allocate rx buffer\n"); + goto out; + } + ec_bhf_setup_rx_descs(priv); + + dev_info(dev, "RX buffer allocated, address: %x\n", + (unsigned)priv->rx_buf.buf_phys); + + err = ec_bhf_alloc_dma_mem(priv, &priv->tx_buf, priv->tx_dma_chan, + FIFO_SIZE * sizeof(struct tx_desc)); + if (err) { + dev_err(dev, "Failed to allocate tx buffer\n"); + goto error_rx_free; + } + dev_dbg(dev, "TX buffer allocated, addres: %x\n", + (unsigned)priv->tx_buf.buf_phys); + + iowrite8(0, priv->mii_io + MII_MAC_FILT_FLAG); + + ec_bhf_setup_tx_descs(priv); + + netif_start_queue(net_dev); + + hrtimer_init(&priv->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + priv->hrtimer.function = ec_bhf_timer_fun; + hrtimer_start(&priv->hrtimer, ktime_set(0, polling_frequency), + HRTIMER_MODE_REL); + + dev_info(PRIV_TO_DEV(priv), "Device open\n"); + + ec_bhf_print_status(priv); + + return 0; + +error_rx_free: + dma_free_coherent(dev, priv->rx_buf.alloc_len, priv->rx_buf.alloc, + priv->rx_buf.alloc_len); +out: + return err; +} + +static int ec_bhf_stop(struct net_device *net_dev) +{ + struct ec_bhf_priv *priv = netdev_priv(net_dev); + struct device *dev = PRIV_TO_DEV(priv); + + hrtimer_cancel(&priv->hrtimer); + + ec_bhf_reset(priv); + + netif_tx_disable(net_dev); + + dma_free_coherent(dev, priv->tx_buf.alloc_len, + priv->tx_buf.alloc, priv->tx_buf.alloc_phys); + dma_free_coherent(dev, priv->rx_buf.alloc_len, + priv->rx_buf.alloc, priv->rx_buf.alloc_phys); + + return 0; +} + +static struct rtnl_link_stats64 * +ec_bhf_get_stats(struct net_device *net_dev, + struct rtnl_link_stats64 *stats) +{ + struct ec_bhf_priv *priv = netdev_priv(net_dev); + + stats->rx_errors = ioread8(priv->mac_io + MAC_RX_ERR_CNT) + + ioread8(priv->mac_io + MAC_CRC_ERR_CNT) + + ioread8(priv->mac_io + MAC_FRAME_ERR_CNT); + stats->rx_packets = ioread32(priv->mac_io + MAC_RX_FRAME_CNT); + stats->tx_packets = ioread32(priv->mac_io + MAC_TX_FRAME_CNT); + stats->rx_dropped = ioread8(priv->mac_io + MAC_DROPPED_FRMS); + + stats->tx_bytes = priv->stat_tx_bytes; + stats->rx_bytes = priv->stat_rx_bytes; + + return stats; +} + +static const struct net_device_ops ec_bhf_netdev_ops = { + .ndo_start_xmit = ec_bhf_start_xmit, + .ndo_open = ec_bhf_open, + .ndo_stop = ec_bhf_stop, + .ndo_get_stats64 = ec_bhf_get_stats, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr +}; + +static int ec_bhf_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + struct net_device *net_dev; + struct ec_bhf_priv *priv; + void * __iomem dma_io; + void * __iomem io; + int err = 0; + + err = pci_enable_device(dev); + if (err) + return err; + + pci_set_master(dev); + + err = pci_set_dma_mask(dev, DMA_BIT_MASK(32)); + if (err) { + dev_err(&dev->dev, + "Required dma mask not supported, failed to initialize device\n"); + err = -EIO; + goto err_disable_dev; + } + + err = pci_set_consistent_dma_mask(dev, DMA_BIT_MASK(32)); + if (err) { + dev_err(&dev->dev, + "Required dma mask not supported, failed to initialize device\n"); + goto err_disable_dev; + } + + err = pci_request_regions(dev, "ec_bhf"); + if (err) { + dev_err(&dev->dev, "Failed to request pci memory regions\n"); + goto err_disable_dev; + } + + io = pci_iomap(dev, 0, 0); + if (!io) { + dev_err(&dev->dev, "Failed to map pci card memory bar 0"); + err = -EIO; + goto err_release_regions; + } + + dma_io = pci_iomap(dev, 2, 0); + if (!dma_io) { + dev_err(&dev->dev, "Failed to map pci card memory bar 2"); + err = -EIO; + goto err_unmap; + } + + net_dev = alloc_etherdev(sizeof(struct ec_bhf_priv)); + if (net_dev == 0) { + err = -ENOMEM; + goto err_unmap_dma_io; + } + + pci_set_drvdata(dev, net_dev); + SET_NETDEV_DEV(net_dev, &dev->dev); + + net_dev->features = 0; + net_dev->flags |= IFF_NOARP; + + net_dev->netdev_ops = &ec_bhf_netdev_ops; + + priv = netdev_priv(net_dev); + priv->net_dev = net_dev; + priv->io = io; + priv->dma_io = dma_io; + priv->dev = dev; + + err = ec_bhf_setup_offsets(priv); + if (err < 0) + goto err_free_net_dev; + + memcpy_fromio(net_dev->dev_addr, priv->mii_io + MII_MAC_ADDR, 6); + + dev_dbg(&dev->dev, "CX5020 Ethercat master address: %pM\n", + net_dev->dev_addr); + + err = register_netdev(net_dev); + if (err < 0) + goto err_free_net_dev; + + return 0; + +err_free_net_dev: + free_netdev(net_dev); +err_unmap_dma_io: + pci_iounmap(dev, dma_io); +err_unmap: + pci_iounmap(dev, io); +err_release_regions: + pci_release_regions(dev); +err_disable_dev: + pci_clear_master(dev); + pci_disable_device(dev); + + return err; +} + +static void ec_bhf_remove(struct pci_dev *dev) +{ + struct net_device *net_dev = pci_get_drvdata(dev); + struct ec_bhf_priv *priv = netdev_priv(net_dev); + + unregister_netdev(net_dev); + free_netdev(net_dev); + + pci_iounmap(dev, priv->dma_io); + pci_iounmap(dev, priv->io); + pci_release_regions(dev); + pci_clear_master(dev); + pci_disable_device(dev); +} + +static struct pci_driver pci_driver = { + .name = "ec_bhf", + .id_table = ids, + .probe = ec_bhf_probe, + .remove = ec_bhf_remove, +}; + +static int __init ec_bhf_init(void) +{ + return pci_register_driver(&pci_driver); +} + +static void __exit ec_bhf_exit(void) +{ + pci_unregister_driver(&pci_driver); +} + +module_init(ec_bhf_init); +module_exit(ec_bhf_exit); + +module_param(polling_frequency, long, S_IRUGO); +MODULE_PARM_DESC(polling_frequency, "Polling timer frequency in ns"); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Dariusz Marcinkiewicz "); -- cgit v1.2.3 From a1f3b5fa11dfc636288b9e0190a0289f23d95af6 Mon Sep 17 00:00:00 2001 From: Hui Wang Date: Fri, 9 May 2014 11:12:58 +0800 Subject: ALSA: hda - add headset mic detect quirks for three Dell laptops When we plug a 3-ring headset on the Dell machines (VID: 0x10ec0255, SID: 0x1028065c; VID: 0x10ec0255, SID: 0x10280680; VID: 0x10ec0292, SID: 0x10280684), the headset mic can't be detected, after apply this patch, the headset mic can work well. And on the machine with SID 0x10280684, and the Lineout and external microphone should be routed to docking, this patch also fix this problem. BugLink: https://bugs.launchpad.net/bugs/1297581 Cc: David Henningsson Cc: stable@vger.kernel.org Signed-off-by: Hui Wang Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 5f7c765391f1..49e884fb3e5d 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4616,6 +4616,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1028, 0x0653, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x0657, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x0658, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1028, 0x065c, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x065f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x0662, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x0667, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), @@ -4624,6 +4625,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1028, 0x0674, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x067e, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x067f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1028, 0x0680, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1028, 0x0684, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x15cc, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x15cd, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2), -- cgit v1.2.3 From 4a817aa78f573c6964f16d9aea3d0d10a226ade4 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 9 May 2014 09:56:53 +0200 Subject: mac80211: allow VHT with peers not capable of 40MHz There are two (related) issues with this. One case, reported by Michal, is related to hostap: it unsets the 20/40 capability bit for stations that associate when it's in 20 MHz mode. The other case, reported by Eyal, is that some APs like Netgear R6300v2 and probably others based on the BCM4360 chipset can be configured for doing VHT at 20Mhz. In this case the beacon has a VHT IE but the HT cap indicates transmitter only support 20Mhz. In both of these cases, we currently avoid VHT and use only HT this means we can't use the highest rates (MCS8), so fixing this leads to throughput improvements. Reported-by: Michal Kazior Reported-by: Eyal Shapira Signed-off-by: Johannes Berg --- net/mac80211/vht.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c index e9e36a256165..9265adfdabfc 100644 --- a/net/mac80211/vht.c +++ b/net/mac80211/vht.c @@ -129,9 +129,12 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, if (!vht_cap_ie || !sband->vht_cap.vht_supported) return; - /* A VHT STA must support 40 MHz */ - if (!(sta->sta.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)) - return; + /* + * A VHT STA must support 40 MHz, but if we verify that here + * then we break a few things - some APs (e.g. Netgear R6300v2 + * and others based on the BCM4360 chipset) will unset this + * capability bit when operating in 20 MHz. + */ vht_cap->vht_supported = true; -- cgit v1.2.3 From a7008ee1a423720e755e08f33b63669795c1f072 Mon Sep 17 00:00:00 2001 From: Vincent Donnefort Date: Tue, 15 Apr 2014 14:21:43 +0200 Subject: gpio: ich: set regs and reglen for i3100 and ich6 chipset This patch fixes kernel NULL pointer BUG introduced by the following commit: b667cf488aa9476b0ab64acd91f2a96f188cfd21 gpio: ich: Add support for multiple register addresses. Signed-off-by: Vincent Donnefort Tested-by: Eric Paris Signed-off-by: Linus Walleij --- drivers/gpio/gpio-ich.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpio/gpio-ich.c b/drivers/gpio/gpio-ich.c index e73c6755a5eb..70304220a479 100644 --- a/drivers/gpio/gpio-ich.c +++ b/drivers/gpio/gpio-ich.c @@ -305,6 +305,8 @@ static struct ichx_desc ich6_desc = { .ngpio = 50, .have_blink = true, + .regs = ichx_regs, + .reglen = ichx_reglen, }; /* Intel 3100 */ @@ -324,6 +326,8 @@ static struct ichx_desc i3100_desc = { .uses_gpe0 = true, .ngpio = 50, + .regs = ichx_regs, + .reglen = ichx_reglen, }; /* ICH7 and ICH8-based */ -- cgit v1.2.3 From 99e4b98dbe3ad1fe38a74d12c3b8d44a55930de4 Mon Sep 17 00:00:00 2001 From: Michael Welling Date: Wed, 16 Apr 2014 20:00:24 -0500 Subject: gpio: mcp23s08: Bug fix of SPI device tree registration. The chips variable needs to be incremented for each chip that is found in the spi_present_mask when registering via device tree. Without this and the checking a negative index is passed to the data->chip array in a subsequent loop. Cc: stable@vger.kernel.org Signed-off-by: Michael Welling Acked-by: Peter Korsgaard Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mcp23s08.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/gpio/gpio-mcp23s08.c b/drivers/gpio/gpio-mcp23s08.c index 99a68310e7c0..3d53fd6880d1 100644 --- a/drivers/gpio/gpio-mcp23s08.c +++ b/drivers/gpio/gpio-mcp23s08.c @@ -894,9 +894,11 @@ static int mcp23s08_probe(struct spi_device *spi) dev_err(&spi->dev, "invalid spi-present-mask\n"); return -ENODEV; } - - for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++) + for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++) { + if ((spi_present_mask & (1 << addr))) + chips++; pullups[addr] = 0; + } } else { type = spi_get_device_id(spi)->driver_data; pdata = dev_get_platdata(&spi->dev); @@ -919,12 +921,12 @@ static int mcp23s08_probe(struct spi_device *spi) pullups[addr] = pdata->chip[addr].pullups; } - if (!chips) - return -ENODEV; - base = pdata->base; } + if (!chips) + return -ENODEV; + data = kzalloc(sizeof(*data) + chips * sizeof(struct mcp23s08), GFP_KERNEL); if (!data) -- cgit v1.2.3 From f9ac71bfcc5c937ff02765dc316cf5bc01d21d97 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 26 Feb 2014 14:46:35 +0200 Subject: mac80211: fix vif name tracing If sdata doesn't have a valid dev (e.g. in case of monitor vif), the vif_name field was initialized with (a length of) some short string, but later was set to a different, potentially larger one. This resulted in out-of-bounds write, which usually appeared as garbage in the trace log. Simply trace sdata->name, as it should always have the correct name for both cases. Signed-off-by: Eliad Peller Signed-off-by: Johannes Berg --- net/mac80211/trace.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index a0b0aea76525..cec5b60487a4 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h @@ -21,10 +21,10 @@ #define VIF_ENTRY __field(enum nl80211_iftype, vif_type) __field(void *, sdata) \ __field(bool, p2p) \ - __string(vif_name, sdata->dev ? sdata->dev->name : "") + __string(vif_name, sdata->name) #define VIF_ASSIGN __entry->vif_type = sdata->vif.type; __entry->sdata = sdata; \ __entry->p2p = sdata->vif.p2p; \ - __assign_str(vif_name, sdata->dev ? sdata->dev->name : sdata->name) + __assign_str(vif_name, sdata->name) #define VIF_PR_FMT " vif:%s(%d%s)" #define VIF_PR_ARG __get_str(vif_name), __entry->vif_type, __entry->p2p ? "/p2p" : "" -- cgit v1.2.3 From cf01f4eef9fe367ec0d85b38dd7214e29e376cdb Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Fri, 9 May 2014 11:41:54 -0400 Subject: locks: only validate the lock vs. f_mode in F_SETLK codepaths v2: replace missing break in switch statement (as pointed out by Dave Jones) commit bce7560d4946 (locks: consolidate checks for compatible filp->f_mode values in setlk handlers) introduced a regression in the F_GETLK handler. flock64_to_posix_lock is a shared codepath between F_GETLK and F_SETLK, but the f_mode checks should only be applicable to the F_SETLK codepaths according to POSIX. Instead of just reverting the patch, add a new function to do this checking and have the F_SETLK handlers call it. Cc: Dave Jones Reported-and-Tested-by: Reuben Farrelly Signed-off-by: Jeff Layton --- fs/locks.c | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/fs/locks.c b/fs/locks.c index e663aeac579e..e390bd9ae068 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -389,18 +389,6 @@ static int flock64_to_posix_lock(struct file *filp, struct file_lock *fl, fl->fl_ops = NULL; fl->fl_lmops = NULL; - /* Ensure that fl->fl_filp has compatible f_mode */ - switch (l->l_type) { - case F_RDLCK: - if (!(filp->f_mode & FMODE_READ)) - return -EBADF; - break; - case F_WRLCK: - if (!(filp->f_mode & FMODE_WRITE)) - return -EBADF; - break; - } - return assign_type(fl, l->l_type); } @@ -2034,6 +2022,22 @@ static int do_lock_file_wait(struct file *filp, unsigned int cmd, return error; } +/* Ensure that fl->fl_filp has compatible f_mode for F_SETLK calls */ +static int +check_fmode_for_setlk(struct file_lock *fl) +{ + switch (fl->fl_type) { + case F_RDLCK: + if (!(fl->fl_file->f_mode & FMODE_READ)) + return -EBADF; + break; + case F_WRLCK: + if (!(fl->fl_file->f_mode & FMODE_WRITE)) + return -EBADF; + } + return 0; +} + /* Apply the lock described by l to an open file descriptor. * This implements both the F_SETLK and F_SETLKW commands of fcntl(). */ @@ -2071,6 +2075,10 @@ again: if (error) goto out; + error = check_fmode_for_setlk(file_lock); + if (error) + goto out; + /* * If the cmd is requesting file-private locks, then set the * FL_OFDLCK flag and override the owner. @@ -2206,6 +2214,10 @@ again: if (error) goto out; + error = check_fmode_for_setlk(file_lock); + if (error) + goto out; + /* * If the cmd is requesting file-private locks, then set the * FL_OFDLCK flag and override the owner. -- cgit v1.2.3 From 722a0d22d028bd74061cf582de1764884e73674f Mon Sep 17 00:00:00 2001 From: Andres Freund Date: Fri, 9 May 2014 03:29:16 +0200 Subject: x86: Fix typo preventing msr_set/clear_bit from having an effect Due to a typo the msr accessor function introduced in 22085a66c2fab6cf9b9393c056a3600a6b4735de didn't have any lasting effects because they accidentally wrote the old value back. After c0a639ad0bc6b178b46996bd1f821a04643e2bde this at the very least this causes cpuid limits not to be lifted on some cpus leading to missing capabilities for those. Signed-off-by: Andres Freund Link: http://lkml.kernel.org/r/1399598957-7011-2-git-send-email-andres@anarazel.de Cc: Borislav Petkov Signed-off-by: H. Peter Anvin --- arch/x86/lib/msr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/lib/msr.c b/arch/x86/lib/msr.c index db9db446b71a..43623739c7cf 100644 --- a/arch/x86/lib/msr.c +++ b/arch/x86/lib/msr.c @@ -76,7 +76,7 @@ static inline int __flip_bit(u32 msr, u8 bit, bool set) if (m1.q == m.q) return 0; - err = msr_write(msr, &m); + err = msr_write(msr, &m1); if (err) return err; -- cgit v1.2.3 From c45f77364ba060395b7eff1bf45e6c537f913380 Mon Sep 17 00:00:00 2001 From: Andres Freund Date: Fri, 9 May 2014 03:29:17 +0200 Subject: x86: Fix typo in MSR_IA32_MISC_ENABLE_LIMIT_CPUID macro The spuriously added semicolon didn't have any effect because the macro isn't currently in use. c0a639ad0bc6b178b46996bd1f821a04643e2bde Signed-off-by: Andres Freund Link: http://lkml.kernel.org/r/1399598957-7011-3-git-send-email-andres@anarazel.de Cc: Borislav Petkov Signed-off-by: H. Peter Anvin --- arch/x86/include/uapi/asm/msr-index.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/include/uapi/asm/msr-index.h b/arch/x86/include/uapi/asm/msr-index.h index c827ace3121b..fcf2b3ae1bf0 100644 --- a/arch/x86/include/uapi/asm/msr-index.h +++ b/arch/x86/include/uapi/asm/msr-index.h @@ -384,7 +384,7 @@ #define MSR_IA32_MISC_ENABLE_MWAIT_BIT 18 #define MSR_IA32_MISC_ENABLE_MWAIT (1ULL << MSR_IA32_MISC_ENABLE_MWAIT_BIT) #define MSR_IA32_MISC_ENABLE_LIMIT_CPUID_BIT 22 -#define MSR_IA32_MISC_ENABLE_LIMIT_CPUID (1ULL << MSR_IA32_MISC_ENABLE_LIMIT_CPUID_BIT); +#define MSR_IA32_MISC_ENABLE_LIMIT_CPUID (1ULL << MSR_IA32_MISC_ENABLE_LIMIT_CPUID_BIT) #define MSR_IA32_MISC_ENABLE_XTPR_DISABLE_BIT 23 #define MSR_IA32_MISC_ENABLE_XTPR_DISABLE (1ULL << MSR_IA32_MISC_ENABLE_XTPR_DISABLE_BIT) #define MSR_IA32_MISC_ENABLE_XD_DISABLE_BIT 34 -- cgit v1.2.3 From 28b92e09e25bdc0ae864b22eacf195a74f861389 Mon Sep 17 00:00:00 2001 From: Boris Ostrovsky Date: Fri, 9 May 2014 11:11:27 -0400 Subject: x86, vdso, time: Cast tv_nsec to u64 for proper shifting in update_vsyscall() With tk->wall_to_monotonic.tv_nsec being a 32-bit value on 32-bit systems, (tk->wall_to_monotonic.tv_nsec << tk->shift) in update_vsyscall() may lose upper bits or, worse, add them since compiler will do this: (u64)(tk->wall_to_monotonic.tv_nsec << tk->shift) instead of ((u64)tk->wall_to_monotonic.tv_nsec << tk->shift) So if, for example, tv_nsec is 0x800000 and shift is 8 we will end up with 0xffffffff80000000 instead of 0x80000000. And then we are stuck in the subsequent 'while' loop. We need an explicit cast. Signed-off-by: Boris Ostrovsky Link: http://lkml.kernel.org/r/1399648287-15178-1-git-send-email-boris.ostrovsky@oracle.com Acked-by: Konrad Rzeszutek Wilk Cc: # v3.14 Signed-off-by: H. Peter Anvin --- arch/x86/kernel/vsyscall_gtod.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/vsyscall_gtod.c b/arch/x86/kernel/vsyscall_gtod.c index f9c6e56e14b5..9531fbb123ba 100644 --- a/arch/x86/kernel/vsyscall_gtod.c +++ b/arch/x86/kernel/vsyscall_gtod.c @@ -43,7 +43,7 @@ void update_vsyscall(struct timekeeper *tk) vdata->monotonic_time_sec = tk->xtime_sec + tk->wall_to_monotonic.tv_sec; vdata->monotonic_time_snsec = tk->xtime_nsec - + (tk->wall_to_monotonic.tv_nsec + + ((u64)tk->wall_to_monotonic.tv_nsec << tk->shift); while (vdata->monotonic_time_snsec >= (((u64)NSEC_PER_SEC) << tk->shift)) { -- cgit v1.2.3 From 6b5eeb7f874b689403e52a646e485d0191ab9507 Mon Sep 17 00:00:00 2001 From: Bjørn Mork Date: Fri, 9 May 2014 14:45:00 +0200 Subject: net: cdc_mbim: handle unaccelerated VLAN tagged frames MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This driver maps 802.1q VLANs to MBIM sessions. The mapping is based on a bogus assumption that all tagged frames will use the acceleration API because we enable NETIF_F_HW_VLAN_CTAG_TX. This fails for e.g. frames tagged in userspace using packet sockets. Such frames will erroneously be considered as untagged and silently dropped based on not being IP. Fix by falling back to looking into the ethernet header for a tag if no accelerated tag was found. Fixes: a82c7ce5bc5b ("net: cdc_ncm: map MBIM IPS SessionID to VLAN ID") Cc: Greg Suarez Signed-off-by: Bjørn Mork Signed-off-by: David S. Miller --- drivers/net/usb/cdc_mbim.c | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/drivers/net/usb/cdc_mbim.c b/drivers/net/usb/cdc_mbim.c index 13f7705fd679..2e025ddcef21 100644 --- a/drivers/net/usb/cdc_mbim.c +++ b/drivers/net/usb/cdc_mbim.c @@ -120,6 +120,16 @@ static void cdc_mbim_unbind(struct usbnet *dev, struct usb_interface *intf) cdc_ncm_unbind(dev, intf); } +/* verify that the ethernet protocol is IPv4 or IPv6 */ +static bool is_ip_proto(__be16 proto) +{ + switch (proto) { + case htons(ETH_P_IP): + case htons(ETH_P_IPV6): + return true; + } + return false; +} static struct sk_buff *cdc_mbim_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) { @@ -128,6 +138,7 @@ static struct sk_buff *cdc_mbim_tx_fixup(struct usbnet *dev, struct sk_buff *skb struct cdc_ncm_ctx *ctx = info->ctx; __le32 sign = cpu_to_le32(USB_CDC_MBIM_NDP16_IPS_SIGN); u16 tci = 0; + bool is_ip; u8 *c; if (!ctx) @@ -137,25 +148,32 @@ static struct sk_buff *cdc_mbim_tx_fixup(struct usbnet *dev, struct sk_buff *skb if (skb->len <= ETH_HLEN) goto error; + /* Some applications using e.g. packet sockets will + * bypass the VLAN acceleration and create tagged + * ethernet frames directly. We primarily look for + * the accelerated out-of-band tag, but fall back if + * required + */ + skb_reset_mac_header(skb); + if (vlan_get_tag(skb, &tci) < 0 && skb->len > VLAN_ETH_HLEN && + __vlan_get_tag(skb, &tci) == 0) { + is_ip = is_ip_proto(vlan_eth_hdr(skb)->h_vlan_encapsulated_proto); + skb_pull(skb, VLAN_ETH_HLEN); + } else { + is_ip = is_ip_proto(eth_hdr(skb)->h_proto); + skb_pull(skb, ETH_HLEN); + } + /* mapping VLANs to MBIM sessions: * no tag => IPS session <0> * 1 - 255 => IPS session * 256 - 511 => DSS session * 512 - 4095 => unsupported, drop */ - vlan_get_tag(skb, &tci); - switch (tci & 0x0f00) { case 0x0000: /* VLAN ID 0 - 255 */ - /* verify that datagram is IPv4 or IPv6 */ - skb_reset_mac_header(skb); - switch (eth_hdr(skb)->h_proto) { - case htons(ETH_P_IP): - case htons(ETH_P_IPV6): - break; - default: + if (!is_ip) goto error; - } c = (u8 *)&sign; c[3] = tci; break; @@ -169,7 +187,6 @@ static struct sk_buff *cdc_mbim_tx_fixup(struct usbnet *dev, struct sk_buff *skb "unsupported tci=0x%04x\n", tci); goto error; } - skb_pull(skb, ETH_HLEN); } spin_lock_bh(&ctx->mtx); -- cgit v1.2.3 From 05adaf1f101f25f40f12c29403e6488f0e45f6b6 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 9 May 2014 14:52:34 +0300 Subject: drm/i915/vlv: reset VLV media force wake request register Media force wake get hangs the machine when the system is booted without displays attached. The assumption is that (at least some versions of) the firmware has skipped some initialization in that case. Empirical evidence suggests we need to reset the media force wake request register in addition to the render one to avoid hangs. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=75895 Reported-by: Imre Deak Reported-by: Darren Hart Tested-by: Darren Hart Reviewed-by: Mika Kuoppala Cc: stable@vger.kernel.org Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_uncore.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index f729dc71d5be..d0c75779d3f6 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -185,6 +185,8 @@ static void vlv_force_wake_reset(struct drm_i915_private *dev_priv) { __raw_i915_write32(dev_priv, FORCEWAKE_VLV, _MASKED_BIT_DISABLE(0xffff)); + __raw_i915_write32(dev_priv, FORCEWAKE_MEDIA_VLV, + _MASKED_BIT_DISABLE(0xffff)); /* something from same cacheline, but !FORCEWAKE_VLV */ __raw_posting_read(dev_priv, FORCEWAKE_ACK_VLV); } -- cgit v1.2.3 From 0953f78971040fff09064bb564d9ac0cd1fb4e69 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 8 May 2014 10:09:20 +0200 Subject: net: mdio-gpio: fix device-tree binding documentation Fix aliases syntax in device-tree binding example to avoid copy-paste errors (the alias would be dropped silently). Signed-off-by: Johan Hovold Signed-off-by: David S. Miller --- Documentation/devicetree/bindings/net/mdio-gpio.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/net/mdio-gpio.txt b/Documentation/devicetree/bindings/net/mdio-gpio.txt index c79bab025369..8dbcf8295c6c 100644 --- a/Documentation/devicetree/bindings/net/mdio-gpio.txt +++ b/Documentation/devicetree/bindings/net/mdio-gpio.txt @@ -14,7 +14,7 @@ node. Example: aliases { - mdio-gpio0 = <&mdio0>; + mdio-gpio0 = &mdio0; }; mdio0: mdio { -- cgit v1.2.3 From 7f52da56f76f61112a9c1db41975376764828e71 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 8 May 2014 10:09:21 +0200 Subject: net: mdio-gpio: warn about missing bus alias id Use a sane default bus id (rather than -ENODEV) and print a warning when the bus alias id is missing. Signed-off-by: Johan Hovold Signed-off-by: David S. Miller --- drivers/net/phy/mdio-gpio.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c index 9c4defdec67b..5f1a2250018f 100644 --- a/drivers/net/phy/mdio-gpio.c +++ b/drivers/net/phy/mdio-gpio.c @@ -215,6 +215,10 @@ static int mdio_gpio_probe(struct platform_device *pdev) if (pdev->dev.of_node) { pdata = mdio_gpio_of_get_data(pdev); bus_id = of_alias_get_id(pdev->dev.of_node, "mdio-gpio"); + if (bus_id < 0) { + dev_warn(&pdev->dev, "failed to get alias id\n"); + bus_id = 0; + } } else { pdata = dev_get_platdata(&pdev->dev); bus_id = pdev->id; -- cgit v1.2.3 From 59993f48b38fd46863b23bb1bb1dc3291e7278fb Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 8 May 2014 10:09:22 +0200 Subject: Revert "net: eth: cpsw: Correctly attach to GPIO bitbang MDIO driver" This reverts commit f8d56d8f892be43a2404356073e16401eb5a42e6 ("net: eth: cpsw: Correctly attach to GPIO bitbang MDIO driver"). Fix potential null-pointer dereference at probe if the mdio-gpio device has not been successfully probed yet. The offending commit is plain wrong for a number of reasons. First of all it accesses internal driver data of an unrelated device. Neither does it check that the data is non-null (which it is in case the device has not been probed yet). Furthermore, the decision on whether to treat any driver data according to the mdio-gpio driver's internals is made based on the node name. But the name is not compared against "mdio" which is the normal name for the node, but rather against "gpio" which the node does not have to be named (and shouldn't be according to the binding documentation). [ If this hack is to be kept out-of-tree it should at least be matching against the compatible property. ] Cc: Stefan Roese Cc: stable # v3.14 Signed-off-by: Johan Hovold Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/cpsw.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index 36aa109416c4..18d83d8d7f74 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@ -1871,18 +1871,8 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data, mdio_node = of_find_node_by_phandle(be32_to_cpup(parp)); phyid = be32_to_cpup(parp+1); mdio = of_find_device_by_node(mdio_node); - - if (strncmp(mdio->name, "gpio", 4) == 0) { - /* GPIO bitbang MDIO driver attached */ - struct mii_bus *bus = dev_get_drvdata(&mdio->dev); - - snprintf(slave_data->phy_id, sizeof(slave_data->phy_id), - PHY_ID_FMT, bus->id, phyid); - } else { - /* davinci MDIO driver attached */ - snprintf(slave_data->phy_id, sizeof(slave_data->phy_id), - PHY_ID_FMT, mdio->name, phyid); - } + snprintf(slave_data->phy_id, sizeof(slave_data->phy_id), + PHY_ID_FMT, mdio->name, phyid); mac_addr = of_get_mac_address(slave_node); if (mac_addr) -- cgit v1.2.3 From 6954cc1f238199e971ec905c5cc87120806ac981 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 8 May 2014 10:09:23 +0200 Subject: net: cpsw: fix null dereference at probe Fix null-pointer dereference at probe when the mdio platform device is missing (e.g. when it has been disabled in DT). Cc: stable # v3.8 Signed-off-by: Johan Hovold Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/cpsw.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index 18d83d8d7f74..db9360cd861c 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@ -1871,6 +1871,10 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data, mdio_node = of_find_node_by_phandle(be32_to_cpup(parp)); phyid = be32_to_cpup(parp+1); mdio = of_find_device_by_node(mdio_node); + if (!mdio) { + pr_err("Missing mdio platform device\n"); + return -EINVAL; + } snprintf(slave_data->phy_id, sizeof(slave_data->phy_id), PHY_ID_FMT, mdio->name, phyid); -- cgit v1.2.3 From 60e71ab56b5fbd839aaef4f4af7778d86e0206f0 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 8 May 2014 10:09:24 +0200 Subject: net: cpsw: add missing of_node_put Add missing of_node_put to avoid kref leak. Signed-off-by: Johan Hovold Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/cpsw.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index db9360cd861c..c331b7ebc812 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@ -1871,6 +1871,7 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data, mdio_node = of_find_node_by_phandle(be32_to_cpup(parp)); phyid = be32_to_cpup(parp+1); mdio = of_find_device_by_node(mdio_node); + of_node_put(mdio_node); if (!mdio) { pr_err("Missing mdio platform device\n"); return -EINVAL; -- cgit v1.2.3 From de682941eef3e5f6d1b653a6c214bc8a288f17c1 Mon Sep 17 00:00:00 2001 From: Yuval Mintz Date: Thu, 8 May 2014 12:34:31 +0300 Subject: bnx2x: Fix UNDI driver unload Commit 91ebb928b "bnx2x: Add support for Multi-Function UNDI" contains a bug which prevent the emptying of the device's Rx buffers before reset. As a result, on new boards it is likely HW will reach some fatal assertion once its interfaces load after UNDI was previously loaded. Signed-off-by: Yuval Mintz Signed-off-by: Ariel Elior Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index b260913db236..3b0d43154e67 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -10051,8 +10051,8 @@ static void bnx2x_prev_unload_close_mac(struct bnx2x *bp, #define BCM_5710_UNDI_FW_MF_MAJOR (0x07) #define BCM_5710_UNDI_FW_MF_MINOR (0x08) #define BCM_5710_UNDI_FW_MF_VERS (0x05) -#define BNX2X_PREV_UNDI_MF_PORT(p) (0x1a150c + ((p) << 4)) -#define BNX2X_PREV_UNDI_MF_FUNC(f) (0x1a184c + ((f) << 4)) +#define BNX2X_PREV_UNDI_MF_PORT(p) (BAR_TSTRORM_INTMEM + 0x150c + ((p) << 4)) +#define BNX2X_PREV_UNDI_MF_FUNC(f) (BAR_TSTRORM_INTMEM + 0x184c + ((f) << 4)) static bool bnx2x_prev_unload_undi_fw_supports_mf(struct bnx2x *bp) { u8 major, minor, version; @@ -10352,6 +10352,7 @@ static int bnx2x_prev_unload_common(struct bnx2x *bp) /* Reset should be performed after BRB is emptied */ if (reset_reg & MISC_REGISTERS_RESET_REG_1_RST_BRB1) { u32 timer_count = 1000; + bool need_write = true; /* Close the MAC Rx to prevent BRB from filling up */ bnx2x_prev_unload_close_mac(bp, &mac_vals); @@ -10398,7 +10399,10 @@ static int bnx2x_prev_unload_common(struct bnx2x *bp) * cleaning methods - might be redundant but harmless. */ if (bnx2x_prev_unload_undi_fw_supports_mf(bp)) { - bnx2x_prev_unload_undi_mf(bp); + if (need_write) { + bnx2x_prev_unload_undi_mf(bp); + need_write = false; + } } else if (prev_undi) { /* If UNDI resides in memory, * manually increment it -- cgit v1.2.3 From d6d211db37e75de2ddc3a4f979038c40df7cc79c Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 9 May 2014 13:10:52 -0700 Subject: Linux 3.15-rc5 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 28a7259e0f3b..8a8440a3578e 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 3 PATCHLEVEL = 15 SUBLEVEL = 0 -EXTRAVERSION = -rc4 +EXTRAVERSION = -rc5 NAME = Shuffling Zombie Juror # *DOCUMENTATION* -- cgit v1.2.3 From a9de0500083c18589ba2ea4543135c1bea8419ec Mon Sep 17 00:00:00 2001 From: Emil Goode Date: Fri, 9 May 2014 01:07:17 +0200 Subject: net: cassini: use nested lock annotation In the cas_lock_tx function we acquire multiple locks in a loop and need to use nested lock annotation to prevent lockdep warnings. Reported-by: Meelis Roos Signed-off-by: Emil Goode Signed-off-by: David S. Miller --- drivers/net/ethernet/sun/cassini.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/sun/cassini.c b/drivers/net/ethernet/sun/cassini.c index df8d383acf48..b9ac20f42651 100644 --- a/drivers/net/ethernet/sun/cassini.c +++ b/drivers/net/ethernet/sun/cassini.c @@ -246,7 +246,7 @@ static inline void cas_lock_tx(struct cas *cp) int i; for (i = 0; i < N_TX_RINGS; i++) - spin_lock(&cp->tx_lock[i]); + spin_lock_nested(&cp->tx_lock[i], i); } static inline void cas_lock_all(struct cas *cp) -- cgit v1.2.3 From c1e517fbbcdb13f50662af4edc11c3251fe44f86 Mon Sep 17 00:00:00 2001 From: Simon Wunderlich Date: Wed, 26 Mar 2014 15:46:21 +0100 Subject: batman-adv: fix neigh_ifinfo imbalance The neigh_ifinfo object must be freed if it has been used in batadv_iv_ogm_process_per_outif(). This is a regression introduced by 89652331c00f43574515059ecbf262d26d885717 ("batman-adv: split tq information in neigh_node struct") Reported-by: Antonio Quartulli Signed-off-by: Simon Wunderlich Signed-off-by: Marek Lindner Signed-off-by: Antonio Quartulli --- net/batman-adv/bat_iv_ogm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index b3bd4ec3fd94..f04224c32005 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c @@ -1545,6 +1545,8 @@ out_neigh: if ((orig_neigh_node) && (!is_single_hop_neigh)) batadv_orig_node_free_ref(orig_neigh_node); out: + if (router_ifinfo) + batadv_neigh_ifinfo_free_ref(router_ifinfo); if (router) batadv_neigh_node_free_ref(router); if (router_router) -- cgit v1.2.3 From 000c8dff97311357535d64539e58990526e4de70 Mon Sep 17 00:00:00 2001 From: Simon Wunderlich Date: Wed, 26 Mar 2014 15:46:22 +0100 Subject: batman-adv: fix neigh reference imbalance When an interface is removed from batman-adv, the orig_ifinfo of a orig_node may be removed without releasing the router first. This will prevent the reference for the neighbor pointed at by the orig_ifinfo->router to be released, and this leak may result in reference leaks for the interface used by this neighbor. Fix that. This is a regression introduced by 7351a4822d42827ba0110677c0cbad88a3d52585 ("batman-adv: split out router from orig_node"). Reported-by: Antonio Quartulli Signed-off-by: Simon Wunderlich Signed-off-by: Marek Lindner Signed-off-by: Antonio Quartulli --- net/batman-adv/originator.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index ffd9dfbd9b0e..a43da6918512 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c @@ -501,12 +501,17 @@ batadv_neigh_node_get(const struct batadv_orig_node *orig_node, static void batadv_orig_ifinfo_free_rcu(struct rcu_head *rcu) { struct batadv_orig_ifinfo *orig_ifinfo; + struct batadv_neigh_node *router; orig_ifinfo = container_of(rcu, struct batadv_orig_ifinfo, rcu); if (orig_ifinfo->if_outgoing != BATADV_IF_DEFAULT) batadv_hardif_free_ref_now(orig_ifinfo->if_outgoing); + /* this is the last reference to this object */ + router = rcu_dereference_protected(orig_ifinfo->router, true); + if (router) + batadv_neigh_node_free_ref_now(router); kfree(orig_ifinfo); } -- cgit v1.2.3 From 7b955a9fc164487d7c51acb9787f6d1b01b35ef6 Mon Sep 17 00:00:00 2001 From: Simon Wunderlich Date: Wed, 26 Mar 2014 15:46:23 +0100 Subject: batman-adv: always run purge_orig_neighbors The current code will not execute batadv_purge_orig_neighbors() when an orig_ifinfo has already been purged. However we need to run it in any case. Fix that. This is a regression introduced by 7351a4822d42827ba0110677c0cbad88a3d52585 ("batman-adv: split out router from orig_node") Signed-off-by: Simon Wunderlich Signed-off-by: Marek Lindner Signed-off-by: Antonio Quartulli --- net/batman-adv/originator.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index a43da6918512..8104c3cf7741 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c @@ -862,7 +862,7 @@ static bool batadv_purge_orig_node(struct batadv_priv *bat_priv, { struct batadv_neigh_node *best_neigh_node; struct batadv_hard_iface *hard_iface; - bool changed; + bool changed_ifinfo, changed_neigh; if (batadv_has_timed_out(orig_node->last_seen, 2 * BATADV_PURGE_TIMEOUT)) { @@ -872,10 +872,10 @@ static bool batadv_purge_orig_node(struct batadv_priv *bat_priv, jiffies_to_msecs(orig_node->last_seen)); return true; } - changed = batadv_purge_orig_ifinfo(bat_priv, orig_node); - changed = changed || batadv_purge_orig_neighbors(bat_priv, orig_node); + changed_ifinfo = batadv_purge_orig_ifinfo(bat_priv, orig_node); + changed_neigh = batadv_purge_orig_neighbors(bat_priv, orig_node); - if (!changed) + if (!changed_ifinfo && !changed_neigh) return false; /* first for NULL ... */ -- cgit v1.2.3 From 3afcb96fee9ba33ce838f2ceaa248358cffe2f56 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 10 May 2014 13:51:36 +0200 Subject: ACPI / proc: Do not say when /proc interfaces will be deleted in Kconfig Do not tell people in the Kconfig help when exactly we are going to remove the deprecated ACPI interfaces in /proc, because, honestly, we don't know. We will remove them when they are not used any more. In particular, do not tell them that the interfaces will be removed in a kernel release that already happened long ago. Signed-off-by: Rafael J. Wysocki --- drivers/acpi/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index c0160bb451e9..a34a22841002 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -60,7 +60,7 @@ config ACPI_PROCFS_POWER This option has no effect on /proc/acpi/ directories and functions, which do not yet exist in /sys This option, together with the proc directories, will be - deleted in 2.6.39. + deleted in the future. Say N to delete power /proc/acpi/ directories that have moved to /sys/ -- cgit v1.2.3 From d088be8042841f024156ee68fecfef7503d660cb Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Sat, 10 May 2014 13:39:21 +0200 Subject: netfilter: nf_tables: reset rule number counter after jump and goto Otherwise we start incrementing the rule number counter from the previous chain iteration. Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_tables_core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c index 804105391b9a..4368c5850548 100644 --- a/net/netfilter/nf_tables_core.c +++ b/net/netfilter/nf_tables_core.c @@ -123,7 +123,7 @@ nft_do_chain(struct nft_pktinfo *pkt, const struct nf_hook_ops *ops) struct nft_data data[NFT_REG_MAX + 1]; unsigned int stackptr = 0; struct nft_jumpstack jumpstack[NFT_JUMP_STACK_SIZE]; - int rulenum = 0; + int rulenum; /* * Cache cursor to avoid problems in case that the cursor is updated * while traversing the ruleset. @@ -131,6 +131,7 @@ nft_do_chain(struct nft_pktinfo *pkt, const struct nf_hook_ops *ops) unsigned int gencursor = ACCESS_ONCE(chain->net->nft.gencursor); do_chain: + rulenum = 0; rule = list_entry(&chain->rules, struct nft_rule, list); next_rule: data[NFT_REG_VERDICT].verdict = NFT_CONTINUE; -- cgit v1.2.3 From 6d66da89bf4422c0a0693627fb3e25f74af50f92 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Tue, 6 May 2014 13:01:34 +0200 Subject: ARM: dts: i.MX53: Fix ipu register space size The IPU register space is 128MB, not 2GB. Fixes: abed9a6bf2bb 'ARM i.MX53: Add IPU support' Signed-off-by: Sascha Hauer Acked-by: Shawn Guo Cc: Signed-off-by: Olof Johansson --- arch/arm/boot/dts/imx53.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/imx53.dtsi b/arch/arm/boot/dts/imx53.dtsi index 9c2bff2252d0..6a1bf4ff83d5 100644 --- a/arch/arm/boot/dts/imx53.dtsi +++ b/arch/arm/boot/dts/imx53.dtsi @@ -115,7 +115,7 @@ #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx53-ipu"; - reg = <0x18000000 0x080000000>; + reg = <0x18000000 0x08000000>; interrupts = <11 10>; clocks = <&clks IMX5_CLK_IPU_GATE>, <&clks IMX5_CLK_IPU_DI0_GATE>, -- cgit v1.2.3 From 90f4c5944b38b4647373db7a57a2dda1e0c5566a Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Tue, 6 May 2014 12:09:45 -0400 Subject: MAINTAINERS: update Broadcom ARM tree location and add an SoC family The Broadcom ARM tree location has changed names to reflect other SoC families that are queued here. Also add the 216xx family as maintained. Signed-off-by: Matt Porter Signed-off-by: Olof Johansson --- MAINTAINERS | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index e67ea2442041..6031c813d63b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1893,14 +1893,15 @@ L: netdev@vger.kernel.org S: Supported F: drivers/net/ethernet/broadcom/bnx2x/ -BROADCOM BCM281XX/BCM11XXX ARM ARCHITECTURE +BROADCOM BCM281XX/BCM11XXX/BCM216XX ARM ARCHITECTURE M: Christian Daudt M: Matt Porter L: bcm-kernel-feedback-list@broadcom.com -T: git git://git.github.com/broadcom/bcm11351 +T: git git://github.com/broadcom/mach-bcm S: Maintained F: arch/arm/mach-bcm/ F: arch/arm/boot/dts/bcm113* +F: arch/arm/boot/dts/bcm216* F: arch/arm/boot/dts/bcm281* F: arch/arm/configs/bcm_defconfig F: drivers/mmc/host/sdhci_bcm_kona.c -- cgit v1.2.3 From 709de13f0c532fe9c468c094aff069a725ed57fe Mon Sep 17 00:00:00 2001 From: Simon Wunderlich Date: Wed, 26 Mar 2014 15:46:24 +0100 Subject: batman-adv: fix removing neigh_ifinfo When an interface is removed separately, all neighbors need to be checked if they have a neigh_ifinfo structure for that particular interface. If that is the case, remove that ifinfo so any references to a hard interface can be freed. This is a regression introduced by 89652331c00f43574515059ecbf262d26d885717 ("batman-adv: split tq information in neigh_node struct") Reported-by: Antonio Quartulli Signed-off-by: Simon Wunderlich Signed-off-by: Marek Lindner Signed-off-by: Antonio Quartulli --- net/batman-adv/originator.c | 46 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index 8104c3cf7741..1785da37b82c 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c @@ -706,6 +706,47 @@ free_orig_node: return NULL; } +/** + * batadv_purge_neigh_ifinfo - purge obsolete ifinfo entries from neighbor + * @bat_priv: the bat priv with all the soft interface information + * @neigh: orig node which is to be checked + */ +static void +batadv_purge_neigh_ifinfo(struct batadv_priv *bat_priv, + struct batadv_neigh_node *neigh) +{ + struct batadv_neigh_ifinfo *neigh_ifinfo; + struct batadv_hard_iface *if_outgoing; + struct hlist_node *node_tmp; + + spin_lock_bh(&neigh->ifinfo_lock); + + /* for all ifinfo objects for this neighinator */ + hlist_for_each_entry_safe(neigh_ifinfo, node_tmp, + &neigh->ifinfo_list, list) { + if_outgoing = neigh_ifinfo->if_outgoing; + + /* always keep the default interface */ + if (if_outgoing == BATADV_IF_DEFAULT) + continue; + + /* don't purge if the interface is not (going) down */ + if ((if_outgoing->if_status != BATADV_IF_INACTIVE) && + (if_outgoing->if_status != BATADV_IF_NOT_IN_USE) && + (if_outgoing->if_status != BATADV_IF_TO_BE_REMOVED)) + continue; + + batadv_dbg(BATADV_DBG_BATMAN, bat_priv, + "neighbor/ifinfo purge: neighbor %pM, iface: %s\n", + neigh->addr, if_outgoing->net_dev->name); + + hlist_del_rcu(&neigh_ifinfo->list); + batadv_neigh_ifinfo_free_ref(neigh_ifinfo); + } + + spin_unlock_bh(&neigh->ifinfo_lock); +} + /** * batadv_purge_orig_ifinfo - purge obsolete ifinfo entries from originator * @bat_priv: the bat priv with all the soft interface information @@ -805,6 +846,11 @@ batadv_purge_orig_neighbors(struct batadv_priv *bat_priv, hlist_del_rcu(&neigh_node->list); batadv_neigh_node_free_ref(neigh_node); + } else { + /* only necessary if not the whole neighbor is to be + * deleted, but some interface has been removed. + */ + batadv_purge_neigh_ifinfo(bat_priv, neigh_node); } } -- cgit v1.2.3 From 282cba6b00a95f0277ed71551e3f6b0477e8836b Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Fri, 9 May 2014 15:36:57 -0700 Subject: drivers/rtc/rtc-hym8563.c: set uie_unsupported The alarm of the hym8563 only supports a minute accuracy, while the uie wants an alarm one second in the future. Therefore things like the select() syscall will fail with a timeout, because the next alarm will happen in a worst case of 60 seconds. Signed-off-by: Heiko Stuebner Cc: Alessandro Zummo Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-hym8563.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/rtc/rtc-hym8563.c b/drivers/rtc/rtc-hym8563.c index bd628a6f981d..e5f13c4310fe 100644 --- a/drivers/rtc/rtc-hym8563.c +++ b/drivers/rtc/rtc-hym8563.c @@ -569,6 +569,9 @@ static int hym8563_probe(struct i2c_client *client, if (IS_ERR(hym8563->rtc)) return PTR_ERR(hym8563->rtc); + /* the hym8563 alarm only supports a minute accuracy */ + hym8563->rtc->uie_unsupported = 1; + #ifdef CONFIG_COMMON_CLK hym8563_clkout_register_clk(hym8563); #endif -- cgit v1.2.3 From f2eb7f6f7a18fc2eff2f74d2bfa12758c0449f12 Mon Sep 17 00:00:00 2001 From: Cyril Hrubis Date: Fri, 9 May 2014 15:36:58 -0700 Subject: MAINTAINERS: update maintainership of LTP Also remove sf.net git repo which is no longer available and update link to LTP web pages. Signed-off-by: Cyril Hrubis Signed-off-by: Caspar Zhang Signed-off-by: Wanlong Gao Signed-off-by: Jan Stancek Signed-off-by: Alexey Kodanev Signed-off-by: Stanislav Kholmanskikh Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 51ebb779c5f3..764075dd8d61 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5490,15 +5490,15 @@ F: Documentation/hwmon/ltc4261 F: drivers/hwmon/ltc4261.c LTP (Linux Test Project) -M: Shubham Goyal M: Mike Frysinger M: Cyril Hrubis -M: Caspar Zhang M: Wanlong Gao +M: Jan Stancek +M: Stanislav Kholmanskikh +M: Alexey Kodanev L: ltp-list@lists.sourceforge.net (subscribers-only) -W: http://ltp.sourceforge.net/ +W: http://linux-test-project.github.io/ T: git git://github.com/linux-test-project/ltp.git -T: git git://ltp.git.sourceforge.net/gitroot/ltp/ltp-dev S: Maintained M32R ARCHITECTURE -- cgit v1.2.3 From 3551a9280bcb728980a13783ff295e9f0bdedd9a Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Fri, 9 May 2014 15:36:59 -0700 Subject: mm: postpone the disabling of kmemleak early logging Commit 8910ae896c8c ("kmemleak: change some global variables to int"), in addition to the atomic -> int conversion, moved the disabling of kmemleak_early_log to the beginning of the kmemleak_init() function, before the full kmemleak tracing is actually enabled. In this small window, kmem_cache_create() is called by kmemleak which triggers additional memory allocation that are not traced. This patch restores the original logic with kmemleak_early_log disabling when kmemleak is fully functional. Fixes: 8910ae896c8c (kmemleak: change some global variables to int) Signed-off-by: Catalin Marinas Cc: Sasha Levin Cc: Li Zefan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/kmemleak.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mm/kmemleak.c b/mm/kmemleak.c index 91d67eaee050..8d2fcdfeff7f 100644 --- a/mm/kmemleak.c +++ b/mm/kmemleak.c @@ -1775,10 +1775,9 @@ void __init kmemleak_init(void) int i; unsigned long flags; - kmemleak_early_log = 0; - #ifdef CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF if (!kmemleak_skip_disable) { + kmemleak_early_log = 0; kmemleak_disable(); return; } @@ -1796,6 +1795,7 @@ void __init kmemleak_init(void) /* the kernel is still in UP mode, so disabling the IRQs is enough */ local_irq_save(flags); + kmemleak_early_log = 0; if (kmemleak_error) { local_irq_restore(flags); return; -- cgit v1.2.3 From dd18dbc2d42af75fffa60c77e0f02220bc329829 Mon Sep 17 00:00:00 2001 From: "Kirill A. Shutemov" Date: Fri, 9 May 2014 15:37:00 -0700 Subject: mm, thp: close race between mremap() and split_huge_page() It's critical for split_huge_page() (and migration) to catch and freeze all PMDs on rmap walk. It gets tricky if there's concurrent fork() or mremap() since usually we copy/move page table entries on dup_mm() or move_page_tables() without rmap lock taken. To get it work we rely on rmap walk order to not miss any entry. We expect to see destination VMA after source one to work correctly. But after switching rmap implementation to interval tree it's not always possible to preserve expected walk order. It works fine for dup_mm() since new VMA has the same vma_start_pgoff() / vma_last_pgoff() and explicitly insert dst VMA after src one with vma_interval_tree_insert_after(). But on move_vma() destination VMA can be merged into adjacent one and as result shifted left in interval tree. Fortunately, we can detect the situation and prevent race with rmap walk by moving page table entries under rmap lock. See commit 38a76013ad80. Problem is that we miss the lock when we move transhuge PMD. Most likely this bug caused the crash[1]. [1] http://thread.gmane.org/gmane.linux.kernel.mm/96473 Fixes: 108d6642ad81 ("mm anon rmap: remove anon_vma_moveto_tail") Signed-off-by: Kirill A. Shutemov Reviewed-by: Andrea Arcangeli Cc: Rik van Riel Acked-by: Michel Lespinasse Cc: Dave Jones Cc: David Miller Acked-by: Johannes Weiner Cc: [3.7+] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/mremap.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/mm/mremap.c b/mm/mremap.c index 0843feb66f3d..05f1180e9f21 100644 --- a/mm/mremap.c +++ b/mm/mremap.c @@ -194,10 +194,17 @@ unsigned long move_page_tables(struct vm_area_struct *vma, break; if (pmd_trans_huge(*old_pmd)) { int err = 0; - if (extent == HPAGE_PMD_SIZE) + if (extent == HPAGE_PMD_SIZE) { + VM_BUG_ON(vma->vm_file || !vma->anon_vma); + /* See comment in move_ptes() */ + if (need_rmap_locks) + anon_vma_lock_write(vma->anon_vma); err = move_huge_pmd(vma, new_vma, old_addr, new_addr, old_end, old_pmd, new_pmd); + if (need_rmap_locks) + anon_vma_unlock_write(vma->anon_vma); + } if (err > 0) { need_flush = true; continue; -- cgit v1.2.3 From 1c4abec0baf25ffb92a28cc99d4231feeaa4d3f3 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 8 May 2014 09:48:10 +0300 Subject: iwlwifi: mvm: fix setting channel in monitor mode There was a deadlock in monitor mode when we were setting the channel if the channel was not 1. ====================================================== [ INFO: possible circular locking dependency detected ] 3.14.3 #4 Not tainted ------------------------------------------------------- iw/3323 is trying to acquire lock: (&local->chanctx_mtx){+.+.+.}, at: [] ieee80211_vif_release_channel+0x42/0xb0 [mac80211] but task is already holding lock: (&local->iflist_mtx){+.+...}, at: [] ieee80211_set_monitor_channel+0x5a/0x1b0 [mac80211] which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #2 (&local->iflist_mtx){+.+...}: [] __lock_acquire+0xb3b/0x13b0 [] lock_acquire+0xb0/0x1f0 [] mutex_lock_nested+0x78/0x4f0 [] ieee80211_iterate_active_interfaces+0x2f/0x60 [mac80211] [] iwl_mvm_recalc_multicast+0x49/0xa0 [iwlmvm] [] iwl_mvm_configure_filter+0x4e/0x70 [iwlmvm] [] ieee80211_configure_filter+0x153/0x5f0 [mac80211] [] ieee80211_reconfig_filter+0x15/0x20 [mac80211] [snip] -> #1 (&mvm->mutex){+.+.+.}: [] __lock_acquire+0xb3b/0x13b0 [] lock_acquire+0xb0/0x1f0 [] mutex_lock_nested+0x78/0x4f0 [] iwl_mvm_add_chanctx+0x56/0xe0 [iwlmvm] [] ieee80211_new_chanctx+0x13e/0x410 [mac80211] [] ieee80211_vif_use_channel+0x1c3/0x5a0 [mac80211] [] ieee80211_add_virtual_monitor+0x1ab/0x6b0 [mac80211] [] ieee80211_do_open+0xe6a/0x15a0 [mac80211] [] ieee80211_open+0x59/0x60 [mac80211] [snip] -> #0 (&local->chanctx_mtx){+.+.+.}: [] check_prevs_add+0x977/0x980 [] __lock_acquire+0xb3b/0x13b0 [] lock_acquire+0xb0/0x1f0 [] mutex_lock_nested+0x78/0x4f0 [] ieee80211_vif_release_channel+0x42/0xb0 [mac80211] [] ieee80211_set_monitor_channel+0x113/0x1b0 [mac80211] [] cfg80211_set_monitor_channel+0x77/0x2b0 [cfg80211] [] __nl80211_set_channel+0x122/0x140 [cfg80211] [] nl80211_set_wiphy+0x284/0xaf0 [cfg80211] [snip] other info that might help us debug this: Chain exists of: &local->chanctx_mtx --> &mvm->mutex --> &local->iflist_mtx Possible unsafe locking scenario: CPU0 CPU1 ---- ---- lock(&local->iflist_mtx); lock(&mvm->mutex); lock(&local->iflist_mtx); lock(&local->chanctx_mtx); *** DEADLOCK *** This deadlock actually occurs: INFO: task iw:3323 blocked for more than 120 seconds. Not tainted 3.14.3 #4 "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. iw D ffff8800c8afcd80 4192 3323 3322 0x00000000 ffff880078fdb7e0 0000000000000046 ffff8800c8afcd80 ffff880078fdbfd8 00000000001d5540 00000000001d5540 ffff8801141b0000 ffff8800c8afcd80 ffff880078ff9e38 ffff880078ff9e38 ffff880078ff9e40 0000000000000246 Call Trace: [] schedule_preempt_disabled+0x31/0x80 [] mutex_lock_nested+0x19d/0x4f0 [] ? ieee80211_iterate_active_interfaces+0x2f/0x60 [mac80211] [] ? ieee80211_iterate_active_interfaces+0x2f/0x60 [mac80211] [] ? iwl_mvm_power_mac_update_mode+0xc0/0xc0 [iwlmvm] [] ieee80211_iterate_active_interfaces+0x2f/0x60 [mac80211] [] _iwl_mvm_power_update_binding+0x27/0x80 [iwlmvm] [] iwl_mvm_unassign_vif_chanctx+0x81/0xc0 [iwlmvm] [] __ieee80211_vif_release_channel+0xdf/0x470 [mac80211] [] ieee80211_vif_release_channel+0x4a/0xb0 [mac80211] [] ieee80211_set_monitor_channel+0x113/0x1b0 [mac80211] [] cfg80211_set_monitor_channel+0x77/0x2b0 [cfg80211] [] __nl80211_set_channel+0x122/0x140 [cfg80211] [] nl80211_set_wiphy+0x284/0xaf0 [cfg80211] This fixes https://bugzilla.kernel.org/show_bug.cgi?id=75541 Cc: [3.13+] Reviewed-by: Johannes Berg Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/mac80211.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index 593f723a74c4..4b0b8b6571ee 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -1007,7 +1007,7 @@ static void iwl_mvm_mc_iface_iterator(void *_data, u8 *mac, memcpy(cmd->bssid, vif->bss_conf.bssid, ETH_ALEN); len = roundup(sizeof(*cmd) + cmd->count * ETH_ALEN, 4); - ret = iwl_mvm_send_cmd_pdu(mvm, MCAST_FILTER_CMD, CMD_SYNC, len, cmd); + ret = iwl_mvm_send_cmd_pdu(mvm, MCAST_FILTER_CMD, CMD_ASYNC, len, cmd); if (ret) IWL_ERR(mvm, "mcast filter cmd error. ret=%d\n", ret); } @@ -1023,7 +1023,7 @@ static void iwl_mvm_recalc_multicast(struct iwl_mvm *mvm) if (WARN_ON_ONCE(!mvm->mcast_filter_cmd)) return; - ieee80211_iterate_active_interfaces( + ieee80211_iterate_active_interfaces_atomic( mvm->hw, IEEE80211_IFACE_ITER_NORMAL, iwl_mvm_mc_iface_iterator, &iter_data); } -- cgit v1.2.3 From f759546498d820670934c901a2fdf1ce948d2e5c Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 12 May 2014 01:13:28 +0200 Subject: ACPI / TPM: Fix resume regression on Chromebooks Chromebooks (at least Acer C720 and Pixel) implement an ACPI object for TPM, but don't implement the _DSM method to support PPI. As a result, the TPM driver fails to load on those machines after commit 1569a4c4ceba (ACPI / TPM: detect PPI features by checking availability of _DSM functions) which causes them to fail to resume from system suspend, becuase they require the TPM hardware to be put into the right state during resume and the TPM driver is necessary for that. Fix the problem by making tpm_add_ppi() return 0 when tpm_ppi_handle is still NULL after walking the ACPI namespace in search for the PPI _DSM, which allows the TPM driver to load and operate the hardware (during system resume in particular), but avoid creating the PPI sysfs group in that case. This change is based on a prototype patch from Jiang Liu. Fixes: 1569a4c4ceba (ACPI / TPM: detect PPI features by checking availability of _DSM functions) References: https://bugzilla.kernel.org/show_bug.cgi?id=74021 Reported-by: James Duley Reported-by: Phillip Dixon Tested-by: Brandon Casey Cc: 3.14+ # 3.14+ Signed-off-by: Rafael J. Wysocki --- drivers/char/tpm/tpm_ppi.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/char/tpm/tpm_ppi.c b/drivers/char/tpm/tpm_ppi.c index b3ea223585bd..61dcc8011ec7 100644 --- a/drivers/char/tpm/tpm_ppi.c +++ b/drivers/char/tpm/tpm_ppi.c @@ -328,13 +328,11 @@ int tpm_add_ppi(struct kobject *parent) /* Cache TPM ACPI handle and version string */ acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, ppi_callback, NULL, NULL, &tpm_ppi_handle); - if (tpm_ppi_handle == NULL) - return -ENODEV; - - return sysfs_create_group(parent, &ppi_attr_grp); + return tpm_ppi_handle ? sysfs_create_group(parent, &ppi_attr_grp) : 0; } void tpm_remove_ppi(struct kobject *parent) { - sysfs_remove_group(parent, &ppi_attr_grp); + if (tpm_ppi_handle) + sysfs_remove_group(parent, &ppi_attr_grp); } -- cgit v1.2.3 From 21855ff5bcbdd075e1c99772827a84912ab083dd Mon Sep 17 00:00:00 2001 From: Dirk Brandewie Date: Thu, 8 May 2014 12:57:23 -0700 Subject: intel_pstate: Set turbo VID for BayTrail A documentation update exposed that there is a separate set of VID values that must be used in the turbo/boost P state range. Add enumerating and setting the correct VID for P states in the turbo range. Cc: v3.13+ # v3.13+ Signed-off-by: Dirk Brandewie Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/intel_pstate.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 099967302bf2..39c4f8520848 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -37,6 +37,7 @@ #define BYT_RATIOS 0x66a #define BYT_VIDS 0x66b #define BYT_TURBO_RATIOS 0x66c +#define BYT_TURBO_VIDS 0x66d #define FRAC_BITS 6 @@ -70,8 +71,9 @@ struct pstate_data { }; struct vid_data { - int32_t min; - int32_t max; + int min; + int max; + int turbo; int32_t ratio; }; @@ -359,14 +361,14 @@ static int byt_get_min_pstate(void) { u64 value; rdmsrl(BYT_RATIOS, value); - return (value >> 8) & 0xFF; + return (value >> 8) & 0x3F; } static int byt_get_max_pstate(void) { u64 value; rdmsrl(BYT_RATIOS, value); - return (value >> 16) & 0xFF; + return (value >> 16) & 0x3F; } static int byt_get_turbo_pstate(void) @@ -393,6 +395,9 @@ static void byt_set_pstate(struct cpudata *cpudata, int pstate) vid_fp = clamp_t(int32_t, vid_fp, cpudata->vid.min, cpudata->vid.max); vid = fp_toint(vid_fp); + if (pstate > cpudata->pstate.max_pstate) + vid = cpudata->vid.turbo; + val |= vid; wrmsrl(MSR_IA32_PERF_CTL, val); @@ -402,13 +407,17 @@ static void byt_get_vid(struct cpudata *cpudata) { u64 value; + rdmsrl(BYT_VIDS, value); - cpudata->vid.min = int_tofp((value >> 8) & 0x7f); - cpudata->vid.max = int_tofp((value >> 16) & 0x7f); + cpudata->vid.min = int_tofp((value >> 8) & 0x3f); + cpudata->vid.max = int_tofp((value >> 16) & 0x3f); cpudata->vid.ratio = div_fp( cpudata->vid.max - cpudata->vid.min, int_tofp(cpudata->pstate.max_pstate - cpudata->pstate.min_pstate)); + + rdmsrl(BYT_TURBO_VIDS, value); + cpudata->vid.turbo = value & 0x7f; } -- cgit v1.2.3 From 372cf1244d7c271806b83b32b09a1c8b1b31b353 Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Thu, 24 Apr 2014 18:00:22 +1000 Subject: powerpc/powernv: Reset root port in firmware Resetting root port has more stuff to do than that for PCIe switch ports and we should have resetting root port done in firmware instead of the kernel itself. The problem was introduced by commit 5b2e198e ("powerpc/powernv: Rework EEH reset"). Cc: linux-stable Signed-off-by: Gavin Shan Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/platforms/powernv/eeh-ioda.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/platforms/powernv/eeh-ioda.c b/arch/powerpc/platforms/powernv/eeh-ioda.c index 253fefe3d1a0..5b51079f3e3b 100644 --- a/arch/powerpc/platforms/powernv/eeh-ioda.c +++ b/arch/powerpc/platforms/powernv/eeh-ioda.c @@ -549,7 +549,8 @@ static int ioda_eeh_reset(struct eeh_pe *pe, int option) ret = ioda_eeh_phb_reset(hose, option); } else { bus = eeh_pe_bus_get(pe); - if (pci_is_root_bus(bus)) + if (pci_is_root_bus(bus) || + pci_is_root_bus(bus->parent)) ret = ioda_eeh_root_reset(hose, option); else ret = ioda_eeh_bridge_reset(hose, bus->self, option); -- cgit v1.2.3 From 7a5091d58419b4e5222abce58a40c072786ea1d6 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Sun, 11 May 2014 20:25:20 -0700 Subject: x86, rdrand: When nordrand is specified, disable RDSEED as well One can logically expect that when the user has specified "nordrand", the user doesn't want any use of the CPU random number generator, neither RDRAND nor RDSEED, so disable both. Reported-by: Stephan Mueller Cc: Theodore Ts'o Link: http://lkml.kernel.org/r/21542339.0lFnPSyGRS@myon.chronox.de Signed-off-by: H. Peter Anvin --- Documentation/kernel-parameters.txt | 8 ++++---- arch/x86/kernel/cpu/rdrand.c | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 43842177b771..30a8ad0dae53 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -2218,10 +2218,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted. noreplace-smp [X86-32,SMP] Don't replace SMP instructions with UP alternatives - nordrand [X86] Disable the direct use of the RDRAND - instruction even if it is supported by the - processor. RDRAND is still available to user - space applications. + nordrand [X86] Disable kernel use of the RDRAND and + RDSEED instructions even if they are supported + by the processor. RDRAND and RDSEED are still + available to user space applications. noresume [SWSUSP] Disables resume and restores original swap space. diff --git a/arch/x86/kernel/cpu/rdrand.c b/arch/x86/kernel/cpu/rdrand.c index 384df5105fbc..136ac74dee82 100644 --- a/arch/x86/kernel/cpu/rdrand.c +++ b/arch/x86/kernel/cpu/rdrand.c @@ -27,6 +27,7 @@ static int __init x86_rdrand_setup(char *s) { setup_clear_cpu_cap(X86_FEATURE_RDRAND); + setup_clear_cpu_cap(X86_FEATURE_RDSEED); return 1; } __setup("nordrand", x86_rdrand_setup); -- cgit v1.2.3 From 1a466ae96e9f749d02a73315a3e66375e61a61dd Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Thu, 8 May 2014 14:54:42 -0700 Subject: ptp: fix kconfig dependency warnings Fix kconfig warnings: PTP_1588_CLOCK selects NET_PTP_CLASSIFY, which depends on NET, so PTP_1588_CLOCK should also depend on NET. PTP_1588_CLOCK_PCH selects PTP_1588_CLOCK so the former should depend on NET. warning: (IXP4XX_ETH && PTP_1588_CLOCK) selects NET_PTP_CLASSIFY which has unmet direct dependencies (NET) warning: (SFC && TILE_NET && BFIN_MAC_USE_HWSTAMP && TIGON3 && FEC && E1000E && IGB && IXGBE && I40E && MLX4_EN && SXGBE_ETH && STMMAC_ETH && TI_CPTS && PTP_1588_CLOCK_GIANFAR && PTP_1588_CLOCK_IXP46X && DP83640_PHY && PTP_1588_CLOCK_PCH) selects PTP_1588_CLOCK which has unmet direct dependencies (NET) [This warning is caused by the new 'depends on NET' in PTP_1588_CLOCK.] Signed-off-by: Randy Dunlap Acked-by: Richard Cochran Signed-off-by: David S. Miller --- drivers/ptp/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig index 6963bdf54175..6aea373547f6 100644 --- a/drivers/ptp/Kconfig +++ b/drivers/ptp/Kconfig @@ -6,6 +6,7 @@ menu "PTP clock support" config PTP_1588_CLOCK tristate "PTP clock support" + depends on NET select PPS select NET_PTP_CLASSIFY help @@ -74,7 +75,7 @@ config DP83640_PHY config PTP_1588_CLOCK_PCH tristate "Intel PCH EG20T as PTP clock" depends on X86 || COMPILE_TEST - depends on HAS_IOMEM + depends on HAS_IOMEM && NET select PTP_1588_CLOCK help This driver adds support for using the PCH EG20T as a PTP -- cgit v1.2.3 From 8050936caf125fbe54111ba5e696b68a360556ba Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Fri, 9 May 2014 17:47:12 +1000 Subject: powerpc: irq work racing with timer interrupt can result in timer interrupt hang I am seeing an issue where a CPU running perf eventually hangs. Traces show timer interrupts happening every 4 seconds even when a userspace task is running on the CPU. /proc/timer_list also shows pending hrtimers have not run in over an hour, including the scheduler. Looking closer, decrementers_next_tb is getting set to 0xffffffffffffffff, and at that point we will never take a timer interrupt again. In __timer_interrupt() we set decrementers_next_tb to 0xffffffffffffffff and rely on ->event_handler to update it: *next_tb = ~(u64)0; if (evt->event_handler) evt->event_handler(evt); In this case ->event_handler is hrtimer_interrupt. This will eventually call back through the clockevents code with the next event to be programmed: static int decrementer_set_next_event(unsigned long evt, struct clock_event_device *dev) { /* Don't adjust the decrementer if some irq work is pending */ if (test_irq_work_pending()) return 0; __get_cpu_var(decrementers_next_tb) = get_tb_or_rtc() + evt; If irq work came in between these two points, we will return before updating decrementers_next_tb and we never process a timer interrupt again. This looks to have been introduced by 0215f7d8c53f (powerpc: Fix races with irq_work). Fix it by removing the early exit and relying on code later on in the function to force an early decrementer: /* We may have raced with new irq work */ if (test_irq_work_pending()) set_dec(1); Signed-off-by: Anton Blanchard Cc: stable@vger.kernel.org # 3.14+ Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/kernel/time.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 122a580f7322..7e711bdcc6da 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -813,9 +813,6 @@ static void __init clocksource_init(void) static int decrementer_set_next_event(unsigned long evt, struct clock_event_device *dev) { - /* Don't adjust the decrementer if some irq work is pending */ - if (test_irq_work_pending()) - return 0; __get_cpu_var(decrementers_next_tb) = get_tb_or_rtc() + evt; set_dec(evt); -- cgit v1.2.3 From fd71143645a9958e437c8cf394be2c44a6acb23a Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Fri, 9 May 2014 23:43:40 +0200 Subject: vti6: Don't unregister pernet ops twice on init errors If we fail to register one of the xfrm protocol handlers we will unregister the pernet ops twice on the error exit path. This will probably lead to a kernel panic as the double deregistration leads to a double kfree(). Fix this by removing one of the calls to do it only once. Fixes: fa9ad96d49 ("vti6: Update the ipv6 side to use its own...") Signed-off-by: Mathias Krause Signed-off-by: Steffen Klassert --- net/ipv6/ip6_vti.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c index b7c0f827140b..a51100379f4a 100644 --- a/net/ipv6/ip6_vti.c +++ b/net/ipv6/ip6_vti.c @@ -1097,7 +1097,6 @@ static int __init vti6_tunnel_init(void) err = xfrm6_protocol_register(&vti_esp6_protocol, IPPROTO_ESP); if (err < 0) { - unregister_pernet_device(&vti6_net_ops); pr_err("%s: can't register vti6 protocol\n", __func__); goto out; @@ -1106,7 +1105,6 @@ static int __init vti6_tunnel_init(void) err = xfrm6_protocol_register(&vti_ah6_protocol, IPPROTO_AH); if (err < 0) { xfrm6_protocol_deregister(&vti_esp6_protocol, IPPROTO_ESP); - unregister_pernet_device(&vti6_net_ops); pr_err("%s: can't register vti6 protocol\n", __func__); goto out; @@ -1116,7 +1114,6 @@ static int __init vti6_tunnel_init(void) if (err < 0) { xfrm6_protocol_deregister(&vti_ah6_protocol, IPPROTO_AH); xfrm6_protocol_deregister(&vti_esp6_protocol, IPPROTO_ESP); - unregister_pernet_device(&vti6_net_ops); pr_err("%s: can't register vti6 protocol\n", __func__); goto out; -- cgit v1.2.3 From 3c90c55dcde745bed81f6447f24ba96bda43d984 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 6 May 2014 23:26:19 +0200 Subject: drivers: sh: compile drivers/sh/pm_runtime.c if ARCH_SHMOBILE_MULTI If the kernel is built to support multi-ARM configuration with shmobile support built in, then drivers/sh is not built. This contains the PM runtime code in drivers/sh/pm_runtime.c, which implicitly enables the module clocks for all devices, and thus is quite essential. Without this, the state of clocks depends on implicit reset state, or on the bootloader. If ARCH_SHMOBILE_MULTI then build the drivers/sh directory, but ensure that bits that may conflict (drivers/sh/clk if the common clock framework is enabled) or are not used (drivers/sh/intc), are not built. Also, only enable the PM runtime code when actually running on a shmobile SoCs that needs it. ARCH_SHMOBILE_MULTI was added a while ago by commit efacfce5f8a523457e9419a25d52fe39db00b26a ("ARM: shmobile: Introduce ARCH_SHMOBILE_MULTI"), but drivers/sh was compiled for both ARCH_SHMOBILE_LEGACY and ARCH_SHMOBILE_MULTI until commit bf98c1eac1d4a6bcf00532e4fa41d8126cd6c187 ("ARM: Rename ARCH_SHMOBILE to ARCH_SHMOBILE_LEGACY"). Inspired by a patch from Ben Dooks . Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- drivers/Makefile | 2 +- drivers/sh/Makefile | 14 ++++++++------ drivers/sh/pm_runtime.c | 20 +++++++++++++++++++- 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/drivers/Makefile b/drivers/Makefile index e3ced91b1784..c033798f300a 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -119,7 +119,7 @@ obj-$(CONFIG_SGI_SN) += sn/ obj-y += firmware/ obj-$(CONFIG_CRYPTO) += crypto/ obj-$(CONFIG_SUPERH) += sh/ -obj-$(CONFIG_ARCH_SHMOBILE_LEGACY) += sh/ +obj-$(CONFIG_ARCH_SHMOBILE) += sh/ ifndef CONFIG_ARCH_USES_GETTIMEOFFSET obj-y += clocksource/ endif diff --git a/drivers/sh/Makefile b/drivers/sh/Makefile index fc67f564f02c..788ed9b59b4e 100644 --- a/drivers/sh/Makefile +++ b/drivers/sh/Makefile @@ -1,10 +1,12 @@ # # Makefile for the SuperH specific drivers. # -obj-y := intc/ +obj-$(CONFIG_SUPERH) += intc/ +obj-$(CONFIG_ARCH_SHMOBILE_LEGACY) += intc/ +ifneq ($(CONFIG_COMMON_CLK),y) +obj-$(CONFIG_HAVE_CLK) += clk/ +endif +obj-$(CONFIG_MAPLE) += maple/ +obj-$(CONFIG_SUPERHYWAY) += superhyway/ -obj-$(CONFIG_HAVE_CLK) += clk/ -obj-$(CONFIG_MAPLE) += maple/ -obj-$(CONFIG_SUPERHYWAY) += superhyway/ - -obj-y += pm_runtime.o +obj-y += pm_runtime.o diff --git a/drivers/sh/pm_runtime.c b/drivers/sh/pm_runtime.c index 8afa5a4589f2..10c65eb51f85 100644 --- a/drivers/sh/pm_runtime.c +++ b/drivers/sh/pm_runtime.c @@ -50,8 +50,25 @@ static struct pm_clk_notifier_block platform_bus_notifier = { .con_ids = { NULL, }, }; +static bool default_pm_on; + static int __init sh_pm_runtime_init(void) { + if (IS_ENABLED(CONFIG_ARCH_SHMOBILE_MULTI)) { + if (!of_machine_is_compatible("renesas,emev2") && + !of_machine_is_compatible("renesas,r7s72100") && + !of_machine_is_compatible("renesas,r8a73a4") && + !of_machine_is_compatible("renesas,r8a7740") && + !of_machine_is_compatible("renesas,r8a7778") && + !of_machine_is_compatible("renesas,r8a7779") && + !of_machine_is_compatible("renesas,r8a7790") && + !of_machine_is_compatible("renesas,r8a7791") && + !of_machine_is_compatible("renesas,sh7372") && + !of_machine_is_compatible("renesas,sh73a0")) + return 0; + } + + default_pm_on = true; pm_clk_add_notifier(&platform_bus_type, &platform_bus_notifier); return 0; } @@ -59,7 +76,8 @@ core_initcall(sh_pm_runtime_init); static int __init sh_pm_runtime_late_init(void) { - pm_genpd_poweroff_unused(); + if (default_pm_on) + pm_genpd_poweroff_unused(); return 0; } late_initcall(sh_pm_runtime_late_init); -- cgit v1.2.3 From 6d004d6cc73920299adf4cfe25010b348fc94395 Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Mon, 12 May 2014 09:09:26 +0200 Subject: vti: Use the tunnel mark for lookup in the error handlers. We need to use the mark we get from the tunnels o_key to lookup the right vti state in the error handlers. This patch ensures that. Fixes: df3893c1 ("vti: Update the ipv4 side to use it's own receive hook.") Fixes: fa9ad96d ("vti6: Update the ipv6 side to use its own receive hook.") Signed-off-by: Steffen Klassert --- net/ipv4/ip_vti.c | 5 ++++- net/ipv6/ip6_vti.c | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c index cd62596e9a87..d3f64d7f355e 100644 --- a/net/ipv4/ip_vti.c +++ b/net/ipv4/ip_vti.c @@ -239,6 +239,7 @@ static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) static int vti4_err(struct sk_buff *skb, u32 info) { __be32 spi; + __u32 mark; struct xfrm_state *x; struct ip_tunnel *tunnel; struct ip_esp_hdr *esph; @@ -254,6 +255,8 @@ static int vti4_err(struct sk_buff *skb, u32 info) if (!tunnel) return -1; + mark = be32_to_cpu(tunnel->parms.o_key); + switch (protocol) { case IPPROTO_ESP: esph = (struct ip_esp_hdr *)(skb->data+(iph->ihl<<2)); @@ -281,7 +284,7 @@ static int vti4_err(struct sk_buff *skb, u32 info) return 0; } - x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr, + x = xfrm_state_lookup(net, mark, (const xfrm_address_t *)&iph->daddr, spi, protocol, AF_INET); if (!x) return 0; diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c index a51100379f4a..6cc9f9371cc5 100644 --- a/net/ipv6/ip6_vti.c +++ b/net/ipv6/ip6_vti.c @@ -511,6 +511,7 @@ static int vti6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, u8 type, u8 code, int offset, __be32 info) { __be32 spi; + __u32 mark; struct xfrm_state *x; struct ip6_tnl *t; struct ip_esp_hdr *esph; @@ -524,6 +525,8 @@ static int vti6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, if (!t) return -1; + mark = be32_to_cpu(t->parms.o_key); + switch (protocol) { case IPPROTO_ESP: esph = (struct ip_esp_hdr *)(skb->data + offset); @@ -545,7 +548,7 @@ static int vti6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, type != NDISC_REDIRECT) return 0; - x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr, + x = xfrm_state_lookup(net, mark, (const xfrm_address_t *)&iph->daddr, spi, protocol, AF_INET6); if (!x) return 0; -- cgit v1.2.3 From 84ea7fe37908254c3bd90910921f6e1045c1747a Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 12 May 2014 13:42:29 +0530 Subject: hrtimer: Set expiry time before switch_hrtimer_base() switch_hrtimer_base() calls hrtimer_check_target() which ensures that we do not migrate a timer to a remote cpu if the timer expires before the current programmed expiry time on that remote cpu. But __hrtimer_start_range_ns() calls switch_hrtimer_base() before the new expiry time is set. So the sanity check in hrtimer_check_target() is operating on stale or even uninitialized data. Update expiry time before calling switch_hrtimer_base(). [ tglx: Rewrote changelog once again ] Signed-off-by: Viresh Kumar Cc: linaro-kernel@lists.linaro.org Cc: linaro-networking@linaro.org Cc: fweisbec@gmail.com Cc: arvind.chauhan@arm.com Link: http://lkml.kernel.org/r/81999e148745fc51bbcd0615823fbab9b2e87e23.1399882253.git.viresh.kumar@linaro.org Cc: stable@vger.kernel.org Signed-off-by: Thomas Gleixner --- kernel/hrtimer.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index 6b715c0af1b1..e0501fe7140d 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c @@ -990,11 +990,8 @@ int __hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim, /* Remove an active timer from the queue: */ ret = remove_hrtimer(timer, base); - /* Switch the timer base, if necessary: */ - new_base = switch_hrtimer_base(timer, base, mode & HRTIMER_MODE_PINNED); - if (mode & HRTIMER_MODE_REL) { - tim = ktime_add_safe(tim, new_base->get_time()); + tim = ktime_add_safe(tim, base->get_time()); /* * CONFIG_TIME_LOW_RES is a temporary way for architectures * to signal that they simply return xtime in @@ -1009,6 +1006,9 @@ int __hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim, hrtimer_set_expires_range_ns(timer, tim, delta_ns); + /* Switch the timer base, if necessary: */ + new_base = switch_hrtimer_base(timer, base, mode & HRTIMER_MODE_PINNED); + timer_stats_hrtimer_set_start_info(timer); leftmost = enqueue_hrtimer(timer, new_base); -- cgit v1.2.3 From 1f53ba6e81749a420226e5502c49ab83ba85c81d Mon Sep 17 00:00:00 2001 From: Stefano Stabellini Date: Thu, 8 May 2014 15:48:13 +0000 Subject: arm64: introduce virt_to_pfn virt_to_pfn has been defined in arch/arm/include/asm/memory.h by commit e26a9e0 "ARM: Better virt_to_page() handling" and Xen has come to rely on it. Introduce virt_to_pfn on arm64 too. Signed-off-by: Stefano Stabellini Acked-by: Catalin Marinas --- arch/arm64/include/asm/memory.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h index 9dc5dc39fded..d79a79e7dd04 100644 --- a/arch/arm64/include/asm/memory.h +++ b/arch/arm64/include/asm/memory.h @@ -138,6 +138,7 @@ static inline void *phys_to_virt(phys_addr_t x) #define __pa(x) __virt_to_phys((unsigned long)(x)) #define __va(x) ((void *)__phys_to_virt((phys_addr_t)(x))) #define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT) +#define virt_to_pfn(x) __phys_to_pfn(__virt_to_phys(x)) /* * virt_to_page(k) convert a _valid_ virtual address to struct page * -- cgit v1.2.3 From 5467a512216753d54f757314c73dbc60f659f9e6 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Sat, 10 May 2014 18:33:11 +0200 Subject: netfilter: nf_tables: fix goto action This patch fixes a crash when trying to access the counters and the default chain policy from the non-base chain that we have reached via the goto chain. Fix this by falling back on the original base chain after returning from the custom chain. While fixing this, kill the inline function to account chain statistics to improve source code readability. Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_tables_core.c | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c index 4368c5850548..7d83a49fd8e5 100644 --- a/net/netfilter/nf_tables_core.c +++ b/net/netfilter/nf_tables_core.c @@ -66,20 +66,6 @@ struct nft_jumpstack { int rulenum; }; -static inline void -nft_chain_stats(const struct nft_chain *this, const struct nft_pktinfo *pkt, - struct nft_jumpstack *jumpstack, unsigned int stackptr) -{ - struct nft_stats __percpu *stats; - const struct nft_chain *chain = stackptr ? jumpstack[0].chain : this; - - rcu_read_lock_bh(); - stats = rcu_dereference(nft_base_chain(chain)->stats); - __this_cpu_inc(stats->pkts); - __this_cpu_add(stats->bytes, pkt->skb->len); - rcu_read_unlock_bh(); -} - enum nft_trace { NFT_TRACE_RULE, NFT_TRACE_RETURN, @@ -117,12 +103,13 @@ static void nft_trace_packet(const struct nft_pktinfo *pkt, unsigned int nft_do_chain(struct nft_pktinfo *pkt, const struct nf_hook_ops *ops) { - const struct nft_chain *chain = ops->priv; + const struct nft_chain *chain = ops->priv, *basechain = chain; const struct nft_rule *rule; const struct nft_expr *expr, *last; struct nft_data data[NFT_REG_MAX + 1]; unsigned int stackptr = 0; struct nft_jumpstack jumpstack[NFT_JUMP_STACK_SIZE]; + struct nft_stats __percpu *stats; int rulenum; /* * Cache cursor to avoid problems in case that the cursor is updated @@ -209,12 +196,17 @@ next_rule: rulenum = jumpstack[stackptr].rulenum; goto next_rule; } - nft_chain_stats(chain, pkt, jumpstack, stackptr); if (unlikely(pkt->skb->nf_trace)) - nft_trace_packet(pkt, chain, ++rulenum, NFT_TRACE_POLICY); + nft_trace_packet(pkt, basechain, ++rulenum, NFT_TRACE_POLICY); + + rcu_read_lock_bh(); + stats = rcu_dereference(nft_base_chain(basechain)->stats); + __this_cpu_inc(stats->pkts); + __this_cpu_add(stats->bytes, pkt->skb->len); + rcu_read_unlock_bh(); - return nft_base_chain(chain)->policy; + return nft_base_chain(basechain)->policy; } EXPORT_SYMBOL_GPL(nft_do_chain); -- cgit v1.2.3 From 7b9d5ef932297413adcbd8be98fe612b9527a312 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Sat, 10 May 2014 18:42:57 +0200 Subject: netfilter: nf_tables: fix tracing of the goto action Add missing code to trace goto actions. Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_tables_core.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c index 7d83a49fd8e5..f55fb28264fa 100644 --- a/net/netfilter/nf_tables_core.c +++ b/net/netfilter/nf_tables_core.c @@ -171,8 +171,12 @@ next_rule: jumpstack[stackptr].rule = rule; jumpstack[stackptr].rulenum = rulenum; stackptr++; - /* fall through */ + chain = data[NFT_REG_VERDICT].chain; + goto do_chain; case NFT_GOTO: + if (unlikely(pkt->skb->nf_trace)) + nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE); + chain = data[NFT_REG_VERDICT].chain; goto do_chain; case NFT_RETURN: -- cgit v1.2.3 From f7e7e39b21c285ad73a62fac0736191b8d830704 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Sat, 10 May 2014 18:46:02 +0200 Subject: netfilter: nf_tables: fix bogus rulenum after goto action After returning from the chain that we just went to with no matchings, we get a bogus rule number in the trace. To fix this, we would need to iterate over the list of remaining rules in the chain to update the rule number counter. Patrick suggested to set this to the maximum value since the default base chain policy is the very last action when the processing the base chain is over. Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_tables_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c index f55fb28264fa..be08a96b4f45 100644 --- a/net/netfilter/nf_tables_core.c +++ b/net/netfilter/nf_tables_core.c @@ -202,7 +202,7 @@ next_rule: } if (unlikely(pkt->skb->nf_trace)) - nft_trace_packet(pkt, basechain, ++rulenum, NFT_TRACE_POLICY); + nft_trace_packet(pkt, basechain, -1, NFT_TRACE_POLICY); rcu_read_lock_bh(); stats = rcu_dereference(nft_base_chain(basechain)->stats); -- cgit v1.2.3 From 7e9bc10db275b22a9db0f976b33b5aeed288da73 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Sun, 11 May 2014 17:14:49 +0200 Subject: netfilter: nf_tables: fix missing return trace at the end of non-base chain Display "return" for implicit rule at the end of a non-base chain, instead of when popping chain from the stack. Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_tables_core.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c index be08a96b4f45..421c36ac5145 100644 --- a/net/netfilter/nf_tables_core.c +++ b/net/netfilter/nf_tables_core.c @@ -182,18 +182,16 @@ next_rule: case NFT_RETURN: if (unlikely(pkt->skb->nf_trace)) nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RETURN); - - /* fall through */ + break; case NFT_CONTINUE: + if (unlikely(pkt->skb->nf_trace && !(chain->flags & NFT_BASE_CHAIN))) + nft_trace_packet(pkt, chain, ++rulenum, NFT_TRACE_RETURN); break; default: WARN_ON(1); } if (stackptr > 0) { - if (unlikely(pkt->skb->nf_trace)) - nft_trace_packet(pkt, chain, ++rulenum, NFT_TRACE_RETURN); - stackptr--; chain = jumpstack[stackptr].chain; rule = jumpstack[stackptr].rule; -- cgit v1.2.3 From 601c942176d8ad8334118bddb747e3720bed24f8 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Fri, 9 May 2014 17:37:44 +0100 Subject: arm64: use cpu_online_mask when using forced irq_set_affinity Commit 01f8fa4f01d8("genirq: Allow forcing cpu affinity of interrupts") enabled the forced irq_set_affinity which previously refused to route an interrupt to an offline cpu. Commit ffde1de64012("irqchip: Gic: Support forced affinity setting") implements this force logic and disables the cpu online check for GIC interrupt controller. When __cpu_disable calls migrate_irqs, it disables the current cpu in cpu_online_mask and uses forced irq_set_affinity to migrate the IRQs away from the cpu but passes affinity mask with the cpu being offlined also included in it. When calling irq_set_affinity with force == true in a cpu hotplug path, the caller must ensure that the cpu being offlined is not present in the affinity mask or it may be selected as the target CPU, leading to the interrupt not being migrated. This patch uses cpu_online_mask when using forced irq_set_affinity so that the IRQs are properly migrated away. Signed-off-by: Sudeep Holla Acked-by: Mark Rutland Cc: Will Deacon Signed-off-by: Catalin Marinas --- arch/arm64/kernel/irq.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/arch/arm64/kernel/irq.c b/arch/arm64/kernel/irq.c index 473e5dbf8f39..0f08dfd69ebc 100644 --- a/arch/arm64/kernel/irq.c +++ b/arch/arm64/kernel/irq.c @@ -97,11 +97,15 @@ static bool migrate_one_irq(struct irq_desc *desc) if (irqd_is_per_cpu(d) || !cpumask_test_cpu(smp_processor_id(), affinity)) return false; - if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) { - affinity = cpu_online_mask; + if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) ret = true; - } + /* + * when using forced irq_set_affinity we must ensure that the cpu + * being offlined is not present in the affinity mask, it may be + * selected as the target CPU otherwise + */ + affinity = cpu_online_mask; c = irq_data_get_irq_chip(d); if (!c->irq_set_affinity) pr_debug("IRQ%u: unable to set affinity\n", d->irq); -- cgit v1.2.3 From 17c048fc4bd95efea208a1920f169547d8588f1f Mon Sep 17 00:00:00 2001 From: Josef Gajdusek Date: Sun, 11 May 2014 14:40:44 +0200 Subject: hwmon: (emc1403) fix inverted store_hyst() Attempts to set the hysteresis value to a temperature below the target limit fails with "write error: Numerical result out of range" due to an inverted comparison. Signed-off-by: Josef Gajdusek Reviewed-by: Jean Delvare Cc: stable@vger.kernel.org [Guenter Roeck: Updated headline and description] Signed-off-by: Guenter Roeck --- drivers/hwmon/emc1403.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hwmon/emc1403.c b/drivers/hwmon/emc1403.c index 90ec1173b8a1..61d89d6d58fe 100644 --- a/drivers/hwmon/emc1403.c +++ b/drivers/hwmon/emc1403.c @@ -163,7 +163,7 @@ static ssize_t store_hyst(struct device *dev, if (retval < 0) goto fail; - hyst = val - retval * 1000; + hyst = retval * 1000 - val; hyst = DIV_ROUND_CLOSEST(hyst, 1000); if (hyst < 0 || hyst > 255) { retval = -ERANGE; -- cgit v1.2.3 From 8759f9046550f463098148bf577ccd32cdb895e3 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Mon, 12 May 2014 11:44:51 +0200 Subject: hwmon: (emc1403) Fix resource leak on module unload Commit 454aee17f claims to convert driver emc1403 to use devm_hwmon_device_register_with_groups, however the patch itself makes use of hwmon_device_register_with_groups instead. As the driver remove function was still dropped, the hwmon device is no longer unregistered on driver removal, leading to a resource leak. Signed-off-by: Jean Delvare Fixes: 454aee17f hwmon: (emc1403) Convert to use devm_hwmon_device_register_with_groups Cc: Guenter Roeck Cc: stable@vger.kernel.org [3.13+] Signed-off-by: Guenter Roeck --- drivers/hwmon/emc1403.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/hwmon/emc1403.c b/drivers/hwmon/emc1403.c index 61d89d6d58fe..42a3cfcd15c1 100644 --- a/drivers/hwmon/emc1403.c +++ b/drivers/hwmon/emc1403.c @@ -355,9 +355,9 @@ static int emc1403_probe(struct i2c_client *client, if (id->driver_data) data->groups[1] = &emc1404_group; - hwmon_dev = hwmon_device_register_with_groups(&client->dev, - client->name, data, - data->groups); + hwmon_dev = devm_hwmon_device_register_with_groups(&client->dev, + client->name, data, + data->groups); if (IS_ERR(hwmon_dev)) return PTR_ERR(hwmon_dev); -- cgit v1.2.3 From 3a18e1398fc2dc9c32bbdc50664da3a77959a8d1 Mon Sep 17 00:00:00 2001 From: Josef Gajdusek Date: Mon, 12 May 2014 13:48:26 +0200 Subject: hwmon: (emc1403) Support full range of known chip revision numbers The datasheet for EMC1413/EMC1414, which is fully compatible to EMC1403/1404 and uses the same chip identification, references revision numbers 0x01, 0x03, and 0x04. Accept the full range of revision numbers from 0x01 to 0x04 to make sure none are missed. Signed-off-by: Josef Gajdusek Cc: stable@vger.kernel.org [Guenter Roeck: Updated headline and description] Signed-off-by: Guenter Roeck --- drivers/hwmon/emc1403.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hwmon/emc1403.c b/drivers/hwmon/emc1403.c index 42a3cfcd15c1..01723f04fe45 100644 --- a/drivers/hwmon/emc1403.c +++ b/drivers/hwmon/emc1403.c @@ -330,7 +330,7 @@ static int emc1403_detect(struct i2c_client *client, } id = i2c_smbus_read_byte_data(client, THERMAL_REVISION_REG); - if (id != 0x01) + if (id < 0x01 || id > 0x04) return -ENODEV; return 0; -- cgit v1.2.3 From 03e5da151b8e390f2e28c4edf8fbbb6ca6d7a7ed Mon Sep 17 00:00:00 2001 From: Daniel Kim Date: Fri, 9 May 2014 12:37:05 +0200 Subject: brcmfmac: Fix iovar 'bw_cap' set command failure Fix iovar 'bw_cap' set command failure introduced by commit ff3b0fba6f25555ef59c55d138a467d0f81d82d7 Author: Arend van Spriel Date: Sat Mar 15 12:00:57 2014 +0100 brcmfmac: fallback to mimo_bw_cap for older firmwares This resulted in disabling 20MHz operation in the firmware. Reviewed-by: Arend Van Spriel Signed-off-by: Daniel Kim Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index afb3d15e38ff..be1985296bdc 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c @@ -4948,7 +4948,7 @@ static int brcmf_enable_bw40_2g(struct brcmf_if *ifp) if (!err) { /* only set 2G bandwidth using bw_cap command */ band_bwcap.band = cpu_to_le32(WLC_BAND_2G); - band_bwcap.bw_cap = cpu_to_le32(WLC_BW_40MHZ_BIT); + band_bwcap.bw_cap = cpu_to_le32(WLC_BW_CAP_40MHZ); err = brcmf_fil_iovar_data_set(ifp, "bw_cap", &band_bwcap, sizeof(band_bwcap)); } else { -- cgit v1.2.3 From bbeb0eadcf9fe74fb2b9b1a6fea82cd538b1e556 Mon Sep 17 00:00:00 2001 From: Peter Christensen Date: Thu, 8 May 2014 11:15:37 +0200 Subject: macvlan: Don't propagate IFF_ALLMULTI changes on down interfaces. Clearing the IFF_ALLMULTI flag on a down interface could cause an allmulti overflow on the underlying interface. Attempting the set IFF_ALLMULTI on the underlying interface would cause an error and the log message: "allmulti touches root, set allmulti failed." Signed-off-by: Peter Christensen Signed-off-by: David S. Miller --- drivers/net/macvlan.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index b0e2865a6810..c5fb9cf95c12 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -458,8 +458,10 @@ static void macvlan_change_rx_flags(struct net_device *dev, int change) struct macvlan_dev *vlan = netdev_priv(dev); struct net_device *lowerdev = vlan->lowerdev; - if (change & IFF_ALLMULTI) - dev_set_allmulti(lowerdev, dev->flags & IFF_ALLMULTI ? 1 : -1); + if (dev->flags & IFF_UP) { + if (change & IFF_ALLMULTI) + dev_set_allmulti(lowerdev, dev->flags & IFF_ALLMULTI ? 1 : -1); + } } static void macvlan_set_mac_lists(struct net_device *dev) -- cgit v1.2.3 From 1c3639005f48492e5f2d965779efd814e80f8b15 Mon Sep 17 00:00:00 2001 From: Nikolay Aleksandrov Date: Fri, 9 May 2014 11:11:39 +0200 Subject: sfc: fix calling of free_irq with already free vector If the sfc driver is in legacy interrupt mode (either explicitly by using interrupt_mode module param or by falling back to it) it will hit a warning at kernel/irq/manage.c because it will try to free an irq which wasn't allocated by it in the first place because the MSI(X) irqs are zero and it'll try to free them unconditionally. So fix it by checking if we're in legacy mode and freeing the appropriate irqs. CC: Zenghui Shi CC: Ben Hutchings CC: CC: Shradha Shah CC: David S. Miller Fixes: 1899c111a535 ("sfc: Fix IRQ cleanup in case of a probe failure") Reported-by: Zenghui Shi Signed-off-by: Nikolay Aleksandrov Acked-by: Shradha Shah Signed-off-by: David S. Miller --- drivers/net/ethernet/sfc/nic.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/sfc/nic.c b/drivers/net/ethernet/sfc/nic.c index 32d969e857f7..89b83e59e1dc 100644 --- a/drivers/net/ethernet/sfc/nic.c +++ b/drivers/net/ethernet/sfc/nic.c @@ -156,13 +156,15 @@ void efx_nic_fini_interrupt(struct efx_nic *efx) efx->net_dev->rx_cpu_rmap = NULL; #endif - /* Disable MSI/MSI-X interrupts */ - efx_for_each_channel(channel, efx) - free_irq(channel->irq, &efx->msi_context[channel->channel]); - - /* Disable legacy interrupt */ - if (efx->legacy_irq) + if (EFX_INT_MODE_USE_MSI(efx)) { + /* Disable MSI/MSI-X interrupts */ + efx_for_each_channel(channel, efx) + free_irq(channel->irq, + &efx->msi_context[channel->channel]); + } else { + /* Disable legacy interrupt */ free_irq(efx->legacy_irq, efx); + } } /* Register dump */ -- cgit v1.2.3 From 0a4ac2ea2714b5e43293f752737b8c2731a26679 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 12 May 2014 11:00:15 -0700 Subject: Input: fix ps2/serio module dependency The ps2 mouse and keyboard drivers use the "serio" framework that they correctly select in Kconfig, and that in turn depends on the i8042 driver, which is also allowed to be disabled for architectures that don't have an i8042. However, Kconfig also allows i8042 to be built as a module while the serio framework is built-in, which causes this link error: drivers/built-in.o: In function `ps2_begin_command': :(.text+0x26b6cc): undefined reference to `i8042_check_port_owner' :(.text+0x26b6d4): undefined reference to `i8042_lock_chip' drivers/built-in.o: In function `ps2_end_command': :(.text+0x26b734): undefined reference to `i8042_check_port_owner' :(.text+0x26b73c): undefined reference to `i8042_unlock_chip' On x86, a specific 'select SERIO_I8042' takes care of it, but not on the other architecture that potentially have a i8042. This patch changes the Kconfig logic to ensure that whenever there is an i8042, it does get used for the serio driver, avoiding the link error above. Signed-off-by: Arnd Bergmann Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/Kconfig | 2 +- drivers/input/mouse/Kconfig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 76842d7dc2e3..ffc7ad3a2c88 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -71,7 +71,7 @@ config KEYBOARD_ATKBD default y select SERIO select SERIO_LIBPS2 - select SERIO_I8042 if X86 + select SERIO_I8042 if ARCH_MIGHT_HAVE_PC_SERIO select SERIO_GSCPS2 if GSC help Say Y here if you want to use a standard AT or PS/2 keyboard. Usually diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index effa9c5f2c5c..6b8441f7bc32 100644 --- a/drivers/input/mouse/Kconfig +++ b/drivers/input/mouse/Kconfig @@ -17,7 +17,7 @@ config MOUSE_PS2 default y select SERIO select SERIO_LIBPS2 - select SERIO_I8042 if X86 + select SERIO_I8042 if ARCH_MIGHT_HAVE_PC_SERIO select SERIO_GSCPS2 if GSC help Say Y here if you have a PS/2 mouse connected to your system. This -- cgit v1.2.3 From ba77341cfd180022e60f08f55025ad59a8387538 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 12 May 2014 11:01:48 -0700 Subject: Input: atmel-wm97xx - only build for AVR32 Building this driver on ARM/at91 always gives us this error message: drivers/input/touchscreen/atmel-wm97xx.c:63:2: error: #error Unknown CPU, this driver only supports AT32AP700X CPUs. Clearly this configuration is not meant to work, so let's just prevent it in Kconfig. If we ever want to use it on another platform, we should also pass proper resources for GPIO, IRQ and memory, which are hardcoded to AT32AP700X at the moment. Signed-off-by: Arnd Bergmann Acked-by: Nicolas Ferre Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 68edc9db2c64..b845e9370871 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -640,7 +640,7 @@ config TOUCHSCREEN_WM9713 config TOUCHSCREEN_WM97XX_ATMEL tristate "WM97xx Atmel accelerated touch" - depends on TOUCHSCREEN_WM97XX && (AVR32 || ARCH_AT91) + depends on TOUCHSCREEN_WM97XX && AVR32 help Say Y here for support for streaming mode with WM97xx touchscreens on Atmel AT91 or AVR32 systems with an AC97C module. -- cgit v1.2.3 From 868a6ca84ee7e547ae01a5e04e232e4a392c50b8 Mon Sep 17 00:00:00 2001 From: Nicolin Chen Date: Mon, 12 May 2014 20:12:05 +0800 Subject: ASoC: pcm: Fix incorrect condition check for case SNDRV_PCM_TRIGGER_SUSPEND The regular state before we execute SNDRV_PCM_TRIGGER_SUSPEND should be SNDRV_PCM_TRIGGER_START, not SNDRV_PCM_TRIGGER_STOP. Thus fix it. Signed-off-by: Nicolin Chen Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 2cedf09f6d96..a391de058037 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1675,7 +1675,7 @@ int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, be->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP; break; case SNDRV_PCM_TRIGGER_SUSPEND: - if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP) + if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_START) continue; if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream)) -- cgit v1.2.3 From ca5106ae3da0179dcee3ae21f3ea94f62e9fdb0c Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 7 May 2014 16:20:24 +0200 Subject: ASoC: dapm: Skip CODEC<->CODEC links in connect_dai_link_widgets() For CODEC to CODEC DAI links the paths are created in snd_soc_dapm_new_pcm(). Also for CODEC to CODEC links the widgets are connected cross-over via a DAI link widget, meaning that the capture widget of one CODEC will be connected to the playback widget of the other and vice versa. Whereas snd_soc_dapm_connect_dai_link_widgets() directly connects the playback widget of the CPU DAI to the playback widget of the CODEC DAI and the capture widget of the CPU DAI to the capture widget of the CODEC DAI. So not skipping CODEC<->CODEC links in snd_soc_dapm_connect_dai_link_widgets() will create incorrect connections between the two CODECs which will cause DAPM to detect active paths where there are none and unnecessarily power up widgets. Fixes: b893ea5 ("ASoC: sapm: Automatically connect DAI link widgets in DAPM graph.") Cc: (for 3.14+) Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 7769b0a2bc5a..ef78a699bb20 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -3475,8 +3475,11 @@ void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card) cpu_dai = rtd->cpu_dai; codec_dai = rtd->codec_dai; - /* dynamic FE links have no fixed DAI mapping */ - if (rtd->dai_link->dynamic) + /* + * dynamic FE links have no fixed DAI mapping. + * CODEC<->CODEC links have no direct connection. + */ + if (rtd->dai_link->dynamic || rtd->dai_link->params) continue; /* there is no point in connecting BE DAI links with dummies */ -- cgit v1.2.3 From 111e0a9dc71ed75baa5e739289b9bdb06fda13be Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Thu, 8 May 2014 17:30:31 +0300 Subject: spi/pxa2xx: Prevent DMA from transferring too many bytes In case we are doing DMA transfer and the size of the buffer is not multiple of 4 bytes the driver truncates that to 4-byte boundary and tries to handle remaining bytes using PIO. Or that is what it tried to do. What actually happens is that it calls ALIGN() to the buffer size which aligns it to the next 4-byte boundary (doesn't truncate). Doing this results 1-3 bytes extra to be transferred. Furthermore we handle remaining bytes using PIO which results one extra byte to be transferred. In worst case the driver transfers 4 extra bytes. While investigating this it turned out that the DMA hardware doesn't even have such limitation so we can solve this by dropping the code that tries to handle unaligned bytes. Reported-by: Chiau Ee Chew Reported-by: Hock Leong Kweh Signed-off-by: Mika Westerberg Signed-off-by: Mark Brown --- drivers/spi/spi-pxa2xx-dma.c | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/drivers/spi/spi-pxa2xx-dma.c b/drivers/spi/spi-pxa2xx-dma.c index 713af4806f26..f6759dc0153b 100644 --- a/drivers/spi/spi-pxa2xx-dma.c +++ b/drivers/spi/spi-pxa2xx-dma.c @@ -29,18 +29,6 @@ static int pxa2xx_spi_map_dma_buffer(struct driver_data *drv_data, struct sg_table *sgt; void *buf, *pbuf; - /* - * Some DMA controllers have problems transferring buffers that are - * not multiple of 4 bytes. So we truncate the transfer so that it - * is suitable for such controllers, and handle the trailing bytes - * manually after the DMA completes. - * - * REVISIT: It would be better if this information could be - * retrieved directly from the DMA device in a similar way than - * ->copy_align etc. is done. - */ - len = ALIGN(drv_data->len, 4); - if (dir == DMA_TO_DEVICE) { dmadev = drv_data->tx_chan->device->dev; sgt = &drv_data->tx_sgt; @@ -144,12 +132,8 @@ static void pxa2xx_spi_dma_transfer_complete(struct driver_data *drv_data, if (!error) { pxa2xx_spi_unmap_dma_buffers(drv_data); - /* Handle the last bytes of unaligned transfer */ drv_data->tx += drv_data->tx_map_len; - drv_data->write(drv_data); - drv_data->rx += drv_data->rx_map_len; - drv_data->read(drv_data); msg->actual_length += drv_data->len; msg->state = pxa2xx_spi_next_transfer(drv_data); -- cgit v1.2.3 From ce85a4d726ecd286f933d4eedf01c5acb4f47a38 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 6 May 2014 10:32:15 +0200 Subject: ASoC: dapm: Fix SUSPEND -> OFF bias sequence Currently when the DAPM context bias level is SUSPEND and the target bias level is OFF dapm_pre_sequence_async() will first transition to PREPARE and dapm_post_sequence_async() will then transition back from PREPARE to STANDBY and then to OFF. This patch makes sure that dapm_pre_sequence_async() only transitions to PREPARE when either going to ON or away from ON. This avoids the extra unnecessary transitions. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index ef78a699bb20..6d6ceee447d5 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -1612,8 +1612,11 @@ static void dapm_pre_sequence_async(void *data, async_cookie_t cookie) "ASoC: Failed to turn on bias: %d\n", ret); } - /* Prepare for a STADDBY->ON or ON->STANDBY transition */ - if (d->bias_level != d->target_bias_level) { + /* Prepare for a transition to ON or away from ON */ + if ((d->target_bias_level == SND_SOC_BIAS_ON && + d->bias_level != SND_SOC_BIAS_ON) || + (d->target_bias_level != SND_SOC_BIAS_ON && + d->bias_level == SND_SOC_BIAS_ON)) { ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_PREPARE); if (ret != 0) dev_err(d->dev, -- cgit v1.2.3 From 89e47f62cf3eea7ad5e3d7d72ea846be37d6e352 Mon Sep 17 00:00:00 2001 From: Nicolin Chen Date: Tue, 6 May 2014 16:55:59 +0800 Subject: ASoC: fsl_esai: Fix incorrect condition within ratio range check for FP The range here from 1 to 16 is confined to FP divider only while the sck_div indicates if the calculation contains PSR and PM dividers. So for the case using PSR and PM since the sck_div is true, the range of ratio would simply become bigger than 16. So this patch fixes the condition here and adds one line comments to make the purpose here clear. Signed-off-by: Nicolin Chen Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_esai.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index c8e5db1414d7..35c0b9295a80 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c @@ -307,7 +307,8 @@ static int fsl_esai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq) return -EINVAL; } - if (esai_priv->sck_div[tx] && (ratio > 16 || ratio == 0)) { + /* The ratio should be contented by FP alone if bypassing PM and PSR */ + if (!esai_priv->sck_div[tx] && (ratio > 16 || ratio == 0)) { dev_err(dai->dev, "the ratio is out of range (1 ~ 16)\n"); return -EINVAL; } -- cgit v1.2.3 From 57ebbcafab0ce8cce4493c6a243ecdd7066e6ef1 Mon Sep 17 00:00:00 2001 From: Nicolin Chen Date: Tue, 6 May 2014 16:56:00 +0800 Subject: ASoC: fsl_esai: Only bypass sck_div for EXTAL source ESAI can only output EXTAL clock source directly. But for FSYS clock source, ESAI can not output it without getting through PSR PM dividers. So this patch adds an extra check in the code. Signed-off-by: Nicolin Chen Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_esai.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index 35c0b9295a80..c674fd99158b 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c @@ -258,10 +258,16 @@ static int fsl_esai_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, return -EINVAL; } - if (ratio == 1) { + /* Only EXTAL source can be output directly without using PSR and PM */ + if (ratio == 1 && clksrc == esai_priv->extalclk) { /* Bypass all the dividers if not being needed */ ecr |= tx ? ESAI_ECR_ETO : ESAI_ECR_ERO; goto out; + } else if (ratio < 2) { + /* The ratio should be no less than 2 if using other sources */ + dev_err(dai->dev, "failed to derive required HCK%c rate\n", + tx ? 'T' : 'R'); + return -EINVAL; } ret = fsl_esai_divisor_cal(dai, tx, ratio, false, 0); -- cgit v1.2.3 From 4f8210f66e5a200c63770ea9445ff913a28a3be2 Mon Sep 17 00:00:00 2001 From: Nicolin Chen Date: Tue, 6 May 2014 16:56:02 +0800 Subject: ASoC: fsl_esai: Set PCRC and PRRC registers at the end of hw_params() According to Reference Manual -- ESAI Initialization chapter, as the standard procedure of ESAI personal reset, the PCRC and PRRC registers should be remained in its reset value and then configured after T/RCCR and T/RCR configurations's done but before TE/RE's enabling. So this patch moves PCRC and PRRC settings to the end of hw_params(). Signed-off-by: Nicolin Chen Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_esai.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index c674fd99158b..496ce2eb2f1f 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c @@ -461,12 +461,6 @@ static int fsl_esai_startup(struct snd_pcm_substream *substream, } if (!dai->active) { - /* Reset Port C */ - regmap_update_bits(esai_priv->regmap, REG_ESAI_PRRC, - ESAI_PRRC_PDC_MASK, ESAI_PRRC_PDC(ESAI_GPIO)); - regmap_update_bits(esai_priv->regmap, REG_ESAI_PCRC, - ESAI_PCRC_PC_MASK, ESAI_PCRC_PC(ESAI_GPIO)); - /* Set synchronous mode */ regmap_update_bits(esai_priv->regmap, REG_ESAI_SAICR, ESAI_SAICR_SYNC, esai_priv->synchronous ? @@ -526,6 +520,11 @@ static int fsl_esai_hw_params(struct snd_pcm_substream *substream, regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), mask, val); + /* Remove ESAI personal reset by configuring ESAI_PCRC and ESAI_PRRC */ + regmap_update_bits(esai_priv->regmap, REG_ESAI_PRRC, + ESAI_PRRC_PDC_MASK, ESAI_PRRC_PDC(ESAI_GPIO)); + regmap_update_bits(esai_priv->regmap, REG_ESAI_PCRC, + ESAI_PCRC_PC_MASK, ESAI_PCRC_PC(ESAI_GPIO)); return 0; } -- cgit v1.2.3 From 5508d456e9992bb81f21d4bd3b1f60f3eb04eb40 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 3 Apr 2014 13:14:05 +0200 Subject: Revert "MIPS: MT: proc: Add support for printing VPE and TC ids" Reverts commit 795038a6910937fa167d47f6f6183db0eb8fb706 because d6d3c9afaab47418ab2d7f874fb8aeac1f067104 provides the same functionality in a more generic way. Both patches applied however means that the VPE and TC IDs get printed twice currently. --- arch/mips/kernel/proc.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c index e40971b51d2f..037a44d962f3 100644 --- a/arch/mips/kernel/proc.c +++ b/arch/mips/kernel/proc.c @@ -124,14 +124,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) seq_printf(m, "kscratch registers\t: %d\n", hweight8(cpu_data[n].kscratch_mask)); seq_printf(m, "core\t\t\t: %d\n", cpu_data[n].core); -#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_MIPS_MT_SMTC) - if (cpu_has_mipsmt) { - seq_printf(m, "VPE\t\t\t: %d\n", cpu_data[n].vpe_id); -#if defined(CONFIG_MIPS_MT_SMTC) - seq_printf(m, "TC\t\t\t: %d\n", cpu_data[n].tc_id); -#endif - } -#endif + sprintf(fmt, "VCE%%c exceptions\t\t: %s\n", cpu_has_vce ? "%u" : "not available"); seq_printf(m, fmt, 'D', vced_count); -- cgit v1.2.3 From c406339cf15e53d70c095d590f437ee6ff24595d Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 3 Apr 2014 13:29:06 +0200 Subject: MAINTAINERS: TURBOchannel: Update entry Add mailing list and patchwork URL so patches now have a defined path. Also add myself as a TURBOchannel maintainer. However Maciej is going to the the resident TURBOchannel guru. Signed-off-by: Ralf Baechle Acked-by: "Maciej W. Rozycki" --- MAINTAINERS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 51ebb779c5f3..4fe576f6f43a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9107,6 +9107,9 @@ F: arch/um/os-Linux/drivers/ TURBOCHANNEL SUBSYSTEM M: "Maciej W. Rozycki" +M: Ralf Baechle +L: linux-mips@linux-mips.org +Q: http://patchwork.linux-mips.org/project/linux-mips/list/ S: Maintained F: drivers/tc/ F: include/linux/tc.h -- cgit v1.2.3 From af37530bbe9cae2a17044525b9f898ff60012157 Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Mon, 31 Mar 2014 23:51:30 +0100 Subject: MIPS: DEC: Bus error handler fixes Commit 69f24d1784b631b81a54eb57c49bf46536dd2382 [MIPS: Optimize current_cpu_type() for better code.] missed an update for two DECstation bus error support files that now do not build, this is a fix. Signed-off-by: Maciej W. Rozycki Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/6667/ Signed-off-by: Ralf Baechle --- arch/mips/dec/ecc-berr.c | 1 + arch/mips/dec/kn02xa-berr.c | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/mips/dec/ecc-berr.c b/arch/mips/dec/ecc-berr.c index 5abf4e894216..2a66e908f6a9 100644 --- a/arch/mips/dec/ecc-berr.c +++ b/arch/mips/dec/ecc-berr.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/mips/dec/kn02xa-berr.c b/arch/mips/dec/kn02xa-berr.c index f434b759e3b9..ec606363b806 100644 --- a/arch/mips/dec/kn02xa-berr.c +++ b/arch/mips/dec/kn02xa-berr.c @@ -19,6 +19,7 @@ #include #include +#include #include #include #include -- cgit v1.2.3 From 824122a319d827d42aeb4646a3bf639937fdb2ce Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Tue, 1 Apr 2014 00:14:41 +0100 Subject: MIPS: DEC/SNI: O32 wrapper stack switching fixes Commit 231a35d37293ab88d325a9cb94e5474c156282c0 [[MIPS] RM: Collected changes] broke DECstation support by introducing an incompatible copy of arch/mips/dec/prom/call_o32.S in arch/mips/fw/lib/, built unconditionally. The copy happens to land earlier of the two among the modules used in the link and is therefore chosen for the DECstation rather than the intended original. As a result random kernel data is corrupted because a pointer to the "%s" formatted output template is used as a temporary stack pointer rather than being passed down to prom_printf. This also explains why prom_printf still works, up to a point -- the next argument is the actual string to output so it works just fine as the output template until enough kernel data has been corrupted to cause a crash. This change adjusts the modified wrapper in arch/mips/fw/lib/call_o32.S to let callers request no stack switching by passing a null temporary stack pointer in $a1, reworks the DECstation callers to work with the updated interface and removes the old copy from arch/mips/dec/prom/call_o32.S. A few minor readability adjustments are included as well, most importantly O32_SZREG is now used throughout where applicable rather than hardcoded multiplies of 4 and $fp is used to access the argument save area as a more usual register to operate the stack with rather than $s0. Finally an update is made to the temporary stack space used by the SNI platform to guarantee 8-byte alignment as per o32 requirements. Signed-off-by: Maciej W. Rozycki Cc: Thomas Bogendoerfer Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/6668/ Signed-off-by: Ralf Baechle --- arch/mips/dec/prom/Makefile | 1 - arch/mips/dec/prom/call_o32.S | 89 ---------------------------------------- arch/mips/fw/lib/call_o32.S | 57 +++++++++++++++---------- arch/mips/fw/sni/sniprom.c | 3 +- arch/mips/include/asm/dec/prom.h | 48 +++++++++++----------- 5 files changed, 61 insertions(+), 137 deletions(-) delete mode 100644 arch/mips/dec/prom/call_o32.S diff --git a/arch/mips/dec/prom/Makefile b/arch/mips/dec/prom/Makefile index 064ae7a76bdc..ae73e42ac20b 100644 --- a/arch/mips/dec/prom/Makefile +++ b/arch/mips/dec/prom/Makefile @@ -6,4 +6,3 @@ lib-y += init.o memory.o cmdline.o identify.o console.o lib-$(CONFIG_32BIT) += locore.o -lib-$(CONFIG_64BIT) += call_o32.o diff --git a/arch/mips/dec/prom/call_o32.S b/arch/mips/dec/prom/call_o32.S deleted file mode 100644 index 8c8498159e43..000000000000 --- a/arch/mips/dec/prom/call_o32.S +++ /dev/null @@ -1,89 +0,0 @@ -/* - * O32 interface for the 64 (or N32) ABI. - * - * Copyright (C) 2002 Maciej W. Rozycki - * - * 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 - -/* Maximum number of arguments supported. Must be even! */ -#define O32_ARGC 32 -/* Number of static registers we save. */ -#define O32_STATC 11 -/* Frame size for both of the above. */ -#define O32_FRAMESZ (4 * O32_ARGC + SZREG * O32_STATC) - - .text - -/* - * O32 function call dispatcher, for interfacing 32-bit ROM routines. - * - * The standard 64 (N32) calling sequence is supported, with a0 - * holding a function pointer, a1-a7 -- its first seven arguments - * and the stack -- remaining ones (up to O32_ARGC, including a1-a7). - * Static registers, gp and fp are preserved, v0 holds a result. - * This code relies on the called o32 function for sp and ra - * restoration and thus both this dispatcher and the current stack - * have to be placed in a KSEGx (or KUSEG) address space. Any - * pointers passed have to point to addresses within one of these - * spaces as well. - */ -NESTED(call_o32, O32_FRAMESZ, ra) - REG_SUBU sp,O32_FRAMESZ - - REG_S ra,O32_FRAMESZ-1*SZREG(sp) - REG_S fp,O32_FRAMESZ-2*SZREG(sp) - REG_S gp,O32_FRAMESZ-3*SZREG(sp) - REG_S s7,O32_FRAMESZ-4*SZREG(sp) - REG_S s6,O32_FRAMESZ-5*SZREG(sp) - REG_S s5,O32_FRAMESZ-6*SZREG(sp) - REG_S s4,O32_FRAMESZ-7*SZREG(sp) - REG_S s3,O32_FRAMESZ-8*SZREG(sp) - REG_S s2,O32_FRAMESZ-9*SZREG(sp) - REG_S s1,O32_FRAMESZ-10*SZREG(sp) - REG_S s0,O32_FRAMESZ-11*SZREG(sp) - - move jp,a0 - - sll a0,a1,zero - sll a1,a2,zero - sll a2,a3,zero - sll a3,a4,zero - sw a5,0x10(sp) - sw a6,0x14(sp) - sw a7,0x18(sp) - - PTR_LA t0,O32_FRAMESZ(sp) - PTR_LA t1,0x1c(sp) - li t2,O32_ARGC-7 -1: - lw t3,(t0) - REG_ADDU t0,SZREG - sw t3,(t1) - REG_SUBU t2,1 - REG_ADDU t1,4 - bnez t2,1b - - jalr jp - - REG_L s0,O32_FRAMESZ-11*SZREG(sp) - REG_L s1,O32_FRAMESZ-10*SZREG(sp) - REG_L s2,O32_FRAMESZ-9*SZREG(sp) - REG_L s3,O32_FRAMESZ-8*SZREG(sp) - REG_L s4,O32_FRAMESZ-7*SZREG(sp) - REG_L s5,O32_FRAMESZ-6*SZREG(sp) - REG_L s6,O32_FRAMESZ-5*SZREG(sp) - REG_L s7,O32_FRAMESZ-4*SZREG(sp) - REG_L gp,O32_FRAMESZ-3*SZREG(sp) - REG_L fp,O32_FRAMESZ-2*SZREG(sp) - REG_L ra,O32_FRAMESZ-1*SZREG(sp) - - REG_ADDU sp,O32_FRAMESZ - jr ra -END(call_o32) diff --git a/arch/mips/fw/lib/call_o32.S b/arch/mips/fw/lib/call_o32.S index b308b2a0613e..4703fe4dbd9a 100644 --- a/arch/mips/fw/lib/call_o32.S +++ b/arch/mips/fw/lib/call_o32.S @@ -1,7 +1,7 @@ /* * O32 interface for the 64 (or N32) ABI. * - * Copyright (C) 2002 Maciej W. Rozycki + * Copyright (C) 2002, 2014 Maciej W. Rozycki * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -12,28 +12,37 @@ #include #include +/* O32 register size. */ +#define O32_SZREG 4 /* Maximum number of arguments supported. Must be even! */ #define O32_ARGC 32 -/* Number of static registers we save. */ +/* Number of static registers we save. */ #define O32_STATC 11 -/* Frame size for static register */ -#define O32_FRAMESZ (SZREG * O32_STATC) -/* Frame size on new stack */ -#define O32_FRAMESZ_NEW (SZREG + 4 * O32_ARGC) +/* Argument area frame size. */ +#define O32_ARGSZ (O32_SZREG * O32_ARGC) +/* Static register save area frame size. */ +#define O32_STATSZ (SZREG * O32_STATC) +/* Stack pointer register save area frame size. */ +#define O32_SPSZ SZREG +/* Combined area frame size. */ +#define O32_FRAMESZ (O32_ARGSZ + O32_SPSZ + O32_STATSZ) +/* Switched stack frame size. */ +#define O32_NFRAMESZ (O32_ARGSZ + O32_SPSZ) .text /* * O32 function call dispatcher, for interfacing 32-bit ROM routines. * - * The standard 64 (N32) calling sequence is supported, with a0 - * holding a function pointer, a1 a new stack pointer, a2-a7 -- its - * first six arguments and the stack -- remaining ones (up to O32_ARGC, - * including a2-a7). Static registers, gp and fp are preserved, v0 holds - * a result. This code relies on the called o32 function for sp and ra - * restoration and this dispatcher has to be placed in a KSEGx (or KUSEG) - * address space. Any pointers passed have to point to addresses within - * one of these spaces as well. + * The standard 64 (N32) calling sequence is supported, with a0 holding + * a function pointer, a1 a pointer to the new stack to call the + * function with or 0 if no stack switching is requested, a2-a7 -- the + * function call's first six arguments, and the stack -- the remaining + * arguments (up to O32_ARGC, including a2-a7). Static registers, gp + * and fp are preserved, v0 holds the result. This code relies on the + * called o32 function for sp and ra restoration and this dispatcher has + * to be placed in a KSEGx (or KUSEG) address space. Any pointers + * passed have to point to addresses within one of these spaces as well. */ NESTED(call_o32, O32_FRAMESZ, ra) REG_SUBU sp,O32_FRAMESZ @@ -51,32 +60,36 @@ NESTED(call_o32, O32_FRAMESZ, ra) REG_S s0,O32_FRAMESZ-11*SZREG(sp) move jp,a0 - REG_SUBU s0,a1,O32_FRAMESZ_NEW - REG_S sp,O32_FRAMESZ_NEW-1*SZREG(s0) + + move fp,sp + beqz a1,0f + REG_SUBU fp,a1,O32_NFRAMESZ +0: + REG_S sp,O32_NFRAMESZ-1*SZREG(fp) sll a0,a2,zero sll a1,a3,zero sll a2,a4,zero sll a3,a5,zero - sw a6,0x10(s0) - sw a7,0x14(s0) + sw a6,4*O32_SZREG(fp) + sw a7,5*O32_SZREG(fp) PTR_LA t0,O32_FRAMESZ(sp) - PTR_LA t1,0x18(s0) + PTR_LA t1,6*O32_SZREG(fp) li t2,O32_ARGC-6 1: lw t3,(t0) REG_ADDU t0,SZREG sw t3,(t1) REG_SUBU t2,1 - REG_ADDU t1,4 + REG_ADDU t1,O32_SZREG bnez t2,1b - move sp,s0 + move sp,fp jalr jp - REG_L sp,O32_FRAMESZ_NEW-1*SZREG(sp) + REG_L sp,O32_NFRAMESZ-1*SZREG(sp) REG_L s0,O32_FRAMESZ-11*SZREG(sp) REG_L s1,O32_FRAMESZ-10*SZREG(sp) diff --git a/arch/mips/fw/sni/sniprom.c b/arch/mips/fw/sni/sniprom.c index 2c2cb182af4e..6aa264b9856a 100644 --- a/arch/mips/fw/sni/sniprom.c +++ b/arch/mips/fw/sni/sniprom.c @@ -40,7 +40,8 @@ #ifdef CONFIG_64BIT -static u8 o32_stk[16384]; +/* O32 stack has to be 8-byte aligned. */ +static u64 o32_stk[4096]; #define O32_STK &o32_stk[sizeof(o32_stk)] #define __PROM_O32(fun, arg) fun arg __asm__(#fun); \ diff --git a/arch/mips/include/asm/dec/prom.h b/arch/mips/include/asm/dec/prom.h index c0ead6313845..b59a2103b61a 100644 --- a/arch/mips/include/asm/dec/prom.h +++ b/arch/mips/include/asm/dec/prom.h @@ -113,31 +113,31 @@ extern int (*__pmax_close)(int); #define __DEC_PROM_O32(fun, arg) fun arg __asm__(#fun); \ __asm__(#fun " = call_o32") -int __DEC_PROM_O32(_rex_bootinit, (int (*)(void))); -int __DEC_PROM_O32(_rex_bootread, (int (*)(void))); -int __DEC_PROM_O32(_rex_getbitmap, (int (*)(memmap *), memmap *)); +int __DEC_PROM_O32(_rex_bootinit, (int (*)(void), void *)); +int __DEC_PROM_O32(_rex_bootread, (int (*)(void), void *)); +int __DEC_PROM_O32(_rex_getbitmap, (int (*)(memmap *), void *, memmap *)); unsigned long *__DEC_PROM_O32(_rex_slot_address, - (unsigned long *(*)(int), int)); -void *__DEC_PROM_O32(_rex_gettcinfo, (void *(*)(void))); -int __DEC_PROM_O32(_rex_getsysid, (int (*)(void))); -void __DEC_PROM_O32(_rex_clear_cache, (void (*)(void))); - -int __DEC_PROM_O32(_prom_getchar, (int (*)(void))); -char *__DEC_PROM_O32(_prom_getenv, (char *(*)(char *), char *)); -int __DEC_PROM_O32(_prom_printf, (int (*)(char *, ...), char *, ...)); - - -#define rex_bootinit() _rex_bootinit(__rex_bootinit) -#define rex_bootread() _rex_bootread(__rex_bootread) -#define rex_getbitmap(x) _rex_getbitmap(__rex_getbitmap, x) -#define rex_slot_address(x) _rex_slot_address(__rex_slot_address, x) -#define rex_gettcinfo() _rex_gettcinfo(__rex_gettcinfo) -#define rex_getsysid() _rex_getsysid(__rex_getsysid) -#define rex_clear_cache() _rex_clear_cache(__rex_clear_cache) - -#define prom_getchar() _prom_getchar(__prom_getchar) -#define prom_getenv(x) _prom_getenv(__prom_getenv, x) -#define prom_printf(x...) _prom_printf(__prom_printf, x) + (unsigned long *(*)(int), void *, int)); +void *__DEC_PROM_O32(_rex_gettcinfo, (void *(*)(void), void *)); +int __DEC_PROM_O32(_rex_getsysid, (int (*)(void), void *)); +void __DEC_PROM_O32(_rex_clear_cache, (void (*)(void), void *)); + +int __DEC_PROM_O32(_prom_getchar, (int (*)(void), void *)); +char *__DEC_PROM_O32(_prom_getenv, (char *(*)(char *), void *, char *)); +int __DEC_PROM_O32(_prom_printf, (int (*)(char *, ...), void *, char *, ...)); + + +#define rex_bootinit() _rex_bootinit(__rex_bootinit, NULL) +#define rex_bootread() _rex_bootread(__rex_bootread, NULL) +#define rex_getbitmap(x) _rex_getbitmap(__rex_getbitmap, NULL, x) +#define rex_slot_address(x) _rex_slot_address(__rex_slot_address, NULL, x) +#define rex_gettcinfo() _rex_gettcinfo(__rex_gettcinfo, NULL) +#define rex_getsysid() _rex_getsysid(__rex_getsysid, NULL) +#define rex_clear_cache() _rex_clear_cache(__rex_clear_cache, NULL) + +#define prom_getchar() _prom_getchar(__prom_getchar, NULL) +#define prom_getenv(x) _prom_getenv(__prom_getenv, NULL, x) +#define prom_printf(x...) _prom_printf(__prom_printf, NULL, x) #else /* !CONFIG_64BIT */ -- cgit v1.2.3 From 2db4bc3418c43f1e810b304c48f8ddff2535075b Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Tue, 1 Apr 2014 00:57:28 +0100 Subject: MIPS: __delay CPU_DADDI_WORKAROUNDS bug fix With CPU_DADDI_WORKAROUNDS enabled __delay assembles with a macro in a branch delay slot: {standard input}: Assembler messages: {standard input}:18: Warning: Macro instruction expanded into multiple instructions in a branch delay slot and broken code results: 0000000000000000 <__delay>: 0: 1480ffff bnez a0,0 <__delay> 4: 24010001 li at,1 8: 0081202f dsubu a0,a0,at c: 03e00008 jr ra 10: 00000000 nop 14: 00000000 nop Consequently the function loops indefinitely, showing up prominently as a hang in the delay loop calibration at bootstrap. This change corrects the problem by forcing the immediate 1 into a register while keeping code produced identical where CPU_DADDI_WORKAROUNDS is disabled. Signed-off-by: Maciej W. Rozycki Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/6669/ Signed-off-by: Ralf Baechle --- arch/mips/lib/delay.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/arch/mips/lib/delay.c b/arch/mips/lib/delay.c index 44713af15a62..705cfb7c1a74 100644 --- a/arch/mips/lib/delay.c +++ b/arch/mips/lib/delay.c @@ -6,7 +6,7 @@ * Copyright (C) 1994 by Waldorf Electronics * Copyright (C) 1995 - 2000, 01, 03 by Ralf Baechle * Copyright (C) 1999, 2000 Silicon Graphics, Inc. - * Copyright (C) 2007 Maciej W. Rozycki + * Copyright (C) 2007, 2014 Maciej W. Rozycki */ #include #include @@ -15,6 +15,12 @@ #include #include +#ifndef CONFIG_CPU_DADDI_WORKAROUNDS +#define GCC_DADDI_IMM_ASM() "I" +#else +#define GCC_DADDI_IMM_ASM() "r" +#endif + void __delay(unsigned long loops) { __asm__ __volatile__ ( @@ -22,13 +28,13 @@ void __delay(unsigned long loops) " .align 3 \n" "1: bnez %0, 1b \n" #if BITS_PER_LONG == 32 - " subu %0, 1 \n" + " subu %0, %1 \n" #else - " dsubu %0, 1 \n" + " dsubu %0, %1 \n" #endif " .set reorder \n" : "=r" (loops) - : "0" (loops)); + : GCC_DADDI_IMM_ASM() (1), "0" (loops)); } EXPORT_SYMBOL(__delay); -- cgit v1.2.3 From 465ca5d6a06bfab861b65bb6b54dca170564326b Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Fri, 4 Apr 2014 03:32:29 +0100 Subject: MIPS: __strncpy_from_user_asm CPU_DADDI_WORKAROUNDS bug fix This corrects assembler warnings and broken code generated in __strncpy_from_user_asm: arch/mips/lib/strncpy_user.S: Assembler messages: arch/mips/lib/strncpy_user.S:52: Warning: Macro instruction expanded into multiple instructions in a branch delay slot with the CPU_DADDI_WORKAROUNDS option set. The function schedules delay slots manually where there is really no need to as GAS is happy to do it all itself, so undo it all and remove `.set noreorder'. Signed-off-by: Maciej W. Rozycki Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/6685/ Signed-off-by: Ralf Baechle --- arch/mips/lib/strncpy_user.S | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/arch/mips/lib/strncpy_user.S b/arch/mips/lib/strncpy_user.S index d3301cd1e9a5..3c32baf8b494 100644 --- a/arch/mips/lib/strncpy_user.S +++ b/arch/mips/lib/strncpy_user.S @@ -35,7 +35,6 @@ LEAF(__strncpy_from_\func\()_asm) bnez v0, .Lfault\@ FEXPORT(__strncpy_from_\func\()_nocheck_asm) - .set noreorder move t0, zero move v1, a1 .ifeqs "\func","kernel" @@ -45,21 +44,21 @@ FEXPORT(__strncpy_from_\func\()_nocheck_asm) .endif PTR_ADDIU v1, 1 R10KCBARRIER(0(ra)) + sb v0, (a0) beqz v0, 2f - sb v0, (a0) PTR_ADDIU t0, 1 + PTR_ADDIU a0, 1 bne t0, a2, 1b - PTR_ADDIU a0, 1 2: PTR_ADDU v0, a1, t0 xor v0, a1 bltz v0, .Lfault\@ - nop + move v0, t0 jr ra # return n - move v0, t0 END(__strncpy_from_\func\()_asm) -.Lfault\@: jr ra - li v0, -EFAULT +.Lfault\@: + li v0, -EFAULT + jr ra .section __ex_table,"a" PTR 1b, .Lfault\@ -- cgit v1.2.3 From 44ba138f55577431cd119840320e31e218d7dd5b Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Fri, 4 Apr 2014 03:32:54 +0100 Subject: MIPS: csum_partial.S CPU_DADDI_WORKAROUNDS bug fix This change reverts most of commit 60724ca59eda766a30be57aec6b49bc3e2bead91 [MIPS: IP checksums: Remove unncessary .set pseudos] that introduced warnings with the CPU_DADDI_WORKAROUNDS option set: arch/mips/lib/csum_partial.S: Assembler messages: arch/mips/lib/csum_partial.S:467: Warning: used $3 with ".set at=$3" arch/mips/lib/csum_partial.S:467: Warning: used $3 with ".set at=$3" arch/mips/lib/csum_partial.S:467: Warning: used $3 with ".set at=$3" arch/mips/lib/csum_partial.S:467: Warning: used $3 with ".set at=$3" arch/mips/lib/csum_partial.S:467: Warning: used $3 with ".set at=$3" arch/mips/lib/csum_partial.S:467: Warning: used $3 with ".set at=$3" arch/mips/lib/csum_partial.S:467: Warning: used $3 with ".set at=$3" arch/mips/lib/csum_partial.S:467: Warning: used $3 with ".set at=$3" arch/mips/lib/csum_partial.S:467: Warning: used $3 with ".set at=$3" arch/mips/lib/csum_partial.S:467: Warning: used $3 with ".set at=$3" [...] arch/mips/lib/csum_partial.S:577: Warning: used $3 with ".set at=$3" arch/mips/lib/csum_partial.S:577: Warning: used $3 with ".set at=$3" arch/mips/lib/csum_partial.S:577: Warning: used $3 with ".set at=$3" arch/mips/lib/csum_partial.S:601: Warning: used $3 with ".set at=$3" arch/mips/lib/csum_partial.S:601: Warning: used $3 with ".set at=$3" arch/mips/lib/csum_partial.S:601: Warning: used $3 with ".set at=$3" arch/mips/lib/csum_partial.S:601: Warning: used $3 with ".set at=$3" [and so on, and so on...] The warnings are benign and good code is produced regardless because no macros that'd use the assembler's temporary register are involved, however the `.set noat' directives removed by the commit referred are crucial to guarantee this is still going to be the case after any changes in the future. Therefore they need to be brought back to place which this change does. Signed-off-by: Maciej W. Rozycki Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/6686/ Signed-off-by: Ralf Baechle --- arch/mips/lib/csum_partial.S | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/mips/lib/csum_partial.S b/arch/mips/lib/csum_partial.S index 2e4825e48388..9901237563c5 100644 --- a/arch/mips/lib/csum_partial.S +++ b/arch/mips/lib/csum_partial.S @@ -56,14 +56,20 @@ #define UNIT(unit) ((unit)*NBYTES) #define ADDC(sum,reg) \ + .set push; \ + .set noat; \ ADD sum, reg; \ sltu v1, sum, reg; \ ADD sum, v1; \ + .set pop #define ADDC32(sum,reg) \ + .set push; \ + .set noat; \ addu sum, reg; \ sltu v1, sum, reg; \ addu sum, v1; \ + .set pop #define CSUM_BIGCHUNK1(src, offset, sum, _t0, _t1, _t2, _t3) \ LOAD _t0, (offset + UNIT(0))(src); \ @@ -710,6 +716,8 @@ LEAF(csum_partial) ADDC(sum, t2) .Ldone\@: /* fold checksum */ + .set push + .set noat #ifdef USE_DOUBLE dsll32 v1, sum, 0 daddu sum, v1 @@ -732,6 +740,7 @@ LEAF(csum_partial) or sum, sum, t0 1: #endif + .set pop .set reorder ADDC32(sum, psum) jr ra -- cgit v1.2.3 From 3deff253315effd23fdde86e4d818d8cf3dcc5dc Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Thu, 3 Apr 2014 11:10:20 +0200 Subject: MIPS: Loongson: No need to select GENERIC_HARDIRQS_NO__DO_IRQ Commit 0e476d91244e ("MIPS: Loongson: Add Loongson-3 Kconfig options") added "select GENERIC_HARDIRQS_NO__DO_IRQ". But the Kconfig symbol GENERIC_HARDIRQS_NO__DO_IRQ was already removed in v2.6.38, so that select is a nop. Drop it. Signed-off-by: Paul Bolle Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/6677/ Signed-off-by: Ralf Baechle --- arch/mips/loongson/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/mips/loongson/Kconfig b/arch/mips/loongson/Kconfig index 7397be226a06..603d79a95f47 100644 --- a/arch/mips/loongson/Kconfig +++ b/arch/mips/loongson/Kconfig @@ -64,7 +64,6 @@ config LEMOTE_MACH3A bool "Lemote Loongson 3A family machines" select ARCH_SPARSEMEM_ENABLE select GENERIC_ISA_DMA_SUPPORT_BROKEN - select GENERIC_HARDIRQS_NO__DO_IRQ select BOOT_ELF32 select BOARD_SCACHE select CSRC_R4K -- cgit v1.2.3 From 8e8acb32960f42c81b1d50deac56a2c07bb6a18a Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Thu, 3 Apr 2014 22:24:01 +0300 Subject: MIPS/loongson2_cpufreq: Fix CPU clock rate setting Loongson2 has been using (incorrectly) kHz for cpu_clk rate. This has been unnoticed, as loongson2_cpufreq was the only place where the rate was set/get. After commit 652ed95d5fa6074b3c4ea245deb0691f1acb6656 (cpufreq: introduce cpufreq_generic_get() routine) things however broke, and now loops_per_jiffy adjustments are incorrect (1000 times too long). The patch fixes this by changing cpu_clk rate to Hz. Signed-off-by: Aaro Koskinen Cc: stable@vger.kernel.org Cc: Rafael J. Wysocki Cc: Viresh Kumar Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Cc: cpufreq@vger.kernel.org Cc: Aaro Koskinen Patchwork: https://patchwork.linux-mips.org/patch/6678/ Signed-off-by: Ralf Baechle --- arch/mips/loongson/lemote-2f/clock.c | 5 +++-- drivers/cpufreq/loongson2_cpufreq.c | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/arch/mips/loongson/lemote-2f/clock.c b/arch/mips/loongson/lemote-2f/clock.c index e1f427f4f5f3..67dd94ef28e6 100644 --- a/arch/mips/loongson/lemote-2f/clock.c +++ b/arch/mips/loongson/lemote-2f/clock.c @@ -91,6 +91,7 @@ EXPORT_SYMBOL(clk_put); int clk_set_rate(struct clk *clk, unsigned long rate) { + unsigned int rate_khz = rate / 1000; int ret = 0; int regval; int i; @@ -111,10 +112,10 @@ int clk_set_rate(struct clk *clk, unsigned long rate) if (loongson2_clockmod_table[i].frequency == CPUFREQ_ENTRY_INVALID) continue; - if (rate == loongson2_clockmod_table[i].frequency) + if (rate_khz == loongson2_clockmod_table[i].frequency) break; } - if (rate != loongson2_clockmod_table[i].frequency) + if (rate_khz != loongson2_clockmod_table[i].frequency) return -ENOTSUPP; clk->rate = rate; diff --git a/drivers/cpufreq/loongson2_cpufreq.c b/drivers/cpufreq/loongson2_cpufreq.c index f0bc31f5db27..d4add8621944 100644 --- a/drivers/cpufreq/loongson2_cpufreq.c +++ b/drivers/cpufreq/loongson2_cpufreq.c @@ -62,7 +62,7 @@ static int loongson2_cpufreq_target(struct cpufreq_policy *policy, set_cpus_allowed_ptr(current, &cpus_allowed); /* setting the cpu frequency */ - clk_set_rate(policy->clk, freq); + clk_set_rate(policy->clk, freq * 1000); return 0; } @@ -92,7 +92,7 @@ static int loongson2_cpufreq_cpu_init(struct cpufreq_policy *policy) i++) loongson2_clockmod_table[i].frequency = (rate * i) / 8; - ret = clk_set_rate(cpuclk, rate); + ret = clk_set_rate(cpuclk, rate * 1000); if (ret) { clk_put(cpuclk); return ret; -- cgit v1.2.3 From cdbb03b00451513c35d10812d2d55d7951bae269 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Fri, 11 Apr 2014 18:28:00 +0200 Subject: MIPS: Remove file missed when removing rm9k support a while ago. Signed-off-by: Ralf Baechle --- arch/mips/include/asm/rm9k-ocd.h | 56 ---------------------------------------- 1 file changed, 56 deletions(-) delete mode 100644 arch/mips/include/asm/rm9k-ocd.h diff --git a/arch/mips/include/asm/rm9k-ocd.h b/arch/mips/include/asm/rm9k-ocd.h deleted file mode 100644 index b0b80d9ecf96..000000000000 --- a/arch/mips/include/asm/rm9k-ocd.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2004 by Basler Vision Technologies AG - * Author: Thomas Koeller - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#if !defined(_ASM_RM9K_OCD_H) -#define _ASM_RM9K_OCD_H - -#include -#include -#include - -extern volatile void __iomem * const ocd_base; -extern volatile void __iomem * const titan_base; - -#define ocd_addr(__x__) (ocd_base + (__x__)) -#define titan_addr(__x__) (titan_base + (__x__)) -#define scram_addr(__x__) (scram_base + (__x__)) - -/* OCD register access */ -#define ocd_readl(__offs__) __raw_readl(ocd_addr(__offs__)) -#define ocd_readw(__offs__) __raw_readw(ocd_addr(__offs__)) -#define ocd_readb(__offs__) __raw_readb(ocd_addr(__offs__)) -#define ocd_writel(__val__, __offs__) \ - __raw_writel((__val__), ocd_addr(__offs__)) -#define ocd_writew(__val__, __offs__) \ - __raw_writew((__val__), ocd_addr(__offs__)) -#define ocd_writeb(__val__, __offs__) \ - __raw_writeb((__val__), ocd_addr(__offs__)) - -/* TITAN register access - 32 bit-wide only */ -#define titan_readl(__offs__) __raw_readl(titan_addr(__offs__)) -#define titan_writel(__val__, __offs__) \ - __raw_writel((__val__), titan_addr(__offs__)) - -/* Protect access to shared TITAN registers */ -extern spinlock_t titan_lock; -extern int titan_irqflags; -#define lock_titan_regs() spin_lock_irqsave(&titan_lock, titan_irqflags) -#define unlock_titan_regs() spin_unlock_irqrestore(&titan_lock, titan_irqflags) - -#endif /* !defined(_ASM_RM9K_OCD_H) */ -- cgit v1.2.3 From 8471ac1b3fc73aeabdabf9ff3c0a4df71d190448 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 16 Apr 2014 00:31:51 +0200 Subject: MIPS: inst.h: Rename BITFIELD_FIELD to __BITFIELD_FIELD. is exported to userland so the macro name BITFIELD_FIELD pollutes the namespace. Prefix the name with __ fixes this. Signed-off-by: Ralf Baechle --- arch/mips/include/uapi/asm/inst.h | 398 +++++++++++++++++++------------------- 1 file changed, 199 insertions(+), 199 deletions(-) diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h index df6e775f3fef..3125797f2a88 100644 --- a/arch/mips/include/uapi/asm/inst.h +++ b/arch/mips/include/uapi/asm/inst.h @@ -484,13 +484,13 @@ enum MIPS6e_i8_func { * Damn ... bitfields depend from byteorder :-( */ #ifdef __MIPSEB__ -#define BITFIELD_FIELD(field, more) \ +#define __BITFIELD_FIELD(field, more) \ field; \ more #elif defined(__MIPSEL__) -#define BITFIELD_FIELD(field, more) \ +#define __BITFIELD_FIELD(field, more) \ more \ field; @@ -499,112 +499,112 @@ enum MIPS6e_i8_func { #endif struct j_format { - BITFIELD_FIELD(unsigned int opcode : 6, /* Jump format */ - BITFIELD_FIELD(unsigned int target : 26, + __BITFIELD_FIELD(unsigned int opcode : 6, /* Jump format */ + __BITFIELD_FIELD(unsigned int target : 26, ;)) }; struct i_format { /* signed immediate format */ - BITFIELD_FIELD(unsigned int opcode : 6, - BITFIELD_FIELD(unsigned int rs : 5, - BITFIELD_FIELD(unsigned int rt : 5, - BITFIELD_FIELD(signed int simmediate : 16, + __BITFIELD_FIELD(unsigned int opcode : 6, + __BITFIELD_FIELD(unsigned int rs : 5, + __BITFIELD_FIELD(unsigned int rt : 5, + __BITFIELD_FIELD(signed int simmediate : 16, ;)))) }; struct u_format { /* unsigned immediate format */ - BITFIELD_FIELD(unsigned int opcode : 6, - BITFIELD_FIELD(unsigned int rs : 5, - BITFIELD_FIELD(unsigned int rt : 5, - BITFIELD_FIELD(unsigned int uimmediate : 16, + __BITFIELD_FIELD(unsigned int opcode : 6, + __BITFIELD_FIELD(unsigned int rs : 5, + __BITFIELD_FIELD(unsigned int rt : 5, + __BITFIELD_FIELD(unsigned int uimmediate : 16, ;)))) }; struct c_format { /* Cache (>= R6000) format */ - BITFIELD_FIELD(unsigned int opcode : 6, - BITFIELD_FIELD(unsigned int rs : 5, - BITFIELD_FIELD(unsigned int c_op : 3, - BITFIELD_FIELD(unsigned int cache : 2, - BITFIELD_FIELD(unsigned int simmediate : 16, + __BITFIELD_FIELD(unsigned int opcode : 6, + __BITFIELD_FIELD(unsigned int rs : 5, + __BITFIELD_FIELD(unsigned int c_op : 3, + __BITFIELD_FIELD(unsigned int cache : 2, + __BITFIELD_FIELD(unsigned int simmediate : 16, ;))))) }; struct r_format { /* Register format */ - BITFIELD_FIELD(unsigned int opcode : 6, - BITFIELD_FIELD(unsigned int rs : 5, - BITFIELD_FIELD(unsigned int rt : 5, - BITFIELD_FIELD(unsigned int rd : 5, - BITFIELD_FIELD(unsigned int re : 5, - BITFIELD_FIELD(unsigned int func : 6, + __BITFIELD_FIELD(unsigned int opcode : 6, + __BITFIELD_FIELD(unsigned int rs : 5, + __BITFIELD_FIELD(unsigned int rt : 5, + __BITFIELD_FIELD(unsigned int rd : 5, + __BITFIELD_FIELD(unsigned int re : 5, + __BITFIELD_FIELD(unsigned int func : 6, ;)))))) }; struct p_format { /* Performance counter format (R10000) */ - BITFIELD_FIELD(unsigned int opcode : 6, - BITFIELD_FIELD(unsigned int rs : 5, - BITFIELD_FIELD(unsigned int rt : 5, - BITFIELD_FIELD(unsigned int rd : 5, - BITFIELD_FIELD(unsigned int re : 5, - BITFIELD_FIELD(unsigned int func : 6, + __BITFIELD_FIELD(unsigned int opcode : 6, + __BITFIELD_FIELD(unsigned int rs : 5, + __BITFIELD_FIELD(unsigned int rt : 5, + __BITFIELD_FIELD(unsigned int rd : 5, + __BITFIELD_FIELD(unsigned int re : 5, + __BITFIELD_FIELD(unsigned int func : 6, ;)))))) }; struct f_format { /* FPU register format */ - BITFIELD_FIELD(unsigned int opcode : 6, - BITFIELD_FIELD(unsigned int : 1, - BITFIELD_FIELD(unsigned int fmt : 4, - BITFIELD_FIELD(unsigned int rt : 5, - BITFIELD_FIELD(unsigned int rd : 5, - BITFIELD_FIELD(unsigned int re : 5, - BITFIELD_FIELD(unsigned int func : 6, + __BITFIELD_FIELD(unsigned int opcode : 6, + __BITFIELD_FIELD(unsigned int : 1, + __BITFIELD_FIELD(unsigned int fmt : 4, + __BITFIELD_FIELD(unsigned int rt : 5, + __BITFIELD_FIELD(unsigned int rd : 5, + __BITFIELD_FIELD(unsigned int re : 5, + __BITFIELD_FIELD(unsigned int func : 6, ;))))))) }; struct ma_format { /* FPU multiply and add format (MIPS IV) */ - BITFIELD_FIELD(unsigned int opcode : 6, - BITFIELD_FIELD(unsigned int fr : 5, - BITFIELD_FIELD(unsigned int ft : 5, - BITFIELD_FIELD(unsigned int fs : 5, - BITFIELD_FIELD(unsigned int fd : 5, - BITFIELD_FIELD(unsigned int func : 4, - BITFIELD_FIELD(unsigned int fmt : 2, + __BITFIELD_FIELD(unsigned int opcode : 6, + __BITFIELD_FIELD(unsigned int fr : 5, + __BITFIELD_FIELD(unsigned int ft : 5, + __BITFIELD_FIELD(unsigned int fs : 5, + __BITFIELD_FIELD(unsigned int fd : 5, + __BITFIELD_FIELD(unsigned int func : 4, + __BITFIELD_FIELD(unsigned int fmt : 2, ;))))))) }; struct b_format { /* BREAK and SYSCALL */ - BITFIELD_FIELD(unsigned int opcode : 6, - BITFIELD_FIELD(unsigned int code : 20, - BITFIELD_FIELD(unsigned int func : 6, + __BITFIELD_FIELD(unsigned int opcode : 6, + __BITFIELD_FIELD(unsigned int code : 20, + __BITFIELD_FIELD(unsigned int func : 6, ;))) }; struct ps_format { /* MIPS-3D / paired single format */ - BITFIELD_FIELD(unsigned int opcode : 6, - BITFIELD_FIELD(unsigned int rs : 5, - BITFIELD_FIELD(unsigned int ft : 5, - BITFIELD_FIELD(unsigned int fs : 5, - BITFIELD_FIELD(unsigned int fd : 5, - BITFIELD_FIELD(unsigned int func : 6, + __BITFIELD_FIELD(unsigned int opcode : 6, + __BITFIELD_FIELD(unsigned int rs : 5, + __BITFIELD_FIELD(unsigned int ft : 5, + __BITFIELD_FIELD(unsigned int fs : 5, + __BITFIELD_FIELD(unsigned int fd : 5, + __BITFIELD_FIELD(unsigned int func : 6, ;)))))) }; struct v_format { /* MDMX vector format */ - BITFIELD_FIELD(unsigned int opcode : 6, - BITFIELD_FIELD(unsigned int sel : 4, - BITFIELD_FIELD(unsigned int fmt : 1, - BITFIELD_FIELD(unsigned int vt : 5, - BITFIELD_FIELD(unsigned int vs : 5, - BITFIELD_FIELD(unsigned int vd : 5, - BITFIELD_FIELD(unsigned int func : 6, + __BITFIELD_FIELD(unsigned int opcode : 6, + __BITFIELD_FIELD(unsigned int sel : 4, + __BITFIELD_FIELD(unsigned int fmt : 1, + __BITFIELD_FIELD(unsigned int vt : 5, + __BITFIELD_FIELD(unsigned int vs : 5, + __BITFIELD_FIELD(unsigned int vd : 5, + __BITFIELD_FIELD(unsigned int func : 6, ;))))))) }; struct spec3_format { /* SPEC3 */ - BITFIELD_FIELD(unsigned int opcode:6, - BITFIELD_FIELD(unsigned int rs:5, - BITFIELD_FIELD(unsigned int rt:5, - BITFIELD_FIELD(signed int simmediate:9, - BITFIELD_FIELD(unsigned int func:7, + __BITFIELD_FIELD(unsigned int opcode:6, + __BITFIELD_FIELD(unsigned int rs:5, + __BITFIELD_FIELD(unsigned int rt:5, + __BITFIELD_FIELD(signed int simmediate:9, + __BITFIELD_FIELD(unsigned int func:7, ;))))) }; @@ -616,141 +616,141 @@ struct spec3_format { /* SPEC3 */ * if it is MIPS32 instruction re-encoded for use in the microMIPS ASE. */ struct fb_format { /* FPU branch format (MIPS32) */ - BITFIELD_FIELD(unsigned int opcode : 6, - BITFIELD_FIELD(unsigned int bc : 5, - BITFIELD_FIELD(unsigned int cc : 3, - BITFIELD_FIELD(unsigned int flag : 2, - BITFIELD_FIELD(signed int simmediate : 16, + __BITFIELD_FIELD(unsigned int opcode : 6, + __BITFIELD_FIELD(unsigned int bc : 5, + __BITFIELD_FIELD(unsigned int cc : 3, + __BITFIELD_FIELD(unsigned int flag : 2, + __BITFIELD_FIELD(signed int simmediate : 16, ;))))) }; struct fp0_format { /* FPU multiply and add format (MIPS32) */ - BITFIELD_FIELD(unsigned int opcode : 6, - BITFIELD_FIELD(unsigned int fmt : 5, - BITFIELD_FIELD(unsigned int ft : 5, - BITFIELD_FIELD(unsigned int fs : 5, - BITFIELD_FIELD(unsigned int fd : 5, - BITFIELD_FIELD(unsigned int func : 6, + __BITFIELD_FIELD(unsigned int opcode : 6, + __BITFIELD_FIELD(unsigned int fmt : 5, + __BITFIELD_FIELD(unsigned int ft : 5, + __BITFIELD_FIELD(unsigned int fs : 5, + __BITFIELD_FIELD(unsigned int fd : 5, + __BITFIELD_FIELD(unsigned int func : 6, ;)))))) }; struct mm_fp0_format { /* FPU multipy and add format (microMIPS) */ - BITFIELD_FIELD(unsigned int opcode : 6, - BITFIELD_FIELD(unsigned int ft : 5, - BITFIELD_FIELD(unsigned int fs : 5, - BITFIELD_FIELD(unsigned int fd : 5, - BITFIELD_FIELD(unsigned int fmt : 3, - BITFIELD_FIELD(unsigned int op : 2, - BITFIELD_FIELD(unsigned int func : 6, + __BITFIELD_FIELD(unsigned int opcode : 6, + __BITFIELD_FIELD(unsigned int ft : 5, + __BITFIELD_FIELD(unsigned int fs : 5, + __BITFIELD_FIELD(unsigned int fd : 5, + __BITFIELD_FIELD(unsigned int fmt : 3, + __BITFIELD_FIELD(unsigned int op : 2, + __BITFIELD_FIELD(unsigned int func : 6, ;))))))) }; struct fp1_format { /* FPU mfc1 and cfc1 format (MIPS32) */ - BITFIELD_FIELD(unsigned int opcode : 6, - BITFIELD_FIELD(unsigned int op : 5, - BITFIELD_FIELD(unsigned int rt : 5, - BITFIELD_FIELD(unsigned int fs : 5, - BITFIELD_FIELD(unsigned int fd : 5, - BITFIELD_FIELD(unsigned int func : 6, + __BITFIELD_FIELD(unsigned int opcode : 6, + __BITFIELD_FIELD(unsigned int op : 5, + __BITFIELD_FIELD(unsigned int rt : 5, + __BITFIELD_FIELD(unsigned int fs : 5, + __BITFIELD_FIELD(unsigned int fd : 5, + __BITFIELD_FIELD(unsigned int func : 6, ;)))))) }; struct mm_fp1_format { /* FPU mfc1 and cfc1 format (microMIPS) */ - BITFIELD_FIELD(unsigned int opcode : 6, - BITFIELD_FIELD(unsigned int rt : 5, - BITFIELD_FIELD(unsigned int fs : 5, - BITFIELD_FIELD(unsigned int fmt : 2, - BITFIELD_FIELD(unsigned int op : 8, - BITFIELD_FIELD(unsigned int func : 6, + __BITFIELD_FIELD(unsigned int opcode : 6, + __BITFIELD_FIELD(unsigned int rt : 5, + __BITFIELD_FIELD(unsigned int fs : 5, + __BITFIELD_FIELD(unsigned int fmt : 2, + __BITFIELD_FIELD(unsigned int op : 8, + __BITFIELD_FIELD(unsigned int func : 6, ;)))))) }; struct mm_fp2_format { /* FPU movt and movf format (microMIPS) */ - BITFIELD_FIELD(unsigned int opcode : 6, - BITFIELD_FIELD(unsigned int fd : 5, - BITFIELD_FIELD(unsigned int fs : 5, - BITFIELD_FIELD(unsigned int cc : 3, - BITFIELD_FIELD(unsigned int zero : 2, - BITFIELD_FIELD(unsigned int fmt : 2, - BITFIELD_FIELD(unsigned int op : 3, - BITFIELD_FIELD(unsigned int func : 6, + __BITFIELD_FIELD(unsigned int opcode : 6, + __BITFIELD_FIELD(unsigned int fd : 5, + __BITFIELD_FIELD(unsigned int fs : 5, + __BITFIELD_FIELD(unsigned int cc : 3, + __BITFIELD_FIELD(unsigned int zero : 2, + __BITFIELD_FIELD(unsigned int fmt : 2, + __BITFIELD_FIELD(unsigned int op : 3, + __BITFIELD_FIELD(unsigned int func : 6, ;)))))))) }; struct mm_fp3_format { /* FPU abs and neg format (microMIPS) */ - BITFIELD_FIELD(unsigned int opcode : 6, - BITFIELD_FIELD(unsigned int rt : 5, - BITFIELD_FIELD(unsigned int fs : 5, - BITFIELD_FIELD(unsigned int fmt : 3, - BITFIELD_FIELD(unsigned int op : 7, - BITFIELD_FIELD(unsigned int func : 6, + __BITFIELD_FIELD(unsigned int opcode : 6, + __BITFIELD_FIELD(unsigned int rt : 5, + __BITFIELD_FIELD(unsigned int fs : 5, + __BITFIELD_FIELD(unsigned int fmt : 3, + __BITFIELD_FIELD(unsigned int op : 7, + __BITFIELD_FIELD(unsigned int func : 6, ;)))))) }; struct mm_fp4_format { /* FPU c.cond format (microMIPS) */ - BITFIELD_FIELD(unsigned int opcode : 6, - BITFIELD_FIELD(unsigned int rt : 5, - BITFIELD_FIELD(unsigned int fs : 5, - BITFIELD_FIELD(unsigned int cc : 3, - BITFIELD_FIELD(unsigned int fmt : 3, - BITFIELD_FIELD(unsigned int cond : 4, - BITFIELD_FIELD(unsigned int func : 6, + __BITFIELD_FIELD(unsigned int opcode : 6, + __BITFIELD_FIELD(unsigned int rt : 5, + __BITFIELD_FIELD(unsigned int fs : 5, + __BITFIELD_FIELD(unsigned int cc : 3, + __BITFIELD_FIELD(unsigned int fmt : 3, + __BITFIELD_FIELD(unsigned int cond : 4, + __BITFIELD_FIELD(unsigned int func : 6, ;))))))) }; struct mm_fp5_format { /* FPU lwxc1 and swxc1 format (microMIPS) */ - BITFIELD_FIELD(unsigned int opcode : 6, - BITFIELD_FIELD(unsigned int index : 5, - BITFIELD_FIELD(unsigned int base : 5, - BITFIELD_FIELD(unsigned int fd : 5, - BITFIELD_FIELD(unsigned int op : 5, - BITFIELD_FIELD(unsigned int func : 6, + __BITFIELD_FIELD(unsigned int opcode : 6, + __BITFIELD_FIELD(unsigned int index : 5, + __BITFIELD_FIELD(unsigned int base : 5, + __BITFIELD_FIELD(unsigned int fd : 5, + __BITFIELD_FIELD(unsigned int op : 5, + __BITFIELD_FIELD(unsigned int func : 6, ;)))))) }; struct fp6_format { /* FPU madd and msub format (MIPS IV) */ - BITFIELD_FIELD(unsigned int opcode : 6, - BITFIELD_FIELD(unsigned int fr : 5, - BITFIELD_FIELD(unsigned int ft : 5, - BITFIELD_FIELD(unsigned int fs : 5, - BITFIELD_FIELD(unsigned int fd : 5, - BITFIELD_FIELD(unsigned int func : 6, + __BITFIELD_FIELD(unsigned int opcode : 6, + __BITFIELD_FIELD(unsigned int fr : 5, + __BITFIELD_FIELD(unsigned int ft : 5, + __BITFIELD_FIELD(unsigned int fs : 5, + __BITFIELD_FIELD(unsigned int fd : 5, + __BITFIELD_FIELD(unsigned int func : 6, ;)))))) }; struct mm_fp6_format { /* FPU madd and msub format (microMIPS) */ - BITFIELD_FIELD(unsigned int opcode : 6, - BITFIELD_FIELD(unsigned int ft : 5, - BITFIELD_FIELD(unsigned int fs : 5, - BITFIELD_FIELD(unsigned int fd : 5, - BITFIELD_FIELD(unsigned int fr : 5, - BITFIELD_FIELD(unsigned int func : 6, + __BITFIELD_FIELD(unsigned int opcode : 6, + __BITFIELD_FIELD(unsigned int ft : 5, + __BITFIELD_FIELD(unsigned int fs : 5, + __BITFIELD_FIELD(unsigned int fd : 5, + __BITFIELD_FIELD(unsigned int fr : 5, + __BITFIELD_FIELD(unsigned int func : 6, ;)))))) }; struct mm_i_format { /* Immediate format (microMIPS) */ - BITFIELD_FIELD(unsigned int opcode : 6, - BITFIELD_FIELD(unsigned int rt : 5, - BITFIELD_FIELD(unsigned int rs : 5, - BITFIELD_FIELD(signed int simmediate : 16, + __BITFIELD_FIELD(unsigned int opcode : 6, + __BITFIELD_FIELD(unsigned int rt : 5, + __BITFIELD_FIELD(unsigned int rs : 5, + __BITFIELD_FIELD(signed int simmediate : 16, ;)))) }; struct mm_m_format { /* Multi-word load/store format (microMIPS) */ - BITFIELD_FIELD(unsigned int opcode : 6, - BITFIELD_FIELD(unsigned int rd : 5, - BITFIELD_FIELD(unsigned int base : 5, - BITFIELD_FIELD(unsigned int func : 4, - BITFIELD_FIELD(signed int simmediate : 12, + __BITFIELD_FIELD(unsigned int opcode : 6, + __BITFIELD_FIELD(unsigned int rd : 5, + __BITFIELD_FIELD(unsigned int base : 5, + __BITFIELD_FIELD(unsigned int func : 4, + __BITFIELD_FIELD(signed int simmediate : 12, ;))))) }; struct mm_x_format { /* Scaled indexed load format (microMIPS) */ - BITFIELD_FIELD(unsigned int opcode : 6, - BITFIELD_FIELD(unsigned int index : 5, - BITFIELD_FIELD(unsigned int base : 5, - BITFIELD_FIELD(unsigned int rd : 5, - BITFIELD_FIELD(unsigned int func : 11, + __BITFIELD_FIELD(unsigned int opcode : 6, + __BITFIELD_FIELD(unsigned int index : 5, + __BITFIELD_FIELD(unsigned int base : 5, + __BITFIELD_FIELD(unsigned int rd : 5, + __BITFIELD_FIELD(unsigned int func : 11, ;))))) }; @@ -758,51 +758,51 @@ struct mm_x_format { /* Scaled indexed load format (microMIPS) */ * microMIPS instruction formats (16-bit length) */ struct mm_b0_format { /* Unconditional branch format (microMIPS) */ - BITFIELD_FIELD(unsigned int opcode : 6, - BITFIELD_FIELD(signed int simmediate : 10, - BITFIELD_FIELD(unsigned int : 16, /* Ignored */ + __BITFIELD_FIELD(unsigned int opcode : 6, + __BITFIELD_FIELD(signed int simmediate : 10, + __BITFIELD_FIELD(unsigned int : 16, /* Ignored */ ;))) }; struct mm_b1_format { /* Conditional branch format (microMIPS) */ - BITFIELD_FIELD(unsigned int opcode : 6, - BITFIELD_FIELD(unsigned int rs : 3, - BITFIELD_FIELD(signed int simmediate : 7, - BITFIELD_FIELD(unsigned int : 16, /* Ignored */ + __BITFIELD_FIELD(unsigned int opcode : 6, + __BITFIELD_FIELD(unsigned int rs : 3, + __BITFIELD_FIELD(signed int simmediate : 7, + __BITFIELD_FIELD(unsigned int : 16, /* Ignored */ ;)))) }; struct mm16_m_format { /* Multi-word load/store format */ - BITFIELD_FIELD(unsigned int opcode : 6, - BITFIELD_FIELD(unsigned int func : 4, - BITFIELD_FIELD(unsigned int rlist : 2, - BITFIELD_FIELD(unsigned int imm : 4, - BITFIELD_FIELD(unsigned int : 16, /* Ignored */ + __BITFIELD_FIELD(unsigned int opcode : 6, + __BITFIELD_FIELD(unsigned int func : 4, + __BITFIELD_FIELD(unsigned int rlist : 2, + __BITFIELD_FIELD(unsigned int imm : 4, + __BITFIELD_FIELD(unsigned int : 16, /* Ignored */ ;))))) }; struct mm16_rb_format { /* Signed immediate format */ - BITFIELD_FIELD(unsigned int opcode : 6, - BITFIELD_FIELD(unsigned int rt : 3, - BITFIELD_FIELD(unsigned int base : 3, - BITFIELD_FIELD(signed int simmediate : 4, - BITFIELD_FIELD(unsigned int : 16, /* Ignored */ + __BITFIELD_FIELD(unsigned int opcode : 6, + __BITFIELD_FIELD(unsigned int rt : 3, + __BITFIELD_FIELD(unsigned int base : 3, + __BITFIELD_FIELD(signed int simmediate : 4, + __BITFIELD_FIELD(unsigned int : 16, /* Ignored */ ;))))) }; struct mm16_r3_format { /* Load from global pointer format */ - BITFIELD_FIELD(unsigned int opcode : 6, - BITFIELD_FIELD(unsigned int rt : 3, - BITFIELD_FIELD(signed int simmediate : 7, - BITFIELD_FIELD(unsigned int : 16, /* Ignored */ + __BITFIELD_FIELD(unsigned int opcode : 6, + __BITFIELD_FIELD(unsigned int rt : 3, + __BITFIELD_FIELD(signed int simmediate : 7, + __BITFIELD_FIELD(unsigned int : 16, /* Ignored */ ;)))) }; struct mm16_r5_format { /* Load/store from stack pointer format */ - BITFIELD_FIELD(unsigned int opcode : 6, - BITFIELD_FIELD(unsigned int rt : 5, - BITFIELD_FIELD(signed int simmediate : 5, - BITFIELD_FIELD(unsigned int : 16, /* Ignored */ + __BITFIELD_FIELD(unsigned int opcode : 6, + __BITFIELD_FIELD(unsigned int rt : 5, + __BITFIELD_FIELD(signed int simmediate : 5, + __BITFIELD_FIELD(unsigned int : 16, /* Ignored */ ;)))) }; @@ -810,57 +810,57 @@ struct mm16_r5_format { /* Load/store from stack pointer format */ * MIPS16e instruction formats (16-bit length) */ struct m16e_rr { - BITFIELD_FIELD(unsigned int opcode : 5, - BITFIELD_FIELD(unsigned int rx : 3, - BITFIELD_FIELD(unsigned int nd : 1, - BITFIELD_FIELD(unsigned int l : 1, - BITFIELD_FIELD(unsigned int ra : 1, - BITFIELD_FIELD(unsigned int func : 5, + __BITFIELD_FIELD(unsigned int opcode : 5, + __BITFIELD_FIELD(unsigned int rx : 3, + __BITFIELD_FIELD(unsigned int nd : 1, + __BITFIELD_FIELD(unsigned int l : 1, + __BITFIELD_FIELD(unsigned int ra : 1, + __BITFIELD_FIELD(unsigned int func : 5, ;)))))) }; struct m16e_jal { - BITFIELD_FIELD(unsigned int opcode : 5, - BITFIELD_FIELD(unsigned int x : 1, - BITFIELD_FIELD(unsigned int imm20_16 : 5, - BITFIELD_FIELD(signed int imm25_21 : 5, + __BITFIELD_FIELD(unsigned int opcode : 5, + __BITFIELD_FIELD(unsigned int x : 1, + __BITFIELD_FIELD(unsigned int imm20_16 : 5, + __BITFIELD_FIELD(signed int imm25_21 : 5, ;)))) }; struct m16e_i64 { - BITFIELD_FIELD(unsigned int opcode : 5, - BITFIELD_FIELD(unsigned int func : 3, - BITFIELD_FIELD(unsigned int imm : 8, + __BITFIELD_FIELD(unsigned int opcode : 5, + __BITFIELD_FIELD(unsigned int func : 3, + __BITFIELD_FIELD(unsigned int imm : 8, ;))) }; struct m16e_ri64 { - BITFIELD_FIELD(unsigned int opcode : 5, - BITFIELD_FIELD(unsigned int func : 3, - BITFIELD_FIELD(unsigned int ry : 3, - BITFIELD_FIELD(unsigned int imm : 5, + __BITFIELD_FIELD(unsigned int opcode : 5, + __BITFIELD_FIELD(unsigned int func : 3, + __BITFIELD_FIELD(unsigned int ry : 3, + __BITFIELD_FIELD(unsigned int imm : 5, ;)))) }; struct m16e_ri { - BITFIELD_FIELD(unsigned int opcode : 5, - BITFIELD_FIELD(unsigned int rx : 3, - BITFIELD_FIELD(unsigned int imm : 8, + __BITFIELD_FIELD(unsigned int opcode : 5, + __BITFIELD_FIELD(unsigned int rx : 3, + __BITFIELD_FIELD(unsigned int imm : 8, ;))) }; struct m16e_rri { - BITFIELD_FIELD(unsigned int opcode : 5, - BITFIELD_FIELD(unsigned int rx : 3, - BITFIELD_FIELD(unsigned int ry : 3, - BITFIELD_FIELD(unsigned int imm : 5, + __BITFIELD_FIELD(unsigned int opcode : 5, + __BITFIELD_FIELD(unsigned int rx : 3, + __BITFIELD_FIELD(unsigned int ry : 3, + __BITFIELD_FIELD(unsigned int imm : 5, ;)))) }; struct m16e_i8 { - BITFIELD_FIELD(unsigned int opcode : 5, - BITFIELD_FIELD(unsigned int func : 3, - BITFIELD_FIELD(unsigned int imm : 8, + __BITFIELD_FIELD(unsigned int opcode : 5, + __BITFIELD_FIELD(unsigned int func : 3, + __BITFIELD_FIELD(unsigned int imm : 8, ;))) }; -- cgit v1.2.3 From 8e33f91a0b84ae1964bef77cb92f5d41d97530c8 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 15 Apr 2014 17:06:34 +0100 Subject: clk: shmobile: clk-mstp: change to using clock-indices With the addition of clock-indices, we need to change the renesas clock implementation to use these instead of the local definition of "renesas,clock-indices". Since this will break booting with older device trees, we add a simple auto-detection of which properties are present. Signed-off-by: Ben Dooks Acked-by: Geert Uytterhoeven Reviewed-by: Wolfram Sang Signed-off-by: Mike Turquette --- .../devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt | 2 +- drivers/clk/shmobile/clk-mstp.c | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt b/Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt index 5992dceec7af..02a25d99ca61 100644 --- a/Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt +++ b/Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt @@ -43,7 +43,7 @@ Example clock-output-names = "tpu0", "mmcif1", "sdhi3", "sdhi2", "sdhi1", "sdhi0", "mmcif0"; - renesas,clock-indices = < + clock-indices = < R8A7790_CLK_TPU0 R8A7790_CLK_MMCIF1 R8A7790_CLK_SDHI3 R8A7790_CLK_SDHI2 R8A7790_CLK_SDHI1 R8A7790_CLK_SDHI0 R8A7790_CLK_MMCIF0 diff --git a/drivers/clk/shmobile/clk-mstp.c b/drivers/clk/shmobile/clk-mstp.c index 2e5810c88d11..1f6324e29a80 100644 --- a/drivers/clk/shmobile/clk-mstp.c +++ b/drivers/clk/shmobile/clk-mstp.c @@ -156,6 +156,7 @@ cpg_mstp_clock_register(const char *name, const char *parent_name, static void __init cpg_mstp_clocks_init(struct device_node *np) { struct mstp_clock_group *group; + const char *idxname; struct clk **clks; unsigned int i; @@ -184,6 +185,11 @@ static void __init cpg_mstp_clocks_init(struct device_node *np) for (i = 0; i < MSTP_MAX_CLOCKS; ++i) clks[i] = ERR_PTR(-ENOENT); + if (of_find_property(np, "clock-indices", &i)) + idxname = "clock-indices"; + else + idxname = "renesas,clock-indices"; + for (i = 0; i < MSTP_MAX_CLOCKS; ++i) { const char *parent_name; const char *name; @@ -197,8 +203,7 @@ static void __init cpg_mstp_clocks_init(struct device_node *np) continue; parent_name = of_clk_get_parent_name(np, i); - ret = of_property_read_u32_index(np, "renesas,clock-indices", i, - &clkidx); + ret = of_property_read_u32_index(np, idxname, i, &clkidx); if (parent_name == NULL || ret < 0) break; -- cgit v1.2.3 From c8965932a2e3b70197ec02c6741c29460279e2a8 Mon Sep 17 00:00:00 2001 From: Susant Sahani Date: Sat, 10 May 2014 00:11:32 +0530 Subject: ip6_tunnel: fix potential NULL pointer dereference The function ip6_tnl_validate assumes that the rtnl attribute IFLA_IPTUN_PROTO always be filled . If this attribute is not filled by the userspace application kernel get crashed with NULL pointer dereference. This patch fixes the potential kernel crash when IFLA_IPTUN_PROTO is missing . Signed-off-by: Susant Sahani Acked-by: Thomas Graf Signed-off-by: David S. Miller --- net/ipv6/ip6_tunnel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index b05b609f69d1..f6a66bb4114d 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -1557,7 +1557,7 @@ static int ip6_tnl_validate(struct nlattr *tb[], struct nlattr *data[]) { u8 proto; - if (!data) + if (!data || !data[IFLA_IPTUN_PROTO]) return 0; proto = nla_get_u8(data[IFLA_IPTUN_PROTO]); -- cgit v1.2.3 From ec5fe98886b686f065ef29d8dee1b3ca66f5fd48 Mon Sep 17 00:00:00 2001 From: Aaron Plattner Date: Mon, 12 May 2014 20:05:02 -0700 Subject: ALSA: hda - Add new GPU codec ID to snd-hda Vendor ID 0x10de0071 is used by a yet-to-be-named GPU chip. Signed-off-by: Aaron Plattner Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 1edbb9c47c2d..b4218a19df22 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -3332,6 +3332,7 @@ static const struct hda_codec_preset snd_hda_preset_hdmi[] = { { .id = 0x10de0051, .name = "GPU 51 HDMI/DP", .patch = patch_nvhdmi }, { .id = 0x10de0060, .name = "GPU 60 HDMI/DP", .patch = patch_nvhdmi }, { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch }, +{ .id = 0x10de0071, .name = "GPU 71 HDMI/DP", .patch = patch_nvhdmi }, { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch }, { .id = 0x11069f80, .name = "VX900 HDMI/DP", .patch = patch_via_hdmi }, { .id = 0x11069f81, .name = "VX900 HDMI/DP", .patch = patch_via_hdmi }, @@ -3387,6 +3388,7 @@ MODULE_ALIAS("snd-hda-codec-id:10de0044"); MODULE_ALIAS("snd-hda-codec-id:10de0051"); MODULE_ALIAS("snd-hda-codec-id:10de0060"); MODULE_ALIAS("snd-hda-codec-id:10de0067"); +MODULE_ALIAS("snd-hda-codec-id:10de0071"); MODULE_ALIAS("snd-hda-codec-id:10de8001"); MODULE_ALIAS("snd-hda-codec-id:11069f80"); MODULE_ALIAS("snd-hda-codec-id:11069f81"); -- cgit v1.2.3 From c1ff0b474c35905061b18e050be14e5a673a5965 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 12 May 2014 18:32:55 +0200 Subject: ARM: at91/dt: sam9260: correct external trigger value The external trigger value is 0b1101 which is 13 but 0xd. Signed-off-by: Alexandre Belloni Signed-off-by: Nicolas Ferre --- arch/arm/boot/dts/at91sam9260.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/at91sam9260.dtsi b/arch/arm/boot/dts/at91sam9260.dtsi index 366fc2cbcd64..c0e0eae16a27 100644 --- a/arch/arm/boot/dts/at91sam9260.dtsi +++ b/arch/arm/boot/dts/at91sam9260.dtsi @@ -641,7 +641,7 @@ trigger@3 { reg = <3>; trigger-name = "external"; - trigger-value = <0x13>; + trigger-value = <0xd>; trigger-external; }; }; -- cgit v1.2.3 From 7189eb9b8f7962474956196c301676470542f253 Mon Sep 17 00:00:00 2001 From: Mengdong Lin Date: Tue, 13 May 2014 16:57:08 +0800 Subject: ALSA: hda - mask buggy stream DMA0 for Broadwell display controller Broadwell display controller has 3 stream DMA engines. DMA0 cannot update DMA postion buffer properly while DMA1 and DMA2 can work well. So this patch masks the buggy DMA0 by keeping it as opened. This is a tentative workaround, so keep the change small as Takashi suggested. Signed-off-by: Mengdong Lin Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index b540ad71eb0d..2c54629d62d1 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -1367,6 +1367,12 @@ static int azx_first_init(struct azx *chip) /* initialize streams */ azx_init_stream(chip); + /* workaround for Broadwell HDMI: the first stream is broken, + * so mask it by keeping it as if opened + */ + if (pci->vendor == 0x8086 && pci->device == 0x160c) + chip->azx_dev[0].opened = 1; + /* initialize chip */ azx_init_pci(chip); azx_init_chip(chip, (probe_only[dev] & 2) == 0); -- cgit v1.2.3 From e028a9e6b8a637af09ac4114083280df4a7045f1 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Tue, 22 Apr 2014 10:08:40 -0600 Subject: iommu/amd: Fix interrupt remapping for aliased devices An apparent cut and paste error prevents the correct flags from being set on the alias device resulting in MSI on conventional PCI devices failing to work. This also produces error events from the IOMMU like: AMD-Vi: Event logged [INVALID_DEVICE_REQUEST device=00:14.4 address=0x000000fdf8000000 flags=0x0a00] Where 14.4 is a PCIe-to-PCI bridge with a device behind it trying to use MSI interrupts. Signed-off-by: Alex Williamson Cc: stable@vger.kernel.org Signed-off-by: Joerg Roedel --- drivers/iommu/amd_iommu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index c949520bd196..57068e8035b5 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -3999,7 +3999,7 @@ static struct irq_remap_table *get_irq_table(u16 devid, bool ioapic) iommu_flush_dte(iommu, devid); if (devid != alias) { irq_lookup_table[alias] = table; - set_dte_irq_entry(devid, table); + set_dte_irq_entry(alias, table); iommu_flush_dte(iommu, alias); } -- cgit v1.2.3 From 4378d99295fae5fd42b0ed1a3eeef2a1684e0c17 Mon Sep 17 00:00:00 2001 From: Jay Cornwall Date: Mon, 28 Apr 2014 17:27:46 -0500 Subject: iommu/amd: Take mmap_sem when calling get_user_pages get_user_pages requires caller to hold a read lock on mmap_sem. Signed-off-by: Jay Cornwall Signed-off-by: Suravee Suthikulpanit Signed-off-by: Joerg Roedel --- drivers/iommu/amd_iommu_v2.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/iommu/amd_iommu_v2.c b/drivers/iommu/amd_iommu_v2.c index 5208828792e6..203b2e6a91cf 100644 --- a/drivers/iommu/amd_iommu_v2.c +++ b/drivers/iommu/amd_iommu_v2.c @@ -504,8 +504,10 @@ static void do_fault(struct work_struct *work) write = !!(fault->flags & PPR_FAULT_WRITE); + down_read(&fault->state->mm->mmap_sem); npages = get_user_pages(fault->state->task, fault->state->mm, fault->address, 1, write, 0, &page, NULL); + up_read(&fault->state->mm->mmap_sem); if (npages == 1) { put_page(page); -- cgit v1.2.3 From 2c16c9fdacbbf3bd8ff6390e12c5d28b3f2c78ac Mon Sep 17 00:00:00 2001 From: Su Friendy Date: Wed, 7 May 2014 13:54:52 +0800 Subject: iommu/amd: fix enabling exclusion range for an exact device set_device_exclusion_range(u16 devid, struct ivmd_header *m) enables exclusion range for ONE device. IOMMU does not translate the access to the exclusion range from the device. The device is specified by input argument 'devid'. But 'devid' is not passed to the actual set function set_dev_entry_bit(), instead 'm->devid' is passed. 'm->devid' does not specify the exact device which needs enable the exclusion range. 'm->devid' represents DeviceID field of IVMD, which has different meaning depends on IVMD type. The caller init_exclusion_range() sets 'devid' for ONE device. When m->type is equal to ACPI_IVMD_TYPE_ALL or ACPI_IVMD_TYPE_RANGE, 'm->devid' is not equal to 'devid'. This patch fixes 'm->devid' to 'devid'. Signed-off-by: Su Friendy Signed-off-by: Tamori Masahiro Signed-off-by: Joerg Roedel --- drivers/iommu/amd_iommu_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index b76c58dbe30c..0e08545d7298 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -788,7 +788,7 @@ static void __init set_device_exclusion_range(u16 devid, struct ivmd_header *m) * per device. But we can enable the exclusion range per * device. This is done here */ - set_dev_entry_bit(m->devid, DEV_ENTRY_EX); + set_dev_entry_bit(devid, DEV_ENTRY_EX); iommu->exclusion_start = m->range_start; iommu->exclusion_length = m->range_length; } -- cgit v1.2.3 From 64793110ad4d82e18d88a33307749c6562a6dd04 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 11 May 2014 19:59:43 +0300 Subject: iwlwifi: mvm: fix off-by-one in scan channels configuration tail should be equal to the last valid index, so decrease it by one. This error causes in "a gap" in some cases (as well as some possible out-of-bound write), finally resulting in ucode assertion. Signed-off-by: Eliad Peller Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/scan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index cba88a379fc8..c28de54c75d4 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c @@ -732,7 +732,7 @@ int iwl_mvm_config_sched_scan(struct iwl_mvm *mvm, int band_2ghz = mvm->nvm_data->bands[IEEE80211_BAND_2GHZ].n_channels; int band_5ghz = mvm->nvm_data->bands[IEEE80211_BAND_5GHZ].n_channels; int head = 0; - int tail = band_2ghz + band_5ghz; + int tail = band_2ghz + band_5ghz - 1; u32 ssid_bitmap; int cmd_len; int ret; -- cgit v1.2.3 From 555724a831b4a146e7bdf16ecc989cda032b076d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 12 May 2014 13:56:27 -0400 Subject: kernfs, sysfs, cgroup: restrict extra perm check on open to sysfs The kernfs open method - kernfs_fop_open() - inherited extra permission checks from sysfs. While the vfs layer allows ignoring the read/write permissions checks if the issuer has CAP_DAC_OVERRIDE, sysfs explicitly denied open regardless of the cap if the file doesn't have any of the UGO perms of the requested access or doesn't implement the requested operation. It can be debated whether this was a good idea or not but the behavior is too subtle and dangerous to change at this point. After cgroup got converted to kernfs, this extra perm check also got applied to cgroup breaking libcgroup which opens write-only files with O_RDWR as root. This patch gates the extra open permission check with a new flag KERNFS_ROOT_EXTRA_OPEN_PERM_CHECK and enables it for sysfs. For sysfs, nothing changes. For cgroup, root now can perform any operation regardless of the permissions as it was before kernfs conversion. Note that kernfs still fails unimplemented operations with -EINVAL. While at it, add comments explaining KERNFS_ROOT flags. Signed-off-by: Tejun Heo Reported-by: Andrey Wagin Tested-by: Andrey Wagin Cc: Li Zefan References: http://lkml.kernel.org/g/CANaxB-xUm3rJ-Cbp72q-rQJO5mZe1qK6qXsQM=vh0U8upJ44+A@mail.gmail.com Fixes: 2bd59d48ebfb ("cgroup: convert to kernfs") Signed-off-by: Greg Kroah-Hartman --- fs/kernfs/file.c | 17 ++++++++++------- fs/sysfs/mount.c | 3 ++- include/linux/kernfs.h | 19 ++++++++++++++++++- 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/fs/kernfs/file.c b/fs/kernfs/file.c index e01ea4a14a01..5e9a80cfc3d8 100644 --- a/fs/kernfs/file.c +++ b/fs/kernfs/file.c @@ -610,6 +610,7 @@ static void kernfs_put_open_node(struct kernfs_node *kn, static int kernfs_fop_open(struct inode *inode, struct file *file) { struct kernfs_node *kn = file->f_path.dentry->d_fsdata; + struct kernfs_root *root = kernfs_root(kn); const struct kernfs_ops *ops; struct kernfs_open_file *of; bool has_read, has_write, has_mmap; @@ -624,14 +625,16 @@ static int kernfs_fop_open(struct inode *inode, struct file *file) has_write = ops->write || ops->mmap; has_mmap = ops->mmap; - /* check perms and supported operations */ - if ((file->f_mode & FMODE_WRITE) && - (!(inode->i_mode & S_IWUGO) || !has_write)) - goto err_out; + /* see the flag definition for details */ + if (root->flags & KERNFS_ROOT_EXTRA_OPEN_PERM_CHECK) { + if ((file->f_mode & FMODE_WRITE) && + (!(inode->i_mode & S_IWUGO) || !has_write)) + goto err_out; - if ((file->f_mode & FMODE_READ) && - (!(inode->i_mode & S_IRUGO) || !has_read)) - goto err_out; + if ((file->f_mode & FMODE_READ) && + (!(inode->i_mode & S_IRUGO) || !has_read)) + goto err_out; + } /* allocate a kernfs_open_file for the file */ error = -ENOMEM; diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c index a66ad6196f59..8794423f7efb 100644 --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c @@ -63,7 +63,8 @@ int __init sysfs_init(void) { int err; - sysfs_root = kernfs_create_root(NULL, 0, NULL); + sysfs_root = kernfs_create_root(NULL, KERNFS_ROOT_EXTRA_OPEN_PERM_CHECK, + NULL); if (IS_ERR(sysfs_root)) return PTR_ERR(sysfs_root); diff --git a/include/linux/kernfs.h b/include/linux/kernfs.h index b0122dc6f96a..ca1be5c9136c 100644 --- a/include/linux/kernfs.h +++ b/include/linux/kernfs.h @@ -50,7 +50,24 @@ enum kernfs_node_flag { /* @flags for kernfs_create_root() */ enum kernfs_root_flag { - KERNFS_ROOT_CREATE_DEACTIVATED = 0x0001, + /* + * kernfs_nodes are created in the deactivated state and invisible. + * They require explicit kernfs_activate() to become visible. This + * can be used to make related nodes become visible atomically + * after all nodes are created successfully. + */ + KERNFS_ROOT_CREATE_DEACTIVATED = 0x0001, + + /* + * For regular flies, if the opener has CAP_DAC_OVERRIDE, open(2) + * succeeds regardless of the RW permissions. sysfs had an extra + * layer of enforcement where open(2) fails with -EACCES regardless + * of CAP_DAC_OVERRIDE if the permission doesn't have the + * respective read or write access at all (none of S_IRUGO or + * S_IWUGO) or the respective operation isn't implemented. The + * following flag enables that behavior. + */ + KERNFS_ROOT_EXTRA_OPEN_PERM_CHECK = 0x0002, }; /* type-specific structures for kernfs_node union members */ -- cgit v1.2.3 From c52666aef9f2dff39276eb53f15d99e2e229870f Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Tue, 13 May 2014 12:54:09 +0300 Subject: mac80211: fix suspend vs. association race If the association is in progress while we suspend, the stack will be in a messed up state. Clean it before we suspend. This patch completes Johannes's patch: 1a1cb744de160ee70086a77afff605bbc275d291 Author: Johannes Berg mac80211: fix suspend vs. authentication race Cc: Fixes: 12e7f517029d ("mac80211: cleanup generic suspend/resume procedures") Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- net/mac80211/mlme.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index dee50aefd6e8..27600a9808ba 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -3598,18 +3598,24 @@ void ieee80211_mgd_quiesce(struct ieee80211_sub_if_data *sdata) sdata_lock(sdata); - if (ifmgd->auth_data) { + if (ifmgd->auth_data || ifmgd->assoc_data) { + const u8 *bssid = ifmgd->auth_data ? + ifmgd->auth_data->bss->bssid : + ifmgd->assoc_data->bss->bssid; + /* - * If we are trying to authenticate while suspending, cfg80211 - * won't know and won't actually abort those attempts, thus we - * need to do that ourselves. + * If we are trying to authenticate / associate while suspending, + * cfg80211 won't know and won't actually abort those attempts, + * thus we need to do that ourselves. */ - ieee80211_send_deauth_disassoc(sdata, - ifmgd->auth_data->bss->bssid, + ieee80211_send_deauth_disassoc(sdata, bssid, IEEE80211_STYPE_DEAUTH, WLAN_REASON_DEAUTH_LEAVING, false, frame_buf); - ieee80211_destroy_auth_data(sdata, false); + if (ifmgd->assoc_data) + ieee80211_destroy_assoc_data(sdata, false); + if (ifmgd->auth_data) + ieee80211_destroy_auth_data(sdata, false); cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf, IEEE80211_DEAUTH_FRAME_LEN); } -- cgit v1.2.3 From b538b8ce76f69f7fa225bc0817bbb361b877ea23 Mon Sep 17 00:00:00 2001 From: David Spinadel Date: Tue, 13 May 2014 14:29:36 +0300 Subject: iwlwifi: mvm: prevent sched scan while not idle Prevent sched scan while not idle (including during association or in AP mode) instead of while associated only. This fixes my previous commit which was incomplete: commit bd5e4744a6ca64299b57a2682c720d00a475a734 Author: David Spinadel Date: Thu Apr 24 13:15:29 2014 +0300 iwlwifi: mvm: do no sched scan while associated Currently the FW doesn't support sched scan while associated, Prevent it. Signed-off-by: David Spinadel Reviewed-by: Johannes Berg Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/mac80211.c | 2 +- drivers/net/wireless/iwlwifi/mvm/mvm.h | 2 +- drivers/net/wireless/iwlwifi/mvm/utils.c | 16 ++++++++-------- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index 4b0b8b6571ee..b41dc84e9431 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -1807,7 +1807,7 @@ static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw, mutex_lock(&mvm->mutex); - if (iwl_mvm_is_associated(mvm)) { + if (!iwl_mvm_is_idle(mvm)) { ret = -EBUSY; goto out; } diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index 84c75a1b267e..f1ec0986c3c9 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h @@ -1004,7 +1004,7 @@ static inline bool iwl_mvm_vif_low_latency(struct iwl_mvm_vif *mvmvif) } /* Assoc status */ -bool iwl_mvm_is_associated(struct iwl_mvm *mvm); +bool iwl_mvm_is_idle(struct iwl_mvm *mvm); /* Thermal management and CT-kill */ void iwl_mvm_tt_tx_backoff(struct iwl_mvm *mvm, u32 backoff); diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c index 6fdbef9696d8..2180902266ae 100644 --- a/drivers/net/wireless/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/iwlwifi/mvm/utils.c @@ -645,21 +645,21 @@ bool iwl_mvm_low_latency(struct iwl_mvm *mvm) return result; } -static void iwl_mvm_assoc_iter(void *_data, u8 *mac, struct ieee80211_vif *vif) +static void iwl_mvm_idle_iter(void *_data, u8 *mac, struct ieee80211_vif *vif) { - bool *assoc = _data; + bool *idle = _data; - if (vif->bss_conf.assoc) - *assoc = true; + if (!vif->bss_conf.idle) + *idle = false; } -bool iwl_mvm_is_associated(struct iwl_mvm *mvm) +bool iwl_mvm_is_idle(struct iwl_mvm *mvm) { - bool assoc = false; + bool idle = true; ieee80211_iterate_active_interfaces_atomic( mvm->hw, IEEE80211_IFACE_ITER_NORMAL, - iwl_mvm_assoc_iter, &assoc); + iwl_mvm_idle_iter, &idle); - return assoc; + return idle; } -- cgit v1.2.3 From 5ff365fb6aed4c7ee5aae7b0239ce0b514aefabc Mon Sep 17 00:00:00 2001 From: Aaron Lu Date: Tue, 13 May 2014 09:51:50 +0800 Subject: ACPI / video: correct DMI tag for Dell Inspiron 7520 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The DMI tag used to identify Dell Inspiron 7520 should be product name instead of product version. Fixes: 0e9f81d3b7cd (ACPI / video: Add systems that should favour native backlight interface) Reported-and-tested-by: Téo Mazars References: https://bugzilla.redhat.com/show_bug.cgi?id=909552 Cc: All applicable Signed-off-by: Aaron Lu Signed-off-by: Rafael J. Wysocki --- 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 88393899a0bc..6c76a49be12e 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -508,7 +508,7 @@ static struct dmi_system_id video_dmi_table[] __initdata = { .ident = "Dell Inspiron 7520", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_VERSION, "Inspiron 7520"), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7520"), }, }, { -- cgit v1.2.3 From f5651986fe438c1ba05fdafa383d38bd86713d13 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 13 May 2014 15:45:55 +0200 Subject: nl80211: fix NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL API My commit removing that also removed it from the header file which can break compilation of userspace that needed it, add it back for API/ABI compatibility purposes (but no code to implement anything for it.) Signed-off-by: Johannes Berg --- include/uapi/linux/nl80211.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 1ba9d626aa83..194c1eab04d8 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -3856,6 +3856,8 @@ enum nl80211_ap_sme_features { * @NL80211_FEATURE_CELL_BASE_REG_HINTS: This driver has been tested * to work properly to suppport receiving regulatory hints from * cellular base stations. + * @NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL: (no longer available, only + * here to reserve the value for API/ABI compatibility) * @NL80211_FEATURE_SAE: This driver supports simultaneous authentication of * equals (SAE) with user space SME (NL80211_CMD_AUTHENTICATE) in station * mode @@ -3897,7 +3899,7 @@ enum nl80211_feature_flags { NL80211_FEATURE_HT_IBSS = 1 << 1, NL80211_FEATURE_INACTIVITY_TIMER = 1 << 2, NL80211_FEATURE_CELL_BASE_REG_HINTS = 1 << 3, - /* bit 4 is reserved - don't use */ + NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL = 1 << 4, NL80211_FEATURE_SAE = 1 << 5, NL80211_FEATURE_LOW_PRIORITY_SCAN = 1 << 6, NL80211_FEATURE_SCAN_FLUSH = 1 << 7, -- cgit v1.2.3 From 85dbd5801f62b66e2aa7826aaefcaebead44c8a6 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Tue, 13 May 2014 16:50:30 +0800 Subject: ACPICA: Tables: Restore old behavor to favor 32-bit FADT addresses. We need to find a smarter way to switch to 64-bit FADT addresses according to the bug report. This patch reverts Linux to the original behavior. Fixes: 0249ed2444d6 (ACPICA: Add option to favor 32-bit FADT addresses.) References: https://bugzilla.kernel.org/show_bug.cgi?id=74021 Reported-and-tested-by: Oswald Buddenhagen Signed-off-by: Lv Zheng Cc: 3.14+ # 3.14+ Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/acglobal.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index 49bbc71fad54..a08a448068dd 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h @@ -141,9 +141,9 @@ ACPI_INIT_GLOBAL(u8, acpi_gbl_do_not_use_xsdt, FALSE); * address. Although ACPICA adheres to the ACPI specification which * requires the use of the corresponding 64-bit address if it is non-zero, * some machines have been found to have a corrupted non-zero 64-bit - * address. Default is FALSE, do not favor the 32-bit addresses. + * address. Default is TRUE, favor the 32-bit addresses. */ -ACPI_INIT_GLOBAL(u8, acpi_gbl_use32_bit_fadt_addresses, FALSE); +ACPI_INIT_GLOBAL(u8, acpi_gbl_use32_bit_fadt_addresses, TRUE); /* * Optionally truncate I/O addresses to 16 bits. Provides compatibility -- cgit v1.2.3 From 42a18d1cf484d02e23afadfa5dc09356e6bef9fa Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Mon, 12 May 2014 16:11:39 +0200 Subject: ARM: mvebu: mvebu-soc-id: add missing clk_put() call The mvebu-soc-id code in mach-mvebu/ needs to enable a clock to read the SoC device ID and revision number. To do so, it does a clk_get(), then a clk_prepare_enable(), reads the value, and disables the clock with clk_disable_unprepare(). However, it forgets to clk_put() the clock. This commit fixes this issue. Signed-off-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1399903900-29977-2-git-send-email-thomas.petazzoni@free-electrons.com Cc: # 3.14+ Fixes: af8d1c63afcb ("ARM: mvebu: Add support to get the ID and the revision of a SoC") Acked-by: Gregory CLEMENT Tested-by: Gregory CLEMENT Tested-by: Andrew Lunn Tested-by: Willy Tarreau Signed-off-by: Jason Cooper --- arch/arm/mach-mvebu/mvebu-soc-id.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-mvebu/mvebu-soc-id.c b/arch/arm/mach-mvebu/mvebu-soc-id.c index f3d4cf53f746..b52af6f4a0c6 100644 --- a/arch/arm/mach-mvebu/mvebu-soc-id.c +++ b/arch/arm/mach-mvebu/mvebu-soc-id.c @@ -109,6 +109,7 @@ static int __init mvebu_soc_id_init(void) res_ioremap: clk_disable_unprepare(clk); + clk_put(clk); clk_err: of_node_put(child); -- cgit v1.2.3 From b25bcf1bcaf6687991ae08dd76cd784bf9fe3d05 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Mon, 12 May 2014 16:11:40 +0200 Subject: ARM: mvebu: mvebu-soc-id: keep clock enabled if PCIe unit is enabled Since the mvebu-soc-id code in mach-mvebu/ was introduced, several users have noticed a regression: the PCIe card connected in the first PCIe interface is not detected properly. This is due to the fact that the mvebu-soc-id code enables the PCIe clock of the first PCIe interface, reads the SoC device ID and revision number (yes this information is made available as part of PCIe registers), and then disables the clock. However, by doing this, we gate the clock and therefore loose the complex PCIe configuration that was done by the bootloader. Unfortunately, as of today, the kernel is not capable of doing this complex configuration by itself, so we really need to keep the PCIe clock enabled. However, we don't want to keep it enabled unconditionally: if the PCIe interface is not enabled or PCI support is not compiled into the kernel, there is no reason to keep the PCIe clock running. This issue was discussed with Kevin Hilman, and the suggested solution was to make the mvebu-soc-id code keep the clock enabled in case it will be needed for PCIe. This is therefore the solution implemented in this patch. Long term, we hope to make the kernel more capable in terms of PCIe configuration for this platform, which will anyway be needed to support the compilation of the PCIe host controller driver as a module. In the mean time however, we don't have much other choice than to implement the currently proposed solution. Reported-by: Neil Greatorex Cc: Neil Greatorex Cc: Jason Gunthorpe Cc: Kevin Hilman Signed-off-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1399903900-29977-3-git-send-email-thomas.petazzoni@free-electrons.com Fixes: af8d1c63afcb ("ARM: mvebu: Add support to get the ID and the revision of a SoC") Cc: # 3.14+: 42a18d1cf484: ARM: mvebu: mvebu-soc-id: add missing clk_put() call Cc: # 3.14+ Acked-by: Gregory CLEMENT Tested-by: Gregory CLEMENT Tested-by: Andrew Lunn Tested-by: Willy Tarreau Signed-off-by: Jason Cooper --- arch/arm/mach-mvebu/mvebu-soc-id.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-mvebu/mvebu-soc-id.c b/arch/arm/mach-mvebu/mvebu-soc-id.c index b52af6f4a0c6..09520e19b78e 100644 --- a/arch/arm/mach-mvebu/mvebu-soc-id.c +++ b/arch/arm/mach-mvebu/mvebu-soc-id.c @@ -108,8 +108,18 @@ static int __init mvebu_soc_id_init(void) iounmap(pci_base); res_ioremap: - clk_disable_unprepare(clk); - clk_put(clk); + /* + * If the PCIe unit is actually enabled and we have PCI + * support in the kernel, we intentionally do not release the + * reference to the clock. We want to keep it running since + * the bootloader does some PCIe link configuration that the + * kernel is for now unable to do, and gating the clock would + * make us loose this precious configuration. + */ + if (!of_device_is_available(child) || !IS_ENABLED(CONFIG_PCI_MVEBU)) { + clk_disable_unprepare(clk); + clk_put(clk); + } clk_err: of_node_put(child); -- cgit v1.2.3 From 5024ae29cd285ce9e736776414da645d3a91828c Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 7 May 2014 21:31:17 -0400 Subject: cgroup: introduce task_css_is_root() Determining the css of a task usually requires RCU read lock as that's the only thing which keeps the returned css accessible till its reference is acquired; however, testing whether a task belongs to the root can be performed without dereferencing the returned css by comparing the returned pointer against the root one in init_css_set[] which never changes. Implement task_css_is_root() which can be invoked in any context. This will be used by the scheduled cgroup_freezer change. v2: cgroup no longer supports modular controllers. No need to export init_css_set. Pointed out by Li. Signed-off-by: Tejun Heo Acked-by: Li Zefan --- include/linux/cgroup.h | 15 +++++++++++++++ kernel/cgroup.c | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index c2515851c1aa..d60904b9e505 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h @@ -473,6 +473,7 @@ struct cftype { }; extern struct cgroup_root cgrp_dfl_root; +extern struct css_set init_css_set; static inline bool cgroup_on_dfl(const struct cgroup *cgrp) { @@ -700,6 +701,20 @@ static inline struct cgroup_subsys_state *task_css(struct task_struct *task, return task_css_check(task, subsys_id, false); } +/** + * task_css_is_root - test whether a task belongs to the root css + * @task: the target task + * @subsys_id: the target subsystem ID + * + * Test whether @task belongs to the root css on the specified subsystem. + * May be invoked in any context. + */ +static inline bool task_css_is_root(struct task_struct *task, int subsys_id) +{ + return task_css_check(task, subsys_id, true) == + init_css_set.subsys[subsys_id]; +} + static inline struct cgroup *task_cgroup(struct task_struct *task, int subsys_id) { diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 11a03d67635a..3f1ca934a237 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -348,7 +348,7 @@ struct cgrp_cset_link { * reference-counted, to improve performance when child cgroups * haven't been created. */ -static struct css_set init_css_set = { +struct css_set init_css_set = { .refcount = ATOMIC_INIT(1), .cgrp_links = LIST_HEAD_INIT(init_css_set.cgrp_links), .tasks = LIST_HEAD_INIT(init_css_set.tasks), -- cgit v1.2.3 From e5ced8ebb10c20a3b349bd798b69ccabd3b25d21 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 7 May 2014 21:31:17 -0400 Subject: cgroup_freezer: replace freezer->lock with freezer_mutex After 96d365e0b86e ("cgroup: make css_set_lock a rwsem and rename it to css_set_rwsem"), css task iterators requires sleepable context as it may block on css_set_rwsem. I missed that cgroup_freezer was iterating tasks under IRQ-safe spinlock freezer->lock. This leads to errors like the following on freezer state reads and transitions. BUG: sleeping function called from invalid context at /work /os/work/kernel/locking/rwsem.c:20 in_atomic(): 0, irqs_disabled(): 0, pid: 462, name: bash 5 locks held by bash/462: #0: (sb_writers#7){.+.+.+}, at: [] vfs_write+0x1a3/0x1c0 #1: (&of->mutex){+.+.+.}, at: [] kernfs_fop_write+0xbb/0x170 #2: (s_active#70){.+.+.+}, at: [] kernfs_fop_write+0xc3/0x170 #3: (freezer_mutex){+.+...}, at: [] freezer_write+0x61/0x1e0 #4: (rcu_read_lock){......}, at: [] freezer_write+0x53/0x1e0 Preemption disabled at:[] console_unlock+0x1e4/0x460 CPU: 3 PID: 462 Comm: bash Not tainted 3.15.0-rc1-work+ #10 Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011 ffff88000916a6d0 ffff88000e0a3da0 ffffffff81cf8c96 0000000000000000 ffff88000e0a3dc8 ffffffff810cf4f2 ffffffff82388040 ffff880013aaf740 0000000000000002 ffff88000e0a3de8 ffffffff81d05974 0000000000000246 Call Trace: [] dump_stack+0x4e/0x7a [] __might_sleep+0x162/0x260 [] down_read+0x24/0x60 [] css_task_iter_start+0x27/0x70 [] freezer_apply_state+0x5d/0x130 [] freezer_write+0xf6/0x1e0 [] cgroup_file_write+0xd8/0x230 [] kernfs_fop_write+0xe7/0x170 [] vfs_write+0xb6/0x1c0 [] SyS_write+0x4d/0xc0 [] system_call_fastpath+0x16/0x1b freezer->lock used to be used in hot paths but that time is long gone and there's no reason for the lock to be IRQ-safe spinlock or even per-cgroup. In fact, given the fact that a cgroup may contain large number of tasks, it's not a good idea to iterate over them while holding IRQ-safe spinlock. Let's simplify locking by replacing per-cgroup freezer->lock with global freezer_mutex. This also makes the comments explaining the intricacies of policy inheritance and the locking around it as the states are protected by a common mutex. The conversion is mostly straight-forward. The followings are worth mentioning. * freezer_css_online() no longer needs double locking. * freezer_attach() now performs propagation simply while holding freezer_mutex. update_if_frozen() race no longer exists and the comment is removed. * freezer_fork() now tests whether the task is in root cgroup using the new task_css_is_root() without doing rcu_read_lock/unlock(). If not, it grabs freezer_mutex and performs the operation. * freezer_read() and freezer_change_state() grab freezer_mutex across the whole operation and pin the css while iterating so that each descendant processing happens in sleepable context. Fixes: 96d365e0b86e ("cgroup: make css_set_lock a rwsem and rename it to css_set_rwsem") Signed-off-by: Tejun Heo Acked-by: Li Zefan --- kernel/cgroup_freezer.c | 112 ++++++++++++++++++++---------------------------- 1 file changed, 46 insertions(+), 66 deletions(-) diff --git a/kernel/cgroup_freezer.c b/kernel/cgroup_freezer.c index 2bc4a2256444..12ead0b766ee 100644 --- a/kernel/cgroup_freezer.c +++ b/kernel/cgroup_freezer.c @@ -21,6 +21,7 @@ #include #include #include +#include /* * A cgroup is freezing if any FREEZING flags are set. FREEZING_SELF is @@ -42,9 +43,10 @@ enum freezer_state_flags { struct freezer { struct cgroup_subsys_state css; unsigned int state; - spinlock_t lock; }; +static DEFINE_MUTEX(freezer_mutex); + static inline struct freezer *css_freezer(struct cgroup_subsys_state *css) { return css ? container_of(css, struct freezer, css) : NULL; @@ -93,7 +95,6 @@ freezer_css_alloc(struct cgroup_subsys_state *parent_css) if (!freezer) return ERR_PTR(-ENOMEM); - spin_lock_init(&freezer->lock); return &freezer->css; } @@ -110,14 +111,7 @@ static int freezer_css_online(struct cgroup_subsys_state *css) struct freezer *freezer = css_freezer(css); struct freezer *parent = parent_freezer(freezer); - /* - * The following double locking and freezing state inheritance - * guarantee that @cgroup can never escape ancestors' freezing - * states. See css_for_each_descendant_pre() for details. - */ - if (parent) - spin_lock_irq(&parent->lock); - spin_lock_nested(&freezer->lock, SINGLE_DEPTH_NESTING); + mutex_lock(&freezer_mutex); freezer->state |= CGROUP_FREEZER_ONLINE; @@ -126,10 +120,7 @@ static int freezer_css_online(struct cgroup_subsys_state *css) atomic_inc(&system_freezing_cnt); } - spin_unlock(&freezer->lock); - if (parent) - spin_unlock_irq(&parent->lock); - + mutex_unlock(&freezer_mutex); return 0; } @@ -144,14 +135,14 @@ static void freezer_css_offline(struct cgroup_subsys_state *css) { struct freezer *freezer = css_freezer(css); - spin_lock_irq(&freezer->lock); + mutex_lock(&freezer_mutex); if (freezer->state & CGROUP_FREEZING) atomic_dec(&system_freezing_cnt); freezer->state = 0; - spin_unlock_irq(&freezer->lock); + mutex_unlock(&freezer_mutex); } static void freezer_css_free(struct cgroup_subsys_state *css) @@ -175,7 +166,7 @@ static void freezer_attach(struct cgroup_subsys_state *new_css, struct task_struct *task; bool clear_frozen = false; - spin_lock_irq(&freezer->lock); + mutex_lock(&freezer_mutex); /* * Make the new tasks conform to the current state of @new_css. @@ -197,21 +188,13 @@ static void freezer_attach(struct cgroup_subsys_state *new_css, } } - spin_unlock_irq(&freezer->lock); - - /* - * Propagate FROZEN clearing upwards. We may race with - * update_if_frozen(), but as long as both work bottom-up, either - * update_if_frozen() sees child's FROZEN cleared or we clear the - * parent's FROZEN later. No parent w/ !FROZEN children can be - * left FROZEN. - */ + /* propagate FROZEN clearing upwards */ while (clear_frozen && (freezer = parent_freezer(freezer))) { - spin_lock_irq(&freezer->lock); freezer->state &= ~CGROUP_FROZEN; clear_frozen = freezer->state & CGROUP_FREEZING; - spin_unlock_irq(&freezer->lock); } + + mutex_unlock(&freezer_mutex); } /** @@ -228,9 +211,6 @@ static void freezer_fork(struct task_struct *task) { struct freezer *freezer; - rcu_read_lock(); - freezer = task_freezer(task); - /* * The root cgroup is non-freezable, so we can skip locking the * freezer. This is safe regardless of race with task migration. @@ -238,24 +218,18 @@ static void freezer_fork(struct task_struct *task) * to do. If we lost and root is the new cgroup, noop is still the * right thing to do. */ - if (!parent_freezer(freezer)) - goto out; + if (task_css_is_root(task, freezer_cgrp_id)) + return; - /* - * Grab @freezer->lock and freeze @task after verifying @task still - * belongs to @freezer and it's freezing. The former is for the - * case where we have raced against task migration and lost and - * @task is already in a different cgroup which may not be frozen. - * This isn't strictly necessary as freeze_task() is allowed to be - * called spuriously but let's do it anyway for, if nothing else, - * documentation. - */ - spin_lock_irq(&freezer->lock); - if (freezer == task_freezer(task) && (freezer->state & CGROUP_FREEZING)) + mutex_lock(&freezer_mutex); + rcu_read_lock(); + + freezer = task_freezer(task); + if (freezer->state & CGROUP_FREEZING) freeze_task(task); - spin_unlock_irq(&freezer->lock); -out: + rcu_read_unlock(); + mutex_unlock(&freezer_mutex); } /** @@ -281,22 +255,22 @@ static void update_if_frozen(struct cgroup_subsys_state *css) struct css_task_iter it; struct task_struct *task; - WARN_ON_ONCE(!rcu_read_lock_held()); - - spin_lock_irq(&freezer->lock); + lockdep_assert_held(&freezer_mutex); if (!(freezer->state & CGROUP_FREEZING) || (freezer->state & CGROUP_FROZEN)) - goto out_unlock; + return; /* are all (live) children frozen? */ + rcu_read_lock(); css_for_each_child(pos, css) { struct freezer *child = css_freezer(pos); if ((child->state & CGROUP_FREEZER_ONLINE) && !(child->state & CGROUP_FROZEN)) - goto out_unlock; + return; } + rcu_read_unlock(); /* are all tasks frozen? */ css_task_iter_start(css, &it); @@ -317,21 +291,29 @@ static void update_if_frozen(struct cgroup_subsys_state *css) freezer->state |= CGROUP_FROZEN; out_iter_end: css_task_iter_end(&it); -out_unlock: - spin_unlock_irq(&freezer->lock); } static int freezer_read(struct seq_file *m, void *v) { struct cgroup_subsys_state *css = seq_css(m), *pos; + mutex_lock(&freezer_mutex); rcu_read_lock(); /* update states bottom-up */ - css_for_each_descendant_post(pos, css) + css_for_each_descendant_post(pos, css) { + if (!css_tryget(pos)) + continue; + rcu_read_unlock(); + update_if_frozen(pos); + rcu_read_lock(); + css_put(pos); + } + rcu_read_unlock(); + mutex_unlock(&freezer_mutex); seq_puts(m, freezer_state_strs(css_freezer(css)->state)); seq_putc(m, '\n'); @@ -373,7 +355,7 @@ static void freezer_apply_state(struct freezer *freezer, bool freeze, unsigned int state) { /* also synchronizes against task migration, see freezer_attach() */ - lockdep_assert_held(&freezer->lock); + lockdep_assert_held(&freezer_mutex); if (!(freezer->state & CGROUP_FREEZER_ONLINE)) return; @@ -414,31 +396,29 @@ static void freezer_change_state(struct freezer *freezer, bool freeze) * descendant will try to inherit its parent's FREEZING state as * CGROUP_FREEZING_PARENT. */ + mutex_lock(&freezer_mutex); rcu_read_lock(); css_for_each_descendant_pre(pos, &freezer->css) { struct freezer *pos_f = css_freezer(pos); struct freezer *parent = parent_freezer(pos_f); - spin_lock_irq(&pos_f->lock); + if (!css_tryget(pos)) + continue; + rcu_read_unlock(); - if (pos_f == freezer) { + if (pos_f == freezer) freezer_apply_state(pos_f, freeze, CGROUP_FREEZING_SELF); - } else { - /* - * Our update to @parent->state is already visible - * which is all we need. No need to lock @parent. - * For more info on synchronization, see - * freezer_post_create(). - */ + else freezer_apply_state(pos_f, parent->state & CGROUP_FREEZING, CGROUP_FREEZING_PARENT); - } - spin_unlock_irq(&pos_f->lock); + rcu_read_lock(); + css_put(pos); } rcu_read_unlock(); + mutex_unlock(&freezer_mutex); } static int freezer_write(struct cgroup_subsys_state *css, struct cftype *cft, -- cgit v1.2.3 From 36e9d2ebcc15d029b33f42a36146ab5a5bcfcfe7 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 13 May 2014 11:28:30 -0400 Subject: cgroup: fix rcu_read_lock() leak in update_if_frozen() While updating cgroup_freezer locking, 68fafb77d827 ("cgroup_freezer: replace freezer->lock with freezer_mutex") introduced a bug in update_if_frozen() where it returns with rcu_read_lock() held. Fix it by adding rcu_read_unlock() before returning. Signed-off-by: Tejun Heo Reported-by: kbuild test robot --- kernel/cgroup_freezer.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/kernel/cgroup_freezer.c b/kernel/cgroup_freezer.c index 12ead0b766ee..345628c78b5b 100644 --- a/kernel/cgroup_freezer.c +++ b/kernel/cgroup_freezer.c @@ -267,8 +267,10 @@ static void update_if_frozen(struct cgroup_subsys_state *css) struct freezer *child = css_freezer(pos); if ((child->state & CGROUP_FREEZER_ONLINE) && - !(child->state & CGROUP_FROZEN)) + !(child->state & CGROUP_FROZEN)) { + rcu_read_unlock(); return; + } } rcu_read_unlock(); -- cgit v1.2.3 From d40a63c45b506b0681918d7c62a15cc9d48c8681 Mon Sep 17 00:00:00 2001 From: Dirk Brandewie Date: Thu, 8 May 2014 12:57:24 -0700 Subject: intel_pstate: remove setting P state to MAX on init Setting the P state of the core to max at init time is a hold over from early implementation of intel_pstate where intel_pstate disabled cpufreq and loaded VERY early in the boot sequence. This was to ensure that intel_pstate did not affect boot time. This in not needed now that intel_pstate is a cpufreq driver. Removing this covers the case where a CPU has gone through a manual CPU offline/online cycle and the P state is set to MAX on init and the CPU immediately goes idle. Due to HW coordination the P state request on the idle CPU will drag all cores to MAX P state until the load is reevaluated when to core goes non-idle. Reported-by: Patrick Marlier Signed-off-by: Dirk Brandewie Cc: 3.14+ # 3.14+ Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/intel_pstate.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 39c4f8520848..eab8ccfe6beb 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -554,12 +554,7 @@ static void intel_pstate_get_cpu_pstates(struct cpudata *cpu) if (pstate_funcs.get_vid) pstate_funcs.get_vid(cpu); - - /* - * goto max pstate so we don't slow up boot if we are built-in if we are - * a module we will take care of it during normal operation - */ - intel_pstate_set_pstate(cpu, cpu->pstate.max_pstate); + intel_pstate_set_pstate(cpu, cpu->pstate.min_pstate); } static inline void intel_pstate_calc_busy(struct cpudata *cpu, @@ -704,11 +699,6 @@ static int intel_pstate_init_cpu(unsigned int cpunum) cpu = all_cpu_data[cpunum]; intel_pstate_get_cpu_pstates(cpu); - if (!cpu->pstate.current_pstate) { - all_cpu_data[cpunum] = NULL; - kfree(cpu); - return -ENODATA; - } cpu->cpu = cpunum; @@ -719,7 +709,6 @@ static int intel_pstate_init_cpu(unsigned int cpunum) cpu->timer.expires = jiffies + HZ/100; intel_pstate_busy_pid_reset(cpu); intel_pstate_sample(cpu); - intel_pstate_set_pstate(cpu, cpu->pstate.max_pstate); add_timer_on(&cpu->timer, cpunum); -- cgit v1.2.3 From 367f0b50e502d2c384277ba2ed43b04add2b8b6f Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 13 May 2014 17:56:41 +0200 Subject: MIPS: Wire up renameat2 syscall. Signed-off-by: Ralf Baechle --- arch/mips/include/uapi/asm/unistd.h | 9 ++++++--- arch/mips/kernel/scall32-o32.S | 1 + arch/mips/kernel/scall64-64.S | 1 + arch/mips/kernel/scall64-n32.S | 1 + arch/mips/kernel/scall64-o32.S | 1 + 5 files changed, 10 insertions(+), 3 deletions(-) diff --git a/arch/mips/include/uapi/asm/unistd.h b/arch/mips/include/uapi/asm/unistd.h index d6e154a9e6a5..2692abb28e36 100644 --- a/arch/mips/include/uapi/asm/unistd.h +++ b/arch/mips/include/uapi/asm/unistd.h @@ -371,11 +371,12 @@ #define __NR_finit_module (__NR_Linux + 348) #define __NR_sched_setattr (__NR_Linux + 349) #define __NR_sched_getattr (__NR_Linux + 350) +#define __NR_renameat2 (__NR_Linux + 351) /* * Offset of the last Linux o32 flavoured syscall */ -#define __NR_Linux_syscalls 350 +#define __NR_Linux_syscalls 351 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */ @@ -699,11 +700,12 @@ #define __NR_getdents64 (__NR_Linux + 308) #define __NR_sched_setattr (__NR_Linux + 309) #define __NR_sched_getattr (__NR_Linux + 310) +#define __NR_renameat2 (__NR_Linux + 311) /* * Offset of the last Linux 64-bit flavoured syscall */ -#define __NR_Linux_syscalls 310 +#define __NR_Linux_syscalls 311 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */ @@ -1031,11 +1033,12 @@ #define __NR_finit_module (__NR_Linux + 312) #define __NR_sched_setattr (__NR_Linux + 313) #define __NR_sched_getattr (__NR_Linux + 314) +#define __NR_renameat2 (__NR_Linux + 315) /* * Offset of the last N32 flavoured syscall */ -#define __NR_Linux_syscalls 314 +#define __NR_Linux_syscalls 315 #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */ diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S index fdc70b400442..3245474f19d5 100644 --- a/arch/mips/kernel/scall32-o32.S +++ b/arch/mips/kernel/scall32-o32.S @@ -577,3 +577,4 @@ EXPORT(sys_call_table) PTR sys_finit_module PTR sys_sched_setattr PTR sys_sched_getattr /* 4350 */ + PTR sys_renameat2 diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S index dd99c3285aea..be2fedd4ae33 100644 --- a/arch/mips/kernel/scall64-64.S +++ b/arch/mips/kernel/scall64-64.S @@ -430,4 +430,5 @@ EXPORT(sys_call_table) PTR sys_getdents64 PTR sys_sched_setattr PTR sys_sched_getattr /* 5310 */ + PTR sys_renameat2 .size sys_call_table,.-sys_call_table diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S index f68d2f4f0090..c1dbcda4b816 100644 --- a/arch/mips/kernel/scall64-n32.S +++ b/arch/mips/kernel/scall64-n32.S @@ -423,4 +423,5 @@ EXPORT(sysn32_call_table) PTR sys_finit_module PTR sys_sched_setattr PTR sys_sched_getattr + PTR sys_renameat2 /* 6315 */ .size sysn32_call_table,.-sysn32_call_table diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S index 70f6acecd928..f1343ccd7ed7 100644 --- a/arch/mips/kernel/scall64-o32.S +++ b/arch/mips/kernel/scall64-o32.S @@ -556,4 +556,5 @@ EXPORT(sys32_call_table) PTR sys_finit_module PTR sys_sched_setattr PTR sys_sched_getattr /* 4350 */ + PTR sys_renameat2 .size sys32_call_table,.-sys32_call_table -- cgit v1.2.3 From 2176d5d41891753774f648b67470398a5acab584 Mon Sep 17 00:00:00 2001 From: Duan Jiong Date: Fri, 9 May 2014 13:16:48 +0800 Subject: neigh: set nud_state to NUD_INCOMPLETE when probing router reachability Since commit 7e98056964("ipv6: router reachability probing"), a router falls into NUD_FAILED will be probed. Now if function rt6_select() selects a router which neighbour state is NUD_FAILED, and at the same time function rt6_probe() changes the neighbour state to NUD_PROBE, then function dst_neigh_output() can directly send packets, but actually the neighbour still is unreachable. If we set nud_state to NUD_INCOMPLETE instead NUD_PROBE, packets will not be sent out until the neihbour is reachable. In addition, because the route should be probes with a single NS, so we must set neigh->probes to neigh_max_probes(), then the neigh timer timeout and function neigh_timer_handler() will not send other NS Messages. Signed-off-by: Duan Jiong Signed-off-by: David S. Miller --- net/core/neighbour.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 8f8a96ef9f3f..32d872eec7f5 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -1248,8 +1248,8 @@ void __neigh_set_probe_once(struct neighbour *neigh) neigh->updated = jiffies; if (!(neigh->nud_state & NUD_FAILED)) return; - neigh->nud_state = NUD_PROBE; - atomic_set(&neigh->probes, NEIGH_VAR(neigh->parms, UCAST_PROBES)); + neigh->nud_state = NUD_INCOMPLETE; + atomic_set(&neigh->probes, neigh_max_probes(neigh)); neigh_add_timer(neigh, jiffies + NEIGH_VAR(neigh->parms, RETRANS_TIME)); } -- cgit v1.2.3 From cffd6665f57ed18f4be9185c4330c8c98c22e201 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Tue, 13 May 2014 15:46:06 +0300 Subject: ASoC: Intel: Fix Baytrail SST DSP firmware loading Commit 10df350977b1 ("ASoC: Intel: Fix Audio DSP usage when IOMMU is enabled.") caused following regression in Baytrail SST: baytrail-pcm-audio baytrail-pcm-audio: error: DMA alloc failed baytrail-pcm-audio baytrail-pcm-audio: error: failed to load firmware Fix this by calling dma_coerce_mask_and_coherent() in sst_byt_init() with the same dma_dev device what is now used in sst_fw_new() when allocating the DMA buffer. Signed-off-by: Jarkko Nikula Signed-off-by: Mark Brown --- sound/soc/intel/sst-baytrail-dsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/sst-baytrail-dsp.c b/sound/soc/intel/sst-baytrail-dsp.c index a50bf7fc0e3a..adf0aca5aca6 100644 --- a/sound/soc/intel/sst-baytrail-dsp.c +++ b/sound/soc/intel/sst-baytrail-dsp.c @@ -324,7 +324,7 @@ static int sst_byt_init(struct sst_dsp *sst, struct sst_pdata *pdata) memcpy_toio(sst->addr.lpe + SST_BYT_MAILBOX_OFFSET, &pdata->fw_base, sizeof(u32)); - ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32)); + ret = dma_coerce_mask_and_coherent(sst->dma_dev, DMA_BIT_MASK(32)); if (ret) return ret; -- cgit v1.2.3 From 44330ab516c15dda8a1e660eeaf0003f84e43e3f Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 13 May 2014 13:45:15 +0100 Subject: ASoC: wm8962: Update register CLASS_D_CONTROL_1 to be non-volatile The register CLASS_D_CONTROL_1 is marked as volatile because it contains a bit, DAC_MUTE, which is also mirrored in the ADC_DAC_CONTROL_1 register. This causes problems for the "Speaker Switch" control, which will report an error if the CODEC is suspended because it relies on a volatile register. To resolve this issue mark CLASS_D_CONTROL_1 as non-volatile and manually keep the register cache in sync by updating both bits when changing the mute status. Reported-by: Shawn Guo Signed-off-by: Charles Keepax Tested-by: Shawn Guo Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- sound/soc/codecs/wm8962.c | 15 ++++++++++++--- sound/soc/codecs/wm8962.h | 4 ++++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 5522d2566c67..ecd26dd2e442 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -154,6 +154,7 @@ static struct reg_default wm8962_reg[] = { { 40, 0x0000 }, /* R40 - SPKOUTL volume */ { 41, 0x0000 }, /* R41 - SPKOUTR volume */ + { 49, 0x0010 }, /* R49 - Class D Control 1 */ { 51, 0x0003 }, /* R51 - Class D Control 2 */ { 56, 0x0506 }, /* R56 - Clocking 4 */ @@ -795,7 +796,6 @@ static bool wm8962_volatile_register(struct device *dev, unsigned int reg) case WM8962_ALC2: case WM8962_THERMAL_SHUTDOWN_STATUS: case WM8962_ADDITIONAL_CONTROL_4: - case WM8962_CLASS_D_CONTROL_1: case WM8962_DC_SERVO_6: case WM8962_INTERRUPT_STATUS_1: case WM8962_INTERRUPT_STATUS_2: @@ -2929,13 +2929,22 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source, static int wm8962_mute(struct snd_soc_dai *dai, int mute) { struct snd_soc_codec *codec = dai->codec; - int val; + int val, ret; if (mute) - val = WM8962_DAC_MUTE; + val = WM8962_DAC_MUTE | WM8962_DAC_MUTE_ALT; else val = 0; + /** + * The DAC mute bit is mirrored in two registers, update both to keep + * the register cache consistent. + */ + ret = snd_soc_update_bits(codec, WM8962_CLASS_D_CONTROL_1, + WM8962_DAC_MUTE_ALT, val); + if (ret < 0) + return ret; + return snd_soc_update_bits(codec, WM8962_ADC_DAC_CONTROL_1, WM8962_DAC_MUTE, val); } diff --git a/sound/soc/codecs/wm8962.h b/sound/soc/codecs/wm8962.h index a1a5d5294c19..910aafd09d21 100644 --- a/sound/soc/codecs/wm8962.h +++ b/sound/soc/codecs/wm8962.h @@ -1954,6 +1954,10 @@ #define WM8962_SPKOUTL_ENA_MASK 0x0040 /* SPKOUTL_ENA */ #define WM8962_SPKOUTL_ENA_SHIFT 6 /* SPKOUTL_ENA */ #define WM8962_SPKOUTL_ENA_WIDTH 1 /* SPKOUTL_ENA */ +#define WM8962_DAC_MUTE_ALT 0x0010 /* DAC_MUTE */ +#define WM8962_DAC_MUTE_ALT_MASK 0x0010 /* DAC_MUTE */ +#define WM8962_DAC_MUTE_ALT_SHIFT 4 /* DAC_MUTE */ +#define WM8962_DAC_MUTE_ALT_WIDTH 1 /* DAC_MUTE */ #define WM8962_SPKOUTL_PGA_MUTE 0x0002 /* SPKOUTL_PGA_MUTE */ #define WM8962_SPKOUTL_PGA_MUTE_MASK 0x0002 /* SPKOUTL_PGA_MUTE */ #define WM8962_SPKOUTL_PGA_MUTE_SHIFT 1 /* SPKOUTL_PGA_MUTE */ -- cgit v1.2.3 From 629c27aa0c930b9c67188cfc625bf6cdd2af6764 Mon Sep 17 00:00:00 2001 From: Vikas Chaudhary Date: Tue, 13 May 2014 07:41:32 -0400 Subject: iscsi_ibft: Fix finding Broadcom specific ibft sign MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Search for Broadcom specific ibft sign "BIFT" along with other possible values on UEFI This patch is fix for regression introduced in “935a9fee51c945b8942be2d7b4bae069167b4886”. https://lkml.org/lkml/2011/12/16/353 This impacts Broadcom CNA for iSCSI Boot on UEFI platform. Signed-off-by: Vikas Chaudhary Signed-off-by: Konrad Rzeszutek Wilk Acked-by: Mike Christie --- drivers/firmware/iscsi_ibft.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/firmware/iscsi_ibft.c b/drivers/firmware/iscsi_ibft.c index 3ee852c9925b..071c2c969eec 100644 --- a/drivers/firmware/iscsi_ibft.c +++ b/drivers/firmware/iscsi_ibft.c @@ -756,6 +756,7 @@ static const struct { */ { ACPI_SIG_IBFT }, { "iBFT" }, + { "BIFT" }, /* Broadcom iSCSI Offload */ }; static void __init acpi_find_ibft_region(void) -- cgit v1.2.3 From 2ed9fd28c2884e9f41c133f86a7e377d7c0a96bf Mon Sep 17 00:00:00 2001 From: Jason Cooper Date: Tue, 13 May 2014 18:47:01 +0000 Subject: MAINTAINERS: Add co-maintainer for drivers/irqchip Thomas Gleixner has asked me to assist with the review and merging of patches for the irqchip subsystem. Signed-off-by: Jason Cooper Link: http://lkml.kernel.org/r/1400006821-32145-1-git-send-email-jason@lakedaemon.net Signed-off-by: Thomas Gleixner --- MAINTAINERS | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 6bef70b614c9..4195801270e2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4818,6 +4818,14 @@ L: linux-kernel@vger.kernel.org S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git irq/core F: kernel/irq/ + +IRQCHIP DRIVERS +M: Thomas Gleixner +M: Jason Cooper +L: linux-kernel@vger.kernel.org +S: Maintained +T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git irq/core +T: git git://git.infradead.org/users/jcooper/linux.git irqchip/core F: drivers/irqchip/ IRQ DOMAINS (IRQ NUMBER MAPPING LIBRARY) -- cgit v1.2.3 From 773cd38f40b8834be991dbfed36683acc1dd41ee Mon Sep 17 00:00:00 2001 From: Alexei Starovoitov Date: Tue, 13 May 2014 15:05:55 -0700 Subject: net: filter: x86: fix JIT address randomization bpf_alloc_binary() adds 128 bytes of room to JITed program image and rounds it up to the nearest page size. If image size is close to page size (like 4000), it is rounded to two pages: round_up(4000 + 4 + 128) == 8192 then 'hole' is computed as 8192 - (4000 + 4) = 4188 If prandom_u32() % hole selects a number >= PAGE_SIZE - sizeof(*header) then kernel will crash during bpf_jit_free(): kernel BUG at arch/x86/mm/pageattr.c:887! Call Trace: [] change_page_attr_set_clr+0x135/0x460 [] ? _raw_spin_unlock_irq+0x30/0x50 [] set_memory_rw+0x2f/0x40 [] bpf_jit_free_deferred+0x2d/0x60 [] process_one_work+0x1d8/0x6a0 [] ? process_one_work+0x178/0x6a0 [] worker_thread+0x11c/0x370 since bpf_jit_free() does: unsigned long addr = (unsigned long)fp->bpf_func & PAGE_MASK; struct bpf_binary_header *header = (void *)addr; to compute start address of 'bpf_binary_header' and header->pages will pass junk to: set_memory_rw(addr, header->pages); Fix it by making sure that &header->image[prandom_u32() % hole] and &header are in the same page Fixes: 314beb9bcabfd ("x86: bpf_jit_comp: secure bpf jit against spraying attacks") Signed-off-by: Alexei Starovoitov Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- arch/x86/net/bpf_jit_comp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c index dc017735bb91..6d5663a599a7 100644 --- a/arch/x86/net/bpf_jit_comp.c +++ b/arch/x86/net/bpf_jit_comp.c @@ -171,7 +171,7 @@ static struct bpf_binary_header *bpf_alloc_binary(unsigned int proglen, memset(header, 0xcc, sz); /* fill whole space with int3 instructions */ header->pages = sz / PAGE_SIZE; - hole = sz - (proglen + sizeof(*header)); + hole = min(sz - (proglen + sizeof(*header)), PAGE_SIZE - sizeof(*header)); /* insert a random number of int3 instructions before BPF code */ *image_ptr = &header->image[prandom_u32() % hole]; -- cgit v1.2.3 From cfece5857ca51d1dcdb157017aba226f594e9dcf Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 14 Apr 2014 10:49:34 -0300 Subject: [media] V4L2: ov7670: fix a wrong index, potentially Oopsing the kernel from user-space Commit 75e2bdad8901a0b599e01a96229be922eef1e488 "ov7670: allow configuration of image size, clock speed, and I/O method" uses a wrong index to iterate an array. Apart from being wrong, it also uses an unchecked value from user-space, which can cause access to unmapped memory in the kernel, triggered by a normal desktop user with rights to use V4L2 devices. Signed-off-by: Guennadi Liakhovetski Acked-by: Jonathan Corbet Cc: stable@vger.kernel.org Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ov7670.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/i2c/ov7670.c b/drivers/media/i2c/ov7670.c index e8a1ce204036..cdd7c1b7259b 100644 --- a/drivers/media/i2c/ov7670.c +++ b/drivers/media/i2c/ov7670.c @@ -1109,7 +1109,7 @@ static int ov7670_enum_framesizes(struct v4l2_subdev *sd, * windows that fall outside that. */ for (i = 0; i < n_win_sizes; i++) { - struct ov7670_win_size *win = &info->devtype->win_sizes[index]; + struct ov7670_win_size *win = &info->devtype->win_sizes[i]; if (info->min_width && win->width < info->min_width) continue; if (info->min_height && win->height < info->min_height) -- cgit v1.2.3 From 97d9d23dda6f37d90aefeec4ed619d52df525382 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Sat, 26 Apr 2014 12:51:31 -0300 Subject: [media] V4L2: fix VIDIOC_CREATE_BUFS in 64- / 32-bit compatibility mode If a struct contains 64-bit fields, it is aligned on 64-bit boundaries within containing structs in 64-bit compilations. This is the case with struct v4l2_window, which contains pointers and is embedded into struct v4l2_format, and that one is embedded into struct v4l2_create_buffers. Unlike some other structs, used as a part of the kernel ABI as ioctl() arguments, that are packed, these structs aren't packed. This isn't a problem per se, but the ioctl-compat code for VIDIOC_CREATE_BUFS contains a bug, that triggers in such 64-bit builds. That code wrongly assumes, that in struct v4l2_create_buffers, struct v4l2_format immediately follows the __u32 memory field, which in fact isn't the case. This bug wasn't visible until now, because until recently hardly any applications used this ioctl() and mostly embedded 32-bit only drivers implemented it. This is changing now with addition of this ioctl() to some USB drivers, e.g. UVC. This patch fixes the bug by copying parts of struct v4l2_create_buffers separately. Signed-off-by: Guennadi Liakhovetski Acked-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab Cc: stable@vger.kernel.org --- drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c index 04b2daf567be..7e2411c36419 100644 --- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c @@ -178,6 +178,9 @@ struct v4l2_create_buffers32 { static int __get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up) { + if (get_user(kp->type, &up->type)) + return -EFAULT; + switch (kp->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: case V4L2_BUF_TYPE_VIDEO_OUTPUT: @@ -204,17 +207,16 @@ static int __get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __us static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up) { - if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_format32)) || - get_user(kp->type, &up->type)) - return -EFAULT; + if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_format32))) + return -EFAULT; return __get_v4l2_format32(kp, up); } static int get_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up) { if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_create_buffers32)) || - copy_from_user(kp, up, offsetof(struct v4l2_create_buffers32, format.fmt))) - return -EFAULT; + copy_from_user(kp, up, offsetof(struct v4l2_create_buffers32, format))) + return -EFAULT; return __get_v4l2_format32(&kp->format, &up->format); } -- cgit v1.2.3 From 9844f5462392b53824e8b86726e7c33b5ecbb676 Mon Sep 17 00:00:00 2001 From: Anthony Iliopoulos Date: Wed, 14 May 2014 11:29:48 +0200 Subject: x86, mm, hugetlb: Add missing TLB page invalidation for hugetlb_cow() The invalidation is required in order to maintain proper semantics under CoW conditions. In scenarios where a process clones several threads, a thread operating on a core whose DTLB entry for a particular hugepage has not been invalidated, will be reading from the hugepage that belongs to the forked child process, even after hugetlb_cow(). The thread will not see the updated page as long as the stale DTLB entry remains cached, the thread attempts to write into the page, the child process exits, or the thread gets migrated to a different processor. Signed-off-by: Anthony Iliopoulos Link: http://lkml.kernel.org/r/20140514092948.GA17391@server-36.huawei.corp Suggested-by: Shay Goikhman Acked-by: Dave Hansen Signed-off-by: H. Peter Anvin Cc: # v2.6.16+ (!) --- arch/x86/include/asm/hugetlb.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/include/asm/hugetlb.h b/arch/x86/include/asm/hugetlb.h index a8091216963b..68c05398bba9 100644 --- a/arch/x86/include/asm/hugetlb.h +++ b/arch/x86/include/asm/hugetlb.h @@ -52,6 +52,7 @@ static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm, static inline void huge_ptep_clear_flush(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep) { + ptep_clear_flush(vma, addr, ptep); } static inline int huge_pte_none(pte_t pte) -- cgit v1.2.3 From f2d0801f00b7aff0ac6b3666cbcdab499267418a Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Tue, 22 Apr 2014 15:40:36 +0100 Subject: MIPS: Add new AUDIT_ARCH token for the N32 ABI on MIPS64 A MIPS64 kernel may support ELF files for all 3 MIPS ABIs (O32, N32, N64). Furthermore, the AUDIT_ARCH_MIPS{,EL}64 token does not provide enough information about the ABI for the 64-bit process. As a result of which, userland needs to use complex seccomp filters to decide whether a syscall belongs to the o32 or n32 or n64 ABI. Therefore, a new arch token for MIPS64/n32 is added so it can be used by seccomp to explicitely set syscall filters for this ABI. Signed-off-by: Markos Chandras Acked-by: Eric Paris Acked-by: Paul Moore Cc: Andy Lutomirski Cc: Ralf Baechle Cc: Andy Lutomirski Cc: linux-mips@linux-mips.org Link: http://sourceforge.net/p/libseccomp/mailman/message/32239040/ Patchwork: https://patchwork.linux-mips.org/patch/6818/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/syscall.h | 2 ++ include/uapi/linux/audit.h | 12 ++++++++++++ 2 files changed, 14 insertions(+) diff --git a/arch/mips/include/asm/syscall.h b/arch/mips/include/asm/syscall.h index c6e9cd2bca8d..17960fe7a8ce 100644 --- a/arch/mips/include/asm/syscall.h +++ b/arch/mips/include/asm/syscall.h @@ -133,6 +133,8 @@ static inline int syscall_get_arch(void) #ifdef CONFIG_64BIT if (!test_thread_flag(TIF_32BIT_REGS)) arch |= __AUDIT_ARCH_64BIT; + if (test_thread_flag(TIF_32BIT_ADDR)) + arch |= __AUDIT_ARCH_CONVENTION_MIPS64_N32; #endif #if defined(__LITTLE_ENDIAN) arch |= __AUDIT_ARCH_LE; diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index 11917f747cb4..1b1efddb91cd 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h @@ -331,9 +331,17 @@ enum { #define AUDIT_FAIL_PRINTK 1 #define AUDIT_FAIL_PANIC 2 +/* + * These bits disambiguate different calling conventions that share an + * ELF machine type, bitness, and endianness + */ +#define __AUDIT_ARCH_CONVENTION_MASK 0x30000000 +#define __AUDIT_ARCH_CONVENTION_MIPS64_N32 0x20000000 + /* distinguish syscall tables */ #define __AUDIT_ARCH_64BIT 0x80000000 #define __AUDIT_ARCH_LE 0x40000000 + #define AUDIT_ARCH_ALPHA (EM_ALPHA|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE) #define AUDIT_ARCH_ARM (EM_ARM|__AUDIT_ARCH_LE) #define AUDIT_ARCH_ARMEB (EM_ARM) @@ -346,7 +354,11 @@ enum { #define AUDIT_ARCH_MIPS (EM_MIPS) #define AUDIT_ARCH_MIPSEL (EM_MIPS|__AUDIT_ARCH_LE) #define AUDIT_ARCH_MIPS64 (EM_MIPS|__AUDIT_ARCH_64BIT) +#define AUDIT_ARCH_MIPS64N32 (EM_MIPS|__AUDIT_ARCH_64BIT|\ + __AUDIT_ARCH_CONVENTION_MIPS64_N32) #define AUDIT_ARCH_MIPSEL64 (EM_MIPS|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE) +#define AUDIT_ARCH_MIPSEL64N32 (EM_MIPS|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE\ + __AUDIT_ARCH_CONVENTION_MIPS64_N32) #define AUDIT_ARCH_OPENRISC (EM_OPENRISC) #define AUDIT_ARCH_PARISC (EM_PARISC) #define AUDIT_ARCH_PARISC64 (EM_PARISC|__AUDIT_ARCH_64BIT) -- cgit v1.2.3 From 3d4405226d27b3a215e4d03cfa51f536244e5de7 Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Sun, 11 May 2014 22:59:30 +0200 Subject: net: avoid dependency of net_get_random_once on nop patching MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit net_get_random_once depends on the static keys infrastructure to patch up the branch to the slow path during boot. This was realized by abusing the static keys api and defining a new initializer to not enable the call site while still indicating that the branch point should get patched up. This was needed to have the fast path considered likely by gcc. The static key initialization during boot up normally walks through all the registered keys and either patches in ideal nops or enables the jump site but omitted that step on x86 if ideal nops where already placed at static_key branch points. Thus net_get_random_once branches not always became active. This patch switches net_get_random_once to the ordinary static_key api and thus places the kernel fast path in the - by gcc considered - unlikely path. Microbenchmarks on Intel and AMD x86-64 showed that the unlikely path actually beats the likely path in terms of cycle cost and that different nop patterns did not make much difference, thus this switch should not be noticeable. Fixes: a48e42920ff38b ("net: introduce new macro net_get_random_once") Reported-by: Tuomas Räsänen Cc: Linus Torvalds Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller --- include/linux/net.h | 15 ++++----------- net/core/utils.c | 8 ++++---- 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/include/linux/net.h b/include/linux/net.h index 94734a6259a4..17d83393afcc 100644 --- a/include/linux/net.h +++ b/include/linux/net.h @@ -248,24 +248,17 @@ do { \ bool __net_get_random_once(void *buf, int nbytes, bool *done, struct static_key *done_key); -#ifdef HAVE_JUMP_LABEL -#define ___NET_RANDOM_STATIC_KEY_INIT ((struct static_key) \ - { .enabled = ATOMIC_INIT(0), .entries = (void *)1 }) -#else /* !HAVE_JUMP_LABEL */ -#define ___NET_RANDOM_STATIC_KEY_INIT STATIC_KEY_INIT_FALSE -#endif /* HAVE_JUMP_LABEL */ - #define net_get_random_once(buf, nbytes) \ ({ \ bool ___ret = false; \ static bool ___done = false; \ - static struct static_key ___done_key = \ - ___NET_RANDOM_STATIC_KEY_INIT; \ - if (!static_key_true(&___done_key)) \ + static struct static_key ___once_key = \ + STATIC_KEY_INIT_TRUE; \ + if (static_key_true(&___once_key)) \ ___ret = __net_get_random_once(buf, \ nbytes, \ &___done, \ - &___done_key); \ + &___once_key); \ ___ret; \ }) diff --git a/net/core/utils.c b/net/core/utils.c index 2f737bf90b3f..eed34338736c 100644 --- a/net/core/utils.c +++ b/net/core/utils.c @@ -348,8 +348,8 @@ static void __net_random_once_deferred(struct work_struct *w) { struct __net_random_once_work *work = container_of(w, struct __net_random_once_work, work); - if (!static_key_enabled(work->key)) - static_key_slow_inc(work->key); + BUG_ON(!static_key_enabled(work->key)); + static_key_slow_dec(work->key); kfree(work); } @@ -367,7 +367,7 @@ static void __net_random_once_disable_jump(struct static_key *key) } bool __net_get_random_once(void *buf, int nbytes, bool *done, - struct static_key *done_key) + struct static_key *once_key) { static DEFINE_SPINLOCK(lock); unsigned long flags; @@ -382,7 +382,7 @@ bool __net_get_random_once(void *buf, int nbytes, bool *done, *done = true; spin_unlock_irqrestore(&lock, flags); - __net_random_once_disable_jump(done_key); + __net_random_once_disable_jump(once_key); return true; } -- cgit v1.2.3 From 3a1cebe7e05027a1c96f2fc1a8eddf5f19b78f42 Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Sun, 11 May 2014 23:01:13 +0200 Subject: ipv6: fix calculation of option len in ip6_append_data tot_len does specify the size of struct ipv6_txoptions. We need opt_flen + opt_nflen to calculate the overall length of additional ipv6 extensions. I found this while auditing the ipv6 output path for a memory corruption reported by Alexey Preobrazhensky while he fuzzed an instrumented AddressSanitizer kernel with trinity. This may or may not be the cause of the original bug. Fixes: 4df98e76cde7c6 ("ipv6: pmtudisc setting not respected with UFO/CORK") Reported-by: Alexey Preobrazhensky Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller --- net/ipv6/ip6_output.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 31a38bde69ef..fbf11562b54c 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -1229,7 +1229,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, unsigned int maxnonfragsize, headersize; headersize = sizeof(struct ipv6hdr) + - (opt ? opt->tot_len : 0) + + (opt ? opt->opt_flen + opt->opt_nflen : 0) + (dst_allfrag(&rt->dst) ? sizeof(struct frag_hdr) : 0) + rt->rt6i_nfheader_len; -- cgit v1.2.3 From c5ec1948eaab7c1c0f412b2804e65a637f1c7443 Mon Sep 17 00:00:00 2001 From: Chao Xie Date: Mon, 12 May 2014 19:20:48 -0700 Subject: Input: pxa27x-keypad - fix generating scancode The number of columns of pxa27x-keypad used by various boards is not fixed. When building keymap with call to: matrix_keypad_build_keymap(keymap_data, NULL, pdata->matrix_key_rows, pdata->matrix_key_cols, keypad->keycodes, input_dev); it will internally calculate needed row shift and use it to fill the keymap. Therefore when calculating the "scancode" we should no longer use constant row shift but also calculate it from number of columns. Signed-off-by: Chao Xie Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/pxa27x_keypad.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c index d8241ba0afa0..a15063bea700 100644 --- a/drivers/input/keyboard/pxa27x_keypad.c +++ b/drivers/input/keyboard/pxa27x_keypad.c @@ -111,6 +111,8 @@ struct pxa27x_keypad { unsigned short keycodes[MAX_KEYPAD_KEYS]; int rotary_rel_code[2]; + unsigned int row_shift; + /* state row bits of each column scan */ uint32_t matrix_key_state[MAX_MATRIX_KEY_COLS]; uint32_t direct_key_state; @@ -467,7 +469,8 @@ scan: if ((bits_changed & (1 << row)) == 0) continue; - code = MATRIX_SCAN_CODE(row, col, MATRIX_ROW_SHIFT); + code = MATRIX_SCAN_CODE(row, col, keypad->row_shift); + input_event(input_dev, EV_MSC, MSC_SCAN, code); input_report_key(input_dev, keypad->keycodes[code], new_state[col] & (1 << row)); @@ -802,6 +805,8 @@ static int pxa27x_keypad_probe(struct platform_device *pdev) goto failed_put_clk; } + keypad->row_shift = get_count_order(pdata->matrix_key_cols); + if ((pdata->enable_rotary0 && keypad->rotary_rel_code[0] != -1) || (pdata->enable_rotary1 && keypad->rotary_rel_code[1] != -1)) { input_dev->evbit[0] |= BIT_MASK(EV_REL); -- cgit v1.2.3 From 5d61b54f5e06621d7b1471cbf8b76bc064117225 Mon Sep 17 00:00:00 2001 From: Liviu Dudau Date: Tue, 13 May 2014 23:17:12 -0700 Subject: Input: ambakmi - request a shared interrupt for AMBA KMI devices Recent ARM boards have the KMI devices share one interrupt line rather than having dedicated IRQs. Update the driver to take that into account. Signed-off-by: Liviu Dudau Signed-off-by: Mark Brown Signed-off-by: Dmitry Torokhov --- drivers/input/serio/ambakmi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/input/serio/ambakmi.c b/drivers/input/serio/ambakmi.c index 762b08432de0..8b748d99b934 100644 --- a/drivers/input/serio/ambakmi.c +++ b/drivers/input/serio/ambakmi.c @@ -79,7 +79,8 @@ static int amba_kmi_open(struct serio *io) writeb(divisor, KMICLKDIV); writeb(KMICR_EN, KMICR); - ret = request_irq(kmi->irq, amba_kmi_int, 0, "kmi-pl050", kmi); + ret = request_irq(kmi->irq, amba_kmi_int, IRQF_SHARED, "kmi-pl050", + kmi); if (ret) { printk(KERN_ERR "kmi: failed to claim IRQ%d\n", kmi->irq); writeb(0, KMICR); -- cgit v1.2.3 From b4b177a5556a686909e643f1e9b6434c10de079f Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 14 May 2014 15:34:41 +0200 Subject: mac80211: fix on-channel remain-on-channel Jouni reported that if a remain-on-channel was active on the same channel as the current operating channel, then the ROC would start, but any frames transmitted using mgmt-tx on the same channel would get delayed until after the ROC. The reason for this is that the ROC starts, but doesn't have any handling for "remain on the same channel", so it stops the interface queues. The later mgmt-tx then puts the frame on the interface queues (since it's on the current operating channel) and thus they get delayed until after the ROC. To fix this, add some logic to handle remaining on the same channel specially and not stop the queues etc. in this case. This not only fixes the bug but also improves behaviour in this case as data frames etc. can continue to flow. Cc: stable@vger.kernel.org Reported-by: Jouni Malinen Tested-by: Jouni Malinen Signed-off-by: Johannes Berg --- net/mac80211/ieee80211_i.h | 1 + net/mac80211/offchannel.c | 27 ++++++++++++++++++++------- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 222c28b75315..f169b6ee94ee 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -317,6 +317,7 @@ struct ieee80211_roc_work { bool started, abort, hw_begun, notified; bool to_be_freed; + bool on_channel; unsigned long hw_start_time; diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index 6fb38558a5e6..7a17decd27f9 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c @@ -333,7 +333,7 @@ void ieee80211_sw_roc_work(struct work_struct *work) container_of(work, struct ieee80211_roc_work, work.work); struct ieee80211_sub_if_data *sdata = roc->sdata; struct ieee80211_local *local = sdata->local; - bool started; + bool started, on_channel; mutex_lock(&local->mtx); @@ -354,14 +354,26 @@ void ieee80211_sw_roc_work(struct work_struct *work) if (!roc->started) { struct ieee80211_roc_work *dep; - /* start this ROC */ - ieee80211_offchannel_stop_vifs(local); + WARN_ON(local->use_chanctx); + + /* If actually operating on the desired channel (with at least + * 20 MHz channel width) don't stop all the operations but still + * treat it as though the ROC operation started properly, so + * other ROC operations won't interfere with this one. + */ + roc->on_channel = roc->chan == local->_oper_chandef.chan && + local->_oper_chandef.width != NL80211_CHAN_WIDTH_5 && + local->_oper_chandef.width != NL80211_CHAN_WIDTH_10; - /* switch channel etc */ + /* start this ROC */ ieee80211_recalc_idle(local); - local->tmp_channel = roc->chan; - ieee80211_hw_config(local, 0); + if (!roc->on_channel) { + ieee80211_offchannel_stop_vifs(local); + + local->tmp_channel = roc->chan; + ieee80211_hw_config(local, 0); + } /* tell userspace or send frame */ ieee80211_handle_roc_started(roc); @@ -380,9 +392,10 @@ void ieee80211_sw_roc_work(struct work_struct *work) finish: list_del(&roc->list); started = roc->started; + on_channel = roc->on_channel; ieee80211_roc_notify_destroy(roc, !roc->abort); - if (started) { + if (started && !on_channel) { ieee80211_flush_queues(local, NULL); local->tmp_channel = NULL; -- cgit v1.2.3 From 582da6527da30f6e21a95c9f3f2810d46a8f406e Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Wed, 14 May 2014 13:36:36 +0200 Subject: of: make of_update_property() usable earlier in the boot process Commit 75b57ecf9d1d1e17d099ab13b8f48e6e038676be ('of: Make device nodes kobjects so they show up in sysfs') has turned Device Tree nodes in kobjects and added a sysfs based representation for Device Tree nodes. Since the sysfs logic is only available after the execution of a core_initcall(), the patch took precautions in of_add_property() and of_remove_property() to not do any sysfs related manipulation early in the boot process. However, it forgot to do the same for of_update_property(), which if used early in the boot process (before core_initcalls have been called), tries to call sysfs_remove_bin_file(), and crashes: ------------[ cut here ]------------ WARNING: CPU: 0 PID: 0 at /home/thomas/projets/linux-2.6/fs/kernfs/dir.c:1216 kernfs_remove_by_name_ns+0x80/0x88() kernfs: can not remove '(null)', no directory Modules linked in: CPU: 0 PID: 0 Comm: swapper/0 Not tainted 3.15.0-rc1-00127-g1d7e7b2-dirty #423 [] (unwind_backtrace) from [] (show_stack+0x10/0x14) [] (show_stack) from [] (dump_stack+0x84/0x94) [] (dump_stack) from [] (warn_slowpath_common+0x6c/0x88) [] (warn_slowpath_common) from [] (warn_slowpath_fmt+0x30/0x40) [] (warn_slowpath_fmt) from [] (kernfs_remove_by_name_ns+0x80/0x88) [] (kernfs_remove_by_name_ns) from [] (of_update_property+0xc0/0xf0) [] (of_update_property) from [] (mvebu_timer_and_clk_init+0xfc/0x194) [] (mvebu_timer_and_clk_init) from [] (start_kernel+0x218/0x350) [] (start_kernel) from [<00008070>] (0x8070) ---[ end trace 3406ff24bd97382e ]--- Unable to handle kernel NULL pointer dereference at virtual address 0000003c pgd = c0004000 [0000003c] *pgd=00000000 Internal error: Oops: 5 [#1] SMP ARM Modules linked in: CPU: 0 PID: 0 Comm: swapper/0 Tainted: G W 3.15.0-rc1-00127-g1d7e7b2-dirty #423 task: c10ad4d8 ti: c10a2000 task.ti: c10a2000 PC is at kernfs_find_ns+0x8/0xf0 LR is at kernfs_find_and_get_ns+0x30/0x48 pc : [] lr : [] psr: 600001d3 sp : c10a3f34 ip : 00000073 fp : 00000000 r10: 00000000 r9 : cfffc240 r8 : cfdf2980 r7 : cf812c00 r6 : 00000000 r5 : 00000000 r4 : c10b45e0 r3 : c10ad4d8 r2 : 00000000 r1 : cf812c00 r0 : 00000000 Flags: nZCv IRQs off FIQs off Mode SVC_32 ISA ARM Segment kernel Control: 10c53c7d Table: 0000404a DAC: 00000015 Process swapper/0 (pid: 0, stack limit = 0xc10a2240) Stack: (0xc10a3f34 to 0xc10a4000) 3f20: c10b45e0 00000000 00000000 3f40: cf812c00 c010394c 00000063 cf812c00 00000001 cf812c00 cfdf29ac c03932cc 3f60: 00000063 cf812bc0 cfdf29ac cf812c00 ffffffff c03943f8 cfdf2980 c0104468 3f80: cfdf2a04 cfdf2980 cf812bc0 c06634b0 c10aa3c0 c0394da4 c10f74dc cfdf2980 3fa0: cf812bc0 c0647248 c10aa3c0 ffffffff c10de940 c10aa3c0 ffffffff c0640934 3fc0: ffffffff ffffffff c06404ec 00000000 00000000 c06634b0 00000000 10c53c7d 3fe0: c10aa434 c06634ac c10ae4c8 0000406a 414fc091 00008070 00000000 00000000 [] (kernfs_find_ns) from [<00000001>] (0x1) Code: e5c89001 eaffffcf e92d40f0 e1a06002 (e1d023bc) ---[ end trace 3406ff24bd97382f ]--- Kernel panic - not syncing: Attempted to kill the idle task! ---[ end Kernel panic - not syncing: Attempted to kill the idle task! To fix this problem, we simply skip the sysfs related calls in of_update_property(), and rely on of_init() to fix up things when it will be called, exactly as is done in of_add_property() and of_remove_property(). Signed-off-by: Thomas Petazzoni Fixes: 75b57ecf9d1d ("of: Make device nodes kobjects so they show up in sysfs") Signed-off-by: Grant Likely --- drivers/of/base.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/of/base.c b/drivers/of/base.c index 6d4ee22708c9..32e969d95319 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1831,6 +1831,10 @@ int of_update_property(struct device_node *np, struct property *newprop) if (!found) return -ENODEV; + /* At early boot, bail out and defer setup to of_init() */ + if (!of_kset) + return found ? 0 : -ENODEV; + /* Update the sysfs attribute */ sysfs_remove_bin_file(&np->kobj, &oldprop->attr); __of_add_property_sysfs(np, newprop); -- cgit v1.2.3 From 665ebe926e7b714369b5329d48745bfef17db512 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 14 May 2014 16:32:21 +0300 Subject: ALSA: sb_mixer: missing return statement The if condition here was supposed to return on error but the return statement is missing. The effect is that the ->mixername is set to "???" instead of "DT019X". Signed-off-by: Dan Carpenter Signed-off-by: Takashi Iwai --- sound/isa/sb/sb_mixer.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/sound/isa/sb/sb_mixer.c b/sound/isa/sb/sb_mixer.c index 6496822c1808..1ff78ec9f0ac 100644 --- a/sound/isa/sb/sb_mixer.c +++ b/sound/isa/sb/sb_mixer.c @@ -818,12 +818,14 @@ int snd_sbmixer_new(struct snd_sb *chip) return err; break; case SB_HW_DT019X: - if ((err = snd_sbmixer_init(chip, - snd_dt019x_controls, - ARRAY_SIZE(snd_dt019x_controls), - snd_dt019x_init_values, - ARRAY_SIZE(snd_dt019x_init_values), - "DT019X")) < 0) + err = snd_sbmixer_init(chip, + snd_dt019x_controls, + ARRAY_SIZE(snd_dt019x_controls), + snd_dt019x_init_values, + ARRAY_SIZE(snd_dt019x_init_values), + "DT019X"); + if (err < 0) + return err; break; default: strcpy(card->mixername, "???"); -- cgit v1.2.3 From 16a9602158861687c78b6de6dc6a79e6e8a9136f Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Wed, 14 May 2014 12:43:24 -0300 Subject: KVM: x86: disable master clock if TSC is reset during suspend Updating system_time from the kernel clock once master clock has been enabled can result in time backwards event, in case kernel clock frequency is lower than TSC frequency. Disable master clock in case it is necessary to update it from the resume path. Signed-off-by: Marcelo Tosatti Signed-off-by: Paolo Bonzini --- arch/x86/kvm/x86.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 8b8fc0b792ba..84a2d4152a63 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -106,6 +106,8 @@ EXPORT_SYMBOL_GPL(kvm_max_guest_tsc_khz); static u32 tsc_tolerance_ppm = 250; module_param(tsc_tolerance_ppm, uint, S_IRUGO | S_IWUSR); +static bool backwards_tsc_observed = false; + #define KVM_NR_SHARED_MSRS 16 struct kvm_shared_msrs_global { @@ -1486,7 +1488,8 @@ static void pvclock_update_vm_gtod_copy(struct kvm *kvm) &ka->master_kernel_ns, &ka->master_cycle_now); - ka->use_master_clock = host_tsc_clocksource & vcpus_matched; + ka->use_master_clock = host_tsc_clocksource && vcpus_matched + && !backwards_tsc_observed; if (ka->use_master_clock) atomic_set(&kvm_guest_has_master_clock, 1); @@ -6945,6 +6948,7 @@ int kvm_arch_hardware_enable(void *garbage) */ if (backwards_tsc) { u64 delta_cyc = max_tsc - local_tsc; + backwards_tsc_observed = true; list_for_each_entry(kvm, &vm_list, vm_list) { kvm_for_each_vcpu(i, vcpu, kvm) { vcpu->arch.tsc_offset_adjustment += delta_cyc; -- cgit v1.2.3 From 7bb394094080a26de06efcd6a870cb2ba21cfb16 Mon Sep 17 00:00:00 2001 From: "Steven J. Hill" Date: Thu, 10 Apr 2014 14:06:17 -0500 Subject: MIPS: mm: Fix broken microMIPS kernel regression. Commit f4ae17aa0f2122b52f642985b46210a1f2eceb0a [MIPS: mm: Use scratch for PGD when !CONFIG_MIPS_PGD_C0_CONTEXT] broke microMIPS kernel builds. This patch refactors that code similar to what was done for the 'clear_page' and 'copy_page' functions. Signed-off-by: Steven J. Hill Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/6744/ Signed-off-by: Ralf Baechle --- arch/mips/mm/tlb-funcs.S | 4 +++- arch/mips/mm/tlbex.c | 7 ++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/arch/mips/mm/tlb-funcs.S b/arch/mips/mm/tlb-funcs.S index 30a494db99c2..a5427c6e9757 100644 --- a/arch/mips/mm/tlb-funcs.S +++ b/arch/mips/mm/tlb-funcs.S @@ -16,8 +16,10 @@ #define FASTPATH_SIZE 128 +EXPORT(tlbmiss_handler_setup_pgd_start) LEAF(tlbmiss_handler_setup_pgd) - .space 16 * 4 +1: j 1b /* Dummy, will be replaced. */ + .space 64 END(tlbmiss_handler_setup_pgd) EXPORT(tlbmiss_handler_setup_pgd_end) diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index ee88367ab3ad..f99ec587b151 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -1422,16 +1422,17 @@ static void build_r4000_tlb_refill_handler(void) extern u32 handle_tlbl[], handle_tlbl_end[]; extern u32 handle_tlbs[], handle_tlbs_end[]; extern u32 handle_tlbm[], handle_tlbm_end[]; -extern u32 tlbmiss_handler_setup_pgd[], tlbmiss_handler_setup_pgd_end[]; +extern u32 tlbmiss_handler_setup_pgd_start[], tlbmiss_handler_setup_pgd[]; +extern u32 tlbmiss_handler_setup_pgd_end[]; static void build_setup_pgd(void) { const int a0 = 4; const int __maybe_unused a1 = 5; const int __maybe_unused a2 = 6; - u32 *p = tlbmiss_handler_setup_pgd; + u32 *p = tlbmiss_handler_setup_pgd_start; const int tlbmiss_handler_setup_pgd_size = - tlbmiss_handler_setup_pgd_end - tlbmiss_handler_setup_pgd; + tlbmiss_handler_setup_pgd_end - tlbmiss_handler_setup_pgd_start; #ifndef CONFIG_MIPS_PGD_C0_CONTEXT long pgdc = (long)pgd_current; #endif -- cgit v1.2.3 From 47bb27e78867997040a228328f2a631c3c7f2c82 Mon Sep 17 00:00:00 2001 From: "Du, Wenkai" Date: Thu, 10 Apr 2014 23:03:19 +0000 Subject: i2c: designware: Mask all interrupts during i2c controller enable There have been "i2c_designware 80860F41:00: controller timed out" errors on a number of Baytrail platforms. The issue is caused by incorrect value in Interrupt Mask Register (DW_IC_INTR_MASK) when i2c core is being enabled. This causes call to __i2c_dw_enable() to immediately start the transfer which leads to timeout. There are 3 failure modes observed: 1. Failure in S0 to S3 resume path The default value after reset for DW_IC_INTR_MASK is 0x8ff. When we start the first transaction after resuming from system sleep, TX_EMPTY interrupt is already unmasked because of the hardware default. 2. Failure in normal operational path This failure happens rarely and is hard to reproduce. Debug trace showed that DW_IC_INTR_MASK had value of 0x254 when failure occurred, which meant TX_EMPTY was unmasked. 3. Failure in S3 to S0 suspend path This failure also happens rarely and is hard to reproduce. Adding debug trace that read DW_IC_INTR_MASK made this failure not reproducible. But from ISR call trace we could conclude TX_EMPTY was unmasked when problem occurred. The patch masks all interrupts before the controller is enabled to resolve the faulty DW_IC_INTR_MASK conditions. Signed-off-by: Wenkai Du Acked-by: Mika Westerberg [wsa: improved the comment and removed typo in commit msg] Signed-off-by: Wolfram Sang Cc: stable@kernel.org --- drivers/i2c/busses/i2c-designware-core.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c index 22e92c3d3d07..3c20e4bd6dd1 100644 --- a/drivers/i2c/busses/i2c-designware-core.c +++ b/drivers/i2c/busses/i2c-designware-core.c @@ -422,6 +422,9 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev) */ dw_writel(dev, msgs[dev->msg_write_idx].addr | ic_tar, DW_IC_TAR); + /* enforce disabled interrupts (due to HW issues) */ + i2c_dw_disable_int(dev); + /* Enable the adapter */ __i2c_dw_enable(dev, true); -- cgit v1.2.3 From 37e5eb0bae7bb4d98c2153c3c3400b5c00c3cad1 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Thu, 10 Apr 2014 16:19:29 +0200 Subject: i2c: nomadik: Don't use IS_ERR for devm_ioremap devm_ioremap() returns NULL on error, not an error. Signed-off-by: Ulf Hansson Acked-by: Linus Walleij Signed-off-by: Wolfram Sang Cc: stable@kernel.org --- drivers/i2c/busses/i2c-nomadik.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index 28cbe1b2a2ec..32c85e9ecdae 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c @@ -999,7 +999,7 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id) dev->virtbase = devm_ioremap(&adev->dev, adev->res.start, resource_size(&adev->res)); - if (IS_ERR(dev->virtbase)) { + if (!dev->virtbase) { ret = -ENOMEM; goto err_no_mem; } -- cgit v1.2.3 From ce78cc071f5f541480e381cc0241d37590041a9d Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Fri, 11 Apr 2014 15:19:41 -0700 Subject: i2c: s3c2410: resume race fix Don't unmark the device as suspended until after it's been re-setup. The main race would be w.r.t. an i2c driver that gets resumed at the same time (asyncronously), that is allowed to do a transfer since suspended is set to 0 before reinit, but really should have seen the -EIO return instead. Signed-off-by: Olof Johansson Signed-off-by: Doug Anderson Acked-by: Kukjin Kim Signed-off-by: Wolfram Sang Cc: stable@kernel.org --- drivers/i2c/busses/i2c-s3c2410.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index ae4491062e41..bb3a9964f7e0 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -1276,10 +1276,10 @@ static int s3c24xx_i2c_resume(struct device *dev) struct platform_device *pdev = to_platform_device(dev); struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev); - i2c->suspended = 0; clk_prepare_enable(i2c->clk); s3c24xx_i2c_init(i2c); clk_disable_unprepare(i2c->clk); + i2c->suspended = 0; return 0; } -- cgit v1.2.3 From fa01d096bfcfd89398b1f3a3f91805dab76f7fe5 Mon Sep 17 00:00:00 2001 From: Andy Gross Date: Fri, 2 May 2014 20:54:29 -0500 Subject: i2c: qup: Fix pm_runtime_get_sync usage This patch corrects the error check on the call to pm_runtime_get_sync. Signed-off-by: Andy Gross Reviewed-by: Ivan T. Ivanov Acked-by: Bjorn Andersson Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-qup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c index 1b4cf14f1106..2a5efb5b487c 100644 --- a/drivers/i2c/busses/i2c-qup.c +++ b/drivers/i2c/busses/i2c-qup.c @@ -479,7 +479,7 @@ static int qup_i2c_xfer(struct i2c_adapter *adap, int ret, idx; ret = pm_runtime_get_sync(qup->dev); - if (ret) + if (ret < 0) goto out; writel(1, qup->base + QUP_SW_RESET); -- cgit v1.2.3 From d7653964c590ba846aa11a8f6edf409773cbc492 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 5 May 2014 18:36:21 +0200 Subject: i2c: rcar: bail out on zero length transfers This hardware does not support zero length transfers. Instead, the driver does one (random) byte transfers currently with undefined results for the slaves. We now bail out. Signed-off-by: Wolfram Sang Signed-off-by: Wolfram Sang Cc: stable@kernel.org --- drivers/i2c/busses/i2c-rcar.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c index d4fa8eba6e9d..06d47aafbb79 100644 --- a/drivers/i2c/busses/i2c-rcar.c +++ b/drivers/i2c/busses/i2c-rcar.c @@ -561,6 +561,12 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap, ret = -EINVAL; for (i = 0; i < num; i++) { + /* This HW can't send STOP after address phase */ + if (msgs[i].len == 0) { + ret = -EOPNOTSUPP; + break; + } + /*-------------- spin lock -----------------*/ spin_lock_irqsave(&priv->lock, flags); @@ -625,7 +631,8 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap, static u32 rcar_i2c_func(struct i2c_adapter *adap) { - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; + /* This HW can't do SMBUS_QUICK and NOSTART */ + return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK); } static const struct i2c_algorithm rcar_i2c_algo = { -- cgit v1.2.3 From 0f9e19ad88eee820f517b85531b555a0fa73e7e4 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 9 May 2014 11:10:05 +0300 Subject: ARM: omap5: hwmod_data: Correct IDLEMODE for McPDM McPDM need to be configured to NO_IDLE mode when it is in used otherwise vital clocks will be gated which results 'slow motion' audio playback. Signed-off-by: Peter Ujfalusi Cc: Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_hwmod_54xx_data.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/omap_hwmod_54xx_data.c b/arch/arm/mach-omap2/omap_hwmod_54xx_data.c index 892317294fdc..e829664e6a6c 100644 --- a/arch/arm/mach-omap2/omap_hwmod_54xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_54xx_data.c @@ -895,7 +895,7 @@ static struct omap_hwmod omap54xx_mcpdm_hwmod = { * current exception. */ - .flags = HWMOD_EXT_OPT_MAIN_CLK, + .flags = HWMOD_EXT_OPT_MAIN_CLK | HWMOD_SWSUP_SIDLE, .main_clk = "pad_clks_ck", .prcm = { .omap4 = { -- cgit v1.2.3 From 0b5fe736fe923f1f5e05413878d5990e92ffbdf5 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 14 May 2014 11:10:40 -0700 Subject: Input: synaptics - add min/max quirk for the ThinkPad W540 https://bugzilla.redhat.com/show_bug.cgi?id=1096436 Cc: stable@vger.kernel.org Tested-and-reported-by: ajayr@bigfoot.com Signed-off-by: Hans de Goede Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/synaptics.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index d68d33fb5ac2..d4c05b103e74 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -1613,6 +1613,14 @@ static const struct dmi_system_id min_max_dmi_table[] __initconst = { }, .driver_data = (int []){1024, 5112, 2024, 4832}, }, + { + /* Lenovo ThinkPad W540 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad W540"), + }, + .driver_data = (int []){1024, 5112, 2024, 4832}, + }, { /* Lenovo Yoga S1 */ .matches = { -- cgit v1.2.3 From c4b160685fc85e41fe8c08478cc61f4877d26973 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Mon, 12 May 2014 10:38:18 -0400 Subject: jme: Fix unmap loop counting error: In my recent fix (76a691d0a: fix dma unmap warning), Ben Hutchings noted that my loop count was incorrect. Where j started at startidx, it should have started at zero, and gone on for count entries, not to endidx. Additionally, a DMA resource exhaustion should drop the frame and (for now), return NETDEV_TX_OK, not NETEV_TX_BUSY. This patch fixes both of those issues: Signed-off-by: Neil Horman CC: Ben Hutchings CC: "David S. Miller" CC: Guo-Fu Tseng Signed-off-by: David S. Miller --- drivers/net/ethernet/jme.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c index 6e664d9038d6..b78378cea5e3 100644 --- a/drivers/net/ethernet/jme.c +++ b/drivers/net/ethernet/jme.c @@ -2027,14 +2027,14 @@ jme_fill_tx_map(struct pci_dev *pdev, return 0; } -static void jme_drop_tx_map(struct jme_adapter *jme, int startidx, int endidx) +static void jme_drop_tx_map(struct jme_adapter *jme, int startidx, int count) { struct jme_ring *txring = &(jme->txring[0]); struct jme_buffer_info *txbi = txring->bufinf, *ctxbi; int mask = jme->tx_ring_mask; int j; - for (j = startidx ; j < endidx ; ++j) { + for (j = 0 ; j < count ; j++) { ctxbi = txbi + ((startidx + j + 2) & (mask)); pci_unmap_page(jme->pdev, ctxbi->mapping, @@ -2069,7 +2069,7 @@ jme_map_tx_skb(struct jme_adapter *jme, struct sk_buff *skb, int idx) skb_frag_page(frag), frag->page_offset, skb_frag_size(frag), hidma); if (ret) { - jme_drop_tx_map(jme, idx, idx+i); + jme_drop_tx_map(jme, idx, i); goto out; } @@ -2081,7 +2081,7 @@ jme_map_tx_skb(struct jme_adapter *jme, struct sk_buff *skb, int idx) ret = jme_fill_tx_map(jme->pdev, ctxdesc, ctxbi, virt_to_page(skb->data), offset_in_page(skb->data), len, hidma); if (ret) - jme_drop_tx_map(jme, idx, idx+i); + jme_drop_tx_map(jme, idx, i); out: return ret; @@ -2269,7 +2269,7 @@ jme_start_xmit(struct sk_buff *skb, struct net_device *netdev) } if (jme_fill_tx_desc(jme, skb, idx)) - return NETDEV_TX_BUSY; + return NETDEV_TX_OK; jwrite32(jme, JME_TXCS, jme->reg_txcs | TXCS_SELECT_QUEUE0 | -- cgit v1.2.3 From 989ff3fdf939b15f0cb91406746da0ded0c06ef0 Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Fri, 9 May 2014 06:19:18 +0900 Subject: ARM: EXYNOS: fix the secondary CPU boot of exynos4212 This patch fixes the offset of CPU boot address and changes the parameter of smc call for SMC_CMD_CPU1BOOT command on exynos4212. Signed-off-by: Kyungmin Park Signed-off-by: Chanwoo Choi Reviewed-by: Tomasz Figa Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/firmware.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-exynos/firmware.c b/arch/arm/mach-exynos/firmware.c index 932129ef26c6..aa01c4222b40 100644 --- a/arch/arm/mach-exynos/firmware.c +++ b/arch/arm/mach-exynos/firmware.c @@ -18,6 +18,8 @@ #include +#include + #include "smc.h" static int exynos_do_idle(void) @@ -28,13 +30,24 @@ static int exynos_do_idle(void) static int exynos_cpu_boot(int cpu) { + /* + * The second parameter of SMC_CMD_CPU1BOOT command means CPU id. + * But, Exynos4212 has only one secondary CPU so second parameter + * isn't used for informing secure firmware about CPU id. + */ + if (soc_is_exynos4212()) + cpu = 0; + exynos_smc(SMC_CMD_CPU1BOOT, cpu, 0, 0); return 0; } static int exynos_set_cpu_boot_addr(int cpu, unsigned long boot_addr) { - void __iomem *boot_reg = S5P_VA_SYSRAM_NS + 0x1c + 4*cpu; + void __iomem *boot_reg = S5P_VA_SYSRAM_NS + 0x1c; + + if (!soc_is_exynos4212()) + boot_reg += 4*cpu; __raw_writel(boot_addr, boot_reg); return 0; -- cgit v1.2.3 From e6015c1f8a9032c2aecb78d23edf49582563bd47 Mon Sep 17 00:00:00 2001 From: Seungwon Jeon Date: Fri, 9 May 2014 07:02:33 +0900 Subject: ARM: dts: disable MDMA1 node for exynos5420 This change places MDMA1 in disabled node for Exynos5420. If MDMA1 region is configured with secure mode, it makes the boot failure with the following on smdk5420 board. ("Unhandled fault: imprecise external abort (0x1406) at 0x00000000") Thus, arndale-octa board don't need to do the same thing anymore. Signed-off-by: Seungwon Jeon Tested-by: Javi Merino Signed-off-by: Kukjin Kim --- arch/arm/boot/dts/exynos5420-arndale-octa.dts | 12 ------------ arch/arm/boot/dts/exynos5420.dtsi | 7 +++++++ 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/arch/arm/boot/dts/exynos5420-arndale-octa.dts b/arch/arm/boot/dts/exynos5420-arndale-octa.dts index 80a3bf4c5986..896a2a6619e0 100644 --- a/arch/arm/boot/dts/exynos5420-arndale-octa.dts +++ b/arch/arm/boot/dts/exynos5420-arndale-octa.dts @@ -364,16 +364,4 @@ gpio-key,wakeup; }; }; - - amba { - mdma1: mdma@11C10000 { - /* - * MDMA1 can support both secure and non-secure - * AXI transactions. When this is enabled in the kernel - * for boards that run in secure mode, we are getting - * imprecise external aborts causing the kernel to oops. - */ - status = "disabled"; - }; - }; }; diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi index c3a9a66c5767..97cbcdd901be 100644 --- a/arch/arm/boot/dts/exynos5420.dtsi +++ b/arch/arm/boot/dts/exynos5420.dtsi @@ -336,6 +336,13 @@ #dma-cells = <1>; #dma-channels = <8>; #dma-requests = <1>; + /* + * MDMA1 can support both secure and non-secure + * AXI transactions. When this is enabled in the kernel + * for boards that run in secure mode, we are getting + * imprecise external aborts causing the kernel to oops. + */ + status = "disabled"; }; }; -- cgit v1.2.3 From a8f1d0889e902cbac8c18a40ec927a109e48a52e Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 15 May 2014 04:14:16 +0900 Subject: ARM: exynos_defconfig: enable HS-I2C to fix for mmc partition mount High speed I2C is used on Exynos5 based SoCs. Enable it. The MMC partition for Root filesystem cannot be mounted without this enabling HS-I2C and regulators on many boards are connected HS-I2C bus so the regulators don't come by default without this. Actually, we are not able to get arndale-octa board to boot and mount an MMC partition without this change. Signed-off-by: Sachin Kamat Tested-by: Javi Merino [kgene.kim@samsung.com: modified description] Signed-off-by: Kukjin Kim --- arch/arm/configs/exynos_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/exynos_defconfig b/arch/arm/configs/exynos_defconfig index 4ce7b70ea901..e07a227ec0db 100644 --- a/arch/arm/configs/exynos_defconfig +++ b/arch/arm/configs/exynos_defconfig @@ -65,6 +65,7 @@ CONFIG_TCG_TIS_I2C_INFINEON=y CONFIG_I2C=y CONFIG_I2C_MUX=y CONFIG_I2C_ARB_GPIO_CHALLENGE=y +CONFIG_I2C_EXYNOS5=y CONFIG_I2C_S3C2410=y CONFIG_DEBUG_GPIO=y # CONFIG_HWMON is not set -- cgit v1.2.3 From c5b817e44bc97a3d119822459f69ea7d1dc528ee Mon Sep 17 00:00:00 2001 From: Tushar Behera Date: Thu, 15 May 2014 04:16:03 +0900 Subject: ARM: dts: Remove mau_pd node for exynos5420 MAU powerdomain provides clocks for Audio sub-system block. This block comprises of the I2S audio controller, audio DMA blocks and Audio sub-system clock registers. Right now, there is no way to hook up power-domains with clock providers. During late boot when this power-domain gets disabled, we get following external abort. Unhandled fault: imprecise external abort (0x1406) at 0x00000000 Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000007 Signed-off-by: Tushar Behera Tested-by: Doug Anderson Signed-off-by: Kukjin Kim --- arch/arm/boot/dts/exynos5420.dtsi | 5 ----- 1 file changed, 5 deletions(-) diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi index 97cbcdd901be..430ba1fe0de2 100644 --- a/arch/arm/boot/dts/exynos5420.dtsi +++ b/arch/arm/boot/dts/exynos5420.dtsi @@ -219,11 +219,6 @@ reg = <0x100440C0 0x20>; }; - mau_pd: power-domain@100440E0 { - compatible = "samsung,exynos4210-pd"; - reg = <0x100440E0 0x20>; - }; - g2d_pd: power-domain@10044100 { compatible = "samsung,exynos4210-pd"; reg = <0x10044100 0x20>; -- cgit v1.2.3 From 702b691e4a711e699cf3cccba879c1d945665c0d Mon Sep 17 00:00:00 2001 From: Arun Kumar K Date: Thu, 15 May 2014 04:17:17 +0900 Subject: ARM: dts: Remove g2d_pd node for exynos5420 G2D power domain also controls the CMU block of G2D. Since clock registers can be accessed anytime for viewing clk_summary, it can cause a system crash if g2d power domain is disabled. Signed-off-by: Arun Kumar K Signed-off-by: Kukjin Kim --- arch/arm/boot/dts/exynos5420.dtsi | 6 ------ 1 file changed, 6 deletions(-) diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi index 430ba1fe0de2..418f2506aaf0 100644 --- a/arch/arm/boot/dts/exynos5420.dtsi +++ b/arch/arm/boot/dts/exynos5420.dtsi @@ -219,11 +219,6 @@ reg = <0x100440C0 0x20>; }; - g2d_pd: power-domain@10044100 { - compatible = "samsung,exynos4210-pd"; - reg = <0x10044100 0x20>; - }; - msc_pd: power-domain@10044120 { compatible = "samsung,exynos4210-pd"; reg = <0x10044120 0x20>; @@ -732,6 +727,5 @@ interrupts = <0 112 0>; clocks = <&clock 471>; clock-names = "secss"; - samsung,power-domain = <&g2d_pd>; }; }; -- cgit v1.2.3 From 03a58baa785f48a85126ab043a14cb80b7e670e0 Mon Sep 17 00:00:00 2001 From: Kalesh AP Date: Tue, 13 May 2014 14:03:11 +0530 Subject: be2net: enable interrupts in EEH resume On some BE3 FW versions, after a HW reset, interrupts will remain disabled for each function. So, explicitly enable the interrupts in the eeh_resume handler, else after an eeh recovery interrupts wouldn't work. Signed-off-by: Kalesh AP Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be_main.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index a18645407d21..dc19bc5dec77 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -4949,6 +4949,12 @@ static void be_eeh_resume(struct pci_dev *pdev) if (status) goto err; + /* On some BE3 FW versions, after a HW reset, + * interrupts will remain disabled for each function. + * So, explicitly enable interrupts + */ + be_intr_set(adapter, true); + /* tell fw we're ready to fire cmds */ status = be_cmd_fw_init(adapter); if (status) -- cgit v1.2.3 From f5738e2ef88070ef1372e6e718124d88e9abe4ac Mon Sep 17 00:00:00 2001 From: Ursula Braun Date: Tue, 13 May 2014 14:38:02 +0200 Subject: af_iucv: wrong mapping of sent and confirmed skbs When sending data through IUCV a MESSAGE COMPLETE interrupt signals that sent data memory can be freed or reused again. With commit f9c41a62bba3f3f7ef3541b2a025e3371bcbba97 "af_iucv: fix recvmsg by replacing skb_pull() function" the MESSAGE COMPLETE callback iucv_callback_txdone() identifies the wrong skb as being confirmed, which leads to data corruption. This patch fixes the skb mapping logic in iucv_callback_txdone(). Signed-off-by: Ursula Braun Signed-off-by: Frank Blaschka Cc: Signed-off-by: David S. Miller --- net/iucv/af_iucv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index 01e77b0ae075..8c9d7302c846 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c @@ -1830,7 +1830,7 @@ static void iucv_callback_txdone(struct iucv_path *path, spin_lock_irqsave(&list->lock, flags); while (list_skb != (struct sk_buff *)list) { - if (msg->tag != IUCV_SKB_CB(list_skb)->tag) { + if (msg->tag == IUCV_SKB_CB(list_skb)->tag) { this = list_skb; break; } -- cgit v1.2.3 From faf1dc64e345ac4de5c4429df6ed492255ae2248 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Wed, 14 May 2014 14:39:21 +0530 Subject: ath9k_htc: Stop ANI before doing hw_reset During remain on channel request, ANI worker thread is not stopped before doing hw reset. This is causing kernel crash in hw_per_calibration. This change ensures that ANI is stopped before doing chip reset and it will be rescheduled later when the chip is configured back to home channel and having valid bss. Reported-by: David Herrmann Tested-by: David Herrmann Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index f46cd0250e48..5627917c5ff7 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -95,8 +95,10 @@ static void ath9k_htc_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) if ((vif->type == NL80211_IFTYPE_AP || vif->type == NL80211_IFTYPE_MESH_POINT) && - bss_conf->enable_beacon) + bss_conf->enable_beacon) { priv->reconfig_beacon = true; + priv->rearm_ani = true; + } if (bss_conf->assoc) { priv->rearm_ani = true; @@ -257,6 +259,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, ath9k_htc_ps_wakeup(priv); + ath9k_htc_stop_ani(priv); del_timer_sync(&priv->tx.cleanup_timer); ath9k_htc_tx_drain(priv); -- cgit v1.2.3 From e84d2f8d2ae33c8215429824e1ecf24cbca9645e Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 14 May 2014 09:48:21 +0200 Subject: net: filter: s390: fix JIT address randomization This is the s390 variant of Alexei's JIT bug fix. (patch description below stolen from Alexei's patch) bpf_alloc_binary() adds 128 bytes of room to JITed program image and rounds it up to the nearest page size. If image size is close to page size (like 4000), it is rounded to two pages: round_up(4000 + 4 + 128) == 8192 then 'hole' is computed as 8192 - (4000 + 4) = 4188 If prandom_u32() % hole selects a number >= PAGE_SIZE - sizeof(*header) then kernel will crash during bpf_jit_free(): kernel BUG at arch/x86/mm/pageattr.c:887! Call Trace: [] change_page_attr_set_clr+0x135/0x460 [] ? _raw_spin_unlock_irq+0x30/0x50 [] set_memory_rw+0x2f/0x40 [] bpf_jit_free_deferred+0x2d/0x60 [] process_one_work+0x1d8/0x6a0 [] ? process_one_work+0x178/0x6a0 [] worker_thread+0x11c/0x370 since bpf_jit_free() does: unsigned long addr = (unsigned long)fp->bpf_func & PAGE_MASK; struct bpf_binary_header *header = (void *)addr; to compute start address of 'bpf_binary_header' and header->pages will pass junk to: set_memory_rw(addr, header->pages); Fix it by making sure that &header->image[prandom_u32() % hole] and &header are in the same page. Fixes: aa2d2c73c21f2 ("s390/bpf,jit: address randomize and write protect jit code") Reported-by: Alexei Starovoitov Cc: # v3.11+ Signed-off-by: Heiko Carstens Signed-off-by: David S. Miller --- arch/s390/net/bpf_jit_comp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c index 452d3ebd9d0f..e9f8fa9337fe 100644 --- a/arch/s390/net/bpf_jit_comp.c +++ b/arch/s390/net/bpf_jit_comp.c @@ -811,7 +811,7 @@ static struct bpf_binary_header *bpf_alloc_binary(unsigned int bpfsize, return NULL; memset(header, 0, sz); header->pages = sz / PAGE_SIZE; - hole = sz - (bpfsize + sizeof(*header)); + hole = min(sz - (bpfsize + sizeof(*header)), PAGE_SIZE - sizeof(*header)); /* Insert random number of illegal instructions before BPF code * and make sure the first instruction starts at an even address. */ -- cgit v1.2.3 From 610f2de3559c383caf8fbbf91e9968102dff7ca0 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Thu, 20 Feb 2014 18:01:01 -0500 Subject: dm crypt: fix cpu hotplug crash by removing per-cpu structure The DM crypt target used per-cpu structures to hold pointers to a ablkcipher_request structure. The code assumed that the work item keeps executing on a single CPU, so it didn't use synchronization when accessing this structure. If a CPU is disabled by writing 0 to /sys/devices/system/cpu/cpu*/online, the work item could be moved to another CPU. This causes dm-crypt crashes, like the following, because the code starts using an incorrect ablkcipher_request: smpboot: CPU 7 is now offline BUG: unable to handle kernel NULL pointer dereference at 0000000000000130 IP: [] crypt_convert+0x12d/0x3c0 [dm_crypt] ... Call Trace: [] ? kcryptd_crypt+0x305/0x470 [dm_crypt] [] ? finish_task_switch+0x40/0xc0 [] ? process_one_work+0x168/0x470 [] ? worker_thread+0x10b/0x390 [] ? manage_workers.isra.26+0x290/0x290 [] ? kthread+0xaf/0xc0 [] ? kthread_create_on_node+0x120/0x120 [] ? ret_from_fork+0x7c/0xb0 [] ? kthread_create_on_node+0x120/0x120 Fix this bug by removing the per-cpu definition. The structure ablkcipher_request is accessed via a pointer from convert_context. Consequently, if the work item is rescheduled to a different CPU, the thread still uses the same ablkcipher_request. This change may undermine performance improvements intended by commit c0297721 ("dm crypt: scale to multiple cpus") on select hardware. In practice no performance difference was observed on recent hardware. But regardless, correctness is more important than performance. Signed-off-by: Mikulas Patocka Signed-off-by: Mike Snitzer Cc: stable@vger.kernel.org --- drivers/md/dm-crypt.c | 61 ++++++++++----------------------------------------- 1 file changed, 12 insertions(+), 49 deletions(-) diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 784695d22fde..53b213226c01 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include @@ -43,6 +42,7 @@ struct convert_context { struct bvec_iter iter_out; sector_t cc_sector; atomic_t cc_pending; + struct ablkcipher_request *req; }; /* @@ -111,15 +111,7 @@ struct iv_tcw_private { enum flags { DM_CRYPT_SUSPENDED, DM_CRYPT_KEY_VALID }; /* - * Duplicated per-CPU state for cipher. - */ -struct crypt_cpu { - struct ablkcipher_request *req; -}; - -/* - * The fields in here must be read only after initialization, - * changing state should be in crypt_cpu. + * The fields in here must be read only after initialization. */ struct crypt_config { struct dm_dev *dev; @@ -150,12 +142,6 @@ struct crypt_config { sector_t iv_offset; unsigned int iv_size; - /* - * Duplicated per cpu state. Access through - * per_cpu_ptr() only. - */ - struct crypt_cpu __percpu *cpu; - /* ESSIV: struct crypto_cipher *essiv_tfm */ void *iv_private; struct crypto_ablkcipher **tfms; @@ -192,11 +178,6 @@ static void clone_init(struct dm_crypt_io *, struct bio *); static void kcryptd_queue_crypt(struct dm_crypt_io *io); static u8 *iv_of_dmreq(struct crypt_config *cc, struct dm_crypt_request *dmreq); -static struct crypt_cpu *this_crypt_config(struct crypt_config *cc) -{ - return this_cpu_ptr(cc->cpu); -} - /* * Use this to access cipher attributes that are the same for each CPU. */ @@ -903,16 +884,15 @@ static void kcryptd_async_done(struct crypto_async_request *async_req, static void crypt_alloc_req(struct crypt_config *cc, struct convert_context *ctx) { - struct crypt_cpu *this_cc = this_crypt_config(cc); unsigned key_index = ctx->cc_sector & (cc->tfms_count - 1); - if (!this_cc->req) - this_cc->req = mempool_alloc(cc->req_pool, GFP_NOIO); + if (!ctx->req) + ctx->req = mempool_alloc(cc->req_pool, GFP_NOIO); - ablkcipher_request_set_tfm(this_cc->req, cc->tfms[key_index]); - ablkcipher_request_set_callback(this_cc->req, + ablkcipher_request_set_tfm(ctx->req, cc->tfms[key_index]); + ablkcipher_request_set_callback(ctx->req, CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, - kcryptd_async_done, dmreq_of_req(cc, this_cc->req)); + kcryptd_async_done, dmreq_of_req(cc, ctx->req)); } /* @@ -921,7 +901,6 @@ static void crypt_alloc_req(struct crypt_config *cc, static int crypt_convert(struct crypt_config *cc, struct convert_context *ctx) { - struct crypt_cpu *this_cc = this_crypt_config(cc); int r; atomic_set(&ctx->cc_pending, 1); @@ -932,7 +911,7 @@ static int crypt_convert(struct crypt_config *cc, atomic_inc(&ctx->cc_pending); - r = crypt_convert_block(cc, ctx, this_cc->req); + r = crypt_convert_block(cc, ctx, ctx->req); switch (r) { /* async */ @@ -941,7 +920,7 @@ static int crypt_convert(struct crypt_config *cc, reinit_completion(&ctx->restart); /* fall through*/ case -EINPROGRESS: - this_cc->req = NULL; + ctx->req = NULL; ctx->cc_sector++; continue; @@ -1040,6 +1019,7 @@ static struct dm_crypt_io *crypt_io_alloc(struct crypt_config *cc, io->sector = sector; io->error = 0; io->base_io = NULL; + io->ctx.req = NULL; atomic_set(&io->io_pending, 0); return io; @@ -1065,6 +1045,8 @@ static void crypt_dec_pending(struct dm_crypt_io *io) if (!atomic_dec_and_test(&io->io_pending)) return; + if (io->ctx.req) + mempool_free(io->ctx.req, cc->req_pool); mempool_free(io, cc->io_pool); if (likely(!base_io)) @@ -1492,8 +1474,6 @@ static int crypt_wipe_key(struct crypt_config *cc) static void crypt_dtr(struct dm_target *ti) { struct crypt_config *cc = ti->private; - struct crypt_cpu *cpu_cc; - int cpu; ti->private = NULL; @@ -1505,13 +1485,6 @@ static void crypt_dtr(struct dm_target *ti) if (cc->crypt_queue) destroy_workqueue(cc->crypt_queue); - if (cc->cpu) - for_each_possible_cpu(cpu) { - cpu_cc = per_cpu_ptr(cc->cpu, cpu); - if (cpu_cc->req) - mempool_free(cpu_cc->req, cc->req_pool); - } - crypt_free_tfms(cc); if (cc->bs) @@ -1530,9 +1503,6 @@ static void crypt_dtr(struct dm_target *ti) if (cc->dev) dm_put_device(ti, cc->dev); - if (cc->cpu) - free_percpu(cc->cpu); - kzfree(cc->cipher); kzfree(cc->cipher_string); @@ -1588,13 +1558,6 @@ static int crypt_ctr_cipher(struct dm_target *ti, if (tmp) DMWARN("Ignoring unexpected additional cipher options"); - cc->cpu = __alloc_percpu(sizeof(*(cc->cpu)), - __alignof__(struct crypt_cpu)); - if (!cc->cpu) { - ti->error = "Cannot allocate per cpu state"; - goto bad_mem; - } - /* * For compatibility with the original dm-crypt mapping format, if * only the cipher name is supplied, use cbc-plain. -- cgit v1.2.3 From 8d07e8a5f5bc7b90f755d9b427ea930024f4c986 Mon Sep 17 00:00:00 2001 From: Joe Thornber Date: Tue, 6 May 2014 16:28:14 +0100 Subject: dm thin: allow metadata commit if pool is in PM_OUT_OF_DATA_SPACE mode Commit 3e1a0699 ("dm thin: fix out of data space handling") introduced a regression in the metadata commit() method by returning an error if the pool is in PM_OUT_OF_DATA_SPACE mode. This oversight caused a thin device to return errors even if the default queue_if_no_space ENOSPC handling mode is used. Fix commit() to only fail if pool is in PM_READ_ONLY or PM_FAIL mode. Reported-by: qindehua@163.com Signed-off-by: Joe Thornber Signed-off-by: Mike Snitzer Cc: stable@vger.kernel.org # 3.14+ --- drivers/md/dm-thin.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index 13abade76ad9..15f748ba6754 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c @@ -935,7 +935,7 @@ static int commit(struct pool *pool) { int r; - if (get_pool_mode(pool) != PM_WRITE) + if (get_pool_mode(pool) >= PM_READ_ONLY) return -EINVAL; r = dm_pool_commit_metadata(pool->pmd); -- cgit v1.2.3 From 85ad643b7e7e52d37620fb272a9fd577a8095647 Mon Sep 17 00:00:00 2001 From: Joe Thornber Date: Fri, 9 May 2014 15:59:38 +0100 Subject: dm thin: add timeout to stop out-of-data-space mode holding IO forever If the pool runs out of data space, dm-thin can be configured to either error IOs that would trigger provisioning, or hold those IOs until the pool is resized. Unfortunately, holding IOs until the pool is resized can result in a cascade of tasks hitting the hung_task_timeout, which may render the system unavailable. Add a fixed timeout so IOs can only be held for a maximum of 60 seconds. If LVM is going to resize a thin-pool that is out of data space it needs to be prompt about it. Signed-off-by: Joe Thornber Signed-off-by: Mike Snitzer Cc: stable@vger.kernel.org # 3.14+ --- drivers/md/dm-thin.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index 15f748ba6754..2e71de8e0048 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c @@ -27,6 +27,7 @@ #define MAPPING_POOL_SIZE 1024 #define PRISON_CELLS 1024 #define COMMIT_PERIOD HZ +#define NO_SPACE_TIMEOUT (HZ * 60) DECLARE_DM_KCOPYD_THROTTLE_WITH_MODULE_PARM(snapshot_copy_throttle, "A percentage of time allocated for copy on write"); @@ -175,6 +176,7 @@ struct pool { struct workqueue_struct *wq; struct work_struct worker; struct delayed_work waker; + struct delayed_work no_space_timeout; unsigned long last_commit_jiffies; unsigned ref_count; @@ -1590,6 +1592,20 @@ static void do_waker(struct work_struct *ws) queue_delayed_work(pool->wq, &pool->waker, COMMIT_PERIOD); } +/* + * We're holding onto IO to allow userland time to react. After the + * timeout either the pool will have been resized (and thus back in + * PM_WRITE mode), or we degrade to PM_READ_ONLY and start erroring IO. + */ +static void do_no_space_timeout(struct work_struct *ws) +{ + struct pool *pool = container_of(to_delayed_work(ws), struct pool, + no_space_timeout); + + if (get_pool_mode(pool) == PM_OUT_OF_DATA_SPACE && !pool->pf.error_if_no_space) + set_pool_mode(pool, PM_READ_ONLY); +} + /*----------------------------------------------------------------*/ struct noflush_work { @@ -1715,6 +1731,9 @@ static void set_pool_mode(struct pool *pool, enum pool_mode new_mode) pool->process_discard = process_discard; pool->process_prepared_mapping = process_prepared_mapping; pool->process_prepared_discard = process_prepared_discard_passdown; + + if (!pool->pf.error_if_no_space) + queue_delayed_work(pool->wq, &pool->no_space_timeout, NO_SPACE_TIMEOUT); break; case PM_WRITE: @@ -2100,6 +2119,7 @@ static struct pool *pool_create(struct mapped_device *pool_md, INIT_WORK(&pool->worker, do_worker); INIT_DELAYED_WORK(&pool->waker, do_waker); + INIT_DELAYED_WORK(&pool->no_space_timeout, do_no_space_timeout); spin_lock_init(&pool->lock); bio_list_init(&pool->deferred_flush_bios); INIT_LIST_HEAD(&pool->prepared_mappings); @@ -2662,6 +2682,7 @@ static void pool_postsuspend(struct dm_target *ti) struct pool *pool = pt->pool; cancel_delayed_work(&pool->waker); + cancel_delayed_work(&pool->no_space_timeout); flush_workqueue(pool->wq); (void) commit(pool); } -- cgit v1.2.3 From 4cdd2ad78098244c1bc9ec4374ea1c225fd1cd6f Mon Sep 17 00:00:00 2001 From: Mike Snitzer Date: Tue, 13 May 2014 13:49:39 -0400 Subject: dm mpath: fix lock order inconsistency in multipath_ioctl Commit 3e9f1be1b40 ("dm mpath: remove process_queued_ios()") did not consistently take the multipath device's spinlock (m->lock) before calling dm_table_run_md_queue_async() -- which takes the q->queue_lock. Found with code inspection using hint from reported lockdep warning. Reported-by: Bart Van Assche Signed-off-by: Mike Snitzer --- drivers/md/dm-mpath.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index aa009e865871..fa0f6cbd6a41 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c @@ -1566,8 +1566,8 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd, } if (m->pg_init_required) __pg_init_all_paths(m); - spin_unlock_irqrestore(&m->lock, flags); dm_table_run_md_queue_async(m->ti->table); + spin_unlock_irqrestore(&m->lock, flags); } return r ? : __blkdev_driver_ioctl(bdev, mode, cmd, arg); -- cgit v1.2.3 From 2425ce84026c385b73ae72039f90d042d49e0394 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Thu, 8 May 2014 15:51:37 -0400 Subject: metag: fix memory barriers Volatile access doesn't really imply the compiler barrier. Volatile access is only ordered with respect to other volatile accesses, it isn't ordered with respect to general memory accesses. Gcc may reorder memory accesses around volatile access, as we can see in this simple example (if we compile it with optimization, both increments of *b will be collapsed to just one): void fn(volatile int *a, long *b) { (*b)++; *a = 10; (*b)++; } Consequently, we need the compiler barrier after a write to the volatile variable, to make sure that the compiler doesn't reorder the volatile write with something else. Signed-off-by: Mikulas Patocka Cc: stable@vger.kernel.org Acked-by: Peter Zijlstra Signed-off-by: James Hogan --- arch/metag/include/asm/barrier.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/metag/include/asm/barrier.h b/arch/metag/include/asm/barrier.h index 5d6b4b407dda..2d6f0de77325 100644 --- a/arch/metag/include/asm/barrier.h +++ b/arch/metag/include/asm/barrier.h @@ -15,6 +15,7 @@ static inline void wr_fence(void) volatile int *flushptr = (volatile int *) LINSYSEVENT_WR_FENCE; barrier(); *flushptr = 0; + barrier(); } #else /* CONFIG_METAG_META21 */ @@ -35,6 +36,7 @@ static inline void wr_fence(void) *flushptr = 0; *flushptr = 0; *flushptr = 0; + barrier(); } #endif /* !CONFIG_METAG_META21 */ @@ -68,6 +70,7 @@ static inline void fence(void) volatile int *flushptr = (volatile int *) LINSYSEVENT_WR_ATOMIC_UNLOCK; barrier(); *flushptr = 0; + barrier(); } #define smp_mb() fence() #define smp_rmb() fence() -- cgit v1.2.3 From d71f290b4e98a39f49f2595a13be3b4d5ce8e1f1 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Tue, 13 May 2014 23:58:24 +0100 Subject: metag: Reduce maximum stack size to 256MB Specify the maximum stack size for arches where the stack grows upward (parisc and metag) in asm/processor.h rather than hard coding in fs/exec.c so that metag can specify a smaller value of 256MB rather than 1GB. This fixes a BUG on metag if the RLIMIT_STACK hard limit is increased beyond a safe value by root. E.g. when starting a process after running "ulimit -H -s unlimited" it will then attempt to use a stack size of the maximum 1GB which is far too big for metag's limited user virtual address space (stack_top is usually 0x3ffff000): BUG: failure at fs/exec.c:589/shift_arg_pages()! Signed-off-by: James Hogan Cc: Helge Deller Cc: "James E.J. Bottomley" Cc: linux-parisc@vger.kernel.org Cc: linux-metag@vger.kernel.org Cc: John David Anglin Cc: stable@vger.kernel.org # only needed for >= v3.9 (arch/metag) --- arch/metag/include/asm/processor.h | 2 ++ arch/parisc/include/asm/processor.h | 2 ++ fs/exec.c | 6 +++--- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/arch/metag/include/asm/processor.h b/arch/metag/include/asm/processor.h index f16477d1f571..3be8581af495 100644 --- a/arch/metag/include/asm/processor.h +++ b/arch/metag/include/asm/processor.h @@ -22,6 +22,8 @@ /* Add an extra page of padding at the top of the stack for the guard page. */ #define STACK_TOP (TASK_SIZE - PAGE_SIZE) #define STACK_TOP_MAX STACK_TOP +/* Maximum virtual space for stack */ +#define STACK_SIZE_MAX (1 << 28) /* 256 MB */ /* This decides where the kernel will search for a free chunk of vm * space during mmap's. diff --git a/arch/parisc/include/asm/processor.h b/arch/parisc/include/asm/processor.h index 198a86feb574..86522ef09d52 100644 --- a/arch/parisc/include/asm/processor.h +++ b/arch/parisc/include/asm/processor.h @@ -55,6 +55,8 @@ #define STACK_TOP TASK_SIZE #define STACK_TOP_MAX DEFAULT_TASK_SIZE +#define STACK_SIZE_MAX (1 << 30) /* 1 GB */ + #endif #ifndef __ASSEMBLY__ diff --git a/fs/exec.c b/fs/exec.c index 476f3ebf437e..238b7aa26f68 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -657,10 +657,10 @@ int setup_arg_pages(struct linux_binprm *bprm, unsigned long rlim_stack; #ifdef CONFIG_STACK_GROWSUP - /* Limit stack size to 1GB */ + /* Limit stack size */ stack_base = rlimit_max(RLIMIT_STACK); - if (stack_base > (1 << 30)) - stack_base = 1 << 30; + if (stack_base > STACK_SIZE_MAX) + stack_base = STACK_SIZE_MAX; /* Make sure we didn't let the argument array grow too large. */ if (vma->vm_end - vma->vm_start > stack_base) -- cgit v1.2.3 From 042d27acb64924a0e8a43e972485913a32407beb Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Wed, 30 Apr 2014 23:26:02 +0200 Subject: parisc,metag: Do not hardcode maximum userspace stack size This patch affects only architectures where the stack grows upwards (currently parisc and metag only). On those do not hardcode the maximum initial stack size to 1GB for 32-bit processes, but make it configurable via a config option. The main problem with the hardcoded stack size is, that we have two memory regions which grow upwards: stack and heap. To keep most of the memory available for heap in a flexmap memory layout, it makes no sense to hard allocate up to 1GB of the memory for stack which can't be used as heap then. This patch makes the stack size for 32-bit processes configurable and uses 80MB as default value which has been in use during the last few years on parisc and which hasn't showed any problems yet. Signed-off-by: Helge Deller Signed-off-by: James Hogan Cc: "James E.J. Bottomley" Cc: linux-parisc@vger.kernel.org Cc: linux-metag@vger.kernel.org Cc: John David Anglin --- arch/metag/include/asm/processor.h | 2 +- arch/parisc/include/asm/processor.h | 5 ++++- arch/parisc/kernel/sys_parisc.c | 6 +++--- mm/Kconfig | 15 +++++++++++++++ 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/arch/metag/include/asm/processor.h b/arch/metag/include/asm/processor.h index 3be8581af495..a8a37477c66e 100644 --- a/arch/metag/include/asm/processor.h +++ b/arch/metag/include/asm/processor.h @@ -23,7 +23,7 @@ #define STACK_TOP (TASK_SIZE - PAGE_SIZE) #define STACK_TOP_MAX STACK_TOP /* Maximum virtual space for stack */ -#define STACK_SIZE_MAX (1 << 28) /* 256 MB */ +#define STACK_SIZE_MAX (CONFIG_MAX_STACK_SIZE_MB*1024*1024) /* This decides where the kernel will search for a free chunk of vm * space during mmap's. diff --git a/arch/parisc/include/asm/processor.h b/arch/parisc/include/asm/processor.h index 86522ef09d52..d951c9681ab3 100644 --- a/arch/parisc/include/asm/processor.h +++ b/arch/parisc/include/asm/processor.h @@ -55,7 +55,10 @@ #define STACK_TOP TASK_SIZE #define STACK_TOP_MAX DEFAULT_TASK_SIZE -#define STACK_SIZE_MAX (1 << 30) /* 1 GB */ +/* Allow bigger stacks for 64-bit processes */ +#define STACK_SIZE_MAX (USER_WIDE_MODE \ + ? (1 << 30) /* 1 GB */ \ + : (CONFIG_MAX_STACK_SIZE_MB*1024*1024)) #endif diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c index 31ffa9b55322..e1ffea2f9a0b 100644 --- a/arch/parisc/kernel/sys_parisc.c +++ b/arch/parisc/kernel/sys_parisc.c @@ -72,10 +72,10 @@ static unsigned long mmap_upper_limit(void) { unsigned long stack_base; - /* Limit stack size to 1GB - see setup_arg_pages() in fs/exec.c */ + /* Limit stack size - see setup_arg_pages() in fs/exec.c */ stack_base = rlimit_max(RLIMIT_STACK); - if (stack_base > (1 << 30)) - stack_base = 1 << 30; + if (stack_base > STACK_SIZE_MAX) + stack_base = STACK_SIZE_MAX; return PAGE_ALIGN(STACK_TOP - stack_base); } diff --git a/mm/Kconfig b/mm/Kconfig index ebe5880c29d6..1b5a95f0fa01 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -581,3 +581,18 @@ config PGTABLE_MAPPING config GENERIC_EARLY_IOREMAP bool + +config MAX_STACK_SIZE_MB + int "Maximum user stack size for 32-bit processes (MB)" + default 80 + range 8 256 if METAG + range 8 2048 + depends on STACK_GROWSUP && (!64BIT || COMPAT) + help + This is the maximum stack size in Megabytes in the VM layout of 32-bit + user processes when the stack grows upwards (currently only on parisc + and metag arch). The stack will be located at the highest memory + address minus the given value, unless the RLIMIT_STACK hard limit is + changed to a smaller value in which case that is used. + + A sane initial value is 80 MB. -- cgit v1.2.3 From 43ec1460a2189fbee87980dd3d3e64cba2f11e1f Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Thu, 15 May 2014 09:21:11 +1000 Subject: xfs: xfs_dir_fsync() returns positive errno And it should be negative. Signed-off-by: Dave Chinner Reviewed-by: Jie Liu Signed-off-by: Dave Chinner --- fs/xfs/xfs_file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 951a2321ee01..f499e47d44d8 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -155,7 +155,7 @@ xfs_dir_fsync( if (!lsn) return 0; - return _xfs_log_force_lsn(mp, lsn, XFS_LOG_SYNC, NULL); + return -_xfs_log_force_lsn(mp, lsn, XFS_LOG_SYNC, NULL); } STATIC int -- cgit v1.2.3 From 8ff1e6705a4c711247708f23881feea169e6fc3c Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Thu, 15 May 2014 09:21:37 +1000 Subject: xfs: fix incorrect error sign in xfs_file_aio_read Signed-off-by: Dave Chinner Reviewed-by: Jie Liu Signed-off-by: Dave Chinner --- fs/xfs/xfs_file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index f499e47d44d8..37f98c6d81aa 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -295,7 +295,7 @@ xfs_file_aio_read( xfs_rw_ilock(ip, XFS_IOLOCK_EXCL); if (inode->i_mapping->nrpages) { - ret = -filemap_write_and_wait_range( + ret = filemap_write_and_wait_range( VFS_I(ip)->i_mapping, pos, -1); if (ret) { -- cgit v1.2.3 From b38a134b22fbd0bed90f3e079bbf8cb2962a52be Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Thu, 15 May 2014 09:21:52 +1000 Subject: xfs: xfs_commit_metadata returns wrong errno Invert it. Signed-off-by: Dave Chinner Reviewed-by: Jie Liu Signed-off-by: Dave Chinner --- fs/xfs/xfs_export.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/xfs/xfs_export.c b/fs/xfs/xfs_export.c index 1399e187d425..753e467aa1a5 100644 --- a/fs/xfs/xfs_export.c +++ b/fs/xfs/xfs_export.c @@ -237,7 +237,7 @@ xfs_fs_nfs_commit_metadata( if (!lsn) return 0; - return _xfs_log_force_lsn(mp, lsn, XFS_LOG_SYNC, NULL); + return -_xfs_log_force_lsn(mp, lsn, XFS_LOG_SYNC, NULL); } const struct export_operations xfs_export_operations = { -- cgit v1.2.3 From 65149e3fab7f053396d09a429085f3071fa50825 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Thu, 15 May 2014 09:22:07 +1000 Subject: xfs: correct error sign on COLLAPSE_RANGE errors Signed-off-by: Dave Chinner Reviewed-by: Jie Liu Signed-off-by: Dave Chinner --- fs/xfs/xfs_file.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 37f98c6d81aa..830c1c937b88 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -837,7 +837,7 @@ xfs_file_fallocate( unsigned blksize_mask = (1 << inode->i_blkbits) - 1; if (offset & blksize_mask || len & blksize_mask) { - error = -EINVAL; + error = EINVAL; goto out_unlock; } @@ -846,7 +846,7 @@ xfs_file_fallocate( * in which case it is effectively a truncate operation */ if (offset + len >= i_size_read(inode)) { - error = -EINVAL; + error = EINVAL; goto out_unlock; } -- cgit v1.2.3 From a5a14de22e8afd771775c7106b3b081c23bac783 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Thu, 15 May 2014 09:22:21 +1000 Subject: xfs: fix wrong errno from xfs_initxattrs Signed-off-by: Dave Chinner Reviewed-by: Jie Liu Signed-off-by: Dave Chinner --- fs/xfs/xfs_iops.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index 301ecbfcc0be..adfb18e19992 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -72,8 +72,8 @@ xfs_initxattrs( int error = 0; for (xattr = xattr_array; xattr->name != NULL; xattr++) { - error = xfs_attr_set(ip, xattr->name, xattr->value, - xattr->value_len, ATTR_SECURE); + error = -xfs_attr_set(ip, xattr->name, xattr->value, + xattr->value_len, ATTR_SECURE); if (error < 0) break; } @@ -93,8 +93,8 @@ xfs_init_security( struct inode *dir, const struct qstr *qstr) { - return security_inode_init_security(inode, dir, qstr, - &xfs_initxattrs, NULL); + return -security_inode_init_security(inode, dir, qstr, + &xfs_initxattrs, NULL); } static void -- cgit v1.2.3 From 6670232b48848e5ad949dbd4866850aec7035f32 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Thu, 15 May 2014 09:22:37 +1000 Subject: xfs: fix wrong err sign on xfs_set_acl() Signed-off-by: Dave Chinner Reviewed-by: Jie Liu Signed-off-by: Dave Chinner --- fs/xfs/xfs_iops.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index adfb18e19992..36d630319a27 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -173,12 +173,12 @@ xfs_generic_create( #ifdef CONFIG_XFS_POSIX_ACL if (default_acl) { - error = xfs_set_acl(inode, default_acl, ACL_TYPE_DEFAULT); + error = -xfs_set_acl(inode, default_acl, ACL_TYPE_DEFAULT); if (error) goto out_cleanup_inode; } if (acl) { - error = xfs_set_acl(inode, acl, ACL_TYPE_ACCESS); + error = -xfs_set_acl(inode, acl, ACL_TYPE_ACCESS); if (error) goto out_cleanup_inode; } -- cgit v1.2.3 From 45687642e43d5a3b700d6c1df0e07b3976c90c08 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Thu, 15 May 2014 09:22:53 +1000 Subject: xfs: negate mount workqueue init error value Signed-off-by: Dave Chinner Reviewed-by: Jie Liu Signed-off-by: Dave Chinner --- fs/xfs/xfs_super.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index 205376776377..e1597f2e58da 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -1433,7 +1433,7 @@ xfs_fs_fill_super( if (error) goto out_free_fsname; - error = xfs_init_mount_workqueues(mp); + error = -xfs_init_mount_workqueues(mp); if (error) goto out_close_devices; -- cgit v1.2.3 From bc147822d5ada188fff792691efffe89589e2e19 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Thu, 15 May 2014 09:23:07 +1000 Subject: xfs: negate xfs_icsb_init_counters error value Signed-off-by: Dave Chinner Reviewed-by: Jie Liu Signed-off-by: Dave Chinner --- fs/xfs/xfs_super.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index e1597f2e58da..3494eff8e4eb 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -1437,7 +1437,7 @@ xfs_fs_fill_super( if (error) goto out_close_devices; - error = xfs_icsb_init_counters(mp); + error = -xfs_icsb_init_counters(mp); if (error) goto out_destroy_workqueues; -- cgit v1.2.3 From ee4eec478be4677b93775d17bc079efb5922b276 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Thu, 15 May 2014 09:23:24 +1000 Subject: xfs: list_lru_init returns a negative error And we don't invert it properly when initialising the dquot lru list. Signed-off-by: Dave Chinner Reviewed-by: Jie Liu Signed-off-by: Dave Chinner --- fs/xfs/xfs_qm.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c index 348e4d2ed6e6..dc977b6e6a36 100644 --- a/fs/xfs/xfs_qm.c +++ b/fs/xfs/xfs_qm.c @@ -843,22 +843,17 @@ xfs_qm_init_quotainfo( qinf = mp->m_quotainfo = kmem_zalloc(sizeof(xfs_quotainfo_t), KM_SLEEP); - if ((error = list_lru_init(&qinf->qi_lru))) { - kmem_free(qinf); - mp->m_quotainfo = NULL; - return error; - } + error = -list_lru_init(&qinf->qi_lru); + if (error) + goto out_free_qinf; /* * See if quotainodes are setup, and if not, allocate them, * and change the superblock accordingly. */ - if ((error = xfs_qm_init_quotainos(mp))) { - list_lru_destroy(&qinf->qi_lru); - kmem_free(qinf); - mp->m_quotainfo = NULL; - return error; - } + error = xfs_qm_init_quotainos(mp); + if (error) + goto out_free_lru; INIT_RADIX_TREE(&qinf->qi_uquota_tree, GFP_NOFS); INIT_RADIX_TREE(&qinf->qi_gquota_tree, GFP_NOFS); @@ -918,7 +913,7 @@ xfs_qm_init_quotainfo( qinf->qi_isoftlimit = be64_to_cpu(ddqp->d_ino_softlimit); qinf->qi_rtbhardlimit = be64_to_cpu(ddqp->d_rtb_hardlimit); qinf->qi_rtbsoftlimit = be64_to_cpu(ddqp->d_rtb_softlimit); - + xfs_qm_dqdestroy(dqp); } else { qinf->qi_btimelimit = XFS_QM_BTIMELIMIT; @@ -935,6 +930,13 @@ xfs_qm_init_quotainfo( qinf->qi_shrinker.flags = SHRINKER_NUMA_AWARE; register_shrinker(&qinf->qi_shrinker); return 0; + +out_free_lru: + list_lru_destroy(&qinf->qi_lru); +out_free_qinf: + kmem_free(qinf); + mp->m_quotainfo = NULL; + return error; } -- cgit v1.2.3 From c70458f50cd4271410aa75011f56ffabc0e2d34a Mon Sep 17 00:00:00 2001 From: James Hogan Date: Thu, 1 May 2014 12:31:14 +0100 Subject: metag: Remove _STK_LIM_MAX override Meta overrode _STK_LIM_MAX (the default RLIMIT_STACK hard limit) to 256MB, apparently in an attempt to prevent setup_arg_pages's STACK_GROWSUP code from choosing the maximum stack size of 1GB, which is far too large for Meta's limited virtual address space and hits a BUG_ON (stack_top is usually 0x3ffff000). However the commit "metag: Reduce maximum stack size to 256MB" reduces the absolute stack size limit to a safe value for metag. This allows the default _STK_LIM_MAX override to be removed, bringing the default behaviour in line with all other architectures. Parisc in particular recently removed their override of _STK_LIMT_MAX in commit e0d8898d76a7 (parisc: remove _STK_LIM_MAX override) since it subtly affects stack allocation semantics in userland. Meta's uapi/asm/resource.h can now be removed and switch to using generic-y. Suggested-by: Helge Deller Signed-off-by: James Hogan Cc: linux-metag@vger.kernel.org Cc: John David Anglin --- arch/metag/include/uapi/asm/Kbuild | 2 +- arch/metag/include/uapi/asm/resource.h | 7 ------- 2 files changed, 1 insertion(+), 8 deletions(-) delete mode 100644 arch/metag/include/uapi/asm/resource.h diff --git a/arch/metag/include/uapi/asm/Kbuild b/arch/metag/include/uapi/asm/Kbuild index 84e09feb4d54..ab78be2b6eb0 100644 --- a/arch/metag/include/uapi/asm/Kbuild +++ b/arch/metag/include/uapi/asm/Kbuild @@ -4,11 +4,11 @@ include include/uapi/asm-generic/Kbuild.asm header-y += byteorder.h header-y += ech.h header-y += ptrace.h -header-y += resource.h header-y += sigcontext.h header-y += siginfo.h header-y += swab.h header-y += unistd.h generic-y += mman.h +generic-y += resource.h generic-y += setup.h diff --git a/arch/metag/include/uapi/asm/resource.h b/arch/metag/include/uapi/asm/resource.h deleted file mode 100644 index 526d23cc3054..000000000000 --- a/arch/metag/include/uapi/asm/resource.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef _UAPI_METAG_RESOURCE_H -#define _UAPI_METAG_RESOURCE_H - -#define _STK_LIM_MAX (1 << 28) -#include - -#endif /* _UAPI_METAG_RESOURCE_H */ -- cgit v1.2.3 From ffe6902b66aaa4ca6694bc19639259c16d84ddb1 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Thu, 1 May 2014 15:05:07 +0100 Subject: asm-generic: remove _STK_LIM_MAX _STK_LIM_MAX could be used to override the RLIMIT_STACK hard limit from an arch's include/uapi/asm-generic/resource.h file, but is no longer used since both parisc and metag removed the override. Therefore remove it entirely, setting the hard RLIMIT_STACK limit to RLIM_INFINITY directly in include/asm-generic/resource.h. Signed-off-by: James Hogan Cc: Arnd Bergmann Cc: linux-arch@vger.kernel.org Cc: Helge Deller Cc: John David Anglin --- include/asm-generic/resource.h | 2 +- include/uapi/asm-generic/resource.h | 7 ------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/include/asm-generic/resource.h b/include/asm-generic/resource.h index b4ea8f50fc65..5e752b959054 100644 --- a/include/asm-generic/resource.h +++ b/include/asm-generic/resource.h @@ -12,7 +12,7 @@ [RLIMIT_CPU] = { RLIM_INFINITY, RLIM_INFINITY }, \ [RLIMIT_FSIZE] = { RLIM_INFINITY, RLIM_INFINITY }, \ [RLIMIT_DATA] = { RLIM_INFINITY, RLIM_INFINITY }, \ - [RLIMIT_STACK] = { _STK_LIM, _STK_LIM_MAX }, \ + [RLIMIT_STACK] = { _STK_LIM, RLIM_INFINITY }, \ [RLIMIT_CORE] = { 0, RLIM_INFINITY }, \ [RLIMIT_RSS] = { RLIM_INFINITY, RLIM_INFINITY }, \ [RLIMIT_NPROC] = { 0, 0 }, \ diff --git a/include/uapi/asm-generic/resource.h b/include/uapi/asm-generic/resource.h index f863428796d5..c6d10af50123 100644 --- a/include/uapi/asm-generic/resource.h +++ b/include/uapi/asm-generic/resource.h @@ -57,12 +57,5 @@ # define RLIM_INFINITY (~0UL) #endif -/* - * RLIMIT_STACK default maximum - some architectures override it: - */ -#ifndef _STK_LIM_MAX -# define _STK_LIM_MAX RLIM_INFINITY -#endif - #endif /* _UAPI_ASM_GENERIC_RESOURCE_H */ -- cgit v1.2.3 From fa81511bb0bbb2b1aace3695ce869da9762624ff Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 14 May 2014 16:33:54 -0700 Subject: x86-64, modify_ldt: Make support for 16-bit segments a runtime option Checkin: b3b42ac2cbae x86-64, modify_ldt: Ban 16-bit segments on 64-bit kernels disabled 16-bit segments on 64-bit kernels due to an information leak. However, it does seem that people are genuinely using Wine to run old 16-bit Windows programs on Linux. A proper fix for this ("espfix64") is coming in the upcoming merge window, but as a temporary fix, create a sysctl to allow the administrator to re-enable support for 16-bit segments. It adds a "/proc/sys/abi/ldt16" sysctl that defaults to zero (off). If you hit this issue and care about your old Windows program more than you care about a kernel stack address information leak, you can do echo 1 > /proc/sys/abi/ldt16 as root (add it to your startup scripts), and you should be ok. The sysctl table is only added if you have COMPAT support enabled on x86-64, but I assume anybody who runs old windows binaries very much does that ;) Signed-off-by: H. Peter Anvin Link: http://lkml.kernel.org/r/CA%2B55aFw9BPoD10U1LfHbOMpHWZkvJTkMcfCs9s3urPr1YyWBxw@mail.gmail.com Cc: --- arch/x86/kernel/ldt.c | 4 +++- arch/x86/vdso/vdso32-setup.c | 8 ++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/ldt.c b/arch/x86/kernel/ldt.c index af1d14a9ebda..dcbbaa165bde 100644 --- a/arch/x86/kernel/ldt.c +++ b/arch/x86/kernel/ldt.c @@ -20,6 +20,8 @@ #include #include +int sysctl_ldt16 = 0; + #ifdef CONFIG_SMP static void flush_ldt(void *current_mm) { @@ -234,7 +236,7 @@ static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode) * IRET leaking the high bits of the kernel stack address. */ #ifdef CONFIG_X86_64 - if (!ldt_info.seg_32bit) { + if (!ldt_info.seg_32bit && !sysctl_ldt16) { error = -EINVAL; goto out_unlock; } diff --git a/arch/x86/vdso/vdso32-setup.c b/arch/x86/vdso/vdso32-setup.c index 00348980a3a6..e1f220e3ca68 100644 --- a/arch/x86/vdso/vdso32-setup.c +++ b/arch/x86/vdso/vdso32-setup.c @@ -39,6 +39,7 @@ #ifdef CONFIG_X86_64 #define vdso_enabled sysctl_vsyscall32 #define arch_setup_additional_pages syscall32_setup_pages +extern int sysctl_ldt16; #endif /* @@ -249,6 +250,13 @@ static struct ctl_table abi_table2[] = { .mode = 0644, .proc_handler = proc_dointvec }, + { + .procname = "ldt16", + .data = &sysctl_ldt16, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec + }, {} }; -- cgit v1.2.3 From f4cdbc21444a45d207a8dc175f44d2facfbd0845 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 14 May 2014 13:02:19 +0300 Subject: drm/i915/dp: force eDP lane count to max available lanes on BDW There are certain BDW high res eDP machines that regressed due to commit 38aecea0ccbb909d635619cba22f1891e589b434 Author: Daniel Vetter Date: Mon Mar 3 11:18:10 2014 +0100 drm/i915: reverse dp link param selection, prefer fast over wide again The commit lead to 2 lanes at 5.4 Gbps being used instead of 4 lanes at 2.7 Gbps on the affected machines. Link training succeeded for both, but the screen remained blank with the former config. Further investigation showed that 4 lanes at 5.4 Gbps worked also. The root cause for the blank screen using 2 lanes remains unknown, but apparently the driver for a certain other operating system by default uses the max available lanes. Follow suit on Broadwell eDP, for at least until we figure out what is going on. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=76711 Reviewed-by: Daniel Vetter Reviewed-by: Rodrigo Vivi Tested-by: Rodrigo Vivi Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_dp.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 8233f2aea665..2a00cb828d20 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -810,7 +810,12 @@ intel_dp_compute_config(struct intel_encoder *encoder, bpp = dev_priv->vbt.edp_bpp; } - if (dev_priv->vbt.edp_lanes) { + if (IS_BROADWELL(dev)) { + /* Yes, it's an ugly hack. */ + min_lane_count = max_lane_count; + DRM_DEBUG_KMS("forcing lane count to max (%u) on BDW\n", + min_lane_count); + } else if (dev_priv->vbt.edp_lanes) { min_lane_count = min(dev_priv->vbt.edp_lanes, max_lane_count); DRM_DEBUG_KMS("using min %u lanes per VBT\n", -- cgit v1.2.3 From afba0b5a221c0dacbbdf3a778d539fbc90fc6191 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 13 May 2014 16:07:37 +0100 Subject: drm/i915: Use the first mode if there is no preferred mode in the EDID This matches the algorithm used by earlier kernels when selecting the mode for the fbcon. And only if there is no modes at all, do we fall back to using the BIOS configuration. Seamless transition is still preserved (from the BIOS configuration to ours) so long as the BIOS has also chosen what we hope is the native configuration. Reported-by: Knut Petersen Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=78655 Reviewed-by: Jesse Barnes Tested-by: Knut Petersen Signed-off-by: Chris Wilson [Jani: applied Chris' "Please imagine that I wrote this correctly."] Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_fbdev.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index fce4a0d93c0b..f73ba5e6b7a8 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@ -387,6 +387,15 @@ static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper, height); } + /* No preferred mode marked by the EDID? Are there any modes? */ + if (!modes[i] && !list_empty(&connector->modes)) { + DRM_DEBUG_KMS("using first mode listed on connector %s\n", + drm_get_connector_name(connector)); + modes[i] = list_first_entry(&connector->modes, + struct drm_display_mode, + head); + } + /* last resort: use current mode */ if (!modes[i]) { /* -- cgit v1.2.3 From 721e82c08c1afd6b47367b0e0c4a62140b0667f3 Mon Sep 17 00:00:00 2001 From: Aaron Lu Date: Mon, 12 May 2014 16:55:45 +0800 Subject: drm/i915: restore backlight precision when converting from ACPI When we set backlight on behalf of ACPI opregion, we will convert the backlight value in the 0-255 range defined in opregion to the actual hardware level. Commit 22505b82a2 (drm/i915: avoid brightness overflow when doing scale) is meant to fix the overflow problem when doing the conversion, but it also caused a problem that the converted hardware level doesn't quite represent the intended value: say user wants maximum backlight level(255 in opregion's range), then we will calculate the actual hardware level to be: level = freq / max * level, where freq is the hardware's max backlight level(937 on an user's box), and max and level are all 255. The converted value should be 937 but the above calculation will yield 765. To fix this issue, just use 64 bits to do the calculation to keep the precision and avoid overflow at the same time. Buglink: https://bugzilla.kernel.org/show_bug.cgi?id=72491 Reported-by: Nico Schottelius Reviewed-by: Chris Wilson Cc: stable@vger.kernel.org Signed-off-by: Aaron Lu Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_panel.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 0eead16aeda7..cb8cfb7e0974 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -492,6 +492,7 @@ void intel_panel_set_backlight(struct intel_connector *connector, u32 level, enum pipe pipe = intel_get_pipe_from_connector(connector); u32 freq; unsigned long flags; + u64 n; if (!panel->backlight.present || pipe == INVALID_PIPE) return; @@ -502,10 +503,9 @@ void intel_panel_set_backlight(struct intel_connector *connector, u32 level, /* scale to hardware max, but be careful to not overflow */ freq = panel->backlight.max; - if (freq < max) - level = level * freq / max; - else - level = freq / max * level; + n = (u64)level * freq; + do_div(n, max); + level = n; panel->backlight.level = level; if (panel->backlight.device) -- cgit v1.2.3 From ebc3226202d5956a5963185222982d435378b899 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Fri, 9 May 2014 15:00:46 +0200 Subject: KVM: s390: announce irqfd capability s390 has acquired irqfd support with commit "KVM: s390: irq routing for adapter interrupts" (84223598778ba08041f4297fda485df83414d57e) but failed to announce it. Let's fix that. Signed-off-by: Cornelia Huck Acked-by: Christian Borntraeger Signed-off-by: Christian Borntraeger --- Documentation/virtual/kvm/api.txt | 2 +- arch/s390/kvm/kvm-s390.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt index a9380ba54c8e..b4f53653c106 100644 --- a/Documentation/virtual/kvm/api.txt +++ b/Documentation/virtual/kvm/api.txt @@ -2126,7 +2126,7 @@ into the hash PTE second double word). 4.75 KVM_IRQFD Capability: KVM_CAP_IRQFD -Architectures: x86 +Architectures: x86 s390 Type: vm ioctl Parameters: struct kvm_irqfd (in) Returns: 0 on success, -1 on error diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index b3ecb8f5b6ce..9ae6664ff08c 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -158,6 +158,7 @@ int kvm_dev_ioctl_check_extension(long ext) case KVM_CAP_ONE_REG: case KVM_CAP_ENABLE_CAP: case KVM_CAP_S390_CSS_SUPPORT: + case KVM_CAP_IRQFD: case KVM_CAP_IOEVENTFD: case KVM_CAP_DEVICE_CTRL: case KVM_CAP_ENABLE_CAP_VM: -- cgit v1.2.3 From e95a2f7509f5219177d6821a0a8754f93892ca56 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 8 May 2014 15:09:19 +0300 Subject: drm/i915: Increase WM memory latency values on SNB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On SNB the BIOS provided WM memory latency values seem insufficient to handle high resolution displays. In this particular case the display mode was a 2560x1440@60Hz, which makes the pixel clock 241.5 MHz. It was empirically found that a memory latency value if 1.2 usec is enough to avoid underruns, whereas the BIOS provided value of 0.7 usec was clearly too low. Incidentally 1.2 usec is what the typical BIOS provided values are on IVB systems. Increase the WM memory latency values to at least 1.2 usec on SNB. Hopefully this won't have a significant effect on power consumption. v2: Increase the latency values regardless of the pixel clock Cc: Robert N Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=70254 Tested-by: Robert Navarro Tested-by: Vitaly Minko Cc: stable@vger.kernel.org Signed-off-by: Ville Syrjälä Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_pm.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 19e94c3edc19..d93dcf683e8c 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2095,6 +2095,43 @@ static void intel_print_wm_latency(struct drm_device *dev, } } +static bool ilk_increase_wm_latency(struct drm_i915_private *dev_priv, + uint16_t wm[5], uint16_t min) +{ + int level, max_level = ilk_wm_max_level(dev_priv->dev); + + if (wm[0] >= min) + return false; + + wm[0] = max(wm[0], min); + for (level = 1; level <= max_level; level++) + wm[level] = max_t(uint16_t, wm[level], DIV_ROUND_UP(min, 5)); + + return true; +} + +static void snb_wm_latency_quirk(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + bool changed; + + /* + * The BIOS provided WM memory latency values are often + * inadequate for high resolution displays. Adjust them. + */ + changed = ilk_increase_wm_latency(dev_priv, dev_priv->wm.pri_latency, 12) | + ilk_increase_wm_latency(dev_priv, dev_priv->wm.spr_latency, 12) | + ilk_increase_wm_latency(dev_priv, dev_priv->wm.cur_latency, 12); + + if (!changed) + return; + + DRM_DEBUG_KMS("WM latency values increased to avoid potential underruns\n"); + intel_print_wm_latency(dev, "Primary", dev_priv->wm.pri_latency); + intel_print_wm_latency(dev, "Sprite", dev_priv->wm.spr_latency); + intel_print_wm_latency(dev, "Cursor", dev_priv->wm.cur_latency); +} + static void ilk_setup_wm_latency(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -2112,6 +2149,9 @@ static void ilk_setup_wm_latency(struct drm_device *dev) intel_print_wm_latency(dev, "Primary", dev_priv->wm.pri_latency); intel_print_wm_latency(dev, "Sprite", dev_priv->wm.spr_latency); intel_print_wm_latency(dev, "Cursor", dev_priv->wm.cur_latency); + + if (IS_GEN6(dev)) + snb_wm_latency_quirk(dev); } static void ilk_compute_wm_parameters(struct drm_crtc *crtc, -- cgit v1.2.3 From 4c358e15553ed88bf2ddae422624624e1dd663d1 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Thu, 15 May 2014 14:44:30 +1000 Subject: of: fix CONFIG_OF=n prototype of of_node_full_name() Make the CONFIG_OF=n prototpe of of_node_full_name() mateh the CONFIG_OF=y version. Fixes compile warnings like this: sound/soc/soc-core.c: In function 'soc_check_aux_dev': sound/soc/soc-core.c:1667:3: warning: passing argument 1 of 'of_node_full_name' discards 'const' qualifier from pointer target type [enabled by default] codecname = of_node_full_name(aux_dev->codec_of_node); when CONFIG_OF is not defined. Signed-off-by: Stephen Rothwell Signed-off-by: Grant Likely --- include/linux/of.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/of.h b/include/linux/of.h index 3bad8d106e0e..e6f0988c1c68 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -349,7 +349,7 @@ int of_device_is_stdout_path(struct device_node *dn); #else /* CONFIG_OF */ -static inline const char* of_node_full_name(struct device_node *np) +static inline const char* of_node_full_name(const struct device_node *np) { return ""; } -- cgit v1.2.3 From 3b084e99a3fabaeb0f9c65a0806cde30f0b2835e Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 15 May 2014 17:18:26 +0200 Subject: netfilter: nf_tables: fix trace of matching non-terminal rule Add the corresponding trace if we have a full match in a non-terminal rule. Note that the traces will look slightly different than in x_tables since the log message after all expressions have been evaluated (contrary to x_tables, that emits it before the target action). This manifests in two differences in nf_tables wrt. x_tables: 1) The rule that enables the tracing is included in the trace. 2) If the rule emits some log message, that is shown before the trace log message. Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_tables_core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c index 421c36ac5145..345acfb1720b 100644 --- a/net/netfilter/nf_tables_core.c +++ b/net/netfilter/nf_tables_core.c @@ -144,8 +144,10 @@ next_rule: switch (data[NFT_REG_VERDICT].verdict) { case NFT_BREAK: data[NFT_REG_VERDICT].verdict = NFT_CONTINUE; - /* fall through */ + continue; case NFT_CONTINUE: + if (unlikely(pkt->skb->nf_trace)) + nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE); continue; } break; -- cgit v1.2.3 From 16a4142363b11952d3aa76ac78004502c0c2fe6e Mon Sep 17 00:00:00 2001 From: Marek Lindner Date: Thu, 24 Apr 2014 03:44:25 +0800 Subject: batman-adv: fix indirect hard_iface NULL dereference If hard_iface is NULL and goto out is made batadv_hardif_free_ref() doesn't check for NULL before dereferencing it to get to refcount. Introduced in cb1c92ec37fb70543d133a1fa7d9b54d6f8a1ecd ("batman-adv: add debugfs support to view multiif tables"). Reported-by: Sven Eckelmann Signed-off-by: Marek Lindner Acked-by: Antonio Quartulli Signed-off-by: Antonio Quartulli --- net/batman-adv/originator.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index 1785da37b82c..6a484514cd3e 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c @@ -1079,7 +1079,8 @@ int batadv_orig_hardif_seq_print_text(struct seq_file *seq, void *offset) bat_priv->bat_algo_ops->bat_orig_print(bat_priv, seq, hard_iface); out: - batadv_hardif_free_ref(hard_iface); + if (hard_iface) + batadv_hardif_free_ref(hard_iface); return 0; } -- cgit v1.2.3 From be181015a189cd141398b761ba4e79d33fe69949 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Wed, 23 Apr 2014 14:05:16 +0200 Subject: batman-adv: fix reference counting imbalance while sending fragment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the new fragmentation code the batadv_frag_send_packet() function obtains a reference to the primary_if, but it does not release it upon return. This reference imbalance prevents the primary_if (and then the related netdevice) to be properly released on shut down. Fix this by releasing the primary_if in batadv_frag_send_packet(). Introduced by ee75ed88879af88558818a5c6609d85f60ff0df4 ("batman-adv: Fragment and send skbs larger than mtu") Cc: Martin Hundebøll Signed-off-by: Antonio Quartulli Signed-off-by: Marek Lindner Acked-by: Martin Hundebøll --- net/batman-adv/fragmentation.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/net/batman-adv/fragmentation.c b/net/batman-adv/fragmentation.c index bcc4bea632fa..f14e54a05691 100644 --- a/net/batman-adv/fragmentation.c +++ b/net/batman-adv/fragmentation.c @@ -418,12 +418,13 @@ bool batadv_frag_send_packet(struct sk_buff *skb, struct batadv_neigh_node *neigh_node) { struct batadv_priv *bat_priv; - struct batadv_hard_iface *primary_if; + struct batadv_hard_iface *primary_if = NULL; struct batadv_frag_packet frag_header; struct sk_buff *skb_fragment; unsigned mtu = neigh_node->if_incoming->net_dev->mtu; unsigned header_size = sizeof(frag_header); unsigned max_fragment_size, max_packet_size; + bool ret = false; /* To avoid merge and refragmentation at next-hops we never send * fragments larger than BATADV_FRAG_MAX_FRAG_SIZE @@ -483,7 +484,11 @@ bool batadv_frag_send_packet(struct sk_buff *skb, skb->len + ETH_HLEN); batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); - return true; + ret = true; + out_err: - return false; + if (primary_if) + batadv_hardif_free_ref(primary_if); + + return ret; } -- cgit v1.2.3 From 377fe0f968b30a1a714fab53a908061914f30e26 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Fri, 2 May 2014 01:35:13 +0200 Subject: batman-adv: increase orig refcount when storing ref in gw_node A pointer to the orig_node representing a bat-gateway is stored in the gw_node->orig_node member, but the refcount for such orig_node is never increased. This leads to memory faults when gw_node->orig_node is accessed and the originator has already been freed. Fix this by increasing the refcount on gw_node creation and decreasing it on gw_node free. Signed-off-by: Antonio Quartulli Signed-off-by: Marek Lindner --- net/batman-adv/gateway_client.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c index c835e137423b..90cff585b37d 100644 --- a/net/batman-adv/gateway_client.c +++ b/net/batman-adv/gateway_client.c @@ -42,8 +42,10 @@ static void batadv_gw_node_free_ref(struct batadv_gw_node *gw_node) { - if (atomic_dec_and_test(&gw_node->refcount)) + if (atomic_dec_and_test(&gw_node->refcount)) { + batadv_orig_node_free_ref(gw_node->orig_node); kfree_rcu(gw_node, rcu); + } } static struct batadv_gw_node * @@ -406,9 +408,14 @@ static void batadv_gw_node_add(struct batadv_priv *bat_priv, if (gateway->bandwidth_down == 0) return; + if (!atomic_inc_not_zero(&orig_node->refcount)) + return; + gw_node = kzalloc(sizeof(*gw_node), GFP_ATOMIC); - if (!gw_node) + if (!gw_node) { + batadv_orig_node_free_ref(orig_node); return; + } INIT_HLIST_NODE(&gw_node->list); gw_node->orig_node = orig_node; -- cgit v1.2.3 From cc2f33860cea0e48ebec096130bd0f7c4bf6e0bc Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Sat, 29 Mar 2014 17:27:38 +0100 Subject: batman-adv: fix local TT check for outgoing arp requests in DAT Change introduced by 88e48d7b3340ef07b108eb8a8b3813dd093cc7f7 ("batman-adv: make DAT drop ARP requests targeting local clients") implements a check that prevents DAT from using the caching mechanism when the client that is supposed to provide a reply to an arp request is local. However change brought by be1db4f6615b5e6156c807ea8985171c215c2d57 ("batman-adv: make the Distributed ARP Table vlan aware") has not converted the above check into its vlan aware version thus making it useless when the local client is behind a vlan. Fix the behaviour by properly specifying the vlan when checking for a client being local or not. Reported-by: Simon Wunderlich Signed-off-by: Antonio Quartulli Signed-off-by: Marek Lindner --- net/batman-adv/distributed-arp-table.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c index b25fd64d727b..aa5d4946d0d7 100644 --- a/net/batman-adv/distributed-arp-table.c +++ b/net/batman-adv/distributed-arp-table.c @@ -940,8 +940,7 @@ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv, * additional DAT answer may trigger kernel warnings about * a packet coming from the wrong port. */ - if (batadv_is_my_client(bat_priv, dat_entry->mac_addr, - BATADV_NO_FLAGS)) { + if (batadv_is_my_client(bat_priv, dat_entry->mac_addr, vid)) { ret = true; goto out; } -- cgit v1.2.3 From 93fa9d32670f5592c8e56abc9928fc194e1e72fc Mon Sep 17 00:00:00 2001 From: Marcel Apfelbaum Date: Thu, 15 May 2014 12:42:49 -0600 Subject: PCI: shpchp: Check bridge's secondary (not primary) bus speed When a new device is added below a hotplug bridge, the bridge's secondary bus speed and the device's bus speed must match. The shpchp driver previously checked the bridge's *primary* bus speed, not the secondary bus speed. This caused hot-add errors like: shpchp 0000:00:03.0: Speed of bus ff and adapter 0 mismatch Check the secondary bus speed instead. [bhelgaas: changelog] Link: https://bugzilla.kernel.org/show_bug.cgi?id=75251 Fixes: 3749c51ac6c1 ("PCI: Make current and maximum bus speeds part of the PCI core") Signed-off-by: Marcel Apfelbaum Signed-off-by: Bjorn Helgaas Acked-by: Michael S. Tsirkin CC: stable@vger.kernel.org # v2.6.34+ --- drivers/pci/hotplug/shpchp_ctrl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index 58499277903a..6efc2ec5e4db 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -282,8 +282,8 @@ static int board_added(struct slot *p_slot) return WRONG_BUS_FREQUENCY; } - bsp = ctrl->pci_dev->bus->cur_bus_speed; - msp = ctrl->pci_dev->bus->max_bus_speed; + bsp = ctrl->pci_dev->subordinate->cur_bus_speed; + msp = ctrl->pci_dev->subordinate->max_bus_speed; /* Check if there are other slots or devices on the same bus */ if (!list_empty(&ctrl->pci_dev->subordinate->devices)) -- cgit v1.2.3 From fef47e2a2e1e75fe50a10f634a80f16808348cc6 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Mon, 5 May 2014 18:07:12 +0200 Subject: parisc: ratelimit userspace segfault printing Ratelimit printing of userspace segfaults and make it runtime configurable via the /proc/sys/debug/exception-trace variable. This should resolve syslog from growing way too fast and thus prevents possible system service attacks. Signed-off-by: Helge Deller Cc: stable@vger.kernel.org # 3.13+ --- arch/parisc/Kconfig | 1 + arch/parisc/kernel/traps.c | 54 +++++++++++++++++++++------------------------- arch/parisc/mm/fault.c | 44 +++++++++++++++++++++++++------------ 3 files changed, 56 insertions(+), 43 deletions(-) diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index bb2a8ec440e7..a8f4a70c0742 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig @@ -22,6 +22,7 @@ config PARISC select GENERIC_SMP_IDLE_THREAD select GENERIC_STRNCPY_FROM_USER select SYSCTL_ARCH_UNALIGN_ALLOW + select SYSCTL_EXCEPTION_TRACE select HAVE_MOD_ARCH_SPECIFIC select VIRT_TO_BUS select MODULES_USE_ELF_RELA diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c index 1cd1d0c83b6d..47ee620d15d2 100644 --- a/arch/parisc/kernel/traps.c +++ b/arch/parisc/kernel/traps.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -42,9 +43,6 @@ #include "../math-emu/math-emu.h" /* for handle_fpe() */ -#define PRINT_USER_FAULTS /* (turn this on if you want user faults to be */ - /* dumped to the console via printk) */ - #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK) DEFINE_SPINLOCK(pa_dbit_lock); #endif @@ -160,6 +158,17 @@ void show_regs(struct pt_regs *regs) } } +static DEFINE_RATELIMIT_STATE(_hppa_rs, + DEFAULT_RATELIMIT_INTERVAL, DEFAULT_RATELIMIT_BURST); + +#define parisc_printk_ratelimited(critical, regs, fmt, ...) { \ + if ((critical || show_unhandled_signals) && __ratelimit(&_hppa_rs)) { \ + printk(fmt, ##__VA_ARGS__); \ + show_regs(regs); \ + } \ +} + + static void do_show_stack(struct unwind_frame_info *info) { int i = 1; @@ -229,12 +238,10 @@ void die_if_kernel(char *str, struct pt_regs *regs, long err) if (err == 0) return; /* STFU */ - printk(KERN_CRIT "%s (pid %d): %s (code %ld) at " RFMT "\n", + parisc_printk_ratelimited(1, regs, + KERN_CRIT "%s (pid %d): %s (code %ld) at " RFMT "\n", current->comm, task_pid_nr(current), str, err, regs->iaoq[0]); -#ifdef PRINT_USER_FAULTS - /* XXX for debugging only */ - show_regs(regs); -#endif + return; } @@ -321,14 +328,11 @@ static void handle_break(struct pt_regs *regs) (tt == BUG_TRAP_TYPE_NONE) ? 9 : 0); } -#ifdef PRINT_USER_FAULTS - if (unlikely(iir != GDB_BREAK_INSN)) { - printk(KERN_DEBUG "break %d,%d: pid=%d command='%s'\n", + if (unlikely(iir != GDB_BREAK_INSN)) + parisc_printk_ratelimited(0, regs, + KERN_DEBUG "break %d,%d: pid=%d command='%s'\n", iir & 31, (iir>>13) & ((1<<13)-1), task_pid_nr(current), current->comm); - show_regs(regs); - } -#endif /* send standard GDB signal */ handle_gdb_break(regs, TRAP_BRKPT); @@ -758,11 +762,9 @@ void notrace handle_interruption(int code, struct pt_regs *regs) default: if (user_mode(regs)) { -#ifdef PRINT_USER_FAULTS - printk(KERN_DEBUG "\nhandle_interruption() pid=%d command='%s'\n", - task_pid_nr(current), current->comm); - show_regs(regs); -#endif + parisc_printk_ratelimited(0, regs, KERN_DEBUG + "handle_interruption() pid=%d command='%s'\n", + task_pid_nr(current), current->comm); /* SIGBUS, for lack of a better one. */ si.si_signo = SIGBUS; si.si_code = BUS_OBJERR; @@ -779,16 +781,10 @@ void notrace handle_interruption(int code, struct pt_regs *regs) if (user_mode(regs)) { if ((fault_space >> SPACEID_SHIFT) != (regs->sr[7] >> SPACEID_SHIFT)) { -#ifdef PRINT_USER_FAULTS - if (fault_space == 0) - printk(KERN_DEBUG "User Fault on Kernel Space "); - else - printk(KERN_DEBUG "User Fault (long pointer) (fault %d) ", - code); - printk(KERN_CONT "pid=%d command='%s'\n", - task_pid_nr(current), current->comm); - show_regs(regs); -#endif + parisc_printk_ratelimited(0, regs, KERN_DEBUG + "User fault %d on space 0x%08lx, pid=%d command='%s'\n", + code, fault_space, + task_pid_nr(current), current->comm); si.si_signo = SIGSEGV; si.si_errno = 0; si.si_code = SEGV_MAPERR; diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c index 9d08c71a967e..d72197f0ddb8 100644 --- a/arch/parisc/mm/fault.c +++ b/arch/parisc/mm/fault.c @@ -19,10 +19,6 @@ #include #include -#define PRINT_USER_FAULTS /* (turn this on if you want user faults to be */ - /* dumped to the console via printk) */ - - /* Various important other fields */ #define bit22set(x) (x & 0x00000200) #define bits23_25set(x) (x & 0x000001c0) @@ -34,6 +30,8 @@ DEFINE_PER_CPU(struct exception_data, exception_data); +int show_unhandled_signals = 1; + /* * parisc_acctyp(unsigned int inst) -- * Given a PA-RISC memory access instruction, determine if the @@ -173,6 +171,32 @@ int fixup_exception(struct pt_regs *regs) return 0; } +/* + * Print out info about fatal segfaults, if the show_unhandled_signals + * sysctl is set: + */ +static inline void +show_signal_msg(struct pt_regs *regs, unsigned long code, + unsigned long address, struct task_struct *tsk, + struct vm_area_struct *vma) +{ + if (!unhandled_signal(tsk, SIGSEGV)) + return; + + if (!printk_ratelimit()) + return; + + pr_warn("\n"); + pr_warn("do_page_fault() command='%s' type=%lu address=0x%08lx", + tsk->comm, code, address); + print_vma_addr(KERN_CONT " in ", regs->iaoq[0]); + if (vma) + pr_warn(" vm_start = 0x%08lx, vm_end = 0x%08lx\n", + vma->vm_start, vma->vm_end); + + show_regs(regs); +} + void do_page_fault(struct pt_regs *regs, unsigned long code, unsigned long address) { @@ -270,16 +294,8 @@ bad_area: if (user_mode(regs)) { struct siginfo si; -#ifdef PRINT_USER_FAULTS - printk(KERN_DEBUG "\n"); - printk(KERN_DEBUG "do_page_fault() pid=%d command='%s' type=%lu address=0x%08lx\n", - task_pid_nr(tsk), tsk->comm, code, address); - if (vma) { - printk(KERN_DEBUG "vm_start = 0x%08lx, vm_end = 0x%08lx\n", - vma->vm_start, vma->vm_end); - } - show_regs(regs); -#endif + show_signal_msg(regs, code, address, tsk, vma); + switch (code) { case 15: /* Data TLB miss fault/Data page fault */ /* send SIGSEGV when outside of vma */ -- cgit v1.2.3 From c776cd89fc705fc8b5c2e5ad906bf5d791620fed Mon Sep 17 00:00:00 2001 From: John David Anglin Date: Sun, 11 May 2014 18:40:50 -0400 Subject: parisc: Improve LWS-CAS performance The attached change significantly improves the performance of the LWS-CAS code in syscall.S. This allows a number of packages to build (e.g., zeromq3, gtest and libxs) that previously failed because slow LWS-CAS performance under contention. In particular, interrupts taken while the lock was taken degraded performance significantly. The change does the following: 1) Disables interrupts around the CAS operation, and 2) Changes the loads and stores to use the ordered completer, "o", on PA 2.0. "o" and "ma" with a zero offset are equivalent. The latter is accepted on both PA 1.X and 2.0. The use of ordered loads and stores probably makes no difference on all existing hardware, but it seemed pedantically correct. In particular, the CAS operation must complete before LDCW lock is released. As written before, a processor could reorder the operations. I don't believe the period interrupts are disabled is long enough to significantly increase interrupt latency. For example, the TLB insert code is longer. Worst case is a memory fault in the CAS operation. Signed-off-by: John David Anglin Cc: stable@vger.kernel.org # 3.13+ Signed-off-by: Helge Deller --- arch/parisc/kernel/syscall.S | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S index a63bb179f79a..838786011037 100644 --- a/arch/parisc/kernel/syscall.S +++ b/arch/parisc/kernel/syscall.S @@ -589,10 +589,13 @@ cas_nocontend: # endif /* ENABLE_LWS_DEBUG */ + rsm PSW_SM_I, %r0 /* Disable interrupts */ + /* COW breaks can cause contention on UP systems */ LDCW 0(%sr2,%r20), %r28 /* Try to acquire the lock */ cmpb,<>,n %r0, %r28, cas_action /* Did we get it? */ cas_wouldblock: ldo 2(%r0), %r28 /* 2nd case */ + ssm PSW_SM_I, %r0 b lws_exit /* Contended... */ ldo -EAGAIN(%r0), %r21 /* Spin in userspace */ @@ -619,15 +622,17 @@ cas_action: stw %r1, 4(%sr2,%r20) #endif /* The load and store could fail */ -1: ldw 0(%sr3,%r26), %r28 +1: ldw,ma 0(%sr3,%r26), %r28 sub,<> %r28, %r25, %r0 -2: stw %r24, 0(%sr3,%r26) +2: stw,ma %r24, 0(%sr3,%r26) /* Free lock */ - stw %r20, 0(%sr2,%r20) + stw,ma %r20, 0(%sr2,%r20) #if ENABLE_LWS_DEBUG /* Clear thread register indicator */ stw %r0, 4(%sr2,%r20) #endif + /* Enable interrupts */ + ssm PSW_SM_I, %r0 /* Return to userspace, set no error */ b lws_exit copy %r0, %r21 @@ -639,6 +644,7 @@ cas_action: #if ENABLE_LWS_DEBUG stw %r0, 4(%sr2,%r20) #endif + ssm PSW_SM_I, %r0 b lws_exit ldo -EFAULT(%r0),%r21 /* set errno */ nop -- cgit v1.2.3 From 200b916f3575bdf11609cb447661b8d5957b0bbf Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Mon, 12 May 2014 15:11:20 -0700 Subject: rtnetlink: wait for unregistering devices in rtnl_link_unregister() From: Cong Wang commit 50624c934db18ab90 (net: Delay default_device_exit_batch until no devices are unregistering) introduced rtnl_lock_unregistering() for default_device_exit_batch(). Same race could happen we when rmmod a driver which calls rtnl_link_unregister() as we call dev->destructor without rtnl lock. For long term, I think we should clean up the mess of netdev_run_todo() and net namespce exit code. Cc: Eric W. Biederman Cc: David S. Miller Signed-off-by: Cong Wang Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- include/linux/rtnetlink.h | 5 +++++ net/core/dev.c | 2 +- net/core/net_namespace.c | 2 +- net/core/rtnetlink.c | 33 ++++++++++++++++++++++++++++++++- 4 files changed, 39 insertions(+), 3 deletions(-) diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h index 8e3e66ac0a52..953937ea5233 100644 --- a/include/linux/rtnetlink.h +++ b/include/linux/rtnetlink.h @@ -4,6 +4,7 @@ #include #include +#include #include extern int rtnetlink_send(struct sk_buff *skb, struct net *net, u32 pid, u32 group, int echo); @@ -22,6 +23,10 @@ extern void rtnl_lock(void); extern void rtnl_unlock(void); extern int rtnl_trylock(void); extern int rtnl_is_locked(void); + +extern wait_queue_head_t netdev_unregistering_wq; +extern struct mutex net_mutex; + #ifdef CONFIG_PROVE_LOCKING extern int lockdep_rtnl_is_held(void); #else diff --git a/net/core/dev.c b/net/core/dev.c index c619b8641337..6da649bde4f7 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -5541,7 +5541,7 @@ static int dev_new_index(struct net *net) /* Delayed registration/unregisteration */ static LIST_HEAD(net_todo_list); -static DECLARE_WAIT_QUEUE_HEAD(netdev_unregistering_wq); +DECLARE_WAIT_QUEUE_HEAD(netdev_unregistering_wq); static void net_set_todo(struct net_device *dev) { diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index 81d3a9a08453..7c8ffd974961 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -24,7 +24,7 @@ static LIST_HEAD(pernet_list); static struct list_head *first_device = &pernet_list; -static DEFINE_MUTEX(net_mutex); +DEFINE_MUTEX(net_mutex); LIST_HEAD(net_namespace_list); EXPORT_SYMBOL_GPL(net_namespace_list); diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 9837bebf93ce..2d8d8fcfa060 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -353,15 +353,46 @@ void __rtnl_link_unregister(struct rtnl_link_ops *ops) } EXPORT_SYMBOL_GPL(__rtnl_link_unregister); +/* Return with the rtnl_lock held when there are no network + * devices unregistering in any network namespace. + */ +static void rtnl_lock_unregistering_all(void) +{ + struct net *net; + bool unregistering; + DEFINE_WAIT(wait); + + for (;;) { + prepare_to_wait(&netdev_unregistering_wq, &wait, + TASK_UNINTERRUPTIBLE); + unregistering = false; + rtnl_lock(); + for_each_net(net) { + if (net->dev_unreg_count > 0) { + unregistering = true; + break; + } + } + if (!unregistering) + break; + __rtnl_unlock(); + schedule(); + } + finish_wait(&netdev_unregistering_wq, &wait); +} + /** * rtnl_link_unregister - Unregister rtnl_link_ops from rtnetlink. * @ops: struct rtnl_link_ops * to unregister */ void rtnl_link_unregister(struct rtnl_link_ops *ops) { - rtnl_lock(); + /* Close the race with cleanup_net() */ + mutex_lock(&net_mutex); + rtnl_lock_unregistering_all(); __rtnl_link_unregister(ops); rtnl_unlock(); + mutex_unlock(&net_mutex); } EXPORT_SYMBOL_GPL(rtnl_link_unregister); -- cgit v1.2.3 From 5513a510fad73594e29e1e48e760e0a644a8a4f3 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Wed, 14 May 2014 21:57:26 -0400 Subject: nfsd4: fix corruption on setting an ACL. As of 06f9cc12caa862f5bc86ebdb4f77568a4bef0167 "nfsd4: don't create unnecessary mask acl", any non-trivial ACL will be left with an unitialized entry, and a trivial ACL may write one entry beyond what's allocated. Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4acl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c index b6f46013dddf..f66c66b9f182 100644 --- a/fs/nfsd/nfs4acl.c +++ b/fs/nfsd/nfs4acl.c @@ -590,7 +590,7 @@ posix_state_to_acl(struct posix_acl_state *state, unsigned int flags) add_to_mask(state, &state->groups->aces[i].perms); } - if (!state->users->n && !state->groups->n) { + if (state->users->n || state->groups->n) { pace++; pace->e_tag = ACL_MASK; low_mode_from_nfs4(state->mask.allow, &pace->e_perm, flags); -- cgit v1.2.3 From 898305806ad56ae11dc2c80931062e6a2c7bba48 Mon Sep 17 00:00:00 2001 From: Vince Bridgers Date: Wed, 14 May 2014 14:38:36 -0500 Subject: Altera TSE: Fix sparse errors and warnings This patch fixes the many sparse errors and warnings contained in the initial submission of the Altera Triple Speed Ethernet driver, and a few minor cppcheck warnings. Changes are tested on ARM and NIOS2 example designs, and compile tested against multiple architectures. Typical issues addressed were as follows: altera_tse_ethtool.c:136:19: warning: incorrect type in argument 1 (different address spaces) altera_tse_ethtool.c:136:19: expected void const volatile [noderef] *addr altera_tse_ethtool.c:136:19: got unsigned int * ... altera_sgdma.c:129:31: warning: cast removes address space of expression Signed-off-by: Vince Bridgers Signed-off-by: David S. Miller --- drivers/net/ethernet/altera/Makefile | 1 + drivers/net/ethernet/altera/altera_msgdma.c | 110 +++++++------- drivers/net/ethernet/altera/altera_msgdmahw.h | 13 +- drivers/net/ethernet/altera/altera_sgdma.c | 181 +++++++++++------------ drivers/net/ethernet/altera/altera_sgdmahw.h | 26 ++-- drivers/net/ethernet/altera/altera_tse.h | 47 ++++++ drivers/net/ethernet/altera/altera_tse_ethtool.c | 108 +++++++++----- drivers/net/ethernet/altera/altera_tse_main.c | 128 +++++++++------- drivers/net/ethernet/altera/altera_utils.c | 20 +-- drivers/net/ethernet/altera/altera_utils.h | 8 +- 10 files changed, 367 insertions(+), 275 deletions(-) diff --git a/drivers/net/ethernet/altera/Makefile b/drivers/net/ethernet/altera/Makefile index d4a187e45369..3eff2fd3997e 100644 --- a/drivers/net/ethernet/altera/Makefile +++ b/drivers/net/ethernet/altera/Makefile @@ -5,3 +5,4 @@ obj-$(CONFIG_ALTERA_TSE) += altera_tse.o altera_tse-objs := altera_tse_main.o altera_tse_ethtool.o \ altera_msgdma.o altera_sgdma.o altera_utils.o +ccflags-y += -D__CHECK_ENDIAN__ diff --git a/drivers/net/ethernet/altera/altera_msgdma.c b/drivers/net/ethernet/altera/altera_msgdma.c index 4d1f2fdd5c32..0fb986ba3290 100644 --- a/drivers/net/ethernet/altera/altera_msgdma.c +++ b/drivers/net/ethernet/altera/altera_msgdma.c @@ -37,18 +37,16 @@ void msgdma_start_rxdma(struct altera_tse_private *priv) void msgdma_reset(struct altera_tse_private *priv) { int counter; - struct msgdma_csr *txcsr = - (struct msgdma_csr *)priv->tx_dma_csr; - struct msgdma_csr *rxcsr = - (struct msgdma_csr *)priv->rx_dma_csr; /* Reset Rx mSGDMA */ - iowrite32(MSGDMA_CSR_STAT_MASK, &rxcsr->status); - iowrite32(MSGDMA_CSR_CTL_RESET, &rxcsr->control); + csrwr32(MSGDMA_CSR_STAT_MASK, priv->rx_dma_csr, + msgdma_csroffs(status)); + csrwr32(MSGDMA_CSR_CTL_RESET, priv->rx_dma_csr, + msgdma_csroffs(control)); counter = 0; while (counter++ < ALTERA_TSE_SW_RESET_WATCHDOG_CNTR) { - if (tse_bit_is_clear(&rxcsr->status, + if (tse_bit_is_clear(priv->rx_dma_csr, msgdma_csroffs(status), MSGDMA_CSR_STAT_RESETTING)) break; udelay(1); @@ -59,15 +57,18 @@ void msgdma_reset(struct altera_tse_private *priv) "TSE Rx mSGDMA resetting bit never cleared!\n"); /* clear all status bits */ - iowrite32(MSGDMA_CSR_STAT_MASK, &rxcsr->status); + csrwr32(MSGDMA_CSR_STAT_MASK, priv->rx_dma_csr, msgdma_csroffs(status)); /* Reset Tx mSGDMA */ - iowrite32(MSGDMA_CSR_STAT_MASK, &txcsr->status); - iowrite32(MSGDMA_CSR_CTL_RESET, &txcsr->control); + csrwr32(MSGDMA_CSR_STAT_MASK, priv->tx_dma_csr, + msgdma_csroffs(status)); + + csrwr32(MSGDMA_CSR_CTL_RESET, priv->tx_dma_csr, + msgdma_csroffs(control)); counter = 0; while (counter++ < ALTERA_TSE_SW_RESET_WATCHDOG_CNTR) { - if (tse_bit_is_clear(&txcsr->status, + if (tse_bit_is_clear(priv->tx_dma_csr, msgdma_csroffs(status), MSGDMA_CSR_STAT_RESETTING)) break; udelay(1); @@ -78,58 +79,58 @@ void msgdma_reset(struct altera_tse_private *priv) "TSE Tx mSGDMA resetting bit never cleared!\n"); /* clear all status bits */ - iowrite32(MSGDMA_CSR_STAT_MASK, &txcsr->status); + csrwr32(MSGDMA_CSR_STAT_MASK, priv->tx_dma_csr, msgdma_csroffs(status)); } void msgdma_disable_rxirq(struct altera_tse_private *priv) { - struct msgdma_csr *csr = priv->rx_dma_csr; - tse_clear_bit(&csr->control, MSGDMA_CSR_CTL_GLOBAL_INTR); + tse_clear_bit(priv->rx_dma_csr, msgdma_csroffs(control), + MSGDMA_CSR_CTL_GLOBAL_INTR); } void msgdma_enable_rxirq(struct altera_tse_private *priv) { - struct msgdma_csr *csr = priv->rx_dma_csr; - tse_set_bit(&csr->control, MSGDMA_CSR_CTL_GLOBAL_INTR); + tse_set_bit(priv->rx_dma_csr, msgdma_csroffs(control), + MSGDMA_CSR_CTL_GLOBAL_INTR); } void msgdma_disable_txirq(struct altera_tse_private *priv) { - struct msgdma_csr *csr = priv->tx_dma_csr; - tse_clear_bit(&csr->control, MSGDMA_CSR_CTL_GLOBAL_INTR); + tse_clear_bit(priv->tx_dma_csr, msgdma_csroffs(control), + MSGDMA_CSR_CTL_GLOBAL_INTR); } void msgdma_enable_txirq(struct altera_tse_private *priv) { - struct msgdma_csr *csr = priv->tx_dma_csr; - tse_set_bit(&csr->control, MSGDMA_CSR_CTL_GLOBAL_INTR); + tse_set_bit(priv->tx_dma_csr, msgdma_csroffs(control), + MSGDMA_CSR_CTL_GLOBAL_INTR); } void msgdma_clear_rxirq(struct altera_tse_private *priv) { - struct msgdma_csr *csr = priv->rx_dma_csr; - iowrite32(MSGDMA_CSR_STAT_IRQ, &csr->status); + csrwr32(MSGDMA_CSR_STAT_IRQ, priv->rx_dma_csr, msgdma_csroffs(status)); } void msgdma_clear_txirq(struct altera_tse_private *priv) { - struct msgdma_csr *csr = priv->tx_dma_csr; - iowrite32(MSGDMA_CSR_STAT_IRQ, &csr->status); + csrwr32(MSGDMA_CSR_STAT_IRQ, priv->tx_dma_csr, msgdma_csroffs(status)); } /* return 0 to indicate transmit is pending */ int msgdma_tx_buffer(struct altera_tse_private *priv, struct tse_buffer *buffer) { - struct msgdma_extended_desc *desc = priv->tx_dma_desc; - - iowrite32(lower_32_bits(buffer->dma_addr), &desc->read_addr_lo); - iowrite32(upper_32_bits(buffer->dma_addr), &desc->read_addr_hi); - iowrite32(0, &desc->write_addr_lo); - iowrite32(0, &desc->write_addr_hi); - iowrite32(buffer->len, &desc->len); - iowrite32(0, &desc->burst_seq_num); - iowrite32(MSGDMA_DESC_TX_STRIDE, &desc->stride); - iowrite32(MSGDMA_DESC_CTL_TX_SINGLE, &desc->control); + csrwr32(lower_32_bits(buffer->dma_addr), priv->tx_dma_desc, + msgdma_descroffs(read_addr_lo)); + csrwr32(upper_32_bits(buffer->dma_addr), priv->tx_dma_desc, + msgdma_descroffs(read_addr_hi)); + csrwr32(0, priv->tx_dma_desc, msgdma_descroffs(write_addr_lo)); + csrwr32(0, priv->tx_dma_desc, msgdma_descroffs(write_addr_hi)); + csrwr32(buffer->len, priv->tx_dma_desc, msgdma_descroffs(len)); + csrwr32(0, priv->tx_dma_desc, msgdma_descroffs(burst_seq_num)); + csrwr32(MSGDMA_DESC_TX_STRIDE, priv->tx_dma_desc, + msgdma_descroffs(stride)); + csrwr32(MSGDMA_DESC_CTL_TX_SINGLE, priv->tx_dma_desc, + msgdma_descroffs(control)); return 0; } @@ -138,17 +139,16 @@ u32 msgdma_tx_completions(struct altera_tse_private *priv) u32 ready = 0; u32 inuse; u32 status; - struct msgdma_csr *txcsr = - (struct msgdma_csr *)priv->tx_dma_csr; /* Get number of sent descriptors */ - inuse = ioread32(&txcsr->rw_fill_level) & 0xffff; + inuse = csrrd32(priv->tx_dma_csr, msgdma_csroffs(rw_fill_level)) + & 0xffff; if (inuse) { /* Tx FIFO is not empty */ ready = priv->tx_prod - priv->tx_cons - inuse - 1; } else { /* Check for buffered last packet */ - status = ioread32(&txcsr->status); + status = csrrd32(priv->tx_dma_csr, msgdma_csroffs(status)); if (status & MSGDMA_CSR_STAT_BUSY) ready = priv->tx_prod - priv->tx_cons - 1; else @@ -162,7 +162,6 @@ u32 msgdma_tx_completions(struct altera_tse_private *priv) void msgdma_add_rx_desc(struct altera_tse_private *priv, struct tse_buffer *rxbuffer) { - struct msgdma_extended_desc *desc = priv->rx_dma_desc; u32 len = priv->rx_dma_buf_sz; dma_addr_t dma_addr = rxbuffer->dma_addr; u32 control = (MSGDMA_DESC_CTL_END_ON_EOP @@ -172,14 +171,16 @@ void msgdma_add_rx_desc(struct altera_tse_private *priv, | MSGDMA_DESC_CTL_TR_ERR_IRQ | MSGDMA_DESC_CTL_GO); - iowrite32(0, &desc->read_addr_lo); - iowrite32(0, &desc->read_addr_hi); - iowrite32(lower_32_bits(dma_addr), &desc->write_addr_lo); - iowrite32(upper_32_bits(dma_addr), &desc->write_addr_hi); - iowrite32(len, &desc->len); - iowrite32(0, &desc->burst_seq_num); - iowrite32(0x00010001, &desc->stride); - iowrite32(control, &desc->control); + csrwr32(0, priv->rx_dma_desc, msgdma_descroffs(read_addr_lo)); + csrwr32(0, priv->rx_dma_desc, msgdma_descroffs(read_addr_hi)); + csrwr32(lower_32_bits(dma_addr), priv->rx_dma_desc, + msgdma_descroffs(write_addr_lo)); + csrwr32(upper_32_bits(dma_addr), priv->rx_dma_desc, + msgdma_descroffs(write_addr_hi)); + csrwr32(len, priv->rx_dma_desc, msgdma_descroffs(len)); + csrwr32(0, priv->rx_dma_desc, msgdma_descroffs(burst_seq_num)); + csrwr32(0x00010001, priv->rx_dma_desc, msgdma_descroffs(stride)); + csrwr32(control, priv->rx_dma_desc, msgdma_descroffs(control)); } /* status is returned on upper 16 bits, @@ -190,14 +191,13 @@ u32 msgdma_rx_status(struct altera_tse_private *priv) u32 rxstatus = 0; u32 pktlength; u32 pktstatus; - struct msgdma_csr *rxcsr = - (struct msgdma_csr *)priv->rx_dma_csr; - struct msgdma_response *rxresp = - (struct msgdma_response *)priv->rx_dma_resp; - - if (ioread32(&rxcsr->resp_fill_level) & 0xffff) { - pktlength = ioread32(&rxresp->bytes_transferred); - pktstatus = ioread32(&rxresp->status); + + if (csrrd32(priv->rx_dma_csr, msgdma_csroffs(resp_fill_level)) + & 0xffff) { + pktlength = csrrd32(priv->rx_dma_resp, + msgdma_respoffs(bytes_transferred)); + pktstatus = csrrd32(priv->rx_dma_resp, + msgdma_respoffs(status)); rxstatus = pktstatus; rxstatus = rxstatus << 16; rxstatus |= (pktlength & 0xffff); diff --git a/drivers/net/ethernet/altera/altera_msgdmahw.h b/drivers/net/ethernet/altera/altera_msgdmahw.h index d7b59ba4019c..e335626e1b6b 100644 --- a/drivers/net/ethernet/altera/altera_msgdmahw.h +++ b/drivers/net/ethernet/altera/altera_msgdmahw.h @@ -17,15 +17,6 @@ #ifndef __ALTERA_MSGDMAHW_H__ #define __ALTERA_MSGDMAHW_H__ -/* mSGDMA standard descriptor format - */ -struct msgdma_desc { - u32 read_addr; /* data buffer source address */ - u32 write_addr; /* data buffer destination address */ - u32 len; /* the number of bytes to transfer per descriptor */ - u32 control; /* characteristics of the transfer */ -}; - /* mSGDMA extended descriptor format */ struct msgdma_extended_desc { @@ -159,6 +150,10 @@ struct msgdma_response { u32 status; }; +#define msgdma_respoffs(a) (offsetof(struct msgdma_response, a)) +#define msgdma_csroffs(a) (offsetof(struct msgdma_csr, a)) +#define msgdma_descroffs(a) (offsetof(struct msgdma_extended_desc, a)) + /* mSGDMA response register bit definitions */ #define MSGDMA_RESP_EARLY_TERM BIT(8) diff --git a/drivers/net/ethernet/altera/altera_sgdma.c b/drivers/net/ethernet/altera/altera_sgdma.c index 9ce8630692b6..99cc56f451cf 100644 --- a/drivers/net/ethernet/altera/altera_sgdma.c +++ b/drivers/net/ethernet/altera/altera_sgdma.c @@ -20,8 +20,8 @@ #include "altera_sgdmahw.h" #include "altera_sgdma.h" -static void sgdma_setup_descrip(struct sgdma_descrip *desc, - struct sgdma_descrip *ndesc, +static void sgdma_setup_descrip(struct sgdma_descrip __iomem *desc, + struct sgdma_descrip __iomem *ndesc, dma_addr_t ndesc_phys, dma_addr_t raddr, dma_addr_t waddr, @@ -31,17 +31,17 @@ static void sgdma_setup_descrip(struct sgdma_descrip *desc, int wfixed); static int sgdma_async_write(struct altera_tse_private *priv, - struct sgdma_descrip *desc); + struct sgdma_descrip __iomem *desc); static int sgdma_async_read(struct altera_tse_private *priv); static dma_addr_t sgdma_txphysaddr(struct altera_tse_private *priv, - struct sgdma_descrip *desc); + struct sgdma_descrip __iomem *desc); static dma_addr_t sgdma_rxphysaddr(struct altera_tse_private *priv, - struct sgdma_descrip *desc); + struct sgdma_descrip __iomem *desc); static int sgdma_txbusy(struct altera_tse_private *priv); @@ -79,7 +79,8 @@ int sgdma_initialize(struct altera_tse_private *priv) priv->rxdescphys = (dma_addr_t) 0; priv->txdescphys = (dma_addr_t) 0; - priv->rxdescphys = dma_map_single(priv->device, priv->rx_dma_desc, + priv->rxdescphys = dma_map_single(priv->device, + (void __force *)priv->rx_dma_desc, priv->rxdescmem, DMA_BIDIRECTIONAL); if (dma_mapping_error(priv->device, priv->rxdescphys)) { @@ -88,7 +89,8 @@ int sgdma_initialize(struct altera_tse_private *priv) return -EINVAL; } - priv->txdescphys = dma_map_single(priv->device, priv->tx_dma_desc, + priv->txdescphys = dma_map_single(priv->device, + (void __force *)priv->tx_dma_desc, priv->txdescmem, DMA_TO_DEVICE); if (dma_mapping_error(priv->device, priv->txdescphys)) { @@ -98,8 +100,8 @@ int sgdma_initialize(struct altera_tse_private *priv) } /* Initialize descriptor memory to all 0's, sync memory to cache */ - memset(priv->tx_dma_desc, 0, priv->txdescmem); - memset(priv->rx_dma_desc, 0, priv->rxdescmem); + memset_io(priv->tx_dma_desc, 0, priv->txdescmem); + memset_io(priv->rx_dma_desc, 0, priv->rxdescmem); dma_sync_single_for_device(priv->device, priv->txdescphys, priv->txdescmem, DMA_TO_DEVICE); @@ -126,22 +128,15 @@ void sgdma_uninitialize(struct altera_tse_private *priv) */ void sgdma_reset(struct altera_tse_private *priv) { - u32 *ptxdescripmem = (u32 *)priv->tx_dma_desc; - u32 txdescriplen = priv->txdescmem; - u32 *prxdescripmem = (u32 *)priv->rx_dma_desc; - u32 rxdescriplen = priv->rxdescmem; - struct sgdma_csr *ptxsgdma = (struct sgdma_csr *)priv->tx_dma_csr; - struct sgdma_csr *prxsgdma = (struct sgdma_csr *)priv->rx_dma_csr; - /* Initialize descriptor memory to 0 */ - memset(ptxdescripmem, 0, txdescriplen); - memset(prxdescripmem, 0, rxdescriplen); + memset_io(priv->tx_dma_desc, 0, priv->txdescmem); + memset_io(priv->rx_dma_desc, 0, priv->rxdescmem); - iowrite32(SGDMA_CTRLREG_RESET, &ptxsgdma->control); - iowrite32(0, &ptxsgdma->control); + csrwr32(SGDMA_CTRLREG_RESET, priv->tx_dma_csr, sgdma_csroffs(control)); + csrwr32(0, priv->tx_dma_csr, sgdma_csroffs(control)); - iowrite32(SGDMA_CTRLREG_RESET, &prxsgdma->control); - iowrite32(0, &prxsgdma->control); + csrwr32(SGDMA_CTRLREG_RESET, priv->rx_dma_csr, sgdma_csroffs(control)); + csrwr32(0, priv->rx_dma_csr, sgdma_csroffs(control)); } /* For SGDMA, interrupts remain enabled after initially enabling, @@ -167,14 +162,14 @@ void sgdma_disable_txirq(struct altera_tse_private *priv) void sgdma_clear_rxirq(struct altera_tse_private *priv) { - struct sgdma_csr *csr = (struct sgdma_csr *)priv->rx_dma_csr; - tse_set_bit(&csr->control, SGDMA_CTRLREG_CLRINT); + tse_set_bit(priv->rx_dma_csr, sgdma_csroffs(control), + SGDMA_CTRLREG_CLRINT); } void sgdma_clear_txirq(struct altera_tse_private *priv) { - struct sgdma_csr *csr = (struct sgdma_csr *)priv->tx_dma_csr; - tse_set_bit(&csr->control, SGDMA_CTRLREG_CLRINT); + tse_set_bit(priv->tx_dma_csr, sgdma_csroffs(control), + SGDMA_CTRLREG_CLRINT); } /* transmits buffer through SGDMA. Returns number of buffers @@ -184,12 +179,11 @@ void sgdma_clear_txirq(struct altera_tse_private *priv) */ int sgdma_tx_buffer(struct altera_tse_private *priv, struct tse_buffer *buffer) { - int pktstx = 0; - struct sgdma_descrip *descbase = - (struct sgdma_descrip *)priv->tx_dma_desc; + struct sgdma_descrip __iomem *descbase = + (struct sgdma_descrip __iomem *)priv->tx_dma_desc; - struct sgdma_descrip *cdesc = &descbase[0]; - struct sgdma_descrip *ndesc = &descbase[1]; + struct sgdma_descrip __iomem *cdesc = &descbase[0]; + struct sgdma_descrip __iomem *ndesc = &descbase[1]; /* wait 'til the tx sgdma is ready for the next transmit request */ if (sgdma_txbusy(priv)) @@ -205,7 +199,7 @@ int sgdma_tx_buffer(struct altera_tse_private *priv, struct tse_buffer *buffer) 0, /* read fixed */ SGDMA_CONTROL_WR_FIXED); /* Generate SOP */ - pktstx = sgdma_async_write(priv, cdesc); + sgdma_async_write(priv, cdesc); /* enqueue the request to the pending transmit queue */ queue_tx(priv, buffer); @@ -219,10 +213,10 @@ int sgdma_tx_buffer(struct altera_tse_private *priv, struct tse_buffer *buffer) u32 sgdma_tx_completions(struct altera_tse_private *priv) { u32 ready = 0; - struct sgdma_descrip *desc = (struct sgdma_descrip *)priv->tx_dma_desc; if (!sgdma_txbusy(priv) && - ((desc->control & SGDMA_CONTROL_HW_OWNED) == 0) && + ((csrrd8(priv->tx_dma_desc, sgdma_descroffs(control)) + & SGDMA_CONTROL_HW_OWNED) == 0) && (dequeue_tx(priv))) { ready = 1; } @@ -246,32 +240,31 @@ void sgdma_add_rx_desc(struct altera_tse_private *priv, */ u32 sgdma_rx_status(struct altera_tse_private *priv) { - struct sgdma_csr *csr = (struct sgdma_csr *)priv->rx_dma_csr; - struct sgdma_descrip *base = (struct sgdma_descrip *)priv->rx_dma_desc; - struct sgdma_descrip *desc = NULL; - int pktsrx; - unsigned int rxstatus = 0; - unsigned int pktlength = 0; - unsigned int pktstatus = 0; + struct sgdma_descrip __iomem *base = + (struct sgdma_descrip __iomem *)priv->rx_dma_desc; + struct sgdma_descrip __iomem *desc = NULL; struct tse_buffer *rxbuffer = NULL; + unsigned int rxstatus = 0; - u32 sts = ioread32(&csr->status); + u32 sts = csrrd32(priv->rx_dma_csr, sgdma_csroffs(status)); desc = &base[0]; if (sts & SGDMA_STSREG_EOP) { + unsigned int pktlength = 0; + unsigned int pktstatus = 0; dma_sync_single_for_cpu(priv->device, priv->rxdescphys, priv->sgdmadesclen, DMA_FROM_DEVICE); - pktlength = desc->bytes_xferred; - pktstatus = desc->status & 0x3f; - rxstatus = pktstatus; + pktlength = csrrd16(desc, sgdma_descroffs(bytes_xferred)); + pktstatus = csrrd8(desc, sgdma_descroffs(status)); + rxstatus = pktstatus & ~SGDMA_STATUS_EOP; rxstatus = rxstatus << 16; rxstatus |= (pktlength & 0xffff); if (rxstatus) { - desc->status = 0; + csrwr8(0, desc, sgdma_descroffs(status)); rxbuffer = dequeue_rx(priv); if (rxbuffer == NULL) @@ -279,12 +272,12 @@ u32 sgdma_rx_status(struct altera_tse_private *priv) "sgdma rx and rx queue empty!\n"); /* Clear control */ - iowrite32(0, &csr->control); + csrwr32(0, priv->rx_dma_csr, sgdma_csroffs(control)); /* clear status */ - iowrite32(0xf, &csr->status); + csrwr32(0xf, priv->rx_dma_csr, sgdma_csroffs(status)); /* kick the rx sgdma after reaping this descriptor */ - pktsrx = sgdma_async_read(priv); + sgdma_async_read(priv); } else { /* If the SGDMA indicated an end of packet on recv, @@ -298,10 +291,11 @@ u32 sgdma_rx_status(struct altera_tse_private *priv) */ netdev_err(priv->dev, "SGDMA RX Error Info: %x, %x, %x\n", - sts, desc->status, rxstatus); + sts, csrrd8(desc, sgdma_descroffs(status)), + rxstatus); } } else if (sts == 0) { - pktsrx = sgdma_async_read(priv); + sgdma_async_read(priv); } return rxstatus; @@ -309,8 +303,8 @@ u32 sgdma_rx_status(struct altera_tse_private *priv) /* Private functions */ -static void sgdma_setup_descrip(struct sgdma_descrip *desc, - struct sgdma_descrip *ndesc, +static void sgdma_setup_descrip(struct sgdma_descrip __iomem *desc, + struct sgdma_descrip __iomem *ndesc, dma_addr_t ndesc_phys, dma_addr_t raddr, dma_addr_t waddr, @@ -320,27 +314,30 @@ static void sgdma_setup_descrip(struct sgdma_descrip *desc, int wfixed) { /* Clear the next descriptor as not owned by hardware */ - u32 ctrl = ndesc->control; + + u32 ctrl = csrrd8(ndesc, sgdma_descroffs(control)); ctrl &= ~SGDMA_CONTROL_HW_OWNED; - ndesc->control = ctrl; + csrwr8(ctrl, ndesc, sgdma_descroffs(control)); - ctrl = 0; ctrl = SGDMA_CONTROL_HW_OWNED; ctrl |= generate_eop; ctrl |= rfixed; ctrl |= wfixed; /* Channel is implicitly zero, initialized to 0 by default */ - - desc->raddr = raddr; - desc->waddr = waddr; - desc->next = lower_32_bits(ndesc_phys); - desc->control = ctrl; - desc->status = 0; - desc->rburst = 0; - desc->wburst = 0; - desc->bytes = length; - desc->bytes_xferred = 0; + csrwr32(lower_32_bits(raddr), desc, sgdma_descroffs(raddr)); + csrwr32(lower_32_bits(waddr), desc, sgdma_descroffs(waddr)); + + csrwr32(0, desc, sgdma_descroffs(pad1)); + csrwr32(0, desc, sgdma_descroffs(pad2)); + csrwr32(lower_32_bits(ndesc_phys), desc, sgdma_descroffs(next)); + + csrwr8(ctrl, desc, sgdma_descroffs(control)); + csrwr8(0, desc, sgdma_descroffs(status)); + csrwr8(0, desc, sgdma_descroffs(wburst)); + csrwr8(0, desc, sgdma_descroffs(rburst)); + csrwr16(length, desc, sgdma_descroffs(bytes)); + csrwr16(0, desc, sgdma_descroffs(bytes_xferred)); } /* If hardware is busy, don't restart async read. @@ -351,12 +348,11 @@ static void sgdma_setup_descrip(struct sgdma_descrip *desc, */ static int sgdma_async_read(struct altera_tse_private *priv) { - struct sgdma_csr *csr = (struct sgdma_csr *)priv->rx_dma_csr; - struct sgdma_descrip *descbase = - (struct sgdma_descrip *)priv->rx_dma_desc; + struct sgdma_descrip __iomem *descbase = + (struct sgdma_descrip __iomem *)priv->rx_dma_desc; - struct sgdma_descrip *cdesc = &descbase[0]; - struct sgdma_descrip *ndesc = &descbase[1]; + struct sgdma_descrip __iomem *cdesc = &descbase[0]; + struct sgdma_descrip __iomem *ndesc = &descbase[1]; struct tse_buffer *rxbuffer = NULL; @@ -382,11 +378,13 @@ static int sgdma_async_read(struct altera_tse_private *priv) priv->sgdmadesclen, DMA_TO_DEVICE); - iowrite32(lower_32_bits(sgdma_rxphysaddr(priv, cdesc)), - &csr->next_descrip); + csrwr32(lower_32_bits(sgdma_rxphysaddr(priv, cdesc)), + priv->rx_dma_csr, + sgdma_csroffs(next_descrip)); - iowrite32((priv->rxctrlreg | SGDMA_CTRLREG_START), - &csr->control); + csrwr32((priv->rxctrlreg | SGDMA_CTRLREG_START), + priv->rx_dma_csr, + sgdma_csroffs(control)); return 1; } @@ -395,32 +393,32 @@ static int sgdma_async_read(struct altera_tse_private *priv) } static int sgdma_async_write(struct altera_tse_private *priv, - struct sgdma_descrip *desc) + struct sgdma_descrip __iomem *desc) { - struct sgdma_csr *csr = (struct sgdma_csr *)priv->tx_dma_csr; - if (sgdma_txbusy(priv)) return 0; /* clear control and status */ - iowrite32(0, &csr->control); - iowrite32(0x1f, &csr->status); + csrwr32(0, priv->tx_dma_csr, sgdma_csroffs(control)); + csrwr32(0x1f, priv->tx_dma_csr, sgdma_csroffs(status)); dma_sync_single_for_device(priv->device, priv->txdescphys, priv->sgdmadesclen, DMA_TO_DEVICE); - iowrite32(lower_32_bits(sgdma_txphysaddr(priv, desc)), - &csr->next_descrip); + csrwr32(lower_32_bits(sgdma_txphysaddr(priv, desc)), + priv->tx_dma_csr, + sgdma_csroffs(next_descrip)); - iowrite32((priv->txctrlreg | SGDMA_CTRLREG_START), - &csr->control); + csrwr32((priv->txctrlreg | SGDMA_CTRLREG_START), + priv->tx_dma_csr, + sgdma_csroffs(control)); return 1; } static dma_addr_t sgdma_txphysaddr(struct altera_tse_private *priv, - struct sgdma_descrip *desc) + struct sgdma_descrip __iomem *desc) { dma_addr_t paddr = priv->txdescmem_busaddr; uintptr_t offs = (uintptr_t)desc - (uintptr_t)priv->tx_dma_desc; @@ -429,7 +427,7 @@ sgdma_txphysaddr(struct altera_tse_private *priv, static dma_addr_t sgdma_rxphysaddr(struct altera_tse_private *priv, - struct sgdma_descrip *desc) + struct sgdma_descrip __iomem *desc) { dma_addr_t paddr = priv->rxdescmem_busaddr; uintptr_t offs = (uintptr_t)desc - (uintptr_t)priv->rx_dma_desc; @@ -518,8 +516,8 @@ queue_rx_peekhead(struct altera_tse_private *priv) */ static int sgdma_rxbusy(struct altera_tse_private *priv) { - struct sgdma_csr *csr = (struct sgdma_csr *)priv->rx_dma_csr; - return ioread32(&csr->status) & SGDMA_STSREG_BUSY; + return csrrd32(priv->rx_dma_csr, sgdma_csroffs(status)) + & SGDMA_STSREG_BUSY; } /* waits for the tx sgdma to finish it's current operation, returns 0 @@ -528,13 +526,14 @@ static int sgdma_rxbusy(struct altera_tse_private *priv) static int sgdma_txbusy(struct altera_tse_private *priv) { int delay = 0; - struct sgdma_csr *csr = (struct sgdma_csr *)priv->tx_dma_csr; /* if DMA is busy, wait for current transactino to finish */ - while ((ioread32(&csr->status) & SGDMA_STSREG_BUSY) && (delay++ < 100)) + while ((csrrd32(priv->tx_dma_csr, sgdma_csroffs(status)) + & SGDMA_STSREG_BUSY) && (delay++ < 100)) udelay(1); - if (ioread32(&csr->status) & SGDMA_STSREG_BUSY) { + if (csrrd32(priv->tx_dma_csr, sgdma_csroffs(status)) + & SGDMA_STSREG_BUSY) { netdev_err(priv->dev, "timeout waiting for tx dma\n"); return 1; } diff --git a/drivers/net/ethernet/altera/altera_sgdmahw.h b/drivers/net/ethernet/altera/altera_sgdmahw.h index ba3334f35383..85bc33b218d9 100644 --- a/drivers/net/ethernet/altera/altera_sgdmahw.h +++ b/drivers/net/ethernet/altera/altera_sgdmahw.h @@ -19,16 +19,16 @@ /* SGDMA descriptor structure */ struct sgdma_descrip { - unsigned int raddr; /* address of data to be read */ - unsigned int pad1; - unsigned int waddr; - unsigned int pad2; - unsigned int next; - unsigned int pad3; - unsigned short bytes; - unsigned char rburst; - unsigned char wburst; - unsigned short bytes_xferred; /* 16 bits, bytes xferred */ + u32 raddr; /* address of data to be read */ + u32 pad1; + u32 waddr; + u32 pad2; + u32 next; + u32 pad3; + u16 bytes; + u8 rburst; + u8 wburst; + u16 bytes_xferred; /* 16 bits, bytes xferred */ /* bit 0: error * bit 1: length error @@ -39,7 +39,7 @@ struct sgdma_descrip { * bit 6: reserved * bit 7: status eop for recv case */ - unsigned char status; + u8 status; /* bit 0: eop * bit 1: read_fixed @@ -47,7 +47,7 @@ struct sgdma_descrip { * bits 3,4,5,6: Channel (always 0) * bit 7: hardware owned */ - unsigned char control; + u8 control; } __packed; @@ -101,6 +101,8 @@ struct sgdma_csr { u32 pad3[3]; }; +#define sgdma_csroffs(a) (offsetof(struct sgdma_csr, a)) +#define sgdma_descroffs(a) (offsetof(struct sgdma_descrip, a)) #define SGDMA_STSREG_ERR BIT(0) /* Error */ #define SGDMA_STSREG_EOP BIT(1) /* EOP */ diff --git a/drivers/net/ethernet/altera/altera_tse.h b/drivers/net/ethernet/altera/altera_tse.h index 465c4aabebbd..2adb24d4523c 100644 --- a/drivers/net/ethernet/altera/altera_tse.h +++ b/drivers/net/ethernet/altera/altera_tse.h @@ -357,6 +357,8 @@ struct altera_tse_mac { u32 reserved5[42]; }; +#define tse_csroffs(a) (offsetof(struct altera_tse_mac, a)) + /* Transmit and Receive Command Registers Bit Definitions */ #define ALTERA_TSE_TX_CMD_STAT_OMIT_CRC BIT(17) @@ -487,4 +489,49 @@ struct altera_tse_private { */ void altera_tse_set_ethtool_ops(struct net_device *); +static inline +u32 csrrd32(void __iomem *mac, size_t offs) +{ + void __iomem *paddr = (void __iomem *)((uintptr_t)mac + offs); + return readl(paddr); +} + +static inline +u16 csrrd16(void __iomem *mac, size_t offs) +{ + void __iomem *paddr = (void __iomem *)((uintptr_t)mac + offs); + return readw(paddr); +} + +static inline +u8 csrrd8(void __iomem *mac, size_t offs) +{ + void __iomem *paddr = (void __iomem *)((uintptr_t)mac + offs); + return readb(paddr); +} + +static inline +void csrwr32(u32 val, void __iomem *mac, size_t offs) +{ + void __iomem *paddr = (void __iomem *)((uintptr_t)mac + offs); + + writel(val, paddr); +} + +static inline +void csrwr16(u16 val, void __iomem *mac, size_t offs) +{ + void __iomem *paddr = (void __iomem *)((uintptr_t)mac + offs); + + writew(val, paddr); +} + +static inline +void csrwr8(u8 val, void __iomem *mac, size_t offs) +{ + void __iomem *paddr = (void __iomem *)((uintptr_t)mac + offs); + + writeb(val, paddr); +} + #endif /* __ALTERA_TSE_H__ */ diff --git a/drivers/net/ethernet/altera/altera_tse_ethtool.c b/drivers/net/ethernet/altera/altera_tse_ethtool.c index 76133caffa78..54c25eff7952 100644 --- a/drivers/net/ethernet/altera/altera_tse_ethtool.c +++ b/drivers/net/ethernet/altera/altera_tse_ethtool.c @@ -96,54 +96,89 @@ static void tse_fill_stats(struct net_device *dev, struct ethtool_stats *dummy, u64 *buf) { struct altera_tse_private *priv = netdev_priv(dev); - struct altera_tse_mac *mac = priv->mac_dev; u64 ext; - buf[0] = ioread32(&mac->frames_transmitted_ok); - buf[1] = ioread32(&mac->frames_received_ok); - buf[2] = ioread32(&mac->frames_check_sequence_errors); - buf[3] = ioread32(&mac->alignment_errors); + buf[0] = csrrd32(priv->mac_dev, + tse_csroffs(frames_transmitted_ok)); + buf[1] = csrrd32(priv->mac_dev, + tse_csroffs(frames_received_ok)); + buf[2] = csrrd32(priv->mac_dev, + tse_csroffs(frames_check_sequence_errors)); + buf[3] = csrrd32(priv->mac_dev, + tse_csroffs(alignment_errors)); /* Extended aOctetsTransmittedOK counter */ - ext = (u64) ioread32(&mac->msb_octets_transmitted_ok) << 32; - ext |= ioread32(&mac->octets_transmitted_ok); + ext = (u64) csrrd32(priv->mac_dev, + tse_csroffs(msb_octets_transmitted_ok)) << 32; + + ext |= csrrd32(priv->mac_dev, + tse_csroffs(octets_transmitted_ok)); buf[4] = ext; /* Extended aOctetsReceivedOK counter */ - ext = (u64) ioread32(&mac->msb_octets_received_ok) << 32; - ext |= ioread32(&mac->octets_received_ok); + ext = (u64) csrrd32(priv->mac_dev, + tse_csroffs(msb_octets_received_ok)) << 32; + + ext |= csrrd32(priv->mac_dev, + tse_csroffs(octets_received_ok)); buf[5] = ext; - buf[6] = ioread32(&mac->tx_pause_mac_ctrl_frames); - buf[7] = ioread32(&mac->rx_pause_mac_ctrl_frames); - buf[8] = ioread32(&mac->if_in_errors); - buf[9] = ioread32(&mac->if_out_errors); - buf[10] = ioread32(&mac->if_in_ucast_pkts); - buf[11] = ioread32(&mac->if_in_multicast_pkts); - buf[12] = ioread32(&mac->if_in_broadcast_pkts); - buf[13] = ioread32(&mac->if_out_discards); - buf[14] = ioread32(&mac->if_out_ucast_pkts); - buf[15] = ioread32(&mac->if_out_multicast_pkts); - buf[16] = ioread32(&mac->if_out_broadcast_pkts); - buf[17] = ioread32(&mac->ether_stats_drop_events); + buf[6] = csrrd32(priv->mac_dev, + tse_csroffs(tx_pause_mac_ctrl_frames)); + buf[7] = csrrd32(priv->mac_dev, + tse_csroffs(rx_pause_mac_ctrl_frames)); + buf[8] = csrrd32(priv->mac_dev, + tse_csroffs(if_in_errors)); + buf[9] = csrrd32(priv->mac_dev, + tse_csroffs(if_out_errors)); + buf[10] = csrrd32(priv->mac_dev, + tse_csroffs(if_in_ucast_pkts)); + buf[11] = csrrd32(priv->mac_dev, + tse_csroffs(if_in_multicast_pkts)); + buf[12] = csrrd32(priv->mac_dev, + tse_csroffs(if_in_broadcast_pkts)); + buf[13] = csrrd32(priv->mac_dev, + tse_csroffs(if_out_discards)); + buf[14] = csrrd32(priv->mac_dev, + tse_csroffs(if_out_ucast_pkts)); + buf[15] = csrrd32(priv->mac_dev, + tse_csroffs(if_out_multicast_pkts)); + buf[16] = csrrd32(priv->mac_dev, + tse_csroffs(if_out_broadcast_pkts)); + buf[17] = csrrd32(priv->mac_dev, + tse_csroffs(ether_stats_drop_events)); /* Extended etherStatsOctets counter */ - ext = (u64) ioread32(&mac->msb_ether_stats_octets) << 32; - ext |= ioread32(&mac->ether_stats_octets); + ext = (u64) csrrd32(priv->mac_dev, + tse_csroffs(msb_ether_stats_octets)) << 32; + ext |= csrrd32(priv->mac_dev, + tse_csroffs(ether_stats_octets)); buf[18] = ext; - buf[19] = ioread32(&mac->ether_stats_pkts); - buf[20] = ioread32(&mac->ether_stats_undersize_pkts); - buf[21] = ioread32(&mac->ether_stats_oversize_pkts); - buf[22] = ioread32(&mac->ether_stats_pkts_64_octets); - buf[23] = ioread32(&mac->ether_stats_pkts_65to127_octets); - buf[24] = ioread32(&mac->ether_stats_pkts_128to255_octets); - buf[25] = ioread32(&mac->ether_stats_pkts_256to511_octets); - buf[26] = ioread32(&mac->ether_stats_pkts_512to1023_octets); - buf[27] = ioread32(&mac->ether_stats_pkts_1024to1518_octets); - buf[28] = ioread32(&mac->ether_stats_pkts_1519tox_octets); - buf[29] = ioread32(&mac->ether_stats_jabbers); - buf[30] = ioread32(&mac->ether_stats_fragments); + buf[19] = csrrd32(priv->mac_dev, + tse_csroffs(ether_stats_pkts)); + buf[20] = csrrd32(priv->mac_dev, + tse_csroffs(ether_stats_undersize_pkts)); + buf[21] = csrrd32(priv->mac_dev, + tse_csroffs(ether_stats_oversize_pkts)); + buf[22] = csrrd32(priv->mac_dev, + tse_csroffs(ether_stats_pkts_64_octets)); + buf[23] = csrrd32(priv->mac_dev, + tse_csroffs(ether_stats_pkts_65to127_octets)); + buf[24] = csrrd32(priv->mac_dev, + tse_csroffs(ether_stats_pkts_128to255_octets)); + buf[25] = csrrd32(priv->mac_dev, + tse_csroffs(ether_stats_pkts_256to511_octets)); + buf[26] = csrrd32(priv->mac_dev, + tse_csroffs(ether_stats_pkts_512to1023_octets)); + buf[27] = csrrd32(priv->mac_dev, + tse_csroffs(ether_stats_pkts_1024to1518_octets)); + buf[28] = csrrd32(priv->mac_dev, + tse_csroffs(ether_stats_pkts_1519tox_octets)); + buf[29] = csrrd32(priv->mac_dev, + tse_csroffs(ether_stats_jabbers)); + buf[30] = csrrd32(priv->mac_dev, + tse_csroffs(ether_stats_fragments)); } static int tse_sset_count(struct net_device *dev, int sset) @@ -178,7 +213,6 @@ static void tse_get_regs(struct net_device *dev, struct ethtool_regs *regs, { int i; struct altera_tse_private *priv = netdev_priv(dev); - u32 *tse_mac_regs = (u32 *)priv->mac_dev; u32 *buf = regbuf; /* Set version to a known value, so ethtool knows @@ -196,7 +230,7 @@ static void tse_get_regs(struct net_device *dev, struct ethtool_regs *regs, regs->version = 1; for (i = 0; i < TSE_NUM_REGS; i++) - buf[i] = ioread32(&tse_mac_regs[i]); + buf[i] = csrrd32(priv->mac_dev, i * 4); } static int tse_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) diff --git a/drivers/net/ethernet/altera/altera_tse_main.c b/drivers/net/ethernet/altera/altera_tse_main.c index e44a4aeb9701..ecc3b4e4588b 100644 --- a/drivers/net/ethernet/altera/altera_tse_main.c +++ b/drivers/net/ethernet/altera/altera_tse_main.c @@ -100,29 +100,30 @@ static inline u32 tse_tx_avail(struct altera_tse_private *priv) */ static int altera_tse_mdio_read(struct mii_bus *bus, int mii_id, int regnum) { - struct altera_tse_mac *mac = (struct altera_tse_mac *)bus->priv; - unsigned int *mdio_regs = (unsigned int *)&mac->mdio_phy0; - u32 data; + struct net_device *ndev = bus->priv; + struct altera_tse_private *priv = netdev_priv(ndev); /* set MDIO address */ - iowrite32((mii_id & 0x1f), &mac->mdio_phy0_addr); + csrwr32((mii_id & 0x1f), priv->mac_dev, + tse_csroffs(mdio_phy0_addr)); /* get the data */ - data = ioread32(&mdio_regs[regnum]) & 0xffff; - return data; + return csrrd32(priv->mac_dev, + tse_csroffs(mdio_phy0) + regnum * 4) & 0xffff; } static int altera_tse_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value) { - struct altera_tse_mac *mac = (struct altera_tse_mac *)bus->priv; - unsigned int *mdio_regs = (unsigned int *)&mac->mdio_phy0; + struct net_device *ndev = bus->priv; + struct altera_tse_private *priv = netdev_priv(ndev); /* set MDIO address */ - iowrite32((mii_id & 0x1f), &mac->mdio_phy0_addr); + csrwr32((mii_id & 0x1f), priv->mac_dev, + tse_csroffs(mdio_phy0_addr)); /* write the data */ - iowrite32((u32) value, &mdio_regs[regnum]); + csrwr32(value, priv->mac_dev, tse_csroffs(mdio_phy0) + regnum * 4); return 0; } @@ -168,7 +169,7 @@ static int altera_tse_mdio_create(struct net_device *dev, unsigned int id) for (i = 0; i < PHY_MAX_ADDR; i++) mdio->irq[i] = PHY_POLL; - mdio->priv = priv->mac_dev; + mdio->priv = dev; mdio->parent = priv->device; ret = of_mdiobus_register(mdio, mdio_node); @@ -563,7 +564,6 @@ static int tse_start_xmit(struct sk_buff *skb, struct net_device *dev) unsigned int nopaged_len = skb_headlen(skb); enum netdev_tx ret = NETDEV_TX_OK; dma_addr_t dma_addr; - int txcomplete = 0; spin_lock_bh(&priv->tx_lock); @@ -599,7 +599,7 @@ static int tse_start_xmit(struct sk_buff *skb, struct net_device *dev) dma_sync_single_for_device(priv->device, buffer->dma_addr, buffer->len, DMA_TO_DEVICE); - txcomplete = priv->dmaops->tx_buffer(priv, buffer); + priv->dmaops->tx_buffer(priv, buffer); skb_tx_timestamp(skb); @@ -698,7 +698,6 @@ static struct phy_device *connect_local_phy(struct net_device *dev) struct altera_tse_private *priv = netdev_priv(dev); struct phy_device *phydev = NULL; char phy_id_fmt[MII_BUS_ID_SIZE + 3]; - int ret; if (priv->phy_addr != POLL_PHY) { snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, @@ -712,6 +711,7 @@ static struct phy_device *connect_local_phy(struct net_device *dev) netdev_err(dev, "Could not attach to PHY\n"); } else { + int ret; phydev = phy_find_first(priv->mdio); if (phydev == NULL) { netdev_err(dev, "No PHY found\n"); @@ -791,7 +791,6 @@ static int init_phy(struct net_device *dev) static void tse_update_mac_addr(struct altera_tse_private *priv, u8 *addr) { - struct altera_tse_mac *mac = priv->mac_dev; u32 msb; u32 lsb; @@ -799,8 +798,8 @@ static void tse_update_mac_addr(struct altera_tse_private *priv, u8 *addr) lsb = ((addr[5] << 8) | addr[4]) & 0xffff; /* Set primary MAC address */ - iowrite32(msb, &mac->mac_addr_0); - iowrite32(lsb, &mac->mac_addr_1); + csrwr32(msb, priv->mac_dev, tse_csroffs(mac_addr_0)); + csrwr32(lsb, priv->mac_dev, tse_csroffs(mac_addr_1)); } /* MAC software reset. @@ -811,26 +810,26 @@ static void tse_update_mac_addr(struct altera_tse_private *priv, u8 *addr) */ static int reset_mac(struct altera_tse_private *priv) { - void __iomem *cmd_cfg_reg = &priv->mac_dev->command_config; int counter; u32 dat; - dat = ioread32(cmd_cfg_reg); + dat = csrrd32(priv->mac_dev, tse_csroffs(command_config)); dat &= ~(MAC_CMDCFG_TX_ENA | MAC_CMDCFG_RX_ENA); dat |= MAC_CMDCFG_SW_RESET | MAC_CMDCFG_CNT_RESET; - iowrite32(dat, cmd_cfg_reg); + csrwr32(dat, priv->mac_dev, tse_csroffs(command_config)); counter = 0; while (counter++ < ALTERA_TSE_SW_RESET_WATCHDOG_CNTR) { - if (tse_bit_is_clear(cmd_cfg_reg, MAC_CMDCFG_SW_RESET)) + if (tse_bit_is_clear(priv->mac_dev, tse_csroffs(command_config), + MAC_CMDCFG_SW_RESET)) break; udelay(1); } if (counter >= ALTERA_TSE_SW_RESET_WATCHDOG_CNTR) { - dat = ioread32(cmd_cfg_reg); + dat = csrrd32(priv->mac_dev, tse_csroffs(command_config)); dat &= ~MAC_CMDCFG_SW_RESET; - iowrite32(dat, cmd_cfg_reg); + csrwr32(dat, priv->mac_dev, tse_csroffs(command_config)); return -1; } return 0; @@ -840,41 +839,57 @@ static int reset_mac(struct altera_tse_private *priv) */ static int init_mac(struct altera_tse_private *priv) { - struct altera_tse_mac *mac = priv->mac_dev; unsigned int cmd = 0; u32 frm_length; /* Setup Rx FIFO */ - iowrite32(priv->rx_fifo_depth - ALTERA_TSE_RX_SECTION_EMPTY, - &mac->rx_section_empty); - iowrite32(ALTERA_TSE_RX_SECTION_FULL, &mac->rx_section_full); - iowrite32(ALTERA_TSE_RX_ALMOST_EMPTY, &mac->rx_almost_empty); - iowrite32(ALTERA_TSE_RX_ALMOST_FULL, &mac->rx_almost_full); + csrwr32(priv->rx_fifo_depth - ALTERA_TSE_RX_SECTION_EMPTY, + priv->mac_dev, tse_csroffs(rx_section_empty)); + + csrwr32(ALTERA_TSE_RX_SECTION_FULL, priv->mac_dev, + tse_csroffs(rx_section_full)); + + csrwr32(ALTERA_TSE_RX_ALMOST_EMPTY, priv->mac_dev, + tse_csroffs(rx_almost_empty)); + + csrwr32(ALTERA_TSE_RX_ALMOST_FULL, priv->mac_dev, + tse_csroffs(rx_almost_full)); /* Setup Tx FIFO */ - iowrite32(priv->tx_fifo_depth - ALTERA_TSE_TX_SECTION_EMPTY, - &mac->tx_section_empty); - iowrite32(ALTERA_TSE_TX_SECTION_FULL, &mac->tx_section_full); - iowrite32(ALTERA_TSE_TX_ALMOST_EMPTY, &mac->tx_almost_empty); - iowrite32(ALTERA_TSE_TX_ALMOST_FULL, &mac->tx_almost_full); + csrwr32(priv->tx_fifo_depth - ALTERA_TSE_TX_SECTION_EMPTY, + priv->mac_dev, tse_csroffs(tx_section_empty)); + + csrwr32(ALTERA_TSE_TX_SECTION_FULL, priv->mac_dev, + tse_csroffs(tx_section_full)); + + csrwr32(ALTERA_TSE_TX_ALMOST_EMPTY, priv->mac_dev, + tse_csroffs(tx_almost_empty)); + + csrwr32(ALTERA_TSE_TX_ALMOST_FULL, priv->mac_dev, + tse_csroffs(tx_almost_full)); /* MAC Address Configuration */ tse_update_mac_addr(priv, priv->dev->dev_addr); /* MAC Function Configuration */ frm_length = ETH_HLEN + priv->dev->mtu + ETH_FCS_LEN; - iowrite32(frm_length, &mac->frm_length); - iowrite32(ALTERA_TSE_TX_IPG_LENGTH, &mac->tx_ipg_length); + csrwr32(frm_length, priv->mac_dev, tse_csroffs(frm_length)); + + csrwr32(ALTERA_TSE_TX_IPG_LENGTH, priv->mac_dev, + tse_csroffs(tx_ipg_length)); /* Disable RX/TX shift 16 for alignment of all received frames on 16-bit * start address */ - tse_set_bit(&mac->rx_cmd_stat, ALTERA_TSE_RX_CMD_STAT_RX_SHIFT16); - tse_clear_bit(&mac->tx_cmd_stat, ALTERA_TSE_TX_CMD_STAT_TX_SHIFT16 | - ALTERA_TSE_TX_CMD_STAT_OMIT_CRC); + tse_set_bit(priv->mac_dev, tse_csroffs(rx_cmd_stat), + ALTERA_TSE_RX_CMD_STAT_RX_SHIFT16); + + tse_clear_bit(priv->mac_dev, tse_csroffs(tx_cmd_stat), + ALTERA_TSE_TX_CMD_STAT_TX_SHIFT16 | + ALTERA_TSE_TX_CMD_STAT_OMIT_CRC); /* Set the MAC options */ - cmd = ioread32(&mac->command_config); + cmd = csrrd32(priv->mac_dev, tse_csroffs(command_config)); cmd &= ~MAC_CMDCFG_PAD_EN; /* No padding Removal on Receive */ cmd &= ~MAC_CMDCFG_CRC_FWD; /* CRC Removal */ cmd |= MAC_CMDCFG_RX_ERR_DISC; /* Automatically discard frames @@ -889,9 +904,10 @@ static int init_mac(struct altera_tse_private *priv) cmd &= ~MAC_CMDCFG_ETH_SPEED; cmd &= ~MAC_CMDCFG_ENA_10; - iowrite32(cmd, &mac->command_config); + csrwr32(cmd, priv->mac_dev, tse_csroffs(command_config)); - iowrite32(ALTERA_TSE_PAUSE_QUANTA, &mac->pause_quanta); + csrwr32(ALTERA_TSE_PAUSE_QUANTA, priv->mac_dev, + tse_csroffs(pause_quanta)); if (netif_msg_hw(priv)) dev_dbg(priv->device, @@ -904,15 +920,14 @@ static int init_mac(struct altera_tse_private *priv) */ static void tse_set_mac(struct altera_tse_private *priv, bool enable) { - struct altera_tse_mac *mac = priv->mac_dev; - u32 value = ioread32(&mac->command_config); + u32 value = csrrd32(priv->mac_dev, tse_csroffs(command_config)); if (enable) value |= MAC_CMDCFG_TX_ENA | MAC_CMDCFG_RX_ENA; else value &= ~(MAC_CMDCFG_TX_ENA | MAC_CMDCFG_RX_ENA); - iowrite32(value, &mac->command_config); + csrwr32(value, priv->mac_dev, tse_csroffs(command_config)); } /* Change the MTU @@ -942,13 +957,12 @@ static int tse_change_mtu(struct net_device *dev, int new_mtu) static void altera_tse_set_mcfilter(struct net_device *dev) { struct altera_tse_private *priv = netdev_priv(dev); - struct altera_tse_mac *mac = priv->mac_dev; int i; struct netdev_hw_addr *ha; /* clear the hash filter */ for (i = 0; i < 64; i++) - iowrite32(0, &(mac->hash_table[i])); + csrwr32(0, priv->mac_dev, tse_csroffs(hash_table) + i * 4); netdev_for_each_mc_addr(ha, dev) { unsigned int hash = 0; @@ -964,7 +978,7 @@ static void altera_tse_set_mcfilter(struct net_device *dev) hash = (hash << 1) | xor_bit; } - iowrite32(1, &(mac->hash_table[hash])); + csrwr32(1, priv->mac_dev, tse_csroffs(hash_table) + hash * 4); } } @@ -972,12 +986,11 @@ static void altera_tse_set_mcfilter(struct net_device *dev) static void altera_tse_set_mcfilterall(struct net_device *dev) { struct altera_tse_private *priv = netdev_priv(dev); - struct altera_tse_mac *mac = priv->mac_dev; int i; /* set the hash filter */ for (i = 0; i < 64; i++) - iowrite32(1, &(mac->hash_table[i])); + csrwr32(1, priv->mac_dev, tse_csroffs(hash_table) + i * 4); } /* Set or clear the multicast filter for this adaptor @@ -985,12 +998,12 @@ static void altera_tse_set_mcfilterall(struct net_device *dev) static void tse_set_rx_mode_hashfilter(struct net_device *dev) { struct altera_tse_private *priv = netdev_priv(dev); - struct altera_tse_mac *mac = priv->mac_dev; spin_lock(&priv->mac_cfg_lock); if (dev->flags & IFF_PROMISC) - tse_set_bit(&mac->command_config, MAC_CMDCFG_PROMIS_EN); + tse_set_bit(priv->mac_dev, tse_csroffs(command_config), + MAC_CMDCFG_PROMIS_EN); if (dev->flags & IFF_ALLMULTI) altera_tse_set_mcfilterall(dev); @@ -1005,15 +1018,16 @@ static void tse_set_rx_mode_hashfilter(struct net_device *dev) static void tse_set_rx_mode(struct net_device *dev) { struct altera_tse_private *priv = netdev_priv(dev); - struct altera_tse_mac *mac = priv->mac_dev; spin_lock(&priv->mac_cfg_lock); if ((dev->flags & IFF_PROMISC) || (dev->flags & IFF_ALLMULTI) || !netdev_mc_empty(dev) || !netdev_uc_empty(dev)) - tse_set_bit(&mac->command_config, MAC_CMDCFG_PROMIS_EN); + tse_set_bit(priv->mac_dev, tse_csroffs(command_config), + MAC_CMDCFG_PROMIS_EN); else - tse_clear_bit(&mac->command_config, MAC_CMDCFG_PROMIS_EN); + tse_clear_bit(priv->mac_dev, tse_csroffs(command_config), + MAC_CMDCFG_PROMIS_EN); spin_unlock(&priv->mac_cfg_lock); } @@ -1493,7 +1507,7 @@ static int altera_tse_remove(struct platform_device *pdev) return 0; } -struct altera_dmaops altera_dtype_sgdma = { +static const struct altera_dmaops altera_dtype_sgdma = { .altera_dtype = ALTERA_DTYPE_SGDMA, .dmamask = 32, .reset_dma = sgdma_reset, @@ -1512,7 +1526,7 @@ struct altera_dmaops altera_dtype_sgdma = { .start_rxdma = sgdma_start_rxdma, }; -struct altera_dmaops altera_dtype_msgdma = { +static const struct altera_dmaops altera_dtype_msgdma = { .altera_dtype = ALTERA_DTYPE_MSGDMA, .dmamask = 64, .reset_dma = msgdma_reset, diff --git a/drivers/net/ethernet/altera/altera_utils.c b/drivers/net/ethernet/altera/altera_utils.c index 70fa13f486b2..d7eeb1713ad2 100644 --- a/drivers/net/ethernet/altera/altera_utils.c +++ b/drivers/net/ethernet/altera/altera_utils.c @@ -17,28 +17,28 @@ #include "altera_tse.h" #include "altera_utils.h" -void tse_set_bit(void __iomem *ioaddr, u32 bit_mask) +void tse_set_bit(void __iomem *ioaddr, size_t offs, u32 bit_mask) { - u32 value = ioread32(ioaddr); + u32 value = csrrd32(ioaddr, offs); value |= bit_mask; - iowrite32(value, ioaddr); + csrwr32(value, ioaddr, offs); } -void tse_clear_bit(void __iomem *ioaddr, u32 bit_mask) +void tse_clear_bit(void __iomem *ioaddr, size_t offs, u32 bit_mask) { - u32 value = ioread32(ioaddr); + u32 value = csrrd32(ioaddr, offs); value &= ~bit_mask; - iowrite32(value, ioaddr); + csrwr32(value, ioaddr, offs); } -int tse_bit_is_set(void __iomem *ioaddr, u32 bit_mask) +int tse_bit_is_set(void __iomem *ioaddr, size_t offs, u32 bit_mask) { - u32 value = ioread32(ioaddr); + u32 value = csrrd32(ioaddr, offs); return (value & bit_mask) ? 1 : 0; } -int tse_bit_is_clear(void __iomem *ioaddr, u32 bit_mask) +int tse_bit_is_clear(void __iomem *ioaddr, size_t offs, u32 bit_mask) { - u32 value = ioread32(ioaddr); + u32 value = csrrd32(ioaddr, offs); return (value & bit_mask) ? 0 : 1; } diff --git a/drivers/net/ethernet/altera/altera_utils.h b/drivers/net/ethernet/altera/altera_utils.h index ce1db36d3583..baf100ccf587 100644 --- a/drivers/net/ethernet/altera/altera_utils.h +++ b/drivers/net/ethernet/altera/altera_utils.h @@ -19,9 +19,9 @@ #ifndef __ALTERA_UTILS_H__ #define __ALTERA_UTILS_H__ -void tse_set_bit(void __iomem *ioaddr, u32 bit_mask); -void tse_clear_bit(void __iomem *ioaddr, u32 bit_mask); -int tse_bit_is_set(void __iomem *ioaddr, u32 bit_mask); -int tse_bit_is_clear(void __iomem *ioaddr, u32 bit_mask); +void tse_set_bit(void __iomem *ioaddr, size_t offs, u32 bit_mask); +void tse_clear_bit(void __iomem *ioaddr, size_t offs, u32 bit_mask); +int tse_bit_is_set(void __iomem *ioaddr, size_t offs, u32 bit_mask); +int tse_bit_is_clear(void __iomem *ioaddr, size_t offs, u32 bit_mask); #endif /* __ALTERA_UTILS_H__*/ -- cgit v1.2.3 From d91e5c02555ae838e9d783b9e83e125fd10dca73 Mon Sep 17 00:00:00 2001 From: Vince Bridgers Date: Wed, 14 May 2014 14:38:37 -0500 Subject: Altera TSE: Disable Multicast filtering to workaround problem This patch disables multicast hash filtering if present in the hardware and uses promiscuous mode instead until the problem with multicast filtering has been debugged, integrated and tested. Signed-off-by: Vince Bridgers Signed-off-by: David S. Miller --- drivers/net/ethernet/altera/altera_tse_main.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/ethernet/altera/altera_tse_main.c b/drivers/net/ethernet/altera/altera_tse_main.c index ecc3b4e4588b..7330681574d2 100644 --- a/drivers/net/ethernet/altera/altera_tse_main.c +++ b/drivers/net/ethernet/altera/altera_tse_main.c @@ -1376,6 +1376,11 @@ static int altera_tse_probe(struct platform_device *pdev) of_property_read_bool(pdev->dev.of_node, "altr,has-hash-multicast-filter"); + /* Set hash filter to not set for now until the + * multicast filter receive issue is debugged + */ + priv->hash_filter = 0; + /* get supplemental address settings for this instance */ priv->added_unicast = of_property_read_bool(pdev->dev.of_node, -- cgit v1.2.3 From 448ba904160f9d8f69217c28a1692cee5afbff88 Mon Sep 17 00:00:00 2001 From: Andy Grover Date: Tue, 15 Apr 2014 14:13:12 -0700 Subject: target: Allow non-supporting backends to set pi_prot_type to 0 Userspace tools assume if a value is read from configfs, it is valid and will not cause an error if the same value is written back. The only valid value for pi_prot_type for backends not supporting DIF is 0, so allow this particular value to be set without returning an error. Reported-by: Krzysztof Chojnowski Signed-off-by: Andy Grover Reviewed-by: Sagi Grimberg Cc: stable@vger.kernel.org # 3.14+ Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_device.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 65001e133670..382b66b212ae 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -936,6 +936,10 @@ int se_dev_set_pi_prot_type(struct se_device *dev, int flag) return 0; } if (!dev->transport->init_prot || !dev->transport->free_prot) { + /* 0 is only allowed value for non-supporting backends */ + if (flag == 0) + return 0; + pr_err("DIF protection not supported by backend: %s\n", dev->transport->name); return -ENOSYS; -- cgit v1.2.3 From 9fe63c88b1d59f1ce054d6948ccd3096496ecedb Mon Sep 17 00:00:00 2001 From: Sagi Grimberg Date: Tue, 29 Apr 2014 13:13:44 +0300 Subject: Target/iser: Fix wrong connection requests list addition Should be adding list_add_tail($new, $head) and not the other way around. Signed-off-by: Sagi Grimberg Cc: stable@vger.kernel.org # 3.10+ Signed-off-by: Nicholas Bellinger --- drivers/infiniband/ulp/isert/ib_isert.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index c98fdb185931..fda3feb45008 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c @@ -663,7 +663,7 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) goto out_conn_dev; mutex_lock(&isert_np->np_accept_mutex); - list_add_tail(&isert_np->np_accept_list, &isert_conn->conn_accept_node); + list_add_tail(&isert_conn->conn_accept_node, &isert_np->np_accept_list); mutex_unlock(&isert_np->np_accept_mutex); pr_debug("isert_connect_request() waking up np_accept_wq: %p\n", np); -- cgit v1.2.3 From 531b7bf4bd795d9a09eac92504322a472c010bc8 Mon Sep 17 00:00:00 2001 From: Sagi Grimberg Date: Tue, 29 Apr 2014 13:13:45 +0300 Subject: Target/iser: Fix iscsit_accept_np and rdma_cm racy flow RDMA CM and iSCSI target flows are asynchronous and completely uncorrelated. Relying on the fact that iscsi_accept_np will be called after CM connection request event and will wait for it is a mistake. When attempting to login to a few targets this flow is racy and unpredictable, but for parallel login to dozens of targets will race and hang every time. The correct synchronizing mechanism in this case is pending on a semaphore rather than a wait_for_event. We keep the pending interruptible for iscsi_np cleanup stage. (Squash patch to remove dead code into parent - nab) Reported-by: Slava Shwartsman Signed-off-by: Sagi Grimberg Cc: stable@vger.kernel.org # 3.10+ Signed-off-by: Nicholas Bellinger --- drivers/infiniband/ulp/isert/ib_isert.c | 25 ++++++------------------- drivers/infiniband/ulp/isert/ib_isert.h | 2 +- 2 files changed, 7 insertions(+), 20 deletions(-) diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index fda3feb45008..826eaf5741f6 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "isert_proto.h" #include "ib_isert.h" @@ -666,8 +667,8 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) list_add_tail(&isert_conn->conn_accept_node, &isert_np->np_accept_list); mutex_unlock(&isert_np->np_accept_mutex); - pr_debug("isert_connect_request() waking up np_accept_wq: %p\n", np); - wake_up(&isert_np->np_accept_wq); + pr_debug("isert_connect_request() up np_sem np: %p\n", np); + up(&isert_np->np_sem); return 0; out_conn_dev: @@ -2999,7 +3000,7 @@ isert_setup_np(struct iscsi_np *np, pr_err("Unable to allocate struct isert_np\n"); return -ENOMEM; } - init_waitqueue_head(&isert_np->np_accept_wq); + sema_init(&isert_np->np_sem, 0); mutex_init(&isert_np->np_accept_mutex); INIT_LIST_HEAD(&isert_np->np_accept_list); init_completion(&isert_np->np_login_comp); @@ -3047,18 +3048,6 @@ out: return ret; } -static int -isert_check_accept_queue(struct isert_np *isert_np) -{ - int empty; - - mutex_lock(&isert_np->np_accept_mutex); - empty = list_empty(&isert_np->np_accept_list); - mutex_unlock(&isert_np->np_accept_mutex); - - return empty; -} - static int isert_rdma_accept(struct isert_conn *isert_conn) { @@ -3151,16 +3140,14 @@ isert_accept_np(struct iscsi_np *np, struct iscsi_conn *conn) int max_accept = 0, ret; accept_wait: - ret = wait_event_interruptible(isert_np->np_accept_wq, - !isert_check_accept_queue(isert_np) || - np->np_thread_state == ISCSI_NP_THREAD_RESET); + ret = down_interruptible(&isert_np->np_sem); if (max_accept > 5) return -ENODEV; spin_lock_bh(&np->np_thread_lock); if (np->np_thread_state == ISCSI_NP_THREAD_RESET) { spin_unlock_bh(&np->np_thread_lock); - pr_err("ISCSI_NP_THREAD_RESET for isert_accept_np\n"); + pr_debug("ISCSI_NP_THREAD_RESET for isert_accept_np\n"); return -ENODEV; } spin_unlock_bh(&np->np_thread_lock); diff --git a/drivers/infiniband/ulp/isert/ib_isert.h b/drivers/infiniband/ulp/isert/ib_isert.h index 4c072ae34c01..da6612e68000 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.h +++ b/drivers/infiniband/ulp/isert/ib_isert.h @@ -182,7 +182,7 @@ struct isert_device { }; struct isert_np { - wait_queue_head_t np_accept_wq; + struct semaphore np_sem; struct rdma_cm_id *np_cm_id; struct mutex np_accept_mutex; struct list_head np_accept_list; -- cgit v1.2.3 From 14f4b54fe38f3a8f8392a50b951c8aa43b63687a Mon Sep 17 00:00:00 2001 From: Sagi Grimberg Date: Tue, 29 Apr 2014 13:13:47 +0300 Subject: Target/iscsi,iser: Avoid accepting transport connections during stop stage When the target is in stop stage, iSER transport initiates RDMA disconnects. The iSER initiator may wish to establish a new connection over the still existing network portal. In this case iSER transport should not accept and resume new RDMA connections. In order to learn that, iscsi_np is added with enabled flag so the iSER transport can check when deciding weather to accept and resume a new connection request. The iscsi_np is enabled after successful transport setup, and disabled before iscsi_np login threads are cleaned up. Signed-off-by: Sagi Grimberg Cc: stable@vger.kernel.org # 3.10+ Signed-off-by: Nicholas Bellinger --- drivers/infiniband/ulp/isert/ib_isert.c | 11 ++++++++++- drivers/target/iscsi/iscsi_target_core.h | 1 + drivers/target/iscsi/iscsi_target_login.c | 1 + drivers/target/iscsi/iscsi_target_tpg.c | 1 + 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index 826eaf5741f6..a1710465faaf 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c @@ -562,7 +562,15 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) struct isert_device *device; struct ib_device *ib_dev = cma_id->device; int ret = 0; - u8 pi_support = np->tpg_np->tpg->tpg_attrib.t10_pi; + u8 pi_support; + + spin_lock_bh(&np->np_thread_lock); + if (!np->enabled) { + spin_unlock_bh(&np->np_thread_lock); + pr_debug("iscsi_np is not enabled, reject connect request\n"); + return rdma_reject(cma_id, NULL, 0); + } + spin_unlock_bh(&np->np_thread_lock); pr_debug("Entering isert_connect_request cma_id: %p, context: %p\n", cma_id, cma_id->context); @@ -653,6 +661,7 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) goto out_mr; } + pi_support = np->tpg_np->tpg->tpg_attrib.t10_pi; if (pi_support && !device->pi_capable) { pr_err("Protection information requested but not supported\n"); ret = -EINVAL; diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h index 6960f22909ae..302eb3b78715 100644 --- a/drivers/target/iscsi/iscsi_target_core.h +++ b/drivers/target/iscsi/iscsi_target_core.h @@ -775,6 +775,7 @@ struct iscsi_np { int np_ip_proto; int np_sock_type; enum np_thread_state_table np_thread_state; + bool enabled; enum iscsi_timer_flags_table np_login_timer_flags; u32 np_exports; enum np_flags_table np_flags; diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index 8739b98f6f93..b72d8550e8bc 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c @@ -984,6 +984,7 @@ int iscsi_target_setup_login_socket( } np->np_transport = t; + np->enabled = true; return 0; } diff --git a/drivers/target/iscsi/iscsi_target_tpg.c b/drivers/target/iscsi/iscsi_target_tpg.c index eb96b20dc09e..ca1811858afd 100644 --- a/drivers/target/iscsi/iscsi_target_tpg.c +++ b/drivers/target/iscsi/iscsi_target_tpg.c @@ -184,6 +184,7 @@ static void iscsit_clear_tpg_np_login_thread( return; } + tpg_np->tpg_np->enabled = false; iscsit_reset_np_thread(tpg_np->tpg_np, tpg_np, tpg, shutdown); } -- cgit v1.2.3 From 7cbfcc953789ff864c2bf8365a82a3fba4869649 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Thu, 1 May 2014 13:44:56 -0700 Subject: iscsi-target: Change BUG_ON to REJECT in iscsit_process_nop_out This patch changes an incorrect use of BUG_ON to instead generate a REJECT + PROTOCOL_ERROR in iscsit_process_nop_out() code. This case can occur with traditional TCP where a flood of zeros in the data stream can reach this block for what is presumed to be a NOP-OUT with a solicited reply, but without a valid iscsi_cmd pointer. This incorrect BUG_ON was introduced during the v3.11-rc timeframe with the following commit: commit 778de368964c5b7e8100cde9f549992d521e9c89 Author: Nicholas Bellinger Date: Fri Jun 14 16:07:47 2013 -0700 iscsi/isert-target: Refactor ISCSI_OP_NOOP RX handling Reported-by: Arshad Hussain Cc: stable@vger.kernel.org # 3.11+ Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 78cab13bbb1b..46588c85d39b 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -1593,7 +1593,9 @@ int iscsit_process_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd, * Initiator is expecting a NopIN ping reply.. */ if (hdr->itt != RESERVED_ITT) { - BUG_ON(!cmd); + if (!cmd) + return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR, + (unsigned char *)hdr); spin_lock_bh(&conn->cmd_lock); list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list); -- cgit v1.2.3 From ed8ec8f707ed4760c124d47b27c93df8ec5b1eba Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Mon, 12 May 2014 12:18:32 -0700 Subject: tcm_fc: Fix free-after-use regression in ft_free_cmd This patch fixes a free-after-use regression in ft_free_cmd(), where ft_sess_put() is called with cmd->sess after percpu_ida_free() has already released the tag. Fix this bug by saving the ft_sess pointer ahead of percpu_ida_free(), and pass it directly to ft_sess_put(). The regression was originally introduced in v3.13-rc1 commit: commit 5f544cfac956971099e906f94568bc3fd1a7108a Author: Nicholas Bellinger Date: Mon Sep 23 12:12:42 2013 -0700 tcm_fc: Convert to per-cpu command map pre-allocation of ft_cmd Reported-by: Jun Wu Cc: Mark Rustad Cc: Robert Love Cc: #3.13+ Signed-off-by: Nicholas Bellinger --- drivers/target/tcm_fc/tfc_cmd.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c index 01cf37f212c3..f5fd515b2bee 100644 --- a/drivers/target/tcm_fc/tfc_cmd.c +++ b/drivers/target/tcm_fc/tfc_cmd.c @@ -90,18 +90,18 @@ static void ft_free_cmd(struct ft_cmd *cmd) { struct fc_frame *fp; struct fc_lport *lport; - struct se_session *se_sess; + struct ft_sess *sess; if (!cmd) return; - se_sess = cmd->sess->se_sess; + sess = cmd->sess; fp = cmd->req_frame; lport = fr_dev(fp); if (fr_seq(fp)) lport->tt.seq_release(fr_seq(fp)); fc_frame_free(fp); - percpu_ida_free(&se_sess->sess_tag_pool, cmd->se_cmd.map_tag); - ft_sess_put(cmd->sess); /* undo get from lookup at recv */ + percpu_ida_free(&sess->se_sess->sess_tag_pool, cmd->se_cmd.map_tag); + ft_sess_put(sess); /* undo get from lookup at recv */ } void ft_release_cmd(struct se_cmd *se_cmd) -- cgit v1.2.3 From 52d0aa7980cfee85c831b2969e659055395386d4 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Wed, 14 May 2014 20:54:26 +0000 Subject: iscsi-target: Disable Immediate + Unsolicited Data with ISER Protection This patch explicitly disables Immediate + Unsolicited Data for ISER connections during login in iscsi_login_zero_tsih_s2() when protection has been enabled for the session by the underlying hardware. This is currently required because protection / signature memory regions (MRs) expect T10 PI to occur on RDMA READs + RDMA WRITEs transfers, and not on a immediate data payload associated with ISCSI_OP_SCSI_CMD, or unsolicited data-out associated with a ISCSI_OP_SCSI_DATA_OUT. v2 changes: - Add TARGET_PROT_DOUT_INSERT check (Sagi) - Add pr_debug noisemaker (Sagi) - Add goto to avoid early return from MRDSL check (nab) Cc: Sagi Grimberg Cc: Or Gerlitz Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target_login.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index b72d8550e8bc..ca31fa1b8a4b 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c @@ -436,7 +436,7 @@ static int iscsi_login_zero_tsih_s2( } off = mrdsl % PAGE_SIZE; if (!off) - return 0; + goto check_prot; if (mrdsl < PAGE_SIZE) mrdsl = PAGE_SIZE; @@ -452,6 +452,31 @@ static int iscsi_login_zero_tsih_s2( ISCSI_LOGIN_STATUS_NO_RESOURCES); return -1; } + /* + * ISER currently requires that ImmediateData + Unsolicited + * Data be disabled when protection / signature MRs are enabled. + */ +check_prot: + if (sess->se_sess->sup_prot_ops & + (TARGET_PROT_DOUT_STRIP | TARGET_PROT_DOUT_PASS | + TARGET_PROT_DOUT_INSERT)) { + + sprintf(buf, "ImmediateData=No"); + if (iscsi_change_param_value(buf, conn->param_list, 0) < 0) { + iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, + ISCSI_LOGIN_STATUS_NO_RESOURCES); + return -1; + } + + sprintf(buf, "InitialR2T=Yes"); + if (iscsi_change_param_value(buf, conn->param_list, 0) < 0) { + iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, + ISCSI_LOGIN_STATUS_NO_RESOURCES); + return -1; + } + pr_debug("Forcing ImmediateData=No + InitialR2T=Yes for" + " T10-PI enabled ISER session\n"); + } } return 0; -- cgit v1.2.3 From 07b8dae38b09bcfede7e726f172e39b5ce8390d9 Mon Sep 17 00:00:00 2001 From: Andy Grover Date: Wed, 14 May 2014 15:48:06 -0700 Subject: target: Don't allow setting WC emulation if device doesn't support Just like for pSCSI, if the transport sets get_write_cache, then it is not valid to enable write cache emulation for it. Return an error. see https://bugzilla.redhat.com/show_bug.cgi?id=1082675 Reviewed-by: Chris Leech Signed-off-by: Andy Grover Cc: stable@vger.kernel.org # 3.10+ Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_device.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 382b66b212ae..26416c15d65c 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -798,10 +798,10 @@ int se_dev_set_emulate_write_cache(struct se_device *dev, int flag) pr_err("emulate_write_cache not supported for pSCSI\n"); return -EINVAL; } - if (dev->transport->get_write_cache) { - pr_warn("emulate_write_cache cannot be changed when underlying" - " HW reports WriteCacheEnabled, ignoring request\n"); - return 0; + if (flag && + dev->transport->get_write_cache) { + pr_err("emulate_write_cache not supported for this device\n"); + return -EINVAL; } dev->dev_attrib.emulate_write_cache = flag; -- cgit v1.2.3 From b394745df2d9d4c30bf1bcc55773bec6f3bc7c67 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Wed, 14 May 2014 13:12:49 -0700 Subject: net: phy: Don't call phy_resume if phy_init_hw failed After the call to phy_init_hw failed in phy_attach_direct, phy_detach is called to detach the phy device from its network device. If the attached driver is a generic phy driver, this also detaches the driver. Subsequently phy_resume is called, which assumes without checking that a driver is attached to the device. This will result in a crash such as Unable to handle kernel paging request for data at address 0xffffffffffffff90 Faulting instruction address: 0xc0000000003a0e18 Oops: Kernel access of bad area, sig: 11 [#1] ... NIP [c0000000003a0e18] .phy_attach_direct+0x68/0x17c LR [c0000000003a0e6c] .phy_attach_direct+0xbc/0x17c Call Trace: [c0000003fc0475d0] [c0000000003a0e6c] .phy_attach_direct+0xbc/0x17c (unreliable) [c0000003fc047670] [c0000000003a0ff8] .phy_connect_direct+0x28/0x98 [c0000003fc047700] [c0000000003f0074] .of_phy_connect+0x4c/0xa4 Only call phy_resume if phy_init_hw was successful. Signed-off-by: Guenter Roeck Acked-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/phy_device.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 0ce606624296..4987a1c6dc52 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -614,8 +614,8 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, err = phy_init_hw(phydev); if (err) phy_detach(phydev); - - phy_resume(phydev); + else + phy_resume(phydev); return err; } -- cgit v1.2.3 From be7a010d6fa33dca9327ad8e91844278dfd1e712 Mon Sep 17 00:00:00 2001 From: Duan Jiong Date: Thu, 15 May 2014 15:56:14 +0800 Subject: ipv6: update Destination Cache entries when gateway turn into host RFC 4861 states in 7.2.5: The IsRouter flag in the cache entry MUST be set based on the Router flag in the received advertisement. In those cases where the IsRouter flag changes from TRUE to FALSE as a result of this update, the node MUST remove that router from the Default Router List and update the Destination Cache entries for all destinations using that neighbor as a router as specified in Section 7.3.3. This is needed to detect when a node that is used as a router stops forwarding packets due to being configured as a host. Currently, when dealing with NA Message which IsRouter flag changes from TRUE to FALSE, the kernel only removes router from the Default Router List, and don't update the Destination Cache entries. Now in order to update those Destination Cache entries, i introduce function rt6_clean_tohost(). Signed-off-by: Duan Jiong Acked-by: Hannes Frederic Sowa Signed-off-by: David S. Miller --- include/net/ip6_route.h | 1 + net/ipv6/ndisc.c | 7 ++----- net/ipv6/route.c | 21 +++++++++++++++++++++ 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h index 6c4f5eac98e7..216cecce65e9 100644 --- a/include/net/ip6_route.h +++ b/include/net/ip6_route.h @@ -127,6 +127,7 @@ int rt6_dump_route(struct rt6_info *rt, void *p_arg); void rt6_ifdown(struct net *net, struct net_device *dev); void rt6_mtu_change(struct net_device *dev, unsigned int mtu); void rt6_remove_prefsrc(struct inet6_ifaddr *ifp); +void rt6_clean_tohost(struct net *net, struct in6_addr *gateway); /* diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 09a22f4f36c9..ca8d4ea48a5d 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -851,7 +851,7 @@ out: static void ndisc_recv_na(struct sk_buff *skb) { struct nd_msg *msg = (struct nd_msg *)skb_transport_header(skb); - const struct in6_addr *saddr = &ipv6_hdr(skb)->saddr; + struct in6_addr *saddr = &ipv6_hdr(skb)->saddr; const struct in6_addr *daddr = &ipv6_hdr(skb)->daddr; u8 *lladdr = NULL; u32 ndoptlen = skb_tail_pointer(skb) - (skb_transport_header(skb) + @@ -944,10 +944,7 @@ static void ndisc_recv_na(struct sk_buff *skb) /* * Change: router to host */ - struct rt6_info *rt; - rt = rt6_get_dflt_router(saddr, dev); - if (rt) - ip6_del_rt(rt); + rt6_clean_tohost(dev_net(dev), saddr); } out: diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 004fffb6c221..58c449ad7f6e 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -2234,6 +2234,27 @@ void rt6_remove_prefsrc(struct inet6_ifaddr *ifp) fib6_clean_all(net, fib6_remove_prefsrc, &adni); } +#define RTF_RA_ROUTER (RTF_ADDRCONF | RTF_DEFAULT | RTF_GATEWAY) +#define RTF_CACHE_GATEWAY (RTF_GATEWAY | RTF_CACHE) + +/* Remove routers and update dst entries when gateway turn into host. */ +static int fib6_clean_tohost(struct rt6_info *rt, void *arg) +{ + struct in6_addr *gateway = (struct in6_addr *)arg; + + if ((((rt->rt6i_flags & RTF_RA_ROUTER) == RTF_RA_ROUTER) || + ((rt->rt6i_flags & RTF_CACHE_GATEWAY) == RTF_CACHE_GATEWAY)) && + ipv6_addr_equal(gateway, &rt->rt6i_gateway)) { + return -1; + } + return 0; +} + +void rt6_clean_tohost(struct net *net, struct in6_addr *gateway) +{ + fib6_clean_all(net, fib6_clean_tohost, gateway); +} + struct arg_dev_net { struct net_device *dev; struct net *net; -- cgit v1.2.3 From 583757446ba6850eff96cef6565d729266da9c5b Mon Sep 17 00:00:00 2001 From: Zoltan Kiss Date: Thu, 15 May 2014 11:08:34 +0100 Subject: xen-netback: Fix grant ref resolution in RX path The original series for reintroducing grant mapping for netback had a patch [1] to handle receiving of packets from an another VIF. Grant copy on the receiving side needs the grant ref of the page to set up the op. The original patch assumed (wrongly) that the frags array haven't changed. In the case reported by Sander, the sending guest sent a packet where the linear buffer and the first frag were under PKT_PROT_LEN (=128) bytes. xenvif_tx_submit() then pulled up the linear area to 128 bytes, and ditched the first frag. The receiving side had an off-by-one problem when gathered the grant refs. This patch fixes that by checking whether the actual frag's page pointer is the same as the page in the original frag list. It can handle any kind of changes on the original frags array, like: - removing granted frags from the array at any point - adding local pages to the frags list anywhere - reordering the frags It's optimized to the most common case, when there is 1:1 relation between the frags and the list, plus works optimal when frags are removed from the end or the beginning. [1]: 3e2234: xen-netback: Handle foreign mapped pages on the guest RX path Reported-by: Sander Eikelenboom Signed-off-by: Zoltan Kiss Acked-by: Ian Campbell Signed-off-by: David S. Miller --- drivers/net/xen-netback/netback.c | 98 ++++++++++++++++++++++++++++++++------- 1 file changed, 80 insertions(+), 18 deletions(-) diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index 76665405c5aa..64ab1d141f1c 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -104,7 +104,7 @@ static inline unsigned long idx_to_kaddr(struct xenvif *vif, /* Find the containing VIF's structure from a pointer in pending_tx_info array */ -static inline struct xenvif* ubuf_to_vif(struct ubuf_info *ubuf) +static inline struct xenvif *ubuf_to_vif(const struct ubuf_info *ubuf) { u16 pending_idx = ubuf->desc; struct pending_tx_info *temp = @@ -322,6 +322,35 @@ static void xenvif_gop_frag_copy(struct xenvif *vif, struct sk_buff *skb, } } +/* + * Find the grant ref for a given frag in a chain of struct ubuf_info's + * skb: the skb itself + * i: the frag's number + * ubuf: a pointer to an element in the chain. It should not be NULL + * + * Returns a pointer to the element in the chain where the page were found. If + * not found, returns NULL. + * See the definition of callback_struct in common.h for more details about + * the chain. + */ +static const struct ubuf_info *xenvif_find_gref(const struct sk_buff *const skb, + const int i, + const struct ubuf_info *ubuf) +{ + struct xenvif *foreign_vif = ubuf_to_vif(ubuf); + + do { + u16 pending_idx = ubuf->desc; + + if (skb_shinfo(skb)->frags[i].page.p == + foreign_vif->mmap_pages[pending_idx]) + break; + ubuf = (struct ubuf_info *) ubuf->ctx; + } while (ubuf); + + return ubuf; +} + /* * Prepare an SKB to be transmitted to the frontend. * @@ -346,9 +375,8 @@ static int xenvif_gop_skb(struct sk_buff *skb, int head = 1; int old_meta_prod; int gso_type; - struct ubuf_info *ubuf = skb_shinfo(skb)->destructor_arg; - grant_ref_t foreign_grefs[MAX_SKB_FRAGS]; - struct xenvif *foreign_vif = NULL; + const struct ubuf_info *ubuf = skb_shinfo(skb)->destructor_arg; + const struct ubuf_info *const head_ubuf = ubuf; old_meta_prod = npo->meta_prod; @@ -386,19 +414,6 @@ static int xenvif_gop_skb(struct sk_buff *skb, npo->copy_off = 0; npo->copy_gref = req->gref; - if ((skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY) && - (ubuf->callback == &xenvif_zerocopy_callback)) { - int i = 0; - foreign_vif = ubuf_to_vif(ubuf); - - do { - u16 pending_idx = ubuf->desc; - foreign_grefs[i++] = - foreign_vif->pending_tx_info[pending_idx].req.gref; - ubuf = (struct ubuf_info *) ubuf->ctx; - } while (ubuf); - } - data = skb->data; while (data < skb_tail_pointer(skb)) { unsigned int offset = offset_in_page(data); @@ -415,13 +430,60 @@ static int xenvif_gop_skb(struct sk_buff *skb, } for (i = 0; i < nr_frags; i++) { + /* This variable also signals whether foreign_gref has a real + * value or not. + */ + struct xenvif *foreign_vif = NULL; + grant_ref_t foreign_gref; + + if ((skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY) && + (ubuf->callback == &xenvif_zerocopy_callback)) { + const struct ubuf_info *const startpoint = ubuf; + + /* Ideally ubuf points to the chain element which + * belongs to this frag. Or if frags were removed from + * the beginning, then shortly before it. + */ + ubuf = xenvif_find_gref(skb, i, ubuf); + + /* Try again from the beginning of the list, if we + * haven't tried from there. This only makes sense in + * the unlikely event of reordering the original frags. + * For injected local pages it's an unnecessary second + * run. + */ + if (unlikely(!ubuf) && startpoint != head_ubuf) + ubuf = xenvif_find_gref(skb, i, head_ubuf); + + if (likely(ubuf)) { + u16 pending_idx = ubuf->desc; + + foreign_vif = ubuf_to_vif(ubuf); + foreign_gref = foreign_vif->pending_tx_info[pending_idx].req.gref; + /* Just a safety measure. If this was the last + * element on the list, the for loop will + * iterate again if a local page were added to + * the end. Using head_ubuf here prevents the + * second search on the chain. Or the original + * frags changed order, but that's less likely. + * In any way, ubuf shouldn't be NULL. + */ + ubuf = ubuf->ctx ? + (struct ubuf_info *) ubuf->ctx : + head_ubuf; + } else + /* This frag was a local page, added to the + * array after the skb left netback. + */ + ubuf = head_ubuf; + } xenvif_gop_frag_copy(vif, skb, npo, skb_frag_page(&skb_shinfo(skb)->frags[i]), skb_frag_size(&skb_shinfo(skb)->frags[i]), skb_shinfo(skb)->frags[i].page_offset, &head, foreign_vif, - foreign_grefs[i]); + foreign_vif ? foreign_gref : UINT_MAX); } return npo->meta_prod - old_meta_prod; -- cgit v1.2.3 From 81c708068dfedece038e07d818ba68333d8d885d Mon Sep 17 00:00:00 2001 From: Nikolay Aleksandrov Date: Thu, 15 May 2014 13:35:23 +0200 Subject: bonding: fix out of range parameters for bond_intmax_tbl I've missed to add a NULL entry to the bond_intmax_tbl when I introduced it with the conversion of arp_interval so add it now. CC: Jay Vosburgh CC: Veaceslav Falico CC: Andy Gospodarek Fixes: 7bdb04ed0dbf ("bonding: convert arp_interval to use the new option API") Signed-off-by: Nikolay Aleksandrov Acked-by: Veaceslav Falico Signed-off-by: David S. Miller --- drivers/net/bonding/bond_options.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c index 724e30fa20b9..832070298446 100644 --- a/drivers/net/bonding/bond_options.c +++ b/drivers/net/bonding/bond_options.c @@ -125,6 +125,7 @@ static const struct bond_opt_value bond_fail_over_mac_tbl[] = { static const struct bond_opt_value bond_intmax_tbl[] = { { "off", 0, BOND_VALFLAG_DEFAULT}, { "maxval", INT_MAX, BOND_VALFLAG_MAX}, + { NULL, -1, 0} }; static const struct bond_opt_value bond_lacp_rate_tbl[] = { -- cgit v1.2.3 From bfaed5abad998bfc88a66e6e71c7b08dcf82f04e Mon Sep 17 00:00:00 2001 From: Leif Lindholm Date: Thu, 17 Apr 2014 18:41:59 +0100 Subject: arm: dts: Fix missing device_type="memory" for ste-ccu8540 The current .dts for ste-ccu8540 lacks a 'device_type = "memory"' for its memory node, relying on an old ppc quirk in order to discover its memory. Fix the data so that all parsing code can handle it correctly. Signed-off-by: Leif Lindholm Acked-by: Lee Jones Acked-by: Linus Walleij Cc: linux-arm-kernel@lists.infradead.org Cc: devicetree@vger.kernel.org Cc: Mark Rutland Cc: Signed-off-by: Grant Likely --- arch/arm/boot/dts/ste-ccu8540.dts | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/ste-ccu8540.dts b/arch/arm/boot/dts/ste-ccu8540.dts index 7f3baf51a3a9..32dd55e5f4e6 100644 --- a/arch/arm/boot/dts/ste-ccu8540.dts +++ b/arch/arm/boot/dts/ste-ccu8540.dts @@ -18,6 +18,7 @@ compatible = "st-ericsson,ccu8540", "st-ericsson,u8540"; memory@0 { + device_type = "memory"; reg = <0x20000000 0x1f000000>, <0xc0000000 0x3f000000>; }; -- cgit v1.2.3 From dfc44f8030653b345fc6fb337558c3a07536823f Mon Sep 17 00:00:00 2001 From: Leif Lindholm Date: Thu, 17 Apr 2014 18:42:00 +0100 Subject: mips: dts: Fix missing device_type="memory" property in memory nodes A few platforms lack a 'device_type = "memory"' for their memory nodes, relying on an old ppc quirk in order to discover its memory. Add the missing data so that all parsing code can find memory nodes correctly. Signed-off-by: Leif Lindholm Cc: linux-mips@linux-mips.org Cc: devicetree@vger.kernel.org Cc: Mark Rutland Cc: Acked-by: John Crispin Signed-off-by: Grant Likely --- arch/mips/lantiq/dts/easy50712.dts | 1 + arch/mips/ralink/dts/mt7620a_eval.dts | 1 + arch/mips/ralink/dts/rt2880_eval.dts | 1 + arch/mips/ralink/dts/rt3052_eval.dts | 1 + arch/mips/ralink/dts/rt3883_eval.dts | 1 + 5 files changed, 5 insertions(+) diff --git a/arch/mips/lantiq/dts/easy50712.dts b/arch/mips/lantiq/dts/easy50712.dts index fac1f5b178eb..143b8a37b5e4 100644 --- a/arch/mips/lantiq/dts/easy50712.dts +++ b/arch/mips/lantiq/dts/easy50712.dts @@ -8,6 +8,7 @@ }; memory@0 { + device_type = "memory"; reg = <0x0 0x2000000>; }; diff --git a/arch/mips/ralink/dts/mt7620a_eval.dts b/arch/mips/ralink/dts/mt7620a_eval.dts index 35eb874ab7f1..709f58132f5c 100644 --- a/arch/mips/ralink/dts/mt7620a_eval.dts +++ b/arch/mips/ralink/dts/mt7620a_eval.dts @@ -7,6 +7,7 @@ model = "Ralink MT7620A evaluation board"; memory@0 { + device_type = "memory"; reg = <0x0 0x2000000>; }; diff --git a/arch/mips/ralink/dts/rt2880_eval.dts b/arch/mips/ralink/dts/rt2880_eval.dts index 322d7002595b..0a685db093d4 100644 --- a/arch/mips/ralink/dts/rt2880_eval.dts +++ b/arch/mips/ralink/dts/rt2880_eval.dts @@ -7,6 +7,7 @@ model = "Ralink RT2880 evaluation board"; memory@0 { + device_type = "memory"; reg = <0x8000000 0x2000000>; }; diff --git a/arch/mips/ralink/dts/rt3052_eval.dts b/arch/mips/ralink/dts/rt3052_eval.dts index 0ac73ea28198..ec9e9a035541 100644 --- a/arch/mips/ralink/dts/rt3052_eval.dts +++ b/arch/mips/ralink/dts/rt3052_eval.dts @@ -7,6 +7,7 @@ model = "Ralink RT3052 evaluation board"; memory@0 { + device_type = "memory"; reg = <0x0 0x2000000>; }; diff --git a/arch/mips/ralink/dts/rt3883_eval.dts b/arch/mips/ralink/dts/rt3883_eval.dts index 2fa6b330bf4f..e8df21a5d10d 100644 --- a/arch/mips/ralink/dts/rt3883_eval.dts +++ b/arch/mips/ralink/dts/rt3883_eval.dts @@ -7,6 +7,7 @@ model = "Ralink RT3883 evaluation board"; memory@0 { + device_type = "memory"; reg = <0x0 0x2000000>; }; -- cgit v1.2.3 From 4797ec2dc83a43be35bad56037d1b53db9e2b5d5 Mon Sep 17 00:00:00 2001 From: Mark Salter Date: Thu, 15 May 2014 15:19:22 +0100 Subject: arm64: fix pud_huge() for 2-level pagetables The following happens when trying to run a kvm guest on a kernel configured for 64k pages. This doesn't happen with 4k pages: BUG: failure at include/linux/mm.h:297/put_page_testzero()! Kernel panic - not syncing: BUG! CPU: 2 PID: 4228 Comm: qemu-system-aar Tainted: GF 3.13.0-0.rc7.31.sa2.k32v1.aarch64.debug #1 Call trace: [] dump_backtrace+0x0/0x16c [] show_stack+0x14/0x1c [] dump_stack+0x84/0xb0 [] panic+0xf4/0x220 [] free_reserved_area+0x0/0x110 [] free_pages+0x50/0x88 [] kvm_free_stage2_pgd+0x30/0x40 [] kvm_arch_destroy_vm+0x18/0x44 [] kvm_put_kvm+0xf0/0x184 [] kvm_vm_release+0x10/0x1c [] __fput+0xb0/0x288 [] ____fput+0xc/0x14 [] task_work_run+0xa8/0x11c [] do_notify_resume+0x54/0x58 In arch/arm/kvm/mmu.c:unmap_range(), we end up doing an extra put_page() on the stage2 pgd which leads to the BUG in put_page_testzero(). This happens because a pud_huge() test in unmap_range() returns true when it should always be false with 2-level pages tables used by 64k pages. This patch removes support for huge puds if 2-level pagetables are being used. Signed-off-by: Mark Salter [catalin.marinas@arm.com: removed #ifndef around PUD_SIZE check] Signed-off-by: Catalin Marinas Cc: # v3.11+ --- arch/arm64/mm/hugetlbpage.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/mm/hugetlbpage.c b/arch/arm64/mm/hugetlbpage.c index 5e9aec358306..31eb959e9aa8 100644 --- a/arch/arm64/mm/hugetlbpage.c +++ b/arch/arm64/mm/hugetlbpage.c @@ -51,7 +51,11 @@ int pmd_huge(pmd_t pmd) int pud_huge(pud_t pud) { +#ifndef __PAGETABLE_PMD_FOLDED return !(pud_val(pud) & PUD_TABLE_BIT); +#else + return 0; +#endif } int pmd_huge_support(void) -- cgit v1.2.3 From 178eda29ca721842f2146378e73d43e0044c4166 Mon Sep 17 00:00:00 2001 From: Chunwei Chen Date: Wed, 23 Apr 2014 12:35:09 +0800 Subject: libceph: fix corruption when using page_count 0 page in rbd It has been reported that using ZFSonLinux on rbd will result in memory corruption. The bug report can be found here: https://github.com/zfsonlinux/spl/issues/241 http://tracker.ceph.com/issues/7790 The reason is that ZFS will send pages with page_count 0 into rbd, which in turns send them to tcp_sendpage. However, tcp_sendpage cannot deal with page_count 0, as it will do get_page and put_page, and erroneously free the page. This type of issue has been noted before, and handled in iscsi, drbd, etc. So, rbd should also handle this. This fix address this issue by fall back to slower sendmsg when page_count 0 detected. Cc: Sage Weil Cc: Yehuda Sadeh Cc: stable@vger.kernel.org Signed-off-by: Chunwei Chen Reviewed-by: Ilya Dryomov --- net/ceph/messenger.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index dac7f9b98687..1948d592aa54 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -557,7 +557,7 @@ static int ceph_tcp_sendmsg(struct socket *sock, struct kvec *iov, return r; } -static int ceph_tcp_sendpage(struct socket *sock, struct page *page, +static int __ceph_tcp_sendpage(struct socket *sock, struct page *page, int offset, size_t size, bool more) { int flags = MSG_DONTWAIT | MSG_NOSIGNAL | (more ? MSG_MORE : MSG_EOR); @@ -570,6 +570,24 @@ static int ceph_tcp_sendpage(struct socket *sock, struct page *page, return ret; } +static int ceph_tcp_sendpage(struct socket *sock, struct page *page, + int offset, size_t size, bool more) +{ + int ret; + struct kvec iov; + + /* sendpage cannot properly handle pages with page_count == 0, + * we need to fallback to sendmsg if that's the case */ + if (page_count(page) >= 1) + return __ceph_tcp_sendpage(sock, page, offset, size, more); + + iov.iov_base = kmap(page) + offset; + iov.iov_len = size; + ret = ceph_tcp_sendmsg(sock, &iov, 1, size, more); + kunmap(page); + + return ret; +} /* * Shutdown/close the socket for the given connection. -- cgit v1.2.3 From f140662f35a7332b5c3188ee667856323783ed5a Mon Sep 17 00:00:00 2001 From: Ilya Dryomov Date: Fri, 9 May 2014 18:27:34 +0400 Subject: crush: decode and initialize chooseleaf_vary_r Commit e2b149cc4ba0 ("crush: add chooseleaf_vary_r tunable") added the crush_map::chooseleaf_vary_r field but missed the decode part. This lead to misdirected requests caused by incorrect raw crush mapping sets. Fixes: http://tracker.ceph.com/issues/8226 Reported-and-Tested-by: Dmitry Smirnov Signed-off-by: Ilya Dryomov Reviewed-by: Sage Weil --- net/ceph/osdmap.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c index 8b8a5a24b223..c547e46084d3 100644 --- a/net/ceph/osdmap.c +++ b/net/ceph/osdmap.c @@ -329,6 +329,11 @@ static struct crush_map *crush_decode(void *pbyval, void *end) dout("crush decode tunable chooseleaf_descend_once = %d", c->chooseleaf_descend_once); + ceph_decode_need(p, end, sizeof(u8), done); + c->chooseleaf_vary_r = ceph_decode_8(p); + dout("crush decode tunable chooseleaf_vary_r = %d", + c->chooseleaf_vary_r); + done: dout("crush_decode success\n"); return c; -- cgit v1.2.3 From be02f259fda66bcfc60ecd78a819e1ce28c8bfb9 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Fri, 16 May 2014 10:05:04 +0200 Subject: staging: rtl8723au: Use correct pipe type for USB interrupts Use a correct pipe type when filling un interrupt urbs. This should finally take care of the WARN() messages on the console when USB urbs are submitted. Signed-off-by: Jes Sorensen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723au/os_dep/usb_ops_linux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/rtl8723au/os_dep/usb_ops_linux.c b/drivers/staging/rtl8723au/os_dep/usb_ops_linux.c index c49160e477d8..07e542e5d156 100644 --- a/drivers/staging/rtl8723au/os_dep/usb_ops_linux.c +++ b/drivers/staging/rtl8723au/os_dep/usb_ops_linux.c @@ -26,7 +26,7 @@ unsigned int ffaddr2pipehdl23a(struct dvobj_priv *pdvobj, u32 addr) if (addr == RECV_BULK_IN_ADDR) { pipe = usb_rcvbulkpipe(pusbd, pdvobj->RtInPipe[0]); } else if (addr == RECV_INT_IN_ADDR) { - pipe = usb_rcvbulkpipe(pusbd, pdvobj->RtInPipe[1]); + pipe = usb_rcvintpipe(pusbd, pdvobj->RtInPipe[1]); } else if (addr < HW_QUEUE_ENTRY) { ep_num = pdvobj->Queue2Pipe[addr]; pipe = usb_sndbulkpipe(pusbd, ep_num); -- cgit v1.2.3 From ce8d9e0d6746ff67c1870386b7121a4448f21130 Mon Sep 17 00:00:00 2001 From: Matan Barak Date: Thu, 15 May 2014 15:29:27 +0300 Subject: net/mlx4_core: Add UPDATE_QP SRIOV wrapper support This patch adds UPDATE_QP SRIOV wrapper support. The mechanism is a general one, but currently only source MAC index changes are allowed for VFs. Signed-off-by: Matan Barak Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/cmd.c | 4 +- drivers/net/ethernet/mellanox/mlx4/mlx4.h | 6 +++ drivers/net/ethernet/mellanox/mlx4/qp.c | 35 ++++++++++++++ .../net/ethernet/mellanox/mlx4/resource_tracker.c | 54 ++++++++++++++++++++++ include/linux/mlx4/qp.h | 11 +++++ 5 files changed, 108 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c index 78099eab7673..92d3249f63f1 100644 --- a/drivers/net/ethernet/mellanox/mlx4/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c @@ -1253,12 +1253,12 @@ static struct mlx4_cmd_info cmd_info[] = { }, { .opcode = MLX4_CMD_UPDATE_QP, - .has_inbox = false, + .has_inbox = true, .has_outbox = false, .out_is_imm = false, .encode_slave_id = false, .verify = NULL, - .wrapper = mlx4_CMD_EPERM_wrapper + .wrapper = mlx4_UPDATE_QP_wrapper }, { .opcode = MLX4_CMD_GET_OP_REQ, diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h index f9c465101963..212cea440f90 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h @@ -1195,6 +1195,12 @@ int mlx4_QP_ATTACH_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_cmd_mailbox *outbox, struct mlx4_cmd_info *cmd); +int mlx4_UPDATE_QP_wrapper(struct mlx4_dev *dev, int slave, + struct mlx4_vhcr *vhcr, + struct mlx4_cmd_mailbox *inbox, + struct mlx4_cmd_mailbox *outbox, + struct mlx4_cmd_info *cmd); + int mlx4_PROMISC_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr, struct mlx4_cmd_mailbox *inbox, diff --git a/drivers/net/ethernet/mellanox/mlx4/qp.c b/drivers/net/ethernet/mellanox/mlx4/qp.c index 61d64ebffd56..fbd32af89c7c 100644 --- a/drivers/net/ethernet/mellanox/mlx4/qp.c +++ b/drivers/net/ethernet/mellanox/mlx4/qp.c @@ -389,6 +389,41 @@ err_icm: EXPORT_SYMBOL_GPL(mlx4_qp_alloc); +#define MLX4_UPDATE_QP_SUPPORTED_ATTRS MLX4_UPDATE_QP_SMAC +int mlx4_update_qp(struct mlx4_dev *dev, struct mlx4_qp *qp, + enum mlx4_update_qp_attr attr, + struct mlx4_update_qp_params *params) +{ + struct mlx4_cmd_mailbox *mailbox; + struct mlx4_update_qp_context *cmd; + u64 pri_addr_path_mask = 0; + int err = 0; + + mailbox = mlx4_alloc_cmd_mailbox(dev); + if (IS_ERR(mailbox)) + return PTR_ERR(mailbox); + + cmd = (struct mlx4_update_qp_context *)mailbox->buf; + + if (!attr || (attr & ~MLX4_UPDATE_QP_SUPPORTED_ATTRS)) + return -EINVAL; + + if (attr & MLX4_UPDATE_QP_SMAC) { + pri_addr_path_mask |= 1ULL << MLX4_UPD_QP_PATH_MASK_MAC_INDEX; + cmd->qp_context.pri_path.grh_mylmc = params->smac_index; + } + + cmd->primary_addr_path_mask = cpu_to_be64(pri_addr_path_mask); + + err = mlx4_cmd(dev, mailbox->dma, qp->qpn & 0xffffff, 0, + MLX4_CMD_UPDATE_QP, MLX4_CMD_TIME_CLASS_A, + MLX4_CMD_NATIVE); + + mlx4_free_cmd_mailbox(dev, mailbox); + return err; +} +EXPORT_SYMBOL_GPL(mlx4_update_qp); + void mlx4_qp_remove(struct mlx4_dev *dev, struct mlx4_qp *qp) { struct mlx4_qp_table *qp_table = &mlx4_priv(dev)->qp_table; diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c index 1c3fdd4a1f7d..8f1254a79832 100644 --- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c @@ -3895,6 +3895,60 @@ static int add_eth_header(struct mlx4_dev *dev, int slave, } +#define MLX4_UPD_QP_PATH_MASK_SUPPORTED (1ULL << MLX4_UPD_QP_PATH_MASK_MAC_INDEX) +int mlx4_UPDATE_QP_wrapper(struct mlx4_dev *dev, int slave, + struct mlx4_vhcr *vhcr, + struct mlx4_cmd_mailbox *inbox, + struct mlx4_cmd_mailbox *outbox, + struct mlx4_cmd_info *cmd_info) +{ + int err; + u32 qpn = vhcr->in_modifier & 0xffffff; + struct res_qp *rqp; + u64 mac; + unsigned port; + u64 pri_addr_path_mask; + struct mlx4_update_qp_context *cmd; + int smac_index; + + cmd = (struct mlx4_update_qp_context *)inbox->buf; + + pri_addr_path_mask = be64_to_cpu(cmd->primary_addr_path_mask); + if (cmd->qp_mask || cmd->secondary_addr_path_mask || + (pri_addr_path_mask & ~MLX4_UPD_QP_PATH_MASK_SUPPORTED)) + return -EPERM; + + /* Just change the smac for the QP */ + err = get_res(dev, slave, qpn, RES_QP, &rqp); + if (err) { + mlx4_err(dev, "Updating qpn 0x%x for slave %d rejected\n", qpn, slave); + return err; + } + + port = (rqp->sched_queue >> 6 & 1) + 1; + smac_index = cmd->qp_context.pri_path.grh_mylmc; + err = mac_find_smac_ix_in_slave(dev, slave, port, + smac_index, &mac); + if (err) { + mlx4_err(dev, "Failed to update qpn 0x%x, MAC is invalid. smac_ix: %d\n", + qpn, smac_index); + goto err_mac; + } + + err = mlx4_cmd(dev, inbox->dma, + vhcr->in_modifier, 0, + MLX4_CMD_UPDATE_QP, MLX4_CMD_TIME_CLASS_A, + MLX4_CMD_NATIVE); + if (err) { + mlx4_err(dev, "Failed to update qpn on qpn 0x%x, command failed\n", qpn); + goto err_mac; + } + +err_mac: + put_res(dev, slave, qpn, RES_QP); + return err; +} + int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr, struct mlx4_cmd_mailbox *inbox, diff --git a/include/linux/mlx4/qp.h b/include/linux/mlx4/qp.h index b66e7610d4ee..7040dc98ff8b 100644 --- a/include/linux/mlx4/qp.h +++ b/include/linux/mlx4/qp.h @@ -421,6 +421,17 @@ struct mlx4_wqe_inline_seg { __be32 byte_count; }; +enum mlx4_update_qp_attr { + MLX4_UPDATE_QP_SMAC = 1 << 0, +}; + +struct mlx4_update_qp_params { + u8 smac_index; +}; + +int mlx4_update_qp(struct mlx4_dev *dev, struct mlx4_qp *qp, + enum mlx4_update_qp_attr attr, + struct mlx4_update_qp_params *params); int mlx4_qp_modify(struct mlx4_dev *dev, struct mlx4_mtt *mtt, enum mlx4_qp_state cur_state, enum mlx4_qp_state new_state, struct mlx4_qp_context *context, enum mlx4_qp_optpar optpar, -- cgit v1.2.3 From 9433c188915c1383ee36259119bc3a9c6f98cfc3 Mon Sep 17 00:00:00 2001 From: Matan Barak Date: Thu, 15 May 2014 15:29:28 +0300 Subject: IB/mlx4: Invoke UPDATE_QP for proxy QP1 on MAC changes When we receive a netdev event indicating a netdev change and/or a netdev address change, we must change the MAC index used by the proxy QP1 (in the QP context), otherwise RoCE CM packets sent by the VF will not carry the same source MAC address as the non-CM packets. We use the UPDATE_QP command to perform this change. In order to avoid modifying a QP context based on netdev event, while the driver attempts to destroy this QP (e.g either the mlx4_ib or ib_mad modules are unloaded), we use mutex locking in both flows. Since the relevant mlx4 proxy GSI QP is created indirectly by the mad module when they create their GSI QP, the mlx4 didn't need to keep track on that QP prior to this change. Now, when QP modifications are needed to this QP from within the driver, we added refernece to it. Signed-off-by: Matan Barak Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- drivers/infiniband/hw/mlx4/main.c | 67 ++++++++++++++++++++++++++++++++++-- drivers/infiniband/hw/mlx4/mlx4_ib.h | 3 ++ drivers/infiniband/hw/mlx4/qp.c | 8 +++++ 3 files changed, 75 insertions(+), 3 deletions(-) diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c index 1b6dbe156a37..199c7896f081 100644 --- a/drivers/infiniband/hw/mlx4/main.c +++ b/drivers/infiniband/hw/mlx4/main.c @@ -48,6 +48,7 @@ #include #include +#include #include "mlx4_ib.h" #include "user.h" @@ -1614,6 +1615,53 @@ static int mlx4_ib_inet6_event(struct notifier_block *this, unsigned long event, } #endif +#define MLX4_IB_INVALID_MAC ((u64)-1) +static void mlx4_ib_update_qps(struct mlx4_ib_dev *ibdev, + struct net_device *dev, + int port) +{ + u64 new_smac = 0; + u64 release_mac = MLX4_IB_INVALID_MAC; + struct mlx4_ib_qp *qp; + + read_lock(&dev_base_lock); + new_smac = mlx4_mac_to_u64(dev->dev_addr); + read_unlock(&dev_base_lock); + + mutex_lock(&ibdev->qp1_proxy_lock[port - 1]); + qp = ibdev->qp1_proxy[port - 1]; + if (qp) { + int new_smac_index; + u64 old_smac = qp->pri.smac; + struct mlx4_update_qp_params update_params; + + if (new_smac == old_smac) + goto unlock; + + new_smac_index = mlx4_register_mac(ibdev->dev, port, new_smac); + + if (new_smac_index < 0) + goto unlock; + + update_params.smac_index = new_smac_index; + if (mlx4_update_qp(ibdev->dev, &qp->mqp, MLX4_UPDATE_QP_SMAC, + &update_params)) { + release_mac = new_smac; + goto unlock; + } + + qp->pri.smac = new_smac; + qp->pri.smac_index = new_smac_index; + + release_mac = old_smac; + } + +unlock: + mutex_unlock(&ibdev->qp1_proxy_lock[port - 1]); + if (release_mac != MLX4_IB_INVALID_MAC) + mlx4_unregister_mac(ibdev->dev, port, release_mac); +} + static void mlx4_ib_get_dev_addr(struct net_device *dev, struct mlx4_ib_dev *ibdev, u8 port) { @@ -1689,9 +1737,13 @@ static int mlx4_ib_init_gid_table(struct mlx4_ib_dev *ibdev) return 0; } -static void mlx4_ib_scan_netdevs(struct mlx4_ib_dev *ibdev) +static void mlx4_ib_scan_netdevs(struct mlx4_ib_dev *ibdev, + struct net_device *dev, + unsigned long event) + { struct mlx4_ib_iboe *iboe; + int update_qps_port = -1; int port; iboe = &ibdev->iboe; @@ -1719,6 +1771,11 @@ static void mlx4_ib_scan_netdevs(struct mlx4_ib_dev *ibdev) } curr_master = iboe->masters[port - 1]; + if (dev == iboe->netdevs[port - 1] && + (event == NETDEV_CHANGEADDR || event == NETDEV_REGISTER || + event == NETDEV_UP || event == NETDEV_CHANGE)) + update_qps_port = port; + if (curr_netdev) { port_state = (netif_running(curr_netdev) && netif_carrier_ok(curr_netdev)) ? IB_PORT_ACTIVE : IB_PORT_DOWN; @@ -1752,6 +1809,9 @@ static void mlx4_ib_scan_netdevs(struct mlx4_ib_dev *ibdev) } spin_unlock(&iboe->lock); + + if (update_qps_port > 0) + mlx4_ib_update_qps(ibdev, dev, update_qps_port); } static int mlx4_ib_netdev_event(struct notifier_block *this, @@ -1764,7 +1824,7 @@ static int mlx4_ib_netdev_event(struct notifier_block *this, return NOTIFY_DONE; ibdev = container_of(this, struct mlx4_ib_dev, iboe.nb); - mlx4_ib_scan_netdevs(ibdev); + mlx4_ib_scan_netdevs(ibdev, dev, event); return NOTIFY_DONE; } @@ -2043,6 +2103,7 @@ static void *mlx4_ib_add(struct mlx4_dev *dev) goto err_map; for (i = 0; i < ibdev->num_ports; ++i) { + mutex_init(&ibdev->qp1_proxy_lock[i]); if (mlx4_ib_port_link_layer(&ibdev->ib_dev, i + 1) == IB_LINK_LAYER_ETHERNET) { err = mlx4_counter_alloc(ibdev->dev, &ibdev->counters[i]); @@ -2126,7 +2187,7 @@ static void *mlx4_ib_add(struct mlx4_dev *dev) for (i = 1 ; i <= ibdev->num_ports ; ++i) reset_gid_table(ibdev, i); rtnl_lock(); - mlx4_ib_scan_netdevs(ibdev); + mlx4_ib_scan_netdevs(ibdev, NULL, 0); rtnl_unlock(); mlx4_ib_init_gid_table(ibdev); } diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h index f589522fddfd..66b0b7dbd9f4 100644 --- a/drivers/infiniband/hw/mlx4/mlx4_ib.h +++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h @@ -522,6 +522,9 @@ struct mlx4_ib_dev { int steer_qpn_count; int steer_qpn_base; int steering_support; + struct mlx4_ib_qp *qp1_proxy[MLX4_MAX_PORTS]; + /* lock when destroying qp1_proxy and getting netdev events */ + struct mutex qp1_proxy_lock[MLX4_MAX_PORTS]; }; struct ib_event_work { diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c index 41308af4163c..dc57482ae7af 100644 --- a/drivers/infiniband/hw/mlx4/qp.c +++ b/drivers/infiniband/hw/mlx4/qp.c @@ -1132,6 +1132,12 @@ int mlx4_ib_destroy_qp(struct ib_qp *qp) if (is_qp0(dev, mqp)) mlx4_CLOSE_PORT(dev->dev, mqp->port); + if (dev->qp1_proxy[mqp->port - 1] == mqp) { + mutex_lock(&dev->qp1_proxy_lock[mqp->port - 1]); + dev->qp1_proxy[mqp->port - 1] = NULL; + mutex_unlock(&dev->qp1_proxy_lock[mqp->port - 1]); + } + pd = get_pd(mqp); destroy_qp_common(dev, mqp, !!pd->ibpd.uobject); @@ -1646,6 +1652,8 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp, err = handle_eth_ud_smac_index(dev, qp, (u8 *)attr->smac, context); if (err) return -EINVAL; + if (qp->mlx4_ib_qp_type == MLX4_IB_QPT_PROXY_GSI) + dev->qp1_proxy[qp->port - 1] = qp; } } } -- cgit v1.2.3 From 6e14a5eeb158215881ef4507833a3574d0dbad19 Mon Sep 17 00:00:00 2001 From: Zhangfei Gao Date: Thu, 15 May 2014 13:35:34 +0800 Subject: net: phy: resume phydev when going to RESUMING With commit be9dad1f9f26604fb ("net: phy: suspend phydev when going to HALTED"), an unused PHY device will be put in a low-power mode using BMCR_PDOWN. Some Ethernet drivers might be calling phy_start() and phy_stop() from ndo_open and ndo_close() respectively, while calling phy_connect() and phy_disconnect() from probe and remove. In such a case, the PHY will be powered down during the phy_stop() call, but will fail to be powered up in phy_start(). This patch fixes this scenario. Signed-off-by: Jiancheng Xue Signed-off-by: Zhangfei Gao Signed-off-by: David S. Miller --- drivers/net/phy/phy.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index a972056b2249..3bc079a67a3d 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -715,7 +715,7 @@ void phy_state_machine(struct work_struct *work) struct delayed_work *dwork = to_delayed_work(work); struct phy_device *phydev = container_of(dwork, struct phy_device, state_queue); - int needs_aneg = 0, do_suspend = 0; + bool needs_aneg = false, do_suspend = false, do_resume = false; int err = 0; mutex_lock(&phydev->lock); @@ -727,7 +727,7 @@ void phy_state_machine(struct work_struct *work) case PHY_PENDING: break; case PHY_UP: - needs_aneg = 1; + needs_aneg = true; phydev->link_timeout = PHY_AN_TIMEOUT; @@ -757,7 +757,7 @@ void phy_state_machine(struct work_struct *work) phydev->adjust_link(phydev->attached_dev); } else if (0 == phydev->link_timeout--) - needs_aneg = 1; + needs_aneg = true; break; case PHY_NOLINK: err = phy_read_status(phydev); @@ -791,7 +791,7 @@ void phy_state_machine(struct work_struct *work) netif_carrier_on(phydev->attached_dev); } else { if (0 == phydev->link_timeout--) - needs_aneg = 1; + needs_aneg = true; } phydev->adjust_link(phydev->attached_dev); @@ -827,7 +827,7 @@ void phy_state_machine(struct work_struct *work) phydev->link = 0; netif_carrier_off(phydev->attached_dev); phydev->adjust_link(phydev->attached_dev); - do_suspend = 1; + do_suspend = true; } break; case PHY_RESUMING: @@ -876,6 +876,7 @@ void phy_state_machine(struct work_struct *work) } phydev->adjust_link(phydev->attached_dev); } + do_resume = true; break; } @@ -883,9 +884,10 @@ void phy_state_machine(struct work_struct *work) if (needs_aneg) err = phy_start_aneg(phydev); - - if (do_suspend) + else if (do_suspend) phy_suspend(phydev); + else if (do_resume) + phy_resume(phydev); if (err < 0) phy_error(phydev); -- cgit v1.2.3 From fde0133b9cfa4e01b275e942ffc32fd78e27d27c Mon Sep 17 00:00:00 2001 From: Nathaniel W Filardo Date: Thu, 15 May 2014 15:51:22 +0100 Subject: af_rxrpc: Fix XDR length check in rxrpc key demarshalling. There may be padding on the ticket contained in the key payload, so just ensure that the claimed token length is large enough, rather than exactly the right size. Signed-off-by: Nathaniel Wesley Filardo Signed-off-by: David Howells Signed-off-by: David S. Miller --- net/rxrpc/ar-key.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/rxrpc/ar-key.c b/net/rxrpc/ar-key.c index 7633a752c65e..0ad080790a32 100644 --- a/net/rxrpc/ar-key.c +++ b/net/rxrpc/ar-key.c @@ -99,7 +99,7 @@ static int rxrpc_instantiate_xdr_rxkad(struct key *key, const __be32 *xdr, _debug("tktlen: %x", tktlen); if (tktlen > AFSTOKEN_RK_TIX_MAX) return -EKEYREJECTED; - if (8 * 4 + tktlen != toklen) + if (toklen < 8 * 4 + tktlen) return -EKEYREJECTED; plen = sizeof(*token) + sizeof(*token->kad) + tktlen; -- cgit v1.2.3 From 07d1d29ee1e194b932328ad2dc1d40297062ab7f Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 16 May 2014 21:10:41 +0200 Subject: ACPI / video: Revert native brightness quirk for ThinkPad T530 Seems it helps some users, but causes issues for other users: https://bugzilla.redhat.com/show_bug.cgi?id=1089545 So lets drop it for now until we've figured out a better fix. Fixes: 43d949024425 (ACPI / video: Add use_native_backlight quirks for more systems) References: https://bugzilla.redhat.com/show_bug.cgi?id=1089545 Cc: All applicable Signed-off-by: Hans de Goede Signed-off-by: Rafael J. Wysocki --- drivers/acpi/video.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 6c76a49be12e..f8bc5a755dda 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -473,14 +473,6 @@ static struct dmi_system_id video_dmi_table[] __initdata = { }, { .callback = video_set_use_native_backlight, - .ident = "ThinkPad T530", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T530"), - }, - }, - { - .callback = video_set_use_native_backlight, .ident = "ThinkPad X1 Carbon", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), -- cgit v1.2.3 From 0d08fceb2e21c30ca3e1e462e678723f806acf18 Mon Sep 17 00:00:00 2001 From: David Vrabel Date: Fri, 16 May 2014 12:26:04 +0100 Subject: xen-netback: fix race between napi_complete() and interrupt handler When the NAPI budget was not all used, xenvif_poll() would call napi_complete() /after/ enabling the interrupt. This resulted in a race between the napi_complete() and the napi_schedule() in the interrupt handler. The use of local_irq_save/restore() avoided by race iff the handler is running on the same CPU but not if it was running on a different CPU. Fix this properly by calling napi_complete() before reenabling interrupts (in the xenvif_napi_schedule_or_enable_irq() call). Signed-off-by: David Vrabel Acked-by: Wei Liu Acked-by: Ian Campbell Signed-off-by: David S. Miller --- drivers/net/xen-netback/common.h | 2 +- drivers/net/xen-netback/interface.c | 30 +++--------------------------- drivers/net/xen-netback/netback.c | 4 ++-- 3 files changed, 6 insertions(+), 30 deletions(-) diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h index 630a3fcf65bc..0d4a285cbd7e 100644 --- a/drivers/net/xen-netback/common.h +++ b/drivers/net/xen-netback/common.h @@ -226,7 +226,7 @@ int xenvif_map_frontend_rings(struct xenvif *vif, grant_ref_t rx_ring_ref); /* Check for SKBs from frontend and schedule backend processing */ -void xenvif_check_rx_xenvif(struct xenvif *vif); +void xenvif_napi_schedule_or_enable_events(struct xenvif *vif); /* Prevent the device from generating any further traffic. */ void xenvif_carrier_off(struct xenvif *vif); diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index ef05c5c49d41..20e9defa1060 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@ -75,32 +75,8 @@ static int xenvif_poll(struct napi_struct *napi, int budget) work_done = xenvif_tx_action(vif, budget); if (work_done < budget) { - int more_to_do = 0; - unsigned long flags; - - /* It is necessary to disable IRQ before calling - * RING_HAS_UNCONSUMED_REQUESTS. Otherwise we might - * lose event from the frontend. - * - * Consider: - * RING_HAS_UNCONSUMED_REQUESTS - * - * __napi_complete - * - * This handler is still in scheduled state so the - * event has no effect at all. After __napi_complete - * this handler is descheduled and cannot get - * scheduled again. We lose event in this case and the ring - * will be completely stalled. - */ - - local_irq_save(flags); - - RING_FINAL_CHECK_FOR_REQUESTS(&vif->tx, more_to_do); - if (!more_to_do) - __napi_complete(napi); - - local_irq_restore(flags); + napi_complete(napi); + xenvif_napi_schedule_or_enable_events(vif); } return work_done; @@ -194,7 +170,7 @@ static void xenvif_up(struct xenvif *vif) enable_irq(vif->tx_irq); if (vif->tx_irq != vif->rx_irq) enable_irq(vif->rx_irq); - xenvif_check_rx_xenvif(vif); + xenvif_napi_schedule_or_enable_events(vif); } static void xenvif_down(struct xenvif *vif) diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index 64ab1d141f1c..7367208ee8cd 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -716,7 +716,7 @@ done: notify_remote_via_irq(vif->rx_irq); } -void xenvif_check_rx_xenvif(struct xenvif *vif) +void xenvif_napi_schedule_or_enable_events(struct xenvif *vif) { int more_to_do; @@ -750,7 +750,7 @@ static void tx_credit_callback(unsigned long data) { struct xenvif *vif = (struct xenvif *)data; tx_add_credit(vif); - xenvif_check_rx_xenvif(vif); + xenvif_napi_schedule_or_enable_events(vif); } static void xenvif_tx_err(struct xenvif *vif, -- cgit v1.2.3 From 2e47b291953c35afa4e20a65475954c1a1b9afe1 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Thu, 15 May 2014 16:38:41 -0700 Subject: net: ipv6: make "ip -6 route get mark xyz" work. Currently, "ip -6 route get mark xyz" ignores the mark passed in by userspace. Make it honour the mark, just like IPv4 does. Signed-off-by: Lorenzo Colitti Signed-off-by: David S. Miller --- net/ipv6/route.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 58c449ad7f6e..6ebdb7b6744c 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -2730,6 +2730,9 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh) if (tb[RTA_OIF]) oif = nla_get_u32(tb[RTA_OIF]); + if (tb[RTA_MARK]) + fl6.flowi6_mark = nla_get_u32(tb[RTA_MARK]); + if (iif) { struct net_device *dev; int flags = 0; -- cgit v1.2.3 From d1c0b471b340f43fa857d19150e029257d7bb475 Mon Sep 17 00:00:00 2001 From: Fabian Godehardt Date: Fri, 16 May 2014 06:21:44 +0200 Subject: net/dsa/dsa.c: increment chip_index during of_node handling on dsa_of_probe() Adding more than one chip on device-tree currently causes the probing routine to always use the first chips data pointer. Signed-off-by: Fabian Godehardt Acked-by: Florian Fainelli Signed-off-by: David S. Miller --- net/dsa/dsa.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c index 0eb5d5e76dfb..5db37cef50a9 100644 --- a/net/dsa/dsa.c +++ b/net/dsa/dsa.c @@ -406,8 +406,9 @@ static int dsa_of_probe(struct platform_device *pdev) goto out_free; } - chip_index = 0; + chip_index = -1; for_each_available_child_of_node(np, child) { + chip_index++; cd = &pd->chip[chip_index]; cd->mii_bus = &mdio_bus->dev; -- cgit v1.2.3 From 22fb22eaebf4d16987f3fd9c3484c436ee0badf2 Mon Sep 17 00:00:00 2001 From: Timo Teräs Date: Fri, 16 May 2014 08:34:39 +0300 Subject: ipv4: ip_tunnels: disable cache for nbma gre tunnels MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The connected check fails to check for ip_gre nbma mode tunnels properly. ip_gre creates temporary tnl_params with daddr specified to pass-in the actual target on per-packet basis from neighbor layer. Detect these tunnels by inspecting the actual tunnel configuration. Minimal test case: ip route add 192.168.1.1/32 via 10.0.0.1 ip route add 192.168.1.2/32 via 10.0.0.2 ip tunnel add nbma0 mode gre key 1 tos c0 ip addr add 172.17.0.0/16 dev nbma0 ip link set nbma0 up ip neigh add 172.17.0.1 lladdr 192.168.1.1 dev nbma0 ip neigh add 172.17.0.2 lladdr 192.168.1.2 dev nbma0 ping 172.17.0.1 ping 172.17.0.2 The second ping should be going to 192.168.1.2 and head 10.0.0.2; but cached gre tunnel level route is used and it's actually going to 192.168.1.1 via 10.0.0.1. The lladdr's need to go to separate dst for the bug to trigger. Test case uses separate route entries, but this can also happen when the route entry is same: if there is a nexthop exception or the GRE tunnel is IPsec'ed in which case the dst points to xfrm bundle unique to the gre lladdr. Fixes: 7d442fab0a67 ("ipv4: Cache dst in tunnels") Signed-off-by: Timo Teräs Cc: Tom Herbert Cc: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/ip_tunnel.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index b3f859731c60..49721d78df75 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c @@ -540,9 +540,10 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, unsigned int max_headroom; /* The extra header space needed */ __be32 dst; int err; - bool connected = true; + bool connected; inner_iph = (const struct iphdr *)skb_inner_network_header(skb); + connected = (tunnel->parms.iph.daddr != 0); dst = tnl_params->daddr; if (dst == 0) { -- cgit v1.2.3 From 29e98242783ed3ba569797846a606ba66f781625 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 16 May 2014 11:34:37 -0700 Subject: net: gro: make sure skb->cb[] initial content has not to be zero MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Starting from linux-3.13, GRO attempts to build full size skbs. Problem is the commit assumed one particular field in skb->cb[] was clean, but it is not the case on some stacked devices. Timo reported a crash in case traffic is decrypted before reaching a GRE device. Fix this by initializing NAPI_GRO_CB(skb)->last at the right place, this also removes one conditional. Thanks a lot to Timo for providing full reports and bisecting this. Fixes: 8a29111c7ca6 ("net: gro: allow to build full sized skb") Bisected-by: Timo Teras Signed-off-by: Eric Dumazet Tested-by: Timo Teräs Signed-off-by: David S. Miller --- net/core/dev.c | 1 + net/core/skbuff.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index 6da649bde4f7..ed928e846559 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3951,6 +3951,7 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff } NAPI_GRO_CB(skb)->count = 1; NAPI_GRO_CB(skb)->age = jiffies; + NAPI_GRO_CB(skb)->last = skb; skb_shinfo(skb)->gso_size = skb_gro_len(skb); skb->next = napi->gro_list; napi->gro_list = skb; diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 1b62343f5837..8383b2bddeb9 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -3076,7 +3076,7 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb) if (unlikely(p->len + len >= 65536)) return -E2BIG; - lp = NAPI_GRO_CB(p)->last ?: p; + lp = NAPI_GRO_CB(p)->last; pinfo = skb_shinfo(lp); if (headlen <= offset) { @@ -3192,7 +3192,7 @@ merge: __skb_pull(skb, offset); - if (!NAPI_GRO_CB(p)->last) + if (NAPI_GRO_CB(p)->last == p) skb_shinfo(p)->frag_list = skb; else NAPI_GRO_CB(p)->last->next = skb; -- cgit v1.2.3 From 5005e0b76781c37d0a16dd6dd17d015098e8ce92 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Fri, 16 May 2014 14:45:40 -0700 Subject: ARM: OMAP2+: nand: Fix NAND on OMAP2 and OMAP3 boards Commit c66d039197e4 broke NAND for non-DT boot on all OMAP2 and OMAP3 boards using board_nand_init(). Following error is seen at boot [ 0.154998] (null): Unsupported NAND ECC scheme selected For OMAP2 and OMAP3 platforms, the ecc_opt parameter in platform data must be set to OMAP_ECC_HAM1_CODE_HW to work properly. Tested on omap3-beagle c4. Fixes: c66d039197e4 (mtd: nand: omap: combine different flavours of 1-bit hamming ecc schemes) Cc: stable@vger.kernel.org # v3.12+ Signed-off-by: Roger Quadros Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/board-flash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c index ac82512b9c8c..b6885e42c0a0 100644 --- a/arch/arm/mach-omap2/board-flash.c +++ b/arch/arm/mach-omap2/board-flash.c @@ -142,7 +142,7 @@ __init board_nand_init(struct mtd_partition *nand_parts, u8 nr_parts, u8 cs, board_nand_data.nr_parts = nr_parts; board_nand_data.devsize = nand_type; - board_nand_data.ecc_opt = OMAP_ECC_BCH8_CODE_HW; + board_nand_data.ecc_opt = OMAP_ECC_HAM1_CODE_HW; gpmc_nand_init(&board_nand_data, gpmc_t); } #endif /* CONFIG_MTD_NAND_OMAP2 || CONFIG_MTD_NAND_OMAP2_MODULE */ -- cgit v1.2.3 From 9ce2482fc6b22709df087d4a8387b67893176312 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Fri, 16 May 2014 14:05:35 -0700 Subject: ARM: OMAP2+: Fix DMA hang after off-idle Commit 6ddeb6d84459 (dmaengine: omap-dma: move IRQ handling to omap-dma) added support for handling interrupts in the omap dmaengine driver instead of the legacy driver. Because of different handling for interrupts this however caused omap3 to hang eventually after hitting off-idle. Any of the virtual 32 DMA channels can be assigned to any of the four DMA interrupts. So commit 6ddeb6d84459 made the omap dmaengine driver to use the second DMA interrupt while keeping the legacy code still using the first DMA interrupt. This means we need to save and restore both IRQENABLE_L1 in addition to IRQENABLE_L0. As there is a chance that the DSP might be using IRQENABLE_L2 or IRQENABLE_L3 lines, let's not touch those until this has been confirmed. Let's just add a comment to the code for now. Fixes: 6ddeb6d84459 (dmaengine: omap-dma: move IRQ handling to omap-dma) Cc: Russell King Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/dma.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index 5f5b975887fc..b5608b1f9fbd 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c @@ -70,6 +70,7 @@ static u32 errata; static struct omap_dma_global_context_registers { u32 dma_irqenable_l0; + u32 dma_irqenable_l1; u32 dma_ocp_sysconfig; u32 dma_gcr; } omap_dma_global_context; @@ -1973,10 +1974,17 @@ static struct irqaction omap24xx_dma_irq; /*----------------------------------------------------------------------------*/ +/* + * Note that we are currently using only IRQENABLE_L0 and L1. + * As the DSP may be using IRQENABLE_L2 and L3, let's not + * touch those for now. + */ void omap_dma_global_context_save(void) { omap_dma_global_context.dma_irqenable_l0 = p->dma_read(IRQENABLE_L0, 0); + omap_dma_global_context.dma_irqenable_l1 = + p->dma_read(IRQENABLE_L1, 0); omap_dma_global_context.dma_ocp_sysconfig = p->dma_read(OCP_SYSCONFIG, 0); omap_dma_global_context.dma_gcr = p->dma_read(GCR, 0); @@ -1991,6 +1999,8 @@ void omap_dma_global_context_restore(void) OCP_SYSCONFIG, 0); p->dma_write(omap_dma_global_context.dma_irqenable_l0, IRQENABLE_L0, 0); + p->dma_write(omap_dma_global_context.dma_irqenable_l1, + IRQENABLE_L1, 0); if (IS_DMA_ERRATA(DMA_ROMCODE_BUG)) p->dma_write(0x3 , IRQSTATUS_L0, 0); -- cgit v1.2.3 From bb4e506565cfc0a2f534dfda1fb7ca5c26f7a604 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Fri, 16 May 2014 22:59:18 +0200 Subject: staging: rtl8723au: Do not reset wdev->iftype in netdev_close() wdev->ifdev should be set by .change_virtual_intf(). This solves the problem of WARN() messages on module unload. Signed-off-by: Jes Sorensen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723au/os_dep/os_intfs.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/rtl8723au/os_dep/os_intfs.c b/drivers/staging/rtl8723au/os_dep/os_intfs.c index 57eca7a45672..4fe751f7c2bf 100644 --- a/drivers/staging/rtl8723au/os_dep/os_intfs.c +++ b/drivers/staging/rtl8723au/os_dep/os_intfs.c @@ -953,8 +953,6 @@ static int netdev_close(struct net_device *pnetdev) #endif /* CONFIG_8723AU_P2P */ rtw_scan_abort23a(padapter); - /* set this at the end */ - padapter->rtw_wdev->iftype = NL80211_IFTYPE_MONITOR; RT_TRACE(_module_os_intfs_c_, _drv_info_, ("-871x_drv - drv_close\n")); DBG_8723A("-871x_drv - drv_close, bup =%d\n", padapter->bup); -- cgit v1.2.3 From d2c834abe2b39a2d5a6c38ef44de87c97cbb34b4 Mon Sep 17 00:00:00 2001 From: Tuomas Tynkkynen Date: Fri, 16 May 2014 16:50:20 +0300 Subject: clk: tegra: Fix wrong value written to PLLE_AUX The value written to PLLE_AUX was incorrect due to a wrong variable being used. Without this fix SATA does not work. Cc: stable@vger.kernel.org Signed-off-by: Tuomas Tynkkynen Tested-by: Mikko Perttunen Reviewed-by: Thierry Reding Tested-by: Thierry Reding Acked-by: Thierry Reding Signed-off-by: Mike Turquette [mturquette@linaro.org: improved changelog] --- drivers/clk/tegra/clk-pll.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c index 0d20241e0770..e1769addf435 100644 --- a/drivers/clk/tegra/clk-pll.c +++ b/drivers/clk/tegra/clk-pll.c @@ -1718,7 +1718,7 @@ struct clk *tegra_clk_register_plle_tegra114(const char *name, "pll_re_vco"); } else { val_aux &= ~(PLLE_AUX_PLLRE_SEL | PLLE_AUX_PLLP_SEL); - pll_writel(val, pll_params->aux_reg, pll); + pll_writel(val_aux, pll_params->aux_reg, pll); } clk = _tegra_clk_register_pll(pll, name, parent_name, flags, -- cgit v1.2.3 From 4085ebe8c31face855fd01ee40372cb4aab1df3a Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Fri, 16 May 2014 17:04:53 -0400 Subject: net: Find the nesting level of a given device by type. Multiple devices in the kernel can be stacked/nested and they need to know their nesting level for the purposes of lockdep. This patch provides a generic function that determines a nesting level of a particular device by its type (ex: vlan, macvlan, etc). We only care about nesting of the same type of devices. For example: eth0 <- vlan0.10 <- macvlan0 <- vlan1.20 The nesting level of vlan1.20 would be 1, since there is another vlan in the stack under it. Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- include/linux/netdevice.h | 10 ++++++++++ net/core/dev.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 20e99efb1ca6..fb912e8e5c7f 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -3077,6 +3077,14 @@ void *netdev_lower_get_next_private_rcu(struct net_device *dev, priv; \ priv = netdev_lower_get_next_private_rcu(dev, &(iter))) +void *netdev_lower_get_next(struct net_device *dev, + struct list_head **iter); +#define netdev_for_each_lower_dev(dev, ldev, iter) \ + for (iter = &(dev)->adj_list.lower, \ + ldev = netdev_lower_get_next(dev, &(iter)); \ + ldev; \ + ldev = netdev_lower_get_next(dev, &(iter))) + void *netdev_adjacent_get_private(struct list_head *adj_list); void *netdev_lower_get_first_private_rcu(struct net_device *dev); struct net_device *netdev_master_upper_dev_get(struct net_device *dev); @@ -3092,6 +3100,8 @@ void netdev_upper_dev_unlink(struct net_device *dev, void netdev_adjacent_rename_links(struct net_device *dev, char *oldname); void *netdev_lower_dev_get_private(struct net_device *dev, struct net_device *lower_dev); +int dev_get_nest_level(struct net_device *dev, + bool (*type_check)(struct net_device *dev)); int skb_checksum_help(struct sk_buff *skb); struct sk_buff *__skb_gso_segment(struct sk_buff *skb, netdev_features_t features, bool tx_path); diff --git a/net/core/dev.c b/net/core/dev.c index ed928e846559..6ee3ac25ed72 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4622,6 +4622,32 @@ void *netdev_lower_get_next_private_rcu(struct net_device *dev, } EXPORT_SYMBOL(netdev_lower_get_next_private_rcu); +/** + * netdev_lower_get_next - Get the next device from the lower neighbour + * list + * @dev: device + * @iter: list_head ** of the current position + * + * Gets the next netdev_adjacent from the dev's lower neighbour + * list, starting from iter position. The caller must hold RTNL lock or + * its own locking that guarantees that the neighbour lower + * list will remain unchainged. + */ +void *netdev_lower_get_next(struct net_device *dev, struct list_head **iter) +{ + struct netdev_adjacent *lower; + + lower = list_entry((*iter)->next, struct netdev_adjacent, list); + + if (&lower->list == &dev->adj_list.lower) + return NULL; + + *iter = &lower->list; + + return lower->dev; +} +EXPORT_SYMBOL(netdev_lower_get_next); + /** * netdev_lower_get_first_private_rcu - Get the first ->private from the * lower neighbour list, RCU @@ -5072,6 +5098,30 @@ void *netdev_lower_dev_get_private(struct net_device *dev, } EXPORT_SYMBOL(netdev_lower_dev_get_private); + +int dev_get_nest_level(struct net_device *dev, + bool (*type_check)(struct net_device *dev)) +{ + struct net_device *lower = NULL; + struct list_head *iter; + int max_nest = -1; + int nest; + + ASSERT_RTNL(); + + netdev_for_each_lower_dev(dev, lower, iter) { + nest = dev_get_nest_level(lower, type_check); + if (max_nest < nest) + max_nest = nest; + } + + if (type_check(dev)) + max_nest++; + + return max_nest; +} +EXPORT_SYMBOL(dev_get_nest_level); + static void dev_change_rx_flags(struct net_device *dev, int flags) { const struct net_device_ops *ops = dev->netdev_ops; -- cgit v1.2.3 From 25175ba5c9bff9aaf0229df34bb5d54c81633ec3 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Fri, 16 May 2014 17:04:54 -0400 Subject: net: Allow for more then a single subclass for netif_addr_lock Currently netif_addr_lock_nested assumes that there can be only a single nesting level between 2 devices. However, if we have multiple devices of the same type stacked, this fails. For example: eth0 <-- vlan0.10 <-- vlan0.10.20 A more complicated configuration may stack more then one type of device in different order. Ex: eth0 <-- vlan0.10 <-- macvlan0 <-- vlan1.10.20 <-- macvlan1 This patch adds an ndo_* function that allows each stackable device to report its nesting level. If the device doesn't provide this function default subclass of 1 is used. Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- include/linux/netdevice.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index fb912e8e5c7f..9d4b1f1b6b75 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1144,6 +1144,7 @@ struct net_device_ops { netdev_tx_t (*ndo_dfwd_start_xmit) (struct sk_buff *skb, struct net_device *dev, void *priv); + int (*ndo_get_lock_subclass)(struct net_device *dev); }; /** @@ -2950,7 +2951,12 @@ static inline void netif_addr_lock(struct net_device *dev) static inline void netif_addr_lock_nested(struct net_device *dev) { - spin_lock_nested(&dev->addr_list_lock, SINGLE_DEPTH_NESTING); + int subclass = SINGLE_DEPTH_NESTING; + + if (dev->netdev_ops->ndo_get_lock_subclass) + subclass = dev->netdev_ops->ndo_get_lock_subclass(dev); + + spin_lock_nested(&dev->addr_list_lock, subclass); } static inline void netif_addr_lock_bh(struct net_device *dev) -- cgit v1.2.3 From d38569ab2bba6e6b3233acfc3a84cdbcfbd1f79f Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Fri, 16 May 2014 17:04:55 -0400 Subject: vlan: Fix lockdep warning with stacked vlan devices. This reverts commit dc8eaaa006350d24030502a4521542e74b5cb39f. vlan: Fix lockdep warning when vlan dev handle notification Instead we use the new new API to find the lock subclass of our vlan device. This way we can support configurations where vlans are interspersed with other devices: bond -> vlan -> macvlan -> vlan Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- include/linux/if_vlan.h | 3 ++- net/8021q/vlan.c | 1 + net/8021q/vlan_dev.c | 52 +++++++++---------------------------------------- net/core/dev.c | 1 - 4 files changed, 12 insertions(+), 45 deletions(-) diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h index 13bbbde00e68..724bde8477b2 100644 --- a/include/linux/if_vlan.h +++ b/include/linux/if_vlan.h @@ -73,7 +73,7 @@ static inline struct vlan_ethhdr *vlan_eth_hdr(const struct sk_buff *skb) /* found in socket.c */ extern void vlan_ioctl_set(int (*hook)(struct net *, void __user *)); -static inline int is_vlan_dev(struct net_device *dev) +static inline bool is_vlan_dev(struct net_device *dev) { return dev->priv_flags & IFF_802_1Q_VLAN; } @@ -159,6 +159,7 @@ struct vlan_dev_priv { #ifdef CONFIG_NET_POLL_CONTROLLER struct netpoll *netpoll; #endif + unsigned int nest_level; }; static inline struct vlan_dev_priv *vlan_dev_priv(const struct net_device *dev) diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index 175273f38cb1..44ebd5c2cd4a 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c @@ -169,6 +169,7 @@ int register_vlan_dev(struct net_device *dev) if (err < 0) goto out_uninit_mvrp; + vlan->nest_level = dev_get_nest_level(real_dev, is_vlan_dev) + 1; err = register_netdevice(dev); if (err < 0) goto out_uninit_mvrp; diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 733ec283ed1b..019efb79708f 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -493,48 +493,10 @@ static void vlan_dev_change_rx_flags(struct net_device *dev, int change) } } -static int vlan_calculate_locking_subclass(struct net_device *real_dev) -{ - int subclass = 0; - - while (is_vlan_dev(real_dev)) { - subclass++; - real_dev = vlan_dev_priv(real_dev)->real_dev; - } - - return subclass; -} - -static void vlan_dev_mc_sync(struct net_device *to, struct net_device *from) -{ - int err = 0, subclass; - - subclass = vlan_calculate_locking_subclass(to); - - spin_lock_nested(&to->addr_list_lock, subclass); - err = __hw_addr_sync(&to->mc, &from->mc, to->addr_len); - if (!err) - __dev_set_rx_mode(to); - spin_unlock(&to->addr_list_lock); -} - -static void vlan_dev_uc_sync(struct net_device *to, struct net_device *from) -{ - int err = 0, subclass; - - subclass = vlan_calculate_locking_subclass(to); - - spin_lock_nested(&to->addr_list_lock, subclass); - err = __hw_addr_sync(&to->uc, &from->uc, to->addr_len); - if (!err) - __dev_set_rx_mode(to); - spin_unlock(&to->addr_list_lock); -} - static void vlan_dev_set_rx_mode(struct net_device *vlan_dev) { - vlan_dev_mc_sync(vlan_dev_priv(vlan_dev)->real_dev, vlan_dev); - vlan_dev_uc_sync(vlan_dev_priv(vlan_dev)->real_dev, vlan_dev); + dev_mc_sync(vlan_dev_priv(vlan_dev)->real_dev, vlan_dev); + dev_uc_sync(vlan_dev_priv(vlan_dev)->real_dev, vlan_dev); } /* @@ -562,6 +524,11 @@ static void vlan_dev_set_lockdep_class(struct net_device *dev, int subclass) netdev_for_each_tx_queue(dev, vlan_dev_set_lockdep_one, &subclass); } +static int vlan_dev_get_lock_subclass(struct net_device *dev) +{ + return vlan_dev_priv(dev)->nest_level; +} + static const struct header_ops vlan_header_ops = { .create = vlan_dev_hard_header, .rebuild = vlan_dev_rebuild_header, @@ -597,7 +564,6 @@ static const struct net_device_ops vlan_netdev_ops; static int vlan_dev_init(struct net_device *dev) { struct net_device *real_dev = vlan_dev_priv(dev)->real_dev; - int subclass = 0; netif_carrier_off(dev); @@ -646,8 +612,7 @@ static int vlan_dev_init(struct net_device *dev) SET_NETDEV_DEVTYPE(dev, &vlan_type); - subclass = vlan_calculate_locking_subclass(dev); - vlan_dev_set_lockdep_class(dev, subclass); + vlan_dev_set_lockdep_class(dev, vlan_dev_get_lock_subclass(dev)); vlan_dev_priv(dev)->vlan_pcpu_stats = netdev_alloc_pcpu_stats(struct vlan_pcpu_stats); if (!vlan_dev_priv(dev)->vlan_pcpu_stats) @@ -819,6 +784,7 @@ static const struct net_device_ops vlan_netdev_ops = { .ndo_netpoll_cleanup = vlan_dev_netpoll_cleanup, #endif .ndo_fix_features = vlan_dev_fix_features, + .ndo_get_lock_subclass = vlan_dev_get_lock_subclass, }; void vlan_setup(struct net_device *dev) diff --git a/net/core/dev.c b/net/core/dev.c index 6ee3ac25ed72..2b872bfbd172 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -5287,7 +5287,6 @@ void __dev_set_rx_mode(struct net_device *dev) if (ops->ndo_set_rx_mode) ops->ndo_set_rx_mode(dev); } -EXPORT_SYMBOL(__dev_set_rx_mode); void dev_set_rx_mode(struct net_device *dev) { -- cgit v1.2.3 From c674ac30c549596295eb0a5af7f4714c0b905b6f Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Fri, 16 May 2014 17:04:56 -0400 Subject: macvlan: Fix lockdep warnings with stacked macvlan devices Macvlan devices try to avoid stacking, but that's not always successfull or even desired. As an example, the following configuration is perefectly legal and valid: eth0 <--- macvlan0 <---- vlan0.10 <--- macvlan1 However, this configuration produces the following lockdep trace: [ 115.620418] ====================================================== [ 115.620477] [ INFO: possible circular locking dependency detected ] [ 115.620516] 3.15.0-rc1+ #24 Not tainted [ 115.620540] ------------------------------------------------------- [ 115.620577] ip/1704 is trying to acquire lock: [ 115.620604] (&vlan_netdev_addr_lock_key/1){+.....}, at: [] dev_uc_sync+0x3c/0x80 [ 115.620686] but task is already holding lock: [ 115.620723] (&macvlan_netdev_addr_lock_key){+.....}, at: [] dev_set_rx_mode+0x1e/0x40 [ 115.620795] which lock already depends on the new lock. [ 115.620853] the existing dependency chain (in reverse order) is: [ 115.620894] -> #1 (&macvlan_netdev_addr_lock_key){+.....}: [ 115.620935] [] lock_acquire+0xa2/0x130 [ 115.620974] [] _raw_spin_lock_nested+0x37/0x50 [ 115.621019] [] vlan_dev_set_rx_mode+0x53/0x110 [8021q] [ 115.621066] [] __dev_set_rx_mode+0x57/0xa0 [ 115.621105] [] dev_set_rx_mode+0x26/0x40 [ 115.621143] [] __dev_open+0xde/0x140 [ 115.621174] [] __dev_change_flags+0x9d/0x170 [ 115.621174] [] dev_change_flags+0x29/0x60 [ 115.621174] [] do_setlink+0x321/0x9a0 [ 115.621174] [] rtnl_newlink+0x51f/0x730 [ 115.621174] [] rtnetlink_rcv_msg+0x95/0x250 [ 115.621174] [] netlink_rcv_skb+0xa9/0xc0 [ 115.621174] [] rtnetlink_rcv+0x2a/0x40 [ 115.621174] [] netlink_unicast+0xf0/0x1c0 [ 115.621174] [] netlink_sendmsg+0x2ff/0x740 [ 115.621174] [] sock_sendmsg+0x8b/0xc0 [ 115.621174] [] ___sys_sendmsg+0x369/0x380 [ 115.621174] [] __sys_sendmsg+0x42/0x80 [ 115.621174] [] SyS_sendmsg+0x12/0x20 [ 115.621174] [] system_call_fastpath+0x16/0x1b [ 115.621174] -> #0 (&vlan_netdev_addr_lock_key/1){+.....}: [ 115.621174] [] __lock_acquire+0x1773/0x1a60 [ 115.621174] [] lock_acquire+0xa2/0x130 [ 115.621174] [] _raw_spin_lock_nested+0x37/0x50 [ 115.621174] [] dev_uc_sync+0x3c/0x80 [ 115.621174] [] macvlan_set_mac_lists+0xca/0x110 [macvlan] [ 115.621174] [] __dev_set_rx_mode+0x57/0xa0 [ 115.621174] [] dev_set_rx_mode+0x26/0x40 [ 115.621174] [] __dev_open+0xde/0x140 [ 115.621174] [] __dev_change_flags+0x9d/0x170 [ 115.621174] [] dev_change_flags+0x29/0x60 [ 115.621174] [] do_setlink+0x321/0x9a0 [ 115.621174] [] rtnl_newlink+0x51f/0x730 [ 115.621174] [] rtnetlink_rcv_msg+0x95/0x250 [ 115.621174] [] netlink_rcv_skb+0xa9/0xc0 [ 115.621174] [] rtnetlink_rcv+0x2a/0x40 [ 115.621174] [] netlink_unicast+0xf0/0x1c0 [ 115.621174] [] netlink_sendmsg+0x2ff/0x740 [ 115.621174] [] sock_sendmsg+0x8b/0xc0 [ 115.621174] [] ___sys_sendmsg+0x369/0x380 [ 115.621174] [] __sys_sendmsg+0x42/0x80 [ 115.621174] [] SyS_sendmsg+0x12/0x20 [ 115.621174] [] system_call_fastpath+0x16/0x1b [ 115.621174] other info that might help us debug this: [ 115.621174] Possible unsafe locking scenario: [ 115.621174] CPU0 CPU1 [ 115.621174] ---- ---- [ 115.621174] lock(&macvlan_netdev_addr_lock_key); [ 115.621174] lock(&vlan_netdev_addr_lock_key/1); [ 115.621174] lock(&macvlan_netdev_addr_lock_key); [ 115.621174] lock(&vlan_netdev_addr_lock_key/1); [ 115.621174] *** DEADLOCK *** [ 115.621174] 2 locks held by ip/1704: [ 115.621174] #0: (rtnl_mutex){+.+.+.}, at: [] rtnetlink_rcv+0x1b/0x40 [ 115.621174] #1: (&macvlan_netdev_addr_lock_key){+.....}, at: [] dev_set_rx_mode+0x1e/0x40 [ 115.621174] stack backtrace: [ 115.621174] CPU: 3 PID: 1704 Comm: ip Not tainted 3.15.0-rc1+ #24 [ 115.621174] Hardware name: Hewlett-Packard HP xw8400 Workstation/0A08h, BIOS 786D5 v02.38 10/25/2010 [ 115.621174] ffffffff82339ae0 ffff880465f79568 ffffffff816ee20c ffffffff82339ae0 [ 115.621174] ffff880465f795a8 ffffffff816e9e1b ffff880465f79600 ffff880465b019c8 [ 115.621174] 0000000000000001 0000000000000002 ffff880465b019c8 ffff880465b01230 [ 115.621174] Call Trace: [ 115.621174] [] dump_stack+0x4d/0x66 [ 115.621174] [] print_circular_bug+0x200/0x20e [ 115.621174] [] __lock_acquire+0x1773/0x1a60 [ 115.621174] [] ? trace_hardirqs_on_caller+0xb2/0x1d0 [ 115.621174] [] lock_acquire+0xa2/0x130 [ 115.621174] [] ? dev_uc_sync+0x3c/0x80 [ 115.621174] [] _raw_spin_lock_nested+0x37/0x50 [ 115.621174] [] ? dev_uc_sync+0x3c/0x80 [ 115.621174] [] dev_uc_sync+0x3c/0x80 [ 115.621174] [] macvlan_set_mac_lists+0xca/0x110 [macvlan] [ 115.621174] [] __dev_set_rx_mode+0x57/0xa0 [ 115.621174] [] dev_set_rx_mode+0x26/0x40 [ 115.621174] [] __dev_open+0xde/0x140 [ 115.621174] [] __dev_change_flags+0x9d/0x170 [ 115.621174] [] dev_change_flags+0x29/0x60 [ 115.621174] [] ? mem_cgroup_bad_page_check+0x21/0x30 [ 115.621174] [] do_setlink+0x321/0x9a0 [ 115.621174] [] ? __lock_acquire+0x37c/0x1a60 [ 115.621174] [] rtnl_newlink+0x51f/0x730 [ 115.621174] [] ? rtnl_newlink+0xe9/0x730 [ 115.621174] [] rtnetlink_rcv_msg+0x95/0x250 [ 115.621174] [] ? trace_hardirqs_on+0xd/0x10 [ 115.621174] [] ? rtnetlink_rcv+0x1b/0x40 [ 115.621174] [] ? rtnetlink_rcv+0x40/0x40 [ 115.621174] [] netlink_rcv_skb+0xa9/0xc0 [ 115.621174] [] rtnetlink_rcv+0x2a/0x40 [ 115.621174] [] netlink_unicast+0xf0/0x1c0 [ 115.621174] [] netlink_sendmsg+0x2ff/0x740 [ 115.621174] [] sock_sendmsg+0x8b/0xc0 [ 115.621174] [] ? might_fault+0x5f/0xb0 [ 115.621174] [] ? might_fault+0xa8/0xb0 [ 115.621174] [] ? might_fault+0x5f/0xb0 [ 115.621174] [] ? verify_iovec+0x5e/0xe0 [ 115.621174] [] ___sys_sendmsg+0x369/0x380 [ 115.621174] [] ? __do_page_fault+0x11d/0x570 [ 115.621174] [] ? up_read+0x1f/0x40 [ 115.621174] [] ? __do_page_fault+0x214/0x570 [ 115.621174] [] ? mntput_no_expire+0x6b/0x1c0 [ 115.621174] [] ? mntput_no_expire+0x17/0x1c0 [ 115.621174] [] ? mntput+0x24/0x40 [ 115.621174] [] __sys_sendmsg+0x42/0x80 [ 115.621174] [] SyS_sendmsg+0x12/0x20 [ 115.621174] [] system_call_fastpath+0x16/0x1b Fix this by correctly providing macvlan lockdep class. Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- drivers/net/macvlan.c | 12 ++++++++++-- include/linux/if_macvlan.h | 1 + 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index c5fb9cf95c12..d53e299ae1d9 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -517,6 +517,11 @@ static struct lock_class_key macvlan_netdev_addr_lock_key; #define MACVLAN_STATE_MASK \ ((1<<__LINK_STATE_NOCARRIER) | (1<<__LINK_STATE_DORMANT)) +static int macvlan_get_nest_level(struct net_device *dev) +{ + return ((struct macvlan_dev *)netdev_priv(dev))->nest_level; +} + static void macvlan_set_lockdep_class_one(struct net_device *dev, struct netdev_queue *txq, void *_unused) @@ -527,8 +532,9 @@ static void macvlan_set_lockdep_class_one(struct net_device *dev, static void macvlan_set_lockdep_class(struct net_device *dev) { - lockdep_set_class(&dev->addr_list_lock, - &macvlan_netdev_addr_lock_key); + lockdep_set_class_and_subclass(&dev->addr_list_lock, + &macvlan_netdev_addr_lock_key, + macvlan_get_nest_level(dev)); netdev_for_each_tx_queue(dev, macvlan_set_lockdep_class_one, NULL); } @@ -723,6 +729,7 @@ static const struct net_device_ops macvlan_netdev_ops = { .ndo_fdb_add = macvlan_fdb_add, .ndo_fdb_del = macvlan_fdb_del, .ndo_fdb_dump = ndo_dflt_fdb_dump, + .ndo_get_lock_subclass = macvlan_get_nest_level, }; void macvlan_common_setup(struct net_device *dev) @@ -851,6 +858,7 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev, vlan->dev = dev; vlan->port = port; vlan->set_features = MACVLAN_FEATURES; + vlan->nest_level = dev_get_nest_level(lowerdev, netif_is_macvlan) + 1; vlan->mode = MACVLAN_MODE_VEPA; if (data && data[IFLA_MACVLAN_MODE]) diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h index 7c8b20b120ea..a9a53b12397b 100644 --- a/include/linux/if_macvlan.h +++ b/include/linux/if_macvlan.h @@ -56,6 +56,7 @@ struct macvlan_dev { int numqueues; netdev_features_t tap_features; int minor; + int nest_level; }; static inline void macvlan_count_rx(const struct macvlan_dev *vlan, -- cgit v1.2.3 From f9c6d4987b23e0a514464bae6771933a48e4cd01 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Fri, 16 May 2014 21:40:41 -0400 Subject: random: fix BUG_ON caused by accounting simplification Commit ee1de406ba6eb1 ("random: simplify accounting logic") simplified things too much, in that it allows the following to trigger an overflow that results in a BUG_ON crash: dd if=/dev/urandom of=/dev/zero bs=67108707 count=1 Thanks to Peter Zihlstra for discovering the crash, and Hannes Frederic for analyizing the root cause. Signed-off-by: "Theodore Ts'o" Reported-by: Peter Zijlstra Reported-by: Hannes Frederic Sowa Cc: Greg Price --- drivers/char/random.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/char/random.c b/drivers/char/random.c index 6b75713d953a..102c50d38902 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -995,8 +995,11 @@ retry: ibytes = min_t(size_t, ibytes, have_bytes - reserved); if (ibytes < min) ibytes = 0; - entropy_count = max_t(int, 0, - entropy_count - (ibytes << (ENTROPY_SHIFT + 3))); + if (have_bytes >= ibytes + reserved) + entropy_count -= ibytes << (ENTROPY_SHIFT + 3); + else + entropy_count = reserved << (ENTROPY_SHIFT + 3); + if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig) goto retry; -- cgit v1.2.3 From 44a4085538c844e79d6ee6bcf46fabf7c57a9a38 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Fri, 16 May 2014 17:20:38 -0400 Subject: bonding: Fix stacked device detection in arp monitoring Prior to commit fbd929f2dce460456807a51e18d623db3db9f077 bonding: support QinQ for bond arp interval the arp monitoring code allowed for proper detection of devices stacked on top of vlans. Since the above commit, the code can still detect a device stacked on top of single vlan, but not a device stacked on top of Q-in-Q configuration. The search will only set the inner vlan tag if the route device is the vlan device. However, this is not always the case, as it is possible to extend the stacked configuration. With this patch it is possible to provision devices on top Q-in-Q vlan configuration that should be used as a source of ARP monitoring information. For example: ip link add link bond0 vlan10 type vlan proto 802.1q id 10 ip link add link vlan10 vlan100 type vlan proto 802.1q id 100 ip link add link vlan100 type macvlan Note: This patch limites the number of stacked VLANs to 2, just like before. The original, however had another issue in that if we had more then 2 levels of VLANs, we would end up generating incorrectly tagged traffic. This is no longer possible. Fixes: fbd929f2dce460456807a51e18d623db3db9f077 (bonding: support QinQ for bond arp interval) CC: Jay Vosburgh CC: Veaceslav Falico CC: Andy Gospodarek CC: Ding Tianhong CC: Patric McHardy Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 134 +++++++++++++++++++--------------------- drivers/net/bonding/bonding.h | 1 + include/linux/if_vlan.h | 6 ++ include/linux/netdevice.h | 9 +++ net/core/dev.c | 26 ++++++++ 5 files changed, 107 insertions(+), 69 deletions(-) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 69aff72c8957..d3a67896d435 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -2126,10 +2126,10 @@ static bool bond_has_this_ip(struct bonding *bond, __be32 ip) */ static void bond_arp_send(struct net_device *slave_dev, int arp_op, __be32 dest_ip, __be32 src_ip, - struct bond_vlan_tag *inner, - struct bond_vlan_tag *outer) + struct bond_vlan_tag *tags) { struct sk_buff *skb; + int i; pr_debug("arp %d on slave %s: dst %pI4 src %pI4\n", arp_op, slave_dev->name, &dest_ip, &src_ip); @@ -2141,21 +2141,26 @@ static void bond_arp_send(struct net_device *slave_dev, int arp_op, net_err_ratelimited("ARP packet allocation failed\n"); return; } - if (outer->vlan_id) { - if (inner->vlan_id) { - pr_debug("inner tag: proto %X vid %X\n", - ntohs(inner->vlan_proto), inner->vlan_id); - skb = __vlan_put_tag(skb, inner->vlan_proto, - inner->vlan_id); - if (!skb) { - net_err_ratelimited("failed to insert inner VLAN tag\n"); - return; - } - } - pr_debug("outer reg: proto %X vid %X\n", - ntohs(outer->vlan_proto), outer->vlan_id); - skb = vlan_put_tag(skb, outer->vlan_proto, outer->vlan_id); + /* Go through all the tags backwards and add them to the packet */ + for (i = BOND_MAX_VLAN_ENCAP - 1; i > 0; i--) { + if (!tags[i].vlan_id) + continue; + + pr_debug("inner tag: proto %X vid %X\n", + ntohs(tags[i].vlan_proto), tags[i].vlan_id); + skb = __vlan_put_tag(skb, tags[i].vlan_proto, + tags[i].vlan_id); + if (!skb) { + net_err_ratelimited("failed to insert inner VLAN tag\n"); + return; + } + } + /* Set the outer tag */ + if (tags[0].vlan_id) { + pr_debug("outer tag: proto %X vid %X\n", + ntohs(tags[0].vlan_proto), tags[0].vlan_id); + skb = vlan_put_tag(skb, tags[0].vlan_proto, tags[0].vlan_id); if (!skb) { net_err_ratelimited("failed to insert outer VLAN tag\n"); return; @@ -2164,22 +2169,52 @@ static void bond_arp_send(struct net_device *slave_dev, int arp_op, arp_xmit(skb); } +/* Validate the device path between the @start_dev and the @end_dev. + * The path is valid if the @end_dev is reachable through device + * stacking. + * When the path is validated, collect any vlan information in the + * path. + */ +static bool bond_verify_device_path(struct net_device *start_dev, + struct net_device *end_dev, + struct bond_vlan_tag *tags) +{ + struct net_device *upper; + struct list_head *iter; + int idx; + + if (start_dev == end_dev) + return true; + + netdev_for_each_upper_dev_rcu(start_dev, upper, iter) { + if (bond_verify_device_path(upper, end_dev, tags)) { + if (is_vlan_dev(upper)) { + idx = vlan_get_encap_level(upper); + if (idx >= BOND_MAX_VLAN_ENCAP) + return false; + + tags[idx].vlan_proto = + vlan_dev_vlan_proto(upper); + tags[idx].vlan_id = vlan_dev_vlan_id(upper); + } + return true; + } + } + + return false; +} static void bond_arp_send_all(struct bonding *bond, struct slave *slave) { - struct net_device *upper, *vlan_upper; - struct list_head *iter, *vlan_iter; struct rtable *rt; - struct bond_vlan_tag inner, outer; + struct bond_vlan_tag tags[BOND_MAX_VLAN_ENCAP]; __be32 *targets = bond->params.arp_targets, addr; int i; + bool ret; for (i = 0; i < BOND_MAX_ARP_TARGETS && targets[i]; i++) { pr_debug("basa: target %pI4\n", &targets[i]); - inner.vlan_proto = 0; - inner.vlan_id = 0; - outer.vlan_proto = 0; - outer.vlan_id = 0; + memset(tags, 0, sizeof(tags)); /* Find out through which dev should the packet go */ rt = ip_route_output(dev_net(bond->dev), targets[i], 0, @@ -2192,7 +2227,8 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave) net_warn_ratelimited("%s: no route to arp_ip_target %pI4 and arp_validate is set\n", bond->dev->name, &targets[i]); - bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i], 0, &inner, &outer); + bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i], + 0, tags); continue; } @@ -2201,52 +2237,12 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave) goto found; rcu_read_lock(); - /* first we search only for vlan devices. for every vlan - * found we verify its upper dev list, searching for the - * rt->dst.dev. If found we save the tag of the vlan and - * proceed to send the packet. - */ - netdev_for_each_all_upper_dev_rcu(bond->dev, vlan_upper, - vlan_iter) { - if (!is_vlan_dev(vlan_upper)) - continue; - - if (vlan_upper == rt->dst.dev) { - outer.vlan_proto = vlan_dev_vlan_proto(vlan_upper); - outer.vlan_id = vlan_dev_vlan_id(vlan_upper); - rcu_read_unlock(); - goto found; - } - netdev_for_each_all_upper_dev_rcu(vlan_upper, upper, - iter) { - if (upper == rt->dst.dev) { - /* If the upper dev is a vlan dev too, - * set the vlan tag to inner tag. - */ - if (is_vlan_dev(upper)) { - inner.vlan_proto = vlan_dev_vlan_proto(upper); - inner.vlan_id = vlan_dev_vlan_id(upper); - } - outer.vlan_proto = vlan_dev_vlan_proto(vlan_upper); - outer.vlan_id = vlan_dev_vlan_id(vlan_upper); - rcu_read_unlock(); - goto found; - } - } - } - - /* if the device we're looking for is not on top of any of - * our upper vlans, then just search for any dev that - * matches, and in case it's a vlan - save the id - */ - netdev_for_each_all_upper_dev_rcu(bond->dev, upper, iter) { - if (upper == rt->dst.dev) { - rcu_read_unlock(); - goto found; - } - } + ret = bond_verify_device_path(bond->dev, rt->dst.dev, tags); rcu_read_unlock(); + if (ret) + goto found; + /* Not our device - skip */ pr_debug("%s: no path to arp_ip_target %pI4 via rt.dev %s\n", bond->dev->name, &targets[i], @@ -2259,7 +2255,7 @@ found: addr = bond_confirm_addr(rt->dst.dev, targets[i], 0); ip_rt_put(rt); bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i], - addr, &inner, &outer); + addr, tags); } } diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index b8bdd0acc8f3..00bea320e3b5 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -36,6 +36,7 @@ #define bond_version DRV_DESCRIPTION ": v" DRV_VERSION " (" DRV_RELDATE ")\n" +#define BOND_MAX_VLAN_ENCAP 2 #define BOND_MAX_ARP_TARGETS 16 #define BOND_DEFAULT_MIIMON 100 diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h index 724bde8477b2..c901b13b6f03 100644 --- a/include/linux/if_vlan.h +++ b/include/linux/if_vlan.h @@ -484,4 +484,10 @@ static inline void vlan_set_encap_proto(struct sk_buff *skb, */ skb->protocol = htons(ETH_P_802_2); } + +static inline int vlan_get_encap_level(struct net_device *dev) +{ + BUG_ON(!is_vlan_dev(dev)); + return vlan_dev_priv(dev)->nest_level; +} #endif /* !(_LINUX_IF_VLAN_H_) */ diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 9d4b1f1b6b75..b42d07b0390b 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -3056,9 +3056,18 @@ extern int weight_p; extern int bpf_jit_enable; bool netdev_has_upper_dev(struct net_device *dev, struct net_device *upper_dev); +struct net_device *netdev_upper_get_next_dev_rcu(struct net_device *dev, + struct list_head **iter); struct net_device *netdev_all_upper_get_next_dev_rcu(struct net_device *dev, struct list_head **iter); +/* iterate through upper list, must be called under RCU read lock */ +#define netdev_for_each_upper_dev_rcu(dev, updev, iter) \ + for (iter = &(dev)->adj_list.upper, \ + updev = netdev_upper_get_next_dev_rcu(dev, &(iter)); \ + updev; \ + updev = netdev_upper_get_next_dev_rcu(dev, &(iter))) + /* iterate through upper list, must be called under RCU read lock */ #define netdev_for_each_all_upper_dev_rcu(dev, updev, iter) \ for (iter = &(dev)->all_adj_list.upper, \ diff --git a/net/core/dev.c b/net/core/dev.c index 2b872bfbd172..9abc503b19b7 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4541,6 +4541,32 @@ void *netdev_adjacent_get_private(struct list_head *adj_list) } EXPORT_SYMBOL(netdev_adjacent_get_private); +/** + * netdev_upper_get_next_dev_rcu - Get the next dev from upper list + * @dev: device + * @iter: list_head ** of the current position + * + * Gets the next device from the dev's upper list, starting from iter + * position. The caller must hold RCU read lock. + */ +struct net_device *netdev_upper_get_next_dev_rcu(struct net_device *dev, + struct list_head **iter) +{ + struct netdev_adjacent *upper; + + WARN_ON_ONCE(!rcu_read_lock_held() && !lockdep_rtnl_is_held()); + + upper = list_entry_rcu((*iter)->next, struct netdev_adjacent, list); + + if (&upper->list == &dev->adj_list.upper) + return NULL; + + *iter = &upper->list; + + return upper->dev; +} +EXPORT_SYMBOL(netdev_upper_get_next_dev_rcu); + /** * netdev_all_upper_get_next_dev_rcu - Get the next dev from upper list * @dev: device -- cgit v1.2.3 From f60c3704e87d39356d00c71bf51e55c2c55ad4f5 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Fri, 16 May 2014 17:20:39 -0400 Subject: bonding: Fix alb mode to only use first level vlans. ALB/TLB learning packets use all vlans configured on top of the bond. This ends up being incorrect if we have a stack of vlans on top of the bond. ALB/TLB should only use first level/outer most vlans in its announcements. Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- drivers/net/bonding/bond_alb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index 9f69e818b000..e53847884319 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -1045,7 +1045,7 @@ static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[]) /* loop through vlans and send one packet for each */ rcu_read_lock(); netdev_for_each_all_upper_dev_rcu(bond->dev, upper, iter) { - if (upper->priv_flags & IFF_802_1Q_VLAN) + if (is_vlan_dev(upper) && vlan_get_encap_level(upper) == 0) alb_send_lp_vid(slave, mac_addr, vlan_dev_vlan_id(upper)); } -- cgit v1.2.3 From 5aa4ecfd0ddb1e6dcd1c886e6c49677550f581aa Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 17 May 2014 11:28:05 -0700 Subject: sparc64: Add membar to Niagara2 memcpy code. This is the prevent previous stores from overlapping the block stores done by the memcpy loop. Based upon a glibc patch by Jose E. Marchesi Signed-off-by: David S. Miller --- arch/sparc/lib/NG2memcpy.S | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/sparc/lib/NG2memcpy.S b/arch/sparc/lib/NG2memcpy.S index 2c20ad63ddbf..30eee6e8a81b 100644 --- a/arch/sparc/lib/NG2memcpy.S +++ b/arch/sparc/lib/NG2memcpy.S @@ -236,6 +236,7 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ */ VISEntryHalf + membar #Sync alignaddr %o1, %g0, %g0 add %o1, (64 - 1), %o4 -- cgit v1.2.3 From 1e1110c43b1cda9fe77fc4a04835e460550e6b3c Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Sat, 17 May 2014 06:49:22 -0400 Subject: target: fix memory leak on XCOPY On each processed XCOPY command, two "kmalloc-512" memory objects are leaked. These represent two allocations of struct xcopy_pt_cmd in target_core_xcopy.c. The reason for the memory leak is that the cmd_kref field is not initialized (thus, it is zero because the allocations were done with kzalloc). When we decrement zero kref in target_put_sess_cmd, the result is not zero, thus target_release_cmd_kref is not called. This patch fixes the bug by moving kref initialization from target_get_sess_cmd to transport_init_se_cmd (this function is called from target_core_xcopy.c, so it will correctly initialize cmd_kref). It can be easily verified that all code that calls target_get_sess_cmd also calls transport_init_se_cmd earlier, thus moving kref_init shouldn't introduce any new problems. Signed-off-by: Mikulas Patocka Cc: stable@vger.kernel.org # 3.12+ Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index d4b98690a736..789aa9eb0a1e 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1113,6 +1113,7 @@ void transport_init_se_cmd( init_completion(&cmd->cmd_wait_comp); init_completion(&cmd->task_stop_comp); spin_lock_init(&cmd->t_state_lock); + kref_init(&cmd->cmd_kref); cmd->transport_state = CMD_T_DEV_ACTIVE; cmd->se_tfo = tfo; @@ -2357,7 +2358,6 @@ int target_get_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd, unsigned long flags; int ret = 0; - kref_init(&se_cmd->cmd_kref); /* * Add a second kref if the fabric caller is expecting to handle * fabric acknowledgement that requires two target_put_sess_cmd() -- cgit v1.2.3 From 02948344fbf511c6eec28687dc76bb64b758ff93 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 15 May 2014 23:51:43 -0700 Subject: bnx2x: Convert return 0 to return rc These "return 0;" uses seem wrong as there are rc variables where error return values are set but unused. Signed-off-by: Joe Perches Acked-by: Dmitry Kravkov Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c | 2 +- drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c index 81cc2d9831c2..b8078d50261b 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c @@ -2695,7 +2695,7 @@ out: bnx2x_unlock_vf_pf_channel(bp, vf, CHANNEL_TLV_PF_SET_MAC); } - return 0; + return rc; } int bnx2x_set_vf_vlan(struct net_device *dev, int vfidx, u16 vlan, u8 qos) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c index 0c067e8564dd..784c7155b98a 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c @@ -747,7 +747,7 @@ int bnx2x_vfpf_config_mac(struct bnx2x *bp, u8 *addr, u8 vf_qid, bool set) out: bnx2x_vfpf_finalize(bp, &req->first_tlv); - return 0; + return rc; } /* request pf to config rss table for vf queues*/ -- cgit v1.2.3 From 4f337ed5c014752b000f593182fdcfa3ecf0d166 Mon Sep 17 00:00:00 2001 From: Jesse Gross Date: Fri, 16 May 2014 15:57:59 -0700 Subject: MAINTAINERS: Pravin Shelar is Open vSwitch maintainer. Pravin will be maintaining Open vSwitch going forward. CC: Pravin Shelar Signed-off-by: Jesse Gross Signed-off-by: David S. Miller --- MAINTAINERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 7578deb8ff20..0eb0adb16f1e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6511,10 +6511,10 @@ T: git git://openrisc.net/~jonas/linux F: arch/openrisc/ OPENVSWITCH -M: Jesse Gross +M: Pravin Shelar L: dev@openvswitch.org W: http://openvswitch.org -T: git git://git.kernel.org/pub/scm/linux/kernel/git/jesse/openvswitch.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/pshelar/openvswitch.git S: Maintained F: net/openvswitch/ -- cgit v1.2.3 From 524369e2391f4b422d0efdd11d526a373a11a43a Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Tue, 6 May 2014 19:45:38 +0200 Subject: can: c_can: remove obsolete STRICT_FRAME_ORDERING Kconfig option MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In 2b9aecdce2 ("can: c_can: Disable rx split as workaround") a new Kconfig option was introduced as a workaround. The tests performed by Alexander Stein confirmed this option to be obsolete with all the other cleanups and fixes that had been discussed that time: http://marc.info/?l=linux-can&m=139746476821294&w=2 Both (author and tester) agreed to remove this Kconfig option again: http://marc.info/?l=linux-can&m=139883820714229&w=2 As some more cleanups took place since then a simple revert is not possible. This patch removes the entire option as it would behave when disabled. Further beautification’s can be done later. Signed-off-by: Oliver Hartkopp Tested-by: Alexander Stein Signed-off-by: Marc Kleine-Budde --- drivers/net/can/c_can/Kconfig | 7 ------- drivers/net/can/c_can/c_can.c | 36 ------------------------------------ 2 files changed, 43 deletions(-) diff --git a/drivers/net/can/c_can/Kconfig b/drivers/net/can/c_can/Kconfig index 8ab7103d4f44..61ffc12d8fd8 100644 --- a/drivers/net/can/c_can/Kconfig +++ b/drivers/net/can/c_can/Kconfig @@ -14,13 +14,6 @@ config CAN_C_CAN_PLATFORM SPEAr1310 and SPEAr320 evaluation boards & TI (www.ti.com) boards like am335x, dm814x, dm813x and dm811x. -config CAN_C_CAN_STRICT_FRAME_ORDERING - bool "Force a strict RX CAN frame order (may cause frame loss)" - ---help--- - The RX split buffer prevents packet reordering but can cause packet - loss. Only enable this option when you accept to lose CAN frames - in favour of getting the received CAN frames in the correct order. - config CAN_C_CAN_PCI tristate "Generic PCI Bus based C_CAN/D_CAN driver" depends on PCI diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c index a2ca820b5373..95e04e2002da 100644 --- a/drivers/net/can/c_can/c_can.c +++ b/drivers/net/can/c_can/c_can.c @@ -732,26 +732,12 @@ static u32 c_can_adjust_pending(u32 pend) static inline void c_can_rx_object_get(struct net_device *dev, struct c_can_priv *priv, u32 obj) { -#ifdef CONFIG_CAN_C_CAN_STRICT_FRAME_ORDERING - if (obj < C_CAN_MSG_RX_LOW_LAST) - c_can_object_get(dev, IF_RX, obj, IF_COMM_RCV_LOW); - else -#endif c_can_object_get(dev, IF_RX, obj, priv->comm_rcv_high); } static inline void c_can_rx_finalize(struct net_device *dev, struct c_can_priv *priv, u32 obj) { -#ifdef CONFIG_CAN_C_CAN_STRICT_FRAME_ORDERING - if (obj < C_CAN_MSG_RX_LOW_LAST) - priv->rxmasked |= BIT(obj - 1); - else if (obj == C_CAN_MSG_RX_LOW_LAST) { - priv->rxmasked = 0; - /* activate all lower message objects */ - c_can_activate_all_lower_rx_msg_obj(dev, IF_RX); - } -#endif if (priv->type != BOSCH_D_CAN) c_can_object_get(dev, IF_RX, obj, IF_COMM_CLR_NEWDAT); } @@ -799,9 +785,6 @@ static inline u32 c_can_get_pending(struct c_can_priv *priv) { u32 pend = priv->read_reg(priv, C_CAN_NEWDAT1_REG); -#ifdef CONFIG_CAN_C_CAN_STRICT_FRAME_ORDERING - pend &= ~priv->rxmasked; -#endif return pend; } @@ -814,25 +797,6 @@ static inline u32 c_can_get_pending(struct c_can_priv *priv) * has arrived. To work-around this issue, we keep two groups of message * objects whose partitioning is defined by C_CAN_MSG_OBJ_RX_SPLIT. * - * If CONFIG_CAN_C_CAN_STRICT_FRAME_ORDERING = y - * - * To ensure in-order frame reception we use the following - * approach while re-activating a message object to receive further - * frames: - * - if the current message object number is lower than - * C_CAN_MSG_RX_LOW_LAST, do not clear the NEWDAT bit while clearing - * the INTPND bit. - * - if the current message object number is equal to - * C_CAN_MSG_RX_LOW_LAST then clear the NEWDAT bit of all lower - * receive message objects. - * - if the current message object number is greater than - * C_CAN_MSG_RX_LOW_LAST then clear the NEWDAT bit of - * only this message object. - * - * This can cause packet loss! - * - * If CONFIG_CAN_C_CAN_STRICT_FRAME_ORDERING = n - * * We clear the newdat bit right away. * * This can result in packet reordering when the readout is slow. -- cgit v1.2.3 From 02fb05a598e9393382f55132a36aff84f4d76ad5 Mon Sep 17 00:00:00 2001 From: Tushar Behera Date: Mon, 19 May 2014 14:53:53 +0530 Subject: ALSA: pcm_dmaengine: Add check during device suspend Currently snd_dmaengine_pcm_trigger() calls dmaengine_pause() unconditinally during device suspend. In case where DMA controller doesn't support PAUSE/RESUME functionality, this call is not able to stop the DMA controller. In this scenario, audio playback doesn't resume after device resume. Calling dmaengine_pause/dmaengine_terminate_all conditionally fixes the issue. It has been tested with audio playback on Samsung platform having PL330 DMA controller which doesn't support PAUSE/RESUME. Signed-off-by: Tushar Behera Acked-by: Lars-Peter Clausen Signed-off-by: Takashi Iwai --- sound/core/pcm_dmaengine.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sound/core/pcm_dmaengine.c b/sound/core/pcm_dmaengine.c index 94d08733cb38..76cbb9ec953a 100644 --- a/sound/core/pcm_dmaengine.c +++ b/sound/core/pcm_dmaengine.c @@ -182,6 +182,7 @@ static int dmaengine_pcm_prepare_and_submit(struct snd_pcm_substream *substream) int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd) { struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + struct snd_pcm_runtime *runtime = substream->runtime; int ret; switch (cmd) { @@ -196,6 +197,11 @@ int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd) dmaengine_resume(prtd->dma_chan); break; case SNDRV_PCM_TRIGGER_SUSPEND: + if (runtime->info & SNDRV_PCM_INFO_PAUSE) + dmaengine_pause(prtd->dma_chan); + else + dmaengine_terminate_all(prtd->dma_chan); + break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: dmaengine_pause(prtd->dma_chan); break; -- cgit v1.2.3 From 866293ee54227584ffcb4a42f69c1f365974ba7f Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 12 May 2014 20:45:34 +0000 Subject: futex: Add another early deadlock detection check Dave Jones trinity syscall fuzzer exposed an issue in the deadlock detection code of rtmutex: http://lkml.kernel.org/r/20140429151655.GA14277@redhat.com That underlying issue has been fixed with a patch to the rtmutex code, but the futex code must not call into rtmutex in that case because - it can detect that issue early - it avoids a different and more complex fixup for backing out If the user space variable got manipulated to 0x80000000 which means no lock holder, but the waiters bit set and an active pi_state in the kernel is found we can figure out the recursive locking issue by looking at the pi_state owner. If that is the current task, then we can safely return -EDEADLK. The check should have been added in commit 59fa62451 (futex: Handle futex_pi OWNER_DIED take over correctly) already, but I did not see the above issue caused by user space manipulation back then. Signed-off-by: Thomas Gleixner Cc: Dave Jones Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Darren Hart Cc: Davidlohr Bueso Cc: Steven Rostedt Cc: Clark Williams Cc: Paul McKenney Cc: Lai Jiangshan Cc: Roland McGrath Cc: Carlos ODonell Cc: Jakub Jelinek Cc: Michael Kerrisk Cc: Sebastian Andrzej Siewior Link: http://lkml.kernel.org/r/20140512201701.097349971@linutronix.de Signed-off-by: Thomas Gleixner Cc: stable@vger.kernel.org --- kernel/futex.c | 47 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/kernel/futex.c b/kernel/futex.c index 5f589279e462..7c68225e3967 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -745,7 +745,8 @@ void exit_pi_state_list(struct task_struct *curr) static int lookup_pi_state(u32 uval, struct futex_hash_bucket *hb, - union futex_key *key, struct futex_pi_state **ps) + union futex_key *key, struct futex_pi_state **ps, + struct task_struct *task) { struct futex_pi_state *pi_state = NULL; struct futex_q *this, *next; @@ -786,6 +787,16 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb, return -EINVAL; } + /* + * Protect against a corrupted uval. If uval + * is 0x80000000 then pid is 0 and the waiter + * bit is set. So the deadlock check in the + * calling code has failed and we did not fall + * into the check above due to !pid. + */ + if (task && pi_state->owner == task) + return -EDEADLK; + atomic_inc(&pi_state->refcount); *ps = pi_state; @@ -935,7 +946,7 @@ retry: * We dont have the lock. Look up the PI state (or create it if * we are the first waiter): */ - ret = lookup_pi_state(uval, hb, key, ps); + ret = lookup_pi_state(uval, hb, key, ps, task); if (unlikely(ret)) { switch (ret) { @@ -1347,7 +1358,7 @@ void requeue_pi_wake_futex(struct futex_q *q, union futex_key *key, * * Return: * 0 - failed to acquire the lock atomically; - * 1 - acquired the lock; + * >0 - acquired the lock, return value is vpid of the top_waiter * <0 - error */ static int futex_proxy_trylock_atomic(u32 __user *pifutex, @@ -1358,7 +1369,7 @@ static int futex_proxy_trylock_atomic(u32 __user *pifutex, { struct futex_q *top_waiter = NULL; u32 curval; - int ret; + int ret, vpid; if (get_futex_value_locked(&curval, pifutex)) return -EFAULT; @@ -1386,11 +1397,13 @@ static int futex_proxy_trylock_atomic(u32 __user *pifutex, * the contended case or if set_waiters is 1. The pi_state is returned * in ps in contended cases. */ + vpid = task_pid_vnr(top_waiter->task); ret = futex_lock_pi_atomic(pifutex, hb2, key2, ps, top_waiter->task, set_waiters); - if (ret == 1) + if (ret == 1) { requeue_pi_wake_futex(top_waiter, key2, hb2); - + return vpid; + } return ret; } @@ -1421,7 +1434,6 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags, struct futex_pi_state *pi_state = NULL; struct futex_hash_bucket *hb1, *hb2; struct futex_q *this, *next; - u32 curval2; if (requeue_pi) { /* @@ -1509,16 +1521,25 @@ retry_private: * At this point the top_waiter has either taken uaddr2 or is * waiting on it. If the former, then the pi_state will not * exist yet, look it up one more time to ensure we have a - * reference to it. + * reference to it. If the lock was taken, ret contains the + * vpid of the top waiter task. */ - if (ret == 1) { + if (ret > 0) { WARN_ON(pi_state); drop_count++; task_count++; - ret = get_futex_value_locked(&curval2, uaddr2); - if (!ret) - ret = lookup_pi_state(curval2, hb2, &key2, - &pi_state); + /* + * If we acquired the lock, then the user + * space value of uaddr2 should be vpid. It + * cannot be changed by the top waiter as it + * is blocked on hb2 lock if it tries to do + * so. If something fiddled with it behind our + * back the pi state lookup might unearth + * it. So we rather use the known value than + * rereading and handing potential crap to + * lookup_pi_state. + */ + ret = lookup_pi_state(ret, hb2, &key2, &pi_state, NULL); } switch (ret) { -- cgit v1.2.3 From f0d71b3dcb8332f7971b5f2363632573e6d9486a Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 12 May 2014 20:45:35 +0000 Subject: futex: Prevent attaching to kernel threads We happily allow userspace to declare a random kernel thread to be the owner of a user space PI futex. Found while analysing the fallout of Dave Jones syscall fuzzer. We also should validate the thread group for private futexes and find some fast way to validate whether the "alleged" owner has RW access on the file which backs the SHM, but that's a separate issue. Signed-off-by: Thomas Gleixner Cc: Dave Jones Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Darren Hart Cc: Davidlohr Bueso Cc: Steven Rostedt Cc: Clark Williams Cc: Paul McKenney Cc: Lai Jiangshan Cc: Roland McGrath Cc: Carlos ODonell Cc: Jakub Jelinek Cc: Michael Kerrisk Cc: Sebastian Andrzej Siewior Link: http://lkml.kernel.org/r/20140512201701.194824402@linutronix.de Signed-off-by: Thomas Gleixner Cc: stable@vger.kernel.org --- kernel/futex.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/kernel/futex.c b/kernel/futex.c index 7c68225e3967..81dbe773ce4c 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -814,6 +814,11 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb, if (!p) return -ESRCH; + if (!p->mm) { + put_task_struct(p); + return -EPERM; + } + /* * We need to look at the task state flags to figure out, * whether the task is exiting. To protect against the do_exit -- cgit v1.2.3 From 0819b2e30ccb93edf04876237b6205eef84ec8d2 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Thu, 15 May 2014 20:23:48 +0200 Subject: perf: Limit perf_event_attr::sample_period to 63 bits Vince reported that using a large sample_period (one with bit 63 set) results in wreckage since while the sample_period is fundamentally unsigned (negative periods don't make sense) the way we implement things very much rely on signed logic. So limit sample_period to 63 bits to avoid tripping over this. Reported-by: Vince Weaver Signed-off-by: Peter Zijlstra Cc: stable@vger.kernel.org Link: http://lkml.kernel.org/n/tip-p25fhunibl4y3qi0zuqmyf4b@git.kernel.org Signed-off-by: Thomas Gleixner --- kernel/events/core.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/events/core.c b/kernel/events/core.c index 71232844f235..1d1ec6453a08 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -7029,6 +7029,9 @@ SYSCALL_DEFINE5(perf_event_open, if (attr.freq) { if (attr.sample_freq > sysctl_perf_event_sample_rate) return -EINVAL; + } else { + if (attr.sample_period & (1ULL << 63)) + return -EINVAL; } /* -- cgit v1.2.3 From 39af6b1678afa5880dda7e375cf3f9d395087f6d Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 7 Apr 2014 11:04:08 +0200 Subject: perf: Prevent false warning in perf_swevent_add The perf cpu offline callback takes down all cpu context events and releases swhash->swevent_hlist. This could race with task context software event being just scheduled on this cpu via perf_swevent_add while cpu hotplug code already cleaned up event's data. The race happens in the gap between the cpu notifier code and the cpu being actually taken down. Note that only cpu ctx events are terminated in the perf cpu hotplug code. It's easily reproduced with: $ perf record -e faults perf bench sched pipe while putting one of the cpus offline: # echo 0 > /sys/devices/system/cpu/cpu1/online Console emits following warning: WARNING: CPU: 1 PID: 2845 at kernel/events/core.c:5672 perf_swevent_add+0x18d/0x1a0() Modules linked in: CPU: 1 PID: 2845 Comm: sched-pipe Tainted: G W 3.14.0+ #256 Hardware name: Intel Corporation Montevina platform/To be filled by O.E.M., BIOS AMVACRB1.86C.0066.B00.0805070703 05/07/2008 0000000000000009 ffff880077233ab8 ffffffff81665a23 0000000000200005 0000000000000000 ffff880077233af8 ffffffff8104732c 0000000000000046 ffff88007467c800 0000000000000002 ffff88007a9cf2a0 0000000000000001 Call Trace: [] dump_stack+0x4f/0x7c [] warn_slowpath_common+0x8c/0xc0 [] warn_slowpath_null+0x1a/0x20 [] perf_swevent_add+0x18d/0x1a0 [] event_sched_in.isra.75+0x9e/0x1f0 [] group_sched_in+0x6a/0x1f0 [] ? sched_clock_local+0x25/0xa0 [] ctx_sched_in+0x1f6/0x450 [] perf_event_sched_in+0x6b/0xa0 [] perf_event_context_sched_in+0x7b/0xc0 [] __perf_event_task_sched_in+0x43e/0x460 [] ? put_lock_stats.isra.18+0xe/0x30 [] finish_task_switch+0xb8/0x100 [] __schedule+0x30e/0xad0 [] ? pipe_read+0x3e2/0x560 [] ? preempt_schedule_irq+0x3e/0x70 [] ? preempt_schedule_irq+0x3e/0x70 [] preempt_schedule_irq+0x44/0x70 [] retint_kernel+0x20/0x30 [] ? lockdep_sys_exit+0x1a/0x90 [] lockdep_sys_exit_thunk+0x35/0x67 [] ? sysret_check+0x5/0x56 Fixing this by tracking the cpu hotplug state and displaying the WARN only if current cpu is initialized properly. Cc: Corey Ashford Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Paul Mackerras Cc: Arnaldo Carvalho de Melo Cc: stable@vger.kernel.org Reported-by: Fengguang Wu Signed-off-by: Jiri Olsa Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1396861448-10097-1-git-send-email-jolsa@redhat.com Signed-off-by: Thomas Gleixner --- kernel/events/core.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/kernel/events/core.c b/kernel/events/core.c index 1d1ec6453a08..feb1329ca331 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -5419,6 +5419,9 @@ struct swevent_htable { /* Recursion avoidance in each contexts */ int recursion[PERF_NR_CONTEXTS]; + + /* Keeps track of cpu being initialized/exited */ + bool online; }; static DEFINE_PER_CPU(struct swevent_htable, swevent_htable); @@ -5665,8 +5668,14 @@ static int perf_swevent_add(struct perf_event *event, int flags) hwc->state = !(flags & PERF_EF_START); head = find_swevent_head(swhash, event); - if (WARN_ON_ONCE(!head)) + if (!head) { + /* + * We can race with cpu hotplug code. Do not + * WARN if the cpu just got unplugged. + */ + WARN_ON_ONCE(swhash->online); return -EINVAL; + } hlist_add_head_rcu(&event->hlist_entry, head); @@ -7845,6 +7854,7 @@ static void perf_event_init_cpu(int cpu) struct swevent_htable *swhash = &per_cpu(swevent_htable, cpu); mutex_lock(&swhash->hlist_mutex); + swhash->online = true; if (swhash->hlist_refcount > 0) { struct swevent_hlist *hlist; @@ -7902,6 +7912,7 @@ static void perf_event_exit_cpu(int cpu) perf_event_exit_cpu_context(cpu); mutex_lock(&swhash->hlist_mutex); + swhash->online = false; swevent_hlist_release(swhash); mutex_unlock(&swhash->hlist_mutex); } -- cgit v1.2.3 From b69cf53640da2b86439596118cfa95233154ee76 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Fri, 14 Mar 2014 10:50:33 +0100 Subject: perf: Fix a race between ring_buffer_detach() and ring_buffer_attach() Alexander noticed that we use RCU iteration on rb->event_list but do not use list_{add,del}_rcu() to add,remove entries to that list, nor do we observe proper grace periods when re-using the entries. Merge ring_buffer_detach() into ring_buffer_attach() such that attaching to the NULL buffer is detaching. Furthermore, ensure that between any 'detach' and 'attach' of the same event we observe the required grace period, but only when strictly required. In effect this means that only ioctl(.request = PERF_EVENT_IOC_SET_OUTPUT) will wait for a grace period, while the normal initial attach and final detach will not be delayed. This patch should, I think, do the right thing under all circumstances, the 'normal' cases all should never see the extra grace period, but the two cases: 1) PERF_EVENT_IOC_SET_OUTPUT on an event which already has a ring_buffer set, will now observe the required grace period between removing itself from the old and attaching itself to the new buffer. This case is 'simple' in that both buffers are present in perf_event_set_output() one could think an unconditional synchronize_rcu() would be sufficient; however... 2) an event that has a buffer attached, the buffer is destroyed (munmap) and then the event is attached to a new/different buffer using PERF_EVENT_IOC_SET_OUTPUT. This case is more complex because the buffer destruction does: ring_buffer_attach(.rb = NULL) followed by the ioctl() doing: ring_buffer_attach(.rb = foo); and we still need to observe the grace period between these two calls due to us reusing the event->rb_entry list_head. In order to make 2 happen we use Paul's latest cond_synchronize_rcu() call. Cc: Paul Mackerras Cc: Stephane Eranian Cc: Andi Kleen Cc: "Paul E. McKenney" Cc: Ingo Molnar Cc: Frederic Weisbecker Cc: Mike Galbraith Reported-by: Alexander Shishkin Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/20140507123526.GD13658@twins.programming.kicks-ass.net Signed-off-by: Thomas Gleixner --- include/linux/perf_event.h | 2 + kernel/events/core.c | 109 ++++++++++++++++++++------------------------- 2 files changed, 51 insertions(+), 60 deletions(-) diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 3356abcfff18..3ef6ea12806a 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -402,6 +402,8 @@ struct perf_event { struct ring_buffer *rb; struct list_head rb_entry; + unsigned long rcu_batches; + int rcu_pending; /* poll related */ wait_queue_head_t waitq; diff --git a/kernel/events/core.c b/kernel/events/core.c index feb1329ca331..440eefc67397 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -3192,7 +3192,8 @@ static void free_event_rcu(struct rcu_head *head) } static void ring_buffer_put(struct ring_buffer *rb); -static void ring_buffer_detach(struct perf_event *event, struct ring_buffer *rb); +static void ring_buffer_attach(struct perf_event *event, + struct ring_buffer *rb); static void unaccount_event_cpu(struct perf_event *event, int cpu) { @@ -3252,8 +3253,6 @@ static void free_event(struct perf_event *event) unaccount_event(event); if (event->rb) { - struct ring_buffer *rb; - /* * Can happen when we close an event with re-directed output. * @@ -3261,12 +3260,7 @@ static void free_event(struct perf_event *event) * over us; possibly making our ring_buffer_put() the last. */ mutex_lock(&event->mmap_mutex); - rb = event->rb; - if (rb) { - rcu_assign_pointer(event->rb, NULL); - ring_buffer_detach(event, rb); - ring_buffer_put(rb); /* could be last */ - } + ring_buffer_attach(event, NULL); mutex_unlock(&event->mmap_mutex); } @@ -3850,28 +3844,47 @@ unlock: static void ring_buffer_attach(struct perf_event *event, struct ring_buffer *rb) { + struct ring_buffer *old_rb = NULL; unsigned long flags; - if (!list_empty(&event->rb_entry)) - return; + if (event->rb) { + /* + * Should be impossible, we set this when removing + * event->rb_entry and wait/clear when adding event->rb_entry. + */ + WARN_ON_ONCE(event->rcu_pending); - spin_lock_irqsave(&rb->event_lock, flags); - if (list_empty(&event->rb_entry)) - list_add(&event->rb_entry, &rb->event_list); - spin_unlock_irqrestore(&rb->event_lock, flags); -} + old_rb = event->rb; + event->rcu_batches = get_state_synchronize_rcu(); + event->rcu_pending = 1; -static void ring_buffer_detach(struct perf_event *event, struct ring_buffer *rb) -{ - unsigned long flags; + spin_lock_irqsave(&old_rb->event_lock, flags); + list_del_rcu(&event->rb_entry); + spin_unlock_irqrestore(&old_rb->event_lock, flags); + } - if (list_empty(&event->rb_entry)) - return; + if (event->rcu_pending && rb) { + cond_synchronize_rcu(event->rcu_batches); + event->rcu_pending = 0; + } - spin_lock_irqsave(&rb->event_lock, flags); - list_del_init(&event->rb_entry); - wake_up_all(&event->waitq); - spin_unlock_irqrestore(&rb->event_lock, flags); + if (rb) { + spin_lock_irqsave(&rb->event_lock, flags); + list_add_rcu(&event->rb_entry, &rb->event_list); + spin_unlock_irqrestore(&rb->event_lock, flags); + } + + rcu_assign_pointer(event->rb, rb); + + if (old_rb) { + ring_buffer_put(old_rb); + /* + * Since we detached before setting the new rb, so that we + * could attach the new rb, we could have missed a wakeup. + * Provide it now. + */ + wake_up_all(&event->waitq); + } } static void ring_buffer_wakeup(struct perf_event *event) @@ -3940,7 +3953,7 @@ static void perf_mmap_close(struct vm_area_struct *vma) { struct perf_event *event = vma->vm_file->private_data; - struct ring_buffer *rb = event->rb; + struct ring_buffer *rb = ring_buffer_get(event); struct user_struct *mmap_user = rb->mmap_user; int mmap_locked = rb->mmap_locked; unsigned long size = perf_data_size(rb); @@ -3948,18 +3961,14 @@ static void perf_mmap_close(struct vm_area_struct *vma) atomic_dec(&rb->mmap_count); if (!atomic_dec_and_mutex_lock(&event->mmap_count, &event->mmap_mutex)) - return; + goto out_put; - /* Detach current event from the buffer. */ - rcu_assign_pointer(event->rb, NULL); - ring_buffer_detach(event, rb); + ring_buffer_attach(event, NULL); mutex_unlock(&event->mmap_mutex); /* If there's still other mmap()s of this buffer, we're done. */ - if (atomic_read(&rb->mmap_count)) { - ring_buffer_put(rb); /* can't be last */ - return; - } + if (atomic_read(&rb->mmap_count)) + goto out_put; /* * No other mmap()s, detach from all other events that might redirect @@ -3989,11 +3998,9 @@ again: * still restart the iteration to make sure we're not now * iterating the wrong list. */ - if (event->rb == rb) { - rcu_assign_pointer(event->rb, NULL); - ring_buffer_detach(event, rb); - ring_buffer_put(rb); /* can't be last, we still have one */ - } + if (event->rb == rb) + ring_buffer_attach(event, NULL); + mutex_unlock(&event->mmap_mutex); put_event(event); @@ -4018,6 +4025,7 @@ again: vma->vm_mm->pinned_vm -= mmap_locked; free_uid(mmap_user); +out_put: ring_buffer_put(rb); /* could be last */ } @@ -4135,7 +4143,6 @@ again: vma->vm_mm->pinned_vm += extra; ring_buffer_attach(event, rb); - rcu_assign_pointer(event->rb, rb); perf_event_init_userpage(event); perf_event_update_userpage(event); @@ -6934,7 +6941,7 @@ err_size: static int perf_event_set_output(struct perf_event *event, struct perf_event *output_event) { - struct ring_buffer *rb = NULL, *old_rb = NULL; + struct ring_buffer *rb = NULL; int ret = -EINVAL; if (!output_event) @@ -6962,8 +6969,6 @@ set: if (atomic_read(&event->mmap_count)) goto unlock; - old_rb = event->rb; - if (output_event) { /* get the rb we want to redirect to */ rb = ring_buffer_get(output_event); @@ -6971,23 +6976,7 @@ set: goto unlock; } - if (old_rb) - ring_buffer_detach(event, old_rb); - - if (rb) - ring_buffer_attach(event, rb); - - rcu_assign_pointer(event->rb, rb); - - if (old_rb) { - ring_buffer_put(old_rb); - /* - * Since we detached before setting the new rb, so that we - * could attach the new rb, we could have missed a wakeup. - * Provide it now. - */ - wake_up_all(&event->waitq); - } + ring_buffer_attach(event, rb); ret = 0; unlock: -- cgit v1.2.3 From 30cc798b63fd21ba58c94f4f8b4c1e55137fd029 Mon Sep 17 00:00:00 2001 From: Beomho Seo Date: Tue, 20 May 2014 01:12:50 +0900 Subject: ARM: dts: fix incorrect ak8975 compatible for exynos4412-trats2 board This patch fixed incorrect compatible for ak8975 magnetic sensor. ak8975 magnetic sensor use compatible "ak8975" or "asahi-kasei,ak8975" In this patch, use "asahi-kasei,ak8975" according to dt bindings document. Signed-off-by: Beomho Seo Signed-off-by: MyungJoo Ham Reviewed-by: Tomasz Figa Signed-off-by: Kukjin Kim --- arch/arm/boot/dts/exynos4412-trats2.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/exynos4412-trats2.dts b/arch/arm/boot/dts/exynos4412-trats2.dts index 9583563dd0ef..8a558b7ac999 100644 --- a/arch/arm/boot/dts/exynos4412-trats2.dts +++ b/arch/arm/boot/dts/exynos4412-trats2.dts @@ -503,7 +503,7 @@ status = "okay"; ak8975@0c { - compatible = "ak,ak8975"; + compatible = "asahi-kasei,ak8975"; reg = <0x0c>; gpios = <&gpj0 7 0>; }; -- cgit v1.2.3 From e3b6c271abddb5363b01b79d6e6e4343008cd991 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 20 May 2014 01:14:03 +0900 Subject: ARM: dts: Fix SPI interrupt numbers for exynos5420 Updated as per the user manual. Signed-off-by: Sachin Kamat Signed-off-by: Kukjin Kim --- arch/arm/boot/dts/exynos5420.dtsi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi index c3a9a66c5767..6f662b5cc90d 100644 --- a/arch/arm/boot/dts/exynos5420.dtsi +++ b/arch/arm/boot/dts/exynos5420.dtsi @@ -385,7 +385,7 @@ spi_0: spi@12d20000 { compatible = "samsung,exynos4210-spi"; reg = <0x12d20000 0x100>; - interrupts = <0 66 0>; + interrupts = <0 68 0>; dmas = <&pdma0 5 &pdma0 4>; dma-names = "tx", "rx"; @@ -401,7 +401,7 @@ spi_1: spi@12d30000 { compatible = "samsung,exynos4210-spi"; reg = <0x12d30000 0x100>; - interrupts = <0 67 0>; + interrupts = <0 69 0>; dmas = <&pdma1 5 &pdma1 4>; dma-names = "tx", "rx"; @@ -417,7 +417,7 @@ spi_2: spi@12d40000 { compatible = "samsung,exynos4210-spi"; reg = <0x12d40000 0x100>; - interrupts = <0 68 0>; + interrupts = <0 70 0>; dmas = <&pdma0 7 &pdma0 6>; dma-names = "tx", "rx"; -- cgit v1.2.3 From 68d0e40298f064a5cff40670caded0480274d4b2 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 20 May 2014 01:15:46 +0900 Subject: ARM: dts: Keep LDO4 always ON for exynos5250-arndale board LDO4 regulator was getting disabled preventing the system from going into low power states. Keep it always on to fix it. Signed-off-by: Sachin Kamat Signed-off-by: Kukjin Kim --- arch/arm/boot/dts/exynos5250-arndale.dts | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/exynos5250-arndale.dts b/arch/arm/boot/dts/exynos5250-arndale.dts index 090f9830b129..cde19c818667 100644 --- a/arch/arm/boot/dts/exynos5250-arndale.dts +++ b/arch/arm/boot/dts/exynos5250-arndale.dts @@ -107,6 +107,7 @@ regulator-name = "VDD_IOPERI_1.8V"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; + regulator-always-on; op_mode = <1>; }; -- cgit v1.2.3 From 4b353a706a86598ba47307c47301c3c428b79e09 Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Mon, 12 May 2014 17:37:59 -0400 Subject: ARM: OMAP4: Fix the boot regression with CPU_IDLE enabled On OMAP4 panda board, there have been several bug reports about boot hang and lock-ups with CPU_IDLE enabled. The root cause of the issue is missing interrupts while in idle state. Commit cb7094e8 {cpuidle / omap4 : use CPUIDLE_FLAG_TIMER_STOP flag} moved the broadcast notifiers to common code for right reasons but on OMAP4 which suffers from a nasty ROM code bug with GIC, commit ff999b8a {ARM: OMAP4460: Workaround for ROM bug ..}, we loose interrupts which leads to issues like lock-up, hangs etc. Patch reverts commit cb7094 {cpuidle / omap4 : use CPUIDLE_FLAG_TIMER_STOP flag} and 54769d6 {cpuidle: OMAP4: remove timer broadcast initialization} to avoid the issue. With this change, OMAP4 panda boards, the mentioned issues are getting fixed. We no longer loose interrupts which was the cause of the regression. Fixes: cb7094e8 (cpuidle / omap4 : use CPUIDLE_FLAG_TIMER_STOP flag) Fixes: ff999b8a (cpuidle: OMAP4: remove timer broadcast initialization) Cc: stable@vger.kernel.org # v3.9+ Cc: Roger Quadros Cc: Kevin Hilman Cc: Tony Lindgren Cc: Daniel Lezcano Reported-tested-by: Roger Quadros Reported-tested-by: Kevin Hilman Tested-by: Tony Lindgren Signed-off-by: Santosh Shilimkar Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/cpuidle44xx.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-omap2/cpuidle44xx.c b/arch/arm/mach-omap2/cpuidle44xx.c index 01fc710c8181..2498ab025fa2 100644 --- a/arch/arm/mach-omap2/cpuidle44xx.c +++ b/arch/arm/mach-omap2/cpuidle44xx.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -83,6 +84,7 @@ static int omap_enter_idle_coupled(struct cpuidle_device *dev, { struct idle_statedata *cx = state_ptr + index; u32 mpuss_can_lose_context = 0; + int cpu_id = smp_processor_id(); /* * CPU0 has to wait and stay ON until CPU1 is OFF state. @@ -110,6 +112,8 @@ static int omap_enter_idle_coupled(struct cpuidle_device *dev, mpuss_can_lose_context = (cx->mpu_state == PWRDM_POWER_RET) && (cx->mpu_logic_state == PWRDM_POWER_OFF); + clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu_id); + /* * Call idle CPU PM enter notifier chain so that * VFP and per CPU interrupt context is saved. @@ -165,6 +169,8 @@ static int omap_enter_idle_coupled(struct cpuidle_device *dev, if (dev->cpu == 0 && mpuss_can_lose_context) cpu_cluster_pm_exit(); + clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu_id); + fail: cpuidle_coupled_parallel_barrier(dev, &abort_barrier); cpu_done[dev->cpu] = false; @@ -172,6 +178,16 @@ fail: return index; } +/* + * For each cpu, setup the broadcast timer because local timers + * stops for the states above C1. + */ +static void omap_setup_broadcast_timer(void *arg) +{ + int cpu = smp_processor_id(); + clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ON, &cpu); +} + static struct cpuidle_driver omap4_idle_driver = { .name = "omap4_idle", .owner = THIS_MODULE, @@ -189,8 +205,7 @@ static struct cpuidle_driver omap4_idle_driver = { /* C2 - CPU0 OFF + CPU1 OFF + MPU CSWR */ .exit_latency = 328 + 440, .target_residency = 960, - .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_COUPLED | - CPUIDLE_FLAG_TIMER_STOP, + .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_COUPLED, .enter = omap_enter_idle_coupled, .name = "C2", .desc = "CPUx OFF, MPUSS CSWR", @@ -199,8 +214,7 @@ static struct cpuidle_driver omap4_idle_driver = { /* C3 - CPU0 OFF + CPU1 OFF + MPU OSWR */ .exit_latency = 460 + 518, .target_residency = 1100, - .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_COUPLED | - CPUIDLE_FLAG_TIMER_STOP, + .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_COUPLED, .enter = omap_enter_idle_coupled, .name = "C3", .desc = "CPUx OFF, MPUSS OSWR", @@ -231,5 +245,8 @@ int __init omap4_idle_init(void) if (!cpu_clkdm[0] || !cpu_clkdm[1]) return -ENODEV; + /* Configure the broadcast timer on each cpu */ + on_each_cpu(omap_setup_broadcast_timer, NULL, 1); + return cpuidle_register(&omap4_idle_driver, cpu_online_mask); } -- cgit v1.2.3 From d0b4cc4e32705ff00d90d32da7783c266c702c04 Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Mon, 19 May 2014 13:06:46 +1000 Subject: PCI: Wrong register used to check pending traffic The incorrect register offset is passed to pci_wait_for_pending(), which is caused by commit 157e876ffe ("PCI: Add pci_wait_for_pending() (refactor pci_wait_for_pending_transaction())"). Fixes: 157e876ffe ("PCI: Add pci_wait_for_pending() (refactor pci_wait_for_pending_transaction()) Signed-off-by: Gavin Shan Signed-off-by: Bjorn Helgaas Acked-by: Alex Williamson CC: stable@vger.kernel.org # v3.14+ --- drivers/pci/pci.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 7325d43bf030..759475ef6ff3 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -3067,7 +3067,8 @@ int pci_wait_for_pending_transaction(struct pci_dev *dev) if (!pci_is_pcie(dev)) return 1; - return pci_wait_for_pending(dev, PCI_EXP_DEVSTA, PCI_EXP_DEVSTA_TRPND); + return pci_wait_for_pending(dev, pci_pcie_cap(dev) + PCI_EXP_DEVSTA, + PCI_EXP_DEVSTA_TRPND); } EXPORT_SYMBOL(pci_wait_for_pending_transaction); @@ -3109,7 +3110,7 @@ static int pci_af_flr(struct pci_dev *dev, int probe) return 0; /* Wait for Transaction Pending bit clean */ - if (pci_wait_for_pending(dev, PCI_AF_STATUS, PCI_AF_STATUS_TP)) + if (pci_wait_for_pending(dev, pos + PCI_AF_STATUS, PCI_AF_STATUS_TP)) goto clear; dev_err(&dev->dev, "transaction is not cleared; " -- cgit v1.2.3 From 3685f2516116c5f3b9d498d531955ad70216ad84 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Sat, 17 May 2014 20:46:01 +0800 Subject: ahci: imx: PLL clock needs 100us to settle down The commit e783c51 (ahci: imx: software workaround for phy reset issue in resume) calls imx_sata_phy_reset() to reset phy immediately after SATA MPLL is enabled. It seems working fine mostly, but fails in some case as below. ... ahci-imx 2200000.sata: failed to reset phy: -110 ahci-imx: probe of 2200000.sata failed with error -110 After talking to the designer, we learnt that when enabling i.MX6Q SATA MPLL, we need to wait 100us for it to settle down for safety. Add this required delay to fix above failure. Signed-off-by: Shawn Guo Tested-by: Fabio Estevam Signed-off-by: Tejun Heo --- drivers/ata/ahci_imx.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c index 5824d99e63fd..8befeb69eeb1 100644 --- a/drivers/ata/ahci_imx.c +++ b/drivers/ata/ahci_imx.c @@ -258,6 +258,8 @@ static int imx_sata_enable(struct ahci_host_priv *hpriv) IMX6Q_GPR13_SATA_MPLL_CLK_EN, IMX6Q_GPR13_SATA_MPLL_CLK_EN); + usleep_range(100, 200); + ret = imx_sata_phy_reset(hpriv); if (ret) { dev_err(dev, "failed to reset phy: %d\n", ret); -- cgit v1.2.3 From c5450db85b828d0c46ac8fc570fb8a51bf07ac40 Mon Sep 17 00:00:00 2001 From: Bibek Basu Date: Mon, 19 May 2014 10:24:01 +0530 Subject: cpufreq: remove race while accessing cur_policy While accessing cur_policy during executing events CPUFREQ_GOV_START, CPUFREQ_GOV_STOP, CPUFREQ_GOV_LIMITS, same mutex lock is not taken, dbs_data->mutex, which leads to race and data corruption while running continious suspend resume test. This is seen with ondemand governor with suspend resume test using rtcwake. Unable to handle kernel NULL pointer dereference at virtual address 00000028 pgd = ed610000 [00000028] *pgd=adf11831, *pte=00000000, *ppte=00000000 Internal error: Oops: 17 [#1] PREEMPT SMP ARM Modules linked in: nvhost_vi CPU: 1 PID: 3243 Comm: rtcwake Not tainted 3.10.24-gf5cf9e5 #1 task: ee708040 ti: ed61c000 task.ti: ed61c000 PC is at cpufreq_governor_dbs+0x400/0x634 LR is at cpufreq_governor_dbs+0x3f8/0x634 pc : [] lr : [] psr: 600f0013 sp : ed61dcb0 ip : 000493e0 fp : c1cc14f0 r10: 00000000 r9 : 00000000 r8 : 00000000 r7 : eb725280 r6 : c1cc1560 r5 : eb575200 r4 : ebad7740 r3 : ee708040 r2 : ed61dca8 r1 : 001ebd24 r0 : 00000000 Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user Control: 10c5387d Table: ad61006a DAC: 00000015 [] (cpufreq_governor_dbs+0x400/0x634) from [] (__cpufreq_governor+0x98/0x1b4) [] (__cpufreq_governor+0x98/0x1b4) from [] (__cpufreq_set_policy+0x250/0x320) [] (__cpufreq_set_policy+0x250/0x320) from [] (cpufreq_update_policy+0xcc/0x168) [] (cpufreq_update_policy+0xcc/0x168) from [] (cpu_freq_notify+0x68/0xdc) [] (cpu_freq_notify+0x68/0xdc) from [] (notifier_call_chain+0x4c/0x8c) [] (notifier_call_chain+0x4c/0x8c) from [] (__blocking_notifier_call_chain+0x50/0x68) [] (__blocking_notifier_call_chain+0x50/0x68) from [] (blocking_notifier_call_chain+0x20/0x28) [] (blocking_notifier_call_chain+0x20/0x28) from [] (pm_qos_update_bounded_target+0xd8/0x310) [] (pm_qos_update_bounded_target+0xd8/0x310) from [] (__pm_qos_update_request+0x64/0x70) [] (__pm_qos_update_request+0x64/0x70) from [] (tegra_pm_notify+0x114/0x134) [] (tegra_pm_notify+0x114/0x134) from [] (notifier_call_chain+0x4c/0x8c) [] (notifier_call_chain+0x4c/0x8c) from [] (__blocking_notifier_call_chain+0x50/0x68) [] (__blocking_notifier_call_chain+0x50/0x68) from [] (blocking_notifier_call_chain+0x20/0x28) [] (blocking_notifier_call_chain+0x20/0x28) from [] (pm_notifier_call_chain+0x1c/0x34) [] (pm_notifier_call_chain+0x1c/0x34) from [] (enter_state+0xec/0x128) [] (enter_state+0xec/0x128) from [] (pm_suspend+0x38/0xa4) [] (pm_suspend+0x38/0xa4) from [] (state_store+0x70/0xc0) [] (state_store+0x70/0xc0) from [] (kobj_attr_store+0x14/0x20) [] (kobj_attr_store+0x14/0x20) from [] (sysfs_write_file+0x104/0x184) [] (sysfs_write_file+0x104/0x184) from [] (vfs_write+0xd0/0x19c) [] (vfs_write+0xd0/0x19c) from [] (SyS_write+0x4c/0x78) [] (SyS_write+0x4c/0x78) from [] (ret_fast_syscall+0x0/0x30) Code: e1a00006 eb084346 e59b0020 e5951024 (e5903028) ---[ end trace 0488523c8f6b0f9d ]--- Signed-off-by: Bibek Basu Acked-by: Viresh Kumar Cc: 3.11+ # 3.11+ Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq_governor.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c index ba43991ba98a..e1c6433b16e0 100644 --- a/drivers/cpufreq/cpufreq_governor.c +++ b/drivers/cpufreq/cpufreq_governor.c @@ -366,6 +366,11 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy, break; case CPUFREQ_GOV_LIMITS: + mutex_lock(&dbs_data->mutex); + if (!cpu_cdbs->cur_policy) { + mutex_unlock(&dbs_data->mutex); + break; + } mutex_lock(&cpu_cdbs->timer_mutex); if (policy->max < cpu_cdbs->cur_policy->cur) __cpufreq_driver_target(cpu_cdbs->cur_policy, @@ -375,6 +380,7 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy, policy->min, CPUFREQ_RELATION_L); dbs_check_cpu(dbs_data, cpu); mutex_unlock(&cpu_cdbs->timer_mutex); + mutex_unlock(&dbs_data->mutex); break; } return 0; -- cgit v1.2.3 From e3beb0ac521d50d158a9d253373eae8421ac3998 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Fri, 16 May 2014 12:20:42 +0200 Subject: cpufreq: cpu0: drop wrong devm usage This driver is using devres managed calls incorrectly, giving the cpu0 device as first parameter instead of the cpufreq platform device. This results in resources not being freed if the cpufreq platform device is unbound, for example if probing has to be deferred for a missing regulator. Signed-off-by: Lucas Stach Acked-by: Viresh Kumar Cc: 3.9+ # 3.9+ Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq-cpu0.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c index 1bf6bbac3e03..09b9129c7bd3 100644 --- a/drivers/cpufreq/cpufreq-cpu0.c +++ b/drivers/cpufreq/cpufreq-cpu0.c @@ -130,7 +130,7 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev) return -ENOENT; } - cpu_reg = devm_regulator_get_optional(cpu_dev, "cpu0"); + cpu_reg = regulator_get_optional(cpu_dev, "cpu0"); if (IS_ERR(cpu_reg)) { /* * If cpu0 regulator supply node is present, but regulator is @@ -145,23 +145,23 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev) PTR_ERR(cpu_reg)); } - cpu_clk = devm_clk_get(cpu_dev, NULL); + cpu_clk = clk_get(cpu_dev, NULL); if (IS_ERR(cpu_clk)) { ret = PTR_ERR(cpu_clk); pr_err("failed to get cpu0 clock: %d\n", ret); - goto out_put_node; + goto out_put_reg; } ret = of_init_opp_table(cpu_dev); if (ret) { pr_err("failed to init OPP table: %d\n", ret); - goto out_put_node; + goto out_put_clk; } ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table); if (ret) { pr_err("failed to init cpufreq table: %d\n", ret); - goto out_put_node; + goto out_put_clk; } of_property_read_u32(np, "voltage-tolerance", &voltage_tolerance); @@ -216,6 +216,12 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev) out_free_table: dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table); +out_put_clk: + if (!IS_ERR(cpu_clk)) + clk_put(cpu_clk); +out_put_reg: + if (!IS_ERR(cpu_reg)) + regulator_put(cpu_reg); out_put_node: of_node_put(np); return ret; -- cgit v1.2.3 From f5c16f29bf5e57ba4051fc7785ba7f035f798c71 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 19 May 2014 15:52:10 -0400 Subject: sysfs: make sure read buffer is zeroed 13c589d5b0ac ("sysfs: use seq_file when reading regular files") switched sysfs from custom read implementation to seq_file to enable later transition to kernfs. After the change, the buffer passed to ->show() is acquired through seq_get_buf(); unfortunately, this introduces a subtle behavior change. Before the commit, the buffer passed to ->show() was always zero as it was allocated using get_zeroed_page(). Because seq_file doesn't clear buffers on allocation and neither does seq_get_buf(), after the commit, depending on the behavior of ->show(), we may end up exposing uninitialized data to userland thus possibly altering userland visible behavior and leaking information. Fix it by explicitly clearing the buffer. Signed-off-by: Tejun Heo Reported-by: Ron Fixes: 13c589d5b0ac ("sysfs: use seq_file when reading regular files") Cc: stable # 3.13+ Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/file.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 28cc1acd5439..e9ef59b3abb1 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -47,12 +47,13 @@ static int sysfs_kf_seq_show(struct seq_file *sf, void *v) ssize_t count; char *buf; - /* acquire buffer and ensure that it's >= PAGE_SIZE */ + /* acquire buffer and ensure that it's >= PAGE_SIZE and clear */ count = seq_get_buf(sf, &buf); if (count < PAGE_SIZE) { seq_commit(sf, -1); return 0; } + memset(buf, 0, PAGE_SIZE); /* * Invoke show(). Control may reach here via seq file lseek even -- cgit v1.2.3 From 6679b2ccc914e84384b1acf0de4423e3738cce9f Mon Sep 17 00:00:00 2001 From: Martin Peres Date: Mon, 12 May 2014 15:05:01 +0200 Subject: drm/nvd9/therm: handle another kind of PWM fan Signed-off-by: Martin Peres Tested-by: SaveTheRobots Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c b/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c index 43fec17ea540..bbf117be572f 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c @@ -40,6 +40,7 @@ pwm_info(struct nouveau_therm *therm, int line) case 0x00: return 2; case 0x19: return 1; case 0x1c: return 0; + case 0x1e: return 2; default: break; } -- cgit v1.2.3 From 0f1d360b2ee3a2a0f510d3f1bcd3f5ebe5d41265 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 20 May 2014 16:13:54 +1000 Subject: drm/gf119-/disp: fix nasty bug which can clobber SOR0's clock setup Fixes a LVDS bleed issue on Lenovo W530 that can occur under a number of circumstances. Cc: # v3.9+ Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c index 7762665ad8fd..876de9ac3793 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c @@ -1009,7 +1009,7 @@ exec_clkcmp(struct nv50_disp_priv *priv, int head, int id, } if (outp == 8) - return false; + return conf; data = exec_lookup(priv, head, outp, ctrl, dcb, &ver, &hdr, &cnt, &len, &info1); if (data == 0x0000) -- cgit v1.2.3 From cc79f00f7611cbb8f1ff1b92fe829548efcb4f08 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Tue, 20 May 2014 10:59:37 +0200 Subject: m68k: add renameat2 syscall Signed-off-by: Miklos Szeredi Acked-by: Geert Uytterhoeven --- arch/m68k/include/asm/unistd.h | 2 +- arch/m68k/include/uapi/asm/unistd.h | 1 + arch/m68k/kernel/syscalltable.S | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/m68k/include/asm/unistd.h b/arch/m68k/include/asm/unistd.h index 9d38b73989eb..33afa56ad47a 100644 --- a/arch/m68k/include/asm/unistd.h +++ b/arch/m68k/include/asm/unistd.h @@ -4,7 +4,7 @@ #include -#define NR_syscalls 351 +#define NR_syscalls 352 #define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_OLD_STAT diff --git a/arch/m68k/include/uapi/asm/unistd.h b/arch/m68k/include/uapi/asm/unistd.h index b932dd470041..9cd82fbc7817 100644 --- a/arch/m68k/include/uapi/asm/unistd.h +++ b/arch/m68k/include/uapi/asm/unistd.h @@ -356,5 +356,6 @@ #define __NR_finit_module 348 #define __NR_sched_setattr 349 #define __NR_sched_getattr 350 +#define __NR_renameat2 351 #endif /* _UAPI_ASM_M68K_UNISTD_H_ */ diff --git a/arch/m68k/kernel/syscalltable.S b/arch/m68k/kernel/syscalltable.S index b6223dc41d82..501e10212789 100644 --- a/arch/m68k/kernel/syscalltable.S +++ b/arch/m68k/kernel/syscalltable.S @@ -371,4 +371,5 @@ ENTRY(sys_call_table) .long sys_finit_module .long sys_sched_setattr .long sys_sched_getattr /* 350 */ + .long sys_renameat2 -- cgit v1.2.3 From 18e480aa07f78abc7938adfe1035a5d9ce188ad8 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Tue, 20 May 2014 10:59:37 +0200 Subject: parisc: add renameat2 syscall Signed-off-by: Miklos Szeredi Acked-by: Helge Deller --- arch/parisc/include/uapi/asm/unistd.h | 3 ++- arch/parisc/kernel/syscall_table.S | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/parisc/include/uapi/asm/unistd.h b/arch/parisc/include/uapi/asm/unistd.h index 265ae5190b0a..47e0e21d2272 100644 --- a/arch/parisc/include/uapi/asm/unistd.h +++ b/arch/parisc/include/uapi/asm/unistd.h @@ -829,8 +829,9 @@ #define __NR_sched_setattr (__NR_Linux + 334) #define __NR_sched_getattr (__NR_Linux + 335) #define __NR_utimes (__NR_Linux + 336) +#define __NR_renameat2 (__NR_Linux + 337) -#define __NR_Linux_syscalls (__NR_utimes + 1) +#define __NR_Linux_syscalls (__NR_renameat2 + 1) #define __IGNORE_select /* newselect */ diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S index 83ead0ea127d..f1432da7b4c0 100644 --- a/arch/parisc/kernel/syscall_table.S +++ b/arch/parisc/kernel/syscall_table.S @@ -432,6 +432,7 @@ ENTRY_SAME(sched_setattr) ENTRY_SAME(sched_getattr) /* 335 */ ENTRY_COMP(utimes) + ENTRY_COMP(renameat2) /* Nothing yet */ -- cgit v1.2.3 From 3ca976a2cf95c1d4254a1eb8e13b5063522691d5 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Tue, 20 May 2014 10:59:38 +0200 Subject: ia64: add renameat2 syscall Signed-off-by: Miklos Szeredi Acked-by: Tony Luck --- arch/ia64/include/asm/unistd.h | 2 +- arch/ia64/include/uapi/asm/unistd.h | 1 + arch/ia64/kernel/entry.S | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/ia64/include/asm/unistd.h b/arch/ia64/include/asm/unistd.h index ae763d8bf55a..fb13dc5e8f8c 100644 --- a/arch/ia64/include/asm/unistd.h +++ b/arch/ia64/include/asm/unistd.h @@ -11,7 +11,7 @@ -#define NR_syscalls 314 /* length of syscall table */ +#define NR_syscalls 315 /* length of syscall table */ /* * The following defines stop scripts/checksyscalls.sh from complaining about diff --git a/arch/ia64/include/uapi/asm/unistd.h b/arch/ia64/include/uapi/asm/unistd.h index 715e85f858de..7de0a2d65da4 100644 --- a/arch/ia64/include/uapi/asm/unistd.h +++ b/arch/ia64/include/uapi/asm/unistd.h @@ -327,5 +327,6 @@ #define __NR_finit_module 1335 #define __NR_sched_setattr 1336 #define __NR_sched_getattr 1337 +#define __NR_renameat2 1338 #endif /* _UAPI_ASM_IA64_UNISTD_H */ diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index fa8d61a312a7..ba3d03503e84 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S @@ -1775,6 +1775,7 @@ sys_call_table: data8 sys_finit_module // 1335 data8 sys_sched_setattr data8 sys_sched_getattr + data8 sys_renameat2 .org sys_call_table + 8*NR_syscalls // guard against failures to increase NR_syscalls #endif /* __IA64_ASM_PARAVIRTUALIZED_NATIVE */ -- cgit v1.2.3 From 63ba600028a001fa19f427486527387f54926d61 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Wed, 23 Apr 2014 11:08:05 +0100 Subject: asm-generic: Add renameat2 syscall Add the renameat2 syscall to the generic syscall list, which is used by the following architectures: arc, arm64, c6x, hexagon, metag, openrisc, score, tile, unicore32. Signed-off-by: James Hogan Acked-by: Arnd Bergmann Signed-off-by: Miklos Szeredi Cc: linux-arch@vger.kernel.org Cc: Vineet Gupta Cc: Catalin Marinas Cc: Will Deacon Cc: linux-arm-kernel@lists.infradead.org Cc: Mark Salter Cc: Aurelien Jacquiot Cc: Richard Kuo Cc: linux-hexagon@vger.kernel.org Cc: linux-metag@vger.kernel.org Cc: Jonas Bonn Cc: Chen Liqin Cc: Lennox Wu Cc: Chris Metcalf Cc: Guan Xuetao --- include/uapi/asm-generic/unistd.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h index 6db66783d268..333640608087 100644 --- a/include/uapi/asm-generic/unistd.h +++ b/include/uapi/asm-generic/unistd.h @@ -697,9 +697,11 @@ __SYSCALL(__NR_finit_module, sys_finit_module) __SYSCALL(__NR_sched_setattr, sys_sched_setattr) #define __NR_sched_getattr 275 __SYSCALL(__NR_sched_getattr, sys_sched_getattr) +#define __NR_renameat2 276 +__SYSCALL(__NR_renameat2, sys_renameat2) #undef __NR_syscalls -#define __NR_syscalls 276 +#define __NR_syscalls 277 /* * All syscalls below here should go away really, -- cgit v1.2.3 From 68b7752462aba4716d9236b28aaa91b48fe059cd Mon Sep 17 00:00:00 2001 From: James Hogan Date: Wed, 23 Apr 2014 11:08:06 +0100 Subject: scripts/checksyscalls.sh: Make renameat optional The new renameat2 syscall provides all the functionality of renameat with an additional flags argument, so make renameat optional so that future architectures can omit it without getting a warning. This patch doesn't affect existing architectures. Signed-off-by: James Hogan Acked-by: Arnd Bergmann Signed-off-by: Miklos Szeredi Cc: linux-arch@vger.kernel.org --- scripts/checksyscalls.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/scripts/checksyscalls.sh b/scripts/checksyscalls.sh index fd8fa9aa7c4e..5b3add31f9f1 100755 --- a/scripts/checksyscalls.sh +++ b/scripts/checksyscalls.sh @@ -25,7 +25,7 @@ cat << EOF #define __IGNORE_rmdir /* unlinkat */ #define __IGNORE_lchown /* fchownat */ #define __IGNORE_access /* faccessat */ -#define __IGNORE_rename /* renameat */ +#define __IGNORE_rename /* renameat2 */ #define __IGNORE_readlink /* readlinkat */ #define __IGNORE_symlink /* symlinkat */ #define __IGNORE_utimes /* futimesat */ @@ -37,6 +37,9 @@ cat << EOF #define __IGNORE_lstat64 /* fstatat64 */ #endif +/* Missing flags argument */ +#define __IGNORE_renameat /* renameat2 */ + /* CLOEXEC flag */ #define __IGNORE_pipe /* pipe2 */ #define __IGNORE_dup2 /* dup3 */ -- cgit v1.2.3 From 544092596e8ac269f70e70961b5e9381909c9b1e Mon Sep 17 00:00:00 2001 From: Christian König Date: Mon, 5 May 2014 18:40:12 +0200 Subject: drm/radeon: also try GART for CPU accessed buffers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Placing them exclusively into VRAM might not work all the time. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=78297 Signed-off-by: Christian König Reviewed-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/radeon_object.c | 38 ++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 19bec0dbfa38..72705fb40d55 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -699,22 +699,30 @@ int radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo) rbo = container_of(bo, struct radeon_bo, tbo); radeon_bo_check_tiling(rbo, 0, 0); rdev = rbo->rdev; - if (bo->mem.mem_type == TTM_PL_VRAM) { - size = bo->mem.num_pages << PAGE_SHIFT; - offset = bo->mem.start << PAGE_SHIFT; - if ((offset + size) > rdev->mc.visible_vram_size) { - /* hurrah the memory is not visible ! */ - radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_VRAM); - rbo->placement.lpfn = rdev->mc.visible_vram_size >> PAGE_SHIFT; - r = ttm_bo_validate(bo, &rbo->placement, false, false); - if (unlikely(r != 0)) - return r; - offset = bo->mem.start << PAGE_SHIFT; - /* this should not happen */ - if ((offset + size) > rdev->mc.visible_vram_size) - return -EINVAL; - } + if (bo->mem.mem_type != TTM_PL_VRAM) + return 0; + + size = bo->mem.num_pages << PAGE_SHIFT; + offset = bo->mem.start << PAGE_SHIFT; + if ((offset + size) <= rdev->mc.visible_vram_size) + return 0; + + /* hurrah the memory is not visible ! */ + radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_VRAM); + rbo->placement.lpfn = rdev->mc.visible_vram_size >> PAGE_SHIFT; + r = ttm_bo_validate(bo, &rbo->placement, false, false); + if (unlikely(r == -ENOMEM)) { + radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_GTT); + return ttm_bo_validate(bo, &rbo->placement, false, false); + } else if (unlikely(r != 0)) { + return r; } + + offset = bo->mem.start << PAGE_SHIFT; + /* this should never happen */ + if ((offset + size) > rdev->mc.visible_vram_size) + return -EINVAL; + return 0; } -- cgit v1.2.3 From 2fc5703abda201f138faf63bdca743d04dbf4b1a Mon Sep 17 00:00:00 2001 From: Leo Liu Date: Mon, 5 May 2014 15:42:18 -0400 Subject: drm/radeon: check VCE relocation buffer range v3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v2 (chk): fix image size storage v3 (chk): fix UV size calculation Signed-off-by: Leo Liu Signed-off-by: Christian König --- drivers/gpu/drm/radeon/radeon.h | 3 +- drivers/gpu/drm/radeon/radeon_vce.c | 130 +++++++++++++++++++++++++++--------- 2 files changed, 102 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 68528619834a..91be3d6eb845 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -1642,6 +1642,7 @@ struct radeon_vce { unsigned fb_version; atomic_t handles[RADEON_MAX_VCE_HANDLES]; struct drm_file *filp[RADEON_MAX_VCE_HANDLES]; + unsigned img_size[RADEON_MAX_VCE_HANDLES]; struct delayed_work idle_work; }; @@ -1655,7 +1656,7 @@ int radeon_vce_get_destroy_msg(struct radeon_device *rdev, int ring, uint32_t handle, struct radeon_fence **fence); void radeon_vce_free_handles(struct radeon_device *rdev, struct drm_file *filp); void radeon_vce_note_usage(struct radeon_device *rdev); -int radeon_vce_cs_reloc(struct radeon_cs_parser *p, int lo, int hi); +int radeon_vce_cs_reloc(struct radeon_cs_parser *p, int lo, int hi, unsigned size); int radeon_vce_cs_parse(struct radeon_cs_parser *p); bool radeon_vce_semaphore_emit(struct radeon_device *rdev, struct radeon_ring *ring, diff --git a/drivers/gpu/drm/radeon/radeon_vce.c b/drivers/gpu/drm/radeon/radeon_vce.c index f73324c81491..3971d968af6c 100644 --- a/drivers/gpu/drm/radeon/radeon_vce.c +++ b/drivers/gpu/drm/radeon/radeon_vce.c @@ -443,13 +443,16 @@ int radeon_vce_get_destroy_msg(struct radeon_device *rdev, int ring, * @p: parser context * @lo: address of lower dword * @hi: address of higher dword + * @size: size of checker for relocation buffer * * Patch relocation inside command stream with real buffer address */ -int radeon_vce_cs_reloc(struct radeon_cs_parser *p, int lo, int hi) +int radeon_vce_cs_reloc(struct radeon_cs_parser *p, int lo, int hi, + unsigned size) { struct radeon_cs_chunk *relocs_chunk; - uint64_t offset; + struct radeon_cs_reloc *reloc; + uint64_t start, end, offset; unsigned idx; relocs_chunk = &p->chunks[p->chunk_relocs_idx]; @@ -462,14 +465,59 @@ int radeon_vce_cs_reloc(struct radeon_cs_parser *p, int lo, int hi) return -EINVAL; } - offset += p->relocs_ptr[(idx / 4)]->gpu_offset; + reloc = p->relocs_ptr[(idx / 4)]; + start = reloc->gpu_offset; + end = start + radeon_bo_size(reloc->robj); + start += offset; - p->ib.ptr[lo] = offset & 0xFFFFFFFF; - p->ib.ptr[hi] = offset >> 32; + p->ib.ptr[lo] = start & 0xFFFFFFFF; + p->ib.ptr[hi] = start >> 32; + + if (end <= start) { + DRM_ERROR("invalid reloc offset %llX!\n", offset); + return -EINVAL; + } + if ((end - start) < size) { + DRM_ERROR("buffer to small (%d / %d)!\n", + (unsigned)(end - start), size); + return -EINVAL; + } return 0; } +/** + * radeon_vce_validate_handle - validate stream handle + * + * @p: parser context + * @handle: handle to validate + * + * Validates the handle and return the found session index or -EINVAL + * we we don't have another free session index. + */ +int radeon_vce_validate_handle(struct radeon_cs_parser *p, uint32_t handle) +{ + unsigned i; + + /* validate the handle */ + for (i = 0; i < RADEON_MAX_VCE_HANDLES; ++i) { + if (atomic_read(&p->rdev->vce.handles[i]) == handle) + return i; + } + + /* handle not found try to alloc a new one */ + for (i = 0; i < RADEON_MAX_VCE_HANDLES; ++i) { + if (!atomic_cmpxchg(&p->rdev->vce.handles[i], 0, handle)) { + p->rdev->vce.filp[i] = p->filp; + p->rdev->vce.img_size[i] = 0; + return i; + } + } + + DRM_ERROR("No more free VCE handles!\n"); + return -EINVAL; +} + /** * radeon_vce_cs_parse - parse and validate the command stream * @@ -478,8 +526,10 @@ int radeon_vce_cs_reloc(struct radeon_cs_parser *p, int lo, int hi) */ int radeon_vce_cs_parse(struct radeon_cs_parser *p) { - uint32_t handle = 0; - bool destroy = false; + int session_idx = -1; + bool destroyed = false; + uint32_t tmp, handle = 0; + uint32_t *size = &tmp; int i, r; while (p->idx < p->chunks[p->chunk_ib_idx].length_dw) { @@ -491,13 +541,29 @@ int radeon_vce_cs_parse(struct radeon_cs_parser *p) return -EINVAL; } + if (destroyed) { + DRM_ERROR("No other command allowed after destroy!\n"); + return -EINVAL; + } + switch (cmd) { case 0x00000001: // session handle = radeon_get_ib_value(p, p->idx + 2); + session_idx = radeon_vce_validate_handle(p, handle); + if (session_idx < 0) + return session_idx; + size = &p->rdev->vce.img_size[session_idx]; break; case 0x00000002: // task info + break; + case 0x01000001: // create + *size = radeon_get_ib_value(p, p->idx + 8) * + radeon_get_ib_value(p, p->idx + 10) * + 8 * 3 / 2; + break; + case 0x04000001: // config extension case 0x04000002: // pic control case 0x04000005: // rate control @@ -506,23 +572,39 @@ int radeon_vce_cs_parse(struct radeon_cs_parser *p) break; case 0x03000001: // encode - r = radeon_vce_cs_reloc(p, p->idx + 10, p->idx + 9); + r = radeon_vce_cs_reloc(p, p->idx + 10, p->idx + 9, + *size); if (r) return r; - r = radeon_vce_cs_reloc(p, p->idx + 12, p->idx + 11); + r = radeon_vce_cs_reloc(p, p->idx + 12, p->idx + 11, + *size / 3); if (r) return r; break; case 0x02000001: // destroy - destroy = true; + destroyed = true; break; case 0x05000001: // context buffer + r = radeon_vce_cs_reloc(p, p->idx + 3, p->idx + 2, + *size * 2); + if (r) + return r; + break; + case 0x05000004: // video bitstream buffer + tmp = radeon_get_ib_value(p, p->idx + 4); + r = radeon_vce_cs_reloc(p, p->idx + 3, p->idx + 2, + tmp); + if (r) + return r; + break; + case 0x05000005: // feedback buffer - r = radeon_vce_cs_reloc(p, p->idx + 3, p->idx + 2); + r = radeon_vce_cs_reloc(p, p->idx + 3, p->idx + 2, + 4096); if (r) return r; break; @@ -532,33 +614,21 @@ int radeon_vce_cs_parse(struct radeon_cs_parser *p) return -EINVAL; } + if (session_idx == -1) { + DRM_ERROR("no session command at start of IB\n"); + return -EINVAL; + } + p->idx += len / 4; } - if (destroy) { + if (destroyed) { /* IB contains a destroy msg, free the handle */ for (i = 0; i < RADEON_MAX_VCE_HANDLES; ++i) atomic_cmpxchg(&p->rdev->vce.handles[i], handle, 0); - - return 0; - } - - /* create or encode, validate the handle */ - for (i = 0; i < RADEON_MAX_VCE_HANDLES; ++i) { - if (atomic_read(&p->rdev->vce.handles[i]) == handle) - return 0; } - /* handle not found try to alloc a new one */ - for (i = 0; i < RADEON_MAX_VCE_HANDLES; ++i) { - if (!atomic_cmpxchg(&p->rdev->vce.handles[i], 0, handle)) { - p->rdev->vce.filp[i] = p->filp; - return 0; - } - } - - DRM_ERROR("No more free VCE handles!\n"); - return -EINVAL; + return 0; } /** -- cgit v1.2.3 From 89d2618dbd114e679b860c3de1df3fe43ee40f6e Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 8 May 2014 18:26:23 -0400 Subject: drm/radeon: fix DCE83 check for mullins MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mullins is DCE83 just like Kabini. Set the proper number of endpoints on mullins. Signed-off-by: Alex Deucher Signed-off-by: Christian König --- drivers/gpu/drm/radeon/radeon.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 91be3d6eb845..8149e7cf4303 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -2641,7 +2641,8 @@ void r100_pll_errata_after_index(struct radeon_device *rdev); #define ASIC_IS_DCE8(rdev) ((rdev->family >= CHIP_BONAIRE)) #define ASIC_IS_DCE81(rdev) ((rdev->family == CHIP_KAVERI)) #define ASIC_IS_DCE82(rdev) ((rdev->family == CHIP_BONAIRE)) -#define ASIC_IS_DCE83(rdev) ((rdev->family == CHIP_KABINI)) +#define ASIC_IS_DCE83(rdev) ((rdev->family == CHIP_KABINI) || \ + (rdev->family == CHIP_MULLINS)) #define ASIC_IS_LOMBOK(rdev) ((rdev->ddev->pdev->device == 0x6849) || \ (rdev->ddev->pdev->device == 0x6850) || \ -- cgit v1.2.3 From d8ade3526b2aa0505132c404c05a38b73ea15490 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 8 May 2014 20:04:03 -0400 Subject: drm/radeon: handle non-VGA class pci devices with ATRM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Newer PX systems have non-VGA pci class dGPUs. Update the ATRM fetch method to handle those cases. bug: https://bugzilla.kernel.org/show_bug.cgi?id=75401 Signed-off-by: Alex Deucher Signed-off-by: Christian König Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/radeon_bios.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c index b3633d9a5317..9ab30976287d 100644 --- a/drivers/gpu/drm/radeon/radeon_bios.c +++ b/drivers/gpu/drm/radeon/radeon_bios.c @@ -196,6 +196,20 @@ static bool radeon_atrm_get_bios(struct radeon_device *rdev) } } + if (!found) { + while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_OTHER << 8, pdev)) != NULL) { + dhandle = ACPI_HANDLE(&pdev->dev); + if (!dhandle) + continue; + + status = acpi_get_handle(dhandle, "ATRM", &atrm_handle); + if (!ACPI_FAILURE(status)) { + found = true; + break; + } + } + } + if (!found) return false; -- cgit v1.2.3 From 4906f6891ef987637b766dfaef1c6fc95804253a Mon Sep 17 00:00:00 2001 From: Christian König Date: Mon, 12 May 2014 14:46:11 +0200 Subject: drm/radeon: fix page directory update size estimation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Take padding into account as well. Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=75651 Signed-off-by: Christian König Reviewed-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_vm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_vm.c b/drivers/gpu/drm/radeon/radeon_vm.c index 2aae6ce49d32..d9ab99f47612 100644 --- a/drivers/gpu/drm/radeon/radeon_vm.c +++ b/drivers/gpu/drm/radeon/radeon_vm.c @@ -595,7 +595,7 @@ int radeon_vm_update_page_directory(struct radeon_device *rdev, ndw = 64; /* assume the worst case */ - ndw += vm->max_pde_used * 12; + ndw += vm->max_pde_used * 16; /* update too big for an IB */ if (ndw > 0xfffff) -- cgit v1.2.3 From 4b09556660bfe1b43d72ca858524c6baf2c6cb1d Mon Sep 17 00:00:00 2001 From: Christian König Date: Sat, 10 May 2014 18:17:09 +0200 Subject: drm/radeon: fix buffer placement under memory pressure v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some buffers (UVD/VM page tables) must be placed in VRAM, but the byte restriction for moving buffers didn't took this into account. v2: keep closer to the original code Signed-off-by: Christian König Reviewed-by: Alex Deucher Reviewed-by: Marek Olšák --- drivers/gpu/drm/radeon/radeon_object.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 72705fb40d55..4faa4d6f9bb4 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -458,7 +458,7 @@ int radeon_bo_list_validate(struct radeon_device *rdev, * into account. We don't want to disallow buffer moves * completely. */ - if (current_domain != RADEON_GEM_DOMAIN_CPU && + if ((lobj->alt_domain & current_domain) != 0 && (domain & current_domain) == 0 && /* will be moved */ bytes_moved > bytes_moved_threshold) { /* don't move it */ -- cgit v1.2.3 From 4955bb073f1be6dd884b5d10041ba4bade6495bf Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 5 May 2014 16:40:42 -0400 Subject: drm/radeon: fix register typo on si MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Probably a copy paste typo. Signed-off-by: Alex Deucher Signed-off-by: Christian König Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/sid.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h index 683532f84931..7321283602ce 100644 --- a/drivers/gpu/drm/radeon/sid.h +++ b/drivers/gpu/drm/radeon/sid.h @@ -107,8 +107,8 @@ #define SPLL_CHG_STATUS (1 << 1) #define SPLL_CNTL_MODE 0x618 #define SPLL_SW_DIR_CONTROL (1 << 0) -# define SPLL_REFCLK_SEL(x) ((x) << 8) -# define SPLL_REFCLK_SEL_MASK 0xFF00 +# define SPLL_REFCLK_SEL(x) ((x) << 26) +# define SPLL_REFCLK_SEL_MASK (3 << 26) #define CG_SPLL_SPREAD_SPECTRUM 0x620 #define SSEN (1 << 0) -- cgit v1.2.3 From 74ad54f249de39bc040cce7237b1b854a9c6f0ad Mon Sep 17 00:00:00 2001 From: Christian König Date: Tue, 13 May 2014 12:50:54 +0200 Subject: drm/radeon: fix typo in finding PLL params MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwise the limit is raised to high. Signed-off-by: Christian König Tested-by: Ken Moffat --- drivers/gpu/drm/radeon/radeon_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 408b6ac53f0b..f00dbbf4d806 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -999,7 +999,7 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll, /* avoid high jitter with small fractional dividers */ if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV && (fb_div % 10)) { - fb_div_min = max(fb_div_min, (9 - (fb_div % 10)) * 20 + 60); + fb_div_min = max(fb_div_min, (9 - (fb_div % 10)) * 20 + 50); if (fb_div < fb_div_min) { unsigned tmp = DIV_ROUND_UP(fb_div_min, fb_div); fb_div *= tmp; -- cgit v1.2.3 From 24f47acc78b0ab5e2201f859fe1f693ae90c7c83 Mon Sep 17 00:00:00 2001 From: Jérôme Glisse Date: Wed, 7 May 2014 16:35:24 -0400 Subject: drm/radeon: avoid segfault on device open when accel is not working. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When accel is not working on device with virtual address space radeon segfault because the ib buffer is NULL and trying to map it inside the virtual address space trigger segfault. This patch only map the ib buffer if accel is working. Cc: Signed-off-by: Jérôme Glisse Reviewed-by: Alex Deucher Signed-off-by: Christian König --- drivers/gpu/drm/radeon/radeon_kms.c | 55 +++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index 0cc47f12d995..eaaedba04675 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -577,28 +577,29 @@ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) return r; } - r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false); - if (r) { - radeon_vm_fini(rdev, &fpriv->vm); - kfree(fpriv); - return r; - } + if (rdev->accel_working) { + r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false); + if (r) { + radeon_vm_fini(rdev, &fpriv->vm); + kfree(fpriv); + return r; + } - /* map the ib pool buffer read only into - * virtual address space */ - bo_va = radeon_vm_bo_add(rdev, &fpriv->vm, - rdev->ring_tmp_bo.bo); - r = radeon_vm_bo_set_addr(rdev, bo_va, RADEON_VA_IB_OFFSET, - RADEON_VM_PAGE_READABLE | - RADEON_VM_PAGE_SNOOPED); + /* map the ib pool buffer read only into + * virtual address space */ + bo_va = radeon_vm_bo_add(rdev, &fpriv->vm, + rdev->ring_tmp_bo.bo); + r = radeon_vm_bo_set_addr(rdev, bo_va, RADEON_VA_IB_OFFSET, + RADEON_VM_PAGE_READABLE | + RADEON_VM_PAGE_SNOOPED); - radeon_bo_unreserve(rdev->ring_tmp_bo.bo); - if (r) { - radeon_vm_fini(rdev, &fpriv->vm); - kfree(fpriv); - return r; + radeon_bo_unreserve(rdev->ring_tmp_bo.bo); + if (r) { + radeon_vm_fini(rdev, &fpriv->vm); + kfree(fpriv); + return r; + } } - file_priv->driver_priv = fpriv; } @@ -626,13 +627,15 @@ void radeon_driver_postclose_kms(struct drm_device *dev, struct radeon_bo_va *bo_va; int r; - r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false); - if (!r) { - bo_va = radeon_vm_bo_find(&fpriv->vm, - rdev->ring_tmp_bo.bo); - if (bo_va) - radeon_vm_bo_rmv(rdev, bo_va); - radeon_bo_unreserve(rdev->ring_tmp_bo.bo); + if (rdev->accel_working) { + r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false); + if (!r) { + bo_va = radeon_vm_bo_find(&fpriv->vm, + rdev->ring_tmp_bo.bo); + if (bo_va) + radeon_vm_bo_rmv(rdev, bo_va); + radeon_bo_unreserve(rdev->ring_tmp_bo.bo); + } } radeon_vm_fini(rdev, &fpriv->vm); -- cgit v1.2.3 From 4f2f203976964e267dc477de6648bdb3acd2b74b Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 19 May 2014 19:21:29 -0400 Subject: drm/radeon/pm: don't allow debugfs/sysfs access when PX card is off (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the PX card is off don't try and access it. Avoid hw access to the card while it's off (e.g., reading back invalid temperature). v2: be less strict bug: https://bugzilla.kernel.org/show_bug.cgi?id=76321 Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org Signed-off-by: Christian König --- drivers/gpu/drm/radeon/radeon_pm.c | 42 +++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index f30b8426eee2..53d6e1bb48dc 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -361,6 +361,11 @@ static ssize_t radeon_set_pm_profile(struct device *dev, struct drm_device *ddev = dev_get_drvdata(dev); struct radeon_device *rdev = ddev->dev_private; + /* Can't set profile when the card is off */ + if ((rdev->flags & RADEON_IS_PX) && + (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) + return -EINVAL; + mutex_lock(&rdev->pm.mutex); if (rdev->pm.pm_method == PM_METHOD_PROFILE) { if (strncmp("default", buf, strlen("default")) == 0) @@ -409,6 +414,13 @@ static ssize_t radeon_set_pm_method(struct device *dev, struct drm_device *ddev = dev_get_drvdata(dev); struct radeon_device *rdev = ddev->dev_private; + /* Can't set method when the card is off */ + if ((rdev->flags & RADEON_IS_PX) && + (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) { + count = -EINVAL; + goto fail; + } + /* we don't support the legacy modes with dpm */ if (rdev->pm.pm_method == PM_METHOD_DPM) { count = -EINVAL; @@ -446,6 +458,10 @@ static ssize_t radeon_get_dpm_state(struct device *dev, struct radeon_device *rdev = ddev->dev_private; enum radeon_pm_state_type pm = rdev->pm.dpm.user_state; + if ((rdev->flags & RADEON_IS_PX) && + (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) + return snprintf(buf, PAGE_SIZE, "off\n"); + return snprintf(buf, PAGE_SIZE, "%s\n", (pm == POWER_STATE_TYPE_BATTERY) ? "battery" : (pm == POWER_STATE_TYPE_BALANCED) ? "balanced" : "performance"); @@ -459,6 +475,11 @@ static ssize_t radeon_set_dpm_state(struct device *dev, struct drm_device *ddev = dev_get_drvdata(dev); struct radeon_device *rdev = ddev->dev_private; + /* Can't set dpm state when the card is off */ + if ((rdev->flags & RADEON_IS_PX) && + (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) + return -EINVAL; + mutex_lock(&rdev->pm.mutex); if (strncmp("battery", buf, strlen("battery")) == 0) rdev->pm.dpm.user_state = POWER_STATE_TYPE_BATTERY; @@ -485,6 +506,10 @@ static ssize_t radeon_get_dpm_forced_performance_level(struct device *dev, struct radeon_device *rdev = ddev->dev_private; enum radeon_dpm_forced_level level = rdev->pm.dpm.forced_level; + if ((rdev->flags & RADEON_IS_PX) && + (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) + return snprintf(buf, PAGE_SIZE, "off\n"); + return snprintf(buf, PAGE_SIZE, "%s\n", (level == RADEON_DPM_FORCED_LEVEL_AUTO) ? "auto" : (level == RADEON_DPM_FORCED_LEVEL_LOW) ? "low" : "high"); @@ -500,6 +525,11 @@ static ssize_t radeon_set_dpm_forced_performance_level(struct device *dev, enum radeon_dpm_forced_level level; int ret = 0; + /* Can't force performance level when the card is off */ + if ((rdev->flags & RADEON_IS_PX) && + (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) + return -EINVAL; + mutex_lock(&rdev->pm.mutex); if (strncmp("low", buf, strlen("low")) == 0) { level = RADEON_DPM_FORCED_LEVEL_LOW; @@ -538,8 +568,14 @@ static ssize_t radeon_hwmon_show_temp(struct device *dev, char *buf) { struct radeon_device *rdev = dev_get_drvdata(dev); + struct drm_device *ddev = rdev->ddev; int temp; + /* Can't get temperature when the card is off */ + if ((rdev->flags & RADEON_IS_PX) && + (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) + return -EINVAL; + if (rdev->asic->pm.get_temperature) temp = radeon_get_temperature(rdev); else @@ -1614,8 +1650,12 @@ static int radeon_debugfs_pm_info(struct seq_file *m, void *data) struct drm_info_node *node = (struct drm_info_node *) m->private; struct drm_device *dev = node->minor->dev; struct radeon_device *rdev = dev->dev_private; + struct drm_device *ddev = rdev->ddev; - if (rdev->pm.dpm_enabled) { + if ((rdev->flags & RADEON_IS_PX) && + (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) { + seq_printf(m, "PX asic powered off\n"); + } else if (rdev->pm.dpm_enabled) { mutex_lock(&rdev->pm.mutex); if (rdev->asic->dpm.debugfs_print_current_performance_level) radeon_dpm_debugfs_print_current_performance_level(rdev, m); -- cgit v1.2.3 From e1618d461ca18d40f9c3ef70598abb72e75d27ae Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Tue, 20 May 2014 10:59:26 -0400 Subject: vlan: Fix build error wth vlan_get_encap_level() The new function vlan_get_encap_level() uses vlan_dev_priv() which is only conditionally avaialble when VLAN support is enabled. Make vlan_get_encap_level() conditionally available as well. Fixes: 44a4085538c8 ("bonding: Fix stacked device detection in arp monitoring") Reported-by: Stephen Rothwell CC: Stephen Rothwell Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- include/linux/if_vlan.h | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h index c901b13b6f03..b2acc4a1b13c 100644 --- a/include/linux/if_vlan.h +++ b/include/linux/if_vlan.h @@ -198,6 +198,12 @@ extern void vlan_vids_del_by_dev(struct net_device *dev, const struct net_device *by_dev); extern bool vlan_uses_dev(const struct net_device *dev); + +static inline int vlan_get_encap_level(struct net_device *dev) +{ + BUG_ON(!is_vlan_dev(dev)); + return vlan_dev_priv(dev)->nest_level; +} #else static inline struct net_device * __vlan_find_dev_deep(struct net_device *real_dev, @@ -264,6 +270,11 @@ static inline bool vlan_uses_dev(const struct net_device *dev) { return false; } +static inline int vlan_get_encap_level(struct net_device *dev) +{ + BUG(); + return 0; +} #endif static inline bool vlan_hw_offload_capable(netdev_features_t features, @@ -485,9 +496,4 @@ static inline void vlan_set_encap_proto(struct sk_buff *skb, skb->protocol = htons(ETH_P_802_2); } -static inline int vlan_get_encap_level(struct net_device *dev) -{ - BUG_ON(!is_vlan_dev(dev)); - return vlan_dev_priv(dev)->nest_level; -} #endif /* !(_LINUX_IF_VLAN_H_) */ -- cgit v1.2.3 From d3ecfcdf9108c833e4e501bfa02ecf673a0ace59 Mon Sep 17 00:00:00 2001 From: Liu Bo Date: Fri, 9 May 2014 10:01:02 +0800 Subject: Btrfs: fix EIO on reading file after ioctl clone works on it For inline data extent, we need to make its length aligned, otherwise, we can get a phantom extent map which confuses readpages() to return -EIO. This can be detected by xfstests/btrfs/035. Reported-by: David Disseldorp Signed-off-by: Liu Bo Signed-off-by: Chris Mason --- fs/btrfs/ioctl.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 7b001abc73c7..e1b47ef380d6 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -3142,6 +3142,8 @@ process_slot: } else if (type == BTRFS_FILE_EXTENT_INLINE) { u64 skip = 0; u64 trim = 0; + u64 aligned_end = 0; + if (off > key.offset) { skip = off - key.offset; new_key.offset += skip; @@ -3158,9 +3160,11 @@ process_slot: size -= skip + trim; datal -= skip + trim; + aligned_end = ALIGN(new_key.offset + datal, + root->sectorsize); ret = btrfs_drop_extents(trans, root, inode, new_key.offset, - new_key.offset + datal, + aligned_end, 1); if (ret) { if (ret != -EOPNOTSUPP) -- cgit v1.2.3 From 51a60253a58514524b7a347c4e68553821a79d04 Mon Sep 17 00:00:00 2001 From: Filipe Manana Date: Tue, 13 May 2014 22:01:02 +0100 Subject: Btrfs: send, fix incorrect ref access when using extrefs When running send, if an inode only has extended reference items associated to it and no regular references, send.c:get_first_ref() was incorrectly assuming the reference it found was of type BTRFS_INODE_REF_KEY due to use of the wrong key variable. This caused weird behaviour when using the found item has a regular reference, such as weird path string, and occasionally (when lucky) a crash: [ 190.600652] general protection fault: 0000 [#1] SMP DEBUG_PAGEALLOC [ 190.600994] Modules linked in: btrfs xor raid6_pq binfmt_misc nfsd auth_rpcgss oid_registry nfs_acl nfs lockd fscache sunrpc psmouse serio_raw evbug pcspkr i2c_piix4 e1000 floppy [ 190.602565] CPU: 2 PID: 14520 Comm: btrfs Not tainted 3.13.0-fdm-btrfs-next-26+ #1 [ 190.602728] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011 [ 190.602868] task: ffff8800d447c920 ti: ffff8801fa79e000 task.ti: ffff8801fa79e000 [ 190.603030] RIP: 0010:[] [] memcpy+0x54/0x110 [ 190.603262] RSP: 0018:ffff8801fa79f880 EFLAGS: 00010202 [ 190.603395] RAX: ffff8800d4326e3f RBX: 000000000000036a RCX: ffff880000000000 [ 190.603553] RDX: 000000000000032a RSI: ffe708844042936a RDI: ffff8800d43271a9 [ 190.603710] RBP: ffff8801fa79f8c8 R08: 00000000003a4ef0 R09: 0000000000000000 [ 190.603867] R10: 793a4ef09f000000 R11: 9f0000000053726f R12: ffff8800d43271a9 [ 190.604020] R13: 0000160000000000 R14: ffff8802110134f0 R15: 000000000000036a [ 190.604020] FS: 00007fb423d09b80(0000) GS:ffff880216200000(0000) knlGS:0000000000000000 [ 190.604020] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b [ 190.604020] CR2: 00007fb4229d4b78 CR3: 00000001f5d76000 CR4: 00000000000006e0 [ 190.604020] Stack: [ 190.604020] ffffffffa01f4d49 ffff8801fa79f8f0 00000000000009f9 ffff8801fa79f8c8 [ 190.604020] 00000000000009f9 ffff880211013260 000000000000f971 ffff88021147dba8 [ 190.604020] 00000000000009f9 ffff8801fa79f918 ffffffffa02367f5 ffff8801fa79f928 [ 190.604020] Call Trace: [ 190.604020] [] ? read_extent_buffer+0xb9/0x120 [btrfs] [ 190.604020] [] fs_path_add_from_extent_buffer+0x45/0x60 [btrfs] [ 190.604020] [] get_first_ref+0x1f6/0x210 [btrfs] [ 190.604020] [] __get_cur_name_and_parent+0x174/0x3a0 [btrfs] [ 190.604020] [] ? kmem_cache_alloc_trace+0x11d/0x1e0 [ 190.604020] [] ? fs_path_alloc+0x24/0x60 [btrfs] [ 190.604020] [] get_cur_path+0xd1/0x240 [btrfs] (...) Steps to reproduce (either crash or some weirdness like an odd path string): mkfs.btrfs -f -O extref /dev/sdd mount /dev/sdd /mnt mkdir /mnt/testdir touch /mnt/testdir/foobar for i in `seq 1 2550`; do ln /mnt/testdir/foobar /mnt/testdir/foobar_link_`printf "%04d" $i` done ln /mnt/testdir/foobar /mnt/testdir/final_foobar_name rm -f /mnt/testdir/foobar for i in `seq 1 2550`; do rm -f /mnt/testdir/foobar_link_`printf "%04d" $i` done btrfs subvolume snapshot -r /mnt /mnt/mysnap btrfs send /mnt/mysnap -f /tmp/mysnap.send Signed-off-by: Filipe David Borba Manana Signed-off-by: Chris Mason Reviewed-by: Liu Bo --- fs/btrfs/send.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index eb6537a08c1b..fd38b5053479 100644 --- a/fs/btrfs/send.c +++ b/fs/btrfs/send.c @@ -1668,7 +1668,7 @@ static int get_first_ref(struct btrfs_root *root, u64 ino, goto out; } - if (key.type == BTRFS_INODE_REF_KEY) { + if (found_key.type == BTRFS_INODE_REF_KEY) { struct btrfs_inode_ref *iref; iref = btrfs_item_ptr(path->nodes[0], path->slots[0], struct btrfs_inode_ref); -- cgit v1.2.3 From 80c578930ce77ba8bcfb226a184b482020bdda7b Mon Sep 17 00:00:00 2001 From: Mike Snitzer Date: Tue, 20 May 2014 13:38:33 -0400 Subject: dm thin: add 'no_space_timeout' dm-thin-pool module param Commit 85ad643b ("dm thin: add timeout to stop out-of-data-space mode holding IO forever") introduced a fixed 60 second timeout. Users may want to either disable or modify this timeout. Allow the out-of-data-space timeout to be configured using the 'no_space_timeout' dm-thin-pool module param. Setting it to 0 will disable the timeout, resulting in IO being queued until more data space is added to the thin-pool. Signed-off-by: Mike Snitzer Cc: stable@vger.kernel.org # 3.14+ --- Documentation/device-mapper/thin-provisioning.txt | 5 ++++- drivers/md/dm-thin.c | 12 +++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/Documentation/device-mapper/thin-provisioning.txt b/Documentation/device-mapper/thin-provisioning.txt index 05a27e9442bd..2f5173500bd9 100644 --- a/Documentation/device-mapper/thin-provisioning.txt +++ b/Documentation/device-mapper/thin-provisioning.txt @@ -309,7 +309,10 @@ ii) Status error_if_no_space|queue_if_no_space If the pool runs out of data or metadata space, the pool will either queue or error the IO destined to the data device. The - default is to queue the IO until more space is added. + default is to queue the IO until more space is added or the + 'no_space_timeout' expires. The 'no_space_timeout' dm-thin-pool + module parameter can be used to change this timeout -- it + defaults to 60 seconds but may be disabled using a value of 0. iii) Messages diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index 2e71de8e0048..242ac2ea5f29 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c @@ -27,7 +27,9 @@ #define MAPPING_POOL_SIZE 1024 #define PRISON_CELLS 1024 #define COMMIT_PERIOD HZ -#define NO_SPACE_TIMEOUT (HZ * 60) +#define NO_SPACE_TIMEOUT_SECS 60 + +static unsigned no_space_timeout_secs = NO_SPACE_TIMEOUT_SECS; DECLARE_DM_KCOPYD_THROTTLE_WITH_MODULE_PARM(snapshot_copy_throttle, "A percentage of time allocated for copy on write"); @@ -1670,6 +1672,7 @@ static void set_pool_mode(struct pool *pool, enum pool_mode new_mode) struct pool_c *pt = pool->ti->private; bool needs_check = dm_pool_metadata_needs_check(pool->pmd); enum pool_mode old_mode = get_pool_mode(pool); + unsigned long no_space_timeout = ACCESS_ONCE(no_space_timeout_secs) * HZ; /* * Never allow the pool to transition to PM_WRITE mode if user @@ -1732,8 +1735,8 @@ static void set_pool_mode(struct pool *pool, enum pool_mode new_mode) pool->process_prepared_mapping = process_prepared_mapping; pool->process_prepared_discard = process_prepared_discard_passdown; - if (!pool->pf.error_if_no_space) - queue_delayed_work(pool->wq, &pool->no_space_timeout, NO_SPACE_TIMEOUT); + if (!pool->pf.error_if_no_space && no_space_timeout) + queue_delayed_work(pool->wq, &pool->no_space_timeout, no_space_timeout); break; case PM_WRITE: @@ -3508,6 +3511,9 @@ static void dm_thin_exit(void) module_init(dm_thin_init); module_exit(dm_thin_exit); +module_param_named(no_space_timeout, no_space_timeout_secs, uint, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(no_space_timeout, "Out of data space queue IO timeout in seconds"); + MODULE_DESCRIPTION(DM_NAME " thin provisioning target"); MODULE_AUTHOR("Joe Thornber "); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 78ff4be45a4c51d8fb21ad92e4fabb467c6c3eeb Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Mon, 19 May 2014 11:36:56 +0200 Subject: ip_tunnel: Initialize the fallback device properly We need to initialize the fallback device to have a correct mtu set on this device. Otherwise the mtu is set to null and the device is unusable. Fixes: fd58156e456d ("IPIP: Use ip-tunneling code.") Cc: Pravin B Shelar Signed-off-by: Steffen Klassert Signed-off-by: David S. Miller --- net/ipv4/ip_tunnel.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index 49721d78df75..2acc2337d38b 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c @@ -883,6 +883,7 @@ int ip_tunnel_init_net(struct net *net, int ip_tnl_net_id, */ if (!IS_ERR(itn->fb_tunnel_dev)) { itn->fb_tunnel_dev->features |= NETIF_F_NETNS_LOCAL; + itn->fb_tunnel_dev->mtu = ip_tunnel_bind_dev(itn->fb_tunnel_dev); ip_tunnel_add(itn, netdev_priv(itn->fb_tunnel_dev)); } rtnl_unlock(); -- cgit v1.2.3 From a8246fedacadaab18b23b280ea3cf916ef5fc30e Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 8 May 2014 16:56:12 +0200 Subject: dmaengine: omap: hide filter_fn for built-in drivers It is not possible to reference the omap_dma_filter_fn filter function from a built-in driver if the dmaengine driver itself is a loadable module, which is a valid configuration otherwise. This provides only the dummy alternative if the function is referenced by a built-in driver to allow a successful build. The filter function is only required by ATAGS based platforms, which will continue to be broken after this change for the bogus configuration. When booting from DT, with the dma channels correctly listed there, it will work fine. Signed-off-by: Arnd Bergmann Acked-by: Tony Lindgren Cc: Russell King Cc: Vinod Koul Cc: dmaengine@vger.kernel.org Signed-off-by: Vinod Koul --- include/linux/omap-dma.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/omap-dma.h b/include/linux/omap-dma.h index 41a13e70f41f..7944cdc27bed 100644 --- a/include/linux/omap-dma.h +++ b/include/linux/omap-dma.h @@ -10,7 +10,7 @@ struct dma_chan; -#if defined(CONFIG_DMA_OMAP) || defined(CONFIG_DMA_OMAP_MODULE) +#if defined(CONFIG_DMA_OMAP) || (defined(CONFIG_DMA_OMAP_MODULE) && defined(MODULE)) bool omap_dma_filter_fn(struct dma_chan *, void *); #else static inline bool omap_dma_filter_fn(struct dma_chan *c, void *d) -- cgit v1.2.3 From fbeb91fe8e4107dc88df4eaa21de02c3fd9d1cd5 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 8 May 2014 16:56:13 +0200 Subject: dmaengine: sa11x0: remove broken #ifdef The sa11x0_dma_pm_ops unconditionally reference sa11x0_dma_resume and sa11x0_dma_suspend, which currently breaks if CONFIG_PM_SLEEP is disabled. There is probably a better way to remove the reference in this case, but the safe choice is to have the suspend/resume code always built in the driver. Signed-off-by: Arnd Bergmann Cc: Russell King Cc: dmaengine@vger.kernel.org Cc: Vinod Koul Cc: Dan Williams Signed-off-by: Vinod Koul --- drivers/dma/sa11x0-dma.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/dma/sa11x0-dma.c b/drivers/dma/sa11x0-dma.c index ab26d46bbe15..5ebdfbc1051e 100644 --- a/drivers/dma/sa11x0-dma.c +++ b/drivers/dma/sa11x0-dma.c @@ -113,11 +113,9 @@ struct sa11x0_dma_phy { struct sa11x0_dma_desc *txd_load; unsigned sg_done; struct sa11x0_dma_desc *txd_done; -#ifdef CONFIG_PM_SLEEP u32 dbs[2]; u32 dbt[2]; u32 dcsr; -#endif }; struct sa11x0_dma_dev { @@ -984,7 +982,6 @@ static int sa11x0_dma_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM_SLEEP static int sa11x0_dma_suspend(struct device *dev) { struct sa11x0_dma_dev *d = dev_get_drvdata(dev); @@ -1054,7 +1051,6 @@ static int sa11x0_dma_resume(struct device *dev) return 0; } -#endif static const struct dev_pm_ops sa11x0_dma_pm_ops = { .suspend_noirq = sa11x0_dma_suspend, -- cgit v1.2.3 From 0b5a958cf4df3a5cd578b861471e62138f55c85e Mon Sep 17 00:00:00 2001 From: Stephane Grosjean Date: Tue, 20 May 2014 11:38:56 +0200 Subject: can: peak_pci: prevent use after free at netdev removal As remarked by Christopher R. Baker in his post at http://marc.info/?l=linux-can&m=139707295706465&w=2 there's a possibility for an use after free condition at device removal. This simplified patch introduces an additional variable to prevent the issue. Thanks for catching this. Cc: linux-stable Reported-by: Christopher R. Baker Signed-off-by: Stephane Grosjean Signed-off-by: Marc Kleine-Budde --- drivers/net/can/sja1000/peak_pci.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/net/can/sja1000/peak_pci.c b/drivers/net/can/sja1000/peak_pci.c index c540e3d12e3d..564933ae218c 100644 --- a/drivers/net/can/sja1000/peak_pci.c +++ b/drivers/net/can/sja1000/peak_pci.c @@ -551,7 +551,7 @@ static int peak_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct sja1000_priv *priv; struct peak_pci_chan *chan; - struct net_device *dev; + struct net_device *dev, *prev_dev; void __iomem *cfg_base, *reg_base; u16 sub_sys_id, icr; int i, err, channels; @@ -688,11 +688,13 @@ failure_remove_channels: writew(0x0, cfg_base + PITA_ICR + 2); chan = NULL; - for (dev = pci_get_drvdata(pdev); dev; dev = chan->prev_dev) { - unregister_sja1000dev(dev); - free_sja1000dev(dev); + for (dev = pci_get_drvdata(pdev); dev; dev = prev_dev) { priv = netdev_priv(dev); chan = priv->priv; + prev_dev = chan->prev_dev; + + unregister_sja1000dev(dev); + free_sja1000dev(dev); } /* free any PCIeC resources too */ @@ -726,10 +728,12 @@ static void peak_pci_remove(struct pci_dev *pdev) /* Loop over all registered devices */ while (1) { + struct net_device *prev_dev = chan->prev_dev; + dev_info(&pdev->dev, "removing device %s\n", dev->name); unregister_sja1000dev(dev); free_sja1000dev(dev); - dev = chan->prev_dev; + dev = prev_dev; if (!dev) { /* do that only for first channel */ -- cgit v1.2.3 From e5eb925a1804c4a52994ba57f4f68ee7a9132905 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 21 May 2014 11:42:10 +0200 Subject: MIPS: Change type of asid_cache to unsigned long asid_cache must be unsigned long otherwise on 64 bit systems it will become 0 if the value in get_new_mmu_context() reaches 0xffffffff and in the end the assumption of ASID_FIRST_VERSION is not true anymore thus leads to more dangerous things. Initial patch by Yong Zhang Signed-off-by: Ralf Baechle Reported-by: libin --- arch/mips/include/asm/cpu-info.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/mips/include/asm/cpu-info.h b/arch/mips/include/asm/cpu-info.h index dc2135be2a3a..ff2707ab3295 100644 --- a/arch/mips/include/asm/cpu-info.h +++ b/arch/mips/include/asm/cpu-info.h @@ -39,14 +39,14 @@ struct cache_desc { #define MIPS_CACHE_PINDEX 0x00000020 /* Physically indexed cache */ struct cpuinfo_mips { - unsigned int udelay_val; - unsigned int asid_cache; + unsigned long asid_cache; /* * Capability and feature descriptor structure for MIPS CPU */ unsigned long options; unsigned long ases; + unsigned int udelay_val; unsigned int processor_id; unsigned int fpu_id; unsigned int msa_id; -- cgit v1.2.3 From 6c67c7c38cf32c2a9cbccb6b21aadf61a85fbfb4 Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 21 May 2014 14:48:05 +0100 Subject: AFS: Fix cache manager service handlers Fix the cache manager RPC service handlers. The afs_send_empty_reply() and afs_send_simple_reply() functions: (a) Kill the call and free up the buffers associated with it if they fail. (b) Return with call intact if it they succeed. However, none of the callers actually check the result or clean up if successful - and may use the now non-existent data if it fails. This was detected by Dan Carpenter using a static checker: The patch 08e0e7c82eea: "[AF_RXRPC]: Make the in-kernel AFS filesystem use AF_RXRPC." from Apr 26, 2007, leads to the following static checker warning: "fs/afs/cmservice.c:155 SRXAFSCB_CallBack() warn: 'call' was already freed." Reported-by: Dan Carpenter Signed-off-by: David Howells --- fs/afs/cmservice.c | 19 +++++++++++++++++++ fs/afs/rxrpc.c | 43 +++++++++++++++++++++---------------------- 2 files changed, 40 insertions(+), 22 deletions(-) diff --git a/fs/afs/cmservice.c b/fs/afs/cmservice.c index 1c8c6cc6de30..4b0eff6da674 100644 --- a/fs/afs/cmservice.c +++ b/fs/afs/cmservice.c @@ -130,6 +130,15 @@ static void afs_cm_destructor(struct afs_call *call) { _enter(""); + /* Break the callbacks here so that we do it after the final ACK is + * received. The step number here must match the final number in + * afs_deliver_cb_callback(). + */ + if (call->unmarshall == 6) { + ASSERT(call->server && call->count && call->request); + afs_break_callbacks(call->server, call->count, call->request); + } + afs_put_server(call->server); call->server = NULL; kfree(call->buffer); @@ -272,6 +281,16 @@ static int afs_deliver_cb_callback(struct afs_call *call, struct sk_buff *skb, _debug("trailer"); if (skb->len != 0) return -EBADMSG; + + /* Record that the message was unmarshalled successfully so + * that the call destructor can know do the callback breaking + * work, even if the final ACK isn't received. + * + * If the step number changes, then afs_cm_destructor() must be + * updated also. + */ + call->unmarshall++; + case 6: break; } diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c index ef943df73b8c..9226a6674d7f 100644 --- a/fs/afs/rxrpc.c +++ b/fs/afs/rxrpc.c @@ -183,6 +183,19 @@ static void afs_free_call(struct afs_call *call) kfree(call); } +/* + * End a call + */ +static void afs_end_call(struct afs_call *call) +{ + if (call->rxcall) { + rxrpc_kernel_end_call(call->rxcall); + call->rxcall = NULL; + } + call->type->destructor(call); + afs_free_call(call); +} + /* * allocate a call with flat request and reply buffers */ @@ -383,11 +396,8 @@ error_do_abort: rxrpc_kernel_abort_call(rxcall, RX_USER_ABORT); while ((skb = skb_dequeue(&call->rx_queue))) afs_free_skb(skb); - rxrpc_kernel_end_call(rxcall); - call->rxcall = NULL; error_kill_call: - call->type->destructor(call); - afs_free_call(call); + afs_end_call(call); _leave(" = %d", ret); return ret; } @@ -509,12 +519,8 @@ static void afs_deliver_to_call(struct afs_call *call) if (call->state >= AFS_CALL_COMPLETE) { while ((skb = skb_dequeue(&call->rx_queue))) afs_free_skb(skb); - if (call->incoming) { - rxrpc_kernel_end_call(call->rxcall); - call->rxcall = NULL; - call->type->destructor(call); - afs_free_call(call); - } + if (call->incoming) + afs_end_call(call); } _leave(""); @@ -564,10 +570,7 @@ static int afs_wait_for_call_to_complete(struct afs_call *call) } _debug("call complete"); - rxrpc_kernel_end_call(call->rxcall); - call->rxcall = NULL; - call->type->destructor(call); - afs_free_call(call); + afs_end_call(call); _leave(" = %d", ret); return ret; } @@ -790,10 +793,7 @@ void afs_send_empty_reply(struct afs_call *call) _debug("oom"); rxrpc_kernel_abort_call(call->rxcall, RX_USER_ABORT); default: - rxrpc_kernel_end_call(call->rxcall); - call->rxcall = NULL; - call->type->destructor(call); - afs_free_call(call); + afs_end_call(call); _leave(" [error]"); return; } @@ -823,17 +823,16 @@ void afs_send_simple_reply(struct afs_call *call, const void *buf, size_t len) call->state = AFS_CALL_AWAIT_ACK; n = rxrpc_kernel_send_data(call->rxcall, &msg, len); if (n >= 0) { + /* Success */ _leave(" [replied]"); return; } + if (n == -ENOMEM) { _debug("oom"); rxrpc_kernel_abort_call(call->rxcall, RX_USER_ABORT); } - rxrpc_kernel_end_call(call->rxcall); - call->rxcall = NULL; - call->type->destructor(call); - afs_free_call(call); + afs_end_call(call); _leave(" [error]"); } -- cgit v1.2.3 From a1b8ff4c97b4375d21b6d6c45d75877303f61b3b Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Tue, 20 May 2014 15:55:21 -0400 Subject: nfsd4: remove lockowner when removing lock stateid The nfsv4 state code has always assumed a one-to-one correspondance between lock stateid's and lockowners even if it appears not to in some places. We may actually change that, but for now when FREE_STATEID releases a lock stateid it also needs to release the parent lockowner. Symptoms were a subsequent LOCK crashing in find_lockowner_str when it calls same_lockowner_ino on a lockowner that unexpectedly has an empty so_stateids list. Cc: stable@vger.kernel.org Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4state.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 32b699bebb9c..89e42409b237 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -3717,9 +3717,16 @@ out: static __be32 nfsd4_free_lock_stateid(struct nfs4_ol_stateid *stp) { - if (check_for_locks(stp->st_file, lockowner(stp->st_stateowner))) + struct nfs4_lockowner *lo = lockowner(stp->st_stateowner); + + if (check_for_locks(stp->st_file, lo)) return nfserr_locks_held; - release_lock_stateid(stp); + /* + * Currently there's a 1-1 lock stateid<->lockowner + * correspondance, and we have to delete the lockowner when we + * delete the lock stateid: + */ + unhash_lockowner(lo); return nfs_ok; } -- cgit v1.2.3 From 27b11428b7de097c42f205beabb1764f4365443b Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Thu, 8 May 2014 11:19:41 -0400 Subject: nfsd4: warn on finding lockowner without stateid's The current code assumes a one-to-one lockowner<->lock stateid correspondance. Cc: stable@vger.kernel.org Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4state.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 89e42409b237..9a77a5a21557 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -4166,6 +4166,10 @@ static bool same_lockowner_ino(struct nfs4_lockowner *lo, struct inode *inode, c if (!same_owner_str(&lo->lo_owner, owner, clid)) return false; + if (list_empty(&lo->lo_owner.so_stateids)) { + WARN_ON_ONCE(1); + return false; + } lst = list_first_entry(&lo->lo_owner.so_stateids, struct nfs4_ol_stateid, st_perstateowner); return lst->st_file->fi_inode == inode; -- cgit v1.2.3 From 8ecc1bad4c9b485ceb47182d282980d0b0fe20ac Mon Sep 17 00:00:00 2001 From: Toralf Förster Date: Mon, 19 May 2014 10:26:31 +0200 Subject: sparc64: fix format string mismatch in arch/sparc/kernel/sysfs.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit found by cppcheck Signed-off-by: Toralf Förster Acked-by: Sam Ravnborg Signed-off-by: David S. Miller --- arch/sparc/kernel/sysfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sparc/kernel/sysfs.c b/arch/sparc/kernel/sysfs.c index a364000ca1aa..7f41d40b7e6e 100644 --- a/arch/sparc/kernel/sysfs.c +++ b/arch/sparc/kernel/sysfs.c @@ -151,7 +151,7 @@ static ssize_t store_mmustat_enable(struct device *s, size_t count) { unsigned long val, err; - int ret = sscanf(buf, "%ld", &val); + int ret = sscanf(buf, "%lu", &val); if (ret != 1) return -EINVAL; -- cgit v1.2.3 From bf63ac73b3e132e6bf0c8798aba7b277c3316e19 Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Mon, 19 May 2014 12:15:49 -0700 Subject: net_sched: fix an oops in tcindex filter Kelly reported the following crash: IP: [] tcf_action_exec+0x46/0x90 PGD 3009067 PUD 300c067 PMD 11ff30067 PTE 800000011634b060 Oops: 0000 [#1] SMP DEBUG_PAGEALLOC CPU: 1 PID: 639 Comm: dhclient Not tainted 3.15.0-rc4+ #342 Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011 task: ffff8801169ecd00 ti: ffff8800d21b8000 task.ti: ffff8800d21b8000 RIP: 0010:[] [] tcf_action_exec+0x46/0x90 RSP: 0018:ffff8800d21b9b90 EFLAGS: 00010283 RAX: 00000000ffffffff RBX: ffff88011634b8e8 RCX: ffff8800cf7133d8 RDX: ffff88011634b900 RSI: ffff8800cf7133e0 RDI: ffff8800d210f840 RBP: ffff8800d21b9bb0 R08: ffffffff8287bf60 R09: 0000000000000001 R10: ffff8800d2b22b24 R11: 0000000000000001 R12: ffff8800d210f840 R13: ffff8800d21b9c50 R14: ffff8800cf7133e0 R15: ffff8800cad433d8 FS: 00007f49723e1840(0000) GS:ffff88011a800000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: ffff88011634b8f0 CR3: 00000000ce469000 CR4: 00000000000006e0 Stack: ffff8800d2170188 ffff8800d210f840 ffff8800d2171b90 0000000000000000 ffff8800d21b9be8 ffffffff817c55bb ffff8800d21b9c50 ffff8800d2171b90 ffff8800d210f840 ffff8800d21b0300 ffff8800d21b9c50 ffff8800d21b9c18 Call Trace: [] tcindex_classify+0x88/0x9b [] tc_classify_compat+0x3e/0x7b [] tc_classify+0x25/0x9f [] htb_enqueue+0x55/0x27a [] dsmark_enqueue+0x165/0x1a4 [] __dev_queue_xmit+0x35e/0x536 [] dev_queue_xmit+0x10/0x12 [] packet_sendmsg+0xb26/0xb9a [] ? __lock_acquire+0x3ae/0xdf3 [] __sock_sendmsg_nosec+0x25/0x27 [] sock_aio_write+0xd0/0xe7 [] do_sync_write+0x59/0x78 [] vfs_write+0xb5/0x10a [] SyS_write+0x49/0x7f [] system_call_fastpath+0x16/0x1b This is because we memcpy struct tcindex_filter_result which contains struct tcf_exts, obviously struct list_head can not be simply copied. This is a regression introduced by commit 33be627159913b094bb578 (net_sched: act: use standard struct list_head). It's not very easy to fix it as the code is a mess: if (old_r) memcpy(&cr, r, sizeof(cr)); else { memset(&cr, 0, sizeof(cr)); tcf_exts_init(&cr.exts, TCA_TCINDEX_ACT, TCA_TCINDEX_POLICE); } ... tcf_exts_change(tp, &cr.exts, &e); ... memcpy(r, &cr, sizeof(cr)); the above code should equal to: tcindex_filter_result_init(&cr); if (old_r) cr.res = r->res; ... if (old_r) tcf_exts_change(tp, &r->exts, &e); else tcf_exts_change(tp, &cr.exts, &e); ... r->res = cr.res; after this change, since there is no need to copy struct tcf_exts. And it also fixes other places zero'ing struct's contains struct tcf_exts. Fixes: commit 33be627159913b0 (net_sched: act: use standard struct list_head) Reported-by: Kelly Anderson Tested-by: Kelly Anderson Cc: David S. Miller Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- net/sched/cls_tcindex.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c index eed8404443d8..f435a88d899a 100644 --- a/net/sched/cls_tcindex.c +++ b/net/sched/cls_tcindex.c @@ -188,6 +188,12 @@ static const struct nla_policy tcindex_policy[TCA_TCINDEX_MAX + 1] = { [TCA_TCINDEX_CLASSID] = { .type = NLA_U32 }, }; +static void tcindex_filter_result_init(struct tcindex_filter_result *r) +{ + memset(r, 0, sizeof(*r)); + tcf_exts_init(&r->exts, TCA_TCINDEX_ACT, TCA_TCINDEX_POLICE); +} + static int tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base, u32 handle, struct tcindex_data *p, @@ -207,15 +213,11 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base, return err; memcpy(&cp, p, sizeof(cp)); - memset(&new_filter_result, 0, sizeof(new_filter_result)); - tcf_exts_init(&new_filter_result.exts, TCA_TCINDEX_ACT, TCA_TCINDEX_POLICE); + tcindex_filter_result_init(&new_filter_result); + tcindex_filter_result_init(&cr); if (old_r) - memcpy(&cr, r, sizeof(cr)); - else { - memset(&cr, 0, sizeof(cr)); - tcf_exts_init(&cr.exts, TCA_TCINDEX_ACT, TCA_TCINDEX_POLICE); - } + cr.res = r->res; if (tb[TCA_TCINDEX_HASH]) cp.hash = nla_get_u32(tb[TCA_TCINDEX_HASH]); @@ -267,9 +269,14 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base, err = -ENOMEM; if (!cp.perfect && !cp.h) { if (valid_perfect_hash(&cp)) { + int i; + cp.perfect = kcalloc(cp.hash, sizeof(*r), GFP_KERNEL); if (!cp.perfect) goto errout; + for (i = 0; i < cp.hash; i++) + tcf_exts_init(&cp.perfect[i].exts, TCA_TCINDEX_ACT, + TCA_TCINDEX_POLICE); balloc = 1; } else { cp.h = kcalloc(cp.hash, sizeof(f), GFP_KERNEL); @@ -295,14 +302,17 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base, tcf_bind_filter(tp, &cr.res, base); } - tcf_exts_change(tp, &cr.exts, &e); + if (old_r) + tcf_exts_change(tp, &r->exts, &e); + else + tcf_exts_change(tp, &cr.exts, &e); tcf_tree_lock(tp); if (old_r && old_r != r) - memset(old_r, 0, sizeof(*old_r)); + tcindex_filter_result_init(old_r); memcpy(p, &cp, sizeof(cp)); - memcpy(r, &cr, sizeof(cr)); + r->res = cr.res; if (r == &new_filter_result) { struct tcindex_filter **fp; -- cgit v1.2.3 From 5a9a55bf9157d3490b0c8c4c81d4708602c26e07 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Wed, 21 May 2014 14:02:35 -0700 Subject: dma: mv_xor: Flush descriptors before activating a channel We need to use writel() instead of writel_relaxed() when starting a channel, to ensure all the descriptors have been flushed before the activation. While at it, remove the unneeded read-modify-write and make the code simpler. Cc: Signed-off-by: Lior Amsalem Signed-off-by: Ezequiel Garcia Signed-off-by: Dan Williams --- drivers/dma/mv_xor.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c index 766b68ed505c..394cbc5c93e3 100644 --- a/drivers/dma/mv_xor.c +++ b/drivers/dma/mv_xor.c @@ -191,12 +191,10 @@ static void mv_set_mode(struct mv_xor_chan *chan, static void mv_chan_activate(struct mv_xor_chan *chan) { - u32 activation; - dev_dbg(mv_chan_to_devp(chan), " activate chan.\n"); - activation = readl_relaxed(XOR_ACTIVATION(chan)); - activation |= 0x1; - writel_relaxed(activation, XOR_ACTIVATION(chan)); + + /* writel ensures all descriptors are flushed before activation */ + writel(BIT(0), XOR_ACTIVATION(chan)); } static char mv_chan_is_busy(struct mv_xor_chan *chan) -- cgit v1.2.3 From c1f43dd9c20d85e66c4d77e284f64ac114abe3f8 Mon Sep 17 00:00:00 2001 From: Xuelin Shi Date: Wed, 21 May 2014 14:02:37 -0700 Subject: dmaengine: fix dmaengine_unmap failure The count which is used to get_unmap_data maybe not the same as the count computed in dmaengine_unmap which causes to free data in a wrong pool. This patch fixes this issue by keeping the map count with unmap_data structure and use this count to get the pool. Cc: Signed-off-by: Xuelin Shi Signed-off-by: Dan Williams --- drivers/dma/dmaengine.c | 2 ++ include/linux/dmaengine.h | 1 + 2 files changed, 3 insertions(+) diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index a886713937fd..d5d30ed863ce 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -1009,6 +1009,7 @@ static void dmaengine_unmap(struct kref *kref) dma_unmap_page(dev, unmap->addr[i], unmap->len, DMA_BIDIRECTIONAL); } + cnt = unmap->map_cnt; mempool_free(unmap, __get_unmap_pool(cnt)->pool); } @@ -1074,6 +1075,7 @@ dmaengine_get_unmap_data(struct device *dev, int nr, gfp_t flags) memset(unmap, 0, sizeof(*unmap)); kref_init(&unmap->kref); unmap->dev = dev; + unmap->map_cnt = nr; return unmap; } diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index 8300fb87b84a..72cb0ddb9678 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -429,6 +429,7 @@ typedef bool (*dma_filter_fn)(struct dma_chan *chan, void *filter_param); typedef void (*dma_async_tx_callback)(void *dma_async_param); struct dmaengine_unmap_data { + u8 map_cnt; u8 to_cnt; u8 from_cnt; u8 bidi_cnt; -- cgit v1.2.3 From 4de462ab63e23953fd05da511aeb460ae10cc726 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 19 May 2014 21:56:34 -0700 Subject: ipv6: gro: fix CHECKSUM_COMPLETE support When GRE support was added in linux-3.14, CHECKSUM_COMPLETE handling broke on GRE+IPv6 because we did not update/use the appropriate csum : GRO layer is supposed to use/update NAPI_GRO_CB(skb)->csum instead of skb->csum Tested using a GRE tunnel and IPv6 traffic. GRO aggregation now happens at the first level (ethernet device) instead of being done in gre tunnel. Native IPv6+TCP is still properly aggregated. Fixes: bf5a755f5e918 ("net-gre-gro: Add GRE support to the GRO stack") Signed-off-by: Eric Dumazet Cc: Jerry Chu Signed-off-by: David S. Miller --- net/ipv6/ip6_offload.c | 6 +----- net/ipv6/tcpv6_offload.c | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c index 59f95affceb0..b2f091566f88 100644 --- a/net/ipv6/ip6_offload.c +++ b/net/ipv6/ip6_offload.c @@ -196,7 +196,6 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head, unsigned int off; u16 flush = 1; int proto; - __wsum csum; off = skb_gro_offset(skb); hlen = off + sizeof(*iph); @@ -264,13 +263,10 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head, NAPI_GRO_CB(skb)->flush |= flush; - csum = skb->csum; - skb_postpull_rcsum(skb, iph, skb_network_header_len(skb)); + skb_gro_postpull_rcsum(skb, iph, nlen); pp = ops->callbacks.gro_receive(head, skb); - skb->csum = csum; - out_unlock: rcu_read_unlock(); diff --git a/net/ipv6/tcpv6_offload.c b/net/ipv6/tcpv6_offload.c index 0d78132ff18a..8517d3cd1aed 100644 --- a/net/ipv6/tcpv6_offload.c +++ b/net/ipv6/tcpv6_offload.c @@ -42,7 +42,7 @@ static struct sk_buff **tcp6_gro_receive(struct sk_buff **head, if (NAPI_GRO_CB(skb)->flush) goto skip_csum; - wsum = skb->csum; + wsum = NAPI_GRO_CB(skb)->csum; switch (skb->ip_summed) { case CHECKSUM_NONE: -- cgit v1.2.3 From 4b660a7f5c8099d88d1a43d8ae138965112592c7 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 22 May 2014 06:42:02 +0900 Subject: Linux 3.15-rc6 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 8a8440a3578e..9d993787afe0 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 3 PATCHLEVEL = 15 SUBLEVEL = 0 -EXTRAVERSION = -rc5 +EXTRAVERSION = -rc6 NAME = Shuffling Zombie Juror # *DOCUMENTATION* -- cgit v1.2.3 From d1d70e5dc2cfa9047bb935c41ba808ebb8135696 Mon Sep 17 00:00:00 2001 From: Emil Goode Date: Mon, 19 May 2014 15:07:54 +0800 Subject: ARM: imx: fix error handling in ipu device registration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If we fail to allocate struct platform_device pdev we dereference it after the goto label err. This bug was found using coccinelle. Fixes: afa77ef (ARM: mx3: dynamically allocate "ipu-core" devices) Signed-off-by: Emil Goode Acked-by: Uwe Kleine-König Cc: Signed-off-by: Shawn Guo Signed-off-by: Olof Johansson --- arch/arm/mach-imx/devices/platform-ipu-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-imx/devices/platform-ipu-core.c b/arch/arm/mach-imx/devices/platform-ipu-core.c index fc4dd7cedc11..6bd7c3f37ac0 100644 --- a/arch/arm/mach-imx/devices/platform-ipu-core.c +++ b/arch/arm/mach-imx/devices/platform-ipu-core.c @@ -77,7 +77,7 @@ struct platform_device *__init imx_alloc_mx3_camera( pdev = platform_device_alloc("mx3-camera", 0); if (!pdev) - goto err; + return ERR_PTR(-ENOMEM); pdev->dev.dma_mask = kmalloc(sizeof(*pdev->dev.dma_mask), GFP_KERNEL); if (!pdev->dev.dma_mask) -- cgit v1.2.3 From 143cf23df25b7082cd706c3c53188e741e7881c3 Mon Sep 17 00:00:00 2001 From: Michael Kerrisk Date: Fri, 9 May 2014 16:54:15 +0200 Subject: sched: Make sched_setattr() correctly return -EFBIG The documented[1] behavior of sched_attr() in the proposed man page text is: sched_attr::size must be set to the size of the structure, as in sizeof(struct sched_attr), if the provided structure is smaller than the kernel structure, any additional fields are assumed '0'. If the provided structure is larger than the kernel structure, the kernel verifies all additional fields are '0' if not the syscall will fail with -E2BIG. As currently implemented, sched_copy_attr() returns -EFBIG for for this case, but the logic in sys_sched_setattr() converts that error to -EFAULT. This patch fixes the behavior. [1] http://thread.gmane.org/gmane.linux.kernel/1615615/focus=1697760 Signed-off-by: Michael Kerrisk Signed-off-by: Peter Zijlstra Cc: Cc: Linus Torvalds Link: http://lkml.kernel.org/r/536CEC17.9070903@gmail.com Signed-off-by: Ingo Molnar --- kernel/sched/core.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 13584f1cccfc..f2205f02eb70 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -3658,8 +3658,9 @@ SYSCALL_DEFINE3(sched_setattr, pid_t, pid, struct sched_attr __user *, uattr, if (!uattr || pid < 0 || flags) return -EINVAL; - if (sched_copy_attr(uattr, &attr)) - return -EFAULT; + retval = sched_copy_attr(uattr, &attr); + if (retval) + return retval; rcu_read_lock(); retval = -ESRCH; -- cgit v1.2.3 From dbdb22754fde671dc93d2fae06f8be113d47f2fb Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Fri, 9 May 2014 10:49:03 +0200 Subject: sched: Disallow sched_attr::sched_policy < 0 The scheduler uses policy=-1 to preserve the current policy state to implement sys_sched_setparam(), this got exposed to userspace by accident through sys_sched_setattr(), cure this. Reported-by: Michael Kerrisk Signed-off-by: Peter Zijlstra Acked-by: Michael Kerrisk Cc: Cc: Linus Torvalds Link: http://lkml.kernel.org/r/20140509085311.GJ30445@twins.programming.kicks-ass.net Signed-off-by: Ingo Molnar --- kernel/sched/core.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index f2205f02eb70..cdefcf7c5925 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -3662,6 +3662,9 @@ SYSCALL_DEFINE3(sched_setattr, pid_t, pid, struct sched_attr __user *, uattr, if (retval) return retval; + if (attr.sched_policy < 0) + return -EINVAL; + rcu_read_lock(); retval = -ESRCH; p = find_process_by_pid(pid); -- cgit v1.2.3 From ce5f7f8200ca2504f6f290044393d73ca314965a Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 12 May 2014 22:50:34 +0200 Subject: sched/deadline: Change sched_getparam() behaviour vs SCHED_DEADLINE The way we read POSIX one should only call sched_getparam() when sched_getscheduler() returns either SCHED_FIFO or SCHED_RR. Given that we currently return sched_param::sched_priority=0 for all others, extend the same behaviour to SCHED_DEADLINE. Requested-by: Michael Kerrisk Signed-off-by: Peter Zijlstra Acked-by: Michael Kerrisk Cc: Dario Faggioli Cc: linux-man Cc: "Michael Kerrisk (man-pages)" Cc: Juri Lelli Cc: Linus Torvalds Cc: Link: http://lkml.kernel.org/r/20140512205034.GH13467@laptop.programming.kicks-ass.net Signed-off-by: Ingo Molnar --- kernel/sched/core.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index cdefcf7c5925..f3f08bf94355 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -3713,7 +3713,7 @@ SYSCALL_DEFINE1(sched_getscheduler, pid_t, pid) */ SYSCALL_DEFINE2(sched_getparam, pid_t, pid, struct sched_param __user *, param) { - struct sched_param lp; + struct sched_param lp = { .sched_priority = 0 }; struct task_struct *p; int retval; @@ -3730,11 +3730,8 @@ SYSCALL_DEFINE2(sched_getparam, pid_t, pid, struct sched_param __user *, param) if (retval) goto out_unlock; - if (task_has_dl_policy(p)) { - retval = -EINVAL; - goto out_unlock; - } - lp.sched_priority = p->rt_priority; + if (task_has_rt_policy(p)) + lp.sched_priority = p->rt_priority; rcu_read_unlock(); /* -- cgit v1.2.3 From b0827819b0da4acfbc1df1e05edcf50efd07cbd1 Mon Sep 17 00:00:00 2001 From: Juri Lelli Date: Tue, 13 May 2014 14:11:31 +0200 Subject: sched/deadline: Restrict user params max value to 2^63 ns Michael Kerrisk noticed that creating SCHED_DEADLINE reservations with certain parameters (e.g, a runtime of something near 2^64 ns) can cause a system freeze for some amount of time. The problem is that in the interface we have u64 sched_runtime; while internally we need to have a signed runtime (to cope with budget overruns) s64 runtime; At the time we setup a new dl_entity we copy the first value in the second. The cast turns out with negative values when sched_runtime is too big, and this causes the scheduler to go crazy right from the start. Moreover, considering how we deal with deadlines wraparound (s64)(a - b) < 0 we also have to restrict acceptable values for sched_{deadline,period}. This patch fixes the thing checking that user parameters are always below 2^63 ns (still large enough for everyone). It also rewrites other conditions that we check, since in __checkparam_dl we don't have to deal with deadline wraparounds and what we have now erroneously fails when the difference between values is too big. Reported-by: Michael Kerrisk Suggested-by: Peter Zijlstra Signed-off-by: Juri Lelli Signed-off-by: Peter Zijlstra Cc: Cc: Dario Faggioli Cc: Dave Jones Cc: Linus Torvalds Link: http://lkml.kernel.org/r/20140513141131.20d944f81633ee937f256385@gmail.com Signed-off-by: Ingo Molnar --- kernel/sched/core.c | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index f3f08bf94355..44e00abece09 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -3195,17 +3195,40 @@ __getparam_dl(struct task_struct *p, struct sched_attr *attr) * We ask for the deadline not being zero, and greater or equal * than the runtime, as well as the period of being zero or * greater than deadline. Furthermore, we have to be sure that - * user parameters are above the internal resolution (1us); we - * check sched_runtime only since it is always the smaller one. + * user parameters are above the internal resolution of 1us (we + * check sched_runtime only since it is always the smaller one) and + * below 2^63 ns (we have to check both sched_deadline and + * sched_period, as the latter can be zero). */ static bool __checkparam_dl(const struct sched_attr *attr) { - return attr && attr->sched_deadline != 0 && - (attr->sched_period == 0 || - (s64)(attr->sched_period - attr->sched_deadline) >= 0) && - (s64)(attr->sched_deadline - attr->sched_runtime ) >= 0 && - attr->sched_runtime >= (2 << (DL_SCALE - 1)); + /* deadline != 0 */ + if (attr->sched_deadline == 0) + return false; + + /* + * Since we truncate DL_SCALE bits, make sure we're at least + * that big. + */ + if (attr->sched_runtime < (1ULL << DL_SCALE)) + return false; + + /* + * Since we use the MSB for wrap-around and sign issues, make + * sure it's not set (mind that period can be equal to zero). + */ + if (attr->sched_deadline & (1ULL << 63) || + attr->sched_period & (1ULL << 63)) + return false; + + /* runtime <= deadline <= period (if period != 0) */ + if ((attr->sched_period != 0 && + attr->sched_period < attr->sched_deadline) || + attr->sched_deadline < attr->sched_runtime) + return false; + + return true; } /* -- cgit v1.2.3 From 944770ab54babaef29d9d1dc8189898b3ee8afcf Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 14 May 2014 16:13:56 +0200 Subject: sched/deadline: Replace NR_CPUS arrays Tejun reported that his resume was failing due to order-3 allocations from sched_domain building. Replace the NR_CPUS arrays in there with a dynamically allocated array. Reported-by: Tejun Heo Signed-off-by: Peter Zijlstra Acked-by: Juri Lelli Cc: Johannes Weiner Cc: Linus Torvalds Link: http://lkml.kernel.org/n/tip-kat4gl1m5a6dwy6nzuqox45e@git.kernel.org Signed-off-by: Ingo Molnar --- kernel/sched/cpudeadline.c | 33 ++++++++++++++++++++++++--------- kernel/sched/cpudeadline.h | 6 +++--- 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/kernel/sched/cpudeadline.c b/kernel/sched/cpudeadline.c index ab001b5d5048..bd95963dae80 100644 --- a/kernel/sched/cpudeadline.c +++ b/kernel/sched/cpudeadline.c @@ -13,6 +13,7 @@ #include #include +#include #include "cpudeadline.h" static inline int parent(int i) @@ -39,8 +40,10 @@ static void cpudl_exchange(struct cpudl *cp, int a, int b) { int cpu_a = cp->elements[a].cpu, cpu_b = cp->elements[b].cpu; - swap(cp->elements[a], cp->elements[b]); - swap(cp->cpu_to_idx[cpu_a], cp->cpu_to_idx[cpu_b]); + swap(cp->elements[a].cpu, cp->elements[b].cpu); + swap(cp->elements[a].dl , cp->elements[b].dl ); + + swap(cp->elements[cpu_a].idx, cp->elements[cpu_b].idx); } static void cpudl_heapify(struct cpudl *cp, int idx) @@ -140,7 +143,7 @@ void cpudl_set(struct cpudl *cp, int cpu, u64 dl, int is_valid) WARN_ON(!cpu_present(cpu)); raw_spin_lock_irqsave(&cp->lock, flags); - old_idx = cp->cpu_to_idx[cpu]; + old_idx = cp->elements[cpu].idx; if (!is_valid) { /* remove item */ if (old_idx == IDX_INVALID) { @@ -155,8 +158,8 @@ void cpudl_set(struct cpudl *cp, int cpu, u64 dl, int is_valid) cp->elements[old_idx].dl = cp->elements[cp->size - 1].dl; cp->elements[old_idx].cpu = new_cpu; cp->size--; - cp->cpu_to_idx[new_cpu] = old_idx; - cp->cpu_to_idx[cpu] = IDX_INVALID; + cp->elements[new_cpu].idx = old_idx; + cp->elements[cpu].idx = IDX_INVALID; while (old_idx > 0 && dl_time_before( cp->elements[parent(old_idx)].dl, cp->elements[old_idx].dl)) { @@ -173,7 +176,7 @@ void cpudl_set(struct cpudl *cp, int cpu, u64 dl, int is_valid) cp->size++; cp->elements[cp->size - 1].dl = 0; cp->elements[cp->size - 1].cpu = cpu; - cp->cpu_to_idx[cpu] = cp->size - 1; + cp->elements[cpu].idx = cp->size - 1; cpudl_change_key(cp, cp->size - 1, dl); cpumask_clear_cpu(cpu, cp->free_cpus); } else { @@ -195,10 +198,21 @@ int cpudl_init(struct cpudl *cp) memset(cp, 0, sizeof(*cp)); raw_spin_lock_init(&cp->lock); cp->size = 0; - for (i = 0; i < NR_CPUS; i++) - cp->cpu_to_idx[i] = IDX_INVALID; - if (!alloc_cpumask_var(&cp->free_cpus, GFP_KERNEL)) + + cp->elements = kcalloc(nr_cpu_ids, + sizeof(struct cpudl_item), + GFP_KERNEL); + if (!cp->elements) + return -ENOMEM; + + if (!alloc_cpumask_var(&cp->free_cpus, GFP_KERNEL)) { + kfree(cp->elements); return -ENOMEM; + } + + for_each_possible_cpu(i) + cp->elements[i].idx = IDX_INVALID; + cpumask_setall(cp->free_cpus); return 0; @@ -211,4 +225,5 @@ int cpudl_init(struct cpudl *cp) void cpudl_cleanup(struct cpudl *cp) { free_cpumask_var(cp->free_cpus); + kfree(cp->elements); } diff --git a/kernel/sched/cpudeadline.h b/kernel/sched/cpudeadline.h index a202789a412c..538c9796ad4a 100644 --- a/kernel/sched/cpudeadline.h +++ b/kernel/sched/cpudeadline.h @@ -5,17 +5,17 @@ #define IDX_INVALID -1 -struct array_item { +struct cpudl_item { u64 dl; int cpu; + int idx; }; struct cpudl { raw_spinlock_t lock; int size; - int cpu_to_idx[NR_CPUS]; - struct array_item elements[NR_CPUS]; cpumask_var_t free_cpus; + struct cpudl_item *elements; }; -- cgit v1.2.3 From 4dac0b638310d2e92f6e19958b73d4c97c9734bb Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 14 May 2014 16:04:26 +0200 Subject: sched/cpupri: Replace NR_CPUS arrays Tejun reported that his resume was failing due to order-3 allocations from sched_domain building. Replace the NR_CPUS arrays in there with a dynamically allocated array. Reported-by: Tejun Heo Signed-off-by: Peter Zijlstra Cc: Johannes Weiner Cc: Steven Rostedt Cc: Linus Torvalds Link: http://lkml.kernel.org/n/tip-7cysnkw1gik45r864t1nkudh@git.kernel.org Signed-off-by: Ingo Molnar --- kernel/sched/cpupri.c | 7 +++++++ kernel/sched/cpupri.h | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/kernel/sched/cpupri.c b/kernel/sched/cpupri.c index 3031bac8aa3e..8834243abee2 100644 --- a/kernel/sched/cpupri.c +++ b/kernel/sched/cpupri.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "cpupri.h" /* Convert between a 140 based task->prio, and our 102 based cpupri */ @@ -218,8 +219,13 @@ int cpupri_init(struct cpupri *cp) goto cleanup; } + cp->cpu_to_pri = kcalloc(nr_cpu_ids, sizeof(int), GFP_KERNEL); + if (!cp->cpu_to_pri) + goto cleanup; + for_each_possible_cpu(i) cp->cpu_to_pri[i] = CPUPRI_INVALID; + return 0; cleanup: @@ -236,6 +242,7 @@ void cpupri_cleanup(struct cpupri *cp) { int i; + kfree(cp->cpu_to_pri); for (i = 0; i < CPUPRI_NR_PRIORITIES; i++) free_cpumask_var(cp->pri_to_cpu[i].mask); } diff --git a/kernel/sched/cpupri.h b/kernel/sched/cpupri.h index f6d756173491..6b033347fdfd 100644 --- a/kernel/sched/cpupri.h +++ b/kernel/sched/cpupri.h @@ -17,7 +17,7 @@ struct cpupri_vec { struct cpupri { struct cpupri_vec pri_to_cpu[CPUPRI_NR_PRIORITIES]; - int cpu_to_pri[NR_CPUS]; + int *cpu_to_pri; }; #ifdef CONFIG_SMP -- cgit v1.2.3 From 6acbfb96976fc3350e30d964acb1dbbdf876d55e Mon Sep 17 00:00:00 2001 From: Lai Jiangshan Date: Fri, 16 May 2014 11:50:42 +0800 Subject: sched: Fix hotplug vs. set_cpus_allowed_ptr() Lai found that: WARNING: CPU: 1 PID: 13 at arch/x86/kernel/smp.c:124 native_smp_send_reschedule+0x2d/0x4b() ... migration_cpu_stop+0x1d/0x22 was caused by set_cpus_allowed_ptr() assuming that cpu_active_mask is always a sub-set of cpu_online_mask. This isn't true since 5fbd036b552f ("sched: Cleanup cpu_active madness"). So set active and online at the same time to avoid this particular problem. Fixes: 5fbd036b552f ("sched: Cleanup cpu_active madness") Signed-off-by: Lai Jiangshan Signed-off-by: Peter Zijlstra Cc: Andrew Morton Cc: Gautham R. Shenoy Cc: Linus Torvalds Cc: Michael wang Cc: Paul Gortmaker Cc: Rafael J. Wysocki Cc: Srivatsa S. Bhat Cc: Toshi Kani Link: http://lkml.kernel.org/r/53758B12.8060609@cn.fujitsu.com Signed-off-by: Ingo Molnar --- kernel/cpu.c | 6 ++++-- kernel/sched/core.c | 1 - 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/kernel/cpu.c b/kernel/cpu.c index a9e710eef0e2..247979a1b815 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -726,10 +726,12 @@ void set_cpu_present(unsigned int cpu, bool present) void set_cpu_online(unsigned int cpu, bool online) { - if (online) + if (online) { cpumask_set_cpu(cpu, to_cpumask(cpu_online_bits)); - else + cpumask_set_cpu(cpu, to_cpumask(cpu_active_bits)); + } else { cpumask_clear_cpu(cpu, to_cpumask(cpu_online_bits)); + } } void set_cpu_active(unsigned int cpu, bool active) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 44e00abece09..86f3890c3d08 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -5076,7 +5076,6 @@ static int sched_cpu_active(struct notifier_block *nfb, unsigned long action, void *hcpu) { switch (action & ~CPU_TASKS_FROZEN) { - case CPU_STARTING: case CPU_DOWN_FAILED: set_cpu_active((long)hcpu, true); return NOTIFY_OK; -- cgit v1.2.3 From dc93f7b68a039fe7d918613163b1cdd21b279ec5 Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Wed, 21 May 2014 10:49:19 +0800 Subject: MIPS: Fix a typo error in AUDIT_ARCH definition Missing a "|" in AUDIT_ARCH_MIPSEL64N32 macro definition. Signed-off-by: Huacai Chen Reviewed-by: Markos Chandras Cc: John Crispin Cc: Steven J. Hill Cc: Aurelien Jarno Cc: linux-mips@linux-mips.org Cc: Fuxin Zhang Cc: Zhangjin Wu Patchwork: https://patchwork.linux-mips.org/patch/6978/ Signed-off-by: Ralf Baechle --- include/uapi/linux/audit.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index 1b1efddb91cd..4c31a366be16 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h @@ -357,7 +357,7 @@ enum { #define AUDIT_ARCH_MIPS64N32 (EM_MIPS|__AUDIT_ARCH_64BIT|\ __AUDIT_ARCH_CONVENTION_MIPS64_N32) #define AUDIT_ARCH_MIPSEL64 (EM_MIPS|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE) -#define AUDIT_ARCH_MIPSEL64N32 (EM_MIPS|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE\ +#define AUDIT_ARCH_MIPSEL64N32 (EM_MIPS|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE|\ __AUDIT_ARCH_CONVENTION_MIPS64_N32) #define AUDIT_ARCH_OPENRISC (EM_OPENRISC) #define AUDIT_ARCH_PARISC (EM_PARISC) -- cgit v1.2.3 From c2a3dd9d2b30f65b4f4a62cb5a9b2c7131bd1ac4 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Tue, 20 May 2014 16:43:28 +0200 Subject: ARM: mvebu: fix definitions of PCIe interfaces on Armada 38x Due a copy/paste error, the 'reg' values for the third PCIe interface on Armada 380, and the third and fourth PCIe interfaces on Armada 385 are wrong: they are equal to the one of the second PCIe interface. This patch fixes this by using the appropriate 'reg' values for those PCIe interfaces. Without this fix, the third and fourth PCIe interfaces are unusable on those platforms. Reported-by: Nadav Haklai Signed-off-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1400597008-4148-1-git-send-email-thomas.petazzoni@free-electrons.com Fixes: 0d3d96ab0059 ("ARM: mvebu: add Device Tree description of the Armada 380/385 SoCs") Signed-off-by: Jason Cooper --- arch/arm/boot/dts/armada-380.dtsi | 2 +- arch/arm/boot/dts/armada-385.dtsi | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/armada-380.dtsi b/arch/arm/boot/dts/armada-380.dtsi index 068031f0f263..6d0f03c98ee9 100644 --- a/arch/arm/boot/dts/armada-380.dtsi +++ b/arch/arm/boot/dts/armada-380.dtsi @@ -99,7 +99,7 @@ pcie@3,0 { device_type = "pci"; assigned-addresses = <0x82000800 0 0x44000 0 0x2000>; - reg = <0x1000 0 0 0 0>; + reg = <0x1800 0 0 0 0>; #address-cells = <3>; #size-cells = <2>; #interrupt-cells = <1>; diff --git a/arch/arm/boot/dts/armada-385.dtsi b/arch/arm/boot/dts/armada-385.dtsi index e2919f02e1d4..da801964a257 100644 --- a/arch/arm/boot/dts/armada-385.dtsi +++ b/arch/arm/boot/dts/armada-385.dtsi @@ -110,7 +110,7 @@ pcie@3,0 { device_type = "pci"; assigned-addresses = <0x82000800 0 0x44000 0 0x2000>; - reg = <0x1000 0 0 0 0>; + reg = <0x1800 0 0 0 0>; #address-cells = <3>; #size-cells = <2>; #interrupt-cells = <1>; @@ -131,7 +131,7 @@ pcie@4,0 { device_type = "pci"; assigned-addresses = <0x82000800 0 0x48000 0 0x2000>; - reg = <0x1000 0 0 0 0>; + reg = <0x2000 0 0 0 0>; #address-cells = <3>; #size-cells = <2>; #interrupt-cells = <1>; -- cgit v1.2.3 From 13984e9bb15528f70059bbbbda3f9028157eebf6 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Wed, 7 May 2014 19:45:48 +0200 Subject: ARM: at91: sam9260: fix compilation issues Use the hexadecimal values for the triggers to match what is done for the device tree. This also fixes compilation issues as the defines have been moved elsewhere. Signed-off-by: Alexandre Belloni Signed-off-by: Nicolas Ferre --- arch/arm/mach-at91/at91sam9260_devices.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c index 8b1b0a870025..9e1695661171 100644 --- a/arch/arm/mach-at91/at91sam9260_devices.c +++ b/arch/arm/mach-at91/at91sam9260_devices.c @@ -1308,19 +1308,19 @@ static struct platform_device at91_adc_device = { static struct at91_adc_trigger at91_adc_triggers[] = { [0] = { .name = "timer-counter-0", - .value = AT91_ADC_TRGSEL_TC0 | AT91_ADC_TRGEN, + .value = 0x1, }, [1] = { .name = "timer-counter-1", - .value = AT91_ADC_TRGSEL_TC1 | AT91_ADC_TRGEN, + .value = 0x3, }, [2] = { .name = "timer-counter-2", - .value = AT91_ADC_TRGSEL_TC2 | AT91_ADC_TRGEN, + .value = 0x5, }, [3] = { .name = "external", - .value = AT91_ADC_TRGSEL_EXTERNAL | AT91_ADC_TRGEN, + .value = 0xd, .is_external = true, }, }; -- cgit v1.2.3 From f214be50f317d78c47532d4ca8aa0ba5e79fc1ca Mon Sep 17 00:00:00 2001 From: Zhiwu Song Date: Wed, 7 May 2014 14:46:44 +0800 Subject: clocksource: marco: Fix the affinity set for local timer of CPU1 irqchip will reject the affinity set to CPUs which is not online yet. but in the CPU1 wakeup stage, OS only sets CPU1 to be online after local timer is set, so that causes the irq_set_affinity not work. this patch moves to irq_force_affinity() for the low level boot stage. Signed-off-by: Zhiwu Song Signed-off-by: Barry Song Signed-off-by: Daniel Lezcano --- drivers/clocksource/timer-marco.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clocksource/timer-marco.c b/drivers/clocksource/timer-marco.c index b52e1c078b99..7f5374dbefd9 100644 --- a/drivers/clocksource/timer-marco.c +++ b/drivers/clocksource/timer-marco.c @@ -199,7 +199,7 @@ static int sirfsoc_local_timer_setup(struct clock_event_device *ce) action->dev_id = ce; BUG_ON(setup_irq(ce->irq, action)); - irq_set_affinity(action->irq, cpumask_of(cpu)); + irq_force_affinity(action->irq, cpumask_of(cpu)); clockevents_register_device(ce); return 0; -- cgit v1.2.3 From acbf6d21ac81195071b97ebb114b0b37bd9fcc86 Mon Sep 17 00:00:00 2001 From: David Jander Date: Thu, 8 May 2014 12:06:25 +0200 Subject: clocksource: tcb_clksrc: Make tc_mode interrupt safe tc_mode() can be called from interrupt context and thus must not call clk_*prepare*() functions. Signed-off-by: David Jander Signed-off-by: Daniel Lezcano Acked-by: Alexandre Belloni Acked-by: Nicolas Ferre --- drivers/clocksource/tcb_clksrc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/clocksource/tcb_clksrc.c b/drivers/clocksource/tcb_clksrc.c index 00fdd1170284..a8d7ea14f183 100644 --- a/drivers/clocksource/tcb_clksrc.c +++ b/drivers/clocksource/tcb_clksrc.c @@ -100,7 +100,7 @@ static void tc_mode(enum clock_event_mode m, struct clock_event_device *d) || tcd->clkevt.mode == CLOCK_EVT_MODE_ONESHOT) { __raw_writel(0xff, regs + ATMEL_TC_REG(2, IDR)); __raw_writel(ATMEL_TC_CLKDIS, regs + ATMEL_TC_REG(2, CCR)); - clk_disable_unprepare(tcd->clk); + clk_disable(tcd->clk); } switch (m) { @@ -109,7 +109,7 @@ static void tc_mode(enum clock_event_mode m, struct clock_event_device *d) * of oneshot, we get lower overhead and improved accuracy. */ case CLOCK_EVT_MODE_PERIODIC: - clk_prepare_enable(tcd->clk); + clk_enable(tcd->clk); /* slow clock, count up to RC, then irq and restart */ __raw_writel(timer_clock @@ -126,7 +126,7 @@ static void tc_mode(enum clock_event_mode m, struct clock_event_device *d) break; case CLOCK_EVT_MODE_ONESHOT: - clk_prepare_enable(tcd->clk); + clk_enable(tcd->clk); /* slow clock, count up to RC, then irq and stop */ __raw_writel(timer_clock | ATMEL_TC_CPCSTOP @@ -194,7 +194,7 @@ static int __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx) ret = clk_prepare_enable(t2_clk); if (ret) return ret; - clk_disable_unprepare(t2_clk); + clk_disable(t2_clk); clkevt.regs = tc->regs; clkevt.clk = t2_clk; -- cgit v1.2.3 From 89df20d951b310f3e33422554054ae6e58a3c7a9 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 20 May 2014 11:38:18 +0200 Subject: stmmac: Remove unbalanced clk_disable call The stmmac_open call was calling clk_disable_unprepare on phy init failure, but it never calls clk_prepare_enable, this causes a WARN_ON in the clk framework to trigger if for some reason phy init fails. Signed-off-by: Hans de Goede Acked-by: Giuseppe Cavallaro Acked-by: Chen-Yu Tsai Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index d940034acdd4..0f4841d2e8dc 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1704,7 +1704,7 @@ static int stmmac_open(struct net_device *dev) if (ret) { pr_err("%s: Cannot attach to PHY (error: %d)\n", __func__, ret); - goto phy_error; + return ret; } } @@ -1779,8 +1779,6 @@ init_error: dma_desc_error: if (priv->phydev) phy_disconnect(priv->phydev); -phy_error: - clk_disable_unprepare(priv->stmmac_clk); return ret; } -- cgit v1.2.3 From b0db5cdf3975134ca967e8b8370a8f0c91ce2329 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Tue, 20 May 2014 13:52:13 +0200 Subject: net: doc: Update references to skb->rxhash In commit 61b905da33 ("net: Rename skb->rxhash to skb->hash"), skb->rxhash was renamed to skb->hash. Update references in Documentation accordingly. Signed-off-by: Tobias Klauser Acked-by: Daniel Borkmann Signed-off-by: David S. Miller --- Documentation/networking/filter.txt | 2 +- Documentation/networking/packet_mmap.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/networking/filter.txt b/Documentation/networking/filter.txt index 81f940f4e884..e3ba753cb714 100644 --- a/Documentation/networking/filter.txt +++ b/Documentation/networking/filter.txt @@ -277,7 +277,7 @@ Possible BPF extensions are shown in the following table: mark skb->mark queue skb->queue_mapping hatype skb->dev->type - rxhash skb->rxhash + rxhash skb->hash cpu raw_smp_processor_id() vlan_tci vlan_tx_tag_get(skb) vlan_pr vlan_tx_tag_present(skb) diff --git a/Documentation/networking/packet_mmap.txt b/Documentation/networking/packet_mmap.txt index 6fea79efb4cb..38112d512f47 100644 --- a/Documentation/networking/packet_mmap.txt +++ b/Documentation/networking/packet_mmap.txt @@ -578,7 +578,7 @@ processes. This also works in combination with mmap(2) on packet sockets. Currently implemented fanout policies are: - - PACKET_FANOUT_HASH: schedule to socket by skb's rxhash + - PACKET_FANOUT_HASH: schedule to socket by skb's packet hash - PACKET_FANOUT_LB: schedule to socket by round-robin - PACKET_FANOUT_CPU: schedule to socket by CPU packet arrives on - PACKET_FANOUT_RND: schedule to socket by random selection -- cgit v1.2.3 From d6b694c0b3f20c3ee54d29d4109fa1978d11a033 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Wed, 21 May 2014 11:24:39 -0400 Subject: bonding: Don't assume 802.1Q when sending alb learning packets. TLB/ALB learning packets always assume 802.1Q vlan protocol, but that is no longer the case since we now have support for Q-in-Q on top of bonding. Pass the vlan protocol to alb_send_lp_vid() so that the packets are properly tagged. CC: Jay Vosburgh CC: Veaceslav Falico CC: Andy Gospodarek Signed-off-by: Vlad Yasevich Acked-by: Veaceslav Falico Signed-off-by: David S. Miller --- drivers/net/bonding/bond_alb.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index e53847884319..2ec945c3b9ba 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -995,7 +995,7 @@ static void rlb_clear_vlan(struct bonding *bond, unsigned short vlan_id) /*********************** tlb/rlb shared functions *********************/ static void alb_send_lp_vid(struct slave *slave, u8 mac_addr[], - u16 vid) + __be16 vlan_proto, u16 vid) { struct learning_pkt pkt; struct sk_buff *skb; @@ -1021,7 +1021,7 @@ static void alb_send_lp_vid(struct slave *slave, u8 mac_addr[], skb->dev = slave->dev; if (vid) { - skb = vlan_put_tag(skb, htons(ETH_P_8021Q), vid); + skb = vlan_put_tag(skb, vlan_proto, vid); if (!skb) { pr_err("%s: Error: failed to insert VLAN tag\n", slave->bond->dev->name); @@ -1040,13 +1040,14 @@ static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[]) struct list_head *iter; /* send untagged */ - alb_send_lp_vid(slave, mac_addr, 0); + alb_send_lp_vid(slave, mac_addr, 0, 0); /* loop through vlans and send one packet for each */ rcu_read_lock(); netdev_for_each_all_upper_dev_rcu(bond->dev, upper, iter) { if (is_vlan_dev(upper) && vlan_get_encap_level(upper) == 0) alb_send_lp_vid(slave, mac_addr, + vlan_dev_vlan_proto(upper), vlan_dev_vlan_id(upper)); } rcu_read_unlock(); -- cgit v1.2.3 From d0c21d43a5a12aaebb1e42e10cf78e6491fc9e5a Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Wed, 21 May 2014 13:19:48 -0400 Subject: bonding: Send ALB learning packets using the right source ALB learning packets are currentlyalways sent using the slave mac address for all vlans configured on top of bond. This is not always correct, as vlans may change their mac address. This patch introduced a concept of strict matching where the source of learning packets can either strictly match the address passed in, or it can determine a more correct address to use. There are 3 casese to consider: 1) Switchover. In this case, we have a new active slave and we need tell the switch about all addresses available on the slave. 2) Monitor. We'll periodically refresh learning info for all slaves. In this case, we refresh all addresses for current active, and just the slave address for other slaves. 3) Teaching of disabled adddress. This happens as part of the failover and in this case, we alwyas to use just the address provided. CC: Jay Vosburgh CC: Veaceslav Falico CC: Andy Gospodarek Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- drivers/net/bonding/bond_alb.c | 49 ++++++++++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index 2ec945c3b9ba..93580a47cc54 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -82,7 +82,8 @@ static inline struct arp_pkt *arp_pkt(const struct sk_buff *skb) } /* Forward declaration */ -static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[]); +static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[], + bool strict_match); static void rlb_purge_src_ip(struct bonding *bond, struct arp_pkt *arp); static void rlb_src_unlink(struct bonding *bond, u32 index); static void rlb_src_link(struct bonding *bond, u32 ip_src_hash, @@ -459,7 +460,7 @@ static void rlb_teach_disabled_mac_on_primary(struct bonding *bond, u8 addr[]) bond->alb_info.rlb_promisc_timeout_counter = 0; - alb_send_learning_packets(bond->curr_active_slave, addr); + alb_send_learning_packets(bond->curr_active_slave, addr, true); } /* slave being removed should not be active at this point @@ -1032,8 +1033,8 @@ static void alb_send_lp_vid(struct slave *slave, u8 mac_addr[], dev_queue_xmit(skb); } - -static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[]) +static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[], + bool strict_match) { struct bonding *bond = bond_get_bond_by_slave(slave); struct net_device *upper; @@ -1045,10 +1046,19 @@ static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[]) /* loop through vlans and send one packet for each */ rcu_read_lock(); netdev_for_each_all_upper_dev_rcu(bond->dev, upper, iter) { - if (is_vlan_dev(upper) && vlan_get_encap_level(upper) == 0) - alb_send_lp_vid(slave, mac_addr, - vlan_dev_vlan_proto(upper), - vlan_dev_vlan_id(upper)); + if (is_vlan_dev(upper) && vlan_get_encap_level(upper) == 0) { + if (strict_match && + ether_addr_equal_64bits(mac_addr, + upper->dev_addr)) { + alb_send_lp_vid(slave, mac_addr, + vlan_dev_vlan_proto(upper), + vlan_dev_vlan_id(upper)); + } else if (!strict_match) { + alb_send_lp_vid(slave, upper->dev_addr, + vlan_dev_vlan_proto(upper), + vlan_dev_vlan_id(upper)); + } + } } rcu_read_unlock(); } @@ -1108,7 +1118,7 @@ static void alb_fasten_mac_swap(struct bonding *bond, struct slave *slave1, /* fasten the change in the switch */ if (SLAVE_IS_OK(slave1)) { - alb_send_learning_packets(slave1, slave1->dev->dev_addr); + alb_send_learning_packets(slave1, slave1->dev->dev_addr, false); if (bond->alb_info.rlb_enabled) { /* inform the clients that the mac address * has changed @@ -1120,7 +1130,7 @@ static void alb_fasten_mac_swap(struct bonding *bond, struct slave *slave1, } if (SLAVE_IS_OK(slave2)) { - alb_send_learning_packets(slave2, slave2->dev->dev_addr); + alb_send_learning_packets(slave2, slave2->dev->dev_addr, false); if (bond->alb_info.rlb_enabled) { /* inform the clients that the mac address * has changed @@ -1491,6 +1501,8 @@ void bond_alb_monitor(struct work_struct *work) /* send learning packets */ if (bond_info->lp_counter >= BOND_ALB_LP_TICKS(bond)) { + bool strict_match; + /* change of curr_active_slave involves swapping of mac addresses. * in order to avoid this swapping from happening while * sending the learning packets, the curr_slave_lock must be held for @@ -1498,8 +1510,15 @@ void bond_alb_monitor(struct work_struct *work) */ read_lock(&bond->curr_slave_lock); - bond_for_each_slave_rcu(bond, slave, iter) - alb_send_learning_packets(slave, slave->dev->dev_addr); + bond_for_each_slave_rcu(bond, slave, iter) { + /* If updating current_active, use all currently + * user mac addreses (!strict_match). Otherwise, only + * use mac of the slave device. + */ + strict_match = (slave != bond->curr_active_slave); + alb_send_learning_packets(slave, slave->dev->dev_addr, + strict_match); + } read_unlock(&bond->curr_slave_lock); @@ -1722,7 +1741,8 @@ void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave } else { /* set the new_slave to the bond mac address */ alb_set_slave_mac_addr(new_slave, bond->dev->dev_addr); - alb_send_learning_packets(new_slave, bond->dev->dev_addr); + alb_send_learning_packets(new_slave, bond->dev->dev_addr, + false); } write_lock_bh(&bond->curr_slave_lock); @@ -1765,7 +1785,8 @@ int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr) alb_set_slave_mac_addr(bond->curr_active_slave, bond_dev->dev_addr); read_lock(&bond->lock); - alb_send_learning_packets(bond->curr_active_slave, bond_dev->dev_addr); + alb_send_learning_packets(bond->curr_active_slave, + bond_dev->dev_addr, false); if (bond->alb_info.rlb_enabled) { /* inform clients mac address has changed */ rlb_req_update_slave_clients(bond, bond->curr_active_slave); -- cgit v1.2.3 From fbdc0ad095c0a299e9abf5d8ac8f58374951149a Mon Sep 17 00:00:00 2001 From: Li RongQing Date: Thu, 22 May 2014 16:36:55 +0800 Subject: ipv4: initialise the itag variable in __mkroute_input the value of itag is a random value from stack, and may not be initiated by fib_validate_source, which called fib_combine_itag if CONFIG_IP_ROUTE_CLASSID is not set This will make the cached dst uncertainty Signed-off-by: Li RongQing Acked-by: Alexei Starovoitov Signed-off-by: David S. Miller --- 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 db1e0da871f4..5e676be3daeb 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1519,7 +1519,7 @@ static int __mkroute_input(struct sk_buff *skb, struct in_device *out_dev; unsigned int flags = 0; bool do_cache; - u32 itag; + u32 itag = 0; /* get a working reference to the output device */ out_dev = __in_dev_get_rcu(FIB_RES_DEV(*res)); -- cgit v1.2.3 From b6ed5498601df40489606dbc14a9c7011c16630b Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Thu, 22 May 2014 11:57:17 -0700 Subject: batman: fix a bogus warning from batadv_is_on_batman_iface() batman tries to search dev->iflink to check if it's a batman interface, but ->iflink could be 0, which is not a valid ifindex. It should just avoid iflink == 0 case. Reported-by: Jet Chen Tested-by: Jet Chen Cc: David S. Miller Cc: Steffen Klassert Cc: Antonio Quartulli Cc: Marek Lindner Signed-off-by: Cong Wang Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- net/batman-adv/hard-interface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c index b851cc580853..fbda6b54baff 100644 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c @@ -83,7 +83,7 @@ static bool batadv_is_on_batman_iface(const struct net_device *net_dev) return true; /* no more parents..stop recursion */ - if (net_dev->iflink == net_dev->ifindex) + if (net_dev->iflink == 0 || net_dev->iflink == net_dev->ifindex) return false; /* recurse over the parent device */ -- cgit v1.2.3 From 7ea456436ff6563b6cf89d3254ae76a8ceab499b Mon Sep 17 00:00:00 2001 From: Alexey Charkov Date: Tue, 29 Apr 2014 23:42:00 +0400 Subject: pinctrl: vt8500: Ensure value reg is updated when setting direction Current code only touches the direction register when setting direction to output, which breaks logic like echo high > /sys/class/gpio/gpio0/direction which is expected to also set the value. This patch also adds a call to update the value register when setting direction to output. Signed-off-by: Alexey Charkov Acked-by: Tony Prisk Signed-off-by: Linus Walleij --- drivers/pinctrl/vt8500/pinctrl-wmt.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/drivers/pinctrl/vt8500/pinctrl-wmt.c b/drivers/pinctrl/vt8500/pinctrl-wmt.c index 9802b67040cc..2c61281bebd7 100644 --- a/drivers/pinctrl/vt8500/pinctrl-wmt.c +++ b/drivers/pinctrl/vt8500/pinctrl-wmt.c @@ -523,17 +523,6 @@ static int wmt_gpio_get_direction(struct gpio_chip *chip, unsigned offset) return GPIOF_DIR_IN; } -static int wmt_gpio_direction_input(struct gpio_chip *chip, unsigned offset) -{ - return pinctrl_gpio_direction_input(chip->base + offset); -} - -static int wmt_gpio_direction_output(struct gpio_chip *chip, unsigned offset, - int value) -{ - return pinctrl_gpio_direction_output(chip->base + offset); -} - static int wmt_gpio_get_value(struct gpio_chip *chip, unsigned offset) { struct wmt_pinctrl_data *data = dev_get_drvdata(chip->dev); @@ -568,6 +557,18 @@ static void wmt_gpio_set_value(struct gpio_chip *chip, unsigned offset, wmt_clearbits(data, reg_data_out, BIT(bit)); } +static int wmt_gpio_direction_input(struct gpio_chip *chip, unsigned offset) +{ + return pinctrl_gpio_direction_input(chip->base + offset); +} + +static int wmt_gpio_direction_output(struct gpio_chip *chip, unsigned offset, + int value) +{ + wmt_gpio_set_value(chip, offset, value); + return pinctrl_gpio_direction_output(chip->base + offset); +} + static struct gpio_chip wmt_gpio_chip = { .label = "gpio-wmt", .owner = THIS_MODULE, -- cgit v1.2.3 From 6aa6caff30f5dcb9e55b03b9710c30b83750cae5 Mon Sep 17 00:00:00 2001 From: Joe Lawrence Date: Thu, 22 May 2014 17:30:54 -0400 Subject: [SCSI] scsi_transport_sas: move bsg destructor into sas_rphy_remove The recent change in sysfs, bcdde7e221a8750f9b62b6d0bd31b72ea4ad9309 "sysfs: make __sysfs_remove_dir() recursive" revealed an asymmetric rphy device creation/deletion sequence in scsi_transport_sas: modprobe mpt2sas sas_rphy_add device_add A rphy->dev device_add B sas_device transport class device_add C sas_end_device transport class device_add D bsg class rmmod mpt2sas sas_rphy_delete sas_rphy_remove device_del B device_del C device_del A sysfs_remove_group recursive sysfs dir removal sas_rphy_free device_del D warning where device A is the parent of B, C, and D. When sas_rphy_free tries to unregister the bsg request queue (device D above), the ensuing sysfs cleanup discovers that its sysfs group has already been removed and emits a warning, "sysfs group... not found for kobject 'end_device-X:0'". Since bsg creation is a side effect of sas_rphy_add, move its complementary removal call into sas_rphy_remove. This imposes the following tear-down order for the devices above: D, B, C, A. Note the sas_device and sas_end_device transport class devices (B and C above) are created and destroyed both via the list match traversal in attribute_container_device_trigger, so the order in which they are handled is fixed. This is fine as long as they are deleted before their parent device. Signed-off-by: Joe Lawrence Acked-by: Dan Williams Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_sas.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index 1b681427dde0..c341f855fadc 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -1621,8 +1621,6 @@ void sas_rphy_free(struct sas_rphy *rphy) list_del(&rphy->list); mutex_unlock(&sas_host->lock); - sas_bsg_remove(shost, rphy); - transport_destroy_device(dev); put_device(dev); @@ -1681,6 +1679,7 @@ sas_rphy_remove(struct sas_rphy *rphy) } sas_rphy_unlink(rphy); + sas_bsg_remove(NULL, rphy); transport_remove_device(dev); device_del(dev); } -- cgit v1.2.3 From 41ca86e8502952116234fa558f4277092a5aaae9 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 22 May 2014 23:19:00 +0200 Subject: MIPS: Fix branch emulation of branch likely instructions. Two issues: o For beql_op, beql_op, bne_op, bnel_op, blez_op, blezl_op, bgtz_op and bgtzl_op the wrong field was being checked for the instruction opcode. o For blez_op / blezl_op and bgtz_op / bgtzl_op the test was testing for the wrong opcode. This bug got introduced by d8d4e3ae0b5c179c0bfd3f0af5b352d13bea9cfa [MIPS Kprobes: Refactor branch emulation]. Signed-off-by: Ralf Baechle Acked-by: Leonid Yegoshin Acked-by: Victor Kamensky --- arch/mips/kernel/branch.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c index 4d78bf445a9c..76122ff5cb5e 100644 --- a/arch/mips/kernel/branch.c +++ b/arch/mips/kernel/branch.c @@ -317,7 +317,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs, if (regs->regs[insn.i_format.rs] == regs->regs[insn.i_format.rt]) { epc = epc + 4 + (insn.i_format.simmediate << 2); - if (insn.i_format.rt == beql_op) + if (insn.i_format.opcode == beql_op) ret = BRANCH_LIKELY_TAKEN; } else epc += 8; @@ -329,7 +329,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs, if (regs->regs[insn.i_format.rs] != regs->regs[insn.i_format.rt]) { epc = epc + 4 + (insn.i_format.simmediate << 2); - if (insn.i_format.rt == bnel_op) + if (insn.i_format.opcode == bnel_op) ret = BRANCH_LIKELY_TAKEN; } else epc += 8; @@ -341,7 +341,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs, /* rt field assumed to be zero */ if ((long)regs->regs[insn.i_format.rs] <= 0) { epc = epc + 4 + (insn.i_format.simmediate << 2); - if (insn.i_format.rt == bnel_op) + if (insn.i_format.opcode == blezl_op) ret = BRANCH_LIKELY_TAKEN; } else epc += 8; @@ -353,7 +353,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs, /* rt field assumed to be zero */ if ((long)regs->regs[insn.i_format.rs] > 0) { epc = epc + 4 + (insn.i_format.simmediate << 2); - if (insn.i_format.rt == bnel_op) + if (insn.i_format.opcode == bgtzl_op) ret = BRANCH_LIKELY_TAKEN; } else epc += 8; -- cgit v1.2.3 From 77f07800cb456bed6e5c345e6e4e83e8eda62437 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 23 May 2014 09:02:44 +0200 Subject: ALSA: hda - Fix onboard audio on Intel H97/Z97 chipsets The recent Intel H97/Z97 chipsets need the similar setups like other Intel chipsets for snooping, etc. Especially without snooping, the audio playback stutters or gets corrupted. This fix patch just adds the corresponding PCI ID entry with the proper flags. Reported-and-tested-by: Arthur Borsboom Cc: Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 2c54629d62d1..6cc3cf285558 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -1743,6 +1743,9 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { /* Lynx Point */ { PCI_DEVICE(0x8086, 0x8c20), .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, + /* 9 Series */ + { PCI_DEVICE(0x8086, 0x8ca0), + .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, /* Wellsburg */ { PCI_DEVICE(0x8086, 0x8d20), .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, -- cgit v1.2.3 From 6cf12869f5c1a837f18af5f8b2308fa243772735 Mon Sep 17 00:00:00 2001 From: Nathaniel Wesley Filardo Date: Wed, 21 May 2014 16:04:11 +0100 Subject: AFS: Part of afs_end_call() is identical to code elsewhere, so split it Split afs_end_call() into two pieces, one of which is identical to code in afs_process_async_call(). Replace the latter with a call to the first part of afs_end_call(). Signed-off-by: Nathaniel Wesley Filardo Signed-off-by: David Howells --- fs/afs/rxrpc.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c index 9226a6674d7f..1a1110b1a7ff 100644 --- a/fs/afs/rxrpc.c +++ b/fs/afs/rxrpc.c @@ -184,15 +184,24 @@ static void afs_free_call(struct afs_call *call) } /* - * End a call + * End a call but do not free it */ -static void afs_end_call(struct afs_call *call) +static void afs_end_call_nofree(struct afs_call *call) { if (call->rxcall) { rxrpc_kernel_end_call(call->rxcall); call->rxcall = NULL; } - call->type->destructor(call); + if (call->type->destructor) + call->type->destructor(call); +} + +/* + * End a call and free it + */ +static void afs_end_call(struct afs_call *call) +{ + afs_end_call_nofree(call); afs_free_call(call); } @@ -640,10 +649,7 @@ static void afs_process_async_call(struct work_struct *work) call->reply = NULL; /* kill the call */ - rxrpc_kernel_end_call(call->rxcall); - call->rxcall = NULL; - if (call->type->destructor) - call->type->destructor(call); + afs_end_call_nofree(call); /* we can't just delete the call because the work item may be * queued */ -- cgit v1.2.3 From 150a6b478982475c60fa25b7060ab990ece5483d Mon Sep 17 00:00:00 2001 From: Nathaniel Wesley Filardo Date: Wed, 21 May 2014 14:58:26 +0100 Subject: AFS: Fix kafs module unloading At present, it is not possible to successfully unload the kafs module if there are outstanding async outgoing calls (those made with afs_make_call()). This appears to be due to the changes introduced by: commit 059499453a9abd1857d442b44da8b4c126dc72a8 Author: Tejun Heo Date: Fri Mar 7 10:24:50 2014 -0500 Subject: afs: don't use PREPARE_WORK which didn't go far enough. The problem is due to: (1) The aforementioned commit introduced a separate handler function pointer in the call, call->async_workfn, in addition to the original workqueue item, call->async_work, for asynchronous operations because workqueues subsystem cannot handle the workqueue item pointer being changed whilst the item is queued or being processed. (2) afs_async_workfn() was introduced in that commit to be the callback for call->async_work. Its sole purpose is to run whatever call->async_workfn points to. (3) call->async_workfn is only used from afs_async_workfn(), which is only set on async_work by afs_collect_incoming_call() - ie. for incoming calls. (4) call->async_workfn is *not* set by afs_make_call() when outgoing calls are made, and call->async_work is set afs_process_async_call() - and not afs_async_workfn(). (5) afs_process_async_call() now changes call->async_workfn rather than call->async_work to point to afs_delete_async_call() to clean up, but this is only effective for incoming calls because call->async_work does not point to afs_async_workfn() for outgoing calls. (6) Because, for incoming calls, call->async_work remains pointing to afs_process_async_call() this results in an infinite loop. Instead, make the workqueue uniformly vector through call->async_workfn, via afs_async_workfn() and simply initialise call->async_workfn to point to afs_process_async_call() in afs_make_call(). Signed-off-by: Nathaniel Wesley Filardo Signed-off-by: David Howells Reviewed-by: Tejun Heo --- fs/afs/rxrpc.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c index 1a1110b1a7ff..5a05014ea7b0 100644 --- a/fs/afs/rxrpc.c +++ b/fs/afs/rxrpc.c @@ -58,6 +58,13 @@ static void afs_collect_incoming_call(struct work_struct *); static struct sk_buff_head afs_incoming_calls; static DECLARE_WORK(afs_collect_incoming_call_work, afs_collect_incoming_call); +static void afs_async_workfn(struct work_struct *work) +{ + struct afs_call *call = container_of(work, struct afs_call, async_work); + + call->async_workfn(work); +} + /* * open an RxRPC socket and bind it to be a server for callback notifications * - the socket is left in blocking mode and non-blocking ops use MSG_DONTWAIT @@ -348,7 +355,8 @@ int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp, atomic_read(&afs_outstanding_calls)); call->wait_mode = wait_mode; - INIT_WORK(&call->async_work, afs_process_async_call); + call->async_workfn = afs_process_async_call; + INIT_WORK(&call->async_work, afs_async_workfn); memset(&srx, 0, sizeof(srx)); srx.srx_family = AF_RXRPC; @@ -672,13 +680,6 @@ void afs_transfer_reply(struct afs_call *call, struct sk_buff *skb) call->reply_size += len; } -static void afs_async_workfn(struct work_struct *work) -{ - struct afs_call *call = container_of(work, struct afs_call, async_work); - - call->async_workfn(work); -} - /* * accept the backlog of incoming calls */ -- cgit v1.2.3 From 656f88ddf1ec3abf2cd20b8b4028c44e8e95f56d Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 21 May 2014 15:55:26 +0100 Subject: AFS: Pass an afs_call* to call->async_workfn() instead of a work_struct* call->async_workfn() can take an afs_call* arg rather than a work_struct* as the functions assigned there are now called from afs_async_workfn() which has to call container_of() anyway. Signed-off-by: David Howells Reviewed-by: Nathaniel Wesley Filardo Reviewed-by: Tejun Heo --- fs/afs/internal.h | 2 +- fs/afs/rxrpc.c | 14 ++++---------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/fs/afs/internal.h b/fs/afs/internal.h index be75b500005d..590b55f46d61 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h @@ -75,7 +75,7 @@ struct afs_call { const struct afs_call_type *type; /* type of call */ const struct afs_wait_mode *wait_mode; /* completion wait mode */ wait_queue_head_t waitq; /* processes awaiting completion */ - work_func_t async_workfn; + void (*async_workfn)(struct afs_call *call); /* asynchronous work function */ struct work_struct async_work; /* asynchronous work processor */ struct work_struct work; /* actual work processor */ struct sk_buff_head rx_queue; /* received packets */ diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c index 5a05014ea7b0..03a3beb17004 100644 --- a/fs/afs/rxrpc.c +++ b/fs/afs/rxrpc.c @@ -25,7 +25,7 @@ static void afs_wake_up_call_waiter(struct afs_call *); static int afs_wait_for_call_to_complete(struct afs_call *); static void afs_wake_up_async_call(struct afs_call *); static int afs_dont_wait_for_call_to_complete(struct afs_call *); -static void afs_process_async_call(struct work_struct *); +static void afs_process_async_call(struct afs_call *); static void afs_rx_interceptor(struct sock *, unsigned long, struct sk_buff *); static int afs_deliver_cm_op_id(struct afs_call *, struct sk_buff *, bool); @@ -62,7 +62,7 @@ static void afs_async_workfn(struct work_struct *work) { struct afs_call *call = container_of(work, struct afs_call, async_work); - call->async_workfn(work); + call->async_workfn(call); } /* @@ -623,11 +623,8 @@ static int afs_dont_wait_for_call_to_complete(struct afs_call *call) /* * delete an asynchronous call */ -static void afs_delete_async_call(struct work_struct *work) +static void afs_delete_async_call(struct afs_call *call) { - struct afs_call *call = - container_of(work, struct afs_call, async_work); - _enter(""); afs_free_call(call); @@ -640,11 +637,8 @@ static void afs_delete_async_call(struct work_struct *work) * - on a multiple-thread workqueue this work item may try to run on several * CPUs at the same time */ -static void afs_process_async_call(struct work_struct *work) +static void afs_process_async_call(struct afs_call *call) { - struct afs_call *call = - container_of(work, struct afs_call, async_work); - _enter(""); if (!skb_queue_empty(&call->rx_queue)) -- cgit v1.2.3 From 9abd09acd664c68f06242da191209d9c70df6953 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 May 2014 09:23:51 -0700 Subject: parisc: 'renameat2()' doesn't need (or have) a separate compat system call The 'renameat2()' system call was incorrectly added as a ENTRY_COMP() in the parisc system call table by commit 18e480aa07f78 ("parisc: add renameat2 syscall"). That causes a link-time error due to there not being any compat version of that system call: arch/parisc/kernel/built-in.o: In function `sys_call_table': (.rodata+0xad0): undefined reference to `compat_sys_renameat2' make: *** [vmlinux] Error 1 Easily fixed by marking the system call as being the same for compat as for native by using ENTRY_SAME() instead of ENTRY_COMP(). Reported-by: Guenter Roeck Acked-by: Miklos Szeredi Acked-by: Helge Deller Signed-off-by: Linus Torvalds --- arch/parisc/kernel/syscall_table.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S index f1432da7b4c0..c5fa7a697fba 100644 --- a/arch/parisc/kernel/syscall_table.S +++ b/arch/parisc/kernel/syscall_table.S @@ -432,7 +432,7 @@ ENTRY_SAME(sched_setattr) ENTRY_SAME(sched_getattr) /* 335 */ ENTRY_COMP(utimes) - ENTRY_COMP(renameat2) + ENTRY_SAME(renameat2) /* Nothing yet */ -- cgit v1.2.3 From b985194c8c0a130ed155b71662e39f7eaea4876f Mon Sep 17 00:00:00 2001 From: Chen Yucong Date: Thu, 22 May 2014 11:54:15 -0700 Subject: hwpoison, hugetlb: lock_page/unlock_page does not match for handling a free hugepage For handling a free hugepage in memory failure, the race will happen if another thread hwpoisoned this hugepage concurrently. So we need to check PageHWPoison instead of !PageHWPoison. If hwpoison_filter(p) returns true or a race happens, then we need to unlock_page(hpage). Signed-off-by: Chen Yucong Reviewed-by: Naoya Horiguchi Tested-by: Naoya Horiguchi Reviewed-by: Andi Kleen Cc: [2.6.36+] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memory-failure.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/mm/memory-failure.c b/mm/memory-failure.c index 35ef28acf137..dbf8922216ad 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -1081,15 +1081,16 @@ int memory_failure(unsigned long pfn, int trapno, int flags) return 0; } else if (PageHuge(hpage)) { /* - * Check "just unpoisoned", "filter hit", and - * "race with other subpage." + * Check "filter hit" and "race with other subpage." */ lock_page(hpage); - if (!PageHWPoison(hpage) - || (hwpoison_filter(p) && TestClearPageHWPoison(p)) - || (p != hpage && TestSetPageHWPoison(hpage))) { - atomic_long_sub(nr_pages, &num_poisoned_pages); - return 0; + if (PageHWPoison(hpage)) { + if ((hwpoison_filter(p) && TestClearPageHWPoison(p)) + || (p != hpage && TestSetPageHWPoison(hpage))) { + atomic_long_sub(nr_pages, &num_poisoned_pages); + unlock_page(hpage); + return 0; + } } set_page_hwpoison_huge_page(hpage); res = dequeue_hwpoisoned_huge_page(hpage); -- cgit v1.2.3 From 7fcbbaf18392f0b17c95e2f033c8ccf87eecde1d Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 22 May 2014 11:54:16 -0700 Subject: mm/filemap.c: avoid always dirtying mapping->flags on O_DIRECT In some testing I ran today (some fio jobs that spread over two nodes), we end up spending 40% of the time in filemap_check_errors(). That smells fishy. Looking further, this is basically what happens: blkdev_aio_read() generic_file_aio_read() filemap_write_and_wait_range() if (!mapping->nr_pages) filemap_check_errors() and filemap_check_errors() always attempts two test_and_clear_bit() on the mapping flags, thus dirtying it for every single invocation. The patch below tests each of these bits before clearing them, avoiding this issue. In my test case (4-socket box), performance went from 1.7M IOPS to 4.0M IOPS. Signed-off-by: Jens Axboe Acked-by: Jeff Moyer Cc: Al Viro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/filemap.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mm/filemap.c b/mm/filemap.c index 000a220e2a41..088358c8006b 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -257,9 +257,11 @@ static int filemap_check_errors(struct address_space *mapping) { int ret = 0; /* Check for outstanding write errors */ - if (test_and_clear_bit(AS_ENOSPC, &mapping->flags)) + if (test_bit(AS_ENOSPC, &mapping->flags) && + test_and_clear_bit(AS_ENOSPC, &mapping->flags)) ret = -ENOSPC; - if (test_and_clear_bit(AS_EIO, &mapping->flags)) + if (test_bit(AS_EIO, &mapping->flags) && + test_and_clear_bit(AS_EIO, &mapping->flags)) ret = -EIO; return ret; } -- cgit v1.2.3 From 55231e5c898c5c03c14194001e349f40f59bd300 Mon Sep 17 00:00:00 2001 From: Johannes Weiner Date: Thu, 22 May 2014 11:54:17 -0700 Subject: mm: madvise: fix MADV_WILLNEED on shmem swapouts MADV_WILLNEED currently does not read swapped out shmem pages back in. Commit 0cd6144aadd2 ("mm + fs: prepare for non-page entries in page cache radix trees") made find_get_page() filter exceptional radix tree entries but failed to convert all find_get_page() callers that WANT exceptional entries over to find_get_entry(). One of them is shmem swap readahead in madvise, which now skips over any swap-out records. Convert it to find_get_entry(). Fixes: 0cd6144aadd2 ("mm + fs: prepare for non-page entries in page cache radix trees") Signed-off-by: Johannes Weiner Reported-by: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/madvise.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/madvise.c b/mm/madvise.c index 539eeb96b323..a402f8fdc68e 100644 --- a/mm/madvise.c +++ b/mm/madvise.c @@ -195,7 +195,7 @@ static void force_shm_swapin_readahead(struct vm_area_struct *vma, for (; start < end; start += PAGE_SIZE) { index = ((start - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff; - page = find_get_page(mapping, index); + page = find_get_entry(mapping, index); if (!radix_tree_exceptional_entry(page)) { if (page) page_cache_release(page); -- cgit v1.2.3 From 6f6acb00514c10be35529402f36ad7a288f08c2e Mon Sep 17 00:00:00 2001 From: Michal Hocko Date: Thu, 22 May 2014 11:54:19 -0700 Subject: memcg: fix swapcache charge from kernel thread context Commit 284f39afeaa4 ("mm: memcg: push !mm handling out to page cache charge function") explicitly checks for page cache charges without any mm context (from kernel thread context[1]). This seemed to be the only possible case where memory could be charged without mm context so commit 03583f1a631c ("memcg: remove unnecessary !mm check from try_get_mem_cgroup_from_mm()") removed the mm check from get_mem_cgroup_from_mm(). This however caused another NULL ptr dereference during early boot when loopback kernel thread splices to tmpfs as reported by Stephan Kulow: BUG: unable to handle kernel NULL pointer dereference at 0000000000000360 IP: get_mem_cgroup_from_mm.isra.42+0x2b/0x60 Oops: 0000 [#1] SMP Modules linked in: btrfs dm_multipath dm_mod scsi_dh multipath raid10 raid456 async_raid6_recov async_memcpy async_pq raid6_pq async_xor xor async_tx raid1 raid0 md_mod parport_pc parport nls_utf8 isofs usb_storage iscsi_ibft iscsi_boot_sysfs arc4 ecb fan thermal nfs lockd fscache nls_iso8859_1 nls_cp437 sg st hid_generic usbhid af_packet sunrpc sr_mod cdrom ata_generic uhci_hcd virtio_net virtio_blk ehci_hcd usbcore ata_piix floppy processor button usb_common virtio_pci virtio_ring virtio edd squashfs loop ppa] CPU: 0 PID: 97 Comm: loop1 Not tainted 3.15.0-rc5-5-default #1 Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011 Call Trace: __mem_cgroup_try_charge_swapin+0x40/0xe0 mem_cgroup_charge_file+0x8b/0xd0 shmem_getpage_gfp+0x66b/0x7b0 shmem_file_splice_read+0x18f/0x430 splice_direct_to_actor+0xa2/0x1c0 do_lo_receive+0x5a/0x60 [loop] loop_thread+0x298/0x720 [loop] kthread+0xc6/0xe0 ret_from_fork+0x7c/0xb0 Also Branimir Maksimovic reported the following oops which is tiggered for the swapcache charge path from the accounting code for kernel threads: CPU: 1 PID: 160 Comm: kworker/u8:5 Tainted: P OE 3.15.0-rc5-core2-custom #159 Hardware name: System manufacturer System Product Name/MAXIMUSV GENE, BIOS 1903 08/19/2013 task: ffff880404e349b0 ti: ffff88040486a000 task.ti: ffff88040486a000 RIP: get_mem_cgroup_from_mm.isra.42+0x2b/0x60 Call Trace: __mem_cgroup_try_charge_swapin+0x45/0xf0 mem_cgroup_charge_file+0x9c/0xe0 shmem_getpage_gfp+0x62c/0x770 shmem_write_begin+0x38/0x40 generic_perform_write+0xc5/0x1c0 __generic_file_aio_write+0x1d1/0x3f0 generic_file_aio_write+0x4f/0xc0 do_sync_write+0x5a/0x90 do_acct_process+0x4b1/0x550 acct_process+0x6d/0xa0 do_exit+0x827/0xa70 kthread+0xc3/0xf0 This patch fixes the issue by reintroducing mm check into get_mem_cgroup_from_mm. We could do the same trick in __mem_cgroup_try_charge_swapin as we do for the regular page cache path but it is not worth troubles. The check is not that expensive and it is better to have get_mem_cgroup_from_mm more robust. [1] - http://marc.info/?l=linux-mm&m=139463617808941&w=2 Fixes: 03583f1a631c ("memcg: remove unnecessary !mm check from try_get_mem_cgroup_from_mm()") Reported-and-tested-by: Stephan Kulow Reported-by: Branimir Maksimovic Signed-off-by: Michal Hocko Acked-by: Johannes Weiner Cc: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memcontrol.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index c47dffdcb246..5177c6d4a2dd 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -1077,9 +1077,18 @@ static struct mem_cgroup *get_mem_cgroup_from_mm(struct mm_struct *mm) rcu_read_lock(); do { - memcg = mem_cgroup_from_task(rcu_dereference(mm->owner)); - if (unlikely(!memcg)) + /* + * Page cache insertions can happen withou an + * actual mm context, e.g. during disk probing + * on boot, loopback IO, acct() writes etc. + */ + if (unlikely(!mm)) memcg = root_mem_cgroup; + else { + memcg = mem_cgroup_from_task(rcu_dereference(mm->owner)); + if (unlikely(!memcg)) + memcg = root_mem_cgroup; + } } while (!css_tryget(&memcg->css)); rcu_read_unlock(); return memcg; @@ -3958,17 +3967,9 @@ int mem_cgroup_charge_file(struct page *page, struct mm_struct *mm, return 0; } - /* - * Page cache insertions can happen without an actual mm - * context, e.g. during disk probing on boot. - */ - if (unlikely(!mm)) - memcg = root_mem_cgroup; - else { - memcg = mem_cgroup_try_charge_mm(mm, gfp_mask, 1, true); - if (!memcg) - return -ENOMEM; - } + memcg = mem_cgroup_try_charge_mm(mm, gfp_mask, 1, true); + if (!memcg) + return -ENOMEM; __mem_cgroup_commit_charge(memcg, page, 1, type, false); return 0; } -- cgit v1.2.3 From ad0f614e4723db8cead439cf414108cbf975b224 Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Thu, 22 May 2014 11:54:20 -0700 Subject: wait: swap EXIT_ZOMBIE(Z) and EXIT_DEAD(X) chars in TASK_STATE_TO_CHAR_STR In commit ad86622b478e ("wait: swap EXIT_ZOMBIE and EXIT_DEAD to hide EXIT_TRACE from user-space") the order of task state definitions were changed: EXIT_DEAD and EXIT_ZOMBIE were swapped. Though the charterers for the states in TASK_STATE_TO_CHAR_STR string were not updated. This patch synchronizes the string to the order of definitions. Signed-off-by: Masatake YAMATO Cc: Oleg Nesterov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/sched.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index 25f54c79f757..21fbdae61b9e 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -220,7 +220,7 @@ print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq); #define TASK_PARKED 512 #define TASK_STATE_MAX 1024 -#define TASK_STATE_TO_CHAR_STR "RSDTtZXxKWP" +#define TASK_STATE_TO_CHAR_STR "RSDTtXZxKWP" extern char ___assert_task_state[1 - 2*!!( sizeof(TASK_STATE_TO_CHAR_STR)-1 != ilog2(TASK_STATE_MAX)+1)]; -- cgit v1.2.3 From 3e030ecc0fc7de10fd0da10c1c19939872a31717 Mon Sep 17 00:00:00 2001 From: Naoya Horiguchi Date: Thu, 22 May 2014 11:54:21 -0700 Subject: mm/memory-failure.c: fix memory leak by race between poison and unpoison When a memory error happens on an in-use page or (free and in-use) hugepage, the victim page is isolated with its refcount set to one. When you try to unpoison it later, unpoison_memory() calls put_page() for it twice in order to bring the page back to free page pool (buddy or free hugepage list). However, if another memory error occurs on the page which we are unpoisoning, memory_failure() returns without releasing the refcount which was incremented in the same call at first, which results in memory leak and unconsistent num_poisoned_pages statistics. This patch fixes it. Signed-off-by: Naoya Horiguchi Cc: Andi Kleen Cc: [2.6.32+] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memory-failure.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mm/memory-failure.c b/mm/memory-failure.c index dbf8922216ad..9ccef39a9de2 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -1153,6 +1153,8 @@ int memory_failure(unsigned long pfn, int trapno, int flags) */ if (!PageHWPoison(p)) { printk(KERN_ERR "MCE %#lx: just unpoisoned\n", pfn); + atomic_long_sub(nr_pages, &num_poisoned_pages); + put_page(hpage); res = 0; goto out; } -- cgit v1.2.3 From 66db6cfd49825f4e3462ceee3bcbb292d57da6fb Mon Sep 17 00:00:00 2001 From: Joseph Qi Date: Thu, 22 May 2014 11:54:22 -0700 Subject: ocfs2: fix double kmem_cache_destroy in dlm_init In dlm_init, if create dlm_lockname_cache failed in dlm_init_master_caches, it will destroy dlm_lockres_cache which created before twice. And this will cause system die when loading modules. Signed-off-by: Joseph Qi Cc: Mark Fasheh Cc: Joel Becker Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ocfs2/dlm/dlmmaster.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c index af3f7aa73e13..ee1f88419cb0 100644 --- a/fs/ocfs2/dlm/dlmmaster.c +++ b/fs/ocfs2/dlm/dlmmaster.c @@ -472,11 +472,15 @@ bail: void dlm_destroy_master_caches(void) { - if (dlm_lockname_cache) + if (dlm_lockname_cache) { kmem_cache_destroy(dlm_lockname_cache); + dlm_lockname_cache = NULL; + } - if (dlm_lockres_cache) + if (dlm_lockres_cache) { kmem_cache_destroy(dlm_lockres_cache); + dlm_lockres_cache = NULL; + } } static void dlm_lockres_release(struct kref *kref) -- cgit v1.2.3 From e60cbeedc48d80689c249ab5dcc3c31ad0452dea Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 22 May 2014 11:54:23 -0700 Subject: Documentation: fix DOCBOOKS=... building Prior to commit 4266129964b8 ("[media] DocBook: Move all media docbook stuff into its own directory") it was possible to build only a single (or more) book(s) by calling, for example make htmldocs DOCBOOKS=80211.xml This now fails: cp: target `.../Documentation/DocBook//media_api' is not a directory Ignore errors from that copy to make this possible again. Fixes: 4266129964b8 ("[media] DocBook: Move all media docbook stuff into its own directory") Signed-off-by: Johannes Berg Acked-by: Randy Dunlap Cc: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/DocBook/media/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/DocBook/media/Makefile b/Documentation/DocBook/media/Makefile index f9fd615427fb..1d27f0a1abd1 100644 --- a/Documentation/DocBook/media/Makefile +++ b/Documentation/DocBook/media/Makefile @@ -195,7 +195,7 @@ DVB_DOCUMENTED = \ # install_media_images = \ - $(Q)cp $(OBJIMGFILES) $(MEDIA_SRC_DIR)/v4l/*.svg $(MEDIA_OBJ_DIR)/media_api + $(Q)-cp $(OBJIMGFILES) $(MEDIA_SRC_DIR)/v4l/*.svg $(MEDIA_OBJ_DIR)/media_api $(MEDIA_OBJ_DIR)/%: $(MEDIA_SRC_DIR)/%.b64 $(Q)base64 -d $< >$@ -- cgit v1.2.3 From 0d9327ab70038ac8c7af6e20456578ab80158f2d Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Thu, 22 May 2014 11:54:24 -0700 Subject: MAINTAINERS: add closing angle bracket to Vince Bridgers' email address Signed-off-by: Tobias Klauser Cc: Vince Bridgers Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 6846c7c622e3..c47d2683bd6b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -537,7 +537,7 @@ L: linux-alpha@vger.kernel.org F: arch/alpha/ ALTERA TRIPLE SPEED ETHERNET DRIVER -M: Vince Bridgers L: netdev@vger.kernel.org L: nios2-dev@lists.rocketboards.org (moderated for non-subscribers) S: Maintained -- cgit v1.2.3 From 3aae97c8b1dbefb23217d193e2818d1490651c95 Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Fri, 23 May 2014 09:23:32 +0900 Subject: ARM: trusted_foundations: fix compile error on non-SMP The setup_max_cpus variable is only defined if CONFIG_SMP is set. Add a preprocessor condition to avoid the following compilation error if CONFIG_SMP is not set: arch/arm/include/asm/trusted_foundations.h: In function 'register_trusted_foundations': arch/arm/include/asm/trusted_foundations.h:57:2: error: 'setup_max_cpus' undeclared (first use in this function) Signed-off-by: Alexandre Courbot Reported-by: Russell King Acked-by: Stephen Warren Signed-off-by: Arnd Bergmann --- arch/arm/include/asm/trusted_foundations.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/include/asm/trusted_foundations.h b/arch/arm/include/asm/trusted_foundations.h index b5f7705abcb0..624e1d436c6c 100644 --- a/arch/arm/include/asm/trusted_foundations.h +++ b/arch/arm/include/asm/trusted_foundations.h @@ -54,7 +54,9 @@ static inline void register_trusted_foundations( */ pr_err("No support for Trusted Foundations, continuing in degraded mode.\n"); pr_err("Secondary processors as well as CPU PM will be disabled.\n"); +#if IS_ENABLED(CONFIG_SMP) setup_max_cpus = 0; +#endif cpu_idle_poll_ctrl(true); } -- cgit v1.2.3 From fe52e7505f8bf365d5ab0eeee19ababe406cbaaf Mon Sep 17 00:00:00 2001 From: Maxime COQUELIN Date: Wed, 7 May 2014 18:48:52 +0200 Subject: clk: divider: Fix table round up function Commit 1d9fe6b97 ("clk: divider: Fix best div calculation for power-of-two and table dividers") introduces a regression in its _table_round_up function. When the divider passed to this function is greater than the max divider available in the table, this function returns table's max divider. Problem is that it causes an infinite loop in clk_divider_bestdiv() because _next_div() will never return a value greater than maxdiv. Instead of returning table's max divider, this patch returns INT_MAX. Reported-by: Fabio Estevam Reported-by: Shawn Guo Tested-by: Fabio Estevam Tested-by: Shawn Guo Signed-off-by: Maxime Coquelin Signed-off-by: Mike Turquette --- drivers/clk/clk-divider.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index 4637697c139f..3fbee4540228 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -147,7 +147,7 @@ static bool _is_valid_div(struct clk_divider *divider, unsigned int div) static int _round_up_table(const struct clk_div_table *table, int div) { const struct clk_div_table *clkt; - int up = _get_table_maxdiv(table); + int up = INT_MAX; for (clkt = table; clkt->div; clkt++) { if (clkt->div == div) -- cgit v1.2.3 From 72b1c2c3a4de8891b06df18da95514d69eae65de Mon Sep 17 00:00:00 2001 From: Valentin Ilie Date: Tue, 22 Apr 2014 16:15:54 +0300 Subject: clk: st: Fix memory leak When it fails to allocate div, gate should be free'd before return Signed-off-by: Valentin Ilie Signed-off-by: Mike Turquette --- drivers/clk/st/clkgen-pll.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/clk/st/clkgen-pll.c b/drivers/clk/st/clkgen-pll.c index bca0a0badbfa..a886702f7c8b 100644 --- a/drivers/clk/st/clkgen-pll.c +++ b/drivers/clk/st/clkgen-pll.c @@ -521,8 +521,10 @@ static struct clk * __init clkgen_odf_register(const char *parent_name, gate->lock = odf_lock; div = kzalloc(sizeof(*div), GFP_KERNEL); - if (!div) + if (!div) { + kfree(gate); return ERR_PTR(-ENOMEM); + } div->flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO; div->reg = reg + pll_data->odf[odf].offset; -- cgit v1.2.3 From defb79f08630f4d1944c75ad0070026d0f534fda Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Sun, 25 May 2014 10:00:36 +0800 Subject: MIPS: Fix inconsistancy of __NR_Linux_syscalls value Originally, __NR_O32_Linux_syscalls, __NR_N32_Linux_syscalls and __NR_64_Linux_syscalls have the same values as __NR_Linux_syscalls in corresponding ABIs. But after commit 367f0b50e502d (MIPS: Wire up renameat2 syscall) they are not the same. I think this is incorrect and need a fix. Signed-off-by: Huacai Chen Cc: John Crispin Cc: Steven J. Hill Cc: Aurelien Jarno Cc: linux-mips@linux-mips.org Cc: Fuxin Zhang Cc: Zhangjin Wu Patchwork: https://patchwork.linux-mips.org/patch/6987/ Signed-off-by: Ralf Baechle --- arch/mips/include/uapi/asm/unistd.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/mips/include/uapi/asm/unistd.h b/arch/mips/include/uapi/asm/unistd.h index 2692abb28e36..5805414777e0 100644 --- a/arch/mips/include/uapi/asm/unistd.h +++ b/arch/mips/include/uapi/asm/unistd.h @@ -381,7 +381,7 @@ #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */ #define __NR_O32_Linux 4000 -#define __NR_O32_Linux_syscalls 350 +#define __NR_O32_Linux_syscalls 351 #if _MIPS_SIM == _MIPS_SIM_ABI64 @@ -710,7 +710,7 @@ #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */ #define __NR_64_Linux 5000 -#define __NR_64_Linux_syscalls 310 +#define __NR_64_Linux_syscalls 311 #if _MIPS_SIM == _MIPS_SIM_NABI32 @@ -1043,6 +1043,6 @@ #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */ #define __NR_N32_Linux 6000 -#define __NR_N32_Linux_syscalls 314 +#define __NR_N32_Linux_syscalls 315 #endif /* _UAPI_ASM_UNISTD_H */ -- cgit v1.2.3 From 721a9205396c4ef2a811dd665ec2a232163b583d Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Wed, 21 May 2014 12:35:00 +0100 Subject: MIPS: Fix typo when reporting cache and ftlb errors for ImgTec cores Introduced by the following two commits: 75b5b5e0a262790fa11043fe45700499c7e3d818 "MIPS: Add support for FTLBs" 6de20451857ed14a4eecc28d08f6de5925d1cf96 "MIPS: Add printing of ES bit for Imgtec cores when cache error occurs" Signed-off-by: Markos Chandras Reported-by: Matheus Almeida Cc: linux-mips@linux-mips.org Cc: Markos Chandras Cc: stable@vger.kernel.org # v3.14+ Patchwork: https://patchwork.linux-mips.org/patch/6980/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/traps.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 074e857ced28..8119ac2fdfc9 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -1545,7 +1545,7 @@ asmlinkage void cache_parity_error(void) reg_val & (1<<30) ? "secondary" : "primary", reg_val & (1<<31) ? "data" : "insn"); if (cpu_has_mips_r2 && - ((current_cpu_data.processor_id && 0xff0000) == PRID_COMP_MIPS)) { + ((current_cpu_data.processor_id & 0xff0000) == PRID_COMP_MIPS)) { pr_err("Error bits: %s%s%s%s%s%s%s%s\n", reg_val & (1<<29) ? "ED " : "", reg_val & (1<<28) ? "ET " : "", @@ -1585,7 +1585,7 @@ asmlinkage void do_ftlb(void) /* For the moment, report the problem and hang. */ if (cpu_has_mips_r2 && - ((current_cpu_data.processor_id && 0xff0000) == PRID_COMP_MIPS)) { + ((current_cpu_data.processor_id & 0xff0000) == PRID_COMP_MIPS)) { pr_err("FTLB error exception, cp0_ecc=0x%08x:\n", read_c0_ecc()); pr_err("cp0_errorepc == %0*lx\n", field, read_c0_errorepc()); -- cgit v1.2.3 From 2ff89d64f23e99da64995844ea42c83b0b4d58c6 Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Fri, 23 May 2014 13:31:31 +0100 Subject: MIPS: malta: memory.c: Initialize the 'memsize' variable If the 'memsize' environmental variable is not set by the bootloader the 'memsize' variable is not initialized, leading to potential memory problems. This patch fixes the problem by setting the initial value to '0' to force the kernel to set a good default memory size. Cc: # v3.15+ Reported-by: Matheus Almeida Signed-off-by: Markos Chandras Cc: linux-mips@linux-mips.org Cc: Markos Chandras Cc: stable@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/6984/ Signed-off-by: Ralf Baechle --- arch/mips/mti-malta/malta-memory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/mti-malta/malta-memory.c b/arch/mips/mti-malta/malta-memory.c index 6d0f4ab3632d..f2364e419682 100644 --- a/arch/mips/mti-malta/malta-memory.c +++ b/arch/mips/mti-malta/malta-memory.c @@ -27,7 +27,7 @@ unsigned long physical_memsize = 0L; fw_memblock_t * __init fw_getmdesc(int eva) { char *memsize_str, *ememsize_str __maybe_unused = NULL, *ptr; - unsigned long memsize, ememsize __maybe_unused = 0; + unsigned long memsize = 0, ememsize __maybe_unused = 0; static char cmdline[COMMAND_LINE_SIZE] __initdata; int tmp; -- cgit v1.2.3 From 0132514588f3a0685861221058116a383bff4deb Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 25 May 2014 17:23:07 +0200 Subject: hwmon: Document temp[1-*]_min_hyst sysfs attribute The temp[1-*]_min_hyst sysfs attribute is already implemented by 3 hwmon drivers (adt7x10, lm77 and lm92) but was missing from the standard interface. Also add temp[1-*]_lcrit_hyst for consistency, even though no driver implement that one for the time being. Signed-off-by: Jean Delvare Reviewed-by: Guenter Roeck --- Documentation/hwmon/sysfs-interface | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Documentation/hwmon/sysfs-interface b/Documentation/hwmon/sysfs-interface index 79f8257dd790..2cc95ad46604 100644 --- a/Documentation/hwmon/sysfs-interface +++ b/Documentation/hwmon/sysfs-interface @@ -327,6 +327,13 @@ temp[1-*]_max_hyst from the max value. RW +temp[1-*]_min_hyst + Temperature hysteresis value for min limit. + Unit: millidegree Celsius + Must be reported as an absolute temperature, NOT a delta + from the min value. + RW + temp[1-*]_input Temperature input value. Unit: millidegree Celsius RO @@ -362,6 +369,13 @@ temp[1-*]_lcrit Temperature critical min value, typically lower than Unit: millidegree Celsius RW +temp[1-*]_lcrit_hyst + Temperature hysteresis value for critical min limit. + Unit: millidegree Celsius + Must be reported as an absolute temperature, NOT a delta + from the critical min value. + RW + temp[1-*]_offset Temperature offset which is added to the temperature reading by the chip. -- cgit v1.2.3 From 59cf4243e557aa64ab2ef51280454aa1f3828e14 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 25 May 2014 17:23:08 +0200 Subject: hwmon: (ntc_thermistor) Fix dependencies In commit 9e8269de, support was added for ntc_thermistor devices being declared in the device tree and implemented on top of IIO. With that change, a dependency was added to the ntc_thermistor driver: depends on (!OF && !IIO) || (OF && IIO) This construct has the drawback that the driver can no longer be selected when OF is set and IIO isn't, nor when IIO is set and OF is not. This is a regression for the original users of the driver. As the new code depends on IIO and is useless without OF, include it only if both are enabled, and set the dependencies accordingly. This is clearer, more simple and more correct. Signed-off-by: Jean Delvare Fixes: 9e8269de hwmon: (ntc_thermistor) Add DT with IIO support to NTC thermistor driver Reviewed-by: Guenter Roeck Cc: Naveen Krishna Chatradhi Cc: Doug Anderson --- drivers/hwmon/Kconfig | 2 +- drivers/hwmon/ntc_thermistor.c | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index bc196f49ec53..4af0da96c2e2 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -1053,7 +1053,7 @@ config SENSORS_PC87427 config SENSORS_NTC_THERMISTOR tristate "NTC thermistor support" - depends on (!OF && !IIO) || (OF && IIO) + depends on !OF || IIO=n || IIO help This driver supports NTC thermistors sensor reading and its interpretation. The driver can also monitor the temperature and diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c index 8a17f01e8672..6b4413ce4d39 100644 --- a/drivers/hwmon/ntc_thermistor.c +++ b/drivers/hwmon/ntc_thermistor.c @@ -141,7 +141,7 @@ struct ntc_data { char name[PLATFORM_NAME_SIZE]; }; -#ifdef CONFIG_OF +#if defined(CONFIG_OF) && IS_ENABLED(CONFIG_IIO) static int ntc_adc_iio_read(struct ntc_thermistor_platform_data *pdata) { struct iio_channel *channel = pdata->chan; @@ -223,6 +223,8 @@ ntc_thermistor_parse_dt(struct platform_device *pdev) return NULL; } +#define ntc_match NULL + static void ntc_iio_channel_release(struct ntc_thermistor_platform_data *pdata) { } #endif -- cgit v1.2.3 From ead82d6792ef5c600d535bca6ec50a4da14ff7c7 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 25 May 2014 17:23:08 +0200 Subject: hwmon: (ntc_thermistor) Fix OF device ID mapping The mapping from OF device IDs to platform device IDs is wrong. TYPE_NCPXXWB473 is 0, TYPE_NCPXXWL333 is 1, so ntc_thermistor_id[TYPE_NCPXXWB473] is { "ncp15wb473", TYPE_NCPXXWB473 } while ntc_thermistor_id[TYPE_NCPXXWL333] is { "ncp18wb473", TYPE_NCPXXWB473 }. So the name is wrong for all but the "ntc,ncp15wb473" entry, and the type is wrong for the "ntc,ncp15wl333" entry. So map the entries by index, it is neither elegant nor robust but at least it is correct. Signed-off-by: Jean Delvare Fixes: 9e8269de hwmon: (ntc_thermistor) Add DT with IIO support to NTC thermistor driver Reviewed-by: Guenter Roeck Cc: Naveen Krishna Chatradhi Cc: Doug Anderson --- drivers/hwmon/ntc_thermistor.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c index 6b4413ce4d39..e76feb86a1d4 100644 --- a/drivers/hwmon/ntc_thermistor.c +++ b/drivers/hwmon/ntc_thermistor.c @@ -44,6 +44,7 @@ struct ntc_compensation { unsigned int ohm; }; +/* Order matters, ntc_match references the entries by index */ static const struct platform_device_id ntc_thermistor_id[] = { { "ncp15wb473", TYPE_NCPXXWB473 }, { "ncp18wb473", TYPE_NCPXXWB473 }, @@ -163,15 +164,15 @@ static int ntc_adc_iio_read(struct ntc_thermistor_platform_data *pdata) static const struct of_device_id ntc_match[] = { { .compatible = "ntc,ncp15wb473", - .data = &ntc_thermistor_id[TYPE_NCPXXWB473] }, + .data = &ntc_thermistor_id[0] }, { .compatible = "ntc,ncp18wb473", - .data = &ntc_thermistor_id[TYPE_NCPXXWB473] }, + .data = &ntc_thermistor_id[1] }, { .compatible = "ntc,ncp21wb473", - .data = &ntc_thermistor_id[TYPE_NCPXXWB473] }, + .data = &ntc_thermistor_id[2] }, { .compatible = "ntc,ncp03wb473", - .data = &ntc_thermistor_id[TYPE_NCPXXWB473] }, + .data = &ntc_thermistor_id[3] }, { .compatible = "ntc,ncp15wl333", - .data = &ntc_thermistor_id[TYPE_NCPXXWL333] }, + .data = &ntc_thermistor_id[4] }, { }, }; MODULE_DEVICE_TABLE(of, ntc_match); -- cgit v1.2.3 From f9b899c44fec53c1519b19f853e96191ae96b1c6 Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Thu, 15 May 2014 13:54:06 -0700 Subject: Documentation: fix typos in drm docbook Fix spelling typo in DocBook/drm.tmpl Signed-off-by: Masanari Iida Signed-off-by: Randy Dunlap Signed-off-by: Linus Torvalds --- Documentation/DocBook/drm.tmpl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 677a02553ec0..ba60d93c1855 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -79,7 +79,7 @@ This first part of the DRM Developer's Guide documents core DRM code, - helper libraries for writting drivers and generic userspace interfaces + helper libraries for writing drivers and generic userspace interfaces exposed by DRM drivers. @@ -459,7 +459,7 @@ char *date; providing a solution to every graphics memory-related problems, GEM identified common code between drivers and created a support library to share it. GEM has simpler initialization and execution requirements than - TTM, but has no video RAM management capabitilies and is thus limited to + TTM, but has no video RAM management capabilities and is thus limited to UMA devices. @@ -889,7 +889,7 @@ int (*prime_fd_to_handle)(struct drm_device *dev, vice versa. Drivers must use the kernel dma-buf buffer sharing framework to manage the PRIME file descriptors. Similar to the mode setting API PRIME is agnostic to the underlying buffer object manager, as - long as handles are 32bit unsinged integers. + long as handles are 32bit unsigned integers. While non-GEM drivers must implement the operations themselves, GEM @@ -2356,7 +2356,7 @@ void intel_crt_init(struct drm_device *dev) first create properties and then create and associate individual instances of those properties to objects. A property can be instantiated multiple times and associated with different objects. Values are stored in property - instances, and all other property information are stored in the propery + instances, and all other property information are stored in the property and shared between all instances of the property. @@ -2697,10 +2697,10 @@ int num_ioctls; Legacy Support Code - The section very brievely covers some of the old legacy support code which + The section very briefly covers some of the old legacy support code which is only used by old DRM drivers which have done a so-called shadow-attach to the underlying device instead of registering as a real driver. This - also includes some of the old generic buffer mangement and command + also includes some of the old generic buffer management and command submission code. Do not use any of this in new and modern drivers. -- cgit v1.2.3 From f9a0974d3f7049f6f753ebd28b8f0907983acf3c Mon Sep 17 00:00:00 2001 From: Paul McQuade Date: Thu, 15 May 2014 13:54:25 -0700 Subject: Documentation: update thunderbird email client settings Added setting to email-clients that is easier to read and is easier to setup thunderbird. Removed config settings and added GUI settings. Signed-off-by: Paul McQuade Signed-off-by: Randy Dunlap Signed-off-by: Linus Torvalds --- Documentation/email-clients.txt | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/Documentation/email-clients.txt b/Documentation/email-clients.txt index e9f5daccbd02..4e30ebaa9e5b 100644 --- a/Documentation/email-clients.txt +++ b/Documentation/email-clients.txt @@ -201,20 +201,15 @@ To beat some sense out of the internal editor, do this: - Edit your Thunderbird config settings so that it won't use format=flowed. Go to "edit->preferences->advanced->config editor" to bring up the - thunderbird's registry editor, and set "mailnews.send_plaintext_flowed" to - "false". + thunderbird's registry editor. -- Disable HTML Format: Set "mail.identity.id1.compose_html" to "false". +- Set "mailnews.send_plaintext_flowed" to "false" -- Enable "preformat" mode: Set "editor.quotesPreformatted" to "true". +- Set "mailnews.wraplength" from "72" to "0" -- Enable UTF8: Set "prefs.converted-to-utf8" to "true". +- "View" > "Message Body As" > "Plain Text" -- Install the "toggle wordwrap" extension. Download the file from: - https://addons.mozilla.org/thunderbird/addon/2351/ - Then go to "tools->add ons", select "install" at the bottom of the screen, - and browse to where you saved the .xul file. This adds an "Enable - Wordwrap" entry under the Options menu of the message composer. +- "View" > "Character Encoding" > "Unicode (UTF-8)" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TkRat (GUI) -- cgit v1.2.3 From f76f133b0c3b182c2d4f4de21a04ba4c964d508d Mon Sep 17 00:00:00 2001 From: Jonathan Callen Date: Thu, 15 May 2014 13:54:52 -0700 Subject: Documentation: update java sample wrapper for java 7 The sample wrapper currently fails on some Java 7 .class files. This updates the wrapper to properly handle those files. Signed-off-by: Jonathan Callen Signed-off-by: Randy Dunlap Signed-off-by: Linus Torvalds --- Documentation/java.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Documentation/java.txt b/Documentation/java.txt index e6a723281547..418020584ccc 100644 --- a/Documentation/java.txt +++ b/Documentation/java.txt @@ -188,6 +188,9 @@ shift #define CP_METHODREF 10 #define CP_INTERFACEMETHODREF 11 #define CP_NAMEANDTYPE 12 +#define CP_METHODHANDLE 15 +#define CP_METHODTYPE 16 +#define CP_INVOKEDYNAMIC 18 /* Define some commonly used error messages */ @@ -242,14 +245,19 @@ void skip_constant(FILE *classfile, u_int16_t *cur) break; case CP_CLASS: case CP_STRING: + case CP_METHODTYPE: seekerr = fseek(classfile, 2, SEEK_CUR); break; + case CP_METHODHANDLE: + seekerr = fseek(classfile, 3, SEEK_CUR); + break; case CP_INTEGER: case CP_FLOAT: case CP_FIELDREF: case CP_METHODREF: case CP_INTERFACEMETHODREF: case CP_NAMEANDTYPE: + case CP_INVOKEDYNAMIC: seekerr = fseek(classfile, 4, SEEK_CUR); break; case CP_LONG: -- cgit v1.2.3 From 3568a1dbf174a1ae0022611998c4e5d588b5014d Mon Sep 17 00:00:00 2001 From: Jan Moskyto Matejka Date: Thu, 15 May 2014 13:55:34 -0700 Subject: Documentation: update /proc/stat "intr" count summary The sum at the beginning of line "intr" includes also unnumbered interrupts. It implies that the sum at the beginning isn't the sum of the remainder of the line, not even an estimation. Fixed the documentation to mention that. This behaviour was added to /proc/stat in commit a2eddfa95919 ("x86: make /proc/stat account for all interrupts") Signed-off-by: Jan Moskyto Matejka Signed-off-by: Randy Dunlap Signed-off-by: Linus Torvalds --- Documentation/filesystems/proc.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt index 8b9cd8eb3f91..264bcde0c51c 100644 --- a/Documentation/filesystems/proc.txt +++ b/Documentation/filesystems/proc.txt @@ -1245,8 +1245,9 @@ second). The meanings of the columns are as follows, from left to right: The "intr" line gives counts of interrupts serviced since boot time, for each of the possible system interrupts. The first column is the total of all -interrupts serviced; each subsequent column is the total for that particular -interrupt. +interrupts serviced including unnumbered architecture specific interrupts; +each subsequent column is the total for that particular numbered interrupt. +Unnumbered interrupts are not shown, only summed into the total. The "ctxt" line gives the total number of context switches across all CPUs. -- cgit v1.2.3 From f9ff907b0af561dcde4683f7c9f71dc0f41d3be3 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Sat, 3 May 2014 18:19:17 +0100 Subject: ARM: 8048/1: fix v7-M setup stack location MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit __v7m_setup_stack currently sits in the .proc.info.init section, and thus creates a bogus proc info entry (which by the way matches any unknown CPU IDs, due to the entry's mask being 0). Move it out of there. Acked-by: Uwe Kleine-König Signed-off-by: Rabin Vincent Signed-off-by: Russell King --- arch/arm/mm/proc-v7m.S | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/arch/arm/mm/proc-v7m.S b/arch/arm/mm/proc-v7m.S index 0c93588fcb91..1ca37c72f12f 100644 --- a/arch/arm/mm/proc-v7m.S +++ b/arch/arm/mm/proc-v7m.S @@ -123,6 +123,11 @@ __v7m_setup: mov pc, lr ENDPROC(__v7m_setup) + .align 2 +__v7m_setup_stack: + .space 4 * 8 @ 8 registers +__v7m_setup_stack_top: + define_processor_functions v7m, dabort=nommu_early_abort, pabort=legacy_pabort, nommu=1 .section ".rodata" @@ -152,6 +157,3 @@ __v7m_proc_info: .long nop_cache_fns @ proc_info_list.cache .size __v7m_proc_info, . - __v7m_proc_info -__v7m_setup_stack: - .space 4 * 8 @ 8 registers -__v7m_setup_stack_top: -- cgit v1.2.3 From 537094b64b229bf3ad146042f83e74cf6abe59df Mon Sep 17 00:00:00 2001 From: Andrey Ryabinin Date: Wed, 7 May 2014 08:07:25 +0100 Subject: ARM: 8051/1: put_user: fix possible data corruption in put_user According to arm procedure call standart r2 register is call-cloberred. So after the result of x expression was put into r2 any following function call in p may overwrite r2. To fix this, the result of p expression must be saved to the temporary variable before the assigment x expression to __r2. Signed-off-by: Andrey Ryabinin Reviewed-by: Nicolas Pitre Cc: stable@vger.kernel.org Signed-off-by: Russell King --- arch/arm/include/asm/uaccess.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h index 12c3a5decc60..75d95799b6e6 100644 --- a/arch/arm/include/asm/uaccess.h +++ b/arch/arm/include/asm/uaccess.h @@ -171,8 +171,9 @@ extern int __put_user_8(void *, unsigned long long); #define __put_user_check(x,p) \ ({ \ unsigned long __limit = current_thread_info()->addr_limit - 1; \ + const typeof(*(p)) __user *__tmp_p = (p); \ register const typeof(*(p)) __r2 asm("r2") = (x); \ - register const typeof(*(p)) __user *__p asm("r0") = (p);\ + register const typeof(*(p)) __user *__p asm("r0") = __tmp_p; \ register unsigned long __l asm("r1") = __limit; \ register int __e asm("r0"); \ switch (sizeof(*(__p))) { \ -- cgit v1.2.3 From 8203d5b628907ae6141e4eb52f9b48e0f1f46cd2 Mon Sep 17 00:00:00 2001 From: Nikolay Borisov Date: Thu, 8 May 2014 15:54:26 +0100 Subject: ARM: 8052/1: unwind: Fix handling of "Pop r4-r[4+nnn],r14" opcode The arm EABI states that unwind opcode 10100nnn means pop register r4-4[4+nnn],aditionally there is a similar unwind opcode: 10101nnn which means the same thing plus popping r14. Those two cases are handled by the unwind_exec_pop_r4_to_rN function which checks whether the 4th bit is set and does r14 popping. However, up until now it has been checking whether the 8th bit was set (mask & 0x80) instead of the 4th (mask & 0x8), a simple to make typo but this meant that we were always popping r14 even if we had the former opcode. This patch changes the mask so that the 2 unwind opcodes are being handled correctly. Signed-off-by: Nikolay Borisov Reviewed-by: Anurag Aggarwal Signed-off-by: Russell King --- arch/arm/kernel/unwind.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/kernel/unwind.c b/arch/arm/kernel/unwind.c index 3c217694ebec..cb791ac6a003 100644 --- a/arch/arm/kernel/unwind.c +++ b/arch/arm/kernel/unwind.c @@ -285,7 +285,7 @@ static int unwind_exec_pop_r4_to_rN(struct unwind_ctrl_block *ctrl, if (unwind_pop_register(ctrl, &vsp, reg)) return -URC_FAILURE; - if (insn & 0x80) + if (insn & 0x8) if (unwind_pop_register(ctrl, &vsp, 14)) return -URC_FAILURE; -- cgit v1.2.3 From fbebf59778600488147744cdf7d7c20d22531025 Mon Sep 17 00:00:00 2001 From: srinik Date: Thu, 15 May 2014 11:28:44 +0100 Subject: ARM: 8057/1: amba: Add Qualcomm vendor ID. This patch adds Qualcomm amba vendor Id to the list. This ID is used in mmci driver. The ID selected in same lines like 0x41 is "A" for ARM, 0x51 is "Q" for Qualcomm. As there are no physical register on Qcom SOC for amba vendor id, this is a fake ID assigned based on "Q" prefix from Qualcomm. Signed-off-by: Srinivas Kandagatla Acked-by: Linus Walleij Signed-off-by: Russell King --- include/linux/amba/bus.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/amba/bus.h b/include/linux/amba/bus.h index 63b5eff0a80f..fdd7e1b61f60 100644 --- a/include/linux/amba/bus.h +++ b/include/linux/amba/bus.h @@ -47,6 +47,7 @@ struct amba_driver { enum amba_vendor { AMBA_VENDOR_ARM = 0x41, AMBA_VENDOR_ST = 0x80, + AMBA_VENDOR_QCOM = 0x51, }; extern struct bus_type amba_bustype; -- cgit v1.2.3 From 483a6c9d447f625b991fa04a1530493d893984db Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Sat, 24 May 2014 17:38:01 +0100 Subject: ARM: 8064/1: fix v7-M signal return MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to the ARM ARM, the behaviour is UNPREDICTABLE if the PC read from the exception return stack is not half word aligned. See the pseudo code for ExceptionReturn() and PopStack(). The signal handler's address has the bit 0 set, and setup_return() directly writes this to regs->ARM_pc. Current hardware happens to discard this bit, but QEMU's emulation doesn't and this makes processes crash. Mask out bit 0 before the exception return in order to get predictable behaviour. Fixes: 19c4d593f0b4 ("ARM: ARMv7-M: Add support for exception handling") Cc: stable@kernel.org Acked-by: Uwe Kleine-König Signed-off-by: Rabin Vincent Signed-off-by: Russell King --- arch/arm/kernel/entry-header.S | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S index 1420725142ca..efb208de75ec 100644 --- a/arch/arm/kernel/entry-header.S +++ b/arch/arm/kernel/entry-header.S @@ -132,6 +132,10 @@ orrne r5, V7M_xPSR_FRAMEPTRALIGN biceq r5, V7M_xPSR_FRAMEPTRALIGN + @ ensure bit 0 is cleared in the PC, otherwise behaviour is + @ unpredictable + bic r4, #1 + @ write basic exception frame stmdb r2!, {r1, r3-r5} ldmia sp, {r1, r3-r5} -- cgit v1.2.3 From c7208164e66f63e3ec1759b98087849286410741 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 25 May 2014 16:06:00 -0700 Subject: Linux 3.15-rc7 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 9d993787afe0..cf3412d78ff1 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 3 PATCHLEVEL = 15 SUBLEVEL = 0 -EXTRAVERSION = -rc6 +EXTRAVERSION = -rc7 NAME = Shuffling Zombie Juror # *DOCUMENTATION* -- cgit v1.2.3 From 66ef3fab94df1004ed02c292d3d4e78485bfc615 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Thu, 15 May 2014 10:35:44 +0200 Subject: MIPS: RC32434: fix broken PCI resource initialization The parent field of the 'rc32434_res_pci_mem1' resource points to the resource itself which is obviously wrong. Due to the broken initialitazion, the PCI devices on the Mikrotik RB532 boards are not working since commit 22283178 (MIPS: avoid possible resource conflict in register_pci_controller). Remove the field initialization to fix the issue. Signed-off-by: Gabor Juhos Reported-by: Waldemar Brodkorb Cc: linux-mips@linux-mips.org Cc: Gabor Juhos Patchwork: https://patchwork.linux-mips.org/patch/6940/ Signed-off-by: Ralf Baechle --- arch/mips/pci/pci-rc32434.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/mips/pci/pci-rc32434.c b/arch/mips/pci/pci-rc32434.c index b128cb973ebe..7f6ce6d734c0 100644 --- a/arch/mips/pci/pci-rc32434.c +++ b/arch/mips/pci/pci-rc32434.c @@ -53,7 +53,6 @@ static struct resource rc32434_res_pci_mem1 = { .start = 0x50000000, .end = 0x5FFFFFFF, .flags = IORESOURCE_MEM, - .parent = &rc32434_res_pci_mem1, .sibling = NULL, .child = &rc32434_res_pci_mem2 }; -- cgit v1.2.3 From 2807bd18cc60ec471917b5158e98e4d7b7e030fb Mon Sep 17 00:00:00 2001 From: Aaron Lu Date: Mon, 26 May 2014 14:34:07 +0200 Subject: ACPI / thermal: fix workqueue destroy order When the thermal module is to be removed, we should destroy the wq acpi_thermal_pm_queue after the ACPI driver's remove callback is executed as we will need to flush the workqueue there, or a NULL pointer access will be hit. Reported-and-tested-by: Kui Zhang References: http://www.spinics.net/lists/kernel/msg1747251.html Cc: All applicable Signed-off-by: Aaron Lu Signed-off-by: Rafael J. Wysocki --- drivers/acpi/thermal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index c1e31a41f949..25bbc55dca89 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -1278,8 +1278,8 @@ static int __init acpi_thermal_init(void) static void __exit acpi_thermal_exit(void) { - destroy_workqueue(acpi_thermal_pm_queue); acpi_bus_unregister_driver(&acpi_thermal_driver); + destroy_workqueue(acpi_thermal_pm_queue); return; } -- cgit v1.2.3 From 6d396ede224dc596d92d7cab433713536e68916c Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 19 May 2014 22:52:30 -0700 Subject: Input: synaptics - T540p - unify with other LEN0034 models The T540p has a touchpad with pnp-id LEN0034, all the models with this pnp-id have the same min/max values, except the T540p where the values are slightly off. Fix them to be identical. This is a preparation patch for simplifying the quirk table. Cc: stable@vger.kernel.org Signed-off-by: Hans de Goede Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/synaptics.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index d4c05b103e74..898e8bb170f9 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -1603,7 +1603,7 @@ static const struct dmi_system_id min_max_dmi_table[] __initconst = { DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T540"), }, - .driver_data = (int []){1024, 5056, 2058, 4832}, + .driver_data = (int []){1024, 5112, 2024, 4832}, }, { /* Lenovo ThinkPad L540 */ -- cgit v1.2.3 From e2f611029b370bb7a04236215ad4b36aa8cb98cd Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 19 May 2014 22:53:23 -0700 Subject: Input: synaptics - add a matches_pnp_id helper function This is a preparation patch for simplifying the min/max quirk table. Cc: stable@vger.kernel.org Signed-off-by: Hans de Goede Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/synaptics.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 898e8bb170f9..395ec9c5ae9a 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -156,6 +156,18 @@ static const char * const topbuttonpad_pnp_ids[] = { NULL }; +static bool matches_pnp_id(struct psmouse *psmouse, const char * const ids[]) +{ + int i; + + if (!strncmp(psmouse->ps2dev.serio->firmware_id, "PNP:", 4)) + for (i = 0; ids[i]; i++) + if (strstr(psmouse->ps2dev.serio->firmware_id, ids[i])) + return true; + + return false; +} + /***************************************************************************** * Synaptics communications functions ****************************************************************************/ @@ -1365,17 +1377,8 @@ static void set_input_params(struct psmouse *psmouse, if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) { __set_bit(INPUT_PROP_BUTTONPAD, dev->propbit); - /* See if this buttonpad has a top button area */ - if (!strncmp(psmouse->ps2dev.serio->firmware_id, "PNP:", 4)) { - for (i = 0; topbuttonpad_pnp_ids[i]; i++) { - if (strstr(psmouse->ps2dev.serio->firmware_id, - topbuttonpad_pnp_ids[i])) { - __set_bit(INPUT_PROP_TOPBUTTONPAD, - dev->propbit); - break; - } - } - } + if (matches_pnp_id(psmouse, topbuttonpad_pnp_ids)) + __set_bit(INPUT_PROP_TOPBUTTONPAD, dev->propbit); /* Clickpads report only left button */ __clear_bit(BTN_RIGHT, dev->keybit); __clear_bit(BTN_MIDDLE, dev->keybit); -- cgit v1.2.3 From 0f68f39c393bc06ac5ccc8794f0e2ed841e41c3e Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 19 May 2014 22:54:09 -0700 Subject: Input: synaptics - change min/max quirk table to pnp-id matching Most of the affected models share pnp-ids for the touchpad. So switching to pnp-ids give us 2 advantages: 1) It shrinks the quirk list 2) It will lower the new quirk addition frequency, ie the recently added W540 quirk would not have been necessary since it uses the same LEN0034 pnp ids as other models already added before it As an added bonus it actually puts the quirk on the actual psmouse, rather then on the machine, which is technically more correct. Cc: stable@vger.kernel.org Signed-off-by: Hans de Goede Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/synaptics.c | 149 ++++++++++------------------------------ 1 file changed, 36 insertions(+), 113 deletions(-) diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 395ec9c5ae9a..c5ec703c727e 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -117,6 +117,31 @@ void synaptics_reset(struct psmouse *psmouse) } #ifdef CONFIG_MOUSE_PS2_SYNAPTICS +struct min_max_quirk { + const char * const *pnp_ids; + int x_min, x_max, y_min, y_max; +}; + +static const struct min_max_quirk min_max_pnpid_table[] = { + { + (const char * const []){"LEN0033", NULL}, + 1024, 5052, 2258, 4832 + }, + { + (const char * const []){"LEN0035", "LEN0042", NULL}, + 1232, 5710, 1156, 4696 + }, + { + (const char * const []){"LEN0034", "LEN0036", "LEN2004", NULL}, + 1024, 5112, 2024, 4832 + }, + { + (const char * const []){"LEN2001", NULL}, + 1024, 5022, 2508, 4832 + }, + { } +}; + /* This list has been kindly provided by Synaptics. */ static const char * const topbuttonpad_pnp_ids[] = { "LEN0017", @@ -129,7 +154,7 @@ static const char * const topbuttonpad_pnp_ids[] = { "LEN002D", "LEN002E", "LEN0033", /* Helix */ - "LEN0034", /* T431s, T540, X1 Carbon 2nd */ + "LEN0034", /* T431s, L440, L540, T540, W540, X1 Carbon 2nd */ "LEN0035", /* X240 */ "LEN0036", /* T440 */ "LEN0037", @@ -142,7 +167,7 @@ static const char * const topbuttonpad_pnp_ids[] = { "LEN0048", "LEN0049", "LEN2000", - "LEN2001", + "LEN2001", /* Edge E431 */ "LEN2002", "LEN2003", "LEN2004", /* L440 */ @@ -316,20 +341,20 @@ static int synaptics_identify(struct psmouse *psmouse) * Resolution is left zero if touchpad does not support the query */ -static const int *quirk_min_max; - static int synaptics_resolution(struct psmouse *psmouse) { struct synaptics_data *priv = psmouse->private; unsigned char resp[3]; + int i; - if (quirk_min_max) { - priv->x_min = quirk_min_max[0]; - priv->x_max = quirk_min_max[1]; - priv->y_min = quirk_min_max[2]; - priv->y_max = quirk_min_max[3]; - return 0; - } + for (i = 0; min_max_pnpid_table[i].pnp_ids; i++) + if (matches_pnp_id(psmouse, min_max_pnpid_table[i].pnp_ids)) { + priv->x_min = min_max_pnpid_table[i].x_min; + priv->x_max = min_max_pnpid_table[i].x_max; + priv->y_min = min_max_pnpid_table[i].y_min; + priv->y_max = min_max_pnpid_table[i].y_max; + return 0; + } if (SYN_ID_MAJOR(priv->identity) < 4) return 0; @@ -1550,112 +1575,10 @@ static const struct dmi_system_id olpc_dmi_table[] __initconst = { { } }; -static const struct dmi_system_id min_max_dmi_table[] __initconst = { -#if defined(CONFIG_DMI) - { - /* Lenovo ThinkPad Helix */ - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad Helix"), - }, - .driver_data = (int []){1024, 5052, 2258, 4832}, - }, - { - /* Lenovo ThinkPad X240 */ - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X240"), - }, - .driver_data = (int []){1232, 5710, 1156, 4696}, - }, - { - /* Lenovo ThinkPad Edge E431 */ - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad Edge E431"), - }, - .driver_data = (int []){1024, 5022, 2508, 4832}, - }, - { - /* Lenovo ThinkPad T431s */ - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T431"), - }, - .driver_data = (int []){1024, 5112, 2024, 4832}, - }, - { - /* Lenovo ThinkPad T440s */ - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T440"), - }, - .driver_data = (int []){1024, 5112, 2024, 4832}, - }, - { - /* Lenovo ThinkPad L440 */ - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L440"), - }, - .driver_data = (int []){1024, 5112, 2024, 4832}, - }, - { - /* Lenovo ThinkPad T540p */ - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T540"), - }, - .driver_data = (int []){1024, 5112, 2024, 4832}, - }, - { - /* Lenovo ThinkPad L540 */ - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L540"), - }, - .driver_data = (int []){1024, 5112, 2024, 4832}, - }, - { - /* Lenovo ThinkPad W540 */ - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad W540"), - }, - .driver_data = (int []){1024, 5112, 2024, 4832}, - }, - { - /* Lenovo Yoga S1 */ - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, - "ThinkPad S1 Yoga"), - }, - .driver_data = (int []){1232, 5710, 1156, 4696}, - }, - { - /* Lenovo ThinkPad X1 Carbon Haswell (3rd generation) */ - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, - "ThinkPad X1 Carbon 2nd"), - }, - .driver_data = (int []){1024, 5112, 2024, 4832}, - }, -#endif - { } -}; - void __init synaptics_module_init(void) { - const struct dmi_system_id *min_max_dmi; - impaired_toshiba_kbc = dmi_check_system(toshiba_dmi_table); broken_olpc_ec = dmi_check_system(olpc_dmi_table); - - min_max_dmi = dmi_first_match(min_max_dmi_table); - if (min_max_dmi) - quirk_min_max = min_max_dmi->driver_data; } static int __synaptics_init(struct psmouse *psmouse, bool absolute_mode) -- cgit v1.2.3 From 00731155a73020c8e3c215723be193f96b4fcb1f Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 21 May 2014 12:42:56 +0100 Subject: drm/i915: Fix dynamic allocation of physical handles MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A single object may be referenced by multiple registers fundamentally breaking the static allotment of ids in the current design. When the object is used the second time, the physical address of the first assignment is relinquished and a second one granted. However, the hardware is still reading (and possibly writing) to the old physical address now returned to the system. Eventually hilarity will ensue, but in the short term, it just means that cursors are broken when using more than one pipe. v2: Fix up leak of pci handle when handling an error during attachment, and avoid a double kmap/kunmap. (Ville) Rebase against -fixes. v3: And fix the error handling added in v2 (Ville) Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=77351 Signed-off-by: Chris Wilson Cc: Ville Syrjälä Cc: Jani Nikula Cc: stable@vger.kernel.org Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_dma.c | 1 - drivers/gpu/drm/i915/i915_drv.h | 24 +-- drivers/gpu/drm/i915/i915_gem.c | 319 ++++++++++++++--------------------- drivers/gpu/drm/i915/intel_display.c | 11 +- drivers/gpu/drm/i915/intel_overlay.c | 12 +- 5 files changed, 136 insertions(+), 231 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 96177eec0a0e..eedb023af27d 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1833,7 +1833,6 @@ int i915_driver_unload(struct drm_device *dev) flush_workqueue(dev_priv->wq); mutex_lock(&dev->struct_mutex); - i915_gem_free_all_phys_object(dev); i915_gem_cleanup_ringbuffer(dev); i915_gem_context_fini(dev); WARN_ON(dev_priv->mm.aliasing_ppgtt); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 108e1ec2fa4b..ec5f6fb42ab3 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -242,18 +242,6 @@ struct intel_ddi_plls { #define WATCH_LISTS 0 #define WATCH_GTT 0 -#define I915_GEM_PHYS_CURSOR_0 1 -#define I915_GEM_PHYS_CURSOR_1 2 -#define I915_GEM_PHYS_OVERLAY_REGS 3 -#define I915_MAX_PHYS_OBJECT (I915_GEM_PHYS_OVERLAY_REGS) - -struct drm_i915_gem_phys_object { - int id; - struct page **page_list; - drm_dma_handle_t *handle; - struct drm_i915_gem_object *cur_obj; -}; - struct opregion_header; struct opregion_acpi; struct opregion_swsci; @@ -1187,9 +1175,6 @@ struct i915_gem_mm { /** Bit 6 swizzling required for Y tiling */ uint32_t bit_6_swizzle_y; - /* storage for physical objects */ - struct drm_i915_gem_phys_object *phys_objs[I915_MAX_PHYS_OBJECT]; - /* accounting, useful for userland debugging */ spinlock_t object_stat_lock; size_t object_memory; @@ -1769,7 +1754,7 @@ struct drm_i915_gem_object { struct drm_file *pin_filp; /** for phy allocated objects */ - struct drm_i915_gem_phys_object *phys_obj; + drm_dma_handle_t *phys_handle; }; #define to_intel_bo(x) container_of(x, struct drm_i915_gem_object, base) @@ -2334,13 +2319,8 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, u32 alignment, struct intel_ring_buffer *pipelined); void i915_gem_object_unpin_from_display_plane(struct drm_i915_gem_object *obj); -int i915_gem_attach_phys_object(struct drm_device *dev, - struct drm_i915_gem_object *obj, - int id, +int i915_gem_object_attach_phys(struct drm_i915_gem_object *obj, int align); -void i915_gem_detach_phys_object(struct drm_device *dev, - struct drm_i915_gem_object *obj); -void i915_gem_free_all_phys_object(struct drm_device *dev); int i915_gem_open(struct drm_device *dev, struct drm_file *file); void i915_gem_release(struct drm_device *dev, struct drm_file *file); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 2871ce75f438..b391f30f9985 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -43,10 +43,6 @@ static void i915_gem_object_flush_cpu_write_domain(struct drm_i915_gem_object *o static __must_check int i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj, bool readonly); -static int i915_gem_phys_pwrite(struct drm_device *dev, - struct drm_i915_gem_object *obj, - struct drm_i915_gem_pwrite *args, - struct drm_file *file); static void i915_gem_write_fence(struct drm_device *dev, int reg, struct drm_i915_gem_object *obj); @@ -209,6 +205,128 @@ i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data, return 0; } +static void i915_gem_object_detach_phys(struct drm_i915_gem_object *obj) +{ + drm_dma_handle_t *phys = obj->phys_handle; + + if (!phys) + return; + + if (obj->madv == I915_MADV_WILLNEED) { + struct address_space *mapping = file_inode(obj->base.filp)->i_mapping; + char *vaddr = phys->vaddr; + int i; + + for (i = 0; i < obj->base.size / PAGE_SIZE; i++) { + struct page *page = shmem_read_mapping_page(mapping, i); + if (!IS_ERR(page)) { + char *dst = kmap_atomic(page); + memcpy(dst, vaddr, PAGE_SIZE); + drm_clflush_virt_range(dst, PAGE_SIZE); + kunmap_atomic(dst); + + set_page_dirty(page); + mark_page_accessed(page); + page_cache_release(page); + } + vaddr += PAGE_SIZE; + } + i915_gem_chipset_flush(obj->base.dev); + } + +#ifdef CONFIG_X86 + set_memory_wb((unsigned long)phys->vaddr, phys->size / PAGE_SIZE); +#endif + drm_pci_free(obj->base.dev, phys); + obj->phys_handle = NULL; +} + +int +i915_gem_object_attach_phys(struct drm_i915_gem_object *obj, + int align) +{ + drm_dma_handle_t *phys; + struct address_space *mapping; + char *vaddr; + int i; + + if (obj->phys_handle) { + if ((unsigned long)obj->phys_handle->vaddr & (align -1)) + return -EBUSY; + + return 0; + } + + if (obj->madv != I915_MADV_WILLNEED) + return -EFAULT; + + if (obj->base.filp == NULL) + return -EINVAL; + + /* create a new object */ + phys = drm_pci_alloc(obj->base.dev, obj->base.size, align); + if (!phys) + return -ENOMEM; + + vaddr = phys->vaddr; +#ifdef CONFIG_X86 + set_memory_wc((unsigned long)vaddr, phys->size / PAGE_SIZE); +#endif + mapping = file_inode(obj->base.filp)->i_mapping; + for (i = 0; i < obj->base.size / PAGE_SIZE; i++) { + struct page *page; + char *src; + + page = shmem_read_mapping_page(mapping, i); + if (IS_ERR(page)) { +#ifdef CONFIG_X86 + set_memory_wb((unsigned long)phys->vaddr, phys->size / PAGE_SIZE); +#endif + drm_pci_free(obj->base.dev, phys); + return PTR_ERR(page); + } + + src = kmap_atomic(page); + memcpy(vaddr, src, PAGE_SIZE); + kunmap_atomic(src); + + mark_page_accessed(page); + page_cache_release(page); + + vaddr += PAGE_SIZE; + } + + obj->phys_handle = phys; + return 0; +} + +static int +i915_gem_phys_pwrite(struct drm_i915_gem_object *obj, + struct drm_i915_gem_pwrite *args, + struct drm_file *file_priv) +{ + struct drm_device *dev = obj->base.dev; + void *vaddr = obj->phys_handle->vaddr + args->offset; + char __user *user_data = to_user_ptr(args->data_ptr); + + if (__copy_from_user_inatomic_nocache(vaddr, user_data, args->size)) { + unsigned long unwritten; + + /* The physical object once assigned is fixed for the lifetime + * of the obj, so we can safely drop the lock and continue + * to access vaddr. + */ + mutex_unlock(&dev->struct_mutex); + unwritten = copy_from_user(vaddr, user_data, args->size); + mutex_lock(&dev->struct_mutex); + if (unwritten) + return -EFAULT; + } + + i915_gem_chipset_flush(dev); + return 0; +} + void *i915_gem_object_alloc(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -921,8 +1039,8 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, * pread/pwrite currently are reading and writing from the CPU * perspective, requiring manual detiling by the client. */ - if (obj->phys_obj) { - ret = i915_gem_phys_pwrite(dev, obj, args, file); + if (obj->phys_handle) { + ret = i915_gem_phys_pwrite(obj, args, file); goto out; } @@ -4163,9 +4281,6 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj) trace_i915_gem_object_destroy(obj); - if (obj->phys_obj) - i915_gem_detach_phys_object(dev, obj); - list_for_each_entry_safe(vma, next, &obj->vma_list, vma_link) { int ret; @@ -4183,6 +4298,8 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj) } } + i915_gem_object_detach_phys(obj); + /* Stolen objects don't hold a ref, but do hold pin count. Fix that up * before progressing. */ if (obj->stolen) @@ -4646,190 +4763,6 @@ i915_gem_load(struct drm_device *dev) register_shrinker(&dev_priv->mm.inactive_shrinker); } -/* - * Create a physically contiguous memory object for this object - * e.g. for cursor + overlay regs - */ -static int i915_gem_init_phys_object(struct drm_device *dev, - int id, int size, int align) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_i915_gem_phys_object *phys_obj; - int ret; - - if (dev_priv->mm.phys_objs[id - 1] || !size) - return 0; - - phys_obj = kzalloc(sizeof(*phys_obj), GFP_KERNEL); - if (!phys_obj) - return -ENOMEM; - - phys_obj->id = id; - - phys_obj->handle = drm_pci_alloc(dev, size, align); - if (!phys_obj->handle) { - ret = -ENOMEM; - goto kfree_obj; - } -#ifdef CONFIG_X86 - set_memory_wc((unsigned long)phys_obj->handle->vaddr, phys_obj->handle->size / PAGE_SIZE); -#endif - - dev_priv->mm.phys_objs[id - 1] = phys_obj; - - return 0; -kfree_obj: - kfree(phys_obj); - return ret; -} - -static void i915_gem_free_phys_object(struct drm_device *dev, int id) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_i915_gem_phys_object *phys_obj; - - if (!dev_priv->mm.phys_objs[id - 1]) - return; - - phys_obj = dev_priv->mm.phys_objs[id - 1]; - if (phys_obj->cur_obj) { - i915_gem_detach_phys_object(dev, phys_obj->cur_obj); - } - -#ifdef CONFIG_X86 - set_memory_wb((unsigned long)phys_obj->handle->vaddr, phys_obj->handle->size / PAGE_SIZE); -#endif - drm_pci_free(dev, phys_obj->handle); - kfree(phys_obj); - dev_priv->mm.phys_objs[id - 1] = NULL; -} - -void i915_gem_free_all_phys_object(struct drm_device *dev) -{ - int i; - - for (i = I915_GEM_PHYS_CURSOR_0; i <= I915_MAX_PHYS_OBJECT; i++) - i915_gem_free_phys_object(dev, i); -} - -void i915_gem_detach_phys_object(struct drm_device *dev, - struct drm_i915_gem_object *obj) -{ - struct address_space *mapping = file_inode(obj->base.filp)->i_mapping; - char *vaddr; - int i; - int page_count; - - if (!obj->phys_obj) - return; - vaddr = obj->phys_obj->handle->vaddr; - - page_count = obj->base.size / PAGE_SIZE; - for (i = 0; i < page_count; i++) { - struct page *page = shmem_read_mapping_page(mapping, i); - if (!IS_ERR(page)) { - char *dst = kmap_atomic(page); - memcpy(dst, vaddr + i*PAGE_SIZE, PAGE_SIZE); - kunmap_atomic(dst); - - drm_clflush_pages(&page, 1); - - set_page_dirty(page); - mark_page_accessed(page); - page_cache_release(page); - } - } - i915_gem_chipset_flush(dev); - - obj->phys_obj->cur_obj = NULL; - obj->phys_obj = NULL; -} - -int -i915_gem_attach_phys_object(struct drm_device *dev, - struct drm_i915_gem_object *obj, - int id, - int align) -{ - struct address_space *mapping = file_inode(obj->base.filp)->i_mapping; - struct drm_i915_private *dev_priv = dev->dev_private; - int ret = 0; - int page_count; - int i; - - if (id > I915_MAX_PHYS_OBJECT) - return -EINVAL; - - if (obj->phys_obj) { - if (obj->phys_obj->id == id) - return 0; - i915_gem_detach_phys_object(dev, obj); - } - - /* create a new object */ - if (!dev_priv->mm.phys_objs[id - 1]) { - ret = i915_gem_init_phys_object(dev, id, - obj->base.size, align); - if (ret) { - DRM_ERROR("failed to init phys object %d size: %zu\n", - id, obj->base.size); - return ret; - } - } - - /* bind to the object */ - obj->phys_obj = dev_priv->mm.phys_objs[id - 1]; - obj->phys_obj->cur_obj = obj; - - page_count = obj->base.size / PAGE_SIZE; - - for (i = 0; i < page_count; i++) { - struct page *page; - char *dst, *src; - - page = shmem_read_mapping_page(mapping, i); - if (IS_ERR(page)) - return PTR_ERR(page); - - src = kmap_atomic(page); - dst = obj->phys_obj->handle->vaddr + (i * PAGE_SIZE); - memcpy(dst, src, PAGE_SIZE); - kunmap_atomic(src); - - mark_page_accessed(page); - page_cache_release(page); - } - - return 0; -} - -static int -i915_gem_phys_pwrite(struct drm_device *dev, - struct drm_i915_gem_object *obj, - struct drm_i915_gem_pwrite *args, - struct drm_file *file_priv) -{ - void *vaddr = obj->phys_obj->handle->vaddr + args->offset; - char __user *user_data = to_user_ptr(args->data_ptr); - - if (__copy_from_user_inatomic_nocache(vaddr, user_data, args->size)) { - unsigned long unwritten; - - /* The physical object once assigned is fixed for the lifetime - * of the obj, so we can safely drop the lock and continue - * to access vaddr. - */ - mutex_unlock(&dev->struct_mutex); - unwritten = copy_from_user(vaddr, user_data, args->size); - mutex_lock(&dev->struct_mutex); - if (unwritten) - return -EFAULT; - } - - i915_gem_chipset_flush(dev); - return 0; -} - void i915_gem_release(struct drm_device *dev, struct drm_file *file) { struct drm_i915_file_private *file_priv = file->driver_priv; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 48aa516a1ac0..5b60e25baa32 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -7825,14 +7825,12 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, addr = i915_gem_obj_ggtt_offset(obj); } else { int align = IS_I830(dev) ? 16 * 1024 : 256; - ret = i915_gem_attach_phys_object(dev, obj, - (intel_crtc->pipe == 0) ? I915_GEM_PHYS_CURSOR_0 : I915_GEM_PHYS_CURSOR_1, - align); + ret = i915_gem_object_attach_phys(obj, align); if (ret) { DRM_DEBUG_KMS("failed to attach phys object\n"); goto fail_locked; } - addr = obj->phys_obj->handle->busaddr; + addr = obj->phys_handle->busaddr; } if (IS_GEN2(dev)) @@ -7840,10 +7838,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, finish: if (intel_crtc->cursor_bo) { - if (INTEL_INFO(dev)->cursor_needs_physical) { - if (intel_crtc->cursor_bo != obj) - i915_gem_detach_phys_object(dev, intel_crtc->cursor_bo); - } else + if (!INTEL_INFO(dev)->cursor_needs_physical) i915_gem_object_unpin_from_display_plane(intel_crtc->cursor_bo); drm_gem_object_unreference(&intel_crtc->cursor_bo->base); } diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index d8adc9104dca..129db0c7d835 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -193,7 +193,7 @@ intel_overlay_map_regs(struct intel_overlay *overlay) struct overlay_registers __iomem *regs; if (OVERLAY_NEEDS_PHYSICAL(overlay->dev)) - regs = (struct overlay_registers __iomem *)overlay->reg_bo->phys_obj->handle->vaddr; + regs = (struct overlay_registers __iomem *)overlay->reg_bo->phys_handle->vaddr; else regs = io_mapping_map_wc(dev_priv->gtt.mappable, i915_gem_obj_ggtt_offset(overlay->reg_bo)); @@ -1340,14 +1340,12 @@ void intel_setup_overlay(struct drm_device *dev) overlay->reg_bo = reg_bo; if (OVERLAY_NEEDS_PHYSICAL(dev)) { - ret = i915_gem_attach_phys_object(dev, reg_bo, - I915_GEM_PHYS_OVERLAY_REGS, - PAGE_SIZE); + ret = i915_gem_object_attach_phys(reg_bo, PAGE_SIZE); if (ret) { DRM_ERROR("failed to attach phys overlay regs\n"); goto out_free_bo; } - overlay->flip_addr = reg_bo->phys_obj->handle->busaddr; + overlay->flip_addr = reg_bo->phys_handle->busaddr; } else { ret = i915_gem_obj_ggtt_pin(reg_bo, PAGE_SIZE, PIN_MAPPABLE); if (ret) { @@ -1428,7 +1426,7 @@ intel_overlay_map_regs_atomic(struct intel_overlay *overlay) /* Cast to make sparse happy, but it's wc memory anyway, so * equivalent to the wc io mapping on X86. */ regs = (struct overlay_registers __iomem *) - overlay->reg_bo->phys_obj->handle->vaddr; + overlay->reg_bo->phys_handle->vaddr; else regs = io_mapping_map_atomic_wc(dev_priv->gtt.mappable, i915_gem_obj_ggtt_offset(overlay->reg_bo)); @@ -1462,7 +1460,7 @@ intel_overlay_capture_error_state(struct drm_device *dev) error->dovsta = I915_READ(DOVSTA); error->isr = I915_READ(ISR); if (OVERLAY_NEEDS_PHYSICAL(overlay->dev)) - error->base = (__force long)overlay->reg_bo->phys_obj->handle->vaddr; + error->base = (__force long)overlay->reg_bo->phys_handle->vaddr; else error->base = i915_gem_obj_ggtt_offset(overlay->reg_bo); -- cgit v1.2.3 From 9aab8bff7aa3bee567213ad3c1fdfb217bb980a2 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 23 May 2014 10:45:52 +0100 Subject: drm/i915: Only copy back the modified fields to userspace from execbuffer We only want to modifiy a single field in the userspace view of the execbuffer command buffer, so explicitly change that rather than copy everything back again. This serves two purposes: 1. The single fields are much cheaper to copy (constant size so the copy uses special case code) and much smaller than the whole array. 2. We modify the array for internal use that need to be masked from the user. Note: We need this backported since without it the next bugfix will blow up when userspace recycles batchbuffers and relocations. Signed-off-by: Chris Wilson Cc: Daniel Vetter Cc: stable@vger.kernel.org Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 54 ++++++++++++++++++------------ 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 2c9d9cbaf653..7aaf6390cfaf 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -773,9 +773,9 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev, * relocations were valid. */ for (j = 0; j < exec[i].relocation_count; j++) { - if (copy_to_user(&user_relocs[j].presumed_offset, - &invalid_offset, - sizeof(invalid_offset))) { + if (__copy_to_user(&user_relocs[j].presumed_offset, + &invalid_offset, + sizeof(invalid_offset))) { ret = -EFAULT; mutex_lock(&dev->struct_mutex); goto err; @@ -1355,18 +1355,21 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, ret = i915_gem_do_execbuffer(dev, data, file, &exec2, exec2_list); if (!ret) { + struct drm_i915_gem_exec_object __user *user_exec_list = + to_user_ptr(args->buffers_ptr); + /* Copy the new buffer offsets back to the user's exec list. */ - for (i = 0; i < args->buffer_count; i++) - exec_list[i].offset = exec2_list[i].offset; - /* ... and back out to userspace */ - ret = copy_to_user(to_user_ptr(args->buffers_ptr), - exec_list, - sizeof(*exec_list) * args->buffer_count); - if (ret) { - ret = -EFAULT; - DRM_DEBUG("failed to copy %d exec entries " - "back to user (%d)\n", - args->buffer_count, ret); + for (i = 0; i < args->buffer_count; i++) { + ret = __copy_to_user(&user_exec_list[i].offset, + &exec2_list[i].offset, + sizeof(user_exec_list[i].offset)); + if (ret) { + ret = -EFAULT; + DRM_DEBUG("failed to copy %d exec entries " + "back to user (%d)\n", + args->buffer_count, ret); + break; + } } } @@ -1412,14 +1415,21 @@ i915_gem_execbuffer2(struct drm_device *dev, void *data, ret = i915_gem_do_execbuffer(dev, data, file, args, exec2_list); if (!ret) { /* Copy the new buffer offsets back to the user's exec list. */ - ret = copy_to_user(to_user_ptr(args->buffers_ptr), - exec2_list, - sizeof(*exec2_list) * args->buffer_count); - if (ret) { - ret = -EFAULT; - DRM_DEBUG("failed to copy %d exec entries " - "back to user (%d)\n", - args->buffer_count, ret); + struct drm_i915_gem_exec_object2 *user_exec_list = + to_user_ptr(args->buffers_ptr); + int i; + + for (i = 0; i < args->buffer_count; i++) { + ret = __copy_to_user(&user_exec_list[i].offset, + &exec2_list[i].offset, + sizeof(user_exec_list[i].offset)); + if (ret) { + ret = -EFAULT; + DRM_DEBUG("failed to copy %d exec entries " + "back to user\n", + args->buffer_count); + break; + } } } -- cgit v1.2.3 From d23db88c3ab233daed18709e3a24d6c95344117f Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 23 May 2014 08:48:08 +0200 Subject: drm/i915: Prevent negative relocation deltas from wrapping This is pure evil. Userspace, I'm looking at you SNA, repacks batch buffers on the fly after generation as they are being passed to the kernel for execution. These batches also contain self-referenced relocations as a single buffer encompasses the state commands, kernels, vertices and sampler. During generation the buffers are placed at known offsets within the full batch, and then the relocation deltas (as passed to the kernel) are tweaked as the batch is repacked into a smaller buffer. This means that userspace is passing negative relocations deltas, which subsequently wrap to large values if the batch is at a low address. The GPU hangs when it then tries to use the large value as a base for its address offsets, rather than wrapping back to the real value (as one would hope). As the GPU uses positive offsets from the base, we can treat the relocation address as the minimum address read by the GPU. For the upper bound, we trust that userspace will not read beyond the end of the buffer. So, how do we fix negative relocations from wrapping? We can either check that every relocation looks valid when we write it, and then position each object such that we prevent the offset wraparound, or we just special-case the self-referential behaviour of SNA and force all batches to be above 256k. Daniel prefers the latter approach. This fixes a GPU hang when it tries to use an address (relocation + offset) greater than the GTT size. The issue would occur quite easily with full-ppgtt as each fd gets its own VM space, so low offsets would often be handed out. However, with the rearrangement of the low GTT due to capturing the BIOS framebuffer, it is already affecting kernels 3.15 onwards. I think only IVB+ is susceptible to this bug, but the workaround should only kick in rarely, so it seems sensible to always apply it. v3: Use a bias for batch buffers to prevent small negative delta relocations from wrapping. v4 from Daniel: - s/BIAS/BATCH_OFFSET_BIAS/ - Extract eb_vma_misplaced/i915_vma_misplaced since the conditions were growing rather cumbersome. - Add a comment to eb_get_batch explaining why we do this. - Apply the batch offset bias everywhere but mention that we've only observed it on gen7 gpus. - Drop PIN_OFFSET_FIX for now, that slipped in from a feature patch. v5: Add static to eb_get_batch, spotted by 0-day tester. Testcase: igt/gem_bad_reloc Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=78533 Signed-off-by: Chris Wilson (v3) Cc: stable@vger.kernel.org Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 6 ++- drivers/gpu/drm/i915/i915_gem.c | 46 +++++++++++++----- drivers/gpu/drm/i915/i915_gem_evict.c | 9 ++-- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 76 ++++++++++++++++++++++-------- drivers/gpu/drm/i915/i915_gem_gtt.c | 4 +- 5 files changed, 103 insertions(+), 38 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ec5f6fb42ab3..388c028e223c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2189,10 +2189,12 @@ void i915_gem_vma_destroy(struct i915_vma *vma); #define PIN_MAPPABLE 0x1 #define PIN_NONBLOCK 0x2 #define PIN_GLOBAL 0x4 +#define PIN_OFFSET_BIAS 0x8 +#define PIN_OFFSET_MASK (~4095) int __must_check i915_gem_object_pin(struct drm_i915_gem_object *obj, struct i915_address_space *vm, uint32_t alignment, - unsigned flags); + uint64_t flags); int __must_check i915_vma_unbind(struct i915_vma *vma); int i915_gem_object_put_pages(struct drm_i915_gem_object *obj); void i915_gem_release_all_mmaps(struct drm_i915_private *dev_priv); @@ -2445,6 +2447,8 @@ int __must_check i915_gem_evict_something(struct drm_device *dev, int min_size, unsigned alignment, unsigned cache_level, + unsigned long start, + unsigned long end, unsigned flags); int i915_gem_evict_vm(struct i915_address_space *vm, bool do_idle); int i915_gem_evict_everything(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index b391f30f9985..3326770c9ed2 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3326,12 +3326,14 @@ static struct i915_vma * i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj, struct i915_address_space *vm, unsigned alignment, - unsigned flags) + uint64_t flags) { struct drm_device *dev = obj->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; u32 size, fence_size, fence_alignment, unfenced_alignment; - size_t gtt_max = + unsigned long start = + flags & PIN_OFFSET_BIAS ? flags & PIN_OFFSET_MASK : 0; + unsigned long end = flags & PIN_MAPPABLE ? dev_priv->gtt.mappable_end : vm->total; struct i915_vma *vma; int ret; @@ -3360,11 +3362,11 @@ i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj, /* If the object is bigger than the entire aperture, reject it early * before evicting everything in a vain attempt to find space. */ - if (obj->base.size > gtt_max) { - DRM_DEBUG("Attempting to bind an object larger than the aperture: object=%zd > %s aperture=%zu\n", + if (obj->base.size > end) { + DRM_DEBUG("Attempting to bind an object larger than the aperture: object=%zd > %s aperture=%lu\n", obj->base.size, flags & PIN_MAPPABLE ? "mappable" : "total", - gtt_max); + end); return ERR_PTR(-E2BIG); } @@ -3381,12 +3383,15 @@ i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj, search_free: ret = drm_mm_insert_node_in_range_generic(&vm->mm, &vma->node, size, alignment, - obj->cache_level, 0, gtt_max, + obj->cache_level, + start, end, DRM_MM_SEARCH_DEFAULT, DRM_MM_CREATE_DEFAULT); if (ret) { ret = i915_gem_evict_something(dev, vm, size, alignment, - obj->cache_level, flags); + obj->cache_level, + start, end, + flags); if (ret == 0) goto search_free; @@ -3946,11 +3951,30 @@ i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file) return ret; } +static bool +i915_vma_misplaced(struct i915_vma *vma, uint32_t alignment, uint64_t flags) +{ + struct drm_i915_gem_object *obj = vma->obj; + + if (alignment && + vma->node.start & (alignment - 1)) + return true; + + if (flags & PIN_MAPPABLE && !obj->map_and_fenceable) + return true; + + if (flags & PIN_OFFSET_BIAS && + vma->node.start < (flags & PIN_OFFSET_MASK)) + return true; + + return false; +} + int i915_gem_object_pin(struct drm_i915_gem_object *obj, struct i915_address_space *vm, uint32_t alignment, - unsigned flags) + uint64_t flags) { struct i915_vma *vma; int ret; @@ -3963,15 +3987,13 @@ i915_gem_object_pin(struct drm_i915_gem_object *obj, if (WARN_ON(vma->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT)) return -EBUSY; - if ((alignment && - vma->node.start & (alignment - 1)) || - (flags & PIN_MAPPABLE && !obj->map_and_fenceable)) { + if (i915_vma_misplaced(vma, alignment, flags)) { WARN(vma->pin_count, "bo is already pinned with incorrect alignment:" " offset=%lx, req.alignment=%x, req.map_and_fenceable=%d," " obj->map_and_fenceable=%d\n", i915_gem_obj_offset(obj, vm), alignment, - flags & PIN_MAPPABLE, + !!(flags & PIN_MAPPABLE), obj->map_and_fenceable); ret = i915_vma_unbind(vma); if (ret) diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c index 75fca63dc8c1..bbf4b12d842e 100644 --- a/drivers/gpu/drm/i915/i915_gem_evict.c +++ b/drivers/gpu/drm/i915/i915_gem_evict.c @@ -68,9 +68,9 @@ mark_free(struct i915_vma *vma, struct list_head *unwind) int i915_gem_evict_something(struct drm_device *dev, struct i915_address_space *vm, int min_size, unsigned alignment, unsigned cache_level, + unsigned long start, unsigned long end, unsigned flags) { - struct drm_i915_private *dev_priv = dev->dev_private; struct list_head eviction_list, unwind_list; struct i915_vma *vma; int ret = 0; @@ -102,11 +102,10 @@ i915_gem_evict_something(struct drm_device *dev, struct i915_address_space *vm, */ INIT_LIST_HEAD(&unwind_list); - if (flags & PIN_MAPPABLE) { - BUG_ON(!i915_is_ggtt(vm)); + if (start != 0 || end != vm->total) { drm_mm_init_scan_with_range(&vm->mm, min_size, - alignment, cache_level, 0, - dev_priv->gtt.mappable_end); + alignment, cache_level, + start, end); } else drm_mm_init_scan(&vm->mm, min_size, alignment, cache_level); diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 7aaf6390cfaf..20fef6c50267 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -35,6 +35,9 @@ #define __EXEC_OBJECT_HAS_PIN (1<<31) #define __EXEC_OBJECT_HAS_FENCE (1<<30) +#define __EXEC_OBJECT_NEEDS_BIAS (1<<28) + +#define BATCH_OFFSET_BIAS (256*1024) struct eb_vmas { struct list_head vmas; @@ -545,7 +548,7 @@ i915_gem_execbuffer_reserve_vma(struct i915_vma *vma, struct drm_i915_gem_exec_object2 *entry = vma->exec_entry; bool has_fenced_gpu_access = INTEL_INFO(ring->dev)->gen < 4; bool need_fence; - unsigned flags; + uint64_t flags; int ret; flags = 0; @@ -559,6 +562,8 @@ i915_gem_execbuffer_reserve_vma(struct i915_vma *vma, if (entry->flags & EXEC_OBJECT_NEEDS_GTT) flags |= PIN_GLOBAL; + if (entry->flags & __EXEC_OBJECT_NEEDS_BIAS) + flags |= BATCH_OFFSET_BIAS | PIN_OFFSET_BIAS; ret = i915_gem_object_pin(obj, vma->vm, entry->alignment, flags); if (ret) @@ -592,6 +597,36 @@ i915_gem_execbuffer_reserve_vma(struct i915_vma *vma, return 0; } +static bool +eb_vma_misplaced(struct i915_vma *vma, bool has_fenced_gpu_access) +{ + struct drm_i915_gem_exec_object2 *entry = vma->exec_entry; + struct drm_i915_gem_object *obj = vma->obj; + bool need_fence, need_mappable; + + need_fence = + has_fenced_gpu_access && + entry->flags & EXEC_OBJECT_NEEDS_FENCE && + obj->tiling_mode != I915_TILING_NONE; + need_mappable = need_fence || need_reloc_mappable(vma); + + WARN_ON((need_mappable || need_fence) && + !i915_is_ggtt(vma->vm)); + + if (entry->alignment && + vma->node.start & (entry->alignment - 1)) + return true; + + if (need_mappable && !obj->map_and_fenceable) + return true; + + if (entry->flags & __EXEC_OBJECT_NEEDS_BIAS && + vma->node.start < BATCH_OFFSET_BIAS) + return true; + + return false; +} + static int i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring, struct list_head *vmas, @@ -653,26 +688,10 @@ i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring, /* Unbind any ill-fitting objects or pin. */ list_for_each_entry(vma, vmas, exec_list) { - struct drm_i915_gem_exec_object2 *entry = vma->exec_entry; - bool need_fence, need_mappable; - - obj = vma->obj; - if (!drm_mm_node_allocated(&vma->node)) continue; - need_fence = - has_fenced_gpu_access && - entry->flags & EXEC_OBJECT_NEEDS_FENCE && - obj->tiling_mode != I915_TILING_NONE; - need_mappable = need_fence || need_reloc_mappable(vma); - - WARN_ON((need_mappable || need_fence) && - !i915_is_ggtt(vma->vm)); - - if ((entry->alignment && - vma->node.start & (entry->alignment - 1)) || - (need_mappable && !obj->map_and_fenceable)) + if (eb_vma_misplaced(vma, has_fenced_gpu_access)) ret = i915_vma_unbind(vma); else ret = i915_gem_execbuffer_reserve_vma(vma, ring, need_relocs); @@ -999,6 +1018,25 @@ i915_reset_gen7_sol_offsets(struct drm_device *dev, return 0; } +static struct drm_i915_gem_object * +eb_get_batch(struct eb_vmas *eb) +{ + struct i915_vma *vma = list_entry(eb->vmas.prev, typeof(*vma), exec_list); + + /* + * SNA is doing fancy tricks with compressing batch buffers, which leads + * to negative relocation deltas. Usually that works out ok since the + * relocate address is still positive, except when the batch is placed + * very low in the GTT. Ensure this doesn't happen. + * + * Note that actual hangs have only been observed on gen7, but for + * paranoia do it everywhere. + */ + vma->exec_entry->flags |= __EXEC_OBJECT_NEEDS_BIAS; + + return vma->obj; +} + static int i915_gem_do_execbuffer(struct drm_device *dev, void *data, struct drm_file *file, @@ -1153,7 +1191,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, goto err; /* take note of the batch buffer before we might reorder the lists */ - batch_obj = list_entry(eb->vmas.prev, struct i915_vma, exec_list)->obj; + batch_obj = eb_get_batch(eb); /* Move the objects en-masse into the GTT, evicting if necessary. */ need_relocs = (args->flags & I915_EXEC_NO_RELOC) == 0; diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 154b0f8bb88d..5deb22864c52 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -1089,7 +1089,9 @@ alloc: if (ret == -ENOSPC && !retried) { ret = i915_gem_evict_something(dev, &dev_priv->gtt.base, GEN6_PD_SIZE, GEN6_PD_ALIGN, - I915_CACHE_NONE, 0); + I915_CACHE_NONE, + 0, dev_priv->gtt.base.total, + 0); if (ret) return ret; -- cgit v1.2.3 From f1daa838e861ae1a0fb7cd9721a21258430fcc8c Mon Sep 17 00:00:00 2001 From: Heinz Mauelshagen Date: Fri, 23 May 2014 14:10:01 -0400 Subject: dm cache: always split discards on cache block boundaries The DM cache target cannot cope with discards that span multiple cache blocks, so each discard bio that spans more than one cache block must get split by the DM core. Signed-off-by: Heinz Mauelshagen Acked-by: Joe Thornber Signed-off-by: Mike Snitzer Cc: stable@vger.kernel.org # v3.9+ --- drivers/md/dm-cache-target.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c index 9380be7b1895..5f054c44b485 100644 --- a/drivers/md/dm-cache-target.c +++ b/drivers/md/dm-cache-target.c @@ -2178,6 +2178,8 @@ static int cache_create(struct cache_args *ca, struct cache **result) ti->num_discard_bios = 1; ti->discards_supported = true; ti->discard_zeroes_data_unsupported = true; + /* Discard bios must be split on a block boundary */ + ti->split_discard_bios = true; cache->features = ca->features; ti->per_bio_data_size = get_per_bio_data_size(cache); -- cgit v1.2.3 From aa0818c6ee8d8e4772725a43550823347bc1ad30 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Fri, 16 May 2014 23:31:21 +0800 Subject: virtio_blk: fix race between start and stop queue When there isn't enough vring descriptor for adding to vq, blk-mq will be put as stopped state until some of pending descriptors are completed & freed. Unfortunately, the vq's interrupt may come just before blk-mq's BLK_MQ_S_STOPPED flag is set, so the blk-mq will still be kept as stopped even though lots of descriptors are completed and freed in the interrupt handler. The worst case is that all pending descriptors are freed in the interrupt handler, and the queue is kept as stopped forever. This patch fixes the problem by starting/stopping blk-mq with holding vq_lock. Cc: Jens Axboe Cc: Rusty Russell Signed-off-by: Ming Lei Cc: stable@kernel.org Signed-off-by: Jens Axboe Conflicts: drivers/block/virtio_blk.c --- drivers/block/virtio_blk.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 6d8a87f252de..cb9b1f8326c3 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -144,11 +144,11 @@ static void virtblk_done(struct virtqueue *vq) if (unlikely(virtqueue_is_broken(vq))) break; } while (!virtqueue_enable_cb(vq)); - spin_unlock_irqrestore(&vblk->vq_lock, flags); /* In case queue is stopped waiting for more buffers. */ if (req_done) blk_mq_start_stopped_hw_queues(vblk->disk->queue); + spin_unlock_irqrestore(&vblk->vq_lock, flags); } static int virtio_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *req) @@ -202,8 +202,8 @@ static int virtio_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *req) err = __virtblk_add_req(vblk->vq, vbr, vbr->sg, num); if (err) { virtqueue_kick(vblk->vq); - spin_unlock_irqrestore(&vblk->vq_lock, flags); blk_mq_stop_hw_queue(hctx); + spin_unlock_irqrestore(&vblk->vq_lock, flags); /* Out of mem doesn't actually happen, since we fall back * to direct descriptors */ if (err == -ENOMEM || err == -ENOSPC) -- cgit v1.2.3 From 63d832c30142cdceb478b1cac7d943d83b95b2dc Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Mon, 26 May 2014 14:45:39 +0200 Subject: dm mpath: really fix lockdep warning lockdep complains about a circular locking. And indeed, we need to release the lock before calling dm_table_run_md_queue_async(). As such, commit 4cdd2ad ("dm mpath: fix lock order inconsistency in multipath_ioctl") must also be reverted in addition to fixing the lock order in the other dm_table_run_md_queue_async() callers. Reported-by: Bart van Assche Tested-by: Bart van Assche Signed-off-by: Hannes Reinecke Signed-off-by: Mike Snitzer --- drivers/md/dm-mpath.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index fa0f6cbd6a41..ebfa411d1a7d 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c @@ -445,11 +445,11 @@ static int queue_if_no_path(struct multipath *m, unsigned queue_if_no_path, else m->saved_queue_if_no_path = queue_if_no_path; m->queue_if_no_path = queue_if_no_path; - if (!m->queue_if_no_path) - dm_table_run_md_queue_async(m->ti->table); - spin_unlock_irqrestore(&m->lock, flags); + if (!queue_if_no_path) + dm_table_run_md_queue_async(m->ti->table); + return 0; } @@ -954,7 +954,7 @@ out: */ static int reinstate_path(struct pgpath *pgpath) { - int r = 0; + int r = 0, run_queue = 0; unsigned long flags; struct multipath *m = pgpath->pg->m; @@ -978,7 +978,7 @@ static int reinstate_path(struct pgpath *pgpath) if (!m->nr_valid_paths++) { m->current_pgpath = NULL; - dm_table_run_md_queue_async(m->ti->table); + run_queue = 1; } else if (m->hw_handler_name && (m->current_pg == pgpath->pg)) { if (queue_work(kmpath_handlerd, &pgpath->activate_path.work)) m->pg_init_in_progress++; @@ -991,6 +991,8 @@ static int reinstate_path(struct pgpath *pgpath) out: spin_unlock_irqrestore(&m->lock, flags); + if (run_queue) + dm_table_run_md_queue_async(m->ti->table); return r; } @@ -1566,8 +1568,8 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd, } if (m->pg_init_required) __pg_init_all_paths(m); - dm_table_run_md_queue_async(m->ti->table); spin_unlock_irqrestore(&m->lock, flags); + dm_table_run_md_queue_async(m->ti->table); } return r ? : __blkdev_driver_ioctl(bdev, mode, cmd, arg); -- cgit v1.2.3 From 1b0fe6be858d47e7e80fe0adc47c7366f5924244 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Tue, 27 May 2014 15:58:09 +0200 Subject: MAINTAINERS: Add reset controller framework entry Signed-off-by: Philipp Zabel Signed-off-by: Olof Johansson --- MAINTAINERS | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 6846c7c622e3..875d2f53d3e3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7405,6 +7405,14 @@ F: drivers/rpmsg/ F: Documentation/rpmsg.txt F: include/linux/rpmsg.h +RESET CONTROLLER FRAMEWORK +M: Philipp Zabel +S: Maintained +F: drivers/reset/ +F: Documentation/devicetree/bindings/reset/ +F: include/linux/reset.h +F: include/linux/reset-controller.h + RFKILL M: Johannes Berg L: linux-wireless@vger.kernel.org -- cgit v1.2.3 From 7998eb3dc700aaf499f93f50b3d77da834ef9e1d Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Thu, 15 May 2014 09:33:42 -0700 Subject: powerpc: Fix 64 bit builds with binutils 2.24 With binutils 2.24, various 64 bit builds fail with relocation errors such as arch/powerpc/kernel/built-in.o: In function `exc_debug_crit_book3e': (.text+0x165ee): relocation truncated to fit: R_PPC64_ADDR16_HI against symbol `interrupt_base_book3e' defined in .text section in arch/powerpc/kernel/built-in.o arch/powerpc/kernel/built-in.o: In function `exc_debug_crit_book3e': (.text+0x16602): relocation truncated to fit: R_PPC64_ADDR16_HI against symbol `interrupt_end_book3e' defined in .text section in arch/powerpc/kernel/built-in.o The assembler maintainer says: I changed the ABI, something that had to be done but unfortunately happens to break the booke kernel code. When building up a 64-bit value with lis, ori, shl, oris, ori or similar sequences, you now should use @high and @higha in place of @h and @ha. @h and @ha (and their associated relocs R_PPC64_ADDR16_HI and R_PPC64_ADDR16_HA) now report overflow if the value is out of 32-bit signed range. ie. @h and @ha assume you're building a 32-bit value. This is needed to report out-of-range -mcmodel=medium toc pointer offsets in @toc@h and @toc@ha expressions, and for consistency I did the same for all other @h and @ha relocs. Replacing @h with @high in one strategic location fixes the relocation errors. This has to be done conditionally since the assembler either supports @h or @high but not both. Cc: Signed-off-by: Guenter Roeck Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/Makefile | 4 +++- arch/powerpc/include/asm/ppc_asm.h | 7 ++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index 4c0cedf4e2c7..ce4c68a4a823 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile @@ -150,7 +150,9 @@ endif CFLAGS-$(CONFIG_TUNE_CELL) += $(call cc-option,-mtune=cell) -KBUILD_CPPFLAGS += -Iarch/$(ARCH) +asinstr := $(call as-instr,lis 9$(comma)foo@high,-DHAVE_AS_ATHIGH=1) + +KBUILD_CPPFLAGS += -Iarch/$(ARCH) $(asinstr) KBUILD_AFLAGS += -Iarch/$(ARCH) KBUILD_CFLAGS += -msoft-float -pipe -Iarch/$(ARCH) $(CFLAGS-y) CPP = $(CC) -E $(KBUILD_CFLAGS) diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h index 6586a40a46ce..cded7c1278ef 100644 --- a/arch/powerpc/include/asm/ppc_asm.h +++ b/arch/powerpc/include/asm/ppc_asm.h @@ -318,11 +318,16 @@ n: addi reg,reg,(name - 0b)@l; #ifdef __powerpc64__ +#ifdef HAVE_AS_ATHIGH +#define __AS_ATHIGH high +#else +#define __AS_ATHIGH h +#endif #define LOAD_REG_IMMEDIATE(reg,expr) \ lis reg,(expr)@highest; \ ori reg,reg,(expr)@higher; \ rldicr reg,reg,32,31; \ - oris reg,reg,(expr)@h; \ + oris reg,reg,(expr)@__AS_ATHIGH; \ ori reg,reg,(expr)@l; #define LOAD_REG_ADDR(reg,name) \ -- cgit v1.2.3 From 011e4b02f1da156ac7fea28a9da878f3c23af739 Mon Sep 17 00:00:00 2001 From: "Srivatsa S. Bhat" Date: Tue, 27 May 2014 16:25:34 +0530 Subject: powerpc, kexec: Fix "Processor X is stuck" issue during kexec from ST mode If we try to perform a kexec when the machine is in ST (Single-Threaded) mode (ppc64_cpu --smt=off), the kexec operation doesn't succeed properly, and we get the following messages during boot: [ 0.089866] POWER8 performance monitor hardware support registered [ 0.089985] power8-pmu: PMAO restore workaround active. [ 5.095419] Processor 1 is stuck. [ 10.097933] Processor 2 is stuck. [ 15.100480] Processor 3 is stuck. [ 20.102982] Processor 4 is stuck. [ 25.105489] Processor 5 is stuck. [ 30.108005] Processor 6 is stuck. [ 35.110518] Processor 7 is stuck. [ 40.113369] Processor 9 is stuck. [ 45.115879] Processor 10 is stuck. [ 50.118389] Processor 11 is stuck. [ 55.120904] Processor 12 is stuck. [ 60.123425] Processor 13 is stuck. [ 65.125970] Processor 14 is stuck. [ 70.128495] Processor 15 is stuck. [ 75.131316] Processor 17 is stuck. Note that only the sibling threads are stuck, while the primary threads (0, 8, 16 etc) boot just fine. Looking closer at the previous step of kexec, we observe that kexec tries to wakeup (bring online) the sibling threads of all the cores, before performing kexec: [ 9464.131231] Starting new kernel [ 9464.148507] kexec: Waking offline cpu 1. [ 9464.148552] kexec: Waking offline cpu 2. [ 9464.148600] kexec: Waking offline cpu 3. [ 9464.148636] kexec: Waking offline cpu 4. [ 9464.148671] kexec: Waking offline cpu 5. [ 9464.148708] kexec: Waking offline cpu 6. [ 9464.148743] kexec: Waking offline cpu 7. [ 9464.148779] kexec: Waking offline cpu 9. [ 9464.148815] kexec: Waking offline cpu 10. [ 9464.148851] kexec: Waking offline cpu 11. [ 9464.148887] kexec: Waking offline cpu 12. [ 9464.148922] kexec: Waking offline cpu 13. [ 9464.148958] kexec: Waking offline cpu 14. [ 9464.148994] kexec: Waking offline cpu 15. [ 9464.149030] kexec: Waking offline cpu 17. Instrumenting this piece of code revealed that the cpu_up() operation actually fails with -EBUSY. Thus, only the primary threads of all the cores are online during kexec, and hence this is a sure-shot receipe for disaster, as explained in commit e8e5c2155b (powerpc/kexec: Fix orphaned offline CPUs across kexec), as well as in the comment above wake_offline_cpus(). It turns out that cpu_up() was returning -EBUSY because the variable 'cpu_hotplug_disabled' was set to 1; and this disabling of CPU hotplug was done by migrate_to_reboot_cpu() inside kernel_kexec(). Now, migrate_to_reboot_cpu() was originally written with the assumption that any further code will not need to perform CPU hotplug, since we are anyway in the reboot path. However, kexec is clearly not such a case, since we depend on onlining CPUs, atleast on powerpc. So re-enable cpu-hotplug after returning from migrate_to_reboot_cpu() in the kexec path, to fix this regression in kexec on powerpc. Also, wrap the cpu_up() in powerpc kexec code within a WARN_ON(), so that we can catch such issues more easily in the future. Fixes: c97102ba963 (kexec: migrate to reboot cpu) Cc: stable@vger.kernel.org Signed-off-by: Srivatsa S. Bhat Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/kernel/machine_kexec_64.c | 2 +- kernel/kexec.c | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/kernel/machine_kexec_64.c b/arch/powerpc/kernel/machine_kexec_64.c index 59d229a2a3e0..879b3aacac32 100644 --- a/arch/powerpc/kernel/machine_kexec_64.c +++ b/arch/powerpc/kernel/machine_kexec_64.c @@ -237,7 +237,7 @@ static void wake_offline_cpus(void) if (!cpu_online(cpu)) { printk(KERN_INFO "kexec: Waking offline cpu %d.\n", cpu); - cpu_up(cpu); + WARN_ON(cpu_up(cpu)); } } } diff --git a/kernel/kexec.c b/kernel/kexec.c index c8380ad203bc..28c57069ef68 100644 --- a/kernel/kexec.c +++ b/kernel/kexec.c @@ -1683,6 +1683,14 @@ int kernel_kexec(void) kexec_in_progress = true; kernel_restart_prepare(NULL); migrate_to_reboot_cpu(); + + /* + * migrate_to_reboot_cpu() disables CPU hotplug assuming that + * no further code needs to use CPU hotplug (which is true in + * the reboot case). However, the kexec path depends on using + * CPU hotplug again; so re-enable it here. + */ + cpu_hotplug_enable(); printk(KERN_EMERG "Starting new kernel\n"); machine_shutdown(); } -- cgit v1.2.3 From b6dd6f4738837439c520e73995ec93fe1de2ec72 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Tue, 27 May 2014 16:41:16 +0200 Subject: vfs: fix vmplice_to_user() Commit 6130f5315ee8 "switch vmsplice_to_user() to copy_page_to_iter()" in v3.15-rc1 broke vmsplice(2). This patch fixes two bugs: - count is not initialized to a proper value, which resulted in no data being copied - if rw_copy_check_uvector() returns negative then the iov might be leaked. Tested OK. Signed-off-by: Miklos Szeredi Signed-off-by: Al Viro --- fs/splice.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fs/splice.c b/fs/splice.c index 9bc07d2b53cf..e246954ea48c 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -1537,7 +1537,7 @@ static long vmsplice_to_user(struct file *file, const struct iovec __user *uiov, struct iovec iovstack[UIO_FASTIOV]; struct iovec *iov = iovstack; struct iov_iter iter; - ssize_t count = 0; + ssize_t count; pipe = get_pipe_info(file); if (!pipe) @@ -1546,8 +1546,9 @@ static long vmsplice_to_user(struct file *file, const struct iovec __user *uiov, ret = rw_copy_check_uvector(READ, uiov, nr_segs, ARRAY_SIZE(iovstack), iovstack, &iov); if (ret <= 0) - return ret; + goto out; + count = ret; iov_iter_init(&iter, iov, nr_segs, count, 0); sd.len = 0; @@ -1560,6 +1561,7 @@ static long vmsplice_to_user(struct file *file, const struct iovec __user *uiov, ret = __splice_from_pipe(pipe, &sd, pipe_to_user); pipe_unlock(pipe); +out: if (iov != iovstack) kfree(iov); -- cgit v1.2.3 From bb6c0bd3fdb67c8a1fceea1d4700b9ee593309f9 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 28 May 2014 08:36:23 +0200 Subject: MIPS: SB1: Fix excessive kernel warnings. A kernel build with binutils 2.24 is going to emit warnings like CC kernel/sys.o {standard input}: Assembler messages: {standard input}:701: Warning: the 32-bit MIPS architecture does not support the `mdmx' extension {standard input}:701: Warning: the `mdmx' extension requires 64-bit FPRs {standard input}:701: Warning: the `mips3d' extension requires MIPS32 revision 2 or greater {standard input}:701: Warning: the `mips3d' extension requires 64-bit FPRs for almost every file. This is caused by changes to gas' interpretation of .set semantics. Fixed by explicitly disabling MIPS3D and MDMX for Sibyte builds. Signed-off-by: Ralf Baechle --- arch/mips/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 1a5b4032cb66..60a359cfa328 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -151,7 +151,7 @@ cflags-$(CONFIG_CPU_NEVADA) += $(call cc-option,-march=rm5200,-march=r5000) \ -Wa,--trap cflags-$(CONFIG_CPU_RM7000) += $(call cc-option,-march=rm7000,-march=r5000) \ -Wa,--trap -cflags-$(CONFIG_CPU_SB1) += $(call cc-option,-march=sb1,-march=r5000) \ +cflags-$(CONFIG_CPU_SB1) += $(call cc-option,-march=sb1 -mno-mdmx -mno-mips3d,-march=r5000) \ -Wa,--trap cflags-$(CONFIG_CPU_R8000) += -march=r8000 -Wa,--trap cflags-$(CONFIG_CPU_R10000) += $(call cc-option,-march=r10000,-march=r8000) \ -- cgit v1.2.3 From f02ffb199d3af57407a79075f3e0e6c0e8980b6c Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Tue, 13 May 2014 17:07:04 +0200 Subject: MIPS: Lemote 2F: cs5536: mfgpt: use raw locks The lock is taken in the raw irq path and therefore a rawlock should be used instead of a normal spinlock. While here I drop the export symbol on that variable since there are no other users. Signed-off-by: Sebastian Andrzej Siewior Cc: linux-mips@linux-mips.org Cc: Hua Yan Cc: Huacai Chen Cc: Alex Smith Cc: Hongliang Tao Cc: Wu Zhangjin Patchwork: https://patchwork.linux-mips.org/patch/6936/ Signed-off-by: Ralf Baechle --- arch/mips/loongson/common/cs5536/cs5536_mfgpt.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c b/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c index c639b9db0012..12c75db23420 100644 --- a/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c +++ b/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c @@ -27,8 +27,7 @@ #include -DEFINE_SPINLOCK(mfgpt_lock); -EXPORT_SYMBOL(mfgpt_lock); +static DEFINE_RAW_SPINLOCK(mfgpt_lock); static u32 mfgpt_base; @@ -55,7 +54,7 @@ EXPORT_SYMBOL(enable_mfgpt0_counter); static void init_mfgpt_timer(enum clock_event_mode mode, struct clock_event_device *evt) { - spin_lock(&mfgpt_lock); + raw_spin_lock(&mfgpt_lock); switch (mode) { case CLOCK_EVT_MODE_PERIODIC: @@ -79,7 +78,7 @@ static void init_mfgpt_timer(enum clock_event_mode mode, /* Nothing to do here */ break; } - spin_unlock(&mfgpt_lock); + raw_spin_unlock(&mfgpt_lock); } static struct clock_event_device mfgpt_clockevent = { @@ -157,7 +156,7 @@ static cycle_t mfgpt_read(struct clocksource *cs) static int old_count; static u32 old_jifs; - spin_lock_irqsave(&mfgpt_lock, flags); + raw_spin_lock_irqsave(&mfgpt_lock, flags); /* * Although our caller may have the read side of xtime_lock, * this is now a seqlock, and we are cheating in this routine @@ -191,7 +190,7 @@ static cycle_t mfgpt_read(struct clocksource *cs) old_count = count; old_jifs = jifs; - spin_unlock_irqrestore(&mfgpt_lock, flags); + raw_spin_unlock_irqrestore(&mfgpt_lock, flags); return (cycle_t) (jifs * COMPARE) + count; } -- cgit v1.2.3 From 57c7ea513f0e4b033ba602550992e2ca0e6b8d2c Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Thu, 1 May 2014 12:51:19 +0100 Subject: MIPS: ptrace: Avoid smp_processor_id() in preemptible code ptrace_{get,set}_watch_regs access current_cpu_data to get the watch register count/masks, which calls smp_processor_id(). However they are run in preemptible context and therefore trigger warnings like so: [ 6340.092000] BUG: using smp_processor_id() in preemptible [00000000] code: gdb/367 [ 6340.092000] caller is ptrace_get_watch_regs+0x44/0x220 Since the watch register count/masks should be the same across all CPUs, use boot_cpu_data instead. Note that this may need to change in future should a heterogenous system be supported where the count/masks are not the same across all CPUs (the current code is also incorrect for this scenario - current_cpu_data here would not necessarily be correct for the CPU that the target task will execute on). Signed-off-by: Alex Smith Reviewed-by: Paul Burton Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/6879/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/ptrace.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 71f85f427034..f639ccd5060c 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -163,7 +163,7 @@ int ptrace_get_watch_regs(struct task_struct *child, enum pt_watch_style style; int i; - if (!cpu_has_watch || current_cpu_data.watch_reg_use_cnt == 0) + if (!cpu_has_watch || boot_cpu_data.watch_reg_use_cnt == 0) return -EIO; if (!access_ok(VERIFY_WRITE, addr, sizeof(struct pt_watch_regs))) return -EIO; @@ -177,14 +177,14 @@ int ptrace_get_watch_regs(struct task_struct *child, #endif __put_user(style, &addr->style); - __put_user(current_cpu_data.watch_reg_use_cnt, + __put_user(boot_cpu_data.watch_reg_use_cnt, &addr->WATCH_STYLE.num_valid); - for (i = 0; i < current_cpu_data.watch_reg_use_cnt; i++) { + for (i = 0; i < boot_cpu_data.watch_reg_use_cnt; i++) { __put_user(child->thread.watch.mips3264.watchlo[i], &addr->WATCH_STYLE.watchlo[i]); __put_user(child->thread.watch.mips3264.watchhi[i] & 0xfff, &addr->WATCH_STYLE.watchhi[i]); - __put_user(current_cpu_data.watch_reg_masks[i], + __put_user(boot_cpu_data.watch_reg_masks[i], &addr->WATCH_STYLE.watch_masks[i]); } for (; i < 8; i++) { @@ -204,12 +204,12 @@ int ptrace_set_watch_regs(struct task_struct *child, unsigned long lt[NUM_WATCH_REGS]; u16 ht[NUM_WATCH_REGS]; - if (!cpu_has_watch || current_cpu_data.watch_reg_use_cnt == 0) + if (!cpu_has_watch || boot_cpu_data.watch_reg_use_cnt == 0) return -EIO; if (!access_ok(VERIFY_READ, addr, sizeof(struct pt_watch_regs))) return -EIO; /* Check the values. */ - for (i = 0; i < current_cpu_data.watch_reg_use_cnt; i++) { + for (i = 0; i < boot_cpu_data.watch_reg_use_cnt; i++) { __get_user(lt[i], &addr->WATCH_STYLE.watchlo[i]); #ifdef CONFIG_32BIT if (lt[i] & __UA_LIMIT) @@ -228,7 +228,7 @@ int ptrace_set_watch_regs(struct task_struct *child, return -EINVAL; } /* Install them. */ - for (i = 0; i < current_cpu_data.watch_reg_use_cnt; i++) { + for (i = 0; i < boot_cpu_data.watch_reg_use_cnt; i++) { if (lt[i] & 7) watch_active = 1; child->thread.watch.mips3264.watchlo[i] = lt[i]; -- cgit v1.2.3 From f3f0d95146901a94eff8fe723eef2a6daf0ae152 Mon Sep 17 00:00:00 2001 From: Thomas Bogendoerfer Date: Tue, 8 Apr 2014 08:58:01 +0200 Subject: MIPS: R46000: Fix Micro-assembler field overflow for R4600 V2 Fix uasm warning, which triggered because of workaround for R4600 V2 CPUs. Signed-off-by: Thomas Bogendoerfer Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/6716/ Signed-off-by: Ralf Baechle --- arch/mips/mm/page.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/mips/mm/page.c b/arch/mips/mm/page.c index 58033c44690d..b611102e23b5 100644 --- a/arch/mips/mm/page.c +++ b/arch/mips/mm/page.c @@ -273,7 +273,7 @@ void build_clear_page(void) uasm_i_ori(&buf, A2, A0, off); if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x()) - uasm_i_lui(&buf, AT, 0xa000); + uasm_i_lui(&buf, AT, uasm_rel_hi(0xa0000000)); off = cache_line_size ? min(8, pref_bias_clear_store / cache_line_size) * cache_line_size : 0; @@ -424,7 +424,7 @@ void build_copy_page(void) uasm_i_ori(&buf, A2, A0, off); if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x()) - uasm_i_lui(&buf, AT, 0xa000); + uasm_i_lui(&buf, AT, uasm_rel_hi(0xa0000000)); off = cache_line_size ? min(8, pref_bias_copy_load / cache_line_size) * cache_line_size : 0; -- cgit v1.2.3 From 64fd72e0a44bdd62c5ca277cb24d0d02b2d8e9dc Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 28 May 2014 09:48:44 -0400 Subject: lift the "already marked killed" case into shrink_dentry_list() It can happen only when dentry_kill() is called with unlock_on_failure equal to 0 - other callers had dentry pinned until the moment they've got ->d_lock and DCACHE_DENTRY_KILLED is set only after lockref_mark_dead(). IOW, only one of three call sites of dentry_kill() might end up reaching that code. Just move it there. Signed-off-by: Al Viro --- fs/dcache.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/fs/dcache.c b/fs/dcache.c index 42ae01eefc07..6888dde4d568 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -455,12 +455,6 @@ dentry_kill(struct dentry *dentry, int unlock_on_failure) struct dentry *parent = NULL; bool can_free = true; - if (unlikely(dentry->d_flags & DCACHE_DENTRY_KILLED)) { - can_free = dentry->d_flags & DCACHE_MAY_FREE; - spin_unlock(&dentry->d_lock); - goto out; - } - inode = dentry->d_inode; if (inode && !spin_trylock(&inode->i_lock)) { relock: @@ -815,6 +809,15 @@ static void shrink_dentry_list(struct list_head *list) continue; } + + if (unlikely(dentry->d_flags & DCACHE_DENTRY_KILLED)) { + bool can_free = dentry->d_flags & DCACHE_MAY_FREE; + spin_unlock(&dentry->d_lock); + if (can_free) + dentry_free(dentry); + continue; + } + parent = dentry_kill(dentry, 0); /* * If dentry_kill returns NULL, we have nothing more to do. -- cgit v1.2.3 From 397335f004f41e5fcf7a795e94eb3ab83411a17c Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 22 May 2014 03:25:39 +0000 Subject: rtmutex: Fix deadlock detector for real The current deadlock detection logic does not work reliably due to the following early exit path: /* * Drop out, when the task has no waiters. Note, * top_waiter can be NULL, when we are in the deboosting * mode! */ if (top_waiter && (!task_has_pi_waiters(task) || top_waiter != task_top_pi_waiter(task))) goto out_unlock_pi; So this not only exits when the task has no waiters, it also exits unconditionally when the current waiter is not the top priority waiter of the task. So in a nested locking scenario, it might abort the lock chain walk and therefor miss a potential deadlock. Simple fix: Continue the chain walk, when deadlock detection is enabled. We also avoid the whole enqueue, if we detect the deadlock right away (A-A). It's an optimization, but also prevents that another waiter who comes in after the detection and before the task has undone the damage observes the situation and detects the deadlock and returns -EDEADLOCK, which is wrong as the other task is not in a deadlock situation. Signed-off-by: Thomas Gleixner Cc: Peter Zijlstra Reviewed-by: Steven Rostedt Cc: Lai Jiangshan Cc: stable@vger.kernel.org Link: http://lkml.kernel.org/r/20140522031949.725272460@linutronix.de Signed-off-by: Thomas Gleixner --- kernel/locking/rtmutex.c | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/kernel/locking/rtmutex.c b/kernel/locking/rtmutex.c index aa4dff04b594..a620d4d08ca6 100644 --- a/kernel/locking/rtmutex.c +++ b/kernel/locking/rtmutex.c @@ -343,9 +343,16 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task, * top_waiter can be NULL, when we are in the deboosting * mode! */ - if (top_waiter && (!task_has_pi_waiters(task) || - top_waiter != task_top_pi_waiter(task))) - goto out_unlock_pi; + if (top_waiter) { + if (!task_has_pi_waiters(task)) + goto out_unlock_pi; + /* + * If deadlock detection is off, we stop here if we + * are not the top pi waiter of the task. + */ + if (!detect_deadlock && top_waiter != task_top_pi_waiter(task)) + goto out_unlock_pi; + } /* * When deadlock detection is off then we check, if further @@ -361,7 +368,12 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task, goto retry; } - /* Deadlock detection */ + /* + * Deadlock detection. If the lock is the same as the original + * lock which caused us to walk the lock chain or if the + * current lock is owned by the task which initiated the chain + * walk, we detected a deadlock. + */ if (lock == orig_lock || rt_mutex_owner(lock) == top_task) { debug_rt_mutex_deadlock(deadlock_detect, orig_waiter, lock); raw_spin_unlock(&lock->wait_lock); @@ -527,6 +539,18 @@ static int task_blocks_on_rt_mutex(struct rt_mutex *lock, unsigned long flags; int chain_walk = 0, res; + /* + * Early deadlock detection. We really don't want the task to + * enqueue on itself just to untangle the mess later. It's not + * only an optimization. We drop the locks, so another waiter + * can come in before the chain walk detects the deadlock. So + * the other will detect the deadlock and return -EDEADLOCK, + * which is wrong, as the other waiter is not in a deadlock + * situation. + */ + if (detect_deadlock && owner == task) + return -EDEADLK; + raw_spin_lock_irqsave(&task->pi_lock, flags); __rt_mutex_adjust_prio(task); waiter->task = task; -- cgit v1.2.3 From 3f8517e7937d04ac7df9082c741fefc9c873065b Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Fri, 23 May 2014 22:31:44 +0100 Subject: ARM: 8063/1: bL_switcher: fix individual online status reporting of removed CPUs The content of /sys/devices/system/cpu/cpu*/online is still 1 for those CPUs that the switcher has removed even though the global state in /sys/devices/system/cpu/online is updated correctly. It turns out that commit 0902a9044f ("Driver core: Use generic offline/online for CPU offline/online") has changed the way those files retrieve their content by relying on on the generic attribute handling code. The switcher, by calling cpu_down() directly, bypasses this handling and the attribute value doesn't get updated. Fix this by calling device_offline()/device_online() instead. Signed-off-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/common/bL_switcher.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/arch/arm/common/bL_switcher.c b/arch/arm/common/bL_switcher.c index f01c0ee0c87e..490f3dced749 100644 --- a/arch/arm/common/bL_switcher.c +++ b/arch/arm/common/bL_switcher.c @@ -433,8 +433,12 @@ static void bL_switcher_restore_cpus(void) { int i; - for_each_cpu(i, &bL_switcher_removed_logical_cpus) - cpu_up(i); + for_each_cpu(i, &bL_switcher_removed_logical_cpus) { + struct device *cpu_dev = get_cpu_device(i); + int ret = device_online(cpu_dev); + if (ret) + dev_err(cpu_dev, "switcher: unable to restore CPU\n"); + } } static int bL_switcher_halve_cpus(void) @@ -521,7 +525,7 @@ static int bL_switcher_halve_cpus(void) continue; } - ret = cpu_down(i); + ret = device_offline(get_cpu_device(i)); if (ret) { bL_switcher_restore_cpus(); return ret; -- cgit v1.2.3 From ceb218359de22e70980801d4fa04fffbfc44adb8 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 27 May 2014 19:11:58 +0100 Subject: arm64: mm: fix pmd_write CoW brokenness Commit 9c7e535fcc17 ("arm64: mm: Route pmd thp functions through pte equivalents") changed the pmd manipulator and accessor functions to convert the target pmd to a pte, process it with the pte functions, then convert it back. Along the way, we gained support for PTE_WRITE, however this is completely ignored by set_pmd_at, and so we fail to set the PMD_SECT_RDONLY for PMDs, resulting in all sorts of lovely failures (like CoW not working). Partially reverting the offending commit (by making use of PMD_SECT_RDONLY explicitly for pmd_{write,wrprotect,mkwrite} functions) leads to further issues because pmd_write can then return potentially incorrect values for page table entries marked as RDONLY, leading to BUG_ON(pmd_write(entry)) tripping under some THP workloads. This patch fixes the issue by routing set_pmd_at through set_pte_at, which correctly takes the PTE_WRITE flag into account. Given that THP mappings are always anonymous, the additional cache-flushing code in __sync_icache_dcache won't impose any significant overhead as the flush will be skipped. Cc: Catalin Marinas Acked-by: Steve Capper Tested-by: Marc Zyngier Signed-off-by: Will Deacon --- arch/arm64/include/asm/pgtable.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index 90c811f05a2e..7b1c67a0b485 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h @@ -266,7 +266,7 @@ static inline pmd_t pte_pmd(pte_t pte) #define pmd_page(pmd) pfn_to_page(__phys_to_pfn(pmd_val(pmd) & PHYS_MASK)) -#define set_pmd_at(mm, addr, pmdp, pmd) set_pmd(pmdp, pmd) +#define set_pmd_at(mm, addr, pmdp, pmd) set_pte_at(mm, addr, (pte_t *)pmdp, pmd_pte(pmd)) static inline int has_transparent_hugepage(void) { -- cgit v1.2.3 From e55fd011549eae01a230e3cace6f4d031b6a3453 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 28 May 2014 13:51:12 -0400 Subject: split dentry_kill() ... into trylocks and everything else. The latter (actual killing) is __dentry_kill(). Signed-off-by: Al Viro --- fs/dcache.c | 62 +++++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 36 insertions(+), 26 deletions(-) diff --git a/fs/dcache.c b/fs/dcache.c index 6888dde4d568..1577c14dfb4e 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -441,36 +441,12 @@ void d_drop(struct dentry *dentry) } EXPORT_SYMBOL(d_drop); -/* - * Finish off a dentry we've decided to kill. - * dentry->d_lock must be held, returns with it unlocked. - * If ref is non-zero, then decrement the refcount too. - * Returns dentry requiring refcount drop, or NULL if we're done. - */ -static struct dentry * -dentry_kill(struct dentry *dentry, int unlock_on_failure) - __releases(dentry->d_lock) +static void __dentry_kill(struct dentry *dentry) { - struct inode *inode; struct dentry *parent = NULL; bool can_free = true; - - inode = dentry->d_inode; - if (inode && !spin_trylock(&inode->i_lock)) { -relock: - if (unlock_on_failure) { - spin_unlock(&dentry->d_lock); - cpu_relax(); - } - return dentry; /* try again with same dentry */ - } if (!IS_ROOT(dentry)) parent = dentry->d_parent; - if (parent && !spin_trylock(&parent->d_lock)) { - if (inode) - spin_unlock(&inode->i_lock); - goto relock; - } /* * The dentry is now unrecoverably dead to the world. @@ -514,10 +490,44 @@ relock: can_free = false; } spin_unlock(&dentry->d_lock); -out: if (likely(can_free)) dentry_free(dentry); +} + +/* + * Finish off a dentry we've decided to kill. + * dentry->d_lock must be held, returns with it unlocked. + * If ref is non-zero, then decrement the refcount too. + * Returns dentry requiring refcount drop, or NULL if we're done. + */ +static struct dentry * +dentry_kill(struct dentry *dentry, int unlock_on_failure) + __releases(dentry->d_lock) +{ + struct inode *inode = dentry->d_inode; + struct dentry *parent = NULL; + + if (inode && unlikely(!spin_trylock(&inode->i_lock))) + goto failed; + + if (!IS_ROOT(dentry)) { + parent = dentry->d_parent; + if (unlikely(!spin_trylock(&parent->d_lock))) { + if (inode) + spin_unlock(&inode->i_lock); + goto failed; + } + } + + __dentry_kill(dentry); return parent; + +failed: + if (unlock_on_failure) { + spin_unlock(&dentry->d_lock); + cpu_relax(); + } + return dentry; /* try again with same dentry */ } /* -- cgit v1.2.3 From ff2fde9929feb2aef45377ce56b8b12df85dda69 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 28 May 2014 13:59:13 -0400 Subject: expand dentry_kill(dentry, 0) in shrink_dentry_list() Result will be massaged to saner shape in the next commits. It is ugly, no questions - the point of that one is to be a provably equivalent transformation (and it might be worth splitting a bit more). Signed-off-by: Al Viro --- fs/dcache.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/fs/dcache.c b/fs/dcache.c index 1577c14dfb4e..c23f78a9d156 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -801,6 +801,7 @@ static void shrink_dentry_list(struct list_head *list) struct dentry *dentry, *parent; while (!list_empty(list)) { + struct inode *inode; dentry = list_entry(list->prev, struct dentry, d_lru); spin_lock(&dentry->d_lock); /* @@ -828,23 +829,26 @@ static void shrink_dentry_list(struct list_head *list) continue; } - parent = dentry_kill(dentry, 0); - /* - * If dentry_kill returns NULL, we have nothing more to do. - */ - if (!parent) - continue; - - if (unlikely(parent == dentry)) { - /* - * trylocks have failed and d_lock has been held the - * whole time, so it could not have been added to any - * other lists. Just add it back to the shrink list. - */ + inode = dentry->d_inode; + if (inode && unlikely(!spin_trylock(&inode->i_lock))) { d_shrink_add(dentry, list); spin_unlock(&dentry->d_lock); continue; } + + parent = NULL; + if (!IS_ROOT(dentry)) { + parent = dentry->d_parent; + if (unlikely(!spin_trylock(&parent->d_lock))) { + if (inode) + spin_unlock(&inode->i_lock); + d_shrink_add(dentry, list); + spin_unlock(&dentry->d_lock); + continue; + } + } + + __dentry_kill(dentry); /* * We need to prune ancestors too. This is necessary to prevent * quadratic behavior of shrink_dcache_parent(), but is also -- cgit v1.2.3 From 2fe2023adf695d08af5b598b2be3b288a95d563c Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Thu, 29 May 2014 15:23:26 +0200 Subject: firewire: revert to 4 GB RDMA, fix protocols using Memory Space Undo a feature introduced in v3.14 by commit fcd46b34425d "firewire: Enable remote DMA above 4 GB". That change raised the minimum address at which protocol drivers and user programs can register for request reception from 0x0001'0000'0000 to 0x8000'0000'0000. It turned out that at least one vendor-specific protocol exists which uses lower addresses: https://bugzilla.kernel.org/show_bug.cgi?id=76921 For the time being, revert most of commit fcd46b34425d so that affected protocols work like with kernel v3.13 and before. Just keep the valid documentation parts from the regressing commit, and the ability to identify controllers which could be programmed to accept >32 bit physical DMA addresses. The rest of fcd46b34425d should probably be brought back as an optional instead of default feature. Reported-by: Fabien Spindler Cc: # 3.14+ Signed-off-by: Stefan Richter --- Documentation/debugging-via-ohci1394.txt | 13 ++++++++----- drivers/firewire/core.h | 4 ++-- drivers/firewire/ohci.c | 2 +- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/Documentation/debugging-via-ohci1394.txt b/Documentation/debugging-via-ohci1394.txt index fa0151a712f9..5c9a567b3fac 100644 --- a/Documentation/debugging-via-ohci1394.txt +++ b/Documentation/debugging-via-ohci1394.txt @@ -25,9 +25,11 @@ using data transfer rates in the order of 10MB/s or more. With most FireWire controllers, memory access is limited to the low 4 GB of physical address space. This can be a problem on IA64 machines where memory is located mostly above that limit, but it is rarely a problem on -more common hardware such as x86, x86-64 and PowerPC. However, at least -Agere/LSI FW643e and FW643e2 controllers are known to support access to -physical addresses above 4 GB. +more common hardware such as x86, x86-64 and PowerPC. + +At least LSI FW643e and FW643e2 controllers are known to support access to +physical addresses above 4 GB, but this feature is currently not enabled by +Linux. Together with a early initialization of the OHCI-1394 controller for debugging, this facility proved most useful for examining long debugs logs in the printk @@ -101,8 +103,9 @@ Step-by-step instructions for using firescope with early OHCI initialization: compliant, they are based on TI PCILynx chips and require drivers for Win- dows operating systems. - The mentioned kernel log message contains ">4 GB phys DMA" in case of - OHCI-1394 controllers which support accesses above this limit. + The mentioned kernel log message contains the string "physUB" if the + controller implements a writable Physical Upper Bound register. This is + required for physical DMA above 4 GB (but not utilized by Linux yet). 2) Establish a working FireWire cable connection: diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h index c98764aeeec6..f477308b6e9c 100644 --- a/drivers/firewire/core.h +++ b/drivers/firewire/core.h @@ -237,8 +237,8 @@ static inline bool is_next_generation(int new_generation, int old_generation) #define LOCAL_BUS 0xffc0 -/* arbitrarily chosen maximum range for physical DMA: 128 TB */ -#define FW_MAX_PHYSICAL_RANGE (128ULL << 40) +/* OHCI-1394's default upper bound for physical DMA: 4 GB */ +#define FW_MAX_PHYSICAL_RANGE (1ULL << 32) void fw_core_handle_request(struct fw_card *card, struct fw_packet *request); void fw_core_handle_response(struct fw_card *card, struct fw_packet *packet); diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 8db663219560..586f2f7f6993 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -3716,7 +3716,7 @@ static int pci_probe(struct pci_dev *dev, version >> 16, version & 0xff, ohci->card.index, ohci->n_ir, ohci->n_it, ohci->quirks, reg_read(ohci, OHCI1394_PhyUpperBound) ? - ", >4 GB phys DMA" : ""); + ", physUB" : ""); return 0; -- cgit v1.2.3 From 4b21ce1b4b5d262e7d4656b8ececc891fc3cb806 Mon Sep 17 00:00:00 2001 From: Christian König Date: Wed, 21 May 2014 15:25:41 +0200 Subject: drm/radeon: lower the ref * post PLL maximum once more MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let's be conservative and use 100 here until we find something better. Bugs: https://bugzilla.kernel.org/show_bug.cgi?id=75241 Signed-off-by: Christian König --- drivers/gpu/drm/radeon/radeon_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index f00dbbf4d806..356b733caafe 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -862,7 +862,7 @@ static void avivo_get_fb_ref_div(unsigned nom, unsigned den, unsigned post_div, unsigned *fb_div, unsigned *ref_div) { /* limit reference * post divider to a maximum */ - ref_div_max = min(128 / post_div, ref_div_max); + ref_div_max = max(min(100 / post_div, ref_div_max), 1u); /* get matching reference and feedback divider */ *ref_div = min(max(DIV_ROUND_CLOSEST(den, post_div), 1u), ref_div_max); -- cgit v1.2.3 From 60a445405a1731bac2279eab354173c9c3156747 Mon Sep 17 00:00:00 2001 From: Christian König Date: Wed, 21 May 2014 17:43:59 +0200 Subject: drm/radeon: avoid crash if VM command submission isn't available MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König CC: stable@vger.kernel.org --- drivers/gpu/drm/radeon/radeon_cs.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index 2b6e0ebcc13a..4b6f5b824153 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c @@ -342,10 +342,17 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) return -EINVAL; /* we only support VM on some SI+ rings */ - if ((p->rdev->asic->ring[p->ring]->cs_parse == NULL) && - ((p->cs_flags & RADEON_CS_USE_VM) == 0)) { - DRM_ERROR("Ring %d requires VM!\n", p->ring); - return -EINVAL; + if ((p->cs_flags & RADEON_CS_USE_VM) == 0) { + if (p->rdev->asic->ring[p->ring]->cs_parse == NULL) { + DRM_ERROR("Ring %d requires VM!\n", p->ring); + return -EINVAL; + } + } else { + if (p->rdev->asic->ring[p->ring]->ib_parse == NULL) { + DRM_ERROR("VM not supported on ring %d!\n", + p->ring); + return -EINVAL; + } } } -- cgit v1.2.3 From ec65da385d46f63740c1c9230b891a6dcbd64c71 Mon Sep 17 00:00:00 2001 From: Marek Olšák Date: Tue, 27 May 2014 02:56:36 +0200 Subject: drm/radeon: don't allow RADEON_GEM_DOMAIN_CPU for command submission MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It hangs the hardware. Signed-off-by: Marek Olšák Reviewed-by: Christian König Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/radeon_cs.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index 4b6f5b824153..41ecf8a60611 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c @@ -152,6 +152,12 @@ static int radeon_cs_parser_relocs(struct radeon_cs_parser *p) uint32_t domain = r->write_domain ? r->write_domain : r->read_domains; + if (domain & RADEON_GEM_DOMAIN_CPU) { + DRM_ERROR("RADEON_GEM_DOMAIN_CPU is not valid " + "for command submission\n"); + return -EINVAL; + } + p->relocs[i].domain = domain; if (domain == RADEON_GEM_DOMAIN_VRAM) domain |= RADEON_GEM_DOMAIN_GTT; -- cgit v1.2.3 From 7d95f6cc4ef73572a43d4a0a1907a13ace17a62a Mon Sep 17 00:00:00 2001 From: Christian König Date: Wed, 28 May 2014 12:24:17 +0200 Subject: drm/radeon: only allocate necessary size for vm bo list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No need to always allocate the theoretical maximum here. Signed-off-by: Christian König --- drivers/gpu/drm/radeon/radeon_vm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_vm.c b/drivers/gpu/drm/radeon/radeon_vm.c index d9ab99f47612..1f426696de36 100644 --- a/drivers/gpu/drm/radeon/radeon_vm.c +++ b/drivers/gpu/drm/radeon/radeon_vm.c @@ -130,10 +130,10 @@ struct radeon_cs_reloc *radeon_vm_get_bos(struct radeon_device *rdev, struct list_head *head) { struct radeon_cs_reloc *list; - unsigned i, idx, size; + unsigned i, idx; - size = (radeon_vm_num_pdes(rdev) + 1) * sizeof(struct radeon_cs_reloc); - list = kmalloc(size, GFP_KERNEL); + list = kmalloc_array(vm->max_pde_used + 1, + sizeof(struct radeon_cs_reloc), GFP_KERNEL); if (!list) return NULL; -- cgit v1.2.3 From 046b961b45f93a92e4c70525a12f3d378bced130 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 29 May 2014 08:54:52 -0400 Subject: shrink_dentry_list(): take parent's ->d_lock earlier The cause of livelocks there is that we are taking ->d_lock on dentry and its parent in the wrong order, forcing us to use trylock on the parent's one. d_walk() takes them in the right order, and unfortunately it's not hard to create a situation when shrink_dentry_list() can't make progress since trylock keeps failing, and shrink_dcache_parent() or check_submounts_and_drop() keeps calling d_walk() disrupting the very shrink_dentry_list() it's waiting for. Solution is straightforward - if that trylock fails, let's unlock the dentry itself and take locks in the right order. We need to stabilize ->d_parent without holding ->d_lock, but that's doable using RCU. And we'd better do that in the very beginning of the loop in shrink_dentry_list(), since the checks on refcount, etc. would need to be redone anyway. That deals with a half of the problem - killing dentries on the shrink list itself. Another one (dropping their parents) is in the next commit. locking parent is interesting - it would be easy to do rcu_read_lock(), lock whatever we think is a parent, lock dentry itself and check if the parent is still the right one. Except that we need to check that *before* locking the dentry, or we are risking taking ->d_lock out of order. Fortunately, once the D1 is locked, we can check if D2->d_parent is equal to D1 without the need to lock D2; D2->d_parent can start or stop pointing to D1 only under D1->d_lock, so taking D1->d_lock is enough. In other words, the right solution is rcu_read_lock/lock what looks like parent right now/check if it's still our parent/rcu_read_unlock/lock the child. Signed-off-by: Al Viro --- fs/dcache.c | 53 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 41 insertions(+), 12 deletions(-) diff --git a/fs/dcache.c b/fs/dcache.c index c23f78a9d156..d54a99baf4f3 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -530,6 +530,38 @@ failed: return dentry; /* try again with same dentry */ } +static inline struct dentry *lock_parent(struct dentry *dentry) +{ + struct dentry *parent = dentry->d_parent; + if (IS_ROOT(dentry)) + return NULL; + if (likely(spin_trylock(&parent->d_lock))) + return parent; + spin_unlock(&dentry->d_lock); + rcu_read_lock(); +again: + parent = ACCESS_ONCE(dentry->d_parent); + spin_lock(&parent->d_lock); + /* + * We can't blindly lock dentry until we are sure + * that we won't violate the locking order. + * Any changes of dentry->d_parent must have + * been done with parent->d_lock held, so + * spin_lock() above is enough of a barrier + * for checking if it's still our child. + */ + if (unlikely(parent != dentry->d_parent)) { + spin_unlock(&parent->d_lock); + goto again; + } + rcu_read_unlock(); + if (parent != dentry) + spin_lock(&dentry->d_lock); + else + parent = NULL; + return parent; +} + /* * This is dput * @@ -804,6 +836,8 @@ static void shrink_dentry_list(struct list_head *list) struct inode *inode; dentry = list_entry(list->prev, struct dentry, d_lru); spin_lock(&dentry->d_lock); + parent = lock_parent(dentry); + /* * The dispose list is isolated and dentries are not accounted * to the LRU here, so we can simply remove it from the list @@ -817,6 +851,8 @@ static void shrink_dentry_list(struct list_head *list) */ if ((int)dentry->d_lockref.count > 0) { spin_unlock(&dentry->d_lock); + if (parent) + spin_unlock(&parent->d_lock); continue; } @@ -824,6 +860,8 @@ static void shrink_dentry_list(struct list_head *list) if (unlikely(dentry->d_flags & DCACHE_DENTRY_KILLED)) { bool can_free = dentry->d_flags & DCACHE_MAY_FREE; spin_unlock(&dentry->d_lock); + if (parent) + spin_unlock(&parent->d_lock); if (can_free) dentry_free(dentry); continue; @@ -833,22 +871,13 @@ static void shrink_dentry_list(struct list_head *list) if (inode && unlikely(!spin_trylock(&inode->i_lock))) { d_shrink_add(dentry, list); spin_unlock(&dentry->d_lock); + if (parent) + spin_unlock(&parent->d_lock); continue; } - parent = NULL; - if (!IS_ROOT(dentry)) { - parent = dentry->d_parent; - if (unlikely(!spin_trylock(&parent->d_lock))) { - if (inode) - spin_unlock(&inode->i_lock); - d_shrink_add(dentry, list); - spin_unlock(&dentry->d_lock); - continue; - } - } - __dentry_kill(dentry); + /* * We need to prune ancestors too. This is necessary to prevent * quadratic behavior of shrink_dcache_parent(), but is also -- cgit v1.2.3 From b2b80195d8829921506880f6dccd21cabd163d0d Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 29 May 2014 09:11:45 -0400 Subject: dealing with the rest of shrink_dentry_list() livelock We have the same problem with ->d_lock order in the inner loop, where we are dropping references to ancestors. Same solution, basically - instead of using dentry_kill() we use lock_parent() (introduced in the previous commit) to get that lock in a safe way, recheck ->d_count (in case if lock_parent() has ended up dropping and retaking ->d_lock and somebody managed to grab a reference during that window), trylock the inode->i_lock and use __dentry_kill() to do the rest. Signed-off-by: Al Viro --- fs/dcache.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/fs/dcache.c b/fs/dcache.c index d54a99baf4f3..eb7c7255470c 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -885,8 +885,26 @@ static void shrink_dentry_list(struct list_head *list) * fragmentation. */ dentry = parent; - while (dentry && !lockref_put_or_lock(&dentry->d_lockref)) - dentry = dentry_kill(dentry, 1); + while (dentry && !lockref_put_or_lock(&dentry->d_lockref)) { + parent = lock_parent(dentry); + if (dentry->d_lockref.count != 1) { + dentry->d_lockref.count--; + spin_unlock(&dentry->d_lock); + if (parent) + spin_unlock(&parent->d_lock); + break; + } + inode = dentry->d_inode; /* can't be NULL */ + if (unlikely(!spin_trylock(&inode->i_lock))) { + spin_unlock(&dentry->d_lock); + if (parent) + spin_unlock(&parent->d_lock); + cpu_relax(); + continue; + } + __dentry_kill(dentry); + dentry = parent; + } } } -- cgit v1.2.3 From 8cbf74da435d1bd13dbb790f94c7ff67b2fb6af4 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 29 May 2014 09:18:26 -0400 Subject: dentry_kill() doesn't need the second argument now it's 1 in the only remaining caller. Signed-off-by: Al Viro --- fs/dcache.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/fs/dcache.c b/fs/dcache.c index eb7c7255470c..bce851dc03ef 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -500,8 +500,7 @@ static void __dentry_kill(struct dentry *dentry) * If ref is non-zero, then decrement the refcount too. * Returns dentry requiring refcount drop, or NULL if we're done. */ -static struct dentry * -dentry_kill(struct dentry *dentry, int unlock_on_failure) +static struct dentry *dentry_kill(struct dentry *dentry) __releases(dentry->d_lock) { struct inode *inode = dentry->d_inode; @@ -523,10 +522,8 @@ dentry_kill(struct dentry *dentry, int unlock_on_failure) return parent; failed: - if (unlock_on_failure) { - spin_unlock(&dentry->d_lock); - cpu_relax(); - } + spin_unlock(&dentry->d_lock); + cpu_relax(); return dentry; /* try again with same dentry */ } @@ -615,7 +612,7 @@ repeat: return; kill_it: - dentry = dentry_kill(dentry, 1); + dentry = dentry_kill(dentry); if (dentry) goto repeat; } -- cgit v1.2.3 From 6538b8ea886e472f4431db8ca1d60478f838d14b Mon Sep 17 00:00:00 2001 From: Minchan Kim Date: Wed, 28 May 2014 15:53:59 +0900 Subject: x86_64: expand kernel stack to 16K While I play inhouse patches with much memory pressure on qemu-kvm, 3.14 kernel was randomly crashed. The reason was kernel stack overflow. When I investigated the problem, the callstack was a little bit deeper by involve with reclaim functions but not direct reclaim path. I tried to diet stack size of some functions related with alloc/reclaim so did a hundred of byte but overflow was't disappeard so that I encounter overflow by another deeper callstack on reclaim/allocator path. Of course, we might sweep every sites we have found for reducing stack usage but I'm not sure how long it saves the world(surely, lots of developer start to add nice features which will use stack agains) and if we consider another more complex feature in I/O layer and/or reclaim path, it might be better to increase stack size( meanwhile, stack usage on 64bit machine was doubled compared to 32bit while it have sticked to 8K. Hmm, it's not a fair to me and arm64 already expaned to 16K. ) So, my stupid idea is just let's expand stack size and keep an eye toward stack consumption on each kernel functions via stacktrace of ftrace. For example, we can have a bar like that each funcion shouldn't exceed 200K and emit the warning when some function consumes more in runtime. Of course, it could make false positive but at least, it could make a chance to think over it. I guess this topic was discussed several time so there might be strong reason not to increase kernel stack size on x86_64, for me not knowing so Ccing x86_64 maintainers, other MM guys and virtio maintainers. Here's an example call trace using up the kernel stack: Depth Size Location (51 entries) ----- ---- -------- 0) 7696 16 lookup_address 1) 7680 16 _lookup_address_cpa.isra.3 2) 7664 24 __change_page_attr_set_clr 3) 7640 392 kernel_map_pages 4) 7248 256 get_page_from_freelist 5) 6992 352 __alloc_pages_nodemask 6) 6640 8 alloc_pages_current 7) 6632 168 new_slab 8) 6464 8 __slab_alloc 9) 6456 80 __kmalloc 10) 6376 376 vring_add_indirect 11) 6000 144 virtqueue_add_sgs 12) 5856 288 __virtblk_add_req 13) 5568 96 virtio_queue_rq 14) 5472 128 __blk_mq_run_hw_queue 15) 5344 16 blk_mq_run_hw_queue 16) 5328 96 blk_mq_insert_requests 17) 5232 112 blk_mq_flush_plug_list 18) 5120 112 blk_flush_plug_list 19) 5008 64 io_schedule_timeout 20) 4944 128 mempool_alloc 21) 4816 96 bio_alloc_bioset 22) 4720 48 get_swap_bio 23) 4672 160 __swap_writepage 24) 4512 32 swap_writepage 25) 4480 320 shrink_page_list 26) 4160 208 shrink_inactive_list 27) 3952 304 shrink_lruvec 28) 3648 80 shrink_zone 29) 3568 128 do_try_to_free_pages 30) 3440 208 try_to_free_pages 31) 3232 352 __alloc_pages_nodemask 32) 2880 8 alloc_pages_current 33) 2872 200 __page_cache_alloc 34) 2672 80 find_or_create_page 35) 2592 80 ext4_mb_load_buddy 36) 2512 176 ext4_mb_regular_allocator 37) 2336 128 ext4_mb_new_blocks 38) 2208 256 ext4_ext_map_blocks 39) 1952 160 ext4_map_blocks 40) 1792 384 ext4_writepages 41) 1408 16 do_writepages 42) 1392 96 __writeback_single_inode 43) 1296 176 writeback_sb_inodes 44) 1120 80 __writeback_inodes_wb 45) 1040 160 wb_writeback 46) 880 208 bdi_writeback_workfn 47) 672 144 process_one_work 48) 528 112 worker_thread 49) 416 240 kthread 50) 176 176 ret_from_fork [ Note: the problem is exacerbated by certain gcc versions that seem to generate much bigger stack frames due to apparently bad coalescing of temporaries and generating too many spills. Rusty saw gcc-4.6.4 using 35% more stack on the virtio path than 4.8.2 does, for example. Minchan not only uses such a bad gcc version (4.6.3 in his case), but some of the stack use is due to debugging (CONFIG_DEBUG_PAGEALLOC is what causes that kernel_map_pages() frame, for example). But we're clearly getting too close. The VM code also seems to have excessive stack frames partly for the same compiler reason, triggered by excessive inlining and lots of function arguments. We need to improve on our stack use, but in the meantime let's do this simple stack increase too. Unlike most earlier reports, there is nothing simple that stands out as being really horribly wrong here, apart from the fact that the stack frames are just bigger than they should need to be. - Linus ] Signed-off-by: Minchan Kim Cc: Peter Anvin Cc: Dave Chinner Cc: Dave Jones Cc: Jens Axboe Cc: Andrew Morton Cc: Ingo Molnar Cc: Peter Zijlstra Cc: Mel Gorman Cc: Rik van Riel Cc: Johannes Weiner Cc: Hugh Dickins Cc: Rusty Russell Cc: Michael S Tsirkin Cc: Dave Hansen Cc: Steven Rostedt Cc: PJ Waskiewicz Signed-off-by: Linus Torvalds --- arch/x86/include/asm/page_64_types.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/include/asm/page_64_types.h b/arch/x86/include/asm/page_64_types.h index 8de6d9cf3b95..678205195ae1 100644 --- a/arch/x86/include/asm/page_64_types.h +++ b/arch/x86/include/asm/page_64_types.h @@ -1,7 +1,7 @@ #ifndef _ASM_X86_PAGE_64_DEFS_H #define _ASM_X86_PAGE_64_DEFS_H -#define THREAD_SIZE_ORDER 1 +#define THREAD_SIZE_ORDER 2 #define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER) #define CURRENT_MASK (~(THREAD_SIZE - 1)) -- cgit v1.2.3 From 18ee37a485653aa635cfab9a3710e9bcf5fbca01 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 30 May 2014 16:41:23 +0200 Subject: drm/radeon: Resume fbcon last So a few people complained that commit 177cf92de4aa97ec1435987e91696ed8b5023130 Author: Daniel Vetter Date: Tue Apr 1 22:14:59 2014 +0200 drm/crtc-helpers: fix dpms on logic which was merged into 3.15-rc1, broke resume on radeons. Strangely git bisect lead everyone to commit 25f397a429dfa43f22c278d0119a60a343aa568f Author: Daniel Vetter Date: Fri Jul 19 18:57:11 2013 +0200 drm/crtc-helper: explicit DPMS on after modeset which was merged long ago and actually part of 3.14. Digging deeper I've noticed (again) that the call to drm_helper_resume_force_mode in the radeon resume handlers was a no-op previously because everything gets shut down on suspend. radeon does this with explicit calls to drm_helper_connector_dpms with DPMS_OFF. But with 177c we now force the dpms state to ON, so suddenly resume_force_mode actually forced the crtcs back on. This is the intention of the change after all, the problem is that radeon resumes the fbdev console layer _before_ restoring the display, through calling fb_set_suspend. And fbcon does an immediate ->set_par, which in turn causes the same forced mode restore to happen. Two concurrent modeset operations didn't lead to happiness. Fix this by delaying the fbcon resume until the end of the readeon resum functions. v2: Fix up a bit of the spelling fail. References: https://lkml.org/lkml/2014/5/29/1043 References: https://lkml.org/lkml/2014/5/2/388 Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=74751 Tested-by: Ken Moffat Cc: Alex Deucher Cc: Ken Moffat Signed-off-by: Daniel Vetter Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_device.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 0e770bbf7e29..14671406212f 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -1533,11 +1533,6 @@ int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon) radeon_restore_bios_scratch_regs(rdev); - if (fbcon) { - radeon_fbdev_set_suspend(rdev, 0); - console_unlock(); - } - /* init dig PHYs, disp eng pll */ if (rdev->is_atom_bios) { radeon_atom_encoder_init(rdev); @@ -1562,6 +1557,12 @@ int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon) } drm_kms_helper_poll_enable(dev); + + if (fbcon) { + radeon_fbdev_set_suspend(rdev, 0); + console_unlock(); + } + return 0; } -- cgit v1.2.3 From 9f12600fe425bc28f0ccba034a77783c09c15af4 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 31 May 2014 09:13:21 -0700 Subject: dcache: add missing lockdep annotation lock_parent() very much on purpose does nested locking of dentries, and is careful to maintain the right order (lock parent first). But because it didn't annotate the nested locking order, lockdep thought it might be a deadlock on d_lock, and complained. Add the proper annotation for the inner locking of the child dentry to make lockdep happy. Introduced by commit 046b961b45f9 ("shrink_dentry_list(): take parent's ->d_lock earlier"). Reported-and-tested-by: Josh Boyer Cc: Al Viro Signed-off-by: Linus Torvalds --- fs/dcache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/dcache.c b/fs/dcache.c index bce851dc03ef..be2bea834bf4 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -553,7 +553,7 @@ again: } rcu_read_unlock(); if (parent != dentry) - spin_lock(&dentry->d_lock); + spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED); else parent = NULL; return parent; -- cgit v1.2.3 From 8212f58a9b151d842fa60a70f354e43c61fad839 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 2 Jun 2014 09:24:27 +1000 Subject: powerpc: Wire renameat2() syscall Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/include/asm/systbl.h | 1 + arch/powerpc/include/asm/unistd.h | 2 +- arch/powerpc/include/uapi/asm/unistd.h | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/include/asm/systbl.h b/arch/powerpc/include/asm/systbl.h index 3ddf70276706..ea4dc3a89c1f 100644 --- a/arch/powerpc/include/asm/systbl.h +++ b/arch/powerpc/include/asm/systbl.h @@ -361,3 +361,4 @@ SYSCALL(finit_module) SYSCALL(ni_syscall) /* sys_kcmp */ SYSCALL_SPU(sched_setattr) SYSCALL_SPU(sched_getattr) +SYSCALL_SPU(renameat2) diff --git a/arch/powerpc/include/asm/unistd.h b/arch/powerpc/include/asm/unistd.h index 4494f029b632..9b892bbd9d84 100644 --- a/arch/powerpc/include/asm/unistd.h +++ b/arch/powerpc/include/asm/unistd.h @@ -12,7 +12,7 @@ #include -#define __NR_syscalls 357 +#define __NR_syscalls 358 #define __NR__exit __NR_exit #define NR_syscalls __NR_syscalls diff --git a/arch/powerpc/include/uapi/asm/unistd.h b/arch/powerpc/include/uapi/asm/unistd.h index 881bf2e2560d..2d526f7b48da 100644 --- a/arch/powerpc/include/uapi/asm/unistd.h +++ b/arch/powerpc/include/uapi/asm/unistd.h @@ -379,5 +379,6 @@ #define __NR_kcmp 354 #define __NR_sched_setattr 355 #define __NR_sched_getattr 356 +#define __NR_renameat2 357 #endif /* _UAPI_ASM_POWERPC_UNISTD_H_ */ -- cgit v1.2.3 From fad01e866afdbe01a1f3ec06a39c3a8b9e197014 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 1 Jun 2014 19:12:24 -0700 Subject: Linux 3.15-rc8 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index cf3412d78ff1..cdaa5b6a1c4d 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 3 PATCHLEVEL = 15 SUBLEVEL = 0 -EXTRAVERSION = -rc7 +EXTRAVERSION = -rc8 NAME = Shuffling Zombie Juror # *DOCUMENTATION* -- cgit v1.2.3 From 0c188a07b6a399e3df66534c29fef0a2082aaf57 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Thu, 29 May 2014 19:52:32 +0900 Subject: perf probe: Fix a segfault if asked for variable it doesn't find Fix a segfault bug by asking for variable it doesn't find. Since the convert_variable() didn't handle error code returned from convert_variable_location(), it just passed an incomplete variable field and then a segfault was occurred when formatting the field. This fixes that bug by handling success code correctly in convert_variable(). Other callers of convert_variable_location() are correctly checking the return code. This bug was introduced by following commit. But another hidden erroneous error handling has been there previously (-ENOMEM case). commit 3d918a12a1b3088ac16ff37fa52760639d6e2403 Signed-off-by: Masami Hiramatsu Reported-by: Arnaldo Carvalho de Melo Tested-by: Arnaldo Carvalho de Melo Cc: Peter Zijlstra Cc: Paul Mackerras Cc: Ingo Molnar Cc: Namhyung Kim Link: http://lkml.kernel.org/r/20140529105232.28251.30447.stgit@ltc230.yrl.intra.hitachi.co.jp Signed-off-by: Jiri Olsa --- tools/perf/util/probe-finder.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 562762117639..9d8eb26f0533 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -511,12 +511,12 @@ static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf) ret = convert_variable_location(vr_die, pf->addr, pf->fb_ops, &pf->sp_die, pf->tvar); - if (ret == -ENOENT) + if (ret == -ENOENT || ret == -EINVAL) pr_err("Failed to find the location of %s at this address.\n" " Perhaps, it has been optimized out.\n", pf->pvar->var); else if (ret == -ENOTSUP) pr_err("Sorry, we don't support this variable location yet.\n"); - else if (pf->pvar->field) { + else if (ret == 0 && pf->pvar->field) { ret = convert_variable_fields(vr_die, pf->pvar->var, pf->pvar->field, &pf->tvar->ref, &die_mem); -- cgit v1.2.3 From 082f96a93eb5ba9bf771518a0dda590624568e8e Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Thu, 29 May 2014 21:19:30 +0900 Subject: perf probe: Fix perf probe to find correct variable DIE Fix perf probe to find correct variable DIE which has location or external instance by tracking down the lexical blocks. Current die_find_variable() expects that the all variable DIEs which has DW_TAG_variable have a location. However, since recent dwarf information may have declaration variable DIEs at the entry of function (subprogram), die_find_variable() returns it. To solve this problem, it must track down the DIE tree to find a DIE which has an actual location or a reference for external instance. e.g. finding a DIE which origin is <0xdc73>; <1><11496>: Abbrev Number: 95 (DW_TAG_subprogram) <11497> DW_AT_abstract_origin: <0xdc42> <1149b> DW_AT_low_pc : 0x1850 [...] <2><114cc>: Abbrev Number: 119 (DW_TAG_variable) <- this is a declaration <114cd> DW_AT_abstract_origin: <0xdc73> <2><114d1>: Abbrev Number: 119 (DW_TAG_variable) [...] <3><115a7>: Abbrev Number: 105 (DW_TAG_lexical_block) <115a8> DW_AT_ranges : 0xaa0 <4><115ac>: Abbrev Number: 96 (DW_TAG_variable) <- this has a location <115ad> DW_AT_abstract_origin: <0xdc73> <115b1> DW_AT_location : 0x486c (location list) Signed-off-by: Masami Hiramatsu Tested-by: Arnaldo Carvalho de Melo Acked-by: Arnaldo Carvalho de Melo Cc: Arnaldo Carvalho de Melo Cc: Peter Zijlstra Cc: Paul Mackerras Cc: Ingo Molnar Cc: Namhyung Kim Link: http://lkml.kernel.org/r/20140529121930.30879.87092.stgit@ltc230.yrl.intra.hitachi.co.jp Signed-off-by: Jiri Olsa --- tools/perf/util/dwarf-aux.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c index 7defd77105d0..cc66c4049e09 100644 --- a/tools/perf/util/dwarf-aux.c +++ b/tools/perf/util/dwarf-aux.c @@ -747,14 +747,17 @@ struct __find_variable_param { static int __die_find_variable_cb(Dwarf_Die *die_mem, void *data) { struct __find_variable_param *fvp = data; + Dwarf_Attribute attr; int tag; tag = dwarf_tag(die_mem); if ((tag == DW_TAG_formal_parameter || tag == DW_TAG_variable) && - die_compare_name(die_mem, fvp->name)) + die_compare_name(die_mem, fvp->name) && + /* Does the DIE have location information or external instance? */ + (dwarf_attr(die_mem, DW_AT_external, &attr) || + dwarf_attr(die_mem, DW_AT_location, &attr))) return DIE_FIND_CB_END; - if (dwarf_haspc(die_mem, fvp->addr)) return DIE_FIND_CB_CONTINUE; else -- cgit v1.2.3 From e041e328c4b41e1db79bfe5ba9992c2ed771ad19 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 21 May 2014 17:32:19 +0200 Subject: perf: Fix perf_event_comm() vs. exec() assumption perf_event_comm() assumes that set_task_comm() is only called on exec(), and in particular that its only called on current. Neither are true, as Dave reported a WARN triggered by set_task_comm() being called on !current. Separate the exec() hook from the comm hook. Reported-by: Dave Jones Signed-off-by: Peter Zijlstra Cc: Alexander Viro Cc: Arnaldo Carvalho de Melo Cc: Linus Torvalds Cc: linux-fsdevel@vger.kernel.org Cc: linux-kernel@vger.kernel.org Link: http://lkml.kernel.org/r/20140521153219.GH5226@laptop.programming.kicks-ass.net [ Build fix. ] Signed-off-by: Ingo Molnar --- fs/exec.c | 1 + include/linux/perf_event.h | 4 +++- kernel/events/core.c | 28 ++++++++++++++++------------ 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/fs/exec.c b/fs/exec.c index 238b7aa26f68..a038a41a3677 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1110,6 +1110,7 @@ void setup_new_exec(struct linux_binprm * bprm) else set_dumpable(current->mm, suid_dumpable); + perf_event_exec(); set_task_comm(current, kbasename(bprm->filename)); /* Set the new mm task size. We have to do that late because it may diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 3ef6ea12806a..9b5cd1992a88 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -695,6 +695,7 @@ extern struct perf_guest_info_callbacks *perf_guest_cbs; extern int perf_register_guest_info_callbacks(struct perf_guest_info_callbacks *callbacks); extern int perf_unregister_guest_info_callbacks(struct perf_guest_info_callbacks *callbacks); +extern void perf_event_exec(void); extern void perf_event_comm(struct task_struct *tsk); extern void perf_event_fork(struct task_struct *tsk); @@ -772,7 +773,7 @@ extern void perf_event_enable(struct perf_event *event); extern void perf_event_disable(struct perf_event *event); extern int __perf_event_disable(void *info); extern void perf_event_task_tick(void); -#else +#else /* !CONFIG_PERF_EVENTS: */ static inline void perf_event_task_sched_in(struct task_struct *prev, struct task_struct *task) { } @@ -802,6 +803,7 @@ static inline int perf_unregister_guest_info_callbacks (struct perf_guest_info_callbacks *callbacks) { return 0; } static inline void perf_event_mmap(struct vm_area_struct *vma) { } +static inline void perf_event_exec(void) { } static inline void perf_event_comm(struct task_struct *tsk) { } static inline void perf_event_fork(struct task_struct *tsk) { } static inline void perf_event_init(void) { } diff --git a/kernel/events/core.c b/kernel/events/core.c index 440eefc67397..647698f91988 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -2970,6 +2970,22 @@ out: local_irq_restore(flags); } +void perf_event_exec(void) +{ + struct perf_event_context *ctx; + int ctxn; + + rcu_read_lock(); + for_each_task_context_nr(ctxn) { + ctx = current->perf_event_ctxp[ctxn]; + if (!ctx) + continue; + + perf_event_enable_on_exec(ctx); + } + rcu_read_unlock(); +} + /* * Cross CPU call to read the hardware event */ @@ -5057,18 +5073,6 @@ static void perf_event_comm_event(struct perf_comm_event *comm_event) void perf_event_comm(struct task_struct *task) { struct perf_comm_event comm_event; - struct perf_event_context *ctx; - int ctxn; - - rcu_read_lock(); - for_each_task_context_nr(ctxn) { - ctx = task->perf_event_ctxp[ctxn]; - if (!ctx) - continue; - - perf_event_enable_on_exec(ctx); - } - rcu_read_unlock(); if (!atomic_read(&nr_comm_events)) return; -- cgit v1.2.3