From 88b5bdfda886e9774b03f02ffe4295be124124f6 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Fri, 27 Sep 2013 16:15:54 +0800 Subject: ASoC: wm8993: drop regulator_bulk_free of devm_ allocated data It's not necessary to free regulator consumers allocated with devm_regulator_bulk_get. Signed-off-by: Wei Yongjun Signed-off-by: Mark Brown --- sound/soc/codecs/wm8993.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index 433d59a0f3ef..2ee23a39622c 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c @@ -1562,7 +1562,6 @@ static int wm8993_remove(struct snd_soc_codec *codec) struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); wm8993_set_bias_level(codec, SND_SOC_BIAS_OFF); - regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); return 0; } -- cgit v1.2.3 From 29191039e21f66e204acffed63c486674a1918bd Mon Sep 17 00:00:00 2001 From: Yufeng Shen Date: Mon, 27 Jan 2014 18:02:46 -0500 Subject: HID: usbhid: quirk for CY-TM75 75 inch Touch Overlay There is timeout error during initialization: kernel: [ 11.733104] hid-multitouch 0003:1870:0110.0001: usb_submit_urb(ctrl) failed: -1 kernel: [ 11.734093] hid-multitouch 0003:1870:0110.0001: timeout initializing reports Adding quirk HID_QUIRK_NO_INIT_REPORTS can solve the problem. Signed-off-by: Yufeng Shen 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 92b40c09d917..7b9f79e25c58 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -642,6 +642,7 @@ #define USB_VENDOR_ID_NEXIO 0x1870 #define USB_DEVICE_ID_NEXIO_MULTITOUCH_420 0x010d +#define USB_DEVICE_ID_NEXIO_MULTITOUCH_PTI0750 0x0110 #define USB_VENDOR_ID_NEXTWINDOW 0x1926 #define USB_DEVICE_ID_NEXTWINDOW_TOUCHSCREEN 0x0003 diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 175ec0afb70c..dbd83878ff99 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -74,6 +74,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET }, { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET }, { USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GX680R_LED_PANEL, HID_QUIRK_NO_INIT_REPORTS }, + { USB_VENDOR_ID_NEXIO, USB_DEVICE_ID_NEXIO_MULTITOUCH_PTI0750, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_NOVATEK, USB_DEVICE_ID_NOVATEK_MOUSE, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1, HID_QUIRK_NO_INIT_REPORTS }, -- cgit v1.2.3 From 117309c51dca42121f70cacec801511b76acf75c Mon Sep 17 00:00:00 2001 From: Reyad Attiyat Date: Tue, 28 Jan 2014 16:17:57 +0100 Subject: HID: microsoft: Add ID's for Surface Type/Touch Cover 2 The Microsoft Surface Type/Touch cover 2 devices have the flag HID_DG_CONTACTID in their reports.This causes the device to bind to the hid-multitouch driver, which doesn't handle generic keyboard/mouse input events. The patch adds the hardware id's of the device to hid-microsoft and to the HID special driver array, which makes the device get handled by hid-generic/hid-input properly. Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=64811 Singed-off-by: Reyad Attiyat Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 2 ++ drivers/hid/hid-ids.h | 2 ++ drivers/hid/hid-microsoft.c | 4 ++++ 3 files changed, 8 insertions(+) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 026ab0fc06f7..6ed8f5f6e7d4 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1779,6 +1779,8 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_2) }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TOUCH_COVER_2) }, { HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) }, { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN) }, { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_1) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 7b9f79e25c58..a348ba0270fd 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -617,6 +617,8 @@ #define USB_DEVICE_ID_MS_PRESENTER_8K_USB 0x0713 #define USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K 0x0730 #define USB_DEVICE_ID_MS_COMFORT_MOUSE_4500 0x076c +#define USB_DEVICE_ID_MS_TOUCH_COVER_2 0x07a7 +#define USB_DEVICE_ID_MS_TYPE_COVER_2 0x07a9 #define USB_VENDOR_ID_MOJO 0x8282 #define USB_DEVICE_ID_RETRO_ADAPTER 0x3201 diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c index c6ef6eed3091..404a3a8a82f1 100644 --- a/drivers/hid/hid-microsoft.c +++ b/drivers/hid/hid-microsoft.c @@ -208,6 +208,10 @@ static const struct hid_device_id ms_devices[] = { .driver_data = MS_NOGET }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500), .driver_data = MS_DUPLICATE_USAGES }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_2), + .driver_data = 0 }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TOUCH_COVER_2), + .driver_data = 0 }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT), .driver_data = MS_PRESENTER }, -- cgit v1.2.3 From 3db187e7bf76ace626664ef80afbc2e1501172c6 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Thu, 23 Jan 2014 16:33:14 -0500 Subject: HID: multitouch: add FocalTech FTxxxx support This is a Win7 device which does not work correctly with the default settings (not the previous default BT). However, the quirk ALWAYS_TRUE makes it working like a charm. Signed-off-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-ids.h | 1 + drivers/hid/hid-multitouch.c | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index a348ba0270fd..2f10e6e7160d 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -240,6 +240,7 @@ #define USB_VENDOR_ID_CYGNAL 0x10c4 #define USB_DEVICE_ID_CYGNAL_RADIO_SI470X 0x818a +#define USB_DEVICE_ID_FOCALTECH_FTXXXX_MULTITOUCH 0x81b9 #define USB_VENDOR_ID_CYPRESS 0x04b4 #define USB_DEVICE_ID_CYPRESS_MOUSE 0x0001 diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index f134d73beca1..221d503f1c24 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -1166,6 +1166,11 @@ static const struct hid_device_id mt_devices[] = { MT_USB_DEVICE(USB_VENDOR_ID_FLATFROG, USB_DEVICE_ID_MULTITOUCH_3200) }, + /* FocalTech Panels */ + { .driver_data = MT_CLS_SERIAL, + MT_USB_DEVICE(USB_VENDOR_ID_CYGNAL, + USB_DEVICE_ID_FOCALTECH_FTXXXX_MULTITOUCH) }, + /* GeneralTouch panel */ { .driver_data = MT_CLS_GENERALTOUCH_TWOFINGERS, MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, -- cgit v1.2.3 From 0475c947d221f9250bbdf430b2604f828b643ee0 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Sat, 25 Jan 2014 19:46:23 -0200 Subject: ata: pata_imx: Check the return value from clk_prepare_enable() clk_prepare_enable() may fail, so let's check its return value and propagate it in the case of error. Signed-off-by: Fabio Estevam Signed-off-by: Tejun Heo --- drivers/ata/pata_imx.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/ata/pata_imx.c b/drivers/ata/pata_imx.c index 26386f0b89a8..b0b18ec5465f 100644 --- a/drivers/ata/pata_imx.c +++ b/drivers/ata/pata_imx.c @@ -119,7 +119,9 @@ static int pata_imx_probe(struct platform_device *pdev) return PTR_ERR(priv->clk); } - clk_prepare_enable(priv->clk); + ret = clk_prepare_enable(priv->clk); + if (ret) + return ret; host = ata_host_alloc(&pdev->dev, 1); if (!host) { @@ -212,7 +214,9 @@ static int pata_imx_resume(struct device *dev) struct ata_host *host = dev_get_drvdata(dev); struct pata_imx_priv *priv = host->private_data; - clk_prepare_enable(priv->clk); + int ret = clk_prepare_enable(priv->clk); + if (ret) + return ret; __raw_writel(priv->ata_ctl, priv->host_regs + PATA_IMX_ATA_CONTROL); -- cgit v1.2.3 From 49c8f1ffe26ffddfb7244a24db21c0b4a79e1c52 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Wed, 22 Jan 2014 20:56:33 +0100 Subject: ATA: SATA_MV: Add missing Kconfig select statememnt SATA_MV depends on GENERIC_PHY. So if SATA_MV is built in, GENERIC_PHY cannot be modular. Fixes build error found by kbuild test robot. Signed-off-by: Andrew Lunn Signed-off-by: Tejun Heo --- drivers/ata/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 4e737728aee2..868429a47be4 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -247,6 +247,7 @@ config SATA_HIGHBANK config SATA_MV tristate "Marvell SATA support" + select GENERIC_PHY help This option enables support for the Marvell Serial ATA family. Currently supports 88SX[56]0[48][01] PCI(-X) chips, -- cgit v1.2.3 From eaff64705dd5557f8e455563da3d9cbdbdec0204 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 30 Jan 2014 11:58:27 +0530 Subject: ASoC: samsung: Remove invalid dependencies These symbols got eliminated when non-DT support for Exynos was removed. Remove them. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/samsung/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index 454f41cfc828..33fd3724557b 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig @@ -145,7 +145,7 @@ config SND_SOC_SAMSUNG_RX1950_UDA1380 config SND_SOC_SAMSUNG_SMDK_WM9713 tristate "SoC AC97 Audio support for SMDK with WM9713" - depends on SND_SOC_SAMSUNG && (MACH_SMDK6410 || MACH_SMDKC100 || MACH_SMDKV210 || MACH_SMDKC110 || MACH_SMDKV310 || MACH_SMDKC210) + depends on SND_SOC_SAMSUNG && (MACH_SMDK6410 || MACH_SMDKC100 || MACH_SMDKV210 || MACH_SMDKC110) select SND_SOC_WM9713 select SND_SAMSUNG_AC97 help -- cgit v1.2.3 From 25e7e34805a39a1b05b659acbed878b3187a2707 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 30 Jan 2014 11:58:28 +0530 Subject: ASoC: samsung: Fix trivial typo Changed Sat -> Say. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/samsung/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index 33fd3724557b..350757400391 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig @@ -59,7 +59,7 @@ config SND_SOC_SAMSUNG_JIVE_WM8750 select SND_SOC_WM8750 select SND_S3C2412_SOC_I2S help - Sat Y if you want to add support for SoC audio on the Jive. + Say Y if you want to add support for SoC audio on the Jive. config SND_SOC_SAMSUNG_SMDK_WM8580 tristate "SoC I2S Audio support for WM8580 on SMDK" @@ -149,7 +149,7 @@ config SND_SOC_SAMSUNG_SMDK_WM9713 select SND_SOC_WM9713 select SND_SAMSUNG_AC97 help - Sat Y if you want to add support for SoC audio on the SMDK. + Say Y if you want to add support for SoC audio on the SMDK. config SND_SOC_SMARTQ tristate "SoC I2S Audio support for SmartQ board" -- cgit v1.2.3 From efb9e0f4f43780f0ae0c6428d66bd03e805c7539 Mon Sep 17 00:00:00 2001 From: "Denis V. Lunev" Date: Thu, 30 Jan 2014 15:20:30 +0400 Subject: ata: enable quirk from jmicron JMB350 for JMB394 Without the patch the kernel generates the following error. ata11.15: SATA link up 1.5 Gbps (SStatus 113 SControl 310) ata11.15: Port Multiplier vendor mismatch '0x197b' != '0x123' ata11.15: PMP revalidation failed (errno=-19) ata11.15: failed to recover PMP after 5 tries, giving up This patch helps to bypass this error and the device becomes functional. Signed-off-by: Denis V. Lunev Signed-off-by: Tejun Heo Cc: Cc: stable@vger.kernel.org --- drivers/ata/libata-pmp.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c index 20fd337a5731..7ccc084bf1df 100644 --- a/drivers/ata/libata-pmp.c +++ b/drivers/ata/libata-pmp.c @@ -447,8 +447,11 @@ static void sata_pmp_quirks(struct ata_port *ap) * otherwise. Don't try hard to recover it. */ ap->pmp_link[ap->nr_pmp_links - 1].flags |= ATA_LFLAG_NO_RETRY; - } else if (vendor == 0x197b && devid == 0x2352) { - /* chip found in Thermaltake BlackX Duet, jmicron JMB350? */ + } else if (vendor == 0x197b && (devid == 0x2352 || devid == 0x0325)) { + /* + * 0x2352: found in Thermaltake BlackX Duet, jmicron JMB350? + * 0x0325: jmicron JMB394. + */ ata_for_each_link(link, ap, EDGE) { /* SRST breaks detection and disks get misclassified * LPM disabled to avoid potential problems -- cgit v1.2.3 From 662ffae9ed036bc82ff74c26dc731e2815431fcc Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 30 Jan 2014 15:15:22 +0200 Subject: ASoC: davinci-mcasp: Harmonize the sub hw_params function names Instead of davinci_hw_common_param - for common, I2S/DIT mode settings davinci_hw_dit_param - for DIT protocol configuration davinci_hw_param - for I2S (and compatible protocols) Use the following names: mcasp_common_hw_param, mcasp_dit_hw_param and mcasp_i2s_hw_param. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/davinci/davinci-mcasp.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index b7858bfa0295..9ec456aaf80b 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -448,7 +448,7 @@ static int davinci_config_channel_size(struct davinci_mcasp *mcasp, return 0; } -static int davinci_hw_common_param(struct davinci_mcasp *mcasp, int stream, +static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream, int channels) { int i; @@ -524,7 +524,7 @@ static int davinci_hw_common_param(struct davinci_mcasp *mcasp, int stream, return 0; } -static void davinci_hw_param(struct davinci_mcasp *mcasp, int stream) +static void mcasp_i2s_hw_param(struct davinci_mcasp *mcasp, int stream) { int i, active_slots; u32 mask = 0; @@ -567,7 +567,7 @@ static void davinci_hw_param(struct davinci_mcasp *mcasp, int stream) } /* S/PDIF */ -static void davinci_hw_dit_param(struct davinci_mcasp *mcasp) +static void mcasp_dit_hw_param(struct davinci_mcasp *mcasp) { /* Set the TX format : 24 bit right rotation, 32 bit slot, Pad 0 and LSB first */ @@ -611,7 +611,7 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, active_serializers = (channels + slots - 1) / slots; - if (davinci_hw_common_param(mcasp, substream->stream, channels) == -EINVAL) + if (mcasp_common_hw_param(mcasp, substream->stream, channels) == -EINVAL) return -EINVAL; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) fifo_level = mcasp->txnumevt * active_serializers; @@ -619,9 +619,9 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, fifo_level = mcasp->rxnumevt * active_serializers; if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE) - davinci_hw_dit_param(mcasp); + mcasp_dit_hw_param(mcasp); else - davinci_hw_param(mcasp, substream->stream); + mcasp_i2s_hw_param(mcasp, substream->stream); switch (params_format(params)) { case SNDRV_PCM_FORMAT_U8: -- cgit v1.2.3 From 2c56c4c27c59edfaa779da156f6a70a38bb1f2df Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 30 Jan 2014 15:15:23 +0200 Subject: ASoC: davinci-mcasp: Configure xxTDM, xxFMT and xxFMCT registers synchronously These registers can be configured synchronously for playback and capture. Furthermore when McASP is in master and sync mode the capture operation needs the TX path to be configured in order to be able to provide the needed clocks for the bus. xxFMT and xxFMCT registers has been already configured for both TX and RX other places in the driver. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/davinci/davinci-mcasp.c | 56 +++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 29 deletions(-) diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index 9ec456aaf80b..ae3e40a63e5e 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -524,12 +524,18 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream, return 0; } -static void mcasp_i2s_hw_param(struct davinci_mcasp *mcasp, int stream) +static int mcasp_i2s_hw_param(struct davinci_mcasp *mcasp, int stream) { int i, active_slots; u32 mask = 0; u32 busel = 0; + if ((mcasp->tdm_slots < 2) || (mcasp->tdm_slots > 32)) { + dev_err(mcasp->dev, "tdm slot %d not supported\n", + mcasp->tdm_slots); + return -EINVAL; + } + active_slots = (mcasp->tdm_slots > 31) ? 32 : mcasp->tdm_slots; for (i = 0; i < active_slots; i++) mask |= (1 << i); @@ -539,35 +545,21 @@ static void mcasp_i2s_hw_param(struct davinci_mcasp *mcasp, int stream) if (!mcasp->dat_port) busel = TXSEL; - if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - /* bit stream is MSB first with no delay */ - /* DSP_B mode */ - mcasp_set_reg(mcasp, DAVINCI_MCASP_TXTDM_REG, mask); - mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, busel | TXORD); - - if ((mcasp->tdm_slots >= 2) && (mcasp->tdm_slots <= 32)) - mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, - FSXMOD(mcasp->tdm_slots), FSXMOD(0x1FF)); - else - printk(KERN_ERR "playback tdm slot %d not supported\n", - mcasp->tdm_slots); - } else { - /* bit stream is MSB first with no delay */ - /* DSP_B mode */ - mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, busel | RXORD); - mcasp_set_reg(mcasp, DAVINCI_MCASP_RXTDM_REG, mask); - - if ((mcasp->tdm_slots >= 2) && (mcasp->tdm_slots <= 32)) - mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, - FSRMOD(mcasp->tdm_slots), FSRMOD(0x1FF)); - else - printk(KERN_ERR "capture tdm slot %d not supported\n", - mcasp->tdm_slots); - } + mcasp_set_reg(mcasp, DAVINCI_MCASP_TXTDM_REG, mask); + mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, busel | TXORD); + mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, + FSXMOD(mcasp->tdm_slots), FSXMOD(0x1FF)); + + mcasp_set_reg(mcasp, DAVINCI_MCASP_RXTDM_REG, mask); + mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, busel | RXORD); + mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, + FSRMOD(mcasp->tdm_slots), FSRMOD(0x1FF)); + + return 0; } /* S/PDIF */ -static void mcasp_dit_hw_param(struct davinci_mcasp *mcasp) +static int mcasp_dit_hw_param(struct davinci_mcasp *mcasp) { /* Set the TX format : 24 bit right rotation, 32 bit slot, Pad 0 and LSB first */ @@ -589,6 +581,8 @@ static void mcasp_dit_hw_param(struct davinci_mcasp *mcasp) /* Enable the DIT */ mcasp_set_bits(mcasp, DAVINCI_MCASP_TXDITCTL_REG, DITEN); + + return 0; } static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, @@ -605,6 +599,7 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, u8 slots = mcasp->tdm_slots; u8 active_serializers; int channels; + int ret; struct snd_interval *pcm_channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); channels = pcm_channels->min; @@ -619,9 +614,12 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, fifo_level = mcasp->rxnumevt * active_serializers; if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE) - mcasp_dit_hw_param(mcasp); + ret = mcasp_dit_hw_param(mcasp); else - mcasp_i2s_hw_param(mcasp, substream->stream); + ret = mcasp_i2s_hw_param(mcasp, substream->stream); + + if (ret) + return ret; switch (params_format(params)) { case SNDRV_PCM_FORMAT_U8: -- cgit v1.2.3 From 1d17a04ef2f2982fb81fde8ca3fe75723204a68a Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 30 Jan 2014 15:21:30 +0200 Subject: ASoC: davinci-mcasp: Consolidate pm_runtime_get/put() use in the driver The use of pm_runtime in trigger() callback is not correct and it will lead to unbalanced power.usage_count. The only place which might need to call pm_runtime is the set_fmt callback. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/davinci/davinci-mcasp.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index ae3e40a63e5e..670afa29e30d 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -263,7 +263,9 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) { struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai); + int ret = 0; + pm_runtime_get_sync(mcasp->dev); switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_DSP_B: case SND_SOC_DAIFMT_AC97: @@ -317,7 +319,8 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, break; default: - return -EINVAL; + ret = -EINVAL; + goto out; } switch (fmt & SND_SOC_DAIFMT_INV_MASK) { @@ -354,10 +357,12 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, break; default: - return -EINVAL; + ret = -EINVAL; + break; } - - return 0; +out: + pm_runtime_put_sync(mcasp->dev); + return ret; } static int davinci_mcasp_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div) @@ -676,19 +681,9 @@ static int davinci_mcasp_trigger(struct snd_pcm_substream *substream, case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - ret = pm_runtime_get_sync(mcasp->dev); - if (IS_ERR_VALUE(ret)) - dev_err(mcasp->dev, "pm_runtime_get_sync() failed\n"); davinci_mcasp_start(mcasp, substream->stream); break; - case SNDRV_PCM_TRIGGER_SUSPEND: - davinci_mcasp_stop(mcasp, substream->stream); - ret = pm_runtime_put_sync(mcasp->dev); - if (IS_ERR_VALUE(ret)) - dev_err(mcasp->dev, "pm_runtime_put_sync() failed\n"); - break; - case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: davinci_mcasp_stop(mcasp, substream->stream); -- cgit v1.2.3 From fb6d208d54de2791d6d361ef258ea7d5d3427d01 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 30 Jan 2014 15:21:31 +0200 Subject: ASoC: davinci-evm: Add pm callbacks to platform driver Set snd_soc_pm_ops for the pm ops. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/davinci/davinci-evm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c index 70ff3772079f..5e3bc3c6801a 100644 --- a/sound/soc/davinci/davinci-evm.c +++ b/sound/soc/davinci/davinci-evm.c @@ -399,6 +399,7 @@ static struct platform_driver davinci_evm_driver = { .driver = { .name = "davinci_evm", .owner = THIS_MODULE, + .pm = &snd_soc_pm_ops, .of_match_table = of_match_ptr(davinci_evm_dt_ids), }, }; -- cgit v1.2.3 From 9d27f43274e4889249dc42ca1a3989dd75c5edaf Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Sat, 1 Feb 2014 23:23:10 -0500 Subject: HID: fix buffer allocations When using hid_output_report(), the buffer should be allocated by hid_alloc_report_buf(), not a custom malloc. Signed-off-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-input.c | 2 +- drivers/hid/i2c-hid/i2c-hid.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index d50e7313b171..a713e6211419 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -1178,7 +1178,7 @@ static void hidinput_led_worker(struct work_struct *work) /* fall back to generic raw-output-report */ len = ((report->size - 1) >> 3) + 1 + (report->id > 0); - buf = kmalloc(len, GFP_KERNEL); + buf = hid_alloc_report_buf(report, GFP_KERNEL); if (!buf) return; diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c index e914f2755491..ce68a120ba26 100644 --- a/drivers/hid/i2c-hid/i2c-hid.c +++ b/drivers/hid/i2c-hid/i2c-hid.c @@ -582,7 +582,7 @@ static void i2c_hid_request(struct hid_device *hid, struct hid_report *rep, int ret; int len = i2c_hid_get_report_length(rep) - 2; - buf = kzalloc(len, GFP_KERNEL); + buf = hid_alloc_report_buf(rep, GFP_KERNEL); if (!buf) return; -- cgit v1.2.3 From 9f9c47f00ce99329b1a82e2ac4f70f0fe3db549c Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 3 Feb 2014 10:42:07 -0500 Subject: sata_sil: apply MOD15WRITE quirk to TOSHIBA MK2561GSYN It's a bit odd to see a newer device showing mod15write; however, the reported behavior is highly consistent and other factors which could contribute seem to have been verified well enough. Also, both sata_sil itself and the drive are fairly outdated at this point making the risk of this change fairly low. It is possible, probably likely, that other drive models in the same family have the same problem; however, for now, let's just add the specific model which was tested. Signed-off-by: Tejun Heo Reported-by: matson References: http://lkml.kernel.org/g/201401211912.s0LJCk7F015058@rs103.luxsci.com Cc: stable@vger.kernel.org --- drivers/ata/sata_sil.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c index d67fc351343c..b7695e804635 100644 --- a/drivers/ata/sata_sil.c +++ b/drivers/ata/sata_sil.c @@ -157,6 +157,7 @@ static const struct sil_drivelist { { "ST380011ASL", SIL_QUIRK_MOD15WRITE }, { "ST3120022ASL", SIL_QUIRK_MOD15WRITE }, { "ST3160021ASL", SIL_QUIRK_MOD15WRITE }, + { "TOSHIBA MK2561GSYN", SIL_QUIRK_MOD15WRITE }, { "Maxtor 4D060H3", SIL_QUIRK_UDMA5MAX }, { } }; -- cgit v1.2.3 From 1ff6bbfd13ca2c114a5cb58e1a92d1e5d68ce0b7 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 28 Jan 2014 18:10:37 -0500 Subject: arm, pm, vmpressure: add missing slab.h includes arch/arm/mach-tegra/pm.c, kernel/power/console.c and mm/vmpressure.c were somehow getting slab.h indirectly through cgroup.h which in turn was getting it indirectly through xattr.h. A scheduled cgroup change drops xattr.h inclusion from cgroup.h and breaks compilation of these three files. Add explicit slab.h includes to the three files. A pending cgroup patch depends on this change and it'd be great if this can be routed through cgroup/for-3.14-fixes branch. Signed-off-by: Tejun Heo Acked-by: Stephen Warren Cc: Thierry Reding Cc: linux-tegra@vger.kernel.org Cc: "Rafael J. Wysocki" Cc: linux-pm@vger.kernel.org Cc: Johannes Weiner Cc: Michal Hocko Cc: Balbir Singh Cc: KAMEZAWA Hiroyuki Cc: cgroups@vger.kernel.org --- arch/arm/mach-tegra/pm.c | 1 + kernel/power/console.c | 1 + mm/vmpressure.c | 1 + 3 files changed, 3 insertions(+) diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c index 4ae0286b468d..f55b05a29b55 100644 --- a/arch/arm/mach-tegra/pm.c +++ b/arch/arm/mach-tegra/pm.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include diff --git a/kernel/power/console.c b/kernel/power/console.c index eacb8bd8cab4..aba9c545a0e3 100644 --- a/kernel/power/console.c +++ b/kernel/power/console.c @@ -9,6 +9,7 @@ #include #include #include +#include #include "power.h" #define SUSPEND_CONSOLE (MAX_NR_CONSOLES-1) diff --git a/mm/vmpressure.c b/mm/vmpressure.c index 196970a4541f..d4042e75f7c7 100644 --- a/mm/vmpressure.c +++ b/mm/vmpressure.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3 From 230579d7e0c46fa078ba11899d9b091df689362f Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Tue, 28 Jan 2014 11:29:09 +0800 Subject: cpuset: update MAINTAINERS entry Add mailing list and tree tag to the entry. Signed-off-by: Li Zefan Signed-off-by: Tejun Heo --- MAINTAINERS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index b2cf5cfb4d29..41e52c57cd1a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2408,8 +2408,10 @@ F: tools/power/cpupower/ CPUSETS M: Li Zefan +L: cgroups@vger.kernel.org W: http://www.bullopensource.org/cpuset/ W: http://oss.sgi.com/projects/cpusets/ +T: git git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git S: Maintained F: Documentation/cgroups/cpusets.txt F: include/linux/cpuset.h -- cgit v1.2.3 From 0a6be6555302eebb14510fd6b35bb17e8dfa1386 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 3 Feb 2014 14:31:07 -0500 Subject: nfs: include xattr.h from fs/nfs/nfs3proc.c fs/nfs/nfs3proc.c is making use of xattr but was getting linux/xattr.h indirectly through linux/cgroup.h, which will soon drop the inclusion of xattr.h. Explicitly include linux/xattr.h from nfs3proc.c so that compilation doesn't fail when linux/cgroup.h drops linux/xattr.h. As the following cgroup changes will depend on these changes, it probably would be easier to route this through cgroup branch. Would that be okay? Signed-off-by: Tejun Heo Acked-by: Trond Myklebust Cc: linux-nfs@vger.kernel.org --- fs/nfs/nfs3proc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index aa9bc973f36a..a462ef0fb5d6 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c @@ -18,6 +18,7 @@ #include #include #include +#include #include "iostat.h" #include "internal.h" -- cgit v1.2.3 From bd4a7ce1da061d97c45673e1ca1a6a474bfb4cff Mon Sep 17 00:00:00 2001 From: Huei-Horng Yo Date: Thu, 6 Feb 2014 17:40:34 +0800 Subject: HID: apple: add Apple wireless keyboard 2011 JIS model support Add Apple wireless keyboard 2011 JIS model (05ac:0257). Signed-off-by: Huei-Horng Yo Signed-off-by: Jiri Kosina --- drivers/hid/hid-apple.c | 3 +++ drivers/hid/hid-core.c | 1 + drivers/hid/hid-ids.h | 1 + 3 files changed, 5 insertions(+) diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index 497558127bb3..f822fd2a1ada 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c @@ -469,6 +469,9 @@ static const struct hid_device_id apple_devices[] = { { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI), .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, + USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_JIS), + .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS), .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI), diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 6ed8f5f6e7d4..f36b3524caf1 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1679,6 +1679,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_JIS) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, { HID_USB_DEVICE(USB_VENDOR_ID_AUREAL, USB_DEVICE_ID_AUREAL_W01RN) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 2f10e6e7160d..36281689351b 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -135,6 +135,7 @@ #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS 0x023b #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI 0x0255 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO 0x0256 +#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_JIS 0x0257 #define USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI 0x0290 #define USB_DEVICE_ID_APPLE_WELLSPRING8_ISO 0x0291 #define USB_DEVICE_ID_APPLE_WELLSPRING8_JIS 0x0292 -- cgit v1.2.3 From 7b119fd1bdc59a8060df5b659b9f7a70e0169fd6 Mon Sep 17 00:00:00 2001 From: Sebastian Hesselbarth Date: Thu, 23 Jan 2014 23:38:04 +0100 Subject: irqchip: orion: clear bridge cause register on init It is good practice to mask and clear pending irqs on init. We already mask all irqs, so also clear the bridge irq cause register. Signed-off-by: Sebastian Hesselbarth Tested-by: Ezequiel Garcia Cc: # v3.10+ Signed-off-by: Jason Cooper --- drivers/irqchip/irq-orion.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/irqchip/irq-orion.c b/drivers/irqchip/irq-orion.c index e51d40031884..4137c3d15284 100644 --- a/drivers/irqchip/irq-orion.c +++ b/drivers/irqchip/irq-orion.c @@ -180,8 +180,9 @@ static int __init orion_bridge_irq_init(struct device_node *np, gc->chip_types[0].chip.irq_mask = irq_gc_mask_clr_bit; gc->chip_types[0].chip.irq_unmask = irq_gc_mask_set_bit; - /* mask all interrupts */ + /* mask and clear all interrupts */ writel(0, gc->reg_base + ORION_BRIDGE_IRQ_MASK); + writel(0, gc->reg_base + ORION_BRIDGE_IRQ_CAUSE); irq_set_handler_data(irq, domain); irq_set_chained_handler(irq, orion_bridge_irq_handler); -- cgit v1.2.3 From 5f40067fc86f0e49329ad4a852c278998ff4394e Mon Sep 17 00:00:00 2001 From: Sebastian Hesselbarth Date: Thu, 23 Jan 2014 23:38:05 +0100 Subject: irqchip: orion: use handle_edge_irq on bridge irqs Bridge irqs are edge-triggered, i.e. they get asserted on low-to-high transitions and not on the level of the downstream interrupt line. This replaces handle_level_irq by the more appropriate handle_edge_irq. Signed-off-by: Sebastian Hesselbarth Tested-by: Ezequiel Garcia Cc: : f56c0738b5c2: "irqchip: orion: clear bridge cause register on init" Cc: # v3.10+ Signed-off-by: Jason Cooper --- drivers/irqchip/irq-orion.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/irqchip/irq-orion.c b/drivers/irqchip/irq-orion.c index 4137c3d15284..1f636f719065 100644 --- a/drivers/irqchip/irq-orion.c +++ b/drivers/irqchip/irq-orion.c @@ -143,7 +143,7 @@ static int __init orion_bridge_irq_init(struct device_node *np, } ret = irq_alloc_domain_generic_chips(domain, nrirqs, 1, np->name, - handle_level_irq, clr, 0, IRQ_GC_INIT_MASK_CACHE); + handle_edge_irq, clr, 0, IRQ_GC_INIT_MASK_CACHE); if (ret) { pr_err("%s: unable to alloc irq domain gc\n", np->name); return ret; -- cgit v1.2.3 From e0318ec3bf3f1502cd11b21b1eb00aa355b40b67 Mon Sep 17 00:00:00 2001 From: Sebastian Hesselbarth Date: Fri, 24 Jan 2014 00:10:32 +0100 Subject: irqchip: orion: clear stale interrupts in irq_startup Bridge IRQ_CAUSE bits are asserted regardless of the corresponding bit in IRQ_MASK register. To avoid interrupt events on stale irqs, we have to clear them before unmask. This installs an .irq_startup callback to ensure stale irqs are cleared before initial unmask. Signed-off-by: Sebastian Hesselbarth Tested-by: Ezequiel Garcia Cc: : f56c0738b5c2: "irqchip: orion: clear bridge cause register on init" Cc: : 38bd80b84fca: "irqchip: orion: use handle_edge_irq on bridge irqs" Cc: # v3.10+ Signed-off-by: Jason Cooper --- drivers/irqchip/irq-orion.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/irqchip/irq-orion.c b/drivers/irqchip/irq-orion.c index 1f636f719065..0dfdc5c824a1 100644 --- a/drivers/irqchip/irq-orion.c +++ b/drivers/irqchip/irq-orion.c @@ -123,6 +123,19 @@ static void orion_bridge_irq_handler(unsigned int irq, struct irq_desc *desc) } } +/* + * Bridge IRQ_CAUSE is asserted regardless of IRQ_MASK register. + * To avoid interrupt events on stale irqs, we clear them before unmask. + */ +static unsigned int orion_bridge_irq_startup(struct irq_data *d) +{ + struct irq_chip_type *ct = irq_data_get_chip_type(d); + + ct->chip.irq_ack(d); + ct->chip.irq_unmask(d); + return 0; +} + static int __init orion_bridge_irq_init(struct device_node *np, struct device_node *parent) { @@ -176,6 +189,7 @@ static int __init orion_bridge_irq_init(struct device_node *np, gc->chip_types[0].regs.ack = ORION_BRIDGE_IRQ_CAUSE; gc->chip_types[0].regs.mask = ORION_BRIDGE_IRQ_MASK; + gc->chip_types[0].chip.irq_startup = orion_bridge_irq_startup; gc->chip_types[0].chip.irq_ack = irq_gc_ack_clr_bit; gc->chip_types[0].chip.irq_mask = irq_gc_mask_clr_bit; gc->chip_types[0].chip.irq_unmask = irq_gc_mask_set_bit; -- cgit v1.2.3 From b31b2b6d5de71c569413d8dc4f7b050cbe25a09e Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Fri, 7 Feb 2014 09:35:16 +0200 Subject: ASoC: rt5640: Add ACPI ID for Intel Baytrail Realtek RT5640 uses ACPI ID "10EC5640" for Intel Baytrail platforms. Signed-off-by: Jarkko Nikula Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- sound/soc/codecs/rt5640.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c index a3fb41179636..886924934aa5 100644 --- a/sound/soc/codecs/rt5640.c +++ b/sound/soc/codecs/rt5640.c @@ -2093,6 +2093,7 @@ MODULE_DEVICE_TABLE(i2c, rt5640_i2c_id); #ifdef CONFIG_ACPI static struct acpi_device_id rt5640_acpi_match[] = { { "INT33CA", 0 }, + { "10EC5640", 0 }, { }, }; MODULE_DEVICE_TABLE(acpi, rt5640_acpi_match); -- cgit v1.2.3 From ab3f5faa6255a0eb4f832675507d9e295ca7e9ba Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Thu, 6 Feb 2014 15:56:01 -0800 Subject: cgroup: use an ordered workqueue for cgroup destruction Sometimes the cleanup after memcg hierarchy testing gets stuck in mem_cgroup_reparent_charges(), unable to bring non-kmem usage down to 0. There may turn out to be several causes, but a major cause is this: the workitem to offline parent can get run before workitem to offline child; parent's mem_cgroup_reparent_charges() circles around waiting for the child's pages to be reparented to its lrus, but it's holding cgroup_mutex which prevents the child from reaching its mem_cgroup_reparent_charges(). Just use an ordered workqueue for cgroup_destroy_wq. tj: Committing as the temporary fix until the reverse dependency can be removed from memcg. Comment updated accordingly. Fixes: e5fca243abae ("cgroup: use a dedicated workqueue for cgroup destruction") Suggested-by: Filipe Brandenburger Signed-off-by: Hugh Dickins Cc: stable@vger.kernel.org # 3.10+ Signed-off-by: Tejun Heo --- kernel/cgroup.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/kernel/cgroup.c b/kernel/cgroup.c index e2f46ba37f72..aa95591c1430 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -4845,12 +4845,16 @@ static int __init cgroup_wq_init(void) /* * There isn't much point in executing destruction path in * parallel. Good chunk is serialized with cgroup_mutex anyway. - * Use 1 for @max_active. + * + * XXX: Must be ordered to make sure parent is offlined after + * children. The ordering requirement is for memcg where a + * parent's offline may wait for a child's leading to deadlock. In + * the long term, this should be fixed from memcg side. * * We would prefer to do this in cgroup_init() above, but that * is called before init_workqueues(): so leave this until after. */ - cgroup_destroy_wq = alloc_workqueue("cgroup_destroy", 0, 1); + cgroup_destroy_wq = alloc_ordered_workqueue("cgroup_destroy", 0); BUG_ON(!cgroup_destroy_wq); /* -- cgit v1.2.3 From eb46bf89696972b856a9adb6aebd5c7b65c266e4 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 8 Feb 2014 10:26:33 -0500 Subject: cgroup: fix error return value in cgroup_mount() When cgroup_mount() fails to allocate an id for the root, it didn't set ret before jumping to unlock_drop ending up returning 0 after a failure. Fix it. Signed-off-by: Tejun Heo Acked-by: Li Zefan Cc: stable@vger.kernel.org --- kernel/cgroup.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/cgroup.c b/kernel/cgroup.c index aa95591c1430..793f37176077 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -1566,10 +1566,10 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type, mutex_lock(&cgroup_mutex); mutex_lock(&cgroup_root_mutex); - root_cgrp->id = idr_alloc(&root->cgroup_idr, root_cgrp, - 0, 1, GFP_KERNEL); - if (root_cgrp->id < 0) + ret = idr_alloc(&root->cgroup_idr, root_cgrp, 0, 1, GFP_KERNEL); + if (ret < 0) goto unlock_drop; + root_cgrp->id = ret; /* Check for name clashes with existing mounts */ ret = -EBUSY; -- cgit v1.2.3 From b58c89986a77a23658682a100eb15d8edb571ebb Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 8 Feb 2014 10:26:33 -0500 Subject: cgroup: fix error return from cgroup_create() cgroup_create() was returning 0 after allocation failures. Fix it. Signed-off-by: Tejun Heo Acked-by: Li Zefan Cc: stable@vger.kernel.org --- kernel/cgroup.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 793f37176077..0eb7b868e1ab 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -4158,7 +4158,7 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry, struct cgroup *cgrp; struct cgroup_name *name; struct cgroupfs_root *root = parent->root; - int ssid, err = 0; + int ssid, err; struct cgroup_subsys *ss; struct super_block *sb = root->sb; @@ -4168,8 +4168,10 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry, return -ENOMEM; name = cgroup_alloc_name(dentry); - if (!name) + if (!name) { + err = -ENOMEM; goto err_free_cgrp; + } rcu_assign_pointer(cgrp->name, name); /* @@ -4177,8 +4179,10 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry, * a half-baked cgroup. */ cgrp->id = idr_alloc(&root->cgroup_idr, NULL, 1, 0, GFP_KERNEL); - if (cgrp->id < 0) + if (cgrp->id < 0) { + err = -ENOMEM; goto err_free_name; + } /* * Only live parents can have children. Note that the liveliness -- cgit v1.2.3 From 48573a893303986e3b0b2974d6fb11f3d1bb7064 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 8 Feb 2014 10:26:34 -0500 Subject: cgroup: fix locking in cgroup_cfts_commit() cgroup_cfts_commit() walks the cgroup hierarchy that the target subsystem is attached to and tries to apply the file changes. Due to the convolution with inode locking, it can't keep cgroup_mutex locked while iterating. It currently holds only RCU read lock around the actual iteration and then pins the found cgroup using dget(). Unfortunately, this is incorrect. Although the iteration does check cgroup_is_dead() before invoking dget(), there's nothing which prevents the dentry from going away inbetween. Note that this is different from the usual css iterations where css_tryget() is used to pin the css - css_tryget() tests whether the css can be pinned and fails if not. The problem can be solved by simply holding cgroup_mutex instead of RCU read lock around the iteration, which actually reduces LOC. Signed-off-by: Tejun Heo Acked-by: Li Zefan Cc: stable@vger.kernel.org --- kernel/cgroup.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 0eb7b868e1ab..3edf7163b84f 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -2763,10 +2763,7 @@ static int cgroup_cfts_commit(struct cftype *cfts, bool is_add) */ update_before = cgroup_serial_nr_next; - mutex_unlock(&cgroup_mutex); - /* add/rm files for all cgroups created before */ - rcu_read_lock(); css_for_each_descendant_pre(css, cgroup_css(root, ss)) { struct cgroup *cgrp = css->cgroup; @@ -2775,23 +2772,19 @@ static int cgroup_cfts_commit(struct cftype *cfts, bool is_add) inode = cgrp->dentry->d_inode; dget(cgrp->dentry); - rcu_read_unlock(); - dput(prev); prev = cgrp->dentry; + mutex_unlock(&cgroup_mutex); mutex_lock(&inode->i_mutex); mutex_lock(&cgroup_mutex); if (cgrp->serial_nr < update_before && !cgroup_is_dead(cgrp)) ret = cgroup_addrm_files(cgrp, cfts, is_add); - mutex_unlock(&cgroup_mutex); mutex_unlock(&inode->i_mutex); - - rcu_read_lock(); if (ret) break; } - rcu_read_unlock(); + mutex_unlock(&cgroup_mutex); dput(prev); deactivate_super(sb); return ret; -- cgit v1.2.3 From 87f9260bf1fb7ec4c3f88c6bb353df17ca1e1c19 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 8 Feb 2014 21:18:24 +0000 Subject: ARM: dts: fix spdif pinmux configuration The spdif pinmux configuration must be connected to the spdif device to take effect, not the spdif-transmitter. Signed-off-by: Russell King --- arch/arm/boot/dts/imx6dl-hummingboard.dts | 10 +++------- arch/arm/boot/dts/imx6qdl-cubox-i.dtsi | 10 +++------- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/arch/arm/boot/dts/imx6dl-hummingboard.dts b/arch/arm/boot/dts/imx6dl-hummingboard.dts index fd8fc7cd53f3..5bfae54fb780 100644 --- a/arch/arm/boot/dts/imx6dl-hummingboard.dts +++ b/arch/arm/boot/dts/imx6dl-hummingboard.dts @@ -52,12 +52,6 @@ }; }; - codec: spdif-transmitter { - compatible = "linux,spdif-dit"; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_hummingboard_spdif>; - }; - sound-spdif { compatible = "fsl,imx-audio-spdif"; model = "imx-spdif"; @@ -111,7 +105,7 @@ }; pinctrl_hummingboard_spdif: hummingboard-spdif { - fsl,pins = ; + fsl,pins = ; }; pinctrl_hummingboard_usbh1_vbus: hummingboard-usbh1-vbus { @@ -142,6 +136,8 @@ }; &spdif { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_hummingboard_spdif>; status = "okay"; }; diff --git a/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi b/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi index 64daa3b311f6..c2a24888a276 100644 --- a/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi +++ b/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi @@ -46,12 +46,6 @@ }; }; - codec: spdif-transmitter { - compatible = "linux,spdif-dit"; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_cubox_i_spdif>; - }; - sound-spdif { compatible = "fsl,imx-audio-spdif"; model = "imx-spdif"; @@ -89,7 +83,7 @@ }; pinctrl_cubox_i_spdif: cubox-i-spdif { - fsl,pins = ; + fsl,pins = ; }; pinctrl_cubox_i_usbh1_vbus: cubox-i-usbh1-vbus { @@ -121,6 +115,8 @@ }; &spdif { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_cubox_i_spdif>; status = "okay"; }; -- cgit v1.2.3 From e97df76377b8b3b1f7dfd5d6f8a1d5a31438b140 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 5 Feb 2014 20:48:51 +0100 Subject: perf/x86/intel/p6: Add userspace RDPMC quirk for PPro PPro machines can die hard when PCE gets enabled due to a CPU erratum. The safe way it so disable it by default and keep it disabled. See erratum 26 in: http://download.intel.com/design/archives/processors/pro/docs/24268935.pdf Reported-and-Tested-by: Mark Davies Cc: Alan Cox Cc: Stephane Eranian Cc: Vince Weaver Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/20140206170815.GW2936@laptop.programming.kicks-ass.net Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/perf_event.c | 6 ++++- arch/x86/kernel/cpu/perf_event.h | 1 + arch/x86/kernel/cpu/perf_event_p6.c | 48 +++++++++++++++++++++++++------------ 3 files changed, 39 insertions(+), 16 deletions(-) diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index b88645191fe5..1246b853c4e0 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -1521,6 +1521,8 @@ static int __init init_hw_perf_events(void) pr_cont("%s PMU driver.\n", x86_pmu.name); + x86_pmu.attr_rdpmc = 1; /* enable userspace RDPMC usage by default */ + for (quirk = x86_pmu.quirks; quirk; quirk = quirk->next) quirk->func(); @@ -1534,7 +1536,6 @@ static int __init init_hw_perf_events(void) __EVENT_CONSTRAINT(0, (1ULL << x86_pmu.num_counters) - 1, 0, x86_pmu.num_counters, 0, 0); - x86_pmu.attr_rdpmc = 1; /* enable userspace RDPMC usage by default */ x86_pmu_format_group.attrs = x86_pmu.format_attrs; if (x86_pmu.event_attrs) @@ -1820,6 +1821,9 @@ static ssize_t set_attr_rdpmc(struct device *cdev, if (ret) return ret; + if (x86_pmu.attr_rdpmc_broken) + return -ENOTSUPP; + if (!!val != !!x86_pmu.attr_rdpmc) { x86_pmu.attr_rdpmc = !!val; smp_call_function(change_rdpmc, (void *)val, 1); diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h index c1a861829d81..4972c244d0bc 100644 --- a/arch/x86/kernel/cpu/perf_event.h +++ b/arch/x86/kernel/cpu/perf_event.h @@ -409,6 +409,7 @@ struct x86_pmu { /* * sysfs attrs */ + int attr_rdpmc_broken; int attr_rdpmc; struct attribute **format_attrs; struct attribute **event_attrs; diff --git a/arch/x86/kernel/cpu/perf_event_p6.c b/arch/x86/kernel/cpu/perf_event_p6.c index b1e2fe115323..7c1a0c07b607 100644 --- a/arch/x86/kernel/cpu/perf_event_p6.c +++ b/arch/x86/kernel/cpu/perf_event_p6.c @@ -231,31 +231,49 @@ static __initconst const struct x86_pmu p6_pmu = { }; +static __init void p6_pmu_rdpmc_quirk(void) +{ + if (boot_cpu_data.x86_mask < 9) { + /* + * PPro erratum 26; fixed in stepping 9 and above. + */ + pr_warn("Userspace RDPMC support disabled due to a CPU erratum\n"); + x86_pmu.attr_rdpmc_broken = 1; + x86_pmu.attr_rdpmc = 0; + } +} + __init int p6_pmu_init(void) { + x86_pmu = p6_pmu; + switch (boot_cpu_data.x86_model) { - case 1: - case 3: /* Pentium Pro */ - case 5: - case 6: /* Pentium II */ - case 7: - case 8: - case 11: /* Pentium III */ - case 9: - case 13: - /* Pentium M */ + case 1: /* Pentium Pro */ + x86_add_quirk(p6_pmu_rdpmc_quirk); + break; + + case 3: /* Pentium II - Klamath */ + case 5: /* Pentium II - Deschutes */ + case 6: /* Pentium II - Mendocino */ break; + + case 7: /* Pentium III - Katmai */ + case 8: /* Pentium III - Coppermine */ + case 10: /* Pentium III Xeon */ + case 11: /* Pentium III - Tualatin */ + break; + + case 9: /* Pentium M - Banias */ + case 13: /* Pentium M - Dothan */ + break; + default: - pr_cont("unsupported p6 CPU model %d ", - boot_cpu_data.x86_model); + pr_cont("unsupported p6 CPU model %d ", boot_cpu_data.x86_model); return -ENODEV; } - x86_pmu = p6_pmu; - memcpy(hw_cache_event_ids, p6_hw_cache_event_ids, sizeof(hw_cache_event_ids)); - return 0; } -- cgit v1.2.3 From 0e9f2204cfa6d79abe3e525ddf7c4ab5792cc751 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 5 Feb 2014 11:19:56 +0100 Subject: perf/x86: Fix Userspace RDPMC switch The current code forgets to change the CR4 state on the current CPU. Use on_each_cpu() instead of smp_call_function(). Reported-by: Mark Davies Suggested-by: Mark Davies Signed-off-by: Peter Zijlstra Cc: fweisbec@gmail.com Link: http://lkml.kernel.org/n/tip-69efsat90ibhnd577zy3z9gh@git.kernel.org Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/perf_event.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 1246b853c4e0..895604f2e916 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -1826,7 +1826,7 @@ static ssize_t set_attr_rdpmc(struct device *cdev, if (!!val != !!x86_pmu.attr_rdpmc) { x86_pmu.attr_rdpmc = !!val; - smp_call_function(change_rdpmc, (void *)val, 1); + on_each_cpu(change_rdpmc, (void *)val, 1); } return count; -- cgit v1.2.3 From fe60a8a0919eeee862054137fed49f00b710d9cd Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 10 Feb 2014 10:35:22 +1100 Subject: xfs: ensure correct timestamp updates from truncate The VFS doesn't set the proper ATTR_CTIME and ATTR_MTIME values for truncate, so filesystems have to manually add them. The introduction of xfs_setattr_time accidentally broke this special case an caused a regression in generic/313. Fix this by removing the local mask variable in xfs_setattr_size so that we only have a single place to keep the attribute information. cc: Signed-off-by: Christoph Hellwig Reported-by: Fengguang Wu Reviewed-by: Brian Foster Reviewed-by: Jie Liu Signed-off-by: Dave Chinner --- fs/xfs/xfs_iops.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index f35d5c953ff9..9ddfb8190ca1 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -705,7 +705,6 @@ xfs_setattr_size( { struct xfs_mount *mp = ip->i_mount; struct inode *inode = VFS_I(ip); - int mask = iattr->ia_valid; xfs_off_t oldsize, newsize; struct xfs_trans *tp; int error; @@ -726,8 +725,8 @@ xfs_setattr_size( ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL)); ASSERT(S_ISREG(ip->i_d.di_mode)); - ASSERT((mask & (ATTR_UID|ATTR_GID|ATTR_ATIME|ATTR_ATIME_SET| - ATTR_MTIME_SET|ATTR_KILL_PRIV|ATTR_TIMES_SET)) == 0); + ASSERT((iattr->ia_valid & (ATTR_UID|ATTR_GID|ATTR_ATIME|ATTR_ATIME_SET| + ATTR_MTIME_SET|ATTR_KILL_PRIV|ATTR_TIMES_SET)) == 0); oldsize = inode->i_size; newsize = iattr->ia_size; @@ -736,7 +735,7 @@ xfs_setattr_size( * Short circuit the truncate case for zero length files. */ if (newsize == 0 && oldsize == 0 && ip->i_d.di_nextents == 0) { - if (!(mask & (ATTR_CTIME|ATTR_MTIME))) + if (!(iattr->ia_valid & (ATTR_CTIME|ATTR_MTIME))) return 0; /* @@ -824,10 +823,11 @@ xfs_setattr_size( * these flags set. For all other operations the VFS set these flags * explicitly if it wants a timestamp update. */ - if (newsize != oldsize && (!(mask & (ATTR_CTIME | ATTR_MTIME)))) { + if (newsize != oldsize && + !(iattr->ia_valid & (ATTR_CTIME | ATTR_MTIME))) { iattr->ia_ctime = iattr->ia_mtime = current_fs_time(inode->i_sb); - mask |= ATTR_CTIME | ATTR_MTIME; + iattr->ia_valid |= ATTR_CTIME | ATTR_MTIME; } /* @@ -863,9 +863,9 @@ xfs_setattr_size( xfs_inode_clear_eofblocks_tag(ip); } - if (mask & ATTR_MODE) + if (iattr->ia_valid & ATTR_MODE) xfs_setattr_mode(ip, iattr); - if (mask & (ATTR_ATIME|ATTR_CTIME|ATTR_MTIME)) + if (iattr->ia_valid & (ATTR_ATIME|ATTR_CTIME|ATTR_MTIME)) xfs_setattr_time(ip, iattr); xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); -- cgit v1.2.3 From 3895e51f6dbf6610519be070a3bede811f6ac4fb Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Mon, 10 Feb 2014 10:37:18 +1100 Subject: xfs: ensure correct log item buffer alignment On 32 bit platforms, the log item vector headers are not 64 bit aligned or sized. hence if we don't take care to align them correctly or pad the buffer appropriately for 8 byte alignment, we can end up with alignment issues when accessing the user buffer directly as a structure. To solve this, simply pad the buffer headers to 64 bit offset so that the data section is always 8 byte aligned. Signed-off-by: Dave Chinner Reported-by: Michael L. Semon Tested-by: Michael L. Semon Reviewed-by: Christoph Hellwig Signed-off-by: Dave Chinner --- fs/xfs/xfs_log_cil.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/fs/xfs/xfs_log_cil.c b/fs/xfs/xfs_log_cil.c index cdebd832c3db..4ef6fdbced78 100644 --- a/fs/xfs/xfs_log_cil.c +++ b/fs/xfs/xfs_log_cil.c @@ -205,16 +205,25 @@ xlog_cil_insert_format_items( /* * We 64-bit align the length of each iovec so that the start * of the next one is naturally aligned. We'll need to - * account for that slack space here. + * account for that slack space here. Then round nbytes up + * to 64-bit alignment so that the initial buffer alignment is + * easy to calculate and verify. */ nbytes += niovecs * sizeof(uint64_t); + nbytes = round_up(nbytes, sizeof(uint64_t)); /* grab the old item if it exists for reservation accounting */ old_lv = lip->li_lv; - /* calc buffer size */ - buf_size = sizeof(struct xfs_log_vec) + nbytes + - niovecs * sizeof(struct xfs_log_iovec); + /* + * The data buffer needs to start 64-bit aligned, so round up + * that space to ensure we can align it appropriately and not + * overrun the buffer. + */ + buf_size = nbytes + + round_up((sizeof(struct xfs_log_vec) + + niovecs * sizeof(struct xfs_log_iovec)), + sizeof(uint64_t)); /* compare to existing item size */ if (lip->li_lv && buf_size <= lip->li_lv->lv_size) { @@ -251,6 +260,8 @@ xlog_cil_insert_format_items( /* The allocated data region lies beyond the iovec region */ lv->lv_buf_len = 0; lv->lv_buf = (char *)lv + buf_size - nbytes; + ASSERT(IS_ALIGNED((unsigned long)lv->lv_buf, sizeof(uint64_t))); + lip->li_ops->iop_format(lip, lv); insert: ASSERT(lv->lv_buf_len <= nbytes); -- cgit v1.2.3 From 4d9c5b89cf3605bbc39c6e274351ff25f0d83e6a Mon Sep 17 00:00:00 2001 From: Christoffer Dall Date: Sun, 2 Feb 2014 22:21:31 +0100 Subject: ARM: 7950/1: mm: Fix stage-2 device memory attributes The stage-2 memory attributes are distinct from the Hyp memory attributes and the Stage-1 memory attributes. We were using the stage-1 memory attributes for stage-2 mappings causing device mappings to be mapped as normal memory. Add the S2 equivalent defines for memory attributes and fix the comments explaining the defines while at it. Add a prot_pte_s2 field to the mem_type struct and fill out the field for device mappings accordingly. Cc: [3.9+] Acked-by: Marc Zyngier Acked-by: Catalin Marinas Signed-off-by: Christoffer Dall Signed-off-by: Russell King --- arch/arm/include/asm/pgtable-3level.h | 15 +++++++++------ arch/arm/mm/mm.h | 1 + arch/arm/mm/mmu.c | 7 ++++++- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/arch/arm/include/asm/pgtable-3level.h b/arch/arm/include/asm/pgtable-3level.h index 03243f7eeddf..85c60adc8b60 100644 --- a/arch/arm/include/asm/pgtable-3level.h +++ b/arch/arm/include/asm/pgtable-3level.h @@ -120,13 +120,16 @@ /* * 2nd stage PTE definitions for LPAE. */ -#define L_PTE_S2_MT_UNCACHED (_AT(pteval_t, 0x5) << 2) /* MemAttr[3:0] */ -#define L_PTE_S2_MT_WRITETHROUGH (_AT(pteval_t, 0xa) << 2) /* MemAttr[3:0] */ -#define L_PTE_S2_MT_WRITEBACK (_AT(pteval_t, 0xf) << 2) /* MemAttr[3:0] */ -#define L_PTE_S2_RDONLY (_AT(pteval_t, 1) << 6) /* HAP[1] */ -#define L_PTE_S2_RDWR (_AT(pteval_t, 3) << 6) /* HAP[2:1] */ +#define L_PTE_S2_MT_UNCACHED (_AT(pteval_t, 0x0) << 2) /* strongly ordered */ +#define L_PTE_S2_MT_WRITETHROUGH (_AT(pteval_t, 0xa) << 2) /* normal inner write-through */ +#define L_PTE_S2_MT_WRITEBACK (_AT(pteval_t, 0xf) << 2) /* normal inner write-back */ +#define L_PTE_S2_MT_DEV_SHARED (_AT(pteval_t, 0x1) << 2) /* device */ +#define L_PTE_S2_MT_MASK (_AT(pteval_t, 0xf) << 2) -#define L_PMD_S2_RDWR (_AT(pmdval_t, 3) << 6) /* HAP[2:1] */ +#define L_PTE_S2_RDONLY (_AT(pteval_t, 1) << 6) /* HAP[1] */ +#define L_PTE_S2_RDWR (_AT(pteval_t, 3) << 6) /* HAP[2:1] */ + +#define L_PMD_S2_RDWR (_AT(pmdval_t, 3) << 6) /* HAP[2:1] */ /* * Hyp-mode PL2 PTE definitions for LPAE. diff --git a/arch/arm/mm/mm.h b/arch/arm/mm/mm.h index d5a982d15a88..7ea641b7aa7d 100644 --- a/arch/arm/mm/mm.h +++ b/arch/arm/mm/mm.h @@ -38,6 +38,7 @@ static inline pmd_t *pmd_off_k(unsigned long virt) struct mem_type { pteval_t prot_pte; + pteval_t prot_pte_s2; pmdval_t prot_l1; pmdval_t prot_sect; unsigned int domain; diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 4f08c133cc25..a623cb3ad012 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -232,12 +232,16 @@ __setup("noalign", noalign_setup); #endif /* ifdef CONFIG_CPU_CP15 / else */ #define PROT_PTE_DEVICE L_PTE_PRESENT|L_PTE_YOUNG|L_PTE_DIRTY|L_PTE_XN +#define PROT_PTE_S2_DEVICE PROT_PTE_DEVICE #define PROT_SECT_DEVICE PMD_TYPE_SECT|PMD_SECT_AP_WRITE static struct mem_type mem_types[] = { [MT_DEVICE] = { /* Strongly ordered / ARMv6 shared device */ .prot_pte = PROT_PTE_DEVICE | L_PTE_MT_DEV_SHARED | L_PTE_SHARED, + .prot_pte_s2 = s2_policy(PROT_PTE_S2_DEVICE) | + s2_policy(L_PTE_S2_MT_DEV_SHARED) | + L_PTE_SHARED, .prot_l1 = PMD_TYPE_TABLE, .prot_sect = PROT_SECT_DEVICE | PMD_SECT_S, .domain = DOMAIN_IO, @@ -508,7 +512,8 @@ static void __init build_mem_type_table(void) cp = &cache_policies[cachepolicy]; vecs_pgprot = kern_pgprot = user_pgprot = cp->pte; s2_pgprot = cp->pte_s2; - hyp_device_pgprot = s2_device_pgprot = mem_types[MT_DEVICE].prot_pte; + hyp_device_pgprot = mem_types[MT_DEVICE].prot_pte; + s2_device_pgprot = mem_types[MT_DEVICE].prot_pte_s2; /* * ARMv6 and above have extended page tables. -- cgit v1.2.3 From ca4744084772e1fee999391bee0fcdca5d91a757 Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Thu, 6 Feb 2014 19:50:35 +0100 Subject: ARM: 7952/1: mm: Fix the memblock allocation for LPAE machines Commit ad6492b8 added much needed memblock_virt_alloc_low() and further commit 07bacb3 {memblock, bootmem: restore goal for alloc_low} fixed the issue with low memory limit thanks to Yinghai. But even after all these fixes, there is still one case where the limit check done with ARCH_LOW_ADDRESS_LIMIT for low memory fails. Russell pointed out the issue with 32 bit LPAE machines in below thread. https://lkml.org/lkml/2014/1/28/364 Since on some LPAE machines where memory start address is beyond 4GB, the low memory marker in memblock will be set to default ARCH_LOW_ADDRESS_LIMIT which is wrong. We can fix this by letting architectures set the ARCH_LOW_ADDRESS_LIMIT using another export similar to memblock_set_current_limit() but am not sure whether its worth the trouble. Tell me if you think otherwise. Rather am just trying to fix that one broken case using memblock_virt_alloc() in setup code since the memblock.current_limit is updated appropriately makes it work on all ARM 32 bit machines. Cc: Yinghai Lu Cc: Strashko, Grygorii Cc: Andrew Morton Signed-off-by: Santosh Shilimkar Signed-off-by: Russell King --- arch/arm/kernel/setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index b0df9761de6d..1e8b030dbefd 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -731,7 +731,7 @@ static void __init request_standard_resources(const struct machine_desc *mdesc) kernel_data.end = virt_to_phys(_end - 1); for_each_memblock(memory, region) { - res = memblock_virt_alloc_low(sizeof(*res), 0); + res = memblock_virt_alloc(sizeof(*res), 0); res->name = "System RAM"; res->start = __pfn_to_phys(memblock_region_memory_base_pfn(region)); res->end = __pfn_to_phys(memblock_region_memory_end_pfn(region)) - 1; -- cgit v1.2.3 From bae0ca2bc550d1ec6a118fb8f2696f18c4da3d8e Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 7 Feb 2014 19:12:20 +0100 Subject: ARM: 7953/1: mm: ensure TLB invalidation is complete before enabling MMU During __v{6,7}_setup, we invalidate the TLBs since we are about to enable the MMU on return to head.S. Unfortunately, without a subsequent dsb instruction, the invalidation is not guaranteed to have completed by the time we write to the sctlr, potentially exposing us to junk/stale translations cached in the TLB. This patch reworks the init functions so that the dsb used to ensure completion of cache/predictor maintenance is also used to ensure completion of the TLB invalidation. Cc: Reported-by: Albin Tonnerre Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/mm/proc-v6.S | 3 ++- arch/arm/mm/proc-v7.S | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S index 45dc29f85d56..32b3558321c4 100644 --- a/arch/arm/mm/proc-v6.S +++ b/arch/arm/mm/proc-v6.S @@ -208,7 +208,6 @@ __v6_setup: mcr p15, 0, r0, c7, c14, 0 @ clean+invalidate D cache mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache mcr p15, 0, r0, c7, c15, 0 @ clean+invalidate cache - mcr p15, 0, r0, c7, c10, 4 @ drain write buffer #ifdef CONFIG_MMU mcr p15, 0, r0, c8, c7, 0 @ invalidate I + D TLBs mcr p15, 0, r0, c2, c0, 2 @ TTB control register @@ -218,6 +217,8 @@ __v6_setup: ALT_UP(orr r8, r8, #TTB_FLAGS_UP) mcr p15, 0, r8, c2, c0, 1 @ load TTB1 #endif /* CONFIG_MMU */ + mcr p15, 0, r0, c7, c10, 4 @ drain write buffer and + @ complete invalidations adr r5, v6_crval ldmia r5, {r5, r6} ARM_BE8(orr r6, r6, #1 << 25) @ big-endian page tables diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index bd1781979a39..74f6033e76dd 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S @@ -351,7 +351,6 @@ __v7_setup: 4: mov r10, #0 mcr p15, 0, r10, c7, c5, 0 @ I+BTB cache invalidate - dsb #ifdef CONFIG_MMU mcr p15, 0, r10, c8, c7, 0 @ invalidate I + D TLBs v7_ttb_setup r10, r4, r8, r5 @ TTBCR, TTBRx setup @@ -360,6 +359,7 @@ __v7_setup: mcr p15, 0, r5, c10, c2, 0 @ write PRRR mcr p15, 0, r6, c10, c2, 1 @ write NMRR #endif + dsb @ Complete invalidations #ifndef CONFIG_ARM_THUMBEE mrc p15, 0, r0, c0, c1, 0 @ read ID_PFR0 for ThumbEE and r0, r0, #(0xf << 12) @ ThumbEE enabled field -- cgit v1.2.3 From 7c8746a9eb287642deaad0e7c2cdf482dce5e4be Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 7 Feb 2014 19:12:32 +0100 Subject: ARM: 7955/1: spinlock: ensure we have a compiler barrier before sev When unlocking a spinlock, we require the following, strictly ordered sequence of events: /* dmb */ /* dsb */ Whilst the code does indeed reflect this in terms of the architecture, the final + have been contracted into a single inline asm without a "memory" clobber, therefore the compiler is at liberty to reorder the unlock to the end of the above sequence. In such a case, a waiting CPU may be woken up before the lock has been unlocked, leading to extremely poor performance. This patch reworks the dsb_sev() function to make use of the dsb() macro and ensure ordering against the unlock. Cc: Reported-by: Mark Rutland Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/include/asm/spinlock.h | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/arch/arm/include/asm/spinlock.h b/arch/arm/include/asm/spinlock.h index ef3c6072aa45..ac4bfae26702 100644 --- a/arch/arm/include/asm/spinlock.h +++ b/arch/arm/include/asm/spinlock.h @@ -37,18 +37,9 @@ static inline void dsb_sev(void) { -#if __LINUX_ARM_ARCH__ >= 7 - __asm__ __volatile__ ( - "dsb ishst\n" - SEV - ); -#else - __asm__ __volatile__ ( - "mcr p15, 0, %0, c7, c10, 4\n" - SEV - : : "r" (0) - ); -#endif + + dsb(ishst); + __asm__(SEV); } /* -- cgit v1.2.3 From 47cf84e17ebb79a20e6244b954c4ea4e18a82d43 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Sat, 8 Feb 2014 13:20:35 +0800 Subject: ASoC: fsl: fix pm support of machine drivers The commit 1abe729 (ASoC: fsl: Add missing pm to current machine drivers) enables pm support for a few IMX machine drivers. But it does not update dev drvdata to be the pointer to 'card'. This causes the kernel dump below in system suspend, because snd_soc_suspend() expects that the dev drvdata points to 'card', while it still points to the private data of machine driver. This patch fixes imx-sgtl5000 and imx-wm8962 by attaching 'card' to dev drvdata and private data to card drvdata. For imx-mc13783, I simply revert the pm change because it must be broken for the same reason and I don't have hardware to test pm enabling code. $ echo mem > /sys/power/state PM: Syncing filesystems ... done. PM: Preparing system for mem sleep mmc1: card e624 removed Freezing user space processes ... (elapsed 0.002 seconds) done. Freezing remaining freezable tasks ... (elapsed 0.002 seconds) done. PM: Entering mem sleep INFO: trying to register non-static key. the code is fine but needs lockdep annotation. turning off the locking correctness validator. CPU: 0 PID: 1861 Comm: bash Not tainted 3.14.0-rc1+ #1648 Backtrace: [<80012144>] (dump_backtrace) from [<800122e4>] (show_stack+0x18/0x1c) r6:8079c77c r5:00000c5a r4:00000000 r3:00000000 [<800122cc>] (show_stack) from [<80637ac0>] (dump_stack+0x78/0x94) [<80637a48>] (dump_stack) from [<80028918>] (warn_slowpath_common+0x6c/0x8c) r4:bdb21c38 r3:be62df00 [<800288ac>] (warn_slowpath_common) from [<800289dc>] (warn_slowpath_fmt+0x38/0x40) r8:be62e3a8 r7:bf122960 r6:00000005 r5:00000000 r4:00000000 [<800289a8>] (warn_slowpath_fmt) from [<8006518c>] (__lock_acquire+0x1ae0/0x1ce0) r3:8079d598 r2:80799e70 [<800636ac>] (__lock_acquire) from [<80065894>] (lock_acquire+0x68/0x7c) r10:bdb20000 r9:be62df00 r8:00000000 r7:00000000 r6:60000013 r5:bdb20000 r4:00000000 [<8006582c>] (lock_acquire) from [<8063c938>] (mutex_lock_nested+0x5c/0x3b8) r7:00000000 r6:80dfc78c r5:804be444 r4:bf122928 [<8063c8dc>] (mutex_lock_nested) from [<804be444>] (snd_soc_suspend+0x34/0x42c) r10:00000000 r9:00000000 r8:00000000 r7:bf1c4444 r6:bf1c4410 r5:be978150 r4:be978010 [<804be410>] (snd_soc_suspend) from [<8034392c>] (platform_pm_suspend+0x34/0x64) r10:00000000 r8:00000000 r7:bf1c4444 r6:bf1c4410 r5:803438f8 r4:bf1c4410 [<803438f8>] (platform_pm_suspend) from [<80348e18>] (dpm_run_callback.isra.7+0x34/0x6c) [<80348de4>] (dpm_run_callback.isra.7) from [<80349354>] (__device_suspend+0x10c/0x220) r9:808dd974 r8:808c4a5c r6:00000002 r5:80e5001c r4:bf1c4410 [<80349248>] (__device_suspend) from [<8034a338>] (dpm_suspend+0x60/0x220) r7:bf1c4410 r6:808dd90c r5:80e5001c r4:bf1c44c0 [<8034a2d8>] (dpm_suspend) from [<8034a790>] (dpm_suspend_start+0x60/0x68) r10:8079a818 r9:00000000 r8:00000004 r7:80dfbe90 r6:80641eec r5:00000000 r4:00000002 [<8034a730>] (dpm_suspend_start) from [<8006a788>] (suspend_devices_and_enter+0x74/0x318) r4:00000003 r3:80dfbe98 [<8006a714>] (suspend_devices_and_enter) from [<8006abd8>] (pm_suspend+0x1ac/0x244) r10:8079a818 r8:00000004 r7:00000003 r6:80641eec r5:00000000 r4:00000003 [<8006aa2c>] (pm_suspend) from [<80069a4c>] (state_store+0x70/0xc0) r5:00000003 r4:bd85ea40 [<800699dc>] (state_store) from [<80294034>] (kobj_attr_store+0x1c/0x28) r10:beb9fe08 r8:00000000 r7:bdb21f78 r6:bd85ea40 r5:00000004 r4:beb9fe00 [<80294018>] (kobj_attr_store) from [<80140f90>] (sysfs_kf_write+0x54/0x58) [<80140f3c>] (sysfs_kf_write) from [<8014474c>] (kernfs_fop_write+0xc4/0x160) r6:bd85ea40 r5:beb9fe00 r4:00000004 r3:80140f3c [<80144688>] (kernfs_fop_write) from [<800dfa14>] (vfs_write+0xbc/0x184) r10:00000000 r9:00000000 r8:00000000 r7:bdb21f78 r6:00500c08 r5:00000004 r4:be782600 [<800df958>] (vfs_write) from [<800dfe00>] (SyS_write+0x48/0x70) r10:00000000 r8:00000000 r7:00000004 r6:00500c08 r5:00000000 r4:be782600 [<800dfdb8>] (SyS_write) from [<8000e800>] (ret_fast_syscall+0x0/0x48) r9:bdb20000 r8:8000e9c4 r7:00000004 r6:00500c08 r5:00000004 r4:76eb65e0 Fixes: 1abe729 (ASoC: fsl: Add missing pm to current machine drivers) Cc: stable@vger.kernel.org Signed-off-by: Shawn Guo Signed-off-by: Mark Brown --- sound/soc/fsl/imx-mc13783.c | 1 - sound/soc/fsl/imx-sgtl5000.c | 10 ++++++---- sound/soc/fsl/imx-wm8962.c | 11 +++++++---- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/sound/soc/fsl/imx-mc13783.c b/sound/soc/fsl/imx-mc13783.c index 79cee782dbbf..a2fd7321b5a9 100644 --- a/sound/soc/fsl/imx-mc13783.c +++ b/sound/soc/fsl/imx-mc13783.c @@ -160,7 +160,6 @@ static struct platform_driver imx_mc13783_audio_driver = { .driver = { .name = "imx_mc13783", .owner = THIS_MODULE, - .pm = &snd_soc_pm_ops, }, .probe = imx_mc13783_probe, .remove = imx_mc13783_remove diff --git a/sound/soc/fsl/imx-sgtl5000.c b/sound/soc/fsl/imx-sgtl5000.c index f2beae78969f..1cb22dd034eb 100644 --- a/sound/soc/fsl/imx-sgtl5000.c +++ b/sound/soc/fsl/imx-sgtl5000.c @@ -33,8 +33,7 @@ struct imx_sgtl5000_data { static int imx_sgtl5000_dai_init(struct snd_soc_pcm_runtime *rtd) { - struct imx_sgtl5000_data *data = container_of(rtd->card, - struct imx_sgtl5000_data, card); + struct imx_sgtl5000_data *data = snd_soc_card_get_drvdata(rtd->card); struct device *dev = rtd->card->dev; int ret; @@ -159,13 +158,15 @@ static int imx_sgtl5000_probe(struct platform_device *pdev) data->card.dapm_widgets = imx_sgtl5000_dapm_widgets; data->card.num_dapm_widgets = ARRAY_SIZE(imx_sgtl5000_dapm_widgets); + platform_set_drvdata(pdev, &data->card); + snd_soc_card_set_drvdata(&data->card, data); + ret = devm_snd_soc_register_card(&pdev->dev, &data->card); if (ret) { dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); goto fail; } - platform_set_drvdata(pdev, data); of_node_put(ssi_np); of_node_put(codec_np); @@ -184,7 +185,8 @@ fail: static int imx_sgtl5000_remove(struct platform_device *pdev) { - struct imx_sgtl5000_data *data = platform_get_drvdata(pdev); + struct snd_soc_card *card = platform_get_drvdata(pdev); + struct imx_sgtl5000_data *data = snd_soc_card_get_drvdata(card); clk_put(data->codec_clk); diff --git a/sound/soc/fsl/imx-wm8962.c b/sound/soc/fsl/imx-wm8962.c index 3fd76bc391de..3a3d17ce6ba4 100644 --- a/sound/soc/fsl/imx-wm8962.c +++ b/sound/soc/fsl/imx-wm8962.c @@ -71,7 +71,7 @@ static int imx_wm8962_set_bias_level(struct snd_soc_card *card, { struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; struct imx_priv *priv = &card_priv; - struct imx_wm8962_data *data = platform_get_drvdata(priv->pdev); + struct imx_wm8962_data *data = snd_soc_card_get_drvdata(card); struct device *dev = &priv->pdev->dev; unsigned int pll_out; int ret; @@ -137,7 +137,7 @@ static int imx_wm8962_late_probe(struct snd_soc_card *card) { struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; struct imx_priv *priv = &card_priv; - struct imx_wm8962_data *data = platform_get_drvdata(priv->pdev); + struct imx_wm8962_data *data = snd_soc_card_get_drvdata(card); struct device *dev = &priv->pdev->dev; int ret; @@ -264,13 +264,15 @@ static int imx_wm8962_probe(struct platform_device *pdev) data->card.late_probe = imx_wm8962_late_probe; data->card.set_bias_level = imx_wm8962_set_bias_level; + platform_set_drvdata(pdev, &data->card); + snd_soc_card_set_drvdata(&data->card, data); + ret = devm_snd_soc_register_card(&pdev->dev, &data->card); if (ret) { dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); goto clk_fail; } - platform_set_drvdata(pdev, data); of_node_put(ssi_np); of_node_put(codec_np); @@ -289,7 +291,8 @@ fail: static int imx_wm8962_remove(struct platform_device *pdev) { - struct imx_wm8962_data *data = platform_get_drvdata(pdev); + struct snd_soc_card *card = platform_get_drvdata(pdev); + struct imx_wm8962_data *data = snd_soc_card_get_drvdata(card); if (!IS_ERR(data->codec_clk)) clk_disable_unprepare(data->codec_clk); -- cgit v1.2.3 From 236014ac7a6524f9f466139c2e47af70cb340ba3 Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Mon, 10 Feb 2014 14:47:17 +0800 Subject: ASoC: fsl-esai: fix ESAI TDM slot setting Signed-off-by: Xiubo Li Acked-by: Nicolin Chen Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_esai.c | 4 ++-- sound/soc/fsl/fsl_esai.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index d0c72ed261e7..c84026c99134 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c @@ -326,7 +326,7 @@ static int fsl_esai_set_dai_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask, regmap_update_bits(esai_priv->regmap, REG_ESAI_TSMA, ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(tx_mask)); regmap_update_bits(esai_priv->regmap, REG_ESAI_TSMB, - ESAI_xSMA_xS_MASK, ESAI_xSMB_xS(tx_mask)); + ESAI_xSMB_xS_MASK, ESAI_xSMB_xS(tx_mask)); regmap_update_bits(esai_priv->regmap, REG_ESAI_RCCR, ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(slots)); @@ -334,7 +334,7 @@ static int fsl_esai_set_dai_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask, regmap_update_bits(esai_priv->regmap, REG_ESAI_RSMA, ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(rx_mask)); regmap_update_bits(esai_priv->regmap, REG_ESAI_RSMB, - ESAI_xSMA_xS_MASK, ESAI_xSMB_xS(rx_mask)); + ESAI_xSMB_xS_MASK, ESAI_xSMB_xS(rx_mask)); esai_priv->slot_width = slot_width; diff --git a/sound/soc/fsl/fsl_esai.h b/sound/soc/fsl/fsl_esai.h index 9c9f957fcae1..75e14033e8d8 100644 --- a/sound/soc/fsl/fsl_esai.h +++ b/sound/soc/fsl/fsl_esai.h @@ -322,7 +322,7 @@ #define ESAI_xSMB_xS_SHIFT 0 #define ESAI_xSMB_xS_WIDTH 16 #define ESAI_xSMB_xS_MASK (((1 << ESAI_xSMB_xS_WIDTH) - 1) << ESAI_xSMB_xS_SHIFT) -#define ESAI_xSMB_xS(v) (((v) >> ESAI_xSMA_xS_WIDTH) & ESAI_xSMA_xS_MASK) +#define ESAI_xSMB_xS(v) (((v) >> ESAI_xSMA_xS_WIDTH) & ESAI_xSMB_xS_MASK) /* Port C Direction Register -- REG_ESAI_PRRC 0xF8 */ #define ESAI_PRRC_PDC_SHIFT 0 -- cgit v1.2.3 From 07b0e5b10258b48e5edfb6c8ac156f05510eb775 Mon Sep 17 00:00:00 2001 From: Adam Thomson Date: Thu, 6 Feb 2014 18:03:07 +0000 Subject: ASoC: da9055: Fix device registration of PMIC and CODEC devices Currently the I2C device Ids conflict for the MFD and CODEC so cannot be both instantiated on one platform. This patch updates the Ids and names to make them unique from each other. It should be noted that the I2C addresses for both PMIC and CODEC are modifiable so instantiation of the two are kept as separate devices, rather than instantiating the CODEC from the MFD code. Signed-off-by: Adam Thomson Acked-by: Mark Brown Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- drivers/mfd/da9055-i2c.c | 12 ++++++++++-- sound/soc/codecs/da9055.c | 11 +++++++++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/drivers/mfd/da9055-i2c.c b/drivers/mfd/da9055-i2c.c index 13af7e50021e..8103e4362132 100644 --- a/drivers/mfd/da9055-i2c.c +++ b/drivers/mfd/da9055-i2c.c @@ -53,17 +53,25 @@ static int da9055_i2c_remove(struct i2c_client *i2c) return 0; } +/* + * DO NOT change the device Ids. The naming is intentionally specific as both + * the PMIC and CODEC parts of this chip are instantiated separately as I2C + * devices (both have configurable I2C addresses, and are to all intents and + * purposes separate). As a result there are specific DA9055 ids for PMIC + * and CODEC, which must be different to operate together. + */ static struct i2c_device_id da9055_i2c_id[] = { - {"da9055", 0}, + {"da9055-pmic", 0}, { } }; +MODULE_DEVICE_TABLE(i2c, da9055_i2c_id); static struct i2c_driver da9055_i2c_driver = { .probe = da9055_i2c_probe, .remove = da9055_i2c_remove, .id_table = da9055_i2c_id, .driver = { - .name = "da9055", + .name = "da9055-pmic", .owner = THIS_MODULE, }, }; diff --git a/sound/soc/codecs/da9055.c b/sound/soc/codecs/da9055.c index 52b79a487ac7..422812613a28 100644 --- a/sound/soc/codecs/da9055.c +++ b/sound/soc/codecs/da9055.c @@ -1523,8 +1523,15 @@ static int da9055_remove(struct i2c_client *client) return 0; } +/* + * DO NOT change the device Ids. The naming is intentionally specific as both + * the CODEC and PMIC parts of this chip are instantiated separately as I2C + * devices (both have configurable I2C addresses, and are to all intents and + * purposes separate). As a result there are specific DA9055 Ids for CODEC + * and PMIC, which must be different to operate together. + */ static const struct i2c_device_id da9055_i2c_id[] = { - { "da9055", 0 }, + { "da9055-codec", 0 }, { } }; MODULE_DEVICE_TABLE(i2c, da9055_i2c_id); @@ -1532,7 +1539,7 @@ MODULE_DEVICE_TABLE(i2c, da9055_i2c_id); /* I2C codec control layer */ static struct i2c_driver da9055_i2c_driver = { .driver = { - .name = "da9055", + .name = "da9055-codec", .owner = THIS_MODULE, }, .probe = da9055_i2c_probe, -- cgit v1.2.3 From fd1defc257e2b12ab69bc0b379105c00eca4e112 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Thu, 6 Feb 2014 14:38:53 -0500 Subject: NFS: Do not set NFS_INO_INVALID_LABEL unless server supports labeled NFS Commit aa9c2669626c (NFS: Client implementation of Labeled-NFS) introduces a performance regression. When nfs_zap_caches_locked is called, it sets the NFS_INO_INVALID_LABEL flag irrespectively of whether or not the NFS server supports security labels. Since that flag is never cleared, it means that all calls to nfs_revalidate_inode() will now trigger an on-the-wire GETATTR call. This patch ensures that we never set the NFS_INO_INVALID_LABEL unless the server advertises support for labeled NFS. It also causes nfs_setsecurity() to clear NFS_INO_INVALID_LABEL when it has successfully set the security label for the inode. Finally it gets rid of the NFS_INO_INVALID_LABEL cruft from nfs_update_inode, which has nothing to do with labeled NFS. Reported-by: Neil Brown Cc: stable@vger.kernel.org # 3.11+ Tested-by: Neil Brown Signed-off-by: Trond Myklebust --- fs/nfs/inode.c | 14 ++++++++++---- fs/nfs/internal.h | 9 +++++++++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 28a0a3cbd3b7..360114ae8b82 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -164,17 +164,16 @@ static void nfs_zap_caches_locked(struct inode *inode) if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) { nfs_fscache_invalidate(inode); nfsi->cache_validity |= NFS_INO_INVALID_ATTR - | NFS_INO_INVALID_LABEL | NFS_INO_INVALID_DATA | NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL | NFS_INO_REVAL_PAGECACHE; } else nfsi->cache_validity |= NFS_INO_INVALID_ATTR - | NFS_INO_INVALID_LABEL | NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL | NFS_INO_REVAL_PAGECACHE; + nfs_zap_label_cache_locked(nfsi); } void nfs_zap_caches(struct inode *inode) @@ -266,6 +265,13 @@ nfs_init_locked(struct inode *inode, void *opaque) } #ifdef CONFIG_NFS_V4_SECURITY_LABEL +static void nfs_clear_label_invalid(struct inode *inode) +{ + spin_lock(&inode->i_lock); + NFS_I(inode)->cache_validity &= ~NFS_INO_INVALID_LABEL; + spin_unlock(&inode->i_lock); +} + void nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr, struct nfs4_label *label) { @@ -283,6 +289,7 @@ void nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr, __func__, (char *)label->label, label->len, error); + nfs_clear_label_invalid(inode); } } @@ -1648,7 +1655,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) inode->i_blocks = fattr->du.nfs2.blocks; /* Update attrtimeo value if we're out of the unstable period */ - if (invalid & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_LABEL)) { + if (invalid & NFS_INO_INVALID_ATTR) { nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE); nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); nfsi->attrtimeo_timestamp = now; @@ -1661,7 +1668,6 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) } } invalid &= ~NFS_INO_INVALID_ATTR; - invalid &= ~NFS_INO_INVALID_LABEL; /* Don't invalidate the data if we were to blame */ if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))) diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 8b5cc04a8611..fafdddac8271 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -279,9 +279,18 @@ static inline void nfs4_label_free(struct nfs4_label *label) } return; } + +static inline void nfs_zap_label_cache_locked(struct nfs_inode *nfsi) +{ + if (nfs_server_capable(&nfsi->vfs_inode, NFS_CAP_SECURITY_LABEL)) + nfsi->cache_validity |= NFS_INO_INVALID_LABEL; +} #else static inline struct nfs4_label *nfs4_label_alloc(struct nfs_server *server, gfp_t flags) { return NULL; } static inline void nfs4_label_free(void *label) {} +static inline void nfs_zap_label_cache_locked(struct nfs_inode *nfsi) +{ +} #endif /* CONFIG_NFS_V4_SECURITY_LABEL */ /* proc.c */ -- cgit v1.2.3 From 981a23792cd02631f8cd5dd65753208a44de5ae1 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Wed, 5 Feb 2014 05:18:58 +0000 Subject: perf probe: Do not add offset twice to uprobe address Fix perf-probe not to add offset value twice to uprobe probe address when post processing. The tevs[i].point.address struct member is the address of symbol+offset, but current perf-probe adjusts the point.address by adding the offset. As a result, the probe address becomes symbol+offset+offset. This may cause unexpected code corruption. Urgent fix is needed. Without this fix: --- # ./perf probe -x ./perf dso__load_vmlinux+4 # ./perf probe -l probe_perf:dso__load_vmlinux (on 0x000000000006d2b8) # nm ./perf.orig | grep dso__load_vmlinux\$ 000000000046d0a0 T dso__load_vmlinux --- You can see the given offset is 3 but the actual probed address is dso__load_vmlinux+8. With this fix: --- # ./perf probe -x ./perf dso__load_vmlinux+4 # ./perf probe -l probe_perf:dso__load_vmlinux (on 0x000000000006d2b4) --- Now the problem is fixed. Note: This bug is introduced by commit fb7345bbf7fad9bf72ef63a19c707970b9685812 Signed-off-by: Masami Hiramatsu Cc: "David A. Long" Cc: David Ahern Cc: Ingo Molnar Cc: Namhyung Kim Cc: Oleg Nesterov Cc: Srikar Dronamraju Cc: Steven Rostedt Cc: yrl.pp-manager.tt@hitachi.com Link: http://lkml.kernel.org/r/20140205051858.6519.27314.stgit@kbuild-fedora.yrl.intra.hitachi.co.jp Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/probe-event.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index a8a9b6cd93a8..d8b048c20cde 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -336,8 +336,8 @@ static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs, return ret; for (i = 0; i < ntevs && ret >= 0; i++) { + /* point.address is the addres of point.symbol + point.offset */ offset = tevs[i].point.address - stext; - offset += tevs[i].point.offset; tevs[i].point.offset = 0; zfree(&tevs[i].point.symbol); ret = e_snprintf(buf, 32, "0x%lx", offset); -- cgit v1.2.3 From f67697bd079f4bbcbe7d6d26765a06b18afe0630 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 4 Feb 2014 15:37:48 +0100 Subject: perf tools: Handle PERF_RECORD_HEADER_EVENT_TYPE properly We removed event types from data file in following commits: 6065210 perf tools: Remove event types framework completely 44b3c57 perf tools: Remove event types from perf data file We no longer need this information, because we can get it directly from tracepoints. But we still need to handle PERF_RECORD_HEADER_EVENT_TYPE event for the sake of old perf data files created in pipe mode like: $ perf.3.4 record -o - foo >perf.data $ perf.312 report -i - < perf.data Reported-by: Stephane Eranian Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1391524668-12546-1-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/session.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 0b39a48e5110..5da6ce74c676 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -1008,6 +1008,12 @@ static int perf_session__process_user_event(struct perf_session *session, union if (err == 0) perf_session__set_id_hdr_size(session); return err; + case PERF_RECORD_HEADER_EVENT_TYPE: + /* + * Depreceated, but we need to handle it for sake + * of old data files create in pipe mode. + */ + return 0; case PERF_RECORD_HEADER_TRACING_DATA: /* setup for reading amidst mmap */ lseek(fd, file_offset, SEEK_SET); -- cgit v1.2.3 From 88fee52e58ca14d8465b614774ed0bf08e1a7790 Mon Sep 17 00:00:00 2001 From: Vince Weaver Date: Mon, 30 Dec 2013 15:39:45 -0500 Subject: perf list: Fix checking for supported events on older kernels "perf list" listing of hardware events doesn't work on older ARM devices. The change enabling event detection: commit b41f1cec91c37eeea6fdb15effbfa24ea0a5536b Author: Namhyung Kim Date: Tue Aug 27 11:41:53 2013 +0900 perf list: Skip unsupported events uses the following code in tools/perf/util/parse-events.c: struct perf_event_attr attr = { .type = type, .config = config, .disabled = 1, .exclude_kernel = 1, }; On ARM machines pre-dating the Cortex-A15 this doesn't work, as these machines don't support .exclude_kernel. So starting with 3.12 "perf list" does not report any hardware events at all on older machines (seen on Rasp-Pi, Pandaboard, Beagleboard, etc). This version of the patch makes changes suggested by Namhyung Kim to check for EACCESS and retry (instead of just dropping the exclude_kernel) so we can properly handle machines where /proc/sys/kernel/perf_event_paranoid is set to 2. Reported-by: Chad Paradis Signed-off-by: Vince Weaver Acked-by: Namhyung Kim Cc: Chad Paradis Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/alpine.DEB.2.10.1312301536150.28814@vincent-weaver-1.um.maine.edu Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/parse-events.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index d248fca6d7ed..1e15df10a88c 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -1091,12 +1091,12 @@ int is_valid_tracepoint(const char *event_string) static bool is_event_supported(u8 type, unsigned config) { bool ret = true; + int open_return; struct perf_evsel *evsel; struct perf_event_attr attr = { .type = type, .config = config, .disabled = 1, - .exclude_kernel = 1, }; struct { struct thread_map map; @@ -1108,7 +1108,20 @@ static bool is_event_supported(u8 type, unsigned config) evsel = perf_evsel__new(&attr); if (evsel) { - ret = perf_evsel__open(evsel, NULL, &tmap.map) >= 0; + open_return = perf_evsel__open(evsel, NULL, &tmap.map); + ret = open_return >= 0; + + if (open_return == -EACCES) { + /* + * This happens if the paranoid value + * /proc/sys/kernel/perf_event_paranoid is set to 2 + * Re-run with exclude_kernel set; we don't do that + * by default as some ARM machines do not support it. + * + */ + evsel->attr.exclude_kernel = 1; + ret = perf_evsel__open(evsel, NULL, &tmap.map) >= 0; + } perf_evsel__delete(evsel); } -- cgit v1.2.3 From 79d26a6a19ace19faabf8d8d27d3430be2e26d34 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 6 Feb 2014 01:00:35 +0000 Subject: perf trace: Add fallback definition of EFD_SEMAPHORE glibc 2.17 is missing this on sparc, despite the fact that it's not architecture-specific. Signed-off-by: Ben Hutchings Fixes: 49af9e93adfa ('perf trace: Beautify eventfd2 'flags' arg') Cc: Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Cc: stable@vger.kernel.org Link: http://lkml.kernel.org/r/1391648435.3003.100.camel@deadeye.wl.decadent.org.uk Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 896f27047ed6..619d11c47a91 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -37,6 +37,10 @@ # define MADV_UNMERGEABLE 13 #endif +#ifndef EFD_SEMAPHORE +# define EFD_SEMAPHORE 1 +#endif + struct tp_field { int offset; union { -- cgit v1.2.3 From 97a644208d1a08b7104d1fe2ace8cef011222711 Mon Sep 17 00:00:00 2001 From: Yifan Zhang Date: Fri, 3 Jan 2014 12:01:26 +0000 Subject: iommu/arm-smmu: fix pud/pmd entry fill sequence The ARM SMMU driver's population of puds and pmds is broken, since we iterate over the next level of table repeatedly setting the current level descriptor to point at the pmd being initialised. This is clearly wrong when dealing with multiple pmds/puds. This patch fixes the problem by moving the pud/pmd population out of the loop and instead performing it when we allocate the next level (like we correctly do for ptes already). The starting address for the next level is then calculated prior to entering the loop. Cc: Signed-off-by: Yifan Zhang Signed-off-by: Will Deacon --- drivers/iommu/arm-smmu.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 8911850c9444..9f210de6537e 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -1320,6 +1320,11 @@ static int arm_smmu_alloc_init_pmd(struct arm_smmu_device *smmu, pud_t *pud, pmd = pmd_alloc_one(NULL, addr); if (!pmd) return -ENOMEM; + + pud_populate(NULL, pud, pmd); + arm_smmu_flush_pgtable(smmu, pud, sizeof(*pud)); + + pmd += pmd_index(addr); } else #endif pmd = pmd_offset(pud, addr); @@ -1328,8 +1333,6 @@ static int arm_smmu_alloc_init_pmd(struct arm_smmu_device *smmu, pud_t *pud, next = pmd_addr_end(addr, end); ret = arm_smmu_alloc_init_pte(smmu, pmd, addr, end, pfn, flags, stage); - pud_populate(NULL, pud, pmd); - arm_smmu_flush_pgtable(smmu, pud, sizeof(*pud)); phys += next - addr; } while (pmd++, addr = next, addr < end); @@ -1349,6 +1352,11 @@ static int arm_smmu_alloc_init_pud(struct arm_smmu_device *smmu, pgd_t *pgd, pud = pud_alloc_one(NULL, addr); if (!pud) return -ENOMEM; + + pgd_populate(NULL, pgd, pud); + arm_smmu_flush_pgtable(smmu, pgd, sizeof(*pgd)); + + pud += pud_index(addr); } else #endif pud = pud_offset(pgd, addr); @@ -1357,8 +1365,6 @@ static int arm_smmu_alloc_init_pud(struct arm_smmu_device *smmu, pgd_t *pgd, next = pud_addr_end(addr, end); ret = arm_smmu_alloc_init_pmd(smmu, pud, addr, next, phys, flags, stage); - pgd_populate(NULL, pud, pgd); - arm_smmu_flush_pgtable(smmu, pgd, sizeof(*pgd)); phys += next - addr; } while (pud++, addr = next, addr < end); -- cgit v1.2.3 From c9d09e2748eaa55cac2af274574baa6368189bc1 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 4 Feb 2014 22:12:42 +0000 Subject: iommu/arm-smmu: really fix page table locking Commit a44a9791e778 ("iommu/arm-smmu: use mutex instead of spinlock for locking page tables") replaced the page table spinlock with a mutex, to allow blocking allocations to satisfy lazy mapping requests. Unfortunately, it turns out that IOMMU mappings are created from atomic context (e.g. spinlock held during a dma_map), so this change doesn't really help us in practice. This patch is a partial revert of the offending commit, bringing back the original spinlock but replacing our page table allocations for any levels below the pgd (which is allocated during domain init) with GFP_ATOMIC instead of GFP_KERNEL. Cc: Reported-by: Andreas Herrmann Signed-off-by: Will Deacon --- drivers/iommu/arm-smmu.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 9f210de6537e..6eb54ae97470 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -393,7 +393,7 @@ struct arm_smmu_domain { struct arm_smmu_cfg root_cfg; phys_addr_t output_mask; - struct mutex lock; + spinlock_t lock; }; static DEFINE_SPINLOCK(arm_smmu_devices_lock); @@ -901,7 +901,7 @@ static int arm_smmu_domain_init(struct iommu_domain *domain) goto out_free_domain; smmu_domain->root_cfg.pgd = pgd; - mutex_init(&smmu_domain->lock); + spin_lock_init(&smmu_domain->lock); domain->priv = smmu_domain; return 0; @@ -1138,7 +1138,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) * Sanity check the domain. We don't currently support domains * that cross between different SMMU chains. */ - mutex_lock(&smmu_domain->lock); + spin_lock(&smmu_domain->lock); if (!smmu_domain->leaf_smmu) { /* Now that we have a master, we can finalise the domain */ ret = arm_smmu_init_domain_context(domain, dev); @@ -1153,7 +1153,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) dev_name(device_smmu->dev)); goto err_unlock; } - mutex_unlock(&smmu_domain->lock); + spin_unlock(&smmu_domain->lock); /* Looks ok, so add the device to the domain */ master = find_smmu_master(smmu_domain->leaf_smmu, dev->of_node); @@ -1163,7 +1163,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) return arm_smmu_domain_add_master(smmu_domain, master); err_unlock: - mutex_unlock(&smmu_domain->lock); + spin_unlock(&smmu_domain->lock); return ret; } @@ -1210,7 +1210,7 @@ static int arm_smmu_alloc_init_pte(struct arm_smmu_device *smmu, pmd_t *pmd, if (pmd_none(*pmd)) { /* Allocate a new set of tables */ - pgtable_t table = alloc_page(PGALLOC_GFP); + pgtable_t table = alloc_page(GFP_ATOMIC|__GFP_ZERO); if (!table) return -ENOMEM; @@ -1317,7 +1317,7 @@ static int arm_smmu_alloc_init_pmd(struct arm_smmu_device *smmu, pud_t *pud, #ifndef __PAGETABLE_PMD_FOLDED if (pud_none(*pud)) { - pmd = pmd_alloc_one(NULL, addr); + pmd = (pmd_t *)get_zeroed_page(GFP_ATOMIC); if (!pmd) return -ENOMEM; @@ -1349,7 +1349,7 @@ static int arm_smmu_alloc_init_pud(struct arm_smmu_device *smmu, pgd_t *pgd, #ifndef __PAGETABLE_PUD_FOLDED if (pgd_none(*pgd)) { - pud = pud_alloc_one(NULL, addr); + pud = (pud_t *)get_zeroed_page(GFP_ATOMIC); if (!pud) return -ENOMEM; @@ -1403,7 +1403,7 @@ static int arm_smmu_handle_mapping(struct arm_smmu_domain *smmu_domain, if (paddr & ~output_mask) return -ERANGE; - mutex_lock(&smmu_domain->lock); + spin_lock(&smmu_domain->lock); pgd += pgd_index(iova); end = iova + size; do { @@ -1419,7 +1419,7 @@ static int arm_smmu_handle_mapping(struct arm_smmu_domain *smmu_domain, } while (pgd++, iova != end); out_unlock: - mutex_unlock(&smmu_domain->lock); + spin_unlock(&smmu_domain->lock); /* Ensure new page tables are visible to the hardware walker */ if (smmu->features & ARM_SMMU_FEAT_COHERENT_WALK) -- cgit v1.2.3 From 6dd35f45b8dac827b6f9dd86f5aca6436cdd2410 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Wed, 5 Feb 2014 17:49:34 +0000 Subject: iommu/arm-smmu: fix table flushing during initial allocations Now that we populate page tables as we traverse them ("iommu/arm-smmu: fix pud/pmd entry fill sequence"), we need to ensure that we flush out our zeroed tables after initial allocation, to prevent speculative TLB fills using bogus data. This patch adds additional calls to arm_smmu_flush_pgtable during initial table allocation, and moves the dsb required by coherent table walkers into the helper. Cc: Signed-off-by: Will Deacon --- drivers/iommu/arm-smmu.c | 51 +++++++++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 6eb54ae97470..509f01f054d9 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -79,7 +79,6 @@ #define ARM_SMMU_PTE_CONT_SIZE (PAGE_SIZE * ARM_SMMU_PTE_CONT_ENTRIES) #define ARM_SMMU_PTE_CONT_MASK (~(ARM_SMMU_PTE_CONT_SIZE - 1)) -#define ARM_SMMU_PTE_HWTABLE_SIZE (PTRS_PER_PTE * sizeof(pte_t)) /* Stage-1 PTE */ #define ARM_SMMU_PTE_AP_UNPRIV (((pteval_t)1) << 6) @@ -632,6 +631,28 @@ static irqreturn_t arm_smmu_global_fault(int irq, void *dev) return IRQ_HANDLED; } +static void arm_smmu_flush_pgtable(struct arm_smmu_device *smmu, void *addr, + size_t size) +{ + unsigned long offset = (unsigned long)addr & ~PAGE_MASK; + + + /* Ensure new page tables are visible to the hardware walker */ + if (smmu->features & ARM_SMMU_FEAT_COHERENT_WALK) { + dsb(); + } else { + /* + * If the SMMU can't walk tables in the CPU caches, treat them + * like non-coherent DMA since we need to flush the new entries + * all the way out to memory. There's no possibility of + * recursion here as the SMMU table walker will not be wired + * through another SMMU. + */ + dma_map_page(smmu->dev, virt_to_page(addr), offset, size, + DMA_TO_DEVICE); + } +} + static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain) { u32 reg; @@ -715,6 +736,8 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain) } /* TTBR0 */ + arm_smmu_flush_pgtable(smmu, root_cfg->pgd, + PTRS_PER_PGD * sizeof(pgd_t)); reg = __pa(root_cfg->pgd); writel_relaxed(reg, cb_base + ARM_SMMU_CB_TTBR0_LO); reg = (phys_addr_t)__pa(root_cfg->pgd) >> 32; @@ -1177,23 +1200,6 @@ static void arm_smmu_detach_dev(struct iommu_domain *domain, struct device *dev) arm_smmu_domain_remove_master(smmu_domain, master); } -static void arm_smmu_flush_pgtable(struct arm_smmu_device *smmu, void *addr, - size_t size) -{ - unsigned long offset = (unsigned long)addr & ~PAGE_MASK; - - /* - * If the SMMU can't walk tables in the CPU caches, treat them - * like non-coherent DMA since we need to flush the new entries - * all the way out to memory. There's no possibility of recursion - * here as the SMMU table walker will not be wired through another - * SMMU. - */ - if (!(smmu->features & ARM_SMMU_FEAT_COHERENT_WALK)) - dma_map_page(smmu->dev, virt_to_page(addr), offset, size, - DMA_TO_DEVICE); -} - static bool arm_smmu_pte_is_contiguous_range(unsigned long addr, unsigned long end) { @@ -1214,8 +1220,7 @@ static int arm_smmu_alloc_init_pte(struct arm_smmu_device *smmu, pmd_t *pmd, if (!table) return -ENOMEM; - arm_smmu_flush_pgtable(smmu, page_address(table), - ARM_SMMU_PTE_HWTABLE_SIZE); + arm_smmu_flush_pgtable(smmu, page_address(table), PAGE_SIZE); if (!pgtable_page_ctor(table)) { __free_page(table); return -ENOMEM; @@ -1321,6 +1326,7 @@ static int arm_smmu_alloc_init_pmd(struct arm_smmu_device *smmu, pud_t *pud, if (!pmd) return -ENOMEM; + arm_smmu_flush_pgtable(smmu, pmd, PAGE_SIZE); pud_populate(NULL, pud, pmd); arm_smmu_flush_pgtable(smmu, pud, sizeof(*pud)); @@ -1353,6 +1359,7 @@ static int arm_smmu_alloc_init_pud(struct arm_smmu_device *smmu, pgd_t *pgd, if (!pud) return -ENOMEM; + arm_smmu_flush_pgtable(smmu, pud, PAGE_SIZE); pgd_populate(NULL, pgd, pud); arm_smmu_flush_pgtable(smmu, pgd, sizeof(*pgd)); @@ -1421,10 +1428,6 @@ static int arm_smmu_handle_mapping(struct arm_smmu_domain *smmu_domain, out_unlock: spin_unlock(&smmu_domain->lock); - /* Ensure new page tables are visible to the hardware walker */ - if (smmu->features & ARM_SMMU_FEAT_COHERENT_WALK) - dsb(); - return ret; } -- cgit v1.2.3 From 57ca90f6800987ac274d7ba065ae6692cdf9bcd7 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Thu, 6 Feb 2014 14:59:05 +0000 Subject: iommu/arm-smmu: set CBARn.BPSHCFG to NSH for s1-s2-bypass contexts Whilst trying to bring-up an SMMUv2 implementation with the table walker plumbed into a coherent interconnect, I noticed that the memory transactions targetting the CPU caches from the SMMU were marked as outer-shareable instead of inner-shareable. After a bunch of digging, it seems that we actually need to program CBARn.BPSHCFG for s1-s2-bypass contexts to act as non-shareable in order for the shareability configured in the corresponding TTBCR not to be overridden with an outer-shareable attribute. Cc: Signed-off-by: Will Deacon --- drivers/iommu/arm-smmu.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 509f01f054d9..0ae4dd39197f 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -190,6 +190,9 @@ #define ARM_SMMU_GR1_CBAR(n) (0x0 + ((n) << 2)) #define CBAR_VMID_SHIFT 0 #define CBAR_VMID_MASK 0xff +#define CBAR_S1_BPSHCFG_SHIFT 8 +#define CBAR_S1_BPSHCFG_MASK 3 +#define CBAR_S1_BPSHCFG_NSH 3 #define CBAR_S1_MEMATTR_SHIFT 12 #define CBAR_S1_MEMATTR_MASK 0xf #define CBAR_S1_MEMATTR_WB 0xf @@ -671,11 +674,16 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain) if (smmu->version == 1) reg |= root_cfg->irptndx << CBAR_IRPTNDX_SHIFT; - /* Use the weakest memory type, so it is overridden by the pte */ - if (stage1) - reg |= (CBAR_S1_MEMATTR_WB << CBAR_S1_MEMATTR_SHIFT); - else + /* + * Use the weakest shareability/memory types, so they are + * overridden by the ttbcr/pte. + */ + if (stage1) { + reg |= (CBAR_S1_BPSHCFG_NSH << CBAR_S1_BPSHCFG_SHIFT) | + (CBAR_S1_MEMATTR_WB << CBAR_S1_MEMATTR_SHIFT); + } else { reg |= ARM_SMMU_CB_VMID(root_cfg) << CBAR_VMID_SHIFT; + } writel_relaxed(reg, gr1_base + ARM_SMMU_GR1_CBAR(root_cfg->cbndx)); if (smmu->version > 1) { -- cgit v1.2.3 From d123cf82d339c5cc4ffe2a481e0caa23a501d4ac Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 4 Feb 2014 22:17:53 +0000 Subject: iommu/arm-smmu: fix compilation issue when !CONFIG_ARM_AMBA If !CONFIG_ARM_AMBA, we shouldn't try to register ourselves with the amba_bustype. Signed-off-by: Will Deacon --- drivers/iommu/arm-smmu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 0ae4dd39197f..6fe7922ecc1d 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -2004,8 +2004,10 @@ static int __init arm_smmu_init(void) if (!iommu_present(&platform_bus_type)) bus_set_iommu(&platform_bus_type, &arm_smmu_ops); +#ifdef CONFIG_ARM_AMBA if (!iommu_present(&amba_bustype)) bus_set_iommu(&amba_bustype, &arm_smmu_ops); +#endif return 0; } -- cgit v1.2.3 From 42eacf9e57b65ffa768af72cb7fc86cc6f6af042 Mon Sep 17 00:00:00 2001 From: Steve French Date: Mon, 10 Feb 2014 14:08:16 -0600 Subject: [CIFS] Fix cifsacl mounts over smb2 to not call cifs When mounting with smb2/smb3 (e.g. vers=2.1) and cifsacl mount option, it was trying to get the mode by querying the acl over the cifs rather than smb2 protocol. This patch makes that protocol independent and makes cifsacl smb2 mounts return a more intuitive operation not supported error (until we add a worker function for smb2_get_acl). Note that a previous patch fixed getxattr/setxattr for the CIFSACL xattr which would unconditionally call cifs_get_acl and cifs_set_acl (even when mounted smb2). I made those protocol independent last week (new protocol version operations "get_acl" and "set_acl" but did not add an smb2_get_acl and smb2_set_acl yet so those now simply return EOPNOTSUPP which at least is better than sending cifs requests on smb2 mount) The previous patches did not fix the one remaining case though ie mounting with "cifsacl" when getting mode from acl would unconditionally end up calling "cifs_get_acl_from_fid" even for smb2 - so made that protocol independent but to make that protocol independent had to make sure that the callers were passing the protocol independent handle structure (cifs_fid) instead of cifs specific _u16 network file handle (ie cifs_fid instead of cifs_fid->fid) Now mount with smb2 and cifsacl mount options will return EOPNOTSUP (instead of timing out) and a future patch will add smb2 operations (e.g. get_smb2_acl) to enable this. Signed-off-by: Steve French --- fs/cifs/cifsacl.c | 33 ++++++++++++++++++++++++--------- fs/cifs/cifsglob.h | 2 ++ fs/cifs/cifsproto.h | 6 ++++-- fs/cifs/dir.c | 2 +- fs/cifs/file.c | 2 +- fs/cifs/inode.c | 2 +- fs/cifs/smb1ops.c | 1 + 7 files changed, 34 insertions(+), 14 deletions(-) diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index c819b0bd491a..7ff866dbb89e 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c @@ -865,8 +865,8 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd, return rc; } -static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb, - __u16 fid, u32 *pacllen) +struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb, + const struct cifs_fid *cifsfid, u32 *pacllen) { struct cifs_ntsd *pntsd = NULL; unsigned int xid; @@ -877,7 +877,8 @@ static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb, return ERR_CAST(tlink); xid = get_xid(); - rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), fid, &pntsd, pacllen); + rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), cifsfid->netfid, &pntsd, + pacllen); free_xid(xid); cifs_put_tlink(tlink); @@ -946,7 +947,7 @@ struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb, if (!open_file) return get_cifs_acl_by_path(cifs_sb, path, pacllen); - pntsd = get_cifs_acl_by_fid(cifs_sb, open_file->fid.netfid, pacllen); + pntsd = get_cifs_acl_by_fid(cifs_sb, &open_file->fid, pacllen); cifsFileInfo_put(open_file); return pntsd; } @@ -1006,19 +1007,31 @@ out: /* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */ int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, - struct inode *inode, const char *path, const __u16 *pfid) + struct inode *inode, const char *path, + const struct cifs_fid *pfid) { struct cifs_ntsd *pntsd = NULL; u32 acllen = 0; int rc = 0; + struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); + struct cifs_tcon *tcon; cifs_dbg(NOISY, "converting ACL to mode for %s\n", path); - if (pfid) - pntsd = get_cifs_acl_by_fid(cifs_sb, *pfid, &acllen); - else - pntsd = get_cifs_acl(cifs_sb, inode, path, &acllen); + if (IS_ERR(tlink)) + return PTR_ERR(tlink); + tcon = tlink_tcon(tlink); + if (pfid && (tcon->ses->server->ops->get_acl_by_fid)) + pntsd = tcon->ses->server->ops->get_acl_by_fid(cifs_sb, pfid, + &acllen); + else if (tcon->ses->server->ops->get_acl) + pntsd = tcon->ses->server->ops->get_acl(cifs_sb, inode, path, + &acllen); + else { + cifs_put_tlink(tlink); + return -EOPNOTSUPP; + } /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */ if (IS_ERR(pntsd)) { rc = PTR_ERR(pntsd); @@ -1030,6 +1043,8 @@ cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, cifs_dbg(VFS, "parse sec desc failed rc = %d\n", rc); } + cifs_put_tlink(tlink); + return rc; } diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 86dc28c7aa5c..cf32f0393369 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -398,6 +398,8 @@ struct smb_version_operations { const struct nls_table *, int); struct cifs_ntsd * (*get_acl)(struct cifs_sb_info *, struct inode *, const char *, u32 *); + struct cifs_ntsd * (*get_acl_by_fid)(struct cifs_sb_info *, + const struct cifs_fid *, u32 *); int (*set_acl)(struct cifs_ntsd *, __u32, struct inode *, const char *, int); }; diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index d00e09dfc452..acc4ee8ed075 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -151,7 +151,7 @@ extern struct inode *cifs_iget(struct super_block *sb, extern int cifs_get_inode_info(struct inode **inode, const char *full_path, FILE_ALL_INFO *data, struct super_block *sb, - int xid, const __u16 *fid); + int xid, const struct cifs_fid *fid); extern int cifs_get_inode_info_unix(struct inode **pinode, const unsigned char *search_path, struct super_block *sb, unsigned int xid); @@ -162,11 +162,13 @@ extern int cifs_rename_pending_delete(const char *full_path, const unsigned int xid); extern int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, struct inode *inode, - const char *path, const __u16 *pfid); + const char *path, const struct cifs_fid *pfid); extern int id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64, kuid_t, kgid_t); extern struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *, struct inode *, const char *, u32 *); +extern struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *, + const struct cifs_fid *, u32 *); extern int set_cifs_acl(struct cifs_ntsd *, __u32, struct inode *, const char *, int); diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index d3a6796caa5a..3db0c5fd9a11 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -378,7 +378,7 @@ cifs_create_get_file_info: xid); else { rc = cifs_get_inode_info(&newinode, full_path, buf, inode->i_sb, - xid, &fid->netfid); + xid, fid); if (newinode) { if (server->ops->set_lease_key) server->ops->set_lease_key(newinode, fid); diff --git a/fs/cifs/file.c b/fs/cifs/file.c index a301edbdad4a..290b4966004f 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -244,7 +244,7 @@ cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb, xid); else rc = cifs_get_inode_info(&inode, full_path, buf, inode->i_sb, - xid, &fid->netfid); + xid, fid); out: kfree(buf); diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index be58b8fcdb3c..aadc2b68678b 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -677,7 +677,7 @@ cgfi_exit: int cifs_get_inode_info(struct inode **inode, const char *full_path, FILE_ALL_INFO *data, struct super_block *sb, int xid, - const __u16 *fid) + const struct cifs_fid *fid) { bool validinum = false; __u16 srchflgs; diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c index bfd66d84831e..526fb89f9230 100644 --- a/fs/cifs/smb1ops.c +++ b/fs/cifs/smb1ops.c @@ -1073,6 +1073,7 @@ struct smb_version_operations smb1_operations = { #endif /* CIFS_XATTR */ #ifdef CONFIG_CIFS_ACL .get_acl = get_cifs_acl, + .get_acl_by_fid = get_cifs_acl_by_fid, .set_acl = set_cifs_acl, #endif /* CIFS_ACL */ }; -- cgit v1.2.3 From a699d65ec4ff82245d2c4fdfb8ed1d64776d756e Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Mon, 10 Feb 2014 16:28:52 -0500 Subject: SUNRPC: Don't create a gss auth cache unless rpc.gssd is running An infinite loop is caused when nfs4_establish_lease() fails with -EACCES. This causes nfs4_handle_reclaim_lease_error() to sleep a bit and resets the NFS4CLNT_LEASE_EXPIRED bit. This in turn causes nfs4_state_manager() to try and reestablished the lease, again, again, again... The problem is a valid RPCSEC_GSS client is being created when rpc.gssd is not running. Link: http://lkml.kernel.org/r/1392066375-16502-1-git-send-email-steved@redhat.com Fixes: 0ea9de0ea6a4 (sunrpc: turn warn_gssd() log message into a dprintk()) Reported-by: Steve Dickson Signed-off-by: Trond Myklebust --- net/sunrpc/auth_gss/auth_gss.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 6c0513a7f992..44a61e8fda6f 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -991,6 +991,8 @@ gss_create_new(struct rpc_auth_create_args *args, struct rpc_clnt *clnt) gss_auth->service = gss_pseudoflavor_to_service(gss_auth->mech, flavor); if (gss_auth->service == 0) goto err_put_mech; + if (!gssd_running(gss_auth->net)) + goto err_put_mech; auth = &gss_auth->rpc_auth; auth->au_cslack = GSS_CRED_SLACK >> 2; auth->au_rslack = GSS_VERF_SLACK >> 2; -- cgit v1.2.3 From 902e6a0c7eba08ec978cea8304c6cb2ddce7b9dc Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 20 Dec 2013 10:46:52 +0100 Subject: ARM: pxa: Add dummy backlight power supply on Mitac Mio A701 Recent changes to the pwm-backlight driver have made the power supply mandatory. There is code in the regulator core to deal with situations where no regulator is specified and provide a dummy, but that works on DT-based boards only. The situation can be remedied by adding a dummy regulator during board initialization. Tested-by: Robert Jarzmik Signed-off-by: Thierry Reding Signed-off-by: Haojian Zhuang --- arch/arm/mach-pxa/mioa701.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm/mach-pxa/mioa701.c b/arch/arm/mach-pxa/mioa701.c index f70583fee59f..29997bde277d 100644 --- a/arch/arm/mach-pxa/mioa701.c +++ b/arch/arm/mach-pxa/mioa701.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -714,6 +715,10 @@ static struct gpio global_gpios[] = { { GPIO56_MT9M111_nOE, GPIOF_OUT_INIT_LOW, "Camera nOE" }, }; +static struct regulator_consumer_supply fixed_5v0_consumers[] = { + REGULATOR_SUPPLY("power", "pwm-backlight"), +}; + static void __init mioa701_machine_init(void) { int rc; @@ -753,6 +758,10 @@ static void __init mioa701_machine_init(void) pxa_set_i2c_info(&i2c_pdata); pxa27x_set_i2c_power_info(NULL); pxa_set_camera_info(&mioa701_pxacamera_platform_data); + + regulator_register_always_on(0, "fixed-5.0V", fixed_5v0_consumers, + ARRAY_SIZE(fixed_5v0_consumers), + 5000000); } static void mioa701_machine_exit(void) -- cgit v1.2.3 From 10c8562f932d89c030083e15f9279971ed637136 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Thu, 16 Jan 2014 15:39:17 +0100 Subject: ARM: dma-mapping: fix GFP_ATOMIC macro usage GFP_ATOMIC is not a single gfp flag, but a macro which expands to the other flags and LACK of __GFP_WAIT flag. To check if caller wanted to perform an atomic allocation, the code must test __GFP_WAIT flag presence. This patch fixes the issue introduced in v3.6-rc5 Signed-off-by: Marek Szyprowski CC: stable@vger.kernel.org --- arch/arm/mm/dma-mapping.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 1a77450e728a..11b3914660d2 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -1358,7 +1358,7 @@ static void *arm_iommu_alloc_attrs(struct device *dev, size_t size, *handle = DMA_ERROR_CODE; size = PAGE_ALIGN(size); - if (gfp & GFP_ATOMIC) + if (!(gfp & __GFP_WAIT)) return __iommu_alloc_atomic(dev, size, handle); /* -- cgit v1.2.3 From c091c71ad2218fc50a07b3d1dab85783f3b77efd Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Fri, 24 Jan 2014 14:49:58 +0100 Subject: x86: dma-mapping: fix GFP_ATOMIC macro usage GFP_ATOMIC is not a single gfp flag, but a macro which expands to the other flags, where meaningful is the LACK of __GFP_WAIT flag. To check if caller wants to perform an atomic allocation, the code must test for a lack of the __GFP_WAIT flag. This patch fixes the issue introduced in v3.5-rc1. CC: stable@vger.kernel.org Signed-off-by: Marek Szyprowski --- arch/x86/kernel/pci-dma.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index 872079a67e4d..f7d0672481fd 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c @@ -100,8 +100,10 @@ void *dma_generic_alloc_coherent(struct device *dev, size_t size, flag |= __GFP_ZERO; again: page = NULL; - if (!(flag & GFP_ATOMIC)) + /* CMA can be used only in the context which permits sleeping */ + if (flag & __GFP_WAIT) page = dma_alloc_from_contiguous(dev, count, get_order(size)); + /* fallback */ if (!page) page = alloc_pages_node(dev_to_node(dev), flag, get_order(size)); if (!page) -- cgit v1.2.3 From 06ea0bfe6e6043cb56a78935a19f6f8ebc636226 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 11 Feb 2014 09:15:54 -0500 Subject: SUNRPC: Fix races in xs_nospace() When a send failure occurs due to the socket being out of buffer space, we call xs_nospace() in order to have the RPC task wait until the socket has drained enough to make it worth while trying again. The current patch fixes a race in which the socket is drained before we get round to setting up the machinery in xs_nospace(), and which is reported to cause hangs. Link: http://lkml.kernel.org/r/20140210170315.33dfc621@notabene.brown Fixes: a9a6b52ee1ba (SUNRPC: Don't start the retransmission timer...) Reported-by: Neil Brown Cc: stable@vger.kernel.org Signed-off-by: Trond Myklebust --- net/sunrpc/xprtsock.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 817a1e523969..0addefca8e77 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -510,6 +510,7 @@ static int xs_nospace(struct rpc_task *task) struct rpc_rqst *req = task->tk_rqstp; struct rpc_xprt *xprt = req->rq_xprt; struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); + struct sock *sk = transport->inet; int ret = -EAGAIN; dprintk("RPC: %5u xmit incomplete (%u left of %u)\n", @@ -527,7 +528,7 @@ static int xs_nospace(struct rpc_task *task) * window size */ set_bit(SOCK_NOSPACE, &transport->sock->flags); - transport->inet->sk_write_pending++; + sk->sk_write_pending++; /* ...and wait for more buffer space */ xprt_wait_for_buffer_space(task, xs_nospace_callback); } @@ -537,6 +538,9 @@ static int xs_nospace(struct rpc_task *task) } spin_unlock_bh(&xprt->transport_lock); + + /* Race breaker in case memory is freed before above code is called */ + sk->sk_write_space(sk); return ret; } -- cgit v1.2.3 From 0ab02ca8f887908152d1a96db5130fc661d36a1e Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Tue, 11 Feb 2014 16:05:46 +0800 Subject: cgroup: protect modifications to cgroup_idr with cgroup_mutex Setup cgroupfs like this: # mount -t cgroup -o cpuacct xxx /cgroup # mkdir /cgroup/sub1 # mkdir /cgroup/sub2 Then run these two commands: # for ((; ;)) { mkdir /cgroup/sub1/tmp && rmdir /mnt/sub1/tmp; } & # for ((; ;)) { mkdir /cgroup/sub2/tmp && rmdir /mnt/sub2/tmp; } & After seconds you may see this warning: ------------[ cut here ]------------ WARNING: CPU: 1 PID: 25243 at lib/idr.c:527 sub_remove+0x87/0x1b0() idr_remove called for id=6 which is not allocated. ... Call Trace: [] dump_stack+0x7a/0x96 [] warn_slowpath_common+0x8c/0xc0 [] warn_slowpath_fmt+0x46/0x50 [] sub_remove+0x87/0x1b0 [] ? css_killed_work_fn+0x32/0x1b0 [] idr_remove+0x25/0xd0 [] cgroup_destroy_css_killed+0x5b/0xc0 [] css_killed_work_fn+0x130/0x1b0 [] process_one_work+0x26c/0x550 [] worker_thread+0x12e/0x3b0 [] kthread+0xe6/0xf0 [] ret_from_fork+0x7c/0xb0 ---[ end trace 2d1577ec10cf80d0 ]--- It's because allocating/removing cgroup ID is not properly synchronized. The bug was introduced when we converted cgroup_ida to cgroup_idr. While synchronization is already done inside ida_simple_{get,remove}(), users are responsible for concurrent calls to idr_{alloc,remove}(). tj: Refreshed on top of b58c89986a77 ("cgroup: fix error return from cgroup_create()"). Fixes: 4e96ee8e981b ("cgroup: convert cgroup_ida to cgroup_idr") Cc: #3.12+ Reported-by: Michal Hocko Signed-off-by: Li Zefan Signed-off-by: Tejun Heo --- include/linux/cgroup.h | 2 ++ kernel/cgroup.c | 34 ++++++++++++++++++---------------- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index 5c097596104b..9450f025fe0c 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h @@ -166,6 +166,8 @@ struct cgroup { * * The ID of the root cgroup is always 0, and a new cgroup * will be assigned with a smallest available ID. + * + * Allocating/Removing ID must be protected by cgroup_mutex. */ int id; diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 3edf7163b84f..52719ce55dd3 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -886,7 +886,9 @@ static void cgroup_diput(struct dentry *dentry, struct inode *inode) * per-subsystem and moved to css->id so that lookups are * successful until the target css is released. */ + mutex_lock(&cgroup_mutex); idr_remove(&cgrp->root->cgroup_idr, cgrp->id); + mutex_unlock(&cgroup_mutex); cgrp->id = -1; call_rcu(&cgrp->rcu_head, cgroup_free_rcu); @@ -4167,16 +4169,6 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry, } rcu_assign_pointer(cgrp->name, name); - /* - * Temporarily set the pointer to NULL, so idr_find() won't return - * a half-baked cgroup. - */ - cgrp->id = idr_alloc(&root->cgroup_idr, NULL, 1, 0, GFP_KERNEL); - if (cgrp->id < 0) { - err = -ENOMEM; - goto err_free_name; - } - /* * Only live parents can have children. Note that the liveliness * check isn't strictly necessary because cgroup_mkdir() and @@ -4186,7 +4178,17 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry, */ if (!cgroup_lock_live_group(parent)) { err = -ENODEV; - goto err_free_id; + goto err_free_name; + } + + /* + * Temporarily set the pointer to NULL, so idr_find() won't return + * a half-baked cgroup. + */ + cgrp->id = idr_alloc(&root->cgroup_idr, NULL, 1, 0, GFP_KERNEL); + if (cgrp->id < 0) { + err = -ENOMEM; + goto err_unlock; } /* Grab a reference on the superblock so the hierarchy doesn't @@ -4218,7 +4220,7 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry, */ err = cgroup_create_file(dentry, S_IFDIR | mode, sb); if (err < 0) - goto err_unlock; + goto err_free_id; lockdep_assert_held(&dentry->d_inode->i_mutex); cgrp->serial_nr = cgroup_serial_nr_next++; @@ -4254,12 +4256,12 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry, return 0; -err_unlock: - mutex_unlock(&cgroup_mutex); - /* Release the reference count that we took on the superblock */ - deactivate_super(sb); err_free_id: idr_remove(&root->cgroup_idr, cgrp->id); + /* Release the reference count that we took on the superblock */ + deactivate_super(sb); +err_unlock: + mutex_unlock(&cgroup_mutex); err_free_name: kfree(rcu_dereference_raw(cgrp->name)); err_free_cgrp: -- cgit v1.2.3 From 628356791b04ea988fee070f66a748a823d001bb Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 11 Feb 2014 13:56:54 -0500 Subject: SUNRPC: Fix potential memory scribble in xprt_free_bc_request() The call to xprt_free_allocation() will call list_del() on req->rq_bc_pa_list, which is not attached to a list. This patch moves the list_del() out of xprt_free_allocation() and into those callers that need it. Signed-off-by: Trond Myklebust --- net/sunrpc/backchannel_rqst.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/sunrpc/backchannel_rqst.c b/net/sunrpc/backchannel_rqst.c index 890a29912d5a..e860d4f7ed2a 100644 --- a/net/sunrpc/backchannel_rqst.c +++ b/net/sunrpc/backchannel_rqst.c @@ -64,7 +64,6 @@ static void xprt_free_allocation(struct rpc_rqst *req) free_page((unsigned long)xbufp->head[0].iov_base); xbufp = &req->rq_snd_buf; free_page((unsigned long)xbufp->head[0].iov_base); - list_del(&req->rq_bc_pa_list); kfree(req); } @@ -168,8 +167,10 @@ out_free: /* * Memory allocation failed, free the temporary list */ - list_for_each_entry_safe(req, tmp, &tmp_list, rq_bc_pa_list) + list_for_each_entry_safe(req, tmp, &tmp_list, rq_bc_pa_list) { + list_del(&req->rq_bc_pa_list); xprt_free_allocation(req); + } dprintk("RPC: setup backchannel transport failed\n"); return -ENOMEM; @@ -198,6 +199,7 @@ void xprt_destroy_backchannel(struct rpc_xprt *xprt, unsigned int max_reqs) xprt_dec_alloc_count(xprt, max_reqs); list_for_each_entry_safe(req, tmp, &xprt->bc_pa_list, rq_bc_pa_list) { dprintk("RPC: req=%p\n", req); + list_del(&req->rq_bc_pa_list); xprt_free_allocation(req); if (--max_reqs == 0) break; -- cgit v1.2.3 From 753b1ad4a281b0663329409d410243e91825c323 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 11 Feb 2014 19:52:05 +0200 Subject: drm/i915: Add intel_ring_cachline_align() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit intel_ring_cachline_align() emits MI_NOOPs until the ring tail is aligned to a cacheline boundary. Cc: Bjoern C Cc: Alexandru DAMIAN Cc: Enrico Tagliavini Suggested-by: Chris Wilson Signed-off-by: Ville Syrjälä Reviewed-by: Chris Wilson Cc: stable@vger.kernel.org (prereq for the next patch) Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ringbuffer.c | 21 +++++++++++++++++++++ drivers/gpu/drm/i915/intel_ringbuffer.h | 1 + 2 files changed, 22 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index b7f1742caf87..31b36c5ac894 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1653,6 +1653,27 @@ int intel_ring_begin(struct intel_ring_buffer *ring, return 0; } +/* Align the ring tail to a cacheline boundary */ +int intel_ring_cacheline_align(struct intel_ring_buffer *ring) +{ + int num_dwords = (64 - (ring->tail & 63)) / sizeof(uint32_t); + int ret; + + if (num_dwords == 0) + return 0; + + ret = intel_ring_begin(ring, num_dwords); + if (ret) + return ret; + + while (num_dwords--) + intel_ring_emit(ring, MI_NOOP); + + intel_ring_advance(ring); + + return 0; +} + void intel_ring_init_seqno(struct intel_ring_buffer *ring, u32 seqno) { struct drm_i915_private *dev_priv = ring->dev->dev_private; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 71a73f4fe252..0b243ce33714 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -233,6 +233,7 @@ intel_write_status_page(struct intel_ring_buffer *ring, void intel_cleanup_ring_buffer(struct intel_ring_buffer *ring); int __must_check intel_ring_begin(struct intel_ring_buffer *ring, int n); +int __must_check intel_ring_cacheline_align(struct intel_ring_buffer *ring); static inline void intel_ring_emit(struct intel_ring_buffer *ring, u32 data) { -- cgit v1.2.3 From f66fab8e1cd6b3127ba4c5c0d11539fbe1de1e36 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 11 Feb 2014 19:52:06 +0200 Subject: drm/i915: Prevent MI_DISPLAY_FLIP straddling two cachelines on IVB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to BSpec the entire MI_DISPLAY_FLIP packet must be contained in a single cacheline. Make sure that happens. v2: Use intel_ring_begin_cacheline_safe() v3: Use intel_ring_cacheline_align() (Chris) Cc: Bjoern C Cc: Alexandru DAMIAN Cc: Enrico Tagliavini Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=74053 Signed-off-by: Ville Syrjälä Cc: stable@vger.kernel.org Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 40a9338ad54f..88ad172143c6 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -8586,6 +8586,20 @@ static int intel_gen7_queue_flip(struct drm_device *dev, if (ring->id == RCS) len += 6; + /* + * BSpec MI_DISPLAY_FLIP for IVB: + * "The full packet must be contained within the same cache line." + * + * Currently the LRI+SRM+MI_DISPLAY_FLIP all fit within the same + * cacheline, if we ever start emitting more commands before + * the MI_DISPLAY_FLIP we may need to first emit everything else, + * then do the cacheline alignment, and finally emit the + * MI_DISPLAY_FLIP. + */ + ret = intel_ring_cacheline_align(ring); + if (ret) + goto err_unpin; + ret = intel_ring_begin(ring, len); if (ret) goto err_unpin; -- cgit v1.2.3 From 862474f8b46f6c1e600d4934e40ba40646c696ec Mon Sep 17 00:00:00 2001 From: Olivier Sobrie Date: Tue, 11 Feb 2014 11:01:23 +0100 Subject: can: kvaser_usb: check number of channels returned by HW It is needed to check the number of channels returned by the HW because it cannot be greater than MAX_NET_DEVICES otherwise it will crash. Signed-off-by: Olivier Sobrie Cc: linux-stable Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/kvaser_usb.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/can/usb/kvaser_usb.c b/drivers/net/can/usb/kvaser_usb.c index 6c859bba8b65..e77d11049747 100644 --- a/drivers/net/can/usb/kvaser_usb.c +++ b/drivers/net/can/usb/kvaser_usb.c @@ -473,6 +473,8 @@ static int kvaser_usb_get_card_info(struct kvaser_usb *dev) return err; dev->nchannels = msg.u.cardinfo.nchannels; + if (dev->nchannels > MAX_NET_DEVICES) + return -EINVAL; return 0; } -- cgit v1.2.3 From 8e67bbbc51dbeaba480e83fe2162eb08083a0459 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Thu, 6 Feb 2014 12:35:05 +0100 Subject: drm/vmwgfx: Fix a couple of sparse warnings and errors Introduced with 3.14-rc1 Reported-by: Fengguang Wu Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz --- drivers/gpu/drm/vmwgfx/vmwgfx_context.c | 9 +++------ drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_shader.c | 16 +++++++++------- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_context.c b/drivers/gpu/drm/vmwgfx/vmwgfx_context.c index 9426c53fb483..1e80152674b5 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_context.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_context.c @@ -551,8 +551,7 @@ static int vmw_context_scrub_shader(struct vmw_ctx_bindinfo *bi, bool rebind) cmd->header.size = sizeof(cmd->body); cmd->body.cid = bi->ctx->id; cmd->body.type = bi->i1.shader_type; - cmd->body.shid = - cpu_to_le32((rebind) ? bi->res->id : SVGA3D_INVALID_ID); + cmd->body.shid = ((rebind) ? bi->res->id : SVGA3D_INVALID_ID); vmw_fifo_commit(dev_priv, sizeof(*cmd)); return 0; @@ -585,8 +584,7 @@ static int vmw_context_scrub_render_target(struct vmw_ctx_bindinfo *bi, cmd->header.size = sizeof(cmd->body); cmd->body.cid = bi->ctx->id; cmd->body.type = bi->i1.rt_type; - cmd->body.target.sid = - cpu_to_le32((rebind) ? bi->res->id : SVGA3D_INVALID_ID); + cmd->body.target.sid = ((rebind) ? bi->res->id : SVGA3D_INVALID_ID); cmd->body.target.face = 0; cmd->body.target.mipmap = 0; vmw_fifo_commit(dev_priv, sizeof(*cmd)); @@ -628,8 +626,7 @@ static int vmw_context_scrub_texture(struct vmw_ctx_bindinfo *bi, cmd->body.c.cid = bi->ctx->id; cmd->body.s1.stage = bi->i1.texture_stage; cmd->body.s1.name = SVGA3D_TS_BIND_TEXTURE; - cmd->body.s1.value = - cpu_to_le32((rebind) ? bi->res->id : SVGA3D_INVALID_ID); + cmd->body.s1.value = ((rebind) ? bi->res->id : SVGA3D_INVALID_ID); vmw_fifo_commit(dev_priv, sizeof(*cmd)); return 0; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index 269b85cc875a..88a2d56e255c 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c @@ -602,7 +602,7 @@ static int vmw_cmd_cid_check(struct vmw_private *dev_priv, { struct vmw_cid_cmd { SVGA3dCmdHeader header; - __le32 cid; + uint32_t cid; } *cmd; cmd = container_of(header, struct vmw_cid_cmd, header); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c index 217d941b8176..ee3856578a12 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c @@ -371,13 +371,13 @@ int vmw_shader_destroy_ioctl(struct drm_device *dev, void *data, TTM_REF_USAGE); } -int vmw_shader_alloc(struct vmw_private *dev_priv, - struct vmw_dma_buffer *buffer, - size_t shader_size, - size_t offset, - SVGA3dShaderType shader_type, - struct ttm_object_file *tfile, - u32 *handle) +static int vmw_shader_alloc(struct vmw_private *dev_priv, + struct vmw_dma_buffer *buffer, + size_t shader_size, + size_t offset, + SVGA3dShaderType shader_type, + struct ttm_object_file *tfile, + u32 *handle) { struct vmw_user_shader *ushader; struct vmw_resource *res, *tmp; @@ -779,6 +779,8 @@ vmw_compat_shader_man_create(struct vmw_private *dev_priv) int ret; man = kzalloc(sizeof(*man), GFP_KERNEL); + if (man == NULL) + return ERR_PTR(-ENOMEM); man->dev_priv = dev_priv; INIT_LIST_HEAD(&man->list); -- cgit v1.2.3 From 857aea1c5769386b1905bb38fbb4464c800b2df6 Mon Sep 17 00:00:00 2001 From: Charmaine Lee Date: Wed, 12 Feb 2014 12:07:38 +0100 Subject: drm/vmwgfx: Get maximum mob size from register SVGA_REG_MOB_MAX_SIZE This patch queries the register SVGA_REG_MOB_MAX_SIZE for the maximum size of a single mob. Signed-off-by: Charmaine Lee Reviewed-by: Thomas Hellstrom --- drivers/gpu/drm/vmwgfx/svga_reg.h | 9 ++++++++- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 3 +++ drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 1 + drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c | 3 +++ include/uapi/drm/vmwgfx_drm.h | 1 + 5 files changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vmwgfx/svga_reg.h b/drivers/gpu/drm/vmwgfx/svga_reg.h index 71defa4d2d75..11323dd5196f 100644 --- a/drivers/gpu/drm/vmwgfx/svga_reg.h +++ b/drivers/gpu/drm/vmwgfx/svga_reg.h @@ -169,10 +169,17 @@ enum { SVGA_REG_TRACES = 45, /* Enable trace-based updates even when FIFO is on */ SVGA_REG_GMRS_MAX_PAGES = 46, /* Maximum number of 4KB pages for all GMRs */ SVGA_REG_MEMORY_SIZE = 47, /* Total dedicated device memory excluding FIFO */ + SVGA_REG_COMMAND_LOW = 48, /* Lower 32 bits and submits commands */ + SVGA_REG_COMMAND_HIGH = 49, /* Upper 32 bits of command buffer PA */ SVGA_REG_MAX_PRIMARY_BOUNDING_BOX_MEM = 50, /* Max primary memory */ SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB = 51, /* Suggested limit on mob mem */ SVGA_REG_DEV_CAP = 52, /* Write dev cap index, read value */ - SVGA_REG_TOP = 53, /* Must be 1 more than the last register */ + SVGA_REG_CMD_PREPEND_LOW = 53, + SVGA_REG_CMD_PREPEND_HIGH = 54, + SVGA_REG_SCREENTARGET_MAX_WIDTH = 55, + SVGA_REG_SCREENTARGET_MAX_HEIGHT = 56, + SVGA_REG_MOB_MAX_SIZE = 57, + SVGA_REG_TOP = 58, /* Must be 1 more than the last register */ SVGA_PALETTE_BASE = 1024, /* Base of SVGA color map */ /* Next 768 (== 256*3) registers exist for colormap */ diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 3bdc0adc656d..0083cbf99edf 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -667,6 +667,7 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) dev_priv->memory_size = 512*1024*1024; } dev_priv->max_mob_pages = 0; + dev_priv->max_mob_size = 0; if (dev_priv->capabilities & SVGA_CAP_GBOBJECTS) { uint64_t mem_size = vmw_read(dev_priv, @@ -676,6 +677,8 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) dev_priv->prim_bb_mem = vmw_read(dev_priv, SVGA_REG_MAX_PRIMARY_BOUNDING_BOX_MEM); + dev_priv->max_mob_size = + vmw_read(dev_priv, SVGA_REG_MOB_MAX_SIZE); } else dev_priv->prim_bb_mem = dev_priv->vram_size; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index ecaa302a6154..9e4be1725985 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -386,6 +386,7 @@ struct vmw_private { uint32_t max_gmr_ids; uint32_t max_gmr_pages; uint32_t max_mob_pages; + uint32_t max_mob_size; uint32_t memory_size; bool has_gmr; bool has_mob; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c index f9881f9e62bd..47b70949bf3a 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c @@ -102,6 +102,9 @@ int vmw_getparam_ioctl(struct drm_device *dev, void *data, vmw_fp->gb_aware = true; param->value = dev_priv->max_mob_pages * PAGE_SIZE; break; + case DRM_VMW_PARAM_MAX_MOB_SIZE: + param->value = dev_priv->max_mob_size; + break; default: DRM_ERROR("Illegal vmwgfx get param request: %d\n", param->param); diff --git a/include/uapi/drm/vmwgfx_drm.h b/include/uapi/drm/vmwgfx_drm.h index 9971c560ed9a..87792a5fee3b 100644 --- a/include/uapi/drm/vmwgfx_drm.h +++ b/include/uapi/drm/vmwgfx_drm.h @@ -87,6 +87,7 @@ #define DRM_VMW_PARAM_MAX_SURF_MEMORY 7 #define DRM_VMW_PARAM_3D_CAPS_SIZE 8 #define DRM_VMW_PARAM_MAX_MOB_MEMORY 9 +#define DRM_VMW_PARAM_MAX_MOB_SIZE 10 /** * struct drm_vmw_getparam_arg -- cgit v1.2.3 From b2ad9881d6aeec4f3ee527c00fce34442d6d02d3 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 11 Feb 2014 19:03:47 +0300 Subject: drm/vmwgfx: unlock on error path in vmw_execbuf_process() There is a missing unlock on error here. Fixes: 30f82d816d2d ('drm/vmwgfx: Reemit context bindings when necessary v2') Signed-off-by: Dan Carpenter Reviewed-by: Thomas Hellstrom --- drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index 88a2d56e255c..216ef23e28ff 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c @@ -2469,7 +2469,7 @@ int vmw_execbuf_process(struct drm_file *file_priv, if (dev_priv->has_mob) { ret = vmw_rebind_contexts(sw_context); if (unlikely(ret != 0)) - goto out_err; + goto out_unlock_binding; } cmd = vmw_fifo_reserve(dev_priv, command_size); -- cgit v1.2.3 From 4fbd9d2ec2f12ffb292c1489d1402e8b956afc01 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 12 Feb 2014 12:37:01 +0100 Subject: drm/vmwgfx: Remove stray const Reported-by: Fengguang Wu Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz --- drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index 216ef23e28ff..904fdde1ebab 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c @@ -1835,7 +1835,7 @@ static int vmw_cmd_check_not_3d(struct vmw_private *dev_priv, return 0; } -static const struct vmw_cmd_entry const vmw_cmd_entries[SVGA_3D_CMD_MAX] = { +static const struct vmw_cmd_entry vmw_cmd_entries[SVGA_3D_CMD_MAX] = { VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DEFINE, &vmw_cmd_invalid, false, false, false), VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DESTROY, &vmw_cmd_invalid, -- cgit v1.2.3 From ebf6dad0de89677aa58a4d8b009014ff88a23452 Mon Sep 17 00:00:00 2001 From: Steve Twiss Date: Wed, 12 Feb 2014 09:57:52 +0000 Subject: regulator: da9063: Bug fix when setting max voltage on LDOs 5-11 Bug fix to allow the setting of maximum voltage for certain LDOs. What the bug is: There is a problem caused by an invalid calculation of n_voltages in the driver. This n_voltages value has the potential to be different for each regulator. The value for linear_min_sel is set as DA9063_V##regl_name# which can be different depending upon the regulator. This is chosen according to the following definitions in the DA9063 registers.h file: DA9063_VLDO1_BIAS 0 DA9063_VLDO2_BIAS 0 DA9063_VLDO3_BIAS 0 DA9063_VLDO4_BIAS 0 DA9063_VLDO5_BIAS 2 DA9063_VLDO6_BIAS 2 DA9063_VLDO7_BIAS 2 DA9063_VLDO8_BIAS 2 DA9063_VLDO9_BIAS 3 DA9063_VLDO10_BIAS 2 DA9063_VLDO11_BIAS 2 The calculation for n_voltages is valid for LDOs whose BIAS value is zero but this is not correct for those LDOs which have a non-zero value. What the fix is: In order to take into account the non-zero linear_min_sel value which is set for the regulators LDO5, LDO6, LDO7, LDO8, LDO9, LDO10 and LDO11, the calculation for n_voltages should take into account the missing term defined by DA9063_V##regl_name#. This will in turn allow the core constraints calculation to set the maximum voltage limits correctly and therefore allow users to apply the maximum expected voltage to all of the LDOs. Signed-off-by: Steve Twiss Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- drivers/regulator/da9063-regulator.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/da9063-regulator.c b/drivers/regulator/da9063-regulator.c index 56727eb745df..91e99a2c8dc1 100644 --- a/drivers/regulator/da9063-regulator.c +++ b/drivers/regulator/da9063-regulator.c @@ -1,3 +1,4 @@ + /* * Regulator driver for DA9063 PMIC series * @@ -60,7 +61,8 @@ struct da9063_regulator_info { .desc.ops = &da9063_ldo_ops, \ .desc.min_uV = (min_mV) * 1000, \ .desc.uV_step = (step_mV) * 1000, \ - .desc.n_voltages = (((max_mV) - (min_mV))/(step_mV) + 1), \ + .desc.n_voltages = (((max_mV) - (min_mV))/(step_mV) + 1 \ + + (DA9063_V##regl_name##_BIAS)), \ .desc.enable_reg = DA9063_REG_##regl_name##_CONT, \ .desc.enable_mask = DA9063_LDO_EN, \ .desc.vsel_reg = DA9063_REG_V##regl_name##_A, \ -- cgit v1.2.3 From 15cc17678547676c82a5da9ccf357447333fc342 Mon Sep 17 00:00:00 2001 From: Eric Whitney Date: Wed, 12 Feb 2014 10:42:45 -0500 Subject: ext4: fix xfstest generic/299 block validity failures Commit a115f749c1 (ext4: remove wait for unwritten extent conversion from ext4_truncate) exposed a bug in ext4_ext_handle_uninitialized_extents(). It can be triggered by xfstest generic/299 when run on a test file system created without a journal. This test continuously fallocates and truncates files to which random dio/aio writes are simultaneously performed by a separate process. The test completes successfully, but if the test filesystem is mounted with the block_validity option, a warning message stating that a logical block has been mapped to an illegal physical block is posted in the kernel log. The bug occurs when an extent is being converted to the written state by ext4_end_io_dio() and ext4_ext_handle_uninitialized_extents() discovers a mapping for an existing uninitialized extent. Although it sets EXT4_MAP_MAPPED in map->m_flags, it fails to set map->m_pblk to the discovered physical block number. Because map->m_pblk is not otherwise initialized or set by this function or its callers, its uninitialized value is returned to ext4_map_blocks(), where it is stored as a bogus mapping in the extent status tree. Since map->m_pblk can accidentally contain illegal values that are larger than the physical size of the file system, calls to check_block_validity() in ext4_map_blocks() that are enabled if the block_validity mount option is used can fail, resulting in the logged warning message. Signed-off-by: Eric Whitney Signed-off-by: "Theodore Ts'o" Cc: stable@vger.kernel.org # 3.11+ --- fs/ext4/extents.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 10cff4736b11..74bc2d549c58 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -3906,6 +3906,7 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode, } else err = ret; map->m_flags |= EXT4_MAP_MAPPED; + map->m_pblk = newblock; if (allocated > map->m_len) allocated = map->m_len; map->m_len = allocated; -- cgit v1.2.3 From e3947ecb4e8adf260b6323eac43b80eeb26911cf Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 12 Feb 2014 17:11:22 +0100 Subject: ASoC: blackfin: Fix machine driver Kconfig dependencies Since the machine driver selects the CODEC driver we need to make sure that the machine driver is only selectable if the CODEC driver can be build. This avoids build errors under some configurations (which typically only result from randconfig). Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/blackfin/Kconfig | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/sound/soc/blackfin/Kconfig b/sound/soc/blackfin/Kconfig index 54f74f8cbb75..4544d8eb1452 100644 --- a/sound/soc/blackfin/Kconfig +++ b/sound/soc/blackfin/Kconfig @@ -11,7 +11,7 @@ config SND_BF5XX_I2S config SND_BF5XX_SOC_SSM2602 tristate "SoC SSM2602 Audio Codec Add-On Card support" - depends on SND_BF5XX_I2S && (SPI_MASTER || I2C) + depends on SND_BF5XX_I2S && SND_SOC_I2C_AND_SPI select SND_BF5XX_SOC_I2S if !BF60x select SND_BF6XX_SOC_I2S if BF60x select SND_SOC_SSM2602 @@ -21,10 +21,9 @@ config SND_BF5XX_SOC_SSM2602 config SND_SOC_BFIN_EVAL_ADAU1701 tristate "Support for the EVAL-ADAU1701MINIZ board on Blackfin eval boards" - depends on SND_BF5XX_I2S + depends on SND_BF5XX_I2S && I2C select SND_BF5XX_SOC_I2S select SND_SOC_ADAU1701 - select I2C help Say Y if you want to add support for the Analog Devices EVAL-ADAU1701MINIZ board connected to one of the Blackfin evaluation boards like the @@ -45,7 +44,7 @@ config SND_SOC_BFIN_EVAL_ADAU1373 config SND_SOC_BFIN_EVAL_ADAV80X tristate "Support for the EVAL-ADAV80X boards on Blackfin eval boards" - depends on SND_BF5XX_I2S && (SPI_MASTER || I2C) + depends on SND_BF5XX_I2S && SND_SOC_I2C_AND_SPI select SND_BF5XX_SOC_I2S select SND_SOC_ADAV80X help @@ -58,7 +57,7 @@ config SND_SOC_BFIN_EVAL_ADAV80X config SND_BF5XX_SOC_AD1836 tristate "SoC AD1836 Audio support for BF5xx" - depends on SND_BF5XX_I2S + depends on SND_BF5XX_I2S && SPI_MASTER select SND_BF5XX_SOC_I2S select SND_SOC_AD1836 help @@ -66,7 +65,7 @@ config SND_BF5XX_SOC_AD1836 config SND_BF5XX_SOC_AD193X tristate "SoC AD193X Audio support for Blackfin" - depends on SND_BF5XX_I2S + depends on SND_BF5XX_I2S && SND_SOC_I2C_AND_SPI select SND_BF5XX_SOC_I2S select SND_SOC_AD193X help -- cgit v1.2.3 From 30d29b119ef01776e0a301444ab24defe8d8bef3 Mon Sep 17 00:00:00 2001 From: Zheng Liu Date: Wed, 12 Feb 2014 11:48:31 -0500 Subject: ext4: fix error paths in swap_inode_boot_loader() In swap_inode_boot_loader() we forgot to release ->i_mutex and resume unlocked dio for inode and inode_bl if there is an error starting the journal handle. This commit fixes this issue. Reported-by: Ahmed Tamrawi Cc: Andreas Dilger Cc: Dr. Tilmann Bubeck Signed-off-by: Zheng Liu Signed-off-by: "Theodore Ts'o" Cc: stable@vger.kernel.org # v3.10+ --- fs/ext4/ioctl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index 6bea80614d77..a2a837f00407 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c @@ -140,7 +140,7 @@ static long swap_inode_boot_loader(struct super_block *sb, handle = ext4_journal_start(inode_bl, EXT4_HT_MOVE_EXTENTS, 2); if (IS_ERR(handle)) { err = -EINVAL; - goto swap_boot_out; + goto journal_err_out; } /* Protect extent tree against block allocations via delalloc */ @@ -198,6 +198,7 @@ static long swap_inode_boot_loader(struct super_block *sb, ext4_double_up_write_data_sem(inode, inode_bl); +journal_err_out: ext4_inode_resume_unlocked_dio(inode); ext4_inode_resume_unlocked_dio(inode_bl); -- cgit v1.2.3 From 23301410972330c0ae9a8afc379ba2005e249cc6 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Wed, 12 Feb 2014 12:16:04 -0500 Subject: ext4: don't try to modify s_flags if the the file system is read-only If an ext4 file system is created by some tool other than mke2fs (perhaps by someone who has a pathalogical fear of the GPL) that doesn't set one or the other of the EXT2_FLAGS_{UN}SIGNED_HASH flags, and that file system is then mounted read-only, don't try to modify the s_flags field. Otherwise, if dm_verity is in use, the superblock will change, causing an dm_verity failure. Signed-off-by: "Theodore Ts'o" Cc: stable@vger.kernel.org --- fs/ext4/super.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 1f7784de05b6..710fed2377d4 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -3695,16 +3695,22 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) for (i = 0; i < 4; i++) sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]); sbi->s_def_hash_version = es->s_def_hash_version; - i = le32_to_cpu(es->s_flags); - if (i & EXT2_FLAGS_UNSIGNED_HASH) - sbi->s_hash_unsigned = 3; - else if ((i & EXT2_FLAGS_SIGNED_HASH) == 0) { + if (EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_DIR_INDEX)) { + i = le32_to_cpu(es->s_flags); + if (i & EXT2_FLAGS_UNSIGNED_HASH) + sbi->s_hash_unsigned = 3; + else if ((i & EXT2_FLAGS_SIGNED_HASH) == 0) { #ifdef __CHAR_UNSIGNED__ - es->s_flags |= cpu_to_le32(EXT2_FLAGS_UNSIGNED_HASH); - sbi->s_hash_unsigned = 3; + if (!(sb->s_flags & MS_RDONLY)) + es->s_flags |= + cpu_to_le32(EXT2_FLAGS_UNSIGNED_HASH); + sbi->s_hash_unsigned = 3; #else - es->s_flags |= cpu_to_le32(EXT2_FLAGS_SIGNED_HASH); + if (!(sb->s_flags & MS_RDONLY)) + es->s_flags |= + cpu_to_le32(EXT2_FLAGS_SIGNED_HASH); #endif + } } /* Handle clustersize */ -- cgit v1.2.3 From b055211d941eb6cb7b285be580cf6e51a01d2f44 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 12 Feb 2014 12:56:48 +0100 Subject: drm/vmwgfx: Fix possible integer overflow Cc: stable@vger.kernel.org Reported-by: Brian Paul Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz --- drivers/gpu/drm/vmwgfx/svga3d_surfacedefs.h | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/svga3d_surfacedefs.h b/drivers/gpu/drm/vmwgfx/svga3d_surfacedefs.h index 8369c3ba10fe..ef3385096145 100644 --- a/drivers/gpu/drm/vmwgfx/svga3d_surfacedefs.h +++ b/drivers/gpu/drm/vmwgfx/svga3d_surfacedefs.h @@ -38,8 +38,11 @@ #define DIV_ROUND_UP(x, y) (((x) + (y) - 1) / (y)) #define max_t(type, x, y) ((x) > (y) ? (x) : (y)) +#define min_t(type, x, y) ((x) < (y) ? (x) : (y)) #define surf_size_struct SVGA3dSize #define u32 uint32 +#define u64 uint64_t +#define U32_MAX ((u32)~0U) #endif /* __KERNEL__ */ @@ -704,8 +707,8 @@ static const struct svga3d_surface_desc svga3d_surface_descs[] = { static inline u32 clamped_umul32(u32 a, u32 b) { - uint64_t tmp = (uint64_t) a*b; - return (tmp > (uint64_t) ((u32) -1)) ? (u32) -1 : tmp; + u64 tmp = (u64) a*b; + return (tmp > (u64) U32_MAX) ? U32_MAX : tmp; } static inline const struct svga3d_surface_desc * @@ -834,7 +837,7 @@ svga3dsurface_get_serialized_size(SVGA3dSurfaceFormat format, bool cubemap) { const struct svga3d_surface_desc *desc = svga3dsurface_get_desc(format); - u32 total_size = 0; + u64 total_size = 0; u32 mip; for (mip = 0; mip < num_mip_levels; mip++) { @@ -847,7 +850,7 @@ svga3dsurface_get_serialized_size(SVGA3dSurfaceFormat format, if (cubemap) total_size *= SVGA3D_MAX_SURFACE_FACES; - return total_size; + return (u32) min_t(u64, total_size, (u64) U32_MAX); } -- cgit v1.2.3 From 36e952c1ed8ca44bca245c465c8293e175dd9222 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 12 Feb 2014 13:19:36 +0100 Subject: drm/vmwgfx: Fix command defines and checks Make sure all guest-backed object commands are properly packed. Have the command verifier treat uninitialized command entries as invalid rather than dereferencing NULL pointers. Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz --- drivers/gpu/drm/vmwgfx/svga3d_reg.h | 122 +++++++++++++++++++------------- drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | 3 + 2 files changed, 75 insertions(+), 50 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/svga3d_reg.h b/drivers/gpu/drm/vmwgfx/svga3d_reg.h index b645647b7776..bb594c11605e 100644 --- a/drivers/gpu/drm/vmwgfx/svga3d_reg.h +++ b/drivers/gpu/drm/vmwgfx/svga3d_reg.h @@ -1223,9 +1223,19 @@ typedef enum { #define SVGA_3D_CMD_INVALIDATE_GB_IMAGE_PARTIAL 1129 #define SVGA_3D_CMD_SET_GB_SHADERCONSTS_INLINE 1130 - +#define SVGA_3D_CMD_GB_SCREEN_DMA 1131 +#define SVGA_3D_CMD_BIND_GB_SURFACE_WITH_PITCH 1132 +#define SVGA_3D_CMD_GB_MOB_FENCE 1133 +#define SVGA_3D_CMD_DEFINE_GB_SURFACE_V2 1134 #define SVGA_3D_CMD_DEFINE_GB_MOB64 1135 #define SVGA_3D_CMD_REDEFINE_GB_MOB64 1136 +#define SVGA_3D_CMD_NOP_ERROR 1137 + +#define SVGA_3D_CMD_RESERVED1 1138 +#define SVGA_3D_CMD_RESERVED2 1139 +#define SVGA_3D_CMD_RESERVED3 1140 +#define SVGA_3D_CMD_RESERVED4 1141 +#define SVGA_3D_CMD_RESERVED5 1142 #define SVGA_3D_CMD_MAX 1142 #define SVGA_3D_CMD_FUTURE_MAX 3000 @@ -1973,8 +1983,7 @@ struct { uint32 sizeInBytes; uint32 validSizeInBytes; SVGAMobFormat ptDepth; -} -__attribute__((__packed__)) +} __packed SVGA3dCmdSetOTableBase; /* SVGA_3D_CMD_SET_OTABLE_BASE */ typedef @@ -1984,15 +1993,13 @@ struct { uint32 sizeInBytes; uint32 validSizeInBytes; SVGAMobFormat ptDepth; -} -__attribute__((__packed__)) +} __packed SVGA3dCmdSetOTableBase64; /* SVGA_3D_CMD_SET_OTABLE_BASE64 */ typedef struct { SVGAOTableType type; -} -__attribute__((__packed__)) +} __packed SVGA3dCmdReadbackOTable; /* SVGA_3D_CMD_READBACK_OTABLE */ /* @@ -2005,8 +2012,7 @@ struct SVGA3dCmdDefineGBMob { SVGAMobFormat ptDepth; PPN base; uint32 sizeInBytes; -} -__attribute__((__packed__)) +} __packed SVGA3dCmdDefineGBMob; /* SVGA_3D_CMD_DEFINE_GB_MOB */ @@ -2017,8 +2023,7 @@ SVGA3dCmdDefineGBMob; /* SVGA_3D_CMD_DEFINE_GB_MOB */ typedef struct SVGA3dCmdDestroyGBMob { SVGAMobId mobid; -} -__attribute__((__packed__)) +} __packed SVGA3dCmdDestroyGBMob; /* SVGA_3D_CMD_DESTROY_GB_MOB */ /* @@ -2031,8 +2036,7 @@ struct SVGA3dCmdRedefineGBMob { SVGAMobFormat ptDepth; PPN base; uint32 sizeInBytes; -} -__attribute__((__packed__)) +} __packed SVGA3dCmdRedefineGBMob; /* SVGA_3D_CMD_REDEFINE_GB_MOB */ /* @@ -2045,8 +2049,7 @@ struct SVGA3dCmdDefineGBMob64 { SVGAMobFormat ptDepth; PPN64 base; uint32 sizeInBytes; -} -__attribute__((__packed__)) +} __packed SVGA3dCmdDefineGBMob64; /* SVGA_3D_CMD_DEFINE_GB_MOB64 */ /* @@ -2059,8 +2062,7 @@ struct SVGA3dCmdRedefineGBMob64 { SVGAMobFormat ptDepth; PPN64 base; uint32 sizeInBytes; -} -__attribute__((__packed__)) +} __packed SVGA3dCmdRedefineGBMob64; /* SVGA_3D_CMD_REDEFINE_GB_MOB64 */ /* @@ -2070,8 +2072,7 @@ SVGA3dCmdRedefineGBMob64; /* SVGA_3D_CMD_REDEFINE_GB_MOB64 */ typedef struct SVGA3dCmdUpdateGBMobMapping { SVGAMobId mobid; -} -__attribute__((__packed__)) +} __packed SVGA3dCmdUpdateGBMobMapping; /* SVGA_3D_CMD_UPDATE_GB_MOB_MAPPING */ /* @@ -2087,7 +2088,8 @@ struct SVGA3dCmdDefineGBSurface { uint32 multisampleCount; SVGA3dTextureFilter autogenFilter; SVGA3dSize size; -} SVGA3dCmdDefineGBSurface; /* SVGA_3D_CMD_DEFINE_GB_SURFACE */ +} __packed +SVGA3dCmdDefineGBSurface; /* SVGA_3D_CMD_DEFINE_GB_SURFACE */ /* * Destroy a guest-backed surface. @@ -2096,7 +2098,8 @@ struct SVGA3dCmdDefineGBSurface { typedef struct SVGA3dCmdDestroyGBSurface { uint32 sid; -} SVGA3dCmdDestroyGBSurface; /* SVGA_3D_CMD_DESTROY_GB_SURFACE */ +} __packed +SVGA3dCmdDestroyGBSurface; /* SVGA_3D_CMD_DESTROY_GB_SURFACE */ /* * Bind a guest-backed surface to an object. @@ -2106,7 +2109,8 @@ typedef struct SVGA3dCmdBindGBSurface { uint32 sid; SVGAMobId mobid; -} SVGA3dCmdBindGBSurface; /* SVGA_3D_CMD_BIND_GB_SURFACE */ +} __packed +SVGA3dCmdBindGBSurface; /* SVGA_3D_CMD_BIND_GB_SURFACE */ /* * Conditionally bind a mob to a guest backed surface if testMobid @@ -2123,7 +2127,7 @@ struct{ SVGAMobId testMobid; SVGAMobId mobid; uint32 flags; -} +} __packed SVGA3dCmdCondBindGBSurface; /* SVGA_3D_CMD_COND_BIND_GB_SURFACE */ /* @@ -2135,7 +2139,8 @@ typedef struct SVGA3dCmdUpdateGBImage { SVGA3dSurfaceImageId image; SVGA3dBox box; -} SVGA3dCmdUpdateGBImage; /* SVGA_3D_CMD_UPDATE_GB_IMAGE */ +} __packed +SVGA3dCmdUpdateGBImage; /* SVGA_3D_CMD_UPDATE_GB_IMAGE */ /* * Update an entire guest-backed surface. @@ -2145,7 +2150,8 @@ struct SVGA3dCmdUpdateGBImage { typedef struct SVGA3dCmdUpdateGBSurface { uint32 sid; -} SVGA3dCmdUpdateGBSurface; /* SVGA_3D_CMD_UPDATE_GB_SURFACE */ +} __packed +SVGA3dCmdUpdateGBSurface; /* SVGA_3D_CMD_UPDATE_GB_SURFACE */ /* * Readback an image in a guest-backed surface. @@ -2155,7 +2161,8 @@ struct SVGA3dCmdUpdateGBSurface { typedef struct SVGA3dCmdReadbackGBImage { SVGA3dSurfaceImageId image; -} SVGA3dCmdReadbackGBImage; /* SVGA_3D_CMD_READBACK_GB_IMAGE*/ +} __packed +SVGA3dCmdReadbackGBImage; /* SVGA_3D_CMD_READBACK_GB_IMAGE*/ /* * Readback an entire guest-backed surface. @@ -2165,7 +2172,8 @@ struct SVGA3dCmdReadbackGBImage { typedef struct SVGA3dCmdReadbackGBSurface { uint32 sid; -} SVGA3dCmdReadbackGBSurface; /* SVGA_3D_CMD_READBACK_GB_SURFACE */ +} __packed +SVGA3dCmdReadbackGBSurface; /* SVGA_3D_CMD_READBACK_GB_SURFACE */ /* * Readback a sub rect of an image in a guest-backed surface. After @@ -2179,7 +2187,7 @@ struct SVGA3dCmdReadbackGBImagePartial { SVGA3dSurfaceImageId image; SVGA3dBox box; uint32 invertBox; -} +} __packed SVGA3dCmdReadbackGBImagePartial; /* SVGA_3D_CMD_READBACK_GB_IMAGE_PARTIAL */ /* @@ -2190,7 +2198,8 @@ SVGA3dCmdReadbackGBImagePartial; /* SVGA_3D_CMD_READBACK_GB_IMAGE_PARTIAL */ typedef struct SVGA3dCmdInvalidateGBImage { SVGA3dSurfaceImageId image; -} SVGA3dCmdInvalidateGBImage; /* SVGA_3D_CMD_INVALIDATE_GB_IMAGE */ +} __packed +SVGA3dCmdInvalidateGBImage; /* SVGA_3D_CMD_INVALIDATE_GB_IMAGE */ /* * Invalidate an entire guest-backed surface. @@ -2200,7 +2209,8 @@ struct SVGA3dCmdInvalidateGBImage { typedef struct SVGA3dCmdInvalidateGBSurface { uint32 sid; -} SVGA3dCmdInvalidateGBSurface; /* SVGA_3D_CMD_INVALIDATE_GB_SURFACE */ +} __packed +SVGA3dCmdInvalidateGBSurface; /* SVGA_3D_CMD_INVALIDATE_GB_SURFACE */ /* * Invalidate a sub rect of an image in a guest-backed surface. After @@ -2214,7 +2224,7 @@ struct SVGA3dCmdInvalidateGBImagePartial { SVGA3dSurfaceImageId image; SVGA3dBox box; uint32 invertBox; -} +} __packed SVGA3dCmdInvalidateGBImagePartial; /* SVGA_3D_CMD_INVALIDATE_GB_IMAGE_PARTIAL */ /* @@ -2224,7 +2234,8 @@ SVGA3dCmdInvalidateGBImagePartial; /* SVGA_3D_CMD_INVALIDATE_GB_IMAGE_PARTIAL */ typedef struct SVGA3dCmdDefineGBContext { uint32 cid; -} SVGA3dCmdDefineGBContext; /* SVGA_3D_CMD_DEFINE_GB_CONTEXT */ +} __packed +SVGA3dCmdDefineGBContext; /* SVGA_3D_CMD_DEFINE_GB_CONTEXT */ /* * Destroy a guest-backed context. @@ -2233,7 +2244,8 @@ struct SVGA3dCmdDefineGBContext { typedef struct SVGA3dCmdDestroyGBContext { uint32 cid; -} SVGA3dCmdDestroyGBContext; /* SVGA_3D_CMD_DESTROY_GB_CONTEXT */ +} __packed +SVGA3dCmdDestroyGBContext; /* SVGA_3D_CMD_DESTROY_GB_CONTEXT */ /* * Bind a guest-backed context. @@ -2252,7 +2264,8 @@ struct SVGA3dCmdBindGBContext { uint32 cid; SVGAMobId mobid; uint32 validContents; -} SVGA3dCmdBindGBContext; /* SVGA_3D_CMD_BIND_GB_CONTEXT */ +} __packed +SVGA3dCmdBindGBContext; /* SVGA_3D_CMD_BIND_GB_CONTEXT */ /* * Readback a guest-backed context. @@ -2262,7 +2275,8 @@ struct SVGA3dCmdBindGBContext { typedef struct SVGA3dCmdReadbackGBContext { uint32 cid; -} SVGA3dCmdReadbackGBContext; /* SVGA_3D_CMD_READBACK_GB_CONTEXT */ +} __packed +SVGA3dCmdReadbackGBContext; /* SVGA_3D_CMD_READBACK_GB_CONTEXT */ /* * Invalidate a guest-backed context. @@ -2270,7 +2284,8 @@ struct SVGA3dCmdReadbackGBContext { typedef struct SVGA3dCmdInvalidateGBContext { uint32 cid; -} SVGA3dCmdInvalidateGBContext; /* SVGA_3D_CMD_INVALIDATE_GB_CONTEXT */ +} __packed +SVGA3dCmdInvalidateGBContext; /* SVGA_3D_CMD_INVALIDATE_GB_CONTEXT */ /* * Define a guest-backed shader. @@ -2281,7 +2296,8 @@ struct SVGA3dCmdDefineGBShader { uint32 shid; SVGA3dShaderType type; uint32 sizeInBytes; -} SVGA3dCmdDefineGBShader; /* SVGA_3D_CMD_DEFINE_GB_SHADER */ +} __packed +SVGA3dCmdDefineGBShader; /* SVGA_3D_CMD_DEFINE_GB_SHADER */ /* * Bind a guest-backed shader. @@ -2291,7 +2307,8 @@ typedef struct SVGA3dCmdBindGBShader { uint32 shid; SVGAMobId mobid; uint32 offsetInBytes; -} SVGA3dCmdBindGBShader; /* SVGA_3D_CMD_BIND_GB_SHADER */ +} __packed +SVGA3dCmdBindGBShader; /* SVGA_3D_CMD_BIND_GB_SHADER */ /* * Destroy a guest-backed shader. @@ -2299,7 +2316,8 @@ typedef struct SVGA3dCmdBindGBShader { typedef struct SVGA3dCmdDestroyGBShader { uint32 shid; -} SVGA3dCmdDestroyGBShader; /* SVGA_3D_CMD_DESTROY_GB_SHADER */ +} __packed +SVGA3dCmdDestroyGBShader; /* SVGA_3D_CMD_DESTROY_GB_SHADER */ typedef struct { @@ -2314,14 +2332,16 @@ struct { * Note that FLOAT and INT constants are 4-dwords in length, while * BOOL constants are 1-dword in length. */ -} SVGA3dCmdSetGBShaderConstInline; +} __packed +SVGA3dCmdSetGBShaderConstInline; /* SVGA_3D_CMD_SET_GB_SHADERCONSTS_INLINE */ typedef struct { uint32 cid; SVGA3dQueryType type; -} SVGA3dCmdBeginGBQuery; /* SVGA_3D_CMD_BEGIN_GB_QUERY */ +} __packed +SVGA3dCmdBeginGBQuery; /* SVGA_3D_CMD_BEGIN_GB_QUERY */ typedef struct { @@ -2329,7 +2349,8 @@ struct { SVGA3dQueryType type; SVGAMobId mobid; uint32 offset; -} SVGA3dCmdEndGBQuery; /* SVGA_3D_CMD_END_GB_QUERY */ +} __packed +SVGA3dCmdEndGBQuery; /* SVGA_3D_CMD_END_GB_QUERY */ /* @@ -2346,21 +2367,22 @@ struct { SVGA3dQueryType type; SVGAMobId mobid; uint32 offset; -} SVGA3dCmdWaitForGBQuery; /* SVGA_3D_CMD_WAIT_FOR_GB_QUERY */ +} __packed +SVGA3dCmdWaitForGBQuery; /* SVGA_3D_CMD_WAIT_FOR_GB_QUERY */ typedef struct { SVGAMobId mobid; uint32 fbOffset; uint32 initalized; -} +} __packed SVGA3dCmdEnableGart; /* SVGA_3D_CMD_ENABLE_GART */ typedef struct { SVGAMobId mobid; uint32 gartOffset; -} +} __packed SVGA3dCmdMapMobIntoGart; /* SVGA_3D_CMD_MAP_MOB_INTO_GART */ @@ -2368,7 +2390,7 @@ typedef struct { uint32 gartOffset; uint32 numPages; -} +} __packed SVGA3dCmdUnmapGartRange; /* SVGA_3D_CMD_UNMAP_GART_RANGE */ @@ -2385,27 +2407,27 @@ struct { int32 xRoot; int32 yRoot; uint32 flags; -} +} __packed SVGA3dCmdDefineGBScreenTarget; /* SVGA_3D_CMD_DEFINE_GB_SCREENTARGET */ typedef struct { uint32 stid; -} +} __packed SVGA3dCmdDestroyGBScreenTarget; /* SVGA_3D_CMD_DESTROY_GB_SCREENTARGET */ typedef struct { uint32 stid; SVGA3dSurfaceImageId image; -} +} __packed SVGA3dCmdBindGBScreenTarget; /* SVGA_3D_CMD_BIND_GB_SCREENTARGET */ typedef struct { uint32 stid; SVGA3dBox box; -} +} __packed SVGA3dCmdUpdateGBScreenTarget; /* SVGA_3D_CMD_UPDATE_GB_SCREENTARGET */ /* diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index 904fdde1ebab..efb575a7996c 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c @@ -2032,6 +2032,9 @@ static int vmw_cmd_check(struct vmw_private *dev_priv, goto out_invalid; entry = &vmw_cmd_entries[cmd_id]; + if (unlikely(!entry->func)) + goto out_invalid; + if (unlikely(!entry->user_allow && !sw_context->kernel)) goto out_privileged; -- cgit v1.2.3 From c42c8922c46d33ed769e99618bdfba06866a0c72 Mon Sep 17 00:00:00 2001 From: Dylan Reid Date: Wed, 12 Feb 2014 10:24:54 -0800 Subject: ASoC: max98090: sync regcache on entering STANDBY Sync regcache when entering STANDBY from OFF. ON isn't entered with OFF as the current state, so the registers were not being re-synced after suspend/resume. The 98088 and 98095 already call regcache_sync from STANDBY. Signed-off-by: Dylan Reid Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- sound/soc/codecs/max98090.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c index 51f9b3d16b41..149b57f6334b 100644 --- a/sound/soc/codecs/max98090.c +++ b/sound/soc/codecs/max98090.c @@ -1769,16 +1769,6 @@ static int max98090_set_bias_level(struct snd_soc_codec *codec, switch (level) { case SND_SOC_BIAS_ON: - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - ret = regcache_sync(max98090->regmap); - - if (ret != 0) { - dev_err(codec->dev, - "Failed to sync cache: %d\n", ret); - return ret; - } - } - if (max98090->jack_state == M98090_JACK_STATE_HEADSET) { /* * Set to normal bias level. @@ -1792,6 +1782,16 @@ static int max98090_set_bias_level(struct snd_soc_codec *codec, break; case SND_SOC_BIAS_STANDBY: + if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { + ret = regcache_sync(max98090->regmap); + if (ret != 0) { + dev_err(codec->dev, + "Failed to sync cache: %d\n", ret); + return ret; + } + } + break; + case SND_SOC_BIAS_OFF: /* Set internal pull-up to lowest power mode */ snd_soc_update_bits(codec, M98090_REG_JACK_DETECT, -- cgit v1.2.3 From 322a8e91844f4ae2093e0d3d8a318d0ef2596756 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Wed, 5 Feb 2014 11:55:49 +0100 Subject: PCI: mvebu: Use Device ID and revision from underlying endpoint Marvell SoCs place the SoC number into the PCIe endpoint device ID. The SoC stepping is placed into the PCIe revision. The old plat-orion PCIe driver allowed this information to be seen in user space with a simple lspci command. The new driver places a virtual PCI-PCI bridge on top of these endpoints. It has its own hard coded PCI device ID. Thus it is no longer possible to see what the SoC is using lspci. When initializing the PCI-PCI bridge, set its device ID and revision from the underlying endpoint, thus restoring this functionality. Debian would like to use this in order to aid installing the correct DTB file. Fixes: 45361a4fe4464 ("pci: PCIe driver for Marvell Armada 370/XP systems") Signed-off-by: Andrew Lunn Signed-off-by: Bjorn Helgaas Acked-by: Thomas Petazzoni Acked-by: Jason Cooper Cc: stable@vger.kernel.org # v3.11+ --- drivers/pci/host/pci-mvebu.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c index 13478ecd4113..0e79665afd44 100644 --- a/drivers/pci/host/pci-mvebu.c +++ b/drivers/pci/host/pci-mvebu.c @@ -60,14 +60,6 @@ #define PCIE_DEBUG_CTRL 0x1a60 #define PCIE_DEBUG_SOFT_RESET BIT(20) -/* - * This product ID is registered by Marvell, and used when the Marvell - * SoC is not the root complex, but an endpoint on the PCIe bus. It is - * therefore safe to re-use this PCI ID for our emulated PCI-to-PCI - * bridge. - */ -#define MARVELL_EMULATED_PCI_PCI_BRIDGE_ID 0x7846 - /* PCI configuration space of a PCI-to-PCI bridge */ struct mvebu_sw_pci_bridge { u16 vendor; @@ -388,7 +380,8 @@ static void mvebu_sw_pci_bridge_init(struct mvebu_pcie_port *port) bridge->class = PCI_CLASS_BRIDGE_PCI; bridge->vendor = PCI_VENDOR_ID_MARVELL; - bridge->device = MARVELL_EMULATED_PCI_PCI_BRIDGE_ID; + bridge->device = mvebu_readl(port, PCIE_DEV_ID_OFF) >> 16; + bridge->revision = mvebu_readl(port, PCIE_DEV_REV_OFF) & 0xff; bridge->header_type = PCI_HEADER_TYPE_BRIDGE; bridge->cache_line_size = 0x10; -- cgit v1.2.3 From 1a11533fbd71792e8c5d36f6763fbce8df0d231d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 12 Feb 2014 19:06:19 -0500 Subject: Revert "cgroup: use an ordered workqueue for cgroup destruction" This reverts commit ab3f5faa6255a0eb4f832675507d9e295ca7e9ba. Explanation from Hugh: It's because more thorough testing, by others here, found that it wasn't always solving the problem: so I asked Tejun privately to hold off from sending it in, until we'd worked out why not. Most of our testing being on a v3,11-based kernel, it was perfectly possible that the problem was merely our own e.g. missing Tejun's 8a2b75384444 ("workqueue: fix ordered workqueues in NUMA setups"). But that turned out not to be enough to fix it either. Then Filipe pointed out how percpu_ref_kill_and_confirm() uses call_rcu_sched() before we ever get to put the offline on to the workqueue: by the time we get to the workqueue, the ordering has already been lost. So, thanks for the Acks, but I'm afraid that this ordered workqueue solution is just not good enough: we should simply forget that patch and provide a different answer." Signed-off-by: Tejun Heo Cc: Hugh Dickins --- kernel/cgroup.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 52719ce55dd3..68d87103b493 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -4844,16 +4844,12 @@ static int __init cgroup_wq_init(void) /* * There isn't much point in executing destruction path in * parallel. Good chunk is serialized with cgroup_mutex anyway. - * - * XXX: Must be ordered to make sure parent is offlined after - * children. The ordering requirement is for memcg where a - * parent's offline may wait for a child's leading to deadlock. In - * the long term, this should be fixed from memcg side. + * Use 1 for @max_active. * * We would prefer to do this in cgroup_init() above, but that * is called before init_workqueues(): so leave this until after. */ - cgroup_destroy_wq = alloc_ordered_workqueue("cgroup_destroy", 0); + cgroup_destroy_wq = alloc_workqueue("cgroup_destroy", 0, 1); BUG_ON(!cgroup_destroy_wq); /* -- cgit v1.2.3 From c0b00a525c127d0055c1df6283300e17f601a1a1 Mon Sep 17 00:00:00 2001 From: Sumit Semwal Date: Mon, 3 Feb 2014 15:09:12 +0530 Subject: dma-buf: update debugfs output Russell King observed 'wierd' looking output from debugfs, and also suggested better ways of getting device names (use KBUILD_MODNAME, dev_name()) This patch addresses these issues to make the debugfs output correct and better looking. While at it, replace seq_printf with seq_puts to remove the checkpatch.pl warnings. Reported-by: Russell King - ARM Linux Signed-off-by: Sumit Semwal --- drivers/base/dma-buf.c | 25 ++++++++++++------------- include/linux/dma-buf.h | 2 +- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/drivers/base/dma-buf.c b/drivers/base/dma-buf.c index 1e16cbd61da2..61d6d62cc0d3 100644 --- a/drivers/base/dma-buf.c +++ b/drivers/base/dma-buf.c @@ -616,36 +616,35 @@ static int dma_buf_describe(struct seq_file *s) if (ret) return ret; - seq_printf(s, "\nDma-buf Objects:\n"); - seq_printf(s, "\texp_name\tsize\tflags\tmode\tcount\n"); + seq_puts(s, "\nDma-buf Objects:\n"); + seq_puts(s, "size\tflags\tmode\tcount\texp_name\n"); list_for_each_entry(buf_obj, &db_list.head, list_node) { ret = mutex_lock_interruptible(&buf_obj->lock); if (ret) { - seq_printf(s, - "\tERROR locking buffer object: skipping\n"); + seq_puts(s, + "\tERROR locking buffer object: skipping\n"); continue; } - seq_printf(s, "\t"); - - seq_printf(s, "\t%s\t%08zu\t%08x\t%08x\t%08ld\n", - buf_obj->exp_name, buf_obj->size, + seq_printf(s, "%08zu\t%08x\t%08x\t%08ld\t%s\n", + buf_obj->size, buf_obj->file->f_flags, buf_obj->file->f_mode, - (long)(buf_obj->file->f_count.counter)); + (long)(buf_obj->file->f_count.counter), + buf_obj->exp_name); - seq_printf(s, "\t\tAttached Devices:\n"); + seq_puts(s, "\tAttached Devices:\n"); attach_count = 0; list_for_each_entry(attach_obj, &buf_obj->attachments, node) { - seq_printf(s, "\t\t"); + seq_puts(s, "\t"); - seq_printf(s, "%s\n", attach_obj->dev->init_name); + seq_printf(s, "%s\n", dev_name(attach_obj->dev)); attach_count++; } - seq_printf(s, "\n\t\tTotal %d devices attached\n", + seq_printf(s, "Total %d devices attached\n\n", attach_count); count++; diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h index dfac5ed31120..f886985a28b2 100644 --- a/include/linux/dma-buf.h +++ b/include/linux/dma-buf.h @@ -171,7 +171,7 @@ struct dma_buf *dma_buf_export_named(void *priv, const struct dma_buf_ops *ops, size_t size, int flags, const char *); #define dma_buf_export(priv, ops, size, flags) \ - dma_buf_export_named(priv, ops, size, flags, __FILE__) + dma_buf_export_named(priv, ops, size, flags, KBUILD_MODNAME) int dma_buf_fd(struct dma_buf *dmabuf, int flags); struct dma_buf *dma_buf_get(int fd); -- cgit v1.2.3 From 205e2210daa975d92ace485a65a31ccc4077fe1a Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Wed, 12 Feb 2014 15:15:05 +0200 Subject: iwlwifi: disable TX AMPDU by default for iwldvm NICs supported by iwldvm don't handle well TX AMPDU. Disable it by default, still leave the possibility to the user to force enable it with a debug parameter. NICs supported by iwlmvm don't suffer from the same issue, leave TX AMPDU enabled by default for these. Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/dvm/mac80211.c | 22 ++++++++++++++++++++-- drivers/net/wireless/iwlwifi/iwl-drv.c | 2 +- drivers/net/wireless/iwlwifi/iwl-modparams.h | 11 +++++++---- drivers/net/wireless/iwlwifi/mvm/mac80211.c | 22 ++++++++++++++++++++-- 4 files changed, 48 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c index c24d1d3d55f6..73086c1629ca 100644 --- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c @@ -696,6 +696,24 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, return ret; } +static inline bool iwl_enable_rx_ampdu(const struct iwl_cfg *cfg) +{ + if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_RXAGG) + return false; + return true; +} + +static inline bool iwl_enable_tx_ampdu(const struct iwl_cfg *cfg) +{ + if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG) + return false; + if (iwlwifi_mod_params.disable_11n & IWL_ENABLE_HT_TXAGG) + return true; + + /* disabled by default */ + return false; +} + static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, @@ -717,7 +735,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, switch (action) { case IEEE80211_AMPDU_RX_START: - if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_RXAGG) + if (!iwl_enable_rx_ampdu(priv->cfg)) break; IWL_DEBUG_HT(priv, "start Rx\n"); ret = iwl_sta_rx_agg_start(priv, sta, tid, *ssn); @@ -729,7 +747,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, case IEEE80211_AMPDU_TX_START: if (!priv->trans->ops->txq_enable) break; - if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG) + if (!iwl_enable_tx_ampdu(priv->cfg)) break; IWL_DEBUG_HT(priv, "start Tx\n"); ret = iwlagn_tx_agg_start(priv, vif, sta, tid, ssn); diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c index c3728163be46..75103554cd63 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/iwlwifi/iwl-drv.c @@ -1286,7 +1286,7 @@ module_param_named(swcrypto, iwlwifi_mod_params.sw_crypto, int, S_IRUGO); MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])"); module_param_named(11n_disable, iwlwifi_mod_params.disable_11n, uint, S_IRUGO); MODULE_PARM_DESC(11n_disable, - "disable 11n functionality, bitmap: 1: full, 2: agg TX, 4: agg RX"); + "disable 11n functionality, bitmap: 1: full, 2: disable agg TX, 4: disable agg RX, 8 enable agg TX"); module_param_named(amsdu_size_8K, iwlwifi_mod_params.amsdu_size_8K, int, S_IRUGO); MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size (default 0)"); diff --git a/drivers/net/wireless/iwlwifi/iwl-modparams.h b/drivers/net/wireless/iwlwifi/iwl-modparams.h index 0a84ade7edac..b29075c3da8e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-modparams.h +++ b/drivers/net/wireless/iwlwifi/iwl-modparams.h @@ -79,9 +79,12 @@ enum iwl_power_level { IWL_POWER_NUM }; -#define IWL_DISABLE_HT_ALL BIT(0) -#define IWL_DISABLE_HT_TXAGG BIT(1) -#define IWL_DISABLE_HT_RXAGG BIT(2) +enum iwl_disable_11n { + IWL_DISABLE_HT_ALL = BIT(0), + IWL_DISABLE_HT_TXAGG = BIT(1), + IWL_DISABLE_HT_RXAGG = BIT(2), + IWL_ENABLE_HT_TXAGG = BIT(3), +}; /** * struct iwl_mod_params @@ -90,7 +93,7 @@ enum iwl_power_level { * * @sw_crypto: using hardware encryption, default = 0 * @disable_11n: disable 11n capabilities, default = 0, - * use IWL_DISABLE_HT_* constants + * use IWL_[DIS,EN]ABLE_HT_* constants * @amsdu_size_8K: enable 8K amsdu size, default = 0 * @restart_fw: restart firmware, default = 1 * @wd_disable: enable stuck queue check, default = 0 diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index 6bf9766e5982..c35b8661b395 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -328,6 +328,24 @@ static void iwl_mvm_mac_tx(struct ieee80211_hw *hw, ieee80211_free_txskb(hw, skb); } +static inline bool iwl_enable_rx_ampdu(const struct iwl_cfg *cfg) +{ + if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_RXAGG) + return false; + return true; +} + +static inline bool iwl_enable_tx_ampdu(const struct iwl_cfg *cfg) +{ + if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG) + return false; + if (iwlwifi_mod_params.disable_11n & IWL_ENABLE_HT_TXAGG) + return true; + + /* enabled by default */ + return true; +} + static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, @@ -347,7 +365,7 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw, switch (action) { case IEEE80211_AMPDU_RX_START: - if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_RXAGG) { + if (!iwl_enable_rx_ampdu(mvm->cfg)) { ret = -EINVAL; break; } @@ -357,7 +375,7 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw, ret = iwl_mvm_sta_rx_agg(mvm, sta, tid, 0, false); break; case IEEE80211_AMPDU_TX_START: - if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG) { + if (!iwl_enable_tx_ampdu(mvm->cfg)) { ret = -EINVAL; break; } -- cgit v1.2.3 From 06521c2e4a049504675f64f0a7e6d882fd364bc1 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Wed, 12 Feb 2014 20:19:05 -0700 Subject: ACPI / AC: fix AC driver compile error when CONFIG_PM_SLEEP is undefined MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ACPI AC driver defines acpi_ac_resume() when CONFIG_PM_SLEEP is defined. This results in the following compile error when CONFIG_PM_SLEEP is undefined: drivers/acpi/ac.c:248:8: error: ‘acpi_ac_resume’ undeclared here (not in a function) Signed-off-by: Shuah Khan Signed-off-by: Rafael J. Wysocki --- drivers/acpi/ac.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index e7515aa43d6b..6f190bc2b8b7 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c @@ -243,6 +243,8 @@ static int acpi_ac_resume(struct device *dev) kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE); return 0; } +#else +#define acpi_ac_resume NULL #endif static SIMPLE_DEV_PM_OPS(acpi_ac_pm_ops, NULL, acpi_ac_resume); -- cgit v1.2.3 From 7f6895c60f40354b5adf0320ea5ef8e47cf475c9 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Wed, 12 Feb 2014 20:19:06 -0700 Subject: ACPI / battery: fix battery driver compile error when CONFIG_PM_SLEEP is undefined MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ACPI battery driver defines acpi_battery_resume() when CONFIG_PM_SLEEP is defined. This results in the following compile error when CONFIG_PM_SLEEP is undefined: drivers/acpi/battery.c:847:8: error: ‘acpi_battery_resume’ undeclared here (not in a function) Signed-off-by: Shuah Khan Signed-off-by: Rafael J. Wysocki --- drivers/acpi/battery.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 018a42883706..797a6938d051 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -841,6 +841,8 @@ static int acpi_battery_resume(struct device *dev) acpi_battery_update(battery); return 0; } +#else +#define acpi_battery_resume NULL #endif static SIMPLE_DEV_PM_OPS(acpi_battery_pm, NULL, acpi_battery_resume); -- cgit v1.2.3 From 2de9fd17c0359fea0c2ab5ae393c40d6d299bcaf Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Wed, 12 Feb 2014 20:19:07 -0700 Subject: ACPI / button: fix button driver compile error when CONFIG_PM_SLEEP is undefined MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ACPI button driver defines acpi_button_resume() when CONFIG_PM_SLEEP is defined. This results in the following compile error when CONFIG_PM_SLEEP is undefined: drivers/acpi/button.c:85:8: error: ‘acpi_button_resume’ undeclared here (not in a function) Signed-off-by: Shuah Khan Signed-off-by: Rafael J. Wysocki --- drivers/acpi/button.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index 11c11f6b8fa1..714e957a871a 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -80,6 +80,8 @@ static void acpi_button_notify(struct acpi_device *device, u32 event); #ifdef CONFIG_PM_SLEEP static int acpi_button_resume(struct device *dev); +#else +#define acpi_button_resume NULL #endif static SIMPLE_DEV_PM_OPS(acpi_button_pm, NULL, acpi_button_resume); -- cgit v1.2.3 From b108e0ea94a33f85590959a7a7fbcfd6f8ea8ab6 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Wed, 12 Feb 2014 20:19:08 -0700 Subject: ACPI / fan: fix fan driver compile error when CONFIG_PM_SLEEP is undefined MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ACPI fan driver defines acpi_fan_suspend() and acpi_fan_resume() when CONFIG_PM_SLEEP is defined. This results in the following compile errors when CONFIG_PM_SLEEP is undefined: drivers/acpi/fan.c:60:8: error: ‘acpi_fan_suspend’ undeclared here (not in a function) drivers/acpi/fan.c:60:8: error: ‘acpi_fan_resume’ undeclared here (not in a function) Signed-off-by: Shuah Khan Signed-off-by: Rafael J. Wysocki --- drivers/acpi/fan.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index 1fb62900f32a..09e423f3d8ad 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c @@ -55,6 +55,9 @@ MODULE_DEVICE_TABLE(acpi, fan_device_ids); #ifdef CONFIG_PM_SLEEP static int acpi_fan_suspend(struct device *dev); static int acpi_fan_resume(struct device *dev); +#else +#define acpi_fan_suspend NULL +#define acpi_fan_resume NULL #endif static SIMPLE_DEV_PM_OPS(acpi_fan_pm, acpi_fan_suspend, acpi_fan_resume); -- cgit v1.2.3 From 15029dd7948c4a7adc0860e1750a2a0bba87c473 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Wed, 12 Feb 2014 20:19:09 -0700 Subject: ACPI / SBS: fix SBS driver compile error when CONFIG_PM_SLEEP is undefined MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ACPI SBS driver defines acpi_sbs_resume() when CONFIG_PM_SLEEP is defined. This results in the following compile error when CONFIG_PM_SLEEP is undefined: CC [M] drivers/acpi/sbs.o drivers/acpi/sbs.c:674:8: error: ‘acpi_sbs_resume’ undeclared here (not in a function) Signed-off-by: Shuah Khan Signed-off-by: Rafael J. Wysocki --- drivers/acpi/sbs.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index d465ae6cdd00..48c92c68dda2 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c @@ -668,6 +668,8 @@ static int acpi_sbs_resume(struct device *dev) acpi_sbs_callback(sbs); return 0; } +#else +#define acpi_sbs_resume NULL #endif static SIMPLE_DEV_PM_OPS(acpi_sbs_pm, NULL, acpi_sbs_resume); -- cgit v1.2.3 From fae9e2a4b1c59d11edfa7c99c34293bf9fbf2bde Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Wed, 12 Feb 2014 20:19:10 -0700 Subject: ACPI / thermal: fix thermal driver compile error when CONFIG_PM_SLEEP is undefined MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ACPI thermal driver defines acpi_thermal_resume() when CONFIG_PM_SLEEP is defined. This results in the following compile error when CONFIG_PM_SLEEP is undefined. CC drivers/acpi/thermal.o drivers/acpi/thermal.c:107:8: error: ‘acpi_thermal_resume’ undeclared here (not in a function) make[2]: *** [drivers/acpi/thermal.o] Error 1 Signed-off-by: Shuah Khan Signed-off-by: Rafael J. Wysocki --- drivers/acpi/thermal.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 8349a555b92b..08626c851be7 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -102,6 +102,8 @@ MODULE_DEVICE_TABLE(acpi, thermal_device_ids); #ifdef CONFIG_PM_SLEEP static int acpi_thermal_resume(struct device *dev); +#else +#define acpi_thermal_resume NULL #endif static SIMPLE_DEV_PM_OPS(acpi_thermal_pm, NULL, acpi_thermal_resume); -- cgit v1.2.3 From 32a90512055b300587cceead9127f41e311e01aa Mon Sep 17 00:00:00 2001 From: "Luis G.F" Date: Mon, 10 Feb 2014 11:36:42 +0100 Subject: ACPI / SBS: Fix incorrect sscanf() string Fix incorrect sscanf() string in function acpi_battery_alarm_store(). Signed-off-by: Luis G.F Signed-off-by: Rafael J. Wysocki --- drivers/acpi/sbs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index d465ae6cdd00..02d0c21b807e 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c @@ -450,7 +450,7 @@ static ssize_t acpi_battery_alarm_store(struct device *dev, { unsigned long x; struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev)); - if (sscanf(buf, "%ld\n", &x) == 1) + if (sscanf(buf, "%lu\n", &x) == 1) battery->alarm_capacity = x / (1000 * acpi_battery_scale(battery)); if (battery->present) -- cgit v1.2.3 From 04eada25d1f72efdecd32d702706594f81de65d5 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 11 Feb 2014 11:52:04 +0200 Subject: drm/i915/dp: increase native aux defer retry timeout Give more slack to sink devices before retrying on native aux defer. AFAICT the 100 us timeout was not based on the DP spec. Signed-off-by: Jani Nikula Cc: stable@vger.kernel.org (on Jani's request) Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 2f517b85b3f4..c36960488c89 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -556,7 +556,7 @@ intel_dp_aux_native_write(struct intel_dp *intel_dp, if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_ACK) break; else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER) - udelay(100); + usleep_range(400, 500); else return -EIO; } @@ -608,7 +608,7 @@ intel_dp_aux_native_read(struct intel_dp *intel_dp, return ret - 1; } else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER) - udelay(100); + usleep_range(400, 500); else return -EIO; } -- cgit v1.2.3 From f51a44b9a6c4982cc25bfb3727de9bb893621ebc Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 11 Feb 2014 11:52:05 +0200 Subject: drm/i915/dp: add native aux defer retry limit Retrying indefinitely places too much trust on the aux implementation of the sink devices. Reported-by: Daniel Martin Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=71267 Signed-off-by: Jani Nikula Cc: stable@vger.kernel.org Tested-by: Theodore Ts'o Tested-by: Sree Harsha Totakura Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dp.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index c36960488c89..57552eb386b0 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -537,6 +537,7 @@ intel_dp_aux_native_write(struct intel_dp *intel_dp, uint8_t msg[20]; int msg_bytes; uint8_t ack; + int retry; if (WARN_ON(send_bytes > 16)) return -E2BIG; @@ -548,19 +549,21 @@ intel_dp_aux_native_write(struct intel_dp *intel_dp, msg[3] = send_bytes - 1; memcpy(&msg[4], send, send_bytes); msg_bytes = send_bytes + 4; - for (;;) { + for (retry = 0; retry < 7; retry++) { ret = intel_dp_aux_ch(intel_dp, msg, msg_bytes, &ack, 1); if (ret < 0) return ret; ack >>= 4; if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_ACK) - break; + return send_bytes; else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER) usleep_range(400, 500); else return -EIO; } - return send_bytes; + + DRM_ERROR("too many retries, giving up\n"); + return -EIO; } /* Write a single byte to the aux channel in native mode */ @@ -582,6 +585,7 @@ intel_dp_aux_native_read(struct intel_dp *intel_dp, int reply_bytes; uint8_t ack; int ret; + int retry; if (WARN_ON(recv_bytes > 19)) return -E2BIG; @@ -595,7 +599,7 @@ intel_dp_aux_native_read(struct intel_dp *intel_dp, msg_bytes = 4; reply_bytes = recv_bytes + 1; - for (;;) { + for (retry = 0; retry < 7; retry++) { ret = intel_dp_aux_ch(intel_dp, msg, msg_bytes, reply, reply_bytes); if (ret == 0) @@ -612,6 +616,9 @@ intel_dp_aux_native_read(struct intel_dp *intel_dp, else return -EIO; } + + DRM_ERROR("too many retries, giving up\n"); + return -EIO; } static int -- cgit v1.2.3 From 86bb4f697a964ab5e50f1159e04c6a5d5acde2d4 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 13 Feb 2014 10:47:20 -0700 Subject: PCI/MSI: Check kmalloc() return value, fix leak of name Coverity reported that I forgot to check the return value of kmalloc() when creating the MSI attribute name, so fix that up and properly free it if there is an error when allocating the msi_dev_attr variable. Found by Coverity (CID 1163315 and 1163316). Fixes: 1c51b50c2995 ("PCI/MSI: Export MSI mode using attributes, not kobjects") Signed-off-by: Greg Kroah-Hartman Signed-off-by: Bjorn Helgaas --- drivers/pci/msi.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 7a0fec6ce571..39dff3fe57af 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -545,9 +545,15 @@ static int populate_msi_sysfs(struct pci_dev *pdev) return -ENOMEM; list_for_each_entry(entry, &pdev->msi_list, list) { char *name = kmalloc(20, GFP_KERNEL); + if (!name) + goto error_attrs; + msi_dev_attr = kzalloc(sizeof(*msi_dev_attr), GFP_KERNEL); - if (!msi_dev_attr) + if (!msi_dev_attr) { + kfree(name); goto error_attrs; + } + sprintf(name, "%d", entry->irq); sysfs_attr_init(&msi_dev_attr->attr); msi_dev_attr->attr.name = name; -- cgit v1.2.3 From 29237756477d5e777e39257d94af449fc66026c2 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 13 Feb 2014 10:47:35 -0700 Subject: PCI/MSI: Fix leak of msi_attrs Coverity reported that I forgot to clean up some allocated memory on the error path in populate_msi_sysfs(), so this patch fixes that. Thanks to Dave Jones for pointing out where the error was, I obviously can't read code this morning... Found by Coverity (CID 1163317). Fixes: 1c51b50c2995 ("PCI/MSI: Export MSI mode using attributes, not kobjects") Signed-off-by: Greg Kroah-Hartman Signed-off-by: Bjorn Helgaas Cc: Dave Jones --- drivers/pci/msi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 39dff3fe57af..6f0474ebe420 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -595,6 +595,7 @@ error_attrs: ++count; msi_attr = msi_attrs[count]; } + kfree(msi_attrs); return ret; } -- cgit v1.2.3 From 75ce2d53cef8ea964634583ba45d6323ba5be243 Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Thu, 13 Feb 2014 10:47:44 -0700 Subject: PCI/MSI: Fix pci_msix_vec_count() htmldocs failure An empty line in msi.c caused "make htmldocs" failure: Warning(/home/iida/Repo/linux-next//drivers/pci/msi.c:962): bad line: Fixes: ff1aa430a2fa ("PCI/MSI: Add pci_msix_vec_count()") Signed-off-by: Masanari Iida Signed-off-by: Bjorn Helgaas --- drivers/pci/msi.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 6f0474ebe420..955ab7990c5b 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -966,7 +966,6 @@ EXPORT_SYMBOL(pci_disable_msi); /** * pci_msix_vec_count - return the number of device's MSI-X table entries * @dev: pointer to the pci_dev data structure of MSI-X device function - * This function returns the number of device's MSI-X table entries and * therefore the number of MSI-X vectors device is capable of sending. * It returns a negative errno if the device is not capable of sending MSI-X -- cgit v1.2.3 From 7918b2dc66055772eecac28d7219ea679bdde420 Mon Sep 17 00:00:00 2001 From: Alexander Gordeev Date: Thu, 13 Feb 2014 10:47:51 -0700 Subject: PCI/MSI: Add pci_enable_msi() documentation back We deprecated pci_enable_msi() in 302a2523c277 ("PCI/MSI: Add pci_enable_msi_range() and pci_enable_msix_range()"). But we changed our minds after noticing that: - pci_enable_msi() doesn't have confusing return values like pci_enable_msi_block() and pci_enable_msix() did, and - pci_enable_msi() has a hundred or so callers that we don't want to change. This adds back the pci_enable_msi() documentation. [bhelgaas: changelog] Signed-off-by: Alexander Gordeev Signed-off-by: Bjorn Helgaas --- Documentation/PCI/MSI-HOWTO.txt | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/Documentation/PCI/MSI-HOWTO.txt b/Documentation/PCI/MSI-HOWTO.txt index a8d01005f480..3c3080e9afef 100644 --- a/Documentation/PCI/MSI-HOWTO.txt +++ b/Documentation/PCI/MSI-HOWTO.txt @@ -82,7 +82,19 @@ Most of the hard work is done for the driver in the PCI layer. It simply has to request that the PCI layer set up the MSI capability for this device. -4.2.1 pci_enable_msi_range +4.2.1 pci_enable_msi + +int pci_enable_msi(struct pci_dev *dev) + +A successful call allocates ONE interrupt to the device, regardless +of how many MSIs the device supports. The device is switched from +pin-based interrupt mode to MSI mode. The dev->irq number is changed +to a new number which represents the message signaled interrupt; +consequently, this function should be called before the driver calls +request_irq(), because an MSI is delivered via a vector that is +different from the vector of a pin-based interrupt. + +4.2.2 pci_enable_msi_range int pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec) @@ -158,7 +170,12 @@ static int foo_driver_enable_single_msi(struct pci_dev *pdev) return pci_enable_msi_range(pdev, 1, 1); } -4.2.2 pci_disable_msi +Note, unlike pci_enable_msi() function, which could be also used to +enable the single MSI mode, pci_enable_msi_range() returns either a +negative errno or 1 (not negative errno or 0 - as pci_enable_msi() +does). + +4.2.3 pci_disable_msi void pci_disable_msi(struct pci_dev *dev) @@ -172,7 +189,7 @@ on any interrupt for which it previously called request_irq(). Failure to do so results in a BUG_ON(), leaving the device with MSI enabled and thus leaking its vector. -4.2.3 pci_msi_vec_count +4.2.4 pci_msi_vec_count int pci_msi_vec_count(struct pci_dev *dev) -- cgit v1.2.3 From 13f9653dab9a5d350a560c435a0f3d90ff7905ef Mon Sep 17 00:00:00 2001 From: Alexander Gordeev Date: Thu, 13 Feb 2014 10:47:56 -0700 Subject: PCI/MSI: Fix cut-and-paste errors in documentation Function pci_enable_msi_range() is used in examples where pci_enable_msix_range() should have been used instead. Reported-by: Bjorn Helgaas Signed-off-by: Alexander Gordeev Signed-off-by: Bjorn Helgaas --- Documentation/PCI/MSI-HOWTO.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Documentation/PCI/MSI-HOWTO.txt b/Documentation/PCI/MSI-HOWTO.txt index 3c3080e9afef..96ee5eb9d4d4 100644 --- a/Documentation/PCI/MSI-HOWTO.txt +++ b/Documentation/PCI/MSI-HOWTO.txt @@ -274,8 +274,8 @@ possible, likely up to the limit returned by pci_msix_vec_count() function: static int foo_driver_enable_msix(struct foo_adapter *adapter, int nvec) { - return pci_enable_msi_range(adapter->pdev, adapter->msix_entries, - 1, nvec); + return pci_enable_msix_range(adapter->pdev, adapter->msix_entries, + 1, nvec); } Note the value of 'minvec' parameter is 1. As 'minvec' is inclusive, @@ -286,8 +286,8 @@ In this case the function could look like this: static int foo_driver_enable_msix(struct foo_adapter *adapter, int nvec) { - return pci_enable_msi_range(adapter->pdev, adapter->msix_entries, - FOO_DRIVER_MINIMUM_NVEC, nvec); + return pci_enable_msix_range(adapter->pdev, adapter->msix_entries, + FOO_DRIVER_MINIMUM_NVEC, nvec); } 4.3.1.2 Exact number of MSI-X interrupts @@ -299,8 +299,8 @@ parameters: static int foo_driver_enable_msix(struct foo_adapter *adapter, int nvec) { - return pci_enable_msi_range(adapter->pdev, adapter->msix_entries, - nvec, nvec); + return pci_enable_msix_range(adapter->pdev, adapter->msix_entries, + nvec, nvec); } 4.3.1.3 Specific requirements to the number of MSI-X interrupts -- cgit v1.2.3 From 3ce4e860e578f843db36a1f7357ba00aeaa7610f Mon Sep 17 00:00:00 2001 From: Alexander Gordeev Date: Thu, 13 Feb 2014 10:48:02 -0700 Subject: PCI/MSI: Add pci_enable_msi_exact() and pci_enable_msix_exact() The new functions are special cases for pci_enable_msi_range() and pci_enable_msix_range() when a particular number of MSI or MSI-X is needed. By contrast with pci_enable_msi_range() and pci_enable_msix_range() functions, pci_enable_msi_exact() and pci_enable_msix_exact() return zero in case of success, which indicates MSI or MSI-X interrupts have been successfully allocated. Signed-off-by: Alexander Gordeev Signed-off-by: Bjorn Helgaas --- Documentation/PCI/MSI-HOWTO.txt | 86 ++++++++++++++++++++++++++++++++++++++++- include/linux/pci.h | 20 ++++++++++ 2 files changed, 104 insertions(+), 2 deletions(-) diff --git a/Documentation/PCI/MSI-HOWTO.txt b/Documentation/PCI/MSI-HOWTO.txt index 96ee5eb9d4d4..10a93696e55a 100644 --- a/Documentation/PCI/MSI-HOWTO.txt +++ b/Documentation/PCI/MSI-HOWTO.txt @@ -159,6 +159,11 @@ static int foo_driver_enable_msi(struct pci_dev *pdev, int nvec) return pci_enable_msi_range(pdev, nvec, nvec); } +Note, unlike pci_enable_msi_exact() function, which could be also used to +enable a particular number of MSI-X interrupts, pci_enable_msi_range() +returns either a negative errno or 'nvec' (not negative errno or 0 - as +pci_enable_msi_exact() does). + 4.2.1.3 Single MSI mode The most notorious example of the request type described above is @@ -175,7 +180,22 @@ enable the single MSI mode, pci_enable_msi_range() returns either a negative errno or 1 (not negative errno or 0 - as pci_enable_msi() does). -4.2.3 pci_disable_msi +4.2.3 pci_enable_msi_exact + +int pci_enable_msi_exact(struct pci_dev *dev, int nvec) + +This variation on pci_enable_msi_range() call allows a device driver to +request exactly 'nvec' MSIs. + +If this function returns a negative number, it indicates an error and +the driver should not attempt to request any more MSI interrupts for +this device. + +By contrast with pci_enable_msi_range() function, pci_enable_msi_exact() +returns zero in case of success, which indicates MSI interrupts have been +successfully allocated. + +4.2.4 pci_disable_msi void pci_disable_msi(struct pci_dev *dev) @@ -303,6 +323,11 @@ static int foo_driver_enable_msix(struct foo_adapter *adapter, int nvec) nvec, nvec); } +Note, unlike pci_enable_msix_exact() function, which could be also used to +enable a particular number of MSI-X interrupts, pci_enable_msix_range() +returns either a negative errno or 'nvec' (not negative errno or 0 - as +pci_enable_msix_exact() does). + 4.3.1.3 Specific requirements to the number of MSI-X interrupts As noted above, there could be devices that can not operate with just any @@ -349,7 +374,64 @@ Note how pci_enable_msix_range() return value is analized for a fallback - any error code other than -ENOSPC indicates a fatal error and should not be retried. -4.3.2 pci_disable_msix +4.3.2 pci_enable_msix_exact + +int pci_enable_msix_exact(struct pci_dev *dev, + struct msix_entry *entries, int nvec) + +This variation on pci_enable_msix_range() call allows a device driver to +request exactly 'nvec' MSI-Xs. + +If this function returns a negative number, it indicates an error and +the driver should not attempt to allocate any more MSI-X interrupts for +this device. + +By contrast with pci_enable_msix_range() function, pci_enable_msix_exact() +returns zero in case of success, which indicates MSI-X interrupts have been +successfully allocated. + +Another version of a routine that enables MSI-X mode for a device with +specific requirements described in chapter 4.3.1.3 might look like this: + +/* + * Assume 'minvec' and 'maxvec' are non-zero + */ +static int foo_driver_enable_msix(struct foo_adapter *adapter, + int minvec, int maxvec) +{ + int rc; + + minvec = roundup_pow_of_two(minvec); + maxvec = rounddown_pow_of_two(maxvec); + + if (minvec > maxvec) + return -ERANGE; + +retry: + rc = pci_enable_msix_exact(adapter->pdev, + adapter->msix_entries, maxvec); + + /* + * -ENOSPC is the only error code allowed to be analyzed + */ + if (rc == -ENOSPC) { + if (maxvec == 1) + return -ENOSPC; + + maxvec /= 2; + + if (minvec > maxvec) + return -ENOSPC; + + goto retry; + } else if (rc < 0) { + return rc; + } + + return maxvec; +} + +4.3.3 pci_disable_msix void pci_disable_msix(struct pci_dev *dev) diff --git a/include/linux/pci.h b/include/linux/pci.h index fb57c892b214..33aa2caf0f0c 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1169,8 +1169,23 @@ void msi_remove_pci_irq_vectors(struct pci_dev *dev); void pci_restore_msi_state(struct pci_dev *dev); int pci_msi_enabled(void); int pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec); +static inline int pci_enable_msi_exact(struct pci_dev *dev, int nvec) +{ + int rc = pci_enable_msi_range(dev, nvec, nvec); + if (rc < 0) + return rc; + return 0; +} int pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries, int minvec, int maxvec); +static inline int pci_enable_msix_exact(struct pci_dev *dev, + struct msix_entry *entries, int nvec) +{ + int rc = pci_enable_msix_range(dev, entries, nvec, nvec); + if (rc < 0) + return rc; + return 0; +} #else static inline int pci_msi_vec_count(struct pci_dev *dev) { return -ENOSYS; } static inline int pci_enable_msi_block(struct pci_dev *dev, int nvec) @@ -1189,9 +1204,14 @@ static inline int pci_msi_enabled(void) { return 0; } static inline int pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec) { return -ENOSYS; } +static inline int pci_enable_msi_exact(struct pci_dev *dev, int nvec) +{ return -ENOSYS; } static inline int pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries, int minvec, int maxvec) { return -ENOSYS; } +static inline int pci_enable_msix_exact(struct pci_dev *dev, + struct msix_entry *entries, int nvec) +{ return -ENOSYS; } #endif #ifdef CONFIG_PCIEPORTBUS -- cgit v1.2.3 From 4e52c03dfcdef5ad1415e18af0e7230d98ff3a7c Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 13 Feb 2014 17:05:06 +0530 Subject: regulator: s5m8767: Use of_get_child_by_name of_find_node_by_name walks the allnodes list, and can thus walk outside of the parent node. Use of_get_child_by_name instead. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- drivers/regulator/s5m8767.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c index d7164bb75d3e..092d44e5db4e 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c @@ -535,7 +535,7 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev, return -ENODEV; } - regulators_np = of_find_node_by_name(pmic_np, "regulators"); + regulators_np = of_get_child_by_name(pmic_np, "regulators"); if (!regulators_np) { dev_err(iodev->dev, "could not find regulators sub-node\n"); return -EINVAL; -- cgit v1.2.3 From b7db01f3b3b86f6b02a98756a051d176610ca0f1 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 13 Feb 2014 17:05:07 +0530 Subject: regulator: s5m8767: Add missing of_node_put Add of_node_put to decrement the ref count. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- drivers/regulator/s5m8767.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c index 092d44e5db4e..d958dfa05125 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c @@ -591,6 +591,8 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev, rmode++; } + of_node_put(regulators_np); + if (of_get_property(pmic_np, "s5m8767,pmic-buck2-uses-gpio-dvs", NULL)) { pdata->buck2_gpiodvs = true; -- cgit v1.2.3 From 71c68c4fc9bdcd6e46107a0f40b50a523f3b4fe0 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 12 Feb 2014 22:47:51 -0500 Subject: drm/i2c: tda998x: Fix memory leak in tda998x_encoder_init error path. Commit 6ae668cc19e8 (drm/i2c: tda998x: check the CEC device creation) introduced a memory leak in the error path of tda998x_encoder_init Picked up by the nightly Coverity scan. CID 1174076 Signed-off-by: Dave Jones Acked-by: Jean-Francois Moine Signed-off-by: Russell King --- drivers/gpu/drm/i2c/tda998x_drv.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c index fa18cf374470..faa77f543a07 100644 --- a/drivers/gpu/drm/i2c/tda998x_drv.c +++ b/drivers/gpu/drm/i2c/tda998x_drv.c @@ -1151,8 +1151,10 @@ tda998x_encoder_init(struct i2c_client *client, priv->current_page = 0xff; priv->cec = i2c_new_dummy(client->adapter, 0x34); - if (!priv->cec) + if (!priv->cec) { + kfree(priv); return -ENODEV; + } priv->dpms = DRM_MODE_DPMS_OFF; encoder_slave->slave_priv = priv; -- cgit v1.2.3 From f78bccd79ba3cd9d9664981b501d57bdb81ab8a4 Mon Sep 17 00:00:00 2001 From: Olivier Langlois Date: Sat, 1 Feb 2014 01:11:09 -0500 Subject: rtlwifi: rtl8192ce: Fix too long disable of IRQs rtl8192ce is disabling for too long the local interrupts during hw initiatialisation when performing scans The observable symptoms in dmesg can be: - underruns from ALSA playback - clock freezes (tstamps do not change for several dmesg entries until irqs are finaly reenabled): [ 250.817669] rtlwifi:rtl_op_config():<0-0-0> 0x100 [ 250.817685] rtl8192ce:_rtl92ce_phy_set_rf_power_state():<0-1-0> IPS Set eRf nic enable [ 250.817732] rtl8192ce:_rtl92ce_init_mac():<0-1-0> reg0xec:18051d59:11 [ 250.817796] rtl8192ce:_rtl92ce_init_mac():<0-1-0> reg0xec:18051d59:11 [ 250.817910] rtl8192ce:_rtl92ce_init_mac():<0-1-0> reg0xec:18051d59:11 [ 250.818024] rtl8192ce:_rtl92ce_init_mac():<0-1-0> reg0xec:18051d59:11 [ 250.818139] rtl8192ce:_rtl92ce_init_mac():<0-1-0> reg0xec:18051d59:11 [ 250.818253] rtl8192ce:_rtl92ce_init_mac():<0-1-0> reg0xec:18051d59:11 [ 250.818367] rtl8192ce:_rtl92ce_init_mac():<0-1-0> reg0xec:18051d59:11 [ 250.818472] rtl8192ce:_rtl92ce_init_mac():<0-1-0> reg0xec:18051d59:11 [ 250.818472] rtl8192ce:_rtl92ce_init_mac():<0-1-0> reg0xec:18051d59:11 [ 250.818472] rtl8192ce:_rtl92ce_init_mac():<0-1-0> reg0xec:18051d59:11 [ 250.818472] rtl8192ce:_rtl92ce_init_mac():<0-1-0> reg0xec:18051d59:11 [ 250.818472] rtl8192ce:_rtl92ce_init_mac():<0-1-0> reg0xec:98053f15:10 [ 250.818472] rtl8192ce:rtl92ce_sw_led_on():<0-1-0> LedAddr:4E ledpin=1 [ 250.818472] rtl8192c_common:rtl92c_download_fw():<0-1-0> Firmware Version(49), Signature(0x88c1),Size(32) [ 250.818472] rtl8192ce:rtl92ce_enable_hw_security_config():<0-1-0> PairwiseEncAlgorithm = 0 GroupEncAlgorithm = 0 [ 250.818472] rtl8192ce:rtl92ce_enable_hw_security_config():<0-1-0> The SECR-value cc [ 250.818472] rtl8192c_common:rtl92c_dm_check_txpower_tracking_thermal_meter():<0-1-0> Schedule TxPowerTracking direct call!! [ 250.818472] rtl8192c_common:rtl92c_dm_txpower_tracking_callback_thermalmeter():<0-1-0> rtl92c_dm_txpower_tracking_callback_thermalmeter [ 250.818472] rtl8192c_common:rtl92c_dm_txpower_tracking_callback_thermalmeter():<0-1-0> Readback Thermal Meter = 0xe pre thermal meter 0xf eeprom_thermalmeter 0xf [ 250.818472] rtl8192c_common:rtl92c_dm_txpower_tracking_callback_thermalmeter():<0-1-0> Initial pathA ele_d reg0xc80 = 0x40000000, ofdm_index=0xc [ 250.818472] rtl8192c_common:rtl92c_dm_txpower_tracking_callback_thermalmeter():<0-1-0> Initial reg0xa24 = 0x90e1317, cck_index=0xc, ch14 0 [ 250.818472] rtl8192c_common:rtl92c_dm_txpower_tracking_callback_thermalmeter():<0-1-0> Readback Thermal Meter = 0xe pre thermal meter 0xf eeprom_thermalmeter 0xf delta 0x1 delta_lck 0x0 delta_iqk 0x0 [ 250.818472] rtl8192c_common:rtl92c_dm_txpower_tracking_callback_thermalmeter():<0-1-0> <=== [ 250.818472] rtl8192c_common:rtl92c_dm_initialize_txpower_tracking_thermalmeter():<0-1-0> pMgntInfo->txpower_tracking = 1 [ 250.818472] rtl8192ce:rtl92ce_led_control():<0-1-0> ledaction 3 [ 250.818472] rtl8192ce:rtl92ce_sw_led_on():<0-1-0> LedAddr:4E ledpin=1 [ 250.818472] rtlwifi:rtl_ips_nic_on():<0-1-0> before spin_unlock_irqrestore [ 251.154656] PCM: Lost interrupts? [Q]-0 (stream=0, delta=15903, new_hw_ptr=293408, old_hw_ptr=277505) The exact code flow that causes that is: 1. wpa_supplicant send a start_scan request to the nl80211 driver 2. mac80211 module call rtl_op_config with IEEE80211_CONF_CHANGE_IDLE 3. rtl_ips_nic_on is called which disable local irqs 4. rtl92c_phy_set_rf_power_state() is called 5. rtl_ps_enable_nic() is called and hw_init()is executed and then the interrupts on the device are enabled A good solution could be to refactor the code to avoid calling rtl92ce_hw_init() with the irqs disabled but a quick and dirty solution that has proven to work is to reenable the irqs during the function rtl92ce_hw_init(). I think that it is safe doing so since the device interrupt will only be enabled after the init function succeed. Signed-off-by: Olivier Langlois Cc: Stable Acked-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/rtl8192ce/hw.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c index a82b30a1996c..2eb0b38384dd 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c @@ -937,14 +937,26 @@ int rtl92ce_hw_init(struct ieee80211_hw *hw) bool is92c; int err; u8 tmp_u1b; + unsigned long flags; rtlpci->being_init_adapter = true; + + /* Since this function can take a very long time (up to 350 ms) + * and can be called with irqs disabled, reenable the irqs + * to let the other devices continue being serviced. + * + * It is safe doing so since our own interrupts will only be enabled + * in a subsequent step. + */ + local_save_flags(flags); + local_irq_enable(); + rtlpriv->intf_ops->disable_aspm(hw); rtstatus = _rtl92ce_init_mac(hw); if (!rtstatus) { RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Init MAC failed\n"); err = 1; - return err; + goto exit; } err = rtl92c_download_fw(hw); @@ -952,7 +964,7 @@ int rtl92ce_hw_init(struct ieee80211_hw *hw) RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, "Failed to download FW. Init HW without FW now..\n"); err = 1; - return err; + goto exit; } rtlhal->last_hmeboxnum = 0; @@ -1032,6 +1044,8 @@ int rtl92ce_hw_init(struct ieee80211_hw *hw) RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "under 1.5V\n"); } rtl92c_dm_init(hw); +exit: + local_irq_restore(flags); rtlpci->being_init_adapter = false; return err; } -- cgit v1.2.3 From 2e8c5e56b307271c2dab6f8bfd1d8a3822ca2390 Mon Sep 17 00:00:00 2001 From: Olivier Langlois Date: Sat, 1 Feb 2014 01:11:10 -0500 Subject: rtlwifi: Fix incorrect return from rtl_ps_enable_nic() rtl_ps_enable_nic() is called from loops that will loop until this function returns true or a maximum number of retries is performed. hw_init() returns non-zero on error. In that situation return false to restore the original design intent to retry hw init when it fails. Signed-off-by: Olivier Langlois Cc: Stable Acked-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/ps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rtlwifi/ps.c b/drivers/net/wireless/rtlwifi/ps.c index deedae3c5449..d1c0191a195b 100644 --- a/drivers/net/wireless/rtlwifi/ps.c +++ b/drivers/net/wireless/rtlwifi/ps.c @@ -48,7 +48,7 @@ bool rtl_ps_enable_nic(struct ieee80211_hw *hw) /*<2> Enable Adapter */ if (rtlpriv->cfg->ops->hw_init(hw)) - return 1; + return false; RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); /*<3> Enable Interrupt */ -- cgit v1.2.3 From 4a0732d1f93ff52b0e74a61302260b9417f6db61 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 7 Feb 2014 14:50:38 +0300 Subject: ath5k: shifting the wrong variable for AR5K_AR5210 In the original code we shift "AR5K_PHY(256) >> 28" which is zero but the intent was to shift the return value of ath5k_hw_reg_read() like we do a couple lines later. Signed-off-by: Dan Carpenter Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/phy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index d6bc7cb61bfb..1a2973b7acf2 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -110,7 +110,7 @@ ath5k_hw_radio_revision(struct ath5k_hw *ah, enum ieee80211_band band) ath5k_hw_reg_write(ah, 0x00010000, AR5K_PHY(0x20)); if (ah->ah_version == AR5K_AR5210) { - srev = ath5k_hw_reg_read(ah, AR5K_PHY(256) >> 28) & 0xf; + srev = (ath5k_hw_reg_read(ah, AR5K_PHY(256)) >> 28) & 0xf; ret = (u16)ath5k_hw_bitswap(srev, 4) + 1; } else { srev = (ath5k_hw_reg_read(ah, AR5K_PHY(0x100)) >> 24) & 0xff; -- cgit v1.2.3 From b6213e413a4e0c66548153516b074df14f9d08e0 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Mon, 10 Feb 2014 22:38:28 +0100 Subject: rtl8187: fix regression on MIPS without coherent DMA This patch fixes regression caused by commit a16dad77634 "MIPS: Fix potencial corruption". That commit fixes one corruption scenario in cost of adding another one, which actually start to cause crashes on Yeeloong laptop when rtl8187 driver is used. For correct DMA read operation on machines without DMA coherence, kernel have to invalidate cache, such it will refill later with new data that device wrote to memory, when that data is needed to process. We can only invalidate full cache line. Hence when cache line includes both dma buffer and some other data (written in cache, but not yet in main memory), the other data can not hit memory due to invalidation. That happen on rtl8187 where struct rtl8187_priv fields are located just before and after small buffers that are passed to USB layer and DMA is performed on them. To fix the problem we align buffers and reserve space after them to make them match cache line. This patch does not resolve all possible MIPS problems entirely, for that we have to assure that we always map cache aligned buffers for DMA, what can be complex or even not possible. But patch fixes visible and reproducible regression and seems other possible corruptions do not happen in practice, since Yeeloong laptop works stable without rtl8187 driver. Bug report: https://bugzilla.kernel.org/show_bug.cgi?id=54391 Reported-by: Petr Pisar Bisected-by: Tom Li Reported-and-tested-by: Tom Li Cc: stable@vger.kernel.org Signed-off-by: Stanislaw Gruszka Acked-by: Larry Finger Acked-by: Hin-Tak Leung Signed-off-by: John W. Linville --- drivers/net/wireless/rtl818x/rtl8187/rtl8187.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h b/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h index 56aee067f324..a6ad79f61bf9 100644 --- a/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h +++ b/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h @@ -15,6 +15,8 @@ #ifndef RTL8187_H #define RTL8187_H +#include + #include "rtl818x.h" #include "leds.h" @@ -139,7 +141,10 @@ struct rtl8187_priv { u8 aifsn[4]; u8 rfkill_mask; struct { - __le64 buf; + union { + __le64 buf; + u8 dummy1[L1_CACHE_BYTES]; + } ____cacheline_aligned; struct sk_buff_head queue; } b_tx_status; /* This queue is used by both -b and non-b devices */ struct mutex io_mutex; @@ -147,7 +152,8 @@ struct rtl8187_priv { u8 bits8; __le16 bits16; __le32 bits32; - } *io_dmabuf; + u8 dummy2[L1_CACHE_BYTES]; + } *io_dmabuf ____cacheline_aligned; bool rfkill_off; u16 seqno; }; -- cgit v1.2.3 From 4885c8731a34eecf509822e089ce17bcd9bd4650 Mon Sep 17 00:00:00 2001 From: Russell King - ARM Linux Date: Wed, 12 Feb 2014 22:38:17 +0000 Subject: hostap: fix "hostap: proc: Use remove_proc_subtree()" remove_proc_subtree() doesn't work here as local->ddev has already been removed, and NULLed out. Use proc_remove() instead. Signed-off-by: Russell King Tested-by: Russell King Signed-off-by: John W. Linville --- drivers/net/wireless/hostap/hostap_proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/hostap/hostap_proc.c b/drivers/net/wireless/hostap/hostap_proc.c index aa7ad3a7a69b..4e5c0f8c9496 100644 --- a/drivers/net/wireless/hostap/hostap_proc.c +++ b/drivers/net/wireless/hostap/hostap_proc.c @@ -496,7 +496,7 @@ void hostap_init_proc(local_info_t *local) void hostap_remove_proc(local_info_t *local) { - remove_proc_subtree(local->ddev->name, hostap_proc); + proc_remove(local->proc); } -- cgit v1.2.3 From 844ae5b46c08dbc7ba695b543c023f9cf3bbf9ff Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 10 Feb 2014 14:09:48 -0300 Subject: perf trace: Fix ioctl 'request' beautifier build problems on !(i386 || x86_64) arches Supporting decoding the ioctl 'request' parameter needs more work to properly support more architectures, the current approach doesn't work on at least powerpc and sparc, as reported by Ben Hutchings in http://lkml.kernel.org/r/1391593985.3003.48.camel@deadeye.wl.decadent.org.uk . Work around that by making it to be ifdefed for the architectures known to work with the current, limited approach, i386 and x86_64 till better code is written. Reported-by: Ben Hutchings Acked-by: Ben Hutchings Cc: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Cc: # 3.13 Fixes: 78645cf3ed32 ("perf trace: Initial beautifier for ioctl's 'cmd' arg") Link: http://lkml.kernel.org/n/tip-ss04k11insqlu329xh5g02q0@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 619d11c47a91..6aa6fb6f7bd9 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -283,6 +283,11 @@ static size_t syscall_arg__scnprintf_strarray(char *bf, size_t size, #define SCA_STRARRAY syscall_arg__scnprintf_strarray +#if defined(__i386__) || defined(__x86_64__) +/* + * FIXME: Make this available to all arches as soon as the ioctl beautifier + * gets rewritten to support all arches. + */ static size_t syscall_arg__scnprintf_strhexarray(char *bf, size_t size, struct syscall_arg *arg) { @@ -290,6 +295,7 @@ static size_t syscall_arg__scnprintf_strhexarray(char *bf, size_t size, } #define SCA_STRHEXARRAY syscall_arg__scnprintf_strhexarray +#endif /* defined(__i386__) || defined(__x86_64__) */ static size_t syscall_arg__scnprintf_fd(char *bf, size_t size, struct syscall_arg *arg); @@ -843,6 +849,10 @@ static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscal #define SCA_SIGNUM syscall_arg__scnprintf_signum +#if defined(__i386__) || defined(__x86_64__) +/* + * FIXME: Make this available to all arches. + */ #define TCGETS 0x5401 static const char *tioctls[] = { @@ -864,6 +874,7 @@ static const char *tioctls[] = { }; static DEFINE_STRARRAY_OFFSET(tioctls, 0x5401); +#endif /* defined(__i386__) || defined(__x86_64__) */ #define STRARRAY(arg, name, array) \ .arg_scnprintf = { [arg] = SCA_STRARRAY, }, \ @@ -945,9 +956,16 @@ static struct syscall_fmt { { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), }, { .name = "ioctl", .errmsg = true, .arg_scnprintf = { [0] = SCA_FD, /* fd */ +#if defined(__i386__) || defined(__x86_64__) +/* + * FIXME: Make this available to all arches. + */ [1] = SCA_STRHEXARRAY, /* cmd */ [2] = SCA_HEX, /* arg */ }, .arg_parm = { [1] = &strarray__tioctls, /* cmd */ }, }, +#else + [2] = SCA_HEX, /* arg */ }, }, +#endif { .name = "kill", .errmsg = true, .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, }, { .name = "linkat", .errmsg = true, -- cgit v1.2.3 From c7966b525fc6af6d18a509b33f938312f59b57f5 Mon Sep 17 00:00:00 2001 From: Jan Luebbe Date: Mon, 10 Feb 2014 21:40:51 +0100 Subject: net: fix macvtap type name in Kconfig The netlink kind (and iproute2 type option) is actually called 'macvtap', not 'macvlan'. Signed-off-by: Jan Luebbe Signed-off-by: David S. Miller --- drivers/net/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index f342278539d5..494b888a6568 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -139,7 +139,7 @@ config MACVTAP This adds a specialized tap character device driver that is based on the MAC-VLAN network interface, called macvtap. A macvtap device can be added in the same way as a macvlan device, using 'type - macvlan', and then be accessed through the tap user space interface. + macvtap', and then be accessed through the tap user space interface. To compile this driver as a module, choose M here: the module will be called macvtap. -- cgit v1.2.3 From d15891ca1fdd7f1f46cede1dc15bcfbf0445a658 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Tue, 11 Feb 2014 09:59:57 +0000 Subject: net: stmmac:sti: Add STi SOC glue driver. STi series SOCs have a glue layer on top of the synopsis gmac IP, this glue layer needs to be configured before the gmac driver starts using the IP. This patch adds a support to this glue layer which is configured via stmmac setup, init, exit callbacks. Signed-off-by: Srinivas Kandagatla Signed-off-by: David S. Miller --- .../devicetree/bindings/net/sti-dwmac.txt | 58 ++++ drivers/net/ethernet/stmicro/stmmac/Kconfig | 11 + drivers/net/ethernet/stmicro/stmmac/Makefile | 1 + drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c | 330 +++++++++++++++++++++ drivers/net/ethernet/stmicro/stmmac/stmmac.h | 3 + .../net/ethernet/stmicro/stmmac/stmmac_platform.c | 5 + 6 files changed, 408 insertions(+) create mode 100644 Documentation/devicetree/bindings/net/sti-dwmac.txt create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c diff --git a/Documentation/devicetree/bindings/net/sti-dwmac.txt b/Documentation/devicetree/bindings/net/sti-dwmac.txt new file mode 100644 index 000000000000..3dd3d0bf112f --- /dev/null +++ b/Documentation/devicetree/bindings/net/sti-dwmac.txt @@ -0,0 +1,58 @@ +STMicroelectronics SoC DWMAC glue layer controller + +The device node has following properties. + +Required properties: + - compatible : Can be "st,stih415-dwmac", "st,stih416-dwmac" or + "st,stid127-dwmac". + - reg : Offset of the glue configuration register map in system + configuration regmap pointed by st,syscon property and size. + + - reg-names : Should be "sti-ethconf". + + - st,syscon : Should be phandle to system configuration node which + encompases this glue registers. + + - st,tx-retime-src: On STi Parts for Giga bit speeds, 125Mhz clocks can be + wired up in from different sources. One via TXCLK pin and other via CLK_125 + pin. This wiring is totally board dependent. However the retiming glue + logic should be configured accordingly. Possible values for this property + + "txclk" - if 125Mhz clock is wired up via txclk line. + "clk_125" - if 125Mhz clock is wired up via clk_125 line. + + This property is only valid for Giga bit setup( GMII, RGMII), and it is + un-used for non-giga bit (MII and RMII) setups. Also note that internal + clockgen can not generate stable 125Mhz clock. + + - st,ext-phyclk: This boolean property indicates who is generating the clock + for tx and rx. This property is only valid for RMII case where the clock can + be generated from the MAC or PHY. + + - clock-names: should be "sti-ethclk". + - clocks: Should point to ethernet clockgen which can generate phyclk. + + +Example: + +ethernet0: dwmac@fe810000 { + device_type = "network"; + compatible = "st,stih416-dwmac", "snps,dwmac", "snps,dwmac-3.710"; + reg = <0xfe810000 0x8000>, <0x8bc 0x4>; + reg-names = "stmmaceth", "sti-ethconf"; + interrupts = <0 133 0>, <0 134 0>, <0 135 0>; + interrupt-names = "macirq", "eth_wake_irq", "eth_lpi"; + phy-mode = "mii"; + + st,syscon = <&syscfg_rear>; + + snps,pbl = <32>; + snps,mixed-burst; + + resets = <&softreset STIH416_ETH0_SOFTRESET>; + reset-names = "stmmaceth"; + pinctrl-0 = <&pinctrl_mii0>; + pinctrl-names = "default"; + clocks = <&CLK_S_GMAC0_PHY>; + clock-names = "stmmaceth"; +}; diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig index e2f202e3932f..f2d7c702c77f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig @@ -37,6 +37,17 @@ config DWMAC_SUNXI stmmac device driver. This driver is used for A20/A31 GMAC ethernet controller. +config DWMAC_STI + bool "STi GMAC support" + depends on STMMAC_PLATFORM && ARCH_STI + default y + ---help--- + Support for ethernet controller on STi SOCs. + + This selects STi SoC glue layer support for the stmmac + device driver. This driver is used on for the STi series + SOCs GMAC ethernet controller. + config STMMAC_PCI bool "STMMAC PCI bus support" depends on STMMAC_ETH && PCI diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile index ecadecea79b2..dcef28775dad 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Makefile +++ b/drivers/net/ethernet/stmicro/stmmac/Makefile @@ -2,6 +2,7 @@ obj-$(CONFIG_STMMAC_ETH) += stmmac.o stmmac-$(CONFIG_STMMAC_PLATFORM) += stmmac_platform.o stmmac-$(CONFIG_STMMAC_PCI) += stmmac_pci.o stmmac-$(CONFIG_DWMAC_SUNXI) += dwmac-sunxi.o +stmmac-$(CONFIG_DWMAC_STI) += dwmac-sti.o stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o \ chain_mode.o dwmac_lib.o dwmac1000_core.o dwmac1000_dma.o \ dwmac100_core.o dwmac100_dma.o enh_desc.o norm_desc.o \ diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c new file mode 100644 index 000000000000..552bbc17863c --- /dev/null +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c @@ -0,0 +1,330 @@ +/** + * dwmac-sti.c - STMicroelectronics DWMAC Specific Glue layer + * + * Copyright (C) 2003-2014 STMicroelectronics (R&D) Limited + * Author: Srinivas Kandagatla + * + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * STi GMAC glue logic. + * -------------------- + * + * _ + * | \ + * --------|0 \ ETH_SEL_INTERNAL_NOTEXT_PHYCLK + * phyclk | |___________________________________________ + * | | | (phyclk-in) + * --------|1 / | + * int-clk |_ / | + * | _ + * | | \ + * |_______|1 \ ETH_SEL_TX_RETIME_CLK + * | |___________________________ + * | | (tx-retime-clk) + * _______|0 / + * | |_ / + * _ | + * | \ | + * --------|0 \ | + * clk_125 | |__| + * | | ETH_SEL_TXCLK_NOT_CLK125 + * --------|1 / + * txclk |_ / + * + * + * ETH_SEL_INTERNAL_NOTEXT_PHYCLK is valid only for RMII where PHY can + * generate 50MHz clock or MAC can generate it. + * This bit is configured by "st,ext-phyclk" property. + * + * ETH_SEL_TXCLK_NOT_CLK125 is only valid for gigabit modes, where the 125Mhz + * clock either comes from clk-125 pin or txclk pin. This configuration is + * totally driven by the board wiring. This bit is configured by + * "st,tx-retime-src" property. + * + * TXCLK configuration is different for different phy interface modes + * and changes according to link speed in modes like RGMII. + * + * Below table summarizes the clock requirement and clock sources for + * supported phy interface modes with link speeds. + * ________________________________________________ + *| PHY_MODE | 1000 Mbit Link | 100 Mbit Link | + * ------------------------------------------------ + *| MII | n/a | 25Mhz | + *| | | txclk | + * ------------------------------------------------ + *| GMII | 125Mhz | 25Mhz | + *| | clk-125/txclk | txclk | + * ------------------------------------------------ + *| RGMII | 125Mhz | 25Mhz | + *| | clk-125/txclk | clkgen | + * ------------------------------------------------ + *| RMII | n/a | 25Mhz | + *| | |clkgen/phyclk-in | + * ------------------------------------------------ + * + * TX lines are always retimed with a clk, which can vary depending + * on the board configuration. Below is the table of these bits + * in eth configuration register depending on source of retime clk. + * + *--------------------------------------------------------------- + * src | tx_rt_clk | int_not_ext_phyclk | txclk_n_clk125| + *--------------------------------------------------------------- + * txclk | 0 | n/a | 1 | + *--------------------------------------------------------------- + * ck_125| 0 | n/a | 0 | + *--------------------------------------------------------------- + * phyclk| 1 | 0 | n/a | + *--------------------------------------------------------------- + * clkgen| 1 | 1 | n/a | + *--------------------------------------------------------------- + */ + + /* Register definition */ + + /* 3 bits [8:6] + * [6:6] ETH_SEL_TXCLK_NOT_CLK125 + * [7:7] ETH_SEL_INTERNAL_NOTEXT_PHYCLK + * [8:8] ETH_SEL_TX_RETIME_CLK + * + */ + +#define TX_RETIME_SRC_MASK GENMASK(8, 6) +#define ETH_SEL_TX_RETIME_CLK BIT(8) +#define ETH_SEL_INTERNAL_NOTEXT_PHYCLK BIT(7) +#define ETH_SEL_TXCLK_NOT_CLK125 BIT(6) + +#define ENMII_MASK GENMASK(5, 5) +#define ENMII BIT(5) + +/** + * 3 bits [4:2] + * 000-GMII/MII + * 001-RGMII + * 010-SGMII + * 100-RMII +*/ +#define MII_PHY_SEL_MASK GENMASK(4, 2) +#define ETH_PHY_SEL_RMII BIT(4) +#define ETH_PHY_SEL_SGMII BIT(3) +#define ETH_PHY_SEL_RGMII BIT(2) +#define ETH_PHY_SEL_GMII 0x0 +#define ETH_PHY_SEL_MII 0x0 + +#define IS_PHY_IF_MODE_RGMII(iface) (iface == PHY_INTERFACE_MODE_RGMII || \ + iface == PHY_INTERFACE_MODE_RGMII_ID || \ + iface == PHY_INTERFACE_MODE_RGMII_RXID || \ + iface == PHY_INTERFACE_MODE_RGMII_TXID) + +#define IS_PHY_IF_MODE_GBIT(iface) (IS_PHY_IF_MODE_RGMII(iface) || \ + iface == PHY_INTERFACE_MODE_GMII) + +struct sti_dwmac { + int interface; + bool ext_phyclk; + bool is_tx_retime_src_clk_125; + struct clk *clk; + int reg; + struct device *dev; + struct regmap *regmap; +}; + +static u32 phy_intf_sels[] = { + [PHY_INTERFACE_MODE_MII] = ETH_PHY_SEL_MII, + [PHY_INTERFACE_MODE_GMII] = ETH_PHY_SEL_GMII, + [PHY_INTERFACE_MODE_RGMII] = ETH_PHY_SEL_RGMII, + [PHY_INTERFACE_MODE_RGMII_ID] = ETH_PHY_SEL_RGMII, + [PHY_INTERFACE_MODE_SGMII] = ETH_PHY_SEL_SGMII, + [PHY_INTERFACE_MODE_RMII] = ETH_PHY_SEL_RMII, +}; + +enum { + TX_RETIME_SRC_NA = 0, + TX_RETIME_SRC_TXCLK = 1, + TX_RETIME_SRC_CLK_125, + TX_RETIME_SRC_PHYCLK, + TX_RETIME_SRC_CLKGEN, +}; + +static const char *const tx_retime_srcs[] = { + [TX_RETIME_SRC_NA] = "", + [TX_RETIME_SRC_TXCLK] = "txclk", + [TX_RETIME_SRC_CLK_125] = "clk_125", + [TX_RETIME_SRC_PHYCLK] = "phyclk", + [TX_RETIME_SRC_CLKGEN] = "clkgen", +}; + +static u32 tx_retime_val[] = { + [TX_RETIME_SRC_TXCLK] = ETH_SEL_TXCLK_NOT_CLK125, + [TX_RETIME_SRC_CLK_125] = 0x0, + [TX_RETIME_SRC_PHYCLK] = ETH_SEL_TX_RETIME_CLK, + [TX_RETIME_SRC_CLKGEN] = ETH_SEL_TX_RETIME_CLK | + ETH_SEL_INTERNAL_NOTEXT_PHYCLK, +}; + +static void setup_retime_src(struct sti_dwmac *dwmac, u32 spd) +{ + u32 src = 0, freq = 0; + + if (spd == SPEED_100) { + if (dwmac->interface == PHY_INTERFACE_MODE_MII || + dwmac->interface == PHY_INTERFACE_MODE_GMII) { + src = TX_RETIME_SRC_TXCLK; + } else if (dwmac->interface == PHY_INTERFACE_MODE_RMII) { + if (dwmac->ext_phyclk) { + src = TX_RETIME_SRC_PHYCLK; + } else { + src = TX_RETIME_SRC_CLKGEN; + freq = 50000000; + } + + } else if (IS_PHY_IF_MODE_RGMII(dwmac->interface)) { + src = TX_RETIME_SRC_CLKGEN; + freq = 25000000; + } + + if (src == TX_RETIME_SRC_CLKGEN && dwmac->clk) + clk_set_rate(dwmac->clk, freq); + + } else if (spd == SPEED_1000) { + if (dwmac->is_tx_retime_src_clk_125) + src = TX_RETIME_SRC_CLK_125; + else + src = TX_RETIME_SRC_TXCLK; + } + + regmap_update_bits(dwmac->regmap, dwmac->reg, + TX_RETIME_SRC_MASK, tx_retime_val[src]); +} + +static void sti_dwmac_exit(struct platform_device *pdev, void *priv) +{ + struct sti_dwmac *dwmac = priv; + + if (dwmac->clk) + clk_disable_unprepare(dwmac->clk); +} + +static void sti_fix_mac_speed(void *priv, unsigned int spd) +{ + struct sti_dwmac *dwmac = priv; + + setup_retime_src(dwmac, spd); + + return; +} + +static int sti_dwmac_parse_data(struct sti_dwmac *dwmac, + struct platform_device *pdev) +{ + struct resource *res; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct regmap *regmap; + int err; + + if (!np) + return -EINVAL; + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sti-ethconf"); + if (!res) + return -ENODATA; + + regmap = syscon_regmap_lookup_by_phandle(np, "st,syscon"); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + dwmac->dev = dev; + dwmac->interface = of_get_phy_mode(np); + dwmac->regmap = regmap; + dwmac->reg = res->start; + dwmac->ext_phyclk = of_property_read_bool(np, "st,ext-phyclk"); + dwmac->is_tx_retime_src_clk_125 = false; + + if (IS_PHY_IF_MODE_GBIT(dwmac->interface)) { + const char *rs; + + err = of_property_read_string(np, "st,tx-retime-src", &rs); + if (err < 0) { + dev_err(dev, "st,tx-retime-src not specified\n"); + return err; + } + + if (!strcasecmp(rs, "clk_125")) + dwmac->is_tx_retime_src_clk_125 = true; + } + + dwmac->clk = devm_clk_get(dev, "sti-ethclk"); + + if (IS_ERR(dwmac->clk)) + dwmac->clk = NULL; + + return 0; +} + +static int sti_dwmac_init(struct platform_device *pdev, void *priv) +{ + struct sti_dwmac *dwmac = priv; + struct regmap *regmap = dwmac->regmap; + int iface = dwmac->interface; + u32 reg = dwmac->reg; + u32 val, spd; + + if (dwmac->clk) + clk_prepare_enable(dwmac->clk); + + regmap_update_bits(regmap, reg, MII_PHY_SEL_MASK, phy_intf_sels[iface]); + + val = (iface == PHY_INTERFACE_MODE_REVMII) ? 0 : ENMII; + regmap_update_bits(regmap, reg, ENMII_MASK, val); + + if (IS_PHY_IF_MODE_GBIT(iface)) + spd = SPEED_1000; + else + spd = SPEED_100; + + setup_retime_src(dwmac, spd); + + return 0; +} + +static void *sti_dwmac_setup(struct platform_device *pdev) +{ + struct sti_dwmac *dwmac; + int ret; + + dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL); + if (!dwmac) + return ERR_PTR(-ENOMEM); + + ret = sti_dwmac_parse_data(dwmac, pdev); + if (ret) { + dev_err(&pdev->dev, "Unable to parse OF data\n"); + return ERR_PTR(ret); + } + + return dwmac; +} + +const struct stmmac_of_data sti_gmac_data = { + .fix_mac_speed = sti_fix_mac_speed, + .setup = sti_dwmac_setup, + .init = sti_dwmac_init, + .exit = sti_dwmac_exit, +}; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index d9af26ed58ee..f9e60d7918c4 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -133,6 +133,9 @@ bool stmmac_eee_init(struct stmmac_priv *priv); #ifdef CONFIG_DWMAC_SUNXI extern const struct stmmac_of_data sun7i_gmac_data; #endif +#ifdef CONFIG_DWMAC_STI +extern const struct stmmac_of_data sti_gmac_data; +#endif extern struct platform_driver stmmac_pltfr_driver; static inline int stmmac_register_platform(void) { diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index 5884a7d2063b..c61bc72b8e90 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c @@ -32,6 +32,11 @@ static const struct of_device_id stmmac_dt_ids[] = { #ifdef CONFIG_DWMAC_SUNXI { .compatible = "allwinner,sun7i-a20-gmac", .data = &sun7i_gmac_data}, +#endif +#ifdef CONFIG_DWMAC_STI + { .compatible = "st,stih415-dwmac", .data = &sti_gmac_data}, + { .compatible = "st,stih416-dwmac", .data = &sti_gmac_data}, + { .compatible = "st,stih127-dwmac", .data = &sti_gmac_data}, #endif /* SoC specific glue layers should come before generic bindings */ { .compatible = "st,spear600-gmac"}, -- cgit v1.2.3 From 64380a04deeed4720de76b086a3a4eab8dd41671 Mon Sep 17 00:00:00 2001 From: Erik Hugne Date: Tue, 11 Feb 2014 11:38:26 +0100 Subject: tipc: fix message corruption bug for deferred packets If a packet received on a link is out-of-sequence, it will be placed on a deferred queue and later reinserted in the receive path once the preceding packets have been processed. The problem with this is that it will be subject to the buffer adjustment from link_recv_buf_validate twice. The second adjustment for 20 bytes header space will corrupt the packet. We solve this by tagging the deferred packets and bail out from receive buffer validation for packets that have already been subjected to this. Signed-off-by: Erik Hugne Reviewed-by: Jon Maloy Signed-off-by: David S. Miller --- net/tipc/core.h | 1 + net/tipc/link.c | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/net/tipc/core.h b/net/tipc/core.h index 1ff477b0450d..5569d96b4da3 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h @@ -192,6 +192,7 @@ static inline void k_term_timer(struct timer_list *timer) struct tipc_skb_cb { void *handle; + bool deferred; }; #define TIPC_SKB_CB(__skb) ((struct tipc_skb_cb *)&((__skb)->cb[0])) diff --git a/net/tipc/link.c b/net/tipc/link.c index d4b5de41b682..da6018beb6eb 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -1391,6 +1391,12 @@ static int link_recv_buf_validate(struct sk_buff *buf) u32 hdr_size; u32 min_hdr_size; + /* If this packet comes from the defer queue, the skb has already + * been validated + */ + if (unlikely(TIPC_SKB_CB(buf)->deferred)) + return 1; + if (unlikely(buf->len < MIN_H_SIZE)) return 0; @@ -1703,6 +1709,7 @@ static void link_handle_out_of_seq_msg(struct tipc_link *l_ptr, &l_ptr->newest_deferred_in, buf)) { l_ptr->deferred_inqueue_sz++; l_ptr->stats.deferred_recv++; + TIPC_SKB_CB(buf)->deferred = true; if ((l_ptr->deferred_inqueue_sz % 16) == 1) tipc_link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0); } else -- cgit v1.2.3 From 844fa1b5f8493cff4b976fa7a5b9ebeeafdd75cc Mon Sep 17 00:00:00 2001 From: Dave Kleikamp Date: Thu, 13 Feb 2014 15:40:13 -0600 Subject: jfs: set i_ctime when setting ACL This fixes a regression in 3.14-rc1 where xfstests generic/307 fails. jfs sets the ctime on the inode when writing an xattr. Previously, jfs went ahead and stored an acl that can be completely represented in the traditional permission bits, so the ctime was always set in the xattr code. The new code doesn't bother storing the acl in that case, thus the ctime isn't getting set. Signed-off-by: Dave Kleikamp Reported-by: Michael L. Semon --- fs/jfs/acl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/jfs/acl.c b/fs/jfs/acl.c index e973b85d6afd..5a8ea16eedbc 100644 --- a/fs/jfs/acl.c +++ b/fs/jfs/acl.c @@ -86,6 +86,8 @@ static int __jfs_set_acl(tid_t tid, struct inode *inode, int type, rc = posix_acl_equiv_mode(acl, &inode->i_mode); if (rc < 0) return rc; + inode->i_ctime = CURRENT_TIME; + mark_inode_dirty(inode); if (rc == 0) acl = NULL; break; -- cgit v1.2.3 From da37705cef30841616ed644ff33455bbc7374db0 Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Tue, 11 Feb 2014 15:51:29 -0800 Subject: macvlan: unregister net device when netdev_upper_dev_link() fails rtnl_newlink() doesn't unregister it for us on failure. Cc: Patrick McHardy Cc: David S. Miller Signed-off-by: Cong Wang Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- drivers/net/macvlan.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index 8433de4509c7..a5d21893670d 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -879,14 +879,15 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev, dev->priv_flags |= IFF_MACVLAN; err = netdev_upper_dev_link(lowerdev, dev); if (err) - goto destroy_port; - + goto unregister_netdev; list_add_tail_rcu(&vlan->list, &port->vlans); netif_stacked_transfer_operstate(lowerdev, dev); return 0; +unregister_netdev: + unregister_netdevice(dev); destroy_port: port->count -= 1; if (!port->count) -- cgit v1.2.3 From 0e0eee2465df77bcec2e8ff75432b8e57897b143 Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Tue, 11 Feb 2014 15:51:30 -0800 Subject: net: correct error path in rtnl_newlink() I saw the following BUG when ->newlink() fails in rtnl_newlink(): [ 40.240058] kernel BUG at net/core/dev.c:6438! this is due to free_netdev() is not supposed to be called before netdev is completely unregistered, therefore it is not correct to call free_netdev() here, at least for ops->newlink!=NULL case, many drivers call it in ->destructor so that rtnl_unlock() will take care of it, we probably don't need to do anything here. Cc: David S. Miller Cc: Eric Dumazet Signed-off-by: Cong Wang Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- net/core/rtnetlink.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 048dc8d183aa..1a0dac2ef9ad 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1963,16 +1963,21 @@ replay: dev->ifindex = ifm->ifi_index; - if (ops->newlink) + if (ops->newlink) { err = ops->newlink(net, dev, tb, data); - else + /* Drivers should call free_netdev() in ->destructor + * and unregister it on failure so that device could be + * finally freed in rtnl_unlock. + */ + if (err < 0) + goto out; + } else { err = register_netdevice(dev); - - if (err < 0) { - free_netdev(dev); - goto out; + if (err < 0) { + free_netdev(dev); + goto out; + } } - err = rtnl_configure_link(dev, ifm); if (err < 0) unregister_netdevice(dev); -- cgit v1.2.3 From 22a1f5140ed69baa5906ce9b2b9143478f5a4da0 Mon Sep 17 00:00:00 2001 From: wangweidong Date: Wed, 12 Feb 2014 09:44:43 +0800 Subject: sctp: fix a missed .data initialization As commit 3c68198e75111a90("sctp: Make hmac algorithm selection for cookie generation dynamic"), we miss the .data initialization. If we don't use the net_namespace, the problem that parts of the sysctl configuration won't be isolation and won't occur. In sctp_sysctl_net_register(), we register the sysctl for each net, in the for(), we use the 'table[i].data' as check condition, so when the 'i' is the index of sctp_hmac_alg, the data is NULL, then break. So add the .data initialization. Acked-by: Neil Horman Signed-off-by: Wang Weidong Signed-off-by: David S. Miller --- net/sctp/sysctl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c index 7135e617ab0f..d354de5a6fe0 100644 --- a/net/sctp/sysctl.c +++ b/net/sctp/sysctl.c @@ -151,6 +151,7 @@ static struct ctl_table sctp_net_table[] = { }, { .procname = "cookie_hmac_alg", + .data = &init_net.sctp.sctp_hmac_alg, .maxlen = 8, .mode = 0644, .proc_handler = proc_sctp_do_hmac_alg, -- cgit v1.2.3 From efb842c45e667332774196bd5a1d539d048159cc Mon Sep 17 00:00:00 2001 From: wangweidong Date: Wed, 12 Feb 2014 09:44:44 +0800 Subject: sctp: optimize the sctp_sysctl_net_register Here, when the net is init_net, we needn't to kmemdup the ctl_table again. So add a check for net. Also we can save some memory. Signed-off-by: Wang Weidong Acked-by: Neil Horman Signed-off-by: David S. Miller --- net/sctp/sysctl.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c index d354de5a6fe0..35c8923b5554 100644 --- a/net/sctp/sysctl.c +++ b/net/sctp/sysctl.c @@ -402,15 +402,18 @@ static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write, int sctp_sysctl_net_register(struct net *net) { - struct ctl_table *table; - int i; + struct ctl_table *table = sctp_net_table; + + if (!net_eq(net, &init_net)) { + int i; - table = kmemdup(sctp_net_table, sizeof(sctp_net_table), GFP_KERNEL); - if (!table) - return -ENOMEM; + table = kmemdup(sctp_net_table, sizeof(sctp_net_table), GFP_KERNEL); + if (!table) + return -ENOMEM; - for (i = 0; table[i].data; i++) - table[i].data += (char *)(&net->sctp) - (char *)&init_net.sctp; + for (i = 0; table[i].data; i++) + table[i].data += (char *)(&net->sctp) - (char *)&init_net.sctp; + } net->sctp.sysctl_header = register_net_sysctl(net, "net/sctp", table); return 0; -- cgit v1.2.3 From 455016e5dc623cb784dbaa4f197054ab87d84c76 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Tue, 11 Feb 2014 20:52:00 -0500 Subject: Documentation/networking: delete orphaned 3c505.txt file. In the commit 0e245dbaac9fa1c2fd0f4e2af7b9f6d874083a8b ("drivers/net: delete the 3Com 3c505/3c507 intel i825xx support") we clobbered the 3c505 driver (over a year ago) along with other abandoned ISA drivers. However, this orphaned README file escaped detection at that time, and has lived on until today. Get rid of it now. Signed-off-by: Paul Gortmaker Signed-off-by: David S. Miller --- Documentation/networking/3c505.txt | 45 -------------------------------------- 1 file changed, 45 deletions(-) delete mode 100644 Documentation/networking/3c505.txt diff --git a/Documentation/networking/3c505.txt b/Documentation/networking/3c505.txt deleted file mode 100644 index 72f38b13101d..000000000000 --- a/Documentation/networking/3c505.txt +++ /dev/null @@ -1,45 +0,0 @@ -The 3Com Etherlink Plus (3c505) driver. - -This driver now uses DMA. There is currently no support for PIO operation. -The default DMA channel is 6; this is _not_ autoprobed, so you must -make sure you configure it correctly. If loading the driver as a -module, you can do this with "modprobe 3c505 dma=n". If the driver is -linked statically into the kernel, you must either use an "ether=" -statement on the command line, or change the definition of ELP_DMA in 3c505.h. - -The driver will warn you if it has to fall back on the compiled in -default DMA channel. - -If no base address is given at boot time, the driver will autoprobe -ports 0x300, 0x280 and 0x310 (in that order). If no IRQ is given, the driver -will try to probe for it. - -The driver can be used as a loadable module. - -Theoretically, one instance of the driver can now run multiple cards, -in the standard way (when loading a module, say "modprobe 3c505 -io=0x300,0x340 irq=10,11 dma=6,7" or whatever). I have not tested -this, though. - -The driver may now support revision 2 hardware; the dependency on -being able to read the host control register has been removed. This -is also untested, since I don't have a suitable card. - -Known problems: - I still see "DMA upload timed out" messages from time to time. These -seem to be fairly non-fatal though. - The card is old and slow. - -To do: - Improve probe/setup code - Test multicast and promiscuous operation - -Authors: - The driver is mainly written by Craig Southeren, email - . - Parts of the driver (adapting the driver to 1.1.4+ kernels, - IRQ/address detection, some changes) and this README by - Juha Laiho . - DMA mode, more fixes, etc, by Philip Blundell - Multicard support, Software configurable DMA, etc., by - Christopher Collins -- cgit v1.2.3 From f80889a5b79cae0b84465a90c21b1273a03b7973 Mon Sep 17 00:00:00 2001 From: dingtianhong Date: Wed, 12 Feb 2014 12:06:40 +0800 Subject: bonding: Fix deadlock in bonding driver when using netpoll The bonding driver take write locks and spin locks that are shared by the tx path in enslave processing and notification processing, If the netconsole is in use, the bonding can call printk which puts us in the netpoll tx path, if the netconsole is attached to the bonding driver, result in deadlock. So add protection for these place, by checking the netpoll_block_tx state, we can defer the sending of the netconsole frames until a later time using the retransmit feature of netpoll_send_skb that is triggered on the return code NETDEV_TX_BUSY. Cc: Jay Vosburgh Cc: Veaceslav Falico Cc: Andy Gospodarek Signed-off-by: Ding Tianhong Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 71ba18efa15b..867664918715 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1543,9 +1543,11 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) bond_set_carrier(bond); if (USES_PRIMARY(bond->params.mode)) { + block_netpoll_tx(); write_lock_bh(&bond->curr_slave_lock); bond_select_active_slave(bond); write_unlock_bh(&bond->curr_slave_lock); + unblock_netpoll_tx(); } pr_info("%s: enslaving %s as a%s interface with a%s link.\n", @@ -1571,10 +1573,12 @@ err_detach: if (bond->primary_slave == new_slave) bond->primary_slave = NULL; if (bond->curr_active_slave == new_slave) { + block_netpoll_tx(); write_lock_bh(&bond->curr_slave_lock); bond_change_active_slave(bond, NULL); bond_select_active_slave(bond); write_unlock_bh(&bond->curr_slave_lock); + unblock_netpoll_tx(); } slave_disable_netpoll(new_slave); @@ -2864,9 +2868,12 @@ static int bond_slave_netdev_event(unsigned long event, pr_info("%s: Primary slave changed to %s, reselecting active slave.\n", bond->dev->name, bond->primary_slave ? slave_dev->name : "none"); + + block_netpoll_tx(); write_lock_bh(&bond->curr_slave_lock); bond_select_active_slave(bond); write_unlock_bh(&bond->curr_slave_lock); + unblock_netpoll_tx(); break; case NETDEV_FEAT_CHANGE: bond_compute_features(bond); -- cgit v1.2.3 From d206940319c41df4299db75ed56142177bb2e5f6 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Thu, 13 Feb 2014 23:09:11 +0100 Subject: net: core: introduce netif_skb_dev_features Will be used by upcoming ipv4 forward path change that needs to determine feature mask using skb->dst->dev instead of skb->dev. Signed-off-by: Florian Westphal Signed-off-by: David S. Miller --- include/linux/netdevice.h | 7 ++++++- net/core/dev.c | 22 ++++++++++++---------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 440a02ee6f92..21d4e6be8949 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -3068,7 +3068,12 @@ 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_features(struct sk_buff *skb); +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); +} 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 4ad1b78c9c77..b1b0c8d4d7df 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2420,7 +2420,7 @@ EXPORT_SYMBOL(netdev_rx_csum_fault); * 2. No high memory really exists on this machine. */ -static int illegal_highdma(struct net_device *dev, struct sk_buff *skb) +static int illegal_highdma(const struct net_device *dev, struct sk_buff *skb) { #ifdef CONFIG_HIGHMEM int i; @@ -2495,34 +2495,36 @@ static int dev_gso_segment(struct sk_buff *skb, netdev_features_t features) } static netdev_features_t harmonize_features(struct sk_buff *skb, - netdev_features_t features) + const struct net_device *dev, + netdev_features_t features) { if (skb->ip_summed != CHECKSUM_NONE && !can_checksum_protocol(features, skb_network_protocol(skb))) { features &= ~NETIF_F_ALL_CSUM; - } else if (illegal_highdma(skb->dev, skb)) { + } else if (illegal_highdma(dev, skb)) { features &= ~NETIF_F_SG; } return features; } -netdev_features_t netif_skb_features(struct sk_buff *skb) +netdev_features_t netif_skb_dev_features(struct sk_buff *skb, + const struct net_device *dev) { __be16 protocol = skb->protocol; - netdev_features_t features = skb->dev->features; + netdev_features_t features = dev->features; - if (skb_shinfo(skb)->gso_segs > skb->dev->gso_max_segs) + if (skb_shinfo(skb)->gso_segs > 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, features); + return harmonize_features(skb, dev, features); } - features &= (skb->dev->vlan_features | NETIF_F_HW_VLAN_CTAG_TX | + features &= (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)) @@ -2530,9 +2532,9 @@ netdev_features_t netif_skb_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, features); + return harmonize_features(skb, dev, features); } -EXPORT_SYMBOL(netif_skb_features); +EXPORT_SYMBOL(netif_skb_dev_features); int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev, struct netdev_queue *txq) -- cgit v1.2.3 From fe6cc55f3a9a053482a76f5a6b2257cee51b4663 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Thu, 13 Feb 2014 23:09:12 +0100 Subject: net: ip, ipv6: handle gso skbs in forwarding path Marcelo Ricardo Leitner reported problems when the forwarding link path has a lower mtu than the incoming one if the inbound interface supports GRO. Given: Host R1 R2 Host sends tcp stream which is routed via R1 and R2. R1 performs GRO. In this case, the kernel will fail to send ICMP fragmentation needed messages (or pkt too big for ipv6), as GSO packets currently bypass dstmtu checks in forward path. Instead, Linux tries to send out packets exceeding the mtu. When locking route MTU on Host (i.e., no ipv4 DF bit set), R1 does not fragment the packets when forwarding, and again tries to send out packets exceeding R1-R2 link mtu. This alters the forwarding dstmtu checks to take the individual gso segment lengths into account. For ipv6, we send out pkt too big error for gso if the individual segments are too big. For ipv4, we either send icmp fragmentation needed, or, if the DF bit is not set, perform software segmentation and let the output path create fragments when the packet is leaving the machine. It is not 100% correct as the error message will contain the headers of the GRO skb instead of the original/segmented one, but it seems to work fine in my (limited) tests. Eric Dumazet suggested to simply shrink mss via ->gso_size to avoid sofware segmentation. However it turns out that skb_segment() assumes skb nr_frags is related to mss size so we would BUG there. I don't want to mess with it considering Herbert and Eric disagree on what the correct behavior should be. Hannes Frederic Sowa notes that when we would shrink gso_size skb_segment would then also need to deal with the case where SKB_MAX_FRAGS would be exceeded. This uses sofware segmentation in the forward path when we hit ipv4 non-DF packets and the outgoing link mtu is too small. Its not perfect, but given the lack of bug reports wrt. GRO fwd being broken this is a rare case anyway. Also its not like this could not be improved later once the dust settles. Acked-by: Herbert Xu Reported-by: Marcelo Ricardo Leitner Signed-off-by: Florian Westphal Signed-off-by: David S. Miller --- include/linux/skbuff.h | 17 ++++++++++++ net/ipv4/ip_forward.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++-- net/ipv6/ip6_output.c | 17 ++++++++++-- 3 files changed, 101 insertions(+), 4 deletions(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index f589c9af8cbf..3ebbbe7b6d05 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -2916,5 +2916,22 @@ static inline bool skb_head_is_locked(const struct sk_buff *skb) { return !skb->head_frag || skb_cloned(skb); } + +/** + * skb_gso_network_seglen - Return length of individual segments of a gso packet + * + * @skb: GSO skb + * + * skb_gso_network_seglen is used to determine the real size of the + * individual segments, including Layer3 (IP, IPv6) and L4 headers (TCP/UDP). + * + * The MAC/L2 header is not accounted for. + */ +static inline unsigned int skb_gso_network_seglen(const struct sk_buff *skb) +{ + unsigned int hdr_len = skb_transport_header(skb) - + skb_network_header(skb); + return hdr_len + skb_gso_transport_seglen(skb); +} #endif /* __KERNEL__ */ #endif /* _LINUX_SKBUFF_H */ diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c index e9f1217a8afd..f3869c186d97 100644 --- a/net/ipv4/ip_forward.c +++ b/net/ipv4/ip_forward.c @@ -39,6 +39,71 @@ #include #include +static bool ip_may_fragment(const struct sk_buff *skb) +{ + return unlikely((ip_hdr(skb)->frag_off & htons(IP_DF)) == 0) || + !skb->local_df; +} + +static bool ip_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu) +{ + if (skb->len <= mtu || skb->local_df) + return false; + + if (skb_is_gso(skb) && skb_gso_network_seglen(skb) <= mtu) + return false; + + 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) { struct ip_options *opt = &(IPCB(skb)->opt); @@ -49,6 +114,9 @@ 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); } @@ -91,8 +159,7 @@ int ip_forward(struct sk_buff *skb) IPCB(skb)->flags |= IPSKB_FORWARDED; mtu = ip_dst_mtu_maybe_forward(&rt->dst, true); - if (unlikely(skb->len > mtu && !skb_is_gso(skb) && - (ip_hdr(skb)->frag_off & htons(IP_DF))) && !skb->local_df) { + if (!ip_may_fragment(skb) && ip_exceeds_mtu(skb, mtu)) { IP_INC_STATS(dev_net(rt->dst.dev), IPSTATS_MIB_FRAGFAILS); icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu)); diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index ef02b26ccf81..070a2fae2375 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -342,6 +342,20 @@ static unsigned int ip6_dst_mtu_forward(const struct dst_entry *dst) return mtu; } +static bool ip6_pkt_too_big(const struct sk_buff *skb, unsigned int mtu) +{ + if (skb->len <= mtu || skb->local_df) + return false; + + if (IP6CB(skb)->frag_max_size && IP6CB(skb)->frag_max_size > mtu) + return true; + + if (skb_is_gso(skb) && skb_gso_network_seglen(skb) <= mtu) + return false; + + return true; +} + int ip6_forward(struct sk_buff *skb) { struct dst_entry *dst = skb_dst(skb); @@ -466,8 +480,7 @@ int ip6_forward(struct sk_buff *skb) if (mtu < IPV6_MIN_MTU) mtu = IPV6_MIN_MTU; - if ((!skb->local_df && skb->len > mtu && !skb_is_gso(skb)) || - (IP6CB(skb)->frag_max_size && IP6CB(skb)->frag_max_size > mtu)) { + if (ip6_pkt_too_big(skb, mtu)) { /* Again, force OUTPUT device used as source address */ skb->dev = dst->dev; icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); -- cgit v1.2.3 From d26794c04553901d00c4ca1542e1cbf4ec9580fb Mon Sep 17 00:00:00 2001 From: Marek Belisko Date: Sat, 21 Dec 2013 16:12:23 +0100 Subject: ARM: dts: omap3-gta04: Add EOC irq gpio line handling. BMP085 EOC (End Of Conversion) irq line is connected to gpio113 on gta04. Set irq properties to have driver using irq instead polling for EOC. Signed-off-by: Marek Belisko Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap3-gta04.dts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/boot/dts/omap3-gta04.dts b/arch/arm/boot/dts/omap3-gta04.dts index b9b55c95a566..7a8e37de51b8 100644 --- a/arch/arm/boot/dts/omap3-gta04.dts +++ b/arch/arm/boot/dts/omap3-gta04.dts @@ -92,6 +92,8 @@ bmp085@77 { compatible = "bosch,bmp085"; reg = <0x77>; + interrupt-parent = <&gpio4>; + interrupts = <17 IRQ_TYPE_EDGE_RISING>; }; /* leds */ -- cgit v1.2.3 From 967d6a0bbfddcc25a7d1debbe8e2e4e7161d0566 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 23 Dec 2013 11:28:34 +0200 Subject: ARM: DTS: am335x-evmsk: Correct audio clock frequency The clock for audio is sourced from virt_24000000_ck, so the correct frequency is 24000000. Signed-off-by: Peter Ujfalusi Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am335x-evmsk.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/am335x-evmsk.dts b/arch/arm/boot/dts/am335x-evmsk.dts index 4718ec4a4dbf..50abe53f6887 100644 --- a/arch/arm/boot/dts/am335x-evmsk.dts +++ b/arch/arm/boot/dts/am335x-evmsk.dts @@ -121,7 +121,7 @@ ti,model = "AM335x-EVMSK"; ti,audio-codec = <&tlv320aic3106>; ti,mcasp-controller = <&mcasp1>; - ti,codec-clock-rate = <24576000>; + ti,codec-clock-rate = <24000000>; ti,audio-routing = "Headphone Jack", "HPLOUT", "Headphone Jack", "HPROUT"; -- cgit v1.2.3 From 29ea5efb0bb612d352aa360de26e2095cb230e4a Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 23 Dec 2013 11:28:35 +0200 Subject: ARM: dts: am335x-evmsk: Fix mmc1 support Add pinctrl section and cd-gpio to mmc1. Without these the SD card is not working on EVM-SK board. Signed-off-by: Peter Ujfalusi Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am335x-evmsk.dts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm/boot/dts/am335x-evmsk.dts b/arch/arm/boot/dts/am335x-evmsk.dts index 50abe53f6887..486880b74831 100644 --- a/arch/arm/boot/dts/am335x-evmsk.dts +++ b/arch/arm/boot/dts/am335x-evmsk.dts @@ -256,6 +256,12 @@ >; }; + mmc1_pins: pinmux_mmc1_pins { + pinctrl-single,pins = < + 0x160 (PIN_INPUT | MUX_MODE7) /* spi0_cs1.gpio0_6 */ + >; + }; + mcasp1_pins: mcasp1_pins { pinctrl-single,pins = < 0x10c (PIN_INPUT_PULLDOWN | MUX_MODE4) /* mii1_crs.mcasp1_aclkx */ @@ -456,6 +462,9 @@ status = "okay"; vmmc-supply = <&vmmc_reg>; bus-width = <4>; + pinctrl-names = "default"; + pinctrl-0 = <&mmc1_pins>; + cd-gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>; }; &sham { -- cgit v1.2.3 From 22106c11252833419a29c9294411101cb2199a5f Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Wed, 15 Jan 2014 14:00:38 -0600 Subject: ARM: OMAP2+: add missing ARCH_HAS_OPP OMAP5, DRA7, AM43xx all have OPPs. So select the same to allow SoC only configuration boot to work with OPP. Reported-by: Nikhil Devshatwar Signed-off-by: Nishanth Menon Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/Kconfig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index 653b489479e0..8165a4a3ce20 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -50,6 +50,7 @@ config SOC_OMAP5 bool "TI OMAP5" depends on ARCH_MULTI_V7 select ARCH_OMAP2PLUS + select ARCH_HAS_OPP select ARM_CPU_SUSPEND if PM select ARM_GIC select CPU_V7 @@ -63,6 +64,7 @@ config SOC_AM33XX bool "TI AM33XX" depends on ARCH_MULTI_V7 select ARCH_OMAP2PLUS + select ARCH_HAS_OPP select ARM_CPU_SUSPEND if PM select CPU_V7 select MULTI_IRQ_HANDLER @@ -72,6 +74,7 @@ config SOC_AM43XX depends on ARCH_MULTI_V7 select CPU_V7 select ARCH_OMAP2PLUS + select ARCH_HAS_OPP select MULTI_IRQ_HANDLER select ARM_GIC select MACH_OMAP_GENERIC @@ -80,6 +83,7 @@ config SOC_DRA7XX bool "TI DRA7XX" depends on ARCH_MULTI_V7 select ARCH_OMAP2PLUS + select ARCH_HAS_OPP select ARM_CPU_SUSPEND if PM select ARM_GIC select CPU_V7 -- cgit v1.2.3 From d8bd67317455744039e10fe33d6c76b82262c647 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Sat, 25 Jan 2014 22:28:55 +0100 Subject: ARM: dts: omap3-gta04: Fix 'aux' gpio key flags. It should be ACTIVE_HIGH. Signed-off-by: NeilBrown Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap3-gta04.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/omap3-gta04.dts b/arch/arm/boot/dts/omap3-gta04.dts index 7a8e37de51b8..81e0bb477bcd 100644 --- a/arch/arm/boot/dts/omap3-gta04.dts +++ b/arch/arm/boot/dts/omap3-gta04.dts @@ -32,7 +32,7 @@ aux-button { label = "aux"; linux,code = <169>; - gpios = <&gpio1 7 GPIO_ACTIVE_LOW>; + gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>; gpio-key,wakeup; }; }; -- cgit v1.2.3 From 2d6ac29e6a043c3adc3e82f5200ae1e07617e3ea Mon Sep 17 00:00:00 2001 From: Marek Belisko Date: Sat, 25 Jan 2014 22:28:57 +0100 Subject: ARM: dts: omap3-gta04: Fix mmc1 properties. Does not have an aux supply, and must be non-removable. Otherwise it is removed during suspend and filesystem gets confused. Signed-off-by: NeilBrown Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap3-gta04.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/omap3-gta04.dts b/arch/arm/boot/dts/omap3-gta04.dts index 81e0bb477bcd..c551e4af4d83 100644 --- a/arch/arm/boot/dts/omap3-gta04.dts +++ b/arch/arm/boot/dts/omap3-gta04.dts @@ -143,8 +143,8 @@ pinctrl-names = "default"; pinctrl-0 = <&mmc1_pins>; vmmc-supply = <&vmmc1>; - vmmc_aux-supply = <&vsim>; bus-width = <4>; + ti,non-removable; }; &mmc2 { -- cgit v1.2.3 From 9d5e8ec6571293cb8a5321176d74d559d2d38542 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 13 Feb 2014 08:10:42 +0100 Subject: net: axienet: Fix compilation error Add missing header to fix compilation error. drivers/net/ethernet/xilinx/xilinx_axienet_main.c:1575:22: error: undefined identifier 'irq_of_parse_and_map' drivers/net/ethernet/xilinx/xilinx_axienet_main.c:1576:22: error: undefined identifier 'irq_of_parse_and_map' Signed-off-by: Michal Simek Signed-off-by: David S. Miller --- drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index 1ec65feebb9e..9fb8ab24121a 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3 From 91ff37ff0b898e1ac8a1557b968a4918250f22ae Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 13 Feb 2014 08:10:43 +0100 Subject: net: axienet: Fix compilation warnings Warning log: xilinx_axienet_main.c: In function 'axienet_start_xmit_done': xilinx_axienet_main.c:617:16: warning: operation on 'lp->tx_bd_ci' may be undefined [-Wsequence-point] xilinx_axienet_main.c: In function 'axienet_start_xmit': xilinx_axienet_main.c:703:18: warning: operation on 'lp->tx_bd_tail' may be undefined [-Wsequence-point] xilinx_axienet_main.c:719:17: warning: operation on 'lp->tx_bd_tail' may be undefined [-Wsequence-point] xilinx_axienet_main.c: In function 'axienet_recv': xilinx_axienet_main.c:792:16: warning: operation on 'lp->rx_bd_ci' may be undefined [-Wsequence-point] xilinx_axienet_main.c: In function 'axienet_of_probe': xilinx_axienet_main.c:1501:21: warning: unused variable 'rc' [-Wunused-variable] Signed-off-by: Michal Simek Signed-off-by: David S. Miller --- drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index 9fb8ab24121a..4bfdf8c7ada0 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -601,7 +601,8 @@ static void axienet_start_xmit_done(struct net_device *ndev) size += status & XAXIDMA_BD_STS_ACTUAL_LEN_MASK; packets++; - lp->tx_bd_ci = ++lp->tx_bd_ci % TX_BD_NUM; + ++lp->tx_bd_ci; + lp->tx_bd_ci %= TX_BD_NUM; cur_p = &lp->tx_bd_v[lp->tx_bd_ci]; status = cur_p->status; } @@ -687,7 +688,8 @@ static int axienet_start_xmit(struct sk_buff *skb, struct net_device *ndev) skb_headlen(skb), DMA_TO_DEVICE); for (ii = 0; ii < num_frag; ii++) { - lp->tx_bd_tail = ++lp->tx_bd_tail % TX_BD_NUM; + ++lp->tx_bd_tail; + lp->tx_bd_tail %= TX_BD_NUM; cur_p = &lp->tx_bd_v[lp->tx_bd_tail]; frag = &skb_shinfo(skb)->frags[ii]; cur_p->phys = dma_map_single(ndev->dev.parent, @@ -703,7 +705,8 @@ static int axienet_start_xmit(struct sk_buff *skb, struct net_device *ndev) tail_p = lp->tx_bd_p + sizeof(*lp->tx_bd_v) * lp->tx_bd_tail; /* Start the transfer */ axienet_dma_out32(lp, XAXIDMA_TX_TDESC_OFFSET, tail_p); - lp->tx_bd_tail = ++lp->tx_bd_tail % TX_BD_NUM; + ++lp->tx_bd_tail; + lp->tx_bd_tail %= TX_BD_NUM; return NETDEV_TX_OK; } @@ -775,7 +778,8 @@ static void axienet_recv(struct net_device *ndev) cur_p->status = 0; cur_p->sw_id_offset = (u32) new_skb; - lp->rx_bd_ci = ++lp->rx_bd_ci % RX_BD_NUM; + ++lp->rx_bd_ci; + lp->rx_bd_ci %= RX_BD_NUM; cur_p = &lp->rx_bd_v[lp->rx_bd_ci]; } -- cgit v1.2.3 From 6b187b21c92b6e2c7e8ef0b450181c37a3f31681 Mon Sep 17 00:00:00 2001 From: Pekon Gupta Date: Tue, 28 Jan 2014 11:42:40 +0530 Subject: ARM: OMAP2+: gpmc: fix: DT NAND child nodes not probed when MTD_NAND is built as module Fixes: commit bc6b1e7b86f5d8e4a6fc1c0189e64bba4077efe0 ARM: OMAP: gpmc: add DT bindings for GPMC timings and NAND OMAP SoC(s) depend on GPMC controller driver to parse GPMC DT child nodes and register them platform_device for NAND driver to probe later. However this does not happen if generic MTD_NAND framework is built as module (CONFIG_MTD_NAND=m). Therefore, when MTD/NAND and MTD/NAND/OMAP2 modules are loaded, they are unable to find any matching platform_device and remain un-binded. This causes on board NAND flash to remain un-detected. This patch causes GPMC controller to parse DT nodes when CONFIG_MTD_NAND=y || CONFIG_MTD_NAND=m CC: # 3.9.x+ Signed-off-by: Pekon Gupta Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/gpmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index d24926e6340f..c77a84b63a59 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -1339,7 +1339,7 @@ static void __maybe_unused gpmc_read_timings_dt(struct device_node *np, of_property_read_bool(np, "gpmc,time-para-granularity"); } -#ifdef CONFIG_MTD_NAND +#if IS_ENABLED(CONFIG_MTD_NAND) static const char * const nand_xfer_types[] = { [NAND_OMAP_PREFETCH_POLLED] = "prefetch-polled", -- cgit v1.2.3 From 980386d2d6d49e0b42f48550853ef1ad6aa5d79a Mon Sep 17 00:00:00 2001 From: Pekon Gupta Date: Tue, 28 Jan 2014 11:42:41 +0530 Subject: ARM: OMAP2+: gpmc: fix: DT ONENAND child nodes not probed when MTD_ONENAND is built as module Fixes: commit 75d3625e0e86b2d8d77b4e9c6f685fd7ea0d5a96 ARM: OMAP2+: gpmc: add DT bindings for OneNAND OMAP SoC(s) depend on GPMC controller driver to parse GPMC DT child nodes and register them platform_device for ONENAND driver to probe later. However this does not happen if generic MTD_ONENAND framework is built as module (CONFIG_MTD_ONENAND=m). Therefore, when MTD/ONENAND and MTD/ONENAND/OMAP2 modules are loaded, they are unable to find any matching platform_device and remain un-binded. This causes on board ONENAND flash to remain un-detected. This patch causes GPMC controller to parse DT nodes when CONFIG_MTD_ONENAND=y || CONFIG_MTD_ONENAND=m CC: # 3.9.x+ Signed-off-by: Pekon Gupta Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/gpmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index c77a84b63a59..ab43755364f5 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -1429,7 +1429,7 @@ static int gpmc_probe_nand_child(struct platform_device *pdev, } #endif -#ifdef CONFIG_MTD_ONENAND +#if IS_ENABLED(CONFIG_MTD_ONENAND) static int gpmc_probe_onenand_child(struct platform_device *pdev, struct device_node *child) { -- cgit v1.2.3 From 8c5cb1a8f81370f60c62450fa5a5cf20aa081050 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sat, 8 Feb 2014 15:48:55 +0200 Subject: ARM: OMAP1: nokia770: enable tahvo-usb Add platform data for tahvo-usb. This is the last missing piece to get Tahvo USB working with 3.14. Signed-off-by: Aaro Koskinen Signed-off-by: Tony Lindgren --- arch/arm/mach-omap1/board-nokia770.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c index 91449c5cb70f..85089d821982 100644 --- a/arch/arm/mach-omap1/board-nokia770.c +++ b/arch/arm/mach-omap1/board-nokia770.c @@ -156,6 +156,7 @@ static struct omap_usb_config nokia770_usb_config __initdata = { .register_dev = 1, .hmc_mode = 16, .pins[0] = 6, + .extcon = "tahvo-usb", }; #if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) -- cgit v1.2.3 From 2a074deffd66d5e1893e859dc0737887fea9d46d Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sun, 9 Feb 2014 14:12:35 +0200 Subject: ARM: dts: N9/N950: fix boot hang with 3.14-rc1 N9/N950 does not boot anymore with 3.14-rc1, because SoC compatible property is missing. Fix that. Signed-off-by: Aaro Koskinen Reviewed-by: Nishanth Menon Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap3-n9.dts | 2 +- arch/arm/boot/dts/omap3-n950.dts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/omap3-n9.dts b/arch/arm/boot/dts/omap3-n9.dts index 39828ce464ee..9938b5dc1909 100644 --- a/arch/arm/boot/dts/omap3-n9.dts +++ b/arch/arm/boot/dts/omap3-n9.dts @@ -14,5 +14,5 @@ / { model = "Nokia N9"; - compatible = "nokia,omap3-n9", "ti,omap3"; + compatible = "nokia,omap3-n9", "ti,omap36xx", "ti,omap3"; }; diff --git a/arch/arm/boot/dts/omap3-n950.dts b/arch/arm/boot/dts/omap3-n950.dts index b076a526b999..261c5589bfa3 100644 --- a/arch/arm/boot/dts/omap3-n950.dts +++ b/arch/arm/boot/dts/omap3-n950.dts @@ -14,5 +14,5 @@ / { model = "Nokia N950"; - compatible = "nokia,omap3-n950", "ti,omap3"; + compatible = "nokia,omap3-n950", "ti,omap36xx", "ti,omap3"; }; -- cgit v1.2.3 From c3580bc12569b4c02ab5505b853825d863e6f86e Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sun, 9 Feb 2014 14:12:36 +0200 Subject: ARM: dts: N900: add missing compatible property Add missing compatible property to avoid problems in the future. Signed-off-by: Aaro Koskinen Reviewed-by: Nishanth Menon Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap3-n900.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/omap3-n900.dts b/arch/arm/boot/dts/omap3-n900.dts index 6fc85f963530..0bf40c90faba 100644 --- a/arch/arm/boot/dts/omap3-n900.dts +++ b/arch/arm/boot/dts/omap3-n900.dts @@ -1,6 +1,6 @@ /* * Copyright (C) 2013 Pavel Machek - * Copyright 2013 Aaro Koskinen + * Copyright (C) 2013-2014 Aaro Koskinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 (or later) as @@ -13,7 +13,7 @@ / { model = "Nokia N900"; - compatible = "nokia,omap3-n900", "ti,omap3"; + compatible = "nokia,omap3-n900", "ti,omap3430", "ti,omap3"; cpus { cpu@0 { -- cgit v1.2.3 From 9b2b6a2d669c909dd0b125fc834da94bcfc0aee7 Mon Sep 17 00:00:00 2001 From: Aleksander Morgado Date: Wed, 12 Feb 2014 15:55:14 +0100 Subject: net: qmi_wwan: add support for Cinterion PXS8 and PHS8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the PXS8 and PHS8 devices show up with PID 0x0053 they will expose both a QMI port and a WWAN interface. CC: Hans-Christoph Schemmel CC: Christian Schmiedl CC: Nicolaus Colberg CC: David McCullough Signed-off-by: Aleksander Morgado Acked-by: Bjørn Mork Signed-off-by: David S. Miller --- drivers/net/usb/qmi_wwan.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index ff5c87128ffe..1eddd43b2f32 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -732,6 +732,7 @@ static const struct usb_device_id products[] = { {QMI_FIXED_INTF(0x1bc7, 0x1201, 2)}, /* Telit LE920 */ {QMI_FIXED_INTF(0x0b3c, 0xc005, 6)}, /* Olivetti Olicard 200 */ {QMI_FIXED_INTF(0x1e2d, 0x0060, 4)}, /* Cinterion PLxx */ + {QMI_FIXED_INTF(0x1e2d, 0x0053, 4)}, /* Cinterion PHxx,PXxx */ /* 4. Gobi 1000 devices */ {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ -- cgit v1.2.3 From 89e101729be4cacd5847fef7e7c99680772c6e3c Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 12 Feb 2014 23:33:22 +0100 Subject: net: cpsw: catch of_get_phy_mode failing and propagate error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's wrong if the device tree doesn't provide a phy-mode property for the cpsw slaves as it is documented to be required in Documentation/devicetree/bindings/net/cpsw.txt. Anyhow it's nice to catch that problem, still more as it used to work without this property up to commit 388367a5a9fb (drivers: net: cpsw: use cpsw-phy-sel driver to configure phy mode) which is in v3.13-rc1. Signed-off-by: Uwe Kleine-König Acked-by: Mugunthan V N Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/cpsw.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index 1d860ce914ed..542c5114851c 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@ -1896,6 +1896,11 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data, memcpy(slave_data->mac_addr, mac_addr, ETH_ALEN); slave_data->phy_if = of_get_phy_mode(slave_node); + if (slave_data->phy_if < 0) { + pr_err("Missing or malformed slave[%d] phy-mode property\n", + i); + return slave_data->phy_if; + } if (data->dual_emac) { if (of_property_read_u32(slave_node, "dual_emac_res_vlan", -- cgit v1.2.3 From 84b57c84b10de62d832b04da02af9cba60199d0c Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Sun, 9 Feb 2014 16:01:28 +0100 Subject: ARM: OMAP2+: Remove MACH_NOKIA_N800 The last caller of machine_is_nokia_n800() was removed in commit 5a87cde490e1 ("ARM: OMAP2+: Remove legacy booting support for n8x0"). That means that the Kconfig symbol MACH_NOKIA_N800 is now unused. It can safely be removed. Signed-off-by: Paul Bolle Acked-by: Aaro Koskinen Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/Kconfig | 4 ---- 1 file changed, 4 deletions(-) diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index 8165a4a3ce20..9320252ca43a 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -272,9 +272,6 @@ config MACH_OMAP_3430SDP default y select OMAP_PACKAGE_CBB -config MACH_NOKIA_N800 - bool - config MACH_NOKIA_N810 bool @@ -285,7 +282,6 @@ config MACH_NOKIA_N8X0 bool "Nokia N800/N810" depends on SOC_OMAP2420 default y - select MACH_NOKIA_N800 select MACH_NOKIA_N810 select MACH_NOKIA_N810_WIMAX select OMAP_PACKAGE_ZAC -- cgit v1.2.3 From 43e21ef061598024dcb4821b97b9eaebfed0b50d Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Wed, 12 Feb 2014 10:45:52 +0100 Subject: ARM: OMAP2+: Remove legacy macros for zoom platforms Commit 97411608fd5f ("ARM: OMAP2+: Remove legacy support for zoom platforms") removed the Kconfig symbols MACH_OMAP_ZOOM2 and MACH_OMAP_ZOOM3. Remove the last usage of the related macros too. Signed-off-by: Paul Bolle Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/io.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c index d408b15b4fbf..af432b191255 100644 --- a/arch/arm/mach-omap2/io.c +++ b/arch/arm/mach-omap2/io.c @@ -179,15 +179,6 @@ static struct map_desc omap34xx_io_desc[] __initdata = { .length = L4_EMU_34XX_SIZE, .type = MT_DEVICE }, -#if defined(CONFIG_DEBUG_LL) && \ - (defined(CONFIG_MACH_OMAP_ZOOM2) || defined(CONFIG_MACH_OMAP_ZOOM3)) - { - .virtual = ZOOM_UART_VIRT, - .pfn = __phys_to_pfn(ZOOM_UART_BASE), - .length = SZ_1M, - .type = MT_DEVICE - }, -#endif }; #endif -- cgit v1.2.3 From 219e288e8900fac65211e0a23e2a1037fd521af1 Mon Sep 17 00:00:00 2001 From: Vijay Subramanian Date: Wed, 12 Feb 2014 18:58:21 -0800 Subject: net: sched: Cleanup PIE comments Fix incorrect comment reported by Norbert Kiesel. Edit another comment to add more details. Also add references to algorithm (IETF draft and paper) to top of file. Signed-off-by: Vijay Subramanian CC: Mythili Prabhu CC: Norbert Kiesel Signed-off-by: David S. Miller --- net/sched/sch_pie.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/net/sched/sch_pie.c b/net/sched/sch_pie.c index a255d0200a59..fefeeb73f15f 100644 --- a/net/sched/sch_pie.c +++ b/net/sched/sch_pie.c @@ -15,6 +15,11 @@ * * ECN support is added by Naeem Khademi * University of Oslo, Norway. + * + * References: + * IETF draft submission: http://tools.ietf.org/html/draft-pan-aqm-pie-00 + * IEEE Conference on High Performance Switching and Routing 2013 : + * "PIE: A * Lightweight Control Scheme to Address the Bufferbloat Problem" */ #include @@ -36,7 +41,7 @@ struct pie_params { psched_time_t target; /* user specified target delay in pschedtime */ u32 tupdate; /* timer frequency (in jiffies) */ u32 limit; /* number of packets that can be enqueued */ - u32 alpha; /* alpha and beta are between -4 and 4 */ + u32 alpha; /* alpha and beta are between 0 and 32 */ u32 beta; /* and are used for shift relative to 1 */ bool ecn; /* true if ecn is enabled */ bool bytemode; /* to scale drop early prob based on pkt size */ @@ -326,10 +331,16 @@ static void calculate_probability(struct Qdisc *sch) if (qdelay == 0 && qlen != 0) update_prob = false; - /* Add ranges for alpha and beta, more aggressive for high dropping - * mode and gentle steps for light dropping mode - * In light dropping mode, take gentle steps; in medium dropping mode, - * take medium steps; in high dropping mode, take big steps. + /* In the algorithm, alpha and beta are between 0 and 2 with typical + * value for alpha as 0.125. In this implementation, we use values 0-32 + * passed from user space to represent this. Also, alpha and beta have + * unit of HZ and need to be scaled before they can used to update + * probability. alpha/beta are updated locally below by 1) scaling them + * appropriately 2) scaling down by 16 to come to 0-2 range. + * Please see paper for details. + * + * We scale alpha and beta differently depending on whether we are in + * light, medium or high dropping mode. */ if (q->vars.prob < MAX_PROB / 100) { alpha = -- cgit v1.2.3 From df1a29f4768a3de4ea793ff0b4c6e79ffa15849d Mon Sep 17 00:00:00 2001 From: Florian Vaussard Date: Thu, 13 Feb 2014 11:25:13 +0100 Subject: ARM: dts: omap3-tobi: Fix boot with OMAP36xx-based Overo Tobi expansion board can be used with both OMAP35xx-based Overo, and OMAP36xx-based Overo. Currently the boot is broken with newer OMAP36xx-based Overo (Storm and alike). Fix include file and compatible string to be able to boot newer models. This will break older models. This will be addressed later. Signed-off-by: Florian Vaussard Tested-by: Kevin Hilman Acked-by: Nishanth Menon Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap3-overo.dtsi | 3 --- arch/arm/boot/dts/omap3-tobi.dts | 5 ++++- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/omap3-overo.dtsi b/arch/arm/boot/dts/omap3-overo.dtsi index a461d2fd1fb0..597099907f8e 100644 --- a/arch/arm/boot/dts/omap3-overo.dtsi +++ b/arch/arm/boot/dts/omap3-overo.dtsi @@ -9,9 +9,6 @@ /* * The Gumstix Overo must be combined with an expansion board. */ -/dts-v1/; - -#include "omap34xx.dtsi" / { pwmleds { diff --git a/arch/arm/boot/dts/omap3-tobi.dts b/arch/arm/boot/dts/omap3-tobi.dts index 7e4ad2aec37a..0e3b8bf49761 100644 --- a/arch/arm/boot/dts/omap3-tobi.dts +++ b/arch/arm/boot/dts/omap3-tobi.dts @@ -10,11 +10,14 @@ * Tobi expansion board is manufactured by Gumstix Inc. */ +/dts-v1/; + +#include "omap36xx.dtsi" #include "omap3-overo.dtsi" / { model = "TI OMAP3 Gumstix Overo on Tobi"; - compatible = "ti,omap3-tobi", "ti,omap3-overo", "ti,omap3"; + compatible = "ti,omap3-tobi", "ti,omap3-overo", "ti,omap36xx", "ti,omap3"; leds { compatible = "gpio-leds"; -- cgit v1.2.3 From 1ce64826b02032827abb166fc2d8909171d4b296 Mon Sep 17 00:00:00 2001 From: Florian Vaussard Date: Thu, 13 Feb 2014 11:25:14 +0100 Subject: ARM: dts: omap3-tobi: Use the correct vendor prefix Gumstix is the correct vendor for all Overo related products. Reported-by: Javier Martinez Canillas Signed-off-by: Florian Vaussard Acked-by: Nishanth Menon Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap3-tobi.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/omap3-tobi.dts b/arch/arm/boot/dts/omap3-tobi.dts index 0e3b8bf49761..c742afaa2c26 100644 --- a/arch/arm/boot/dts/omap3-tobi.dts +++ b/arch/arm/boot/dts/omap3-tobi.dts @@ -17,7 +17,7 @@ / { model = "TI OMAP3 Gumstix Overo on Tobi"; - compatible = "ti,omap3-tobi", "ti,omap3-overo", "ti,omap36xx", "ti,omap3"; + compatible = "gumstix,omap3-tobi", "gumstix,omap3-overo", "ti,omap36xx", "ti,omap3"; leds { compatible = "gpio-leds"; -- cgit v1.2.3 From f03ef09b6f59c0807d6aeba10f18238be1ea6390 Mon Sep 17 00:00:00 2001 From: Florian Vaussard Date: Thu, 13 Feb 2014 11:25:15 +0100 Subject: ARM: dts: Add support for both OMAP35xx and OMAP36xx Overo/Tobi Unfortunatly the device tree for older OMAP35xx Overo cannot be used with newer OMAP36xx and vice-versa. To address this issue, move most of the Tobi DTS to a common include file, and create model-specific Tobi DTS. Signed-off-by: Florian Vaussard Tested-by: Kevin Hilman Acked-by: Nishanth Menon Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/Makefile | 3 +- arch/arm/boot/dts/omap3-overo-storm-tobi.dts | 22 +++++++ arch/arm/boot/dts/omap3-overo-tobi-common.dtsi | 80 ++++++++++++++++++++++++ arch/arm/boot/dts/omap3-overo-tobi.dts | 22 +++++++ arch/arm/boot/dts/omap3-tobi.dts | 86 -------------------------- 5 files changed, 126 insertions(+), 87 deletions(-) create mode 100644 arch/arm/boot/dts/omap3-overo-storm-tobi.dts create mode 100644 arch/arm/boot/dts/omap3-overo-tobi-common.dtsi create mode 100644 arch/arm/boot/dts/omap3-overo-tobi.dts delete mode 100644 arch/arm/boot/dts/omap3-tobi.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index b9d6a8b485e0..e8355f4d8b0c 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -208,7 +208,8 @@ dtb-$(CONFIG_ARCH_OMAP2PLUS) += omap2420-h4.dtb \ omap3-n900.dtb \ omap3-n9.dtb \ omap3-n950.dtb \ - omap3-tobi.dtb \ + omap3-overo-tobi.dtb \ + omap3-overo-storm-tobi.dtb \ omap3-gta04.dtb \ omap3-igep0020.dtb \ omap3-igep0030.dtb \ diff --git a/arch/arm/boot/dts/omap3-overo-storm-tobi.dts b/arch/arm/boot/dts/omap3-overo-storm-tobi.dts new file mode 100644 index 000000000000..966b5c9cd96a --- /dev/null +++ b/arch/arm/boot/dts/omap3-overo-storm-tobi.dts @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2012 Florian Vaussard, EPFL Mobots group + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* + * Tobi expansion board is manufactured by Gumstix Inc. + */ + +/dts-v1/; + +#include "omap36xx.dtsi" +#include "omap3-overo-tobi-common.dtsi" + +/ { + model = "OMAP36xx/AM37xx/DM37xx Gumstix Overo on Tobi"; + compatible = "gumstix,omap3-overo-tobi", "gumstix,omap3-overo", "ti,omap36xx", "ti,omap3"; +}; + diff --git a/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi b/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi new file mode 100644 index 000000000000..4edc013a91c1 --- /dev/null +++ b/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2012 Florian Vaussard, EPFL Mobots group + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* + * Tobi expansion board is manufactured by Gumstix Inc. + */ + +#include "omap3-overo.dtsi" + +/ { + leds { + compatible = "gpio-leds"; + heartbeat { + label = "overo:red:gpio21"; + gpios = <&gpio1 21 GPIO_ACTIVE_LOW>; + linux,default-trigger = "heartbeat"; + }; + }; + + vddvario: regulator-vddvario { + compatible = "regulator-fixed"; + regulator-name = "vddvario"; + regulator-always-on; + }; + + vdd33a: regulator-vdd33a { + compatible = "regulator-fixed"; + regulator-name = "vdd33a"; + regulator-always-on; + }; +}; + +&gpmc { + ranges = <5 0 0x2c000000 0x1000000>; /* CS5 */ + + ethernet@5,0 { + compatible = "smsc,lan9221", "smsc,lan9115"; + reg = <5 0 0xff>; + bank-width = <2>; + + gpmc,mux-add-data; + gpmc,cs-on-ns = <0>; + gpmc,cs-rd-off-ns = <42>; + gpmc,cs-wr-off-ns = <36>; + gpmc,adv-on-ns = <6>; + gpmc,adv-rd-off-ns = <12>; + gpmc,adv-wr-off-ns = <12>; + gpmc,oe-on-ns = <0>; + gpmc,oe-off-ns = <42>; + gpmc,we-on-ns = <0>; + gpmc,we-off-ns = <36>; + gpmc,rd-cycle-ns = <60>; + gpmc,wr-cycle-ns = <54>; + gpmc,access-ns = <36>; + gpmc,page-burst-access-ns = <0>; + gpmc,bus-turnaround-ns = <0>; + gpmc,cycle2cycle-delay-ns = <0>; + gpmc,wr-data-mux-bus-ns = <18>; + gpmc,wr-access-ns = <42>; + gpmc,cycle2cycle-samecsen; + gpmc,cycle2cycle-diffcsen; + + interrupt-parent = <&gpio6>; + interrupts = <16 IRQ_TYPE_LEVEL_LOW>; /* GPIO 176 */ + reg-io-width = <4>; + }; +}; + +&i2c3 { + clock-frequency = <100000>; +}; + +&mmc3 { + status = "disabled"; +}; diff --git a/arch/arm/boot/dts/omap3-overo-tobi.dts b/arch/arm/boot/dts/omap3-overo-tobi.dts new file mode 100644 index 000000000000..de5653e1b5ca --- /dev/null +++ b/arch/arm/boot/dts/omap3-overo-tobi.dts @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2012 Florian Vaussard, EPFL Mobots group + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* + * Tobi expansion board is manufactured by Gumstix Inc. + */ + +/dts-v1/; + +#include "omap34xx.dtsi" +#include "omap3-overo-tobi-common.dtsi" + +/ { + model = "OMAP35xx Gumstix Overo on Tobi"; + compatible = "gumstix,omap3-overo-tobi", "gumstix,omap3-overo", "ti,omap3430", "ti,omap3"; +}; + diff --git a/arch/arm/boot/dts/omap3-tobi.dts b/arch/arm/boot/dts/omap3-tobi.dts deleted file mode 100644 index c742afaa2c26..000000000000 --- a/arch/arm/boot/dts/omap3-tobi.dts +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (C) 2012 Florian Vaussard, EPFL Mobots group - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -/* - * Tobi expansion board is manufactured by Gumstix Inc. - */ - -/dts-v1/; - -#include "omap36xx.dtsi" -#include "omap3-overo.dtsi" - -/ { - model = "TI OMAP3 Gumstix Overo on Tobi"; - compatible = "gumstix,omap3-tobi", "gumstix,omap3-overo", "ti,omap36xx", "ti,omap3"; - - leds { - compatible = "gpio-leds"; - heartbeat { - label = "overo:red:gpio21"; - gpios = <&gpio1 21 GPIO_ACTIVE_LOW>; - linux,default-trigger = "heartbeat"; - }; - }; - - vddvario: regulator-vddvario { - compatible = "regulator-fixed"; - regulator-name = "vddvario"; - regulator-always-on; - }; - - vdd33a: regulator-vdd33a { - compatible = "regulator-fixed"; - regulator-name = "vdd33a"; - regulator-always-on; - }; -}; - -&gpmc { - ranges = <5 0 0x2c000000 0x1000000>; /* CS5 */ - - ethernet@5,0 { - compatible = "smsc,lan9221", "smsc,lan9115"; - reg = <5 0 0xff>; - bank-width = <2>; - - gpmc,mux-add-data; - gpmc,cs-on-ns = <0>; - gpmc,cs-rd-off-ns = <42>; - gpmc,cs-wr-off-ns = <36>; - gpmc,adv-on-ns = <6>; - gpmc,adv-rd-off-ns = <12>; - gpmc,adv-wr-off-ns = <12>; - gpmc,oe-on-ns = <0>; - gpmc,oe-off-ns = <42>; - gpmc,we-on-ns = <0>; - gpmc,we-off-ns = <36>; - gpmc,rd-cycle-ns = <60>; - gpmc,wr-cycle-ns = <54>; - gpmc,access-ns = <36>; - gpmc,page-burst-access-ns = <0>; - gpmc,bus-turnaround-ns = <0>; - gpmc,cycle2cycle-delay-ns = <0>; - gpmc,wr-data-mux-bus-ns = <18>; - gpmc,wr-access-ns = <42>; - gpmc,cycle2cycle-samecsen; - gpmc,cycle2cycle-diffcsen; - - interrupt-parent = <&gpio6>; - interrupts = <16 IRQ_TYPE_LEVEL_LOW>; /* GPIO 176 */ - reg-io-width = <4>; - }; -}; - -&i2c3 { - clock-frequency = <100000>; -}; - -&mmc3 { - status = "disabled"; -}; -- cgit v1.2.3 From 6726d971def461eded39cccce24d28f90a2e6df4 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Thu, 13 Feb 2014 16:09:58 +0900 Subject: USB2NET: SR9800: use %zu for size_t Use %zu for size_t in order to avoid the following build warning in printks. drivers/net/usb/sr9800.c: In function 'sr9800_bind' drivers/net/usb/sr9800.c:826:2: warning: format '%ld' expects argument of type 'long int' but argument 5 has type 'size_t' [-Wformat] Signed-off-by: Jingoo Han Signed-off-by: David S. Miller --- drivers/net/usb/sr9800.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/usb/sr9800.c b/drivers/net/usb/sr9800.c index 4175eb9fdeca..801710883727 100644 --- a/drivers/net/usb/sr9800.c +++ b/drivers/net/usb/sr9800.c @@ -823,7 +823,7 @@ static int sr9800_bind(struct usbnet *dev, struct usb_interface *intf) dev->rx_urb_size = SR9800_BULKIN_SIZE[SR9800_MAX_BULKIN_2K].size; } - netdev_dbg(dev->net, "%s : setting rx_urb_size with : %ld\n", __func__, + netdev_dbg(dev->net, "%s : setting rx_urb_size with : %zu\n", __func__, dev->rx_urb_size); return 0; -- cgit v1.2.3 From 208ece14e23b167b43d906c74e3bdcbee8d6e4aa Mon Sep 17 00:00:00 2001 From: Liu Junliang Date: Thu, 13 Feb 2014 12:22:19 +0800 Subject: USB2NET: Fix Default to 'y' for SR9800 Device Driver, setting to 'n' Signed-off-by: Liu Junliang Signed-off-by: David S. Miller --- drivers/net/usb/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig index 409499fdb157..7e7269fd3707 100644 --- a/drivers/net/usb/Kconfig +++ b/drivers/net/usb/Kconfig @@ -296,7 +296,6 @@ config USB_NET_SR9800 tristate "CoreChip-sz SR9800 based USB 2.0 10/100 ethernet devices" depends on USB_USBNET select CRC32 - default y ---help--- Say Y if you want to use one of the following 100Mbps USB Ethernet device based on the CoreChip-sz SR9800 chip. -- cgit v1.2.3 From 0ad8b480d6ee916aa84324f69acf690142aecd0e Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Thu, 13 Feb 2014 11:42:05 +0200 Subject: vhost: fix ref cnt checking deadlock vhost checked the counter within the refcnt before decrementing. It really wanted to know that it is the one that has the last reference, as a way to batch freeing resources a bit more efficiently. Note: we only let refcount go to 0 on device release. This works well but we now access the ref counter twice so there's a race: all users might see a high count and decide to defer freeing resources. In the end no one initiates freeing resources until the last reference is gone (which is on VM shotdown so might happen after a looooong time). Let's do what we probably should have done straight away: switch from kref to plain atomic, documenting the semantics, return the refcount value atomically after decrement, then use that to avoid the deadlock. Reported-by: Qin Chuanyu Signed-off-by: Michael S. Tsirkin Acked-by: Jason Wang Signed-off-by: David S. Miller --- drivers/vhost/net.c | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index 9a68409580d5..41be4de37e81 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -70,7 +70,12 @@ enum { }; struct vhost_net_ubuf_ref { - struct kref kref; + /* refcount follows semantics similar to kref: + * 0: object is released + * 1: no outstanding ubufs + * >1: outstanding ubufs + */ + atomic_t refcount; wait_queue_head_t wait; struct vhost_virtqueue *vq; }; @@ -116,14 +121,6 @@ static void vhost_net_enable_zcopy(int vq) vhost_net_zcopy_mask |= 0x1 << vq; } -static void vhost_net_zerocopy_done_signal(struct kref *kref) -{ - struct vhost_net_ubuf_ref *ubufs; - - ubufs = container_of(kref, struct vhost_net_ubuf_ref, kref); - wake_up(&ubufs->wait); -} - static struct vhost_net_ubuf_ref * vhost_net_ubuf_alloc(struct vhost_virtqueue *vq, bool zcopy) { @@ -134,21 +131,24 @@ vhost_net_ubuf_alloc(struct vhost_virtqueue *vq, bool zcopy) ubufs = kmalloc(sizeof(*ubufs), GFP_KERNEL); if (!ubufs) return ERR_PTR(-ENOMEM); - kref_init(&ubufs->kref); + atomic_set(&ubufs->refcount, 1); init_waitqueue_head(&ubufs->wait); ubufs->vq = vq; return ubufs; } -static void vhost_net_ubuf_put(struct vhost_net_ubuf_ref *ubufs) +static int vhost_net_ubuf_put(struct vhost_net_ubuf_ref *ubufs) { - kref_put(&ubufs->kref, vhost_net_zerocopy_done_signal); + int r = atomic_sub_return(1, &ubufs->refcount); + if (unlikely(!r)) + wake_up(&ubufs->wait); + return r; } static void vhost_net_ubuf_put_and_wait(struct vhost_net_ubuf_ref *ubufs) { - kref_put(&ubufs->kref, vhost_net_zerocopy_done_signal); - wait_event(ubufs->wait, !atomic_read(&ubufs->kref.refcount)); + vhost_net_ubuf_put(ubufs); + wait_event(ubufs->wait, !atomic_read(&ubufs->refcount)); } static void vhost_net_ubuf_put_wait_and_free(struct vhost_net_ubuf_ref *ubufs) @@ -306,22 +306,21 @@ static void vhost_zerocopy_callback(struct ubuf_info *ubuf, bool success) { struct vhost_net_ubuf_ref *ubufs = ubuf->ctx; struct vhost_virtqueue *vq = ubufs->vq; - int cnt = atomic_read(&ubufs->kref.refcount); + int cnt; /* set len to mark this desc buffers done DMA */ vq->heads[ubuf->desc].len = success ? VHOST_DMA_DONE_LEN : VHOST_DMA_FAILED_LEN; - vhost_net_ubuf_put(ubufs); + cnt = vhost_net_ubuf_put(ubufs); /* * Trigger polling thread if guest stopped submitting new buffers: - * in this case, the refcount after decrement will eventually reach 1 - * so here it is 2. + * in this case, the refcount after decrement will eventually reach 1. * We also trigger polling periodically after each 16 packets * (the value 16 here is more or less arbitrary, it's tuned to trigger * less than 10% of times). */ - if (cnt <= 2 || !(cnt % 16)) + if (cnt <= 1 || !(cnt % 16)) vhost_poll_queue(&vq->poll); } @@ -420,7 +419,7 @@ static void handle_tx(struct vhost_net *net) msg.msg_control = ubuf; msg.msg_controllen = sizeof(ubuf); ubufs = nvq->ubufs; - kref_get(&ubufs->kref); + atomic_inc(&ubufs->refcount); nvq->upend_idx = (nvq->upend_idx + 1) % UIO_MAXIOV; } else { msg.msg_control = NULL; @@ -780,7 +779,7 @@ static void vhost_net_flush(struct vhost_net *n) vhost_net_ubuf_put_and_wait(n->vqs[VHOST_NET_VQ_TX].ubufs); mutex_lock(&n->vqs[VHOST_NET_VQ_TX].vq.mutex); n->tx_flush = false; - kref_init(&n->vqs[VHOST_NET_VQ_TX].ubufs->kref); + atomic_set(&n->vqs[VHOST_NET_VQ_TX].ubufs->refcount, 1); mutex_unlock(&n->vqs[VHOST_NET_VQ_TX].vq.mutex); } } -- cgit v1.2.3 From b0c057ca7e835b36c6050c7627634b664796c1d6 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Thu, 13 Feb 2014 11:45:11 +0200 Subject: vhost: fix a theoretical race in device cleanup vhost_zerocopy_callback accesses VQ right after it drops a ubuf reference. In theory, this could race with device removal which waits on the ubuf kref, and crash on use after free. Do all accesses within rcu read side critical section, and synchronize on release. Since callbacks are always invoked from bh, synchronize_rcu_bh seems enough and will help release complete a bit faster. Signed-off-by: Michael S. Tsirkin Acked-by: Jason Wang Signed-off-by: David S. Miller --- drivers/vhost/net.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index 41be4de37e81..a0fa5de210cf 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -308,6 +308,8 @@ static void vhost_zerocopy_callback(struct ubuf_info *ubuf, bool success) struct vhost_virtqueue *vq = ubufs->vq; int cnt; + rcu_read_lock_bh(); + /* set len to mark this desc buffers done DMA */ vq->heads[ubuf->desc].len = success ? VHOST_DMA_DONE_LEN : VHOST_DMA_FAILED_LEN; @@ -322,6 +324,8 @@ static void vhost_zerocopy_callback(struct ubuf_info *ubuf, bool success) */ if (cnt <= 1 || !(cnt % 16)) vhost_poll_queue(&vq->poll); + + rcu_read_unlock_bh(); } /* Expects to be always run from workqueue - which acts as @@ -799,6 +803,8 @@ static int vhost_net_release(struct inode *inode, struct file *f) fput(tx_sock->file); if (rx_sock) fput(rx_sock->file); + /* Make sure no callbacks are outstanding */ + synchronize_rcu_bh(); /* We do an extra flush before freeing memory, * since jobs can re-queue themselves. */ vhost_net_flush(n); -- cgit v1.2.3 From 0d961b3b52f566f823070ce2366511a7f64b928c Mon Sep 17 00:00:00 2001 From: Heiko Schocher Date: Thu, 13 Feb 2014 14:47:27 +0100 Subject: drivers: net: cpsw: fix buggy loop condition Commit 0cd8f9cc0654c06adde353c6532114c5f53a18e8 ("drivers: net: cpsw: enable promiscuous mode support") Enable promiscuous mode support for CPSW. Introduced a crash on an am335x based board (similiar to am335x-evm). Reason is buggy end condition in for loop in cpsw_set_promiscious() for (i = 0; i <= priv->data.slaves; i++) should be for (i = 0; i < priv->data.slaves; i++) Fix this ... Signed-off-by: Heiko Schocher Cc: Mugunthan V N Cc: David S. Miller Cc: Sebastian Siewior Cc: Daniel Mack Cc: Felipe Balbi Cc: Markus Pargmann Cc: netdev@vger.kernel.org Cc: linux-kernel@vger.kernel.org Acked-by: Mugunthan V N Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/cpsw.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index 542c5114851c..651087b5c8da 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@ -554,7 +554,7 @@ static void cpsw_set_promiscious(struct net_device *ndev, bool enable) * common for both the interface as the interface shares * the same hardware resource. */ - for (i = 0; i <= priv->data.slaves; i++) + for (i = 0; i < priv->data.slaves; i++) if (priv->slaves[i].ndev->flags & IFF_PROMISC) flag = true; @@ -578,7 +578,7 @@ static void cpsw_set_promiscious(struct net_device *ndev, bool enable) unsigned long timeout = jiffies + HZ; /* Disable Learn for all ports */ - for (i = 0; i <= priv->data.slaves; i++) { + for (i = 0; i < priv->data.slaves; i++) { cpsw_ale_control_set(ale, i, ALE_PORT_NOLEARN, 1); cpsw_ale_control_set(ale, i, @@ -606,7 +606,7 @@ static void cpsw_set_promiscious(struct net_device *ndev, bool enable) cpsw_ale_control_set(ale, 0, ALE_P0_UNI_FLOOD, 0); /* Enable Learn for all ports */ - for (i = 0; i <= priv->data.slaves; i++) { + for (i = 0; i < priv->data.slaves; i++) { cpsw_ale_control_set(ale, i, ALE_PORT_NOLEARN, 0); cpsw_ale_control_set(ale, i, -- cgit v1.2.3 From 602b109942b816e56639a965ae81f3a2437004b5 Mon Sep 17 00:00:00 2001 From: Stefan Sørensen Date: Thu, 13 Feb 2014 15:26:57 +0100 Subject: net:phy:dp83640: Move all HW initialization to dp83640_config_init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit phy_init_hw not does a full PHY reset after the driver probe has finished, so any hw initialization done in the probe will be lost. Part of the timestamping functionality of the dp83640 is set up in the probe and with that lost, enabling timestamping will cause a PHY lockup, requiring a hard reset / power cycle to recover. This patch moves all the HW initialization in dp83640_probe to dp83640_config_init. Signed-off-by: Stefan Sørensen Signed-off-by: David S. Miller --- drivers/net/phy/dp83640.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c index 9414fa272160..98e7cbf720a5 100644 --- a/drivers/net/phy/dp83640.c +++ b/drivers/net/phy/dp83640.c @@ -1006,11 +1006,6 @@ static int dp83640_probe(struct phy_device *phydev) } else list_add_tail(&dp83640->list, &clock->phylist); - if (clock->chosen && !list_empty(&clock->phylist)) - recalibrate(clock); - else - enable_broadcast(dp83640->phydev, clock->page, 1); - dp83640_clock_put(clock); return 0; @@ -1063,6 +1058,14 @@ static void dp83640_remove(struct phy_device *phydev) static int dp83640_config_init(struct phy_device *phydev) { + struct dp83640_private *dp83640 = phydev->priv; + struct dp83640_clock *clock = dp83640->clock; + + if (clock->chosen && !list_empty(&clock->phylist)) + recalibrate(clock); + else + enable_broadcast(phydev, clock->page, 1); + enable_status_frames(phydev, true); ext_write(0, phydev, PAGE4, PTP_CTL, PTP_ENABLE); return 0; -- cgit v1.2.3 From 357137a4222b1984b3d867923c7e388669744ceb Mon Sep 17 00:00:00 2001 From: FX Le Bail Date: Mon, 10 Feb 2014 16:46:54 +0100 Subject: ipv4: ipconfig.c: add parentheses in an if statement Even if the 'time_before' macro expand with parentheses, the look is bad. Signed-off-by: Francois-Xavier Le Bail Signed-off-by: David S. Miller --- net/ipv4/ipconfig.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c index efa1138fa523..b3e86ea7b71b 100644 --- a/net/ipv4/ipconfig.c +++ b/net/ipv4/ipconfig.c @@ -273,7 +273,7 @@ static int __init ic_open_devs(void) msleep(1); - if time_before(jiffies, next_msg) + if (time_before(jiffies, next_msg)) continue; elapsed = jiffies_to_msecs(jiffies - start); -- cgit v1.2.3 From fada94ee64e6e18793b1db60fb8278d2eddbf922 Mon Sep 17 00:00:00 2001 From: Li Zhong Date: Fri, 14 Feb 2014 10:52:57 +0800 Subject: workqueue: add args to workqueue lockdep name Tommi noticed a 'funny' lock class name: "%s#5" from a lock acquired in process_one_work(). Maybe #fmt plus #args could be used as the lock_name to give some more information for some fmt string like the above. __builtin_constant_p() check is removed (as there seems no good way to check all the variables in args list). However, by removing the check, it only adds two additional "s for those constants. Some lockdep name examples printed out after the change: lockdep name wq->name "events_long" events_long "%s"("khelper") khelper "xfs-data/%s"mp->m_fsname xfs-data/dm-3 Signed-off-by: Li Zhong Signed-off-by: Tejun Heo --- include/linux/workqueue.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h index 594521ba0d43..704f4f652d0a 100644 --- a/include/linux/workqueue.h +++ b/include/linux/workqueue.h @@ -419,10 +419,7 @@ __alloc_workqueue_key(const char *fmt, unsigned int flags, int max_active, static struct lock_class_key __key; \ const char *__lock_name; \ \ - if (__builtin_constant_p(fmt)) \ - __lock_name = (fmt); \ - else \ - __lock_name = #fmt; \ + __lock_name = #fmt#args; \ \ __alloc_workqueue_key((fmt), (flags), (max_active), \ &__key, __lock_name, ##args); \ -- cgit v1.2.3 From 8842446ac74263f1330f46e11ed649e2b0ed6545 Mon Sep 17 00:00:00 2001 From: Florian Vaussard Date: Thu, 13 Feb 2014 11:25:16 +0100 Subject: Documentation: dt: OMAP: Update Overo/Tobi Update the compatible string for Overo/Tobi to reflect the latest changes. Signed-off-by: Florian Vaussard Acked-by: Nishanth Menon Signed-off-by: Tony Lindgren --- Documentation/devicetree/bindings/arm/omap/omap.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/arm/omap/omap.txt b/Documentation/devicetree/bindings/arm/omap/omap.txt index 34dc40cffdfd..af9b4a0d902b 100644 --- a/Documentation/devicetree/bindings/arm/omap/omap.txt +++ b/Documentation/devicetree/bindings/arm/omap/omap.txt @@ -91,7 +91,7 @@ Boards: compatible = "ti,omap3-beagle", "ti,omap3" - OMAP3 Tobi with Overo : Commercial expansion board with daughter board - compatible = "ti,omap3-tobi", "ti,omap3-overo", "ti,omap3" + compatible = "gumstix,omap3-overo-tobi", "gumstix,omap3-overo", "ti,omap3" - OMAP4 SDP : Software Development Board compatible = "ti,omap4-sdp", "ti,omap4430" -- cgit v1.2.3 From d43ff4cd798911736fb39025ec8004284b1b0bc2 Mon Sep 17 00:00:00 2001 From: Emil Goode Date: Thu, 13 Feb 2014 19:30:39 +0100 Subject: net: asix: add missing flag to struct driver_info MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The struct driver_info ax88178_info is assigned the function asix_rx_fixup_common as it's rx_fixup callback. This means that FLAG_MULTI_PACKET must be set as this function is cloning the data and calling usbnet_skb_return. Not setting this flag leads to usbnet_skb_return beeing called a second time from within the rx_process function in the usbnet module. Signed-off-by: Emil Goode Reported-by: Bjørn Mork Signed-off-by: David S. Miller --- drivers/net/usb/asix_devices.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c index 9765a7d4766d..5d194093f3e1 100644 --- a/drivers/net/usb/asix_devices.c +++ b/drivers/net/usb/asix_devices.c @@ -917,7 +917,8 @@ static const struct driver_info ax88178_info = { .status = asix_status, .link_reset = ax88178_link_reset, .reset = ax88178_reset, - .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR, + .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR | + FLAG_MULTI_PACKET, .rx_fixup = asix_rx_fixup_common, .tx_fixup = asix_tx_fixup, }; -- cgit v1.2.3 From 1f42db786b14a31bf807fc41ee5583a00c08fcb1 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 14 Feb 2014 13:48:16 -0700 Subject: PCI: Enable INTx if BIOS left them disabled Some firmware leaves the Interrupt Disable bit set even if the device uses INTx interrupts. Clear Interrupt Disable so we get those interrupts. Based on the report mentioned below, if the user selects the "EHCI only" option in the Intel Baytrail BIOS, the EHCI device is handed off to the OS with the PCI_COMMAND_INTX_DISABLE bit set. Link: http://lkml.kernel.org/r/20140114181721.GC12126@xanatos Link: https://bugzilla.kernel.org/show_bug.cgi?id=70601 Reported-by: Chris Cheng Reported-and-tested-by: Jamie Chen Signed-off-by: Bjorn Helgaas CC: stable@vger.kernel.org CC: Sarah Sharp --- drivers/pci/pci.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 1febe90831b4..6b05f6134b68 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1181,6 +1181,8 @@ EXPORT_SYMBOL_GPL(pci_load_and_free_saved_state); static int do_pci_enable_device(struct pci_dev *dev, int bars) { int err; + u16 cmd; + u8 pin; err = pci_set_power_state(dev, PCI_D0); if (err < 0 && err != -EIO) @@ -1190,6 +1192,14 @@ static int do_pci_enable_device(struct pci_dev *dev, int bars) return err; pci_fixup_device(pci_fixup_enable, dev); + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); + if (pin) { + pci_read_config_word(dev, PCI_COMMAND, &cmd); + if (cmd & PCI_COMMAND_INTX_DISABLE) + pci_write_config_word(dev, PCI_COMMAND, + cmd & ~PCI_COMMAND_INTX_DISABLE); + } + return 0; } -- cgit v1.2.3 From ce11c436720cdb8437340be93b2f5efe23ce3e1c Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Thu, 13 Feb 2014 13:14:48 -0800 Subject: net: of_mdio: fix of_set_phy_supported after driver probing Commit 8fdade4 ("net: of_mdio: parse "max-speed" property to set PHY supported features") introduced a typo in of_set_phy_supported for the first assignment of phydev->supported which will not effectively limit the PHY device supported features bits if the PHY driver contains "higher" features (e.g: max-speed = <100> and PHY driver has PHY_GBIT_FEATURES set). Fix this by making sure that the very first thing is to reset to sane defaults (PHY_BASIC_FEATURES) and then progressively add speed features as we parse them. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/of/of_mdio.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c index 875b7b6f0d2a..495faccba763 100644 --- a/drivers/of/of_mdio.c +++ b/drivers/of/of_mdio.c @@ -24,7 +24,11 @@ MODULE_LICENSE("GPL"); static void of_set_phy_supported(struct phy_device *phydev, u32 max_speed) { - phydev->supported |= PHY_DEFAULT_FEATURES; + /* The default values for phydev->supported are provided by the PHY + * driver "features" member, we want to reset to sane defaults fist + * before supporting higher speeds. + */ + phydev->supported &= PHY_DEFAULT_FEATURES; switch (max_speed) { default: -- cgit v1.2.3 From eb2d4c64879c99fc78e739b0147db28731ff474e Mon Sep 17 00:00:00 2001 From: Mike Galbraith Date: Fri, 14 Feb 2014 08:21:04 +0100 Subject: net,bonding: fix bond_options.c direct rwlock.h include drivers/net/bonding/bond_options.c includes rwlock.h directly, which is a nono, and which also breaks RT kernel build. Signed-off-by: Mike Galbraith Signed-off-by: David S. Miller --- drivers/net/bonding/bond_options.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c index 11cb943222d5..c37878432717 100644 --- a/drivers/net/bonding/bond_options.c +++ b/drivers/net/bonding/bond_options.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include #include -- cgit v1.2.3 From fc40363b2140f5777c88e67814fac9327bf1ee68 Mon Sep 17 00:00:00 2001 From: Alexander Gordeev Date: Fri, 14 Feb 2014 14:27:19 -0700 Subject: ahci: Fix broken fallback to single MSI mode Commit 7b92b4f61ec4 ("PCI/MSI: Remove pci_enable_msi_block_auto()") introduced a regression: if multiple MSI initialization fails, the code falls back to INTx rather than to single MSI. Fixes: 7b92b4f61ec4 ("PCI/MSI: Remove pci_enable_msi_block_auto()") Signed-off-by: Alexander Gordeev Signed-off-by: Bjorn Helgaas Acked-by: Tejun Heo --- drivers/ata/ahci.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index dc2756fb6f33..3c5f35ef7e55 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -1170,8 +1170,10 @@ static int ahci_init_interrupts(struct pci_dev *pdev, unsigned int n_ports, nvec = rc; rc = pci_enable_msi_block(pdev, nvec); - if (rc) + if (rc < 0) goto intx; + else if (rc > 0) + goto single_msi; return nvec; -- cgit v1.2.3 From 5d81de8e8667da7135d3a32a964087c0faf5483f Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Fri, 14 Feb 2014 07:20:35 -0500 Subject: cifs: ensure that uncached writes handle unmapped areas correctly It's possible for userland to pass down an iovec via writev() that has a bogus user pointer in it. If that happens and we're doing an uncached write, then we can end up getting less bytes than we expect from the call to iov_iter_copy_from_user. This is CVE-2014-0069 cifs_iovec_write isn't set up to handle that situation however. It'll blindly keep chugging through the page array and not filling those pages with anything useful. Worse yet, we'll later end up with a negative number in wdata->tailsz, which will confuse the sending routines and cause an oops at the very least. Fix this by having the copy phase of cifs_iovec_write stop copying data in this situation and send the last write as a short one. At the same time, we want to avoid sending a zero-length write to the server, so break out of the loop and set rc to -EFAULT if that happens. This also allows us to handle the case where no address in the iovec is valid. [Note: Marking this for stable on v3.4+ kernels, but kernels as old as v2.6.38 may have a similar problem and may need similar fix] Cc: # v3.4+ Reviewed-by: Pavel Shilovsky Reported-by: Al Viro Signed-off-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/file.c | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 290b4966004f..18758bcd4dab 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -2389,7 +2389,7 @@ cifs_iovec_write(struct file *file, const struct iovec *iov, unsigned long nr_segs, loff_t *poffset) { unsigned long nr_pages, i; - size_t copied, len, cur_len; + size_t bytes, copied, len, cur_len; ssize_t total_written = 0; loff_t offset; struct iov_iter it; @@ -2444,14 +2444,45 @@ cifs_iovec_write(struct file *file, const struct iovec *iov, save_len = cur_len; for (i = 0; i < nr_pages; i++) { - copied = min_t(const size_t, cur_len, PAGE_SIZE); + bytes = min_t(const size_t, cur_len, PAGE_SIZE); copied = iov_iter_copy_from_user(wdata->pages[i], &it, - 0, copied); + 0, bytes); cur_len -= copied; iov_iter_advance(&it, copied); + /* + * If we didn't copy as much as we expected, then that + * may mean we trod into an unmapped area. Stop copying + * at that point. On the next pass through the big + * loop, we'll likely end up getting a zero-length + * write and bailing out of it. + */ + if (copied < bytes) + break; } cur_len = save_len - cur_len; + /* + * If we have no data to send, then that probably means that + * the copy above failed altogether. That's most likely because + * the address in the iovec was bogus. Set the rc to -EFAULT, + * free anything we allocated and bail out. + */ + if (!cur_len) { + for (i = 0; i < nr_pages; i++) + put_page(wdata->pages[i]); + kfree(wdata); + rc = -EFAULT; + break; + } + + /* + * i + 1 now represents the number of pages we actually used in + * the copy phase above. Bring nr_pages down to that, and free + * any pages that we didn't use. + */ + for ( ; nr_pages > i + 1; nr_pages--) + put_page(wdata->pages[nr_pages - 1]); + wdata->sync_mode = WB_SYNC_ALL; wdata->nr_pages = nr_pages; wdata->offset = (__u64)offset; -- cgit v1.2.3 From 2365c4eaf077c48574ab6f143960048fc0f31518 Mon Sep 17 00:00:00 2001 From: Pavel Shilovsky Date: Fri, 14 Feb 2014 13:31:02 +0400 Subject: CIFS: Fix too big maxBuf size for SMB3 mounts SMB3 servers can respond with MaxTransactSize of more than 4M that can cause a memory allocation error returned from kmalloc in a lock codepath. Also the client doesn't support multicredit requests now and allows buffer sizes of 65536 bytes only. Set MaxTransactSize to this maximum supported value. Cc: stable@vger.kernel.org # 3.7+ Signed-off-by: Pavel Shilovsky Acked-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/smb2glob.h | 3 +++ fs/cifs/smb2ops.c | 14 ++++---------- fs/cifs/smb2pdu.c | 4 +++- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/fs/cifs/smb2glob.h b/fs/cifs/smb2glob.h index c38350851b08..bc0bb9c34f72 100644 --- a/fs/cifs/smb2glob.h +++ b/fs/cifs/smb2glob.h @@ -57,4 +57,7 @@ #define SMB2_CMACAES_SIZE (16) #define SMB3_SIGNKEY_SIZE (16) +/* Maximum buffer size value we can send with 1 credit */ +#define SMB2_MAX_BUFFER_SIZE 65536 + #endif /* _SMB2_GLOB_H */ diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index 757da3e54d3d..192f51a12cf1 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c @@ -182,11 +182,8 @@ smb2_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *volume_info) /* start with specified wsize, or default */ wsize = volume_info->wsize ? volume_info->wsize : CIFS_DEFAULT_IOSIZE; wsize = min_t(unsigned int, wsize, server->max_write); - /* - * limit write size to 2 ** 16, because we don't support multicredit - * requests now. - */ - wsize = min_t(unsigned int, wsize, 2 << 15); + /* set it to the maximum buffer size value we can send with 1 credit */ + wsize = min_t(unsigned int, wsize, SMB2_MAX_BUFFER_SIZE); return wsize; } @@ -200,11 +197,8 @@ smb2_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *volume_info) /* start with specified rsize, or default */ rsize = volume_info->rsize ? volume_info->rsize : CIFS_DEFAULT_IOSIZE; rsize = min_t(unsigned int, rsize, server->max_read); - /* - * limit write size to 2 ** 16, because we don't support multicredit - * requests now. - */ - rsize = min_t(unsigned int, rsize, 2 << 15); + /* set it to the maximum buffer size value we can send with 1 credit */ + rsize = min_t(unsigned int, rsize, SMB2_MAX_BUFFER_SIZE); return rsize; } diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index a3f7a9c3cc69..860344701067 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -413,7 +413,9 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses) /* SMB2 only has an extended negflavor */ server->negflavor = CIFS_NEGFLAVOR_EXTENDED; - server->maxBuf = le32_to_cpu(rsp->MaxTransactSize); + /* set it to the maximum buffer size value we can send with 1 credit */ + server->maxBuf = min_t(unsigned int, le32_to_cpu(rsp->MaxTransactSize), + SMB2_MAX_BUFFER_SIZE); server->max_read = le32_to_cpu(rsp->MaxReadSize); server->max_write = le32_to_cpu(rsp->MaxWriteSize); /* BB Do we need to validate the SecurityMode? */ -- cgit v1.2.3 From ab62f9cd7b5ecdf853f1612fe1e983cb7cbbac3e Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 15 Feb 2014 01:29:06 +0100 Subject: ACPI / dock: Make 'docked' sysfs attribute work as documented After recent ACPI core changes acpi_bus_get_device() will always succeed for dock station ACPI device objects, so show_docked() should not use that function's return value as an indicator of whether or not the dock device is present. Make it use acpi_device_enumerated() for this purpose. Fixes: 202317a573b2 (ACPI / scan: Add acpi_device objects for all device nodes in the namespace) Signed-off-by: Rafael J. Wysocki --- drivers/acpi/dock.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index e9b3081c4fe9..5bfd769fc91f 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -713,13 +713,11 @@ static acpi_status __init find_dock_devices(acpi_handle handle, u32 lvl, static ssize_t show_docked(struct device *dev, struct device_attribute *attr, char *buf) { - struct acpi_device *tmp; - struct dock_station *dock_station = dev->platform_data; + struct acpi_device *adev = NULL; - if (!acpi_bus_get_device(dock_station->handle, &tmp)) - return snprintf(buf, PAGE_SIZE, "1\n"); - return snprintf(buf, PAGE_SIZE, "0\n"); + acpi_bus_get_device(dock_station->handle, &adev); + return snprintf(buf, PAGE_SIZE, "%u\n", acpi_device_enumerated(adev)); } static DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL); -- cgit v1.2.3 From 9febd494d15c4a351e9c9cae7184643144eea892 Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Sat, 15 Feb 2014 23:28:29 +0400 Subject: ASoC: txx9aclc_ac97: Fix kernel crash on probe This patch fixes a crash caused by commit 3bed3344c826 (ASoC: txx9aclc_ac97: Convert to devm_ioremap_resource()). This is an attempt to assign "drvdata->base" while memory for "drvdata" is not already allocated. Fixes: 3bed3344c826 (ASoC: txx9aclc_ac97: Convert to devm_ioremap_resource()) Signed-off-by: Alexander Shiyan Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- sound/soc/txx9/txx9aclc-ac97.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sound/soc/txx9/txx9aclc-ac97.c b/sound/soc/txx9/txx9aclc-ac97.c index e0305a148568..9edd68db9f48 100644 --- a/sound/soc/txx9/txx9aclc-ac97.c +++ b/sound/soc/txx9/txx9aclc-ac97.c @@ -183,14 +183,16 @@ static int txx9aclc_ac97_dev_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) return irq; + + drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL); + if (!drvdata) + return -ENOMEM; + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); drvdata->base = devm_ioremap_resource(&pdev->dev, r); if (IS_ERR(drvdata->base)) return PTR_ERR(drvdata->base); - drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL); - if (!drvdata) - return -ENOMEM; platform_set_drvdata(pdev, drvdata); drvdata->physbase = r->start; if (sizeof(drvdata->physbase) > sizeof(r->start) && -- cgit v1.2.3 From e126a646f77fdd66978785cb0a3a5e46b07aee2e Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Thu, 13 Feb 2014 16:54:24 -0700 Subject: ASoC: max98090: make REVISION_ID readable The REVISION_ID register is not currently marked readable. snd_soc_read() refuses to read the register, and hence probe() fails. Fixes: d4807ad2c4c0 ("regmap: Check readable regs in _regmap_read") [exposed the bug, by checking for readability] Fixes: 685e42154dcf ("ASoC: Replace max98090 Device Driver") [left out this register from the readable list] Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- sound/soc/codecs/max98090.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c index 149b57f6334b..9f714ea86613 100644 --- a/sound/soc/codecs/max98090.c +++ b/sound/soc/codecs/max98090.c @@ -336,6 +336,7 @@ static bool max98090_readable_register(struct device *dev, unsigned int reg) case M98090_REG_RECORD_TDM_SLOT: case M98090_REG_SAMPLE_RATE: case M98090_REG_DMIC34_BIQUAD_BASE ... M98090_REG_DMIC34_BIQUAD_BASE + 0x0E: + case M98090_REG_REVISION_ID: return true; default: return false; -- cgit v1.2.3 From b93c95353413041a8cebad915a8109619f66bcc6 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sat, 15 Feb 2014 21:33:13 -0500 Subject: ext4: fix online resize with very large inode tables If a file system has a large number of inodes per block group, all of the metadata blocks in a flex_bg may be larger than what can fit in a single block group. Unfortunately, ext4_alloc_group_tables() in resize.c was never tested to see if it would handle this case correctly, and there were a large number of bugs which caused the following sequence to result in a BUG_ON: kernel bug at fs/ext4/resize.c:409! ... call trace: [] ext4_flex_group_add+0x1448/0x1830 [] ext4_resize_fs+0x7b2/0xe80 [] ext4_ioctl+0xbf0/0xf00 [] do_vfs_ioctl+0x2dd/0x4b0 [] ? final_putname+0x22/0x50 [] sys_ioctl+0x81/0xa0 [] system_call_fastpath+0x16/0x1b code: c8 4c 89 df e8 41 96 f8 ff 44 89 e8 49 01 c4 44 29 6d d4 0 rip [] set_flexbg_block_bitmap+0x171/0x180 This can be reproduced with the following command sequence: mke2fs -t ext4 -i 4096 /dev/vdd 1G mount -t ext4 /dev/vdd /vdd resize2fs /dev/vdd 8G To fix this, we need to make sure the right thing happens when a block group's inode table straddles two block groups, which means the following bugs had to be fixed: 1) Not clearing the BLOCK_UNINIT flag in the second block group in ext4_alloc_group_tables --- the was proximate cause of the BUG_ON. 2) Incorrectly determining how many block groups contained contiguous free blocks in ext4_alloc_group_tables(). 3) Incorrectly setting the start of the next block range to be marked in use after a discontinuity in setup_new_flex_group_blocks(). Signed-off-by: "Theodore Ts'o" Cc: stable@vger.kernel.org --- fs/ext4/resize.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index c5adbb318a90..69a62610a6ca 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c @@ -243,6 +243,7 @@ static int ext4_alloc_group_tables(struct super_block *sb, ext4_group_t group; ext4_group_t last_group; unsigned overhead; + __u16 uninit_mask = (flexbg_size > 1) ? ~EXT4_BG_BLOCK_UNINIT : ~0; BUG_ON(flex_gd->count == 0 || group_data == NULL); @@ -266,7 +267,7 @@ next_group: src_group++; for (; src_group <= last_group; src_group++) { overhead = ext4_group_overhead_blocks(sb, src_group); - if (overhead != 0) + if (overhead == 0) last_blk += group_data[src_group - group].blocks_count; else break; @@ -280,8 +281,7 @@ next_group: group = ext4_get_group_number(sb, start_blk - 1); group -= group_data[0].group; group_data[group].free_blocks_count--; - if (flexbg_size > 1) - flex_gd->bg_flags[group] &= ~EXT4_BG_BLOCK_UNINIT; + flex_gd->bg_flags[group] &= uninit_mask; } /* Allocate inode bitmaps */ @@ -292,22 +292,30 @@ next_group: group = ext4_get_group_number(sb, start_blk - 1); group -= group_data[0].group; group_data[group].free_blocks_count--; - if (flexbg_size > 1) - flex_gd->bg_flags[group] &= ~EXT4_BG_BLOCK_UNINIT; + flex_gd->bg_flags[group] &= uninit_mask; } /* Allocate inode tables */ for (; it_index < flex_gd->count; it_index++) { - if (start_blk + EXT4_SB(sb)->s_itb_per_group > last_blk) + unsigned int itb = EXT4_SB(sb)->s_itb_per_group; + ext4_fsblk_t next_group_start; + + if (start_blk + itb > last_blk) goto next_group; group_data[it_index].inode_table = start_blk; - group = ext4_get_group_number(sb, start_blk - 1); + group = ext4_get_group_number(sb, start_blk); + next_group_start = ext4_group_first_block_no(sb, group + 1); group -= group_data[0].group; - group_data[group].free_blocks_count -= - EXT4_SB(sb)->s_itb_per_group; - if (flexbg_size > 1) - flex_gd->bg_flags[group] &= ~EXT4_BG_BLOCK_UNINIT; + if (start_blk + itb > next_group_start) { + flex_gd->bg_flags[group + 1] &= uninit_mask; + overhead = start_blk + itb - next_group_start; + group_data[group + 1].free_blocks_count -= overhead; + itb -= overhead; + } + + group_data[group].free_blocks_count -= itb; + flex_gd->bg_flags[group] &= uninit_mask; start_blk += EXT4_SB(sb)->s_itb_per_group; } @@ -620,7 +628,7 @@ handle_ib: if (err) goto out; count = group_table_count[j]; - start = group_data[i].block_bitmap; + start = (&group_data[i].block_bitmap)[j]; block = start; } -- cgit v1.2.3 From 3d2660d0c9c2f296837078c189b68a47f6b2e3b5 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sat, 15 Feb 2014 22:42:25 -0500 Subject: ext4: fix online resize with a non-standard blocks per group setting The set_flexbg_block_bitmap() function assumed that the number of blocks in a blockgroup was sb->blocksize * 8, which is normally true, but not always! Use EXT4_BLOCKS_PER_GROUP(sb) instead, to fix block bitmap corruption after: mke2fs -t ext4 -g 3072 -i 4096 /dev/vdd 1G mount -t ext4 /dev/vdd /vdd resize2fs /dev/vdd 8G Signed-off-by: "Theodore Ts'o" Reported-by: Jon Bernard Cc: stable@vger.kernel.org --- fs/ext4/resize.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index 69a62610a6ca..f3b84cd9de56 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c @@ -409,7 +409,7 @@ static int set_flexbg_block_bitmap(struct super_block *sb, handle_t *handle, start = ext4_group_first_block_no(sb, group); group -= flex_gd->groups[0].group; - count2 = sb->s_blocksize * 8 - (block - start); + count2 = EXT4_BLOCKS_PER_GROUP(sb) - (block - start); if (count2 > count) count2 = count; -- cgit v1.2.3 From 8ad116e649b21a42e3cccfb3c1b8d5ea52ba19e5 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Sun, 16 Feb 2014 12:29:53 -0300 Subject: ata: sata_mv: Cleanup only the initialized ports When an error occurs in the port initialization loop, currently the driver tries to cleanup all the ports. This results in a NULL pointer dereference if the ports were only partially initialized. Fix this by updating only the number of initialized ports (either with failure or successfully), before jumping to the error path and looping over that number in the cleanup loop. Cc: Andrew Lunn Reported-by: Mikael Pettersson Signed-off-by: Ezequiel Garcia Signed-off-by: Tejun Heo Cc: stable@vger.kernel.org --- drivers/ata/sata_mv.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 20a7517bd339..9c1a11de3044 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -4104,7 +4104,6 @@ static int mv_platform_probe(struct platform_device *pdev) if (!hpriv->port_phys) return -ENOMEM; host->private_data = hpriv; - hpriv->n_ports = n_ports; hpriv->board_idx = chip_soc; host->iomap = NULL; @@ -4132,11 +4131,17 @@ static int mv_platform_probe(struct platform_device *pdev) hpriv->port_phys[port] = NULL; if ((rc != -EPROBE_DEFER) && (rc != -ENODEV)) dev_warn(&pdev->dev, "error getting phy"); + + /* Cleanup only the initialized ports */ + hpriv->n_ports = port; goto err; } else phy_power_on(hpriv->port_phys[port]); } + /* All the ports have been initialized */ + hpriv->n_ports = n_ports; + /* * (Re-)program MBUS remapping windows if we are asked to. */ @@ -4174,7 +4179,7 @@ err: clk_disable_unprepare(hpriv->clk); clk_put(hpriv->clk); } - for (port = 0; port < n_ports; port++) { + for (port = 0; port < hpriv->n_ports; port++) { if (!IS_ERR(hpriv->port_clks[port])) { clk_disable_unprepare(hpriv->port_clks[port]); clk_put(hpriv->port_clks[port]); -- cgit v1.2.3 From 9eb2ddb48ce3a7bd745c14a933112994647fa3cd Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Sun, 16 Feb 2014 12:14:13 -0500 Subject: SUNRPC: Ensure that gss_auth isn't freed before its upcall messages Fix a race in which the RPC client is shutting down while the gss daemon is processing a downcall. If the RPC client manages to shut down before the gss daemon is done, then the struct gss_auth used in gss_release_msg() may have already been freed. Link: http://lkml.kernel.org/r/1392494917.71728.YahooMailNeo@web140002.mail.bf1.yahoo.com Reported-by: John Reported-by: Borislav Petkov Cc: stable@vger.kernel.org # 3.12+ Signed-off-by: Trond Myklebust --- net/sunrpc/auth_gss/auth_gss.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 44a61e8fda6f..1ba1fd114912 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -108,6 +108,7 @@ struct gss_auth { static DEFINE_SPINLOCK(pipe_version_lock); static struct rpc_wait_queue pipe_version_rpc_waitqueue; static DECLARE_WAIT_QUEUE_HEAD(pipe_version_waitqueue); +static void gss_put_auth(struct gss_auth *gss_auth); static void gss_free_ctx(struct gss_cl_ctx *); static const struct rpc_pipe_ops gss_upcall_ops_v0; @@ -320,6 +321,7 @@ gss_release_msg(struct gss_upcall_msg *gss_msg) if (gss_msg->ctx != NULL) gss_put_ctx(gss_msg->ctx); rpc_destroy_wait_queue(&gss_msg->rpc_waitqueue); + gss_put_auth(gss_msg->auth); kfree(gss_msg); } @@ -500,6 +502,7 @@ gss_alloc_msg(struct gss_auth *gss_auth, if (err) goto err_free_msg; }; + kref_get(&gss_auth->kref); return gss_msg; err_free_msg: kfree(gss_msg); @@ -1063,6 +1066,12 @@ gss_free_callback(struct kref *kref) gss_free(gss_auth); } +static void +gss_put_auth(struct gss_auth *gss_auth) +{ + kref_put(&gss_auth->kref, gss_free_callback); +} + static void gss_destroy(struct rpc_auth *auth) { @@ -1084,7 +1093,7 @@ gss_destroy(struct rpc_auth *auth) gss_auth->gss_pipe[1] = NULL; rpcauth_destroy_credcache(auth); - kref_put(&gss_auth->kref, gss_free_callback); + gss_put_auth(gss_auth); } /* @@ -1255,7 +1264,7 @@ gss_destroy_nullcred(struct rpc_cred *cred) call_rcu(&cred->cr_rcu, gss_free_cred_callback); if (ctx) gss_put_ctx(ctx); - kref_put(&gss_auth->kref, gss_free_callback); + gss_put_auth(gss_auth); } static void -- cgit v1.2.3 From e9776d0f4adee8877145672f6416b06b57f2dc27 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Sun, 16 Feb 2014 13:28:01 -0500 Subject: SUNRPC: Fix a pipe_version reference leak In gss_alloc_msg(), if the call to gss_encode_v1_msg() fails, we want to release the reference to the pipe_version that was obtained earlier in the function. Fixes: 9d3a2260f0f4b (SUNRPC: Fix buffer overflow checking in...) Signed-off-by: Trond Myklebust --- net/sunrpc/auth_gss/auth_gss.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 1ba1fd114912..36e431ee1c90 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -500,10 +500,12 @@ gss_alloc_msg(struct gss_auth *gss_auth, default: err = gss_encode_v1_msg(gss_msg, service_name, gss_auth->target_name); if (err) - goto err_free_msg; + goto err_put_pipe_version; }; kref_get(&gss_auth->kref); return gss_msg; +err_put_pipe_version: + put_pipe_version(gss_auth->net); err_free_msg: kfree(gss_msg); err: -- cgit v1.2.3 From 1a18a66446f3f289b05b634f18012424d82aa63a Mon Sep 17 00:00:00 2001 From: Kevin Hao Date: Fri, 17 Jan 2014 12:25:28 +0800 Subject: powerpc: Set the correct ksp_limit on ppc32 when switching to irq stack Guenter Roeck has got the following call trace on a p2020 board: Kernel stack overflow in process eb3e5a00, r1=eb79df90 CPU: 0 PID: 2838 Comm: ssh Not tainted 3.13.0-rc8-juniper-00146-g19eca00 #4 task: eb3e5a00 ti: c0616000 task.ti: ef440000 NIP: c003a420 LR: c003a410 CTR: c0017518 REGS: eb79dee0 TRAP: 0901 Not tainted (3.13.0-rc8-juniper-00146-g19eca00) MSR: 00029000 CR: 24008444 XER: 00000000 GPR00: c003a410 eb79df90 eb3e5a00 00000000 eb05d900 00000001 65d87646 00000000 GPR08: 00000000 020b8000 00000000 00000000 44008442 NIP [c003a420] __do_softirq+0x94/0x1ec LR [c003a410] __do_softirq+0x84/0x1ec Call Trace: [eb79df90] [c003a410] __do_softirq+0x84/0x1ec (unreliable) [eb79dfe0] [c003a970] irq_exit+0xbc/0xc8 [eb79dff0] [c000cc1c] call_do_irq+0x24/0x3c [ef441f20] [c00046a8] do_IRQ+0x8c/0xf8 [ef441f40] [c000e7f4] ret_from_except+0x0/0x18 --- Exception: 501 at 0xfcda524 LR = 0x10024900 Instruction dump: 7c781b78 3b40000a 3a73b040 543c0024 3a800000 3b3913a0 7ef5bb78 48201bf9 5463103a 7d3b182e 7e89b92e 7c008146 <3ba00000> 7e7e9b78 48000014 57fff87f Kernel panic - not syncing: kernel stack overflow CPU: 0 PID: 2838 Comm: ssh Not tainted 3.13.0-rc8-juniper-00146-g19eca00 #4 Call Trace: The reason is that we have used the wrong register to calculate the ksp_limit in commit cbc9565ee826 (powerpc: Remove ksp_limit on ppc64). Just fix it. As suggested by Benjamin Herrenschmidt, also add the C prototype of the function in the comment in order to avoid such kind of errors in the future. Cc: stable@vger.kernel.org # 3.12 Reported-by: Guenter Roeck Tested-by: Guenter Roeck Signed-off-by: Kevin Hao Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/kernel/misc_32.S | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S index 879f09620f83..7c6bb4b17b49 100644 --- a/arch/powerpc/kernel/misc_32.S +++ b/arch/powerpc/kernel/misc_32.S @@ -57,11 +57,14 @@ _GLOBAL(call_do_softirq) mtlr r0 blr +/* + * void call_do_irq(struct pt_regs *regs, struct thread_info *irqtp); + */ _GLOBAL(call_do_irq) mflr r0 stw r0,4(r1) lwz r10,THREAD+KSP_LIMIT(r2) - addi r11,r3,THREAD_INFO_GAP + addi r11,r4,THREAD_INFO_GAP stwu r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r4) mr r1,r4 stw r10,8(r1) -- cgit v1.2.3 From b020cc6c03a37c3526fcb1dff274f649257949e0 Mon Sep 17 00:00:00 2001 From: Kleber Sacilotto de Souza Date: Fri, 17 Jan 2014 11:56:51 -0200 Subject: powerpc/pseries: Fix regression on PCI link speed Commit 5091f0c (powerpc/pseries: Fix PCIE link speed endian issue) introduced a regression on the PCI link speed detection using the device-tree property. The ibm,pcie-link-speed-stats property is composed of two 32-bit integers, the first one being the maxinum link speed and the second the current link speed. The changes introduced by the aforementioned commit are considering just the first integer. Fix this issue by changing how the property is accessed, using the helper functions to properly access the array of values. The explicit byte swapping is not needed anymore here, since it's done by the helper functions. Signed-off-by: Kleber Sacilotto de Souza Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/platforms/pseries/pci.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/arch/powerpc/platforms/pseries/pci.c b/arch/powerpc/platforms/pseries/pci.c index 70670a2d9cf2..a6f7a1460e2f 100644 --- a/arch/powerpc/platforms/pseries/pci.c +++ b/arch/powerpc/platforms/pseries/pci.c @@ -113,7 +113,8 @@ int pseries_root_bridge_prepare(struct pci_host_bridge *bridge) { struct device_node *dn, *pdn; struct pci_bus *bus; - const __be32 *pcie_link_speed_stats; + u32 pcie_link_speed_stats[2]; + int rc; bus = bridge->bus; @@ -122,20 +123,21 @@ int pseries_root_bridge_prepare(struct pci_host_bridge *bridge) return 0; for (pdn = dn; pdn != NULL; pdn = of_get_next_parent(pdn)) { - pcie_link_speed_stats = of_get_property(pdn, - "ibm,pcie-link-speed-stats", NULL); - if (pcie_link_speed_stats) + rc = of_property_read_u32_array(pdn, + "ibm,pcie-link-speed-stats", + &pcie_link_speed_stats[0], 2); + if (!rc) break; } of_node_put(pdn); - if (!pcie_link_speed_stats) { + if (rc) { pr_err("no ibm,pcie-link-speed-stats property\n"); return 0; } - switch (be32_to_cpup(pcie_link_speed_stats)) { + switch (pcie_link_speed_stats[0]) { case 0x01: bus->max_bus_speed = PCIE_SPEED_2_5GT; break; @@ -147,7 +149,7 @@ int pseries_root_bridge_prepare(struct pci_host_bridge *bridge) break; } - switch (be32_to_cpup(pcie_link_speed_stats)) { + switch (pcie_link_speed_stats[1]) { case 0x01: bus->cur_bus_speed = PCIE_SPEED_2_5GT; break; -- cgit v1.2.3 From 49d9684a54d21930372b7fb0d3d7b5617f621706 Mon Sep 17 00:00:00 2001 From: Kleber Sacilotto de Souza Date: Fri, 17 Jan 2014 11:56:52 -0200 Subject: powerpc/pseries: Add Gen3 definitions for PCIE link speed Rev3 of the PCI Express Base Specification defines a Supported Link Speeds Vector where the bit definitions within this field are: Bit 0 - 2.5 GT/s Bit 1 - 5.0 GT/s Bit 2 - 8.0 GT/s This vector definition is used by the platform firmware to export the maximum and current link speeds of the PCI bus via the "ibm,pcie-link-speed-stats" device-tree property. This patch updates pseries_root_bridge_prepare() to detect Gen3 speed buses (defined by 0x04). Signed-off-by: Kleber Sacilotto de Souza Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/platforms/pseries/pci.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/powerpc/platforms/pseries/pci.c b/arch/powerpc/platforms/pseries/pci.c index a6f7a1460e2f..c413ec158ff5 100644 --- a/arch/powerpc/platforms/pseries/pci.c +++ b/arch/powerpc/platforms/pseries/pci.c @@ -144,6 +144,9 @@ int pseries_root_bridge_prepare(struct pci_host_bridge *bridge) case 0x02: bus->max_bus_speed = PCIE_SPEED_5_0GT; break; + case 0x04: + bus->max_bus_speed = PCIE_SPEED_8_0GT; + break; default: bus->max_bus_speed = PCI_SPEED_UNKNOWN; break; @@ -156,6 +159,9 @@ int pseries_root_bridge_prepare(struct pci_host_bridge *bridge) case 0x02: bus->cur_bus_speed = PCIE_SPEED_5_0GT; break; + case 0x04: + bus->cur_bus_speed = PCIE_SPEED_8_0GT; + break; default: bus->cur_bus_speed = PCI_SPEED_UNKNOWN; break; -- cgit v1.2.3 From 88247e8d7ba6639f2c199e147ebbc91f7673150c Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Wed, 12 Feb 2014 09:13:36 +0530 Subject: powerpc/mm: Add new "set" flag argument to pte/pmd update function pte_update() is a powerpc-ism used to change the bits of a PTE when the access permission is being restricted (a flush is potentially needed). It uses atomic operations on when needed and handles the hash synchronization on hash based processors. It is currently only used to clear PTE bits and so the current implementation doesn't provide a way to also set PTE bits. The new _PAGE_NUMA bit, when set, is actually restricting access so it must use that function too, so this change adds the ability for pte_update() to also set bits. We will use this later to set the _PAGE_NUMA bit. Acked-by: Mel Gorman Acked-by: Rik van Riel Signed-off-by: Aneesh Kumar K.V Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/include/asm/hugetlb.h | 2 +- arch/powerpc/include/asm/pgtable-ppc64.h | 26 +++++++++++++++----------- arch/powerpc/mm/pgtable_64.c | 12 +++++++----- arch/powerpc/mm/subpage-prot.c | 2 +- 4 files changed, 24 insertions(+), 18 deletions(-) diff --git a/arch/powerpc/include/asm/hugetlb.h b/arch/powerpc/include/asm/hugetlb.h index d750336b171d..623f2971ce0e 100644 --- a/arch/powerpc/include/asm/hugetlb.h +++ b/arch/powerpc/include/asm/hugetlb.h @@ -127,7 +127,7 @@ static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { #ifdef CONFIG_PPC64 - return __pte(pte_update(mm, addr, ptep, ~0UL, 1)); + return __pte(pte_update(mm, addr, ptep, ~0UL, 0, 1)); #else return __pte(pte_update(ptep, ~0UL, 0)); #endif diff --git a/arch/powerpc/include/asm/pgtable-ppc64.h b/arch/powerpc/include/asm/pgtable-ppc64.h index bc141c950b1e..eb9261024f51 100644 --- a/arch/powerpc/include/asm/pgtable-ppc64.h +++ b/arch/powerpc/include/asm/pgtable-ppc64.h @@ -195,6 +195,7 @@ extern void hpte_need_flush(struct mm_struct *mm, unsigned long addr, static inline unsigned long pte_update(struct mm_struct *mm, unsigned long addr, pte_t *ptep, unsigned long clr, + unsigned long set, int huge) { #ifdef PTE_ATOMIC_UPDATES @@ -205,14 +206,15 @@ static inline unsigned long pte_update(struct mm_struct *mm, andi. %1,%0,%6\n\ bne- 1b \n\ andc %1,%0,%4 \n\ + or %1,%1,%7\n\ stdcx. %1,0,%3 \n\ bne- 1b" : "=&r" (old), "=&r" (tmp), "=m" (*ptep) - : "r" (ptep), "r" (clr), "m" (*ptep), "i" (_PAGE_BUSY) + : "r" (ptep), "r" (clr), "m" (*ptep), "i" (_PAGE_BUSY), "r" (set) : "cc" ); #else unsigned long old = pte_val(*ptep); - *ptep = __pte(old & ~clr); + *ptep = __pte((old & ~clr) | set); #endif /* huge pages use the old page table lock */ if (!huge) @@ -231,9 +233,9 @@ static inline int __ptep_test_and_clear_young(struct mm_struct *mm, { unsigned long old; - if ((pte_val(*ptep) & (_PAGE_ACCESSED | _PAGE_HASHPTE)) == 0) + if ((pte_val(*ptep) & (_PAGE_ACCESSED | _PAGE_HASHPTE)) == 0) return 0; - old = pte_update(mm, addr, ptep, _PAGE_ACCESSED, 0); + old = pte_update(mm, addr, ptep, _PAGE_ACCESSED, 0, 0); return (old & _PAGE_ACCESSED) != 0; } #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG @@ -252,7 +254,7 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, if ((pte_val(*ptep) & _PAGE_RW) == 0) return; - pte_update(mm, addr, ptep, _PAGE_RW, 0); + pte_update(mm, addr, ptep, _PAGE_RW, 0, 0); } static inline void huge_ptep_set_wrprotect(struct mm_struct *mm, @@ -261,7 +263,7 @@ static inline void huge_ptep_set_wrprotect(struct mm_struct *mm, if ((pte_val(*ptep) & _PAGE_RW) == 0) return; - pte_update(mm, addr, ptep, _PAGE_RW, 1); + pte_update(mm, addr, ptep, _PAGE_RW, 0, 1); } /* @@ -284,14 +286,14 @@ static inline void huge_ptep_set_wrprotect(struct mm_struct *mm, static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { - unsigned long old = pte_update(mm, addr, ptep, ~0UL, 0); + unsigned long old = pte_update(mm, addr, ptep, ~0UL, 0, 0); return __pte(old); } static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t * ptep) { - pte_update(mm, addr, ptep, ~0UL, 0); + pte_update(mm, addr, ptep, ~0UL, 0, 0); } @@ -506,7 +508,9 @@ extern int pmdp_set_access_flags(struct vm_area_struct *vma, extern unsigned long pmd_hugepage_update(struct mm_struct *mm, unsigned long addr, - pmd_t *pmdp, unsigned long clr); + pmd_t *pmdp, + unsigned long clr, + unsigned long set); static inline int __pmdp_test_and_clear_young(struct mm_struct *mm, unsigned long addr, pmd_t *pmdp) @@ -515,7 +519,7 @@ static inline int __pmdp_test_and_clear_young(struct mm_struct *mm, if ((pmd_val(*pmdp) & (_PAGE_ACCESSED | _PAGE_HASHPTE)) == 0) return 0; - old = pmd_hugepage_update(mm, addr, pmdp, _PAGE_ACCESSED); + old = pmd_hugepage_update(mm, addr, pmdp, _PAGE_ACCESSED, 0); return ((old & _PAGE_ACCESSED) != 0); } @@ -542,7 +546,7 @@ static inline void pmdp_set_wrprotect(struct mm_struct *mm, unsigned long addr, if ((pmd_val(*pmdp) & _PAGE_RW) == 0) return; - pmd_hugepage_update(mm, addr, pmdp, _PAGE_RW); + pmd_hugepage_update(mm, addr, pmdp, _PAGE_RW, 0); } #define __HAVE_ARCH_PMDP_SPLITTING_FLUSH diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c index 65b7b65e8708..62bf5e8e78da 100644 --- a/arch/powerpc/mm/pgtable_64.c +++ b/arch/powerpc/mm/pgtable_64.c @@ -510,7 +510,8 @@ int pmdp_set_access_flags(struct vm_area_struct *vma, unsigned long address, } unsigned long pmd_hugepage_update(struct mm_struct *mm, unsigned long addr, - pmd_t *pmdp, unsigned long clr) + pmd_t *pmdp, unsigned long clr, + unsigned long set) { unsigned long old, tmp; @@ -526,14 +527,15 @@ unsigned long pmd_hugepage_update(struct mm_struct *mm, unsigned long addr, andi. %1,%0,%6\n\ bne- 1b \n\ andc %1,%0,%4 \n\ + or %1,%1,%7\n\ stdcx. %1,0,%3 \n\ bne- 1b" : "=&r" (old), "=&r" (tmp), "=m" (*pmdp) - : "r" (pmdp), "r" (clr), "m" (*pmdp), "i" (_PAGE_BUSY) + : "r" (pmdp), "r" (clr), "m" (*pmdp), "i" (_PAGE_BUSY), "r" (set) : "cc" ); #else old = pmd_val(*pmdp); - *pmdp = __pmd(old & ~clr); + *pmdp = __pmd((old & ~clr) | set); #endif if (old & _PAGE_HASHPTE) hpte_do_hugepage_flush(mm, addr, pmdp); @@ -708,7 +710,7 @@ void set_pmd_at(struct mm_struct *mm, unsigned long addr, void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address, pmd_t *pmdp) { - pmd_hugepage_update(vma->vm_mm, address, pmdp, _PAGE_PRESENT); + pmd_hugepage_update(vma->vm_mm, address, pmdp, _PAGE_PRESENT, 0); } /* @@ -835,7 +837,7 @@ pmd_t pmdp_get_and_clear(struct mm_struct *mm, unsigned long old; pgtable_t *pgtable_slot; - old = pmd_hugepage_update(mm, addr, pmdp, ~0UL); + old = pmd_hugepage_update(mm, addr, pmdp, ~0UL, 0); old_pmd = __pmd(old); /* * We have pmd == none and we are holding page_table_lock. diff --git a/arch/powerpc/mm/subpage-prot.c b/arch/powerpc/mm/subpage-prot.c index a770df2dae70..6c0b1f5f8d2c 100644 --- a/arch/powerpc/mm/subpage-prot.c +++ b/arch/powerpc/mm/subpage-prot.c @@ -78,7 +78,7 @@ static void hpte_flush_range(struct mm_struct *mm, unsigned long addr, pte = pte_offset_map_lock(mm, pmd, addr, &ptl); arch_enter_lazy_mmu_mode(); for (; npages > 0; --npages) { - pte_update(mm, addr, pte, 0, 0); + pte_update(mm, addr, pte, 0, 0, 0); addr += PAGE_SIZE; ++pte; } -- cgit v1.2.3 From 9d85d5863fa4818eb7fa306563bf830c0210c3a6 Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Wed, 12 Feb 2014 09:13:37 +0530 Subject: mm: Dirty accountable change only apply to non prot numa case So move it within the if loop Acked-by: Mel Gorman Reviewed-by: Rik van Riel Signed-off-by: Aneesh Kumar K.V Signed-off-by: Benjamin Herrenschmidt --- mm/mprotect.c | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/mm/mprotect.c b/mm/mprotect.c index 7332c1785744..33eab902f10e 100644 --- a/mm/mprotect.c +++ b/mm/mprotect.c @@ -58,6 +58,13 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd, if (pte_numa(ptent)) ptent = pte_mknonnuma(ptent); ptent = pte_modify(ptent, newprot); + /* + * Avoid taking write faults for pages we + * know to be dirty. + */ + if (dirty_accountable && pte_dirty(ptent)) + ptent = pte_mkwrite(ptent); + ptep_modify_prot_commit(mm, addr, pte, ptent); updated = true; } else { struct page *page; @@ -72,22 +79,8 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd, } } } - - /* - * Avoid taking write faults for pages we know to be - * dirty. - */ - if (dirty_accountable && pte_dirty(ptent)) { - ptent = pte_mkwrite(ptent); - updated = true; - } - if (updated) pages++; - - /* Only !prot_numa always clears the pte */ - if (!prot_numa) - ptep_modify_prot_commit(mm, addr, pte, ptent); } else if (IS_ENABLED(CONFIG_MIGRATION) && !pte_file(oldpte)) { swp_entry_t entry = pte_to_swp_entry(oldpte); -- cgit v1.2.3 From 56eecdb912b536a4fa97fb5bfe5a940a54d79be6 Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Wed, 12 Feb 2014 09:13:38 +0530 Subject: mm: Use ptep/pmdp_set_numa() for updating _PAGE_NUMA bit Archs like ppc64 doesn't do tlb flush in set_pte/pmd functions when using a hash table MMU for various reasons (the flush is handled as part of the PTE modification when necessary). ppc64 thus doesn't implement flush_tlb_range for hash based MMUs. Additionally ppc64 require the tlb flushing to be batched within ptl locks. The reason to do that is to ensure that the hash page table is in sync with linux page table. We track the hpte index in linux pte and if we clear them without flushing hash and drop the ptl lock, we can have another cpu update the pte and can end up with duplicate entry in the hash table, which is fatal. We also want to keep set_pte_at simpler by not requiring them to do hash flush for performance reason. We do that by assuming that set_pte_at() is never *ever* called on a PTE that is already valid. This was the case until the NUMA code went in which broke that assumption. Fix that by introducing a new pair of helpers to set _PAGE_NUMA in a way similar to ptep/pmdp_set_wrprotect(), with a generic implementation using set_pte_at() and a powerpc specific one using the appropriate mechanism needed to keep the hash table in sync. Acked-by: Mel Gorman Reviewed-by: Rik van Riel Signed-off-by: Aneesh Kumar K.V Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/include/asm/pgtable.h | 22 +++++++++++++++++++++ include/asm-generic/pgtable.h | 39 ++++++++++++++++++++++++++++++++++++++ mm/huge_memory.c | 9 ++------- mm/mprotect.c | 4 +--- 4 files changed, 64 insertions(+), 10 deletions(-) diff --git a/arch/powerpc/include/asm/pgtable.h b/arch/powerpc/include/asm/pgtable.h index f83b6f3e1b39..3ebb188c3ff5 100644 --- a/arch/powerpc/include/asm/pgtable.h +++ b/arch/powerpc/include/asm/pgtable.h @@ -75,12 +75,34 @@ static inline pte_t pte_mknuma(pte_t pte) return pte; } +#define ptep_set_numa ptep_set_numa +static inline void ptep_set_numa(struct mm_struct *mm, unsigned long addr, + pte_t *ptep) +{ + if ((pte_val(*ptep) & _PAGE_PRESENT) == 0) + VM_BUG_ON(1); + + pte_update(mm, addr, ptep, _PAGE_PRESENT, _PAGE_NUMA, 0); + return; +} + #define pmd_numa pmd_numa static inline int pmd_numa(pmd_t pmd) { return pte_numa(pmd_pte(pmd)); } +#define pmdp_set_numa pmdp_set_numa +static inline void pmdp_set_numa(struct mm_struct *mm, unsigned long addr, + pmd_t *pmdp) +{ + if ((pmd_val(*pmdp) & _PAGE_PRESENT) == 0) + VM_BUG_ON(1); + + pmd_hugepage_update(mm, addr, pmdp, _PAGE_PRESENT, _PAGE_NUMA); + return; +} + #define pmd_mknonnuma pmd_mknonnuma static inline pmd_t pmd_mknonnuma(pmd_t pmd) { diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h index 8e4f41d9af4d..34c7bdc06014 100644 --- a/include/asm-generic/pgtable.h +++ b/include/asm-generic/pgtable.h @@ -701,6 +701,18 @@ static inline pte_t pte_mknuma(pte_t pte) } #endif +#ifndef ptep_set_numa +static inline void ptep_set_numa(struct mm_struct *mm, unsigned long addr, + pte_t *ptep) +{ + pte_t ptent = *ptep; + + ptent = pte_mknuma(ptent); + set_pte_at(mm, addr, ptep, ptent); + return; +} +#endif + #ifndef pmd_mknuma static inline pmd_t pmd_mknuma(pmd_t pmd) { @@ -708,6 +720,18 @@ static inline pmd_t pmd_mknuma(pmd_t pmd) return pmd_clear_flags(pmd, _PAGE_PRESENT); } #endif + +#ifndef pmdp_set_numa +static inline void pmdp_set_numa(struct mm_struct *mm, unsigned long addr, + pmd_t *pmdp) +{ + pmd_t pmd = *pmdp; + + pmd = pmd_mknuma(pmd); + set_pmd_at(mm, addr, pmdp, pmd); + return; +} +#endif #else extern int pte_numa(pte_t pte); extern int pmd_numa(pmd_t pmd); @@ -715,6 +739,8 @@ extern pte_t pte_mknonnuma(pte_t pte); extern pmd_t pmd_mknonnuma(pmd_t pmd); extern pte_t pte_mknuma(pte_t pte); extern pmd_t pmd_mknuma(pmd_t pmd); +extern void ptep_set_numa(struct mm_struct *mm, unsigned long addr, pte_t *ptep); +extern void pmdp_set_numa(struct mm_struct *mm, unsigned long addr, pmd_t *pmdp); #endif /* CONFIG_ARCH_USES_NUMA_PROT_NONE */ #else static inline int pmd_numa(pmd_t pmd) @@ -742,10 +768,23 @@ static inline pte_t pte_mknuma(pte_t pte) return pte; } +static inline void ptep_set_numa(struct mm_struct *mm, unsigned long addr, + pte_t *ptep) +{ + return; +} + + static inline pmd_t pmd_mknuma(pmd_t pmd) { return pmd; } + +static inline void pmdp_set_numa(struct mm_struct *mm, unsigned long addr, + pmd_t *pmdp) +{ + return ; +} #endif /* CONFIG_NUMA_BALANCING */ #endif /* CONFIG_MMU */ diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 82166bf974e1..da23eb96779f 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -1545,6 +1545,7 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd, entry = pmd_mknonnuma(entry); entry = pmd_modify(entry, newprot); ret = HPAGE_PMD_NR; + set_pmd_at(mm, addr, pmd, entry); BUG_ON(pmd_write(entry)); } else { struct page *page = pmd_page(*pmd); @@ -1557,16 +1558,10 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd, */ if (!is_huge_zero_page(page) && !pmd_numa(*pmd)) { - entry = *pmd; - entry = pmd_mknuma(entry); + pmdp_set_numa(mm, addr, pmd); ret = HPAGE_PMD_NR; } } - - /* Set PMD if cleared earlier */ - if (ret == HPAGE_PMD_NR) - set_pmd_at(mm, addr, pmd, entry); - spin_unlock(ptl); } diff --git a/mm/mprotect.c b/mm/mprotect.c index 33eab902f10e..769a67a15803 100644 --- a/mm/mprotect.c +++ b/mm/mprotect.c @@ -69,12 +69,10 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd, } else { struct page *page; - ptent = *pte; page = vm_normal_page(vma, addr, oldpte); if (page && !PageKsm(page)) { if (!pte_numa(oldpte)) { - ptent = pte_mknuma(ptent); - set_pte_at(mm, addr, pte, ptent); + ptep_set_numa(mm, addr, pte); updated = true; } } -- cgit v1.2.3 From a0a4419e302fedb548d56129e02130347810f892 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Wed, 12 Feb 2014 17:17:05 +1100 Subject: powerpc: Link VDSOs at 0x0 perf is failing to resolve symbols in the VDSO. A while (1) gettimeofday() loop shows: 93.99% [vdso] [.] 0x00000000000005e0 3.12% test [.] 00000037.plt_call.gettimeofday@@GLIBC_2.18 2.81% test [.] main The reason for this is that we are linking our VDSO shared libraries at 1MB, which is a little weird. Even though this is uncommon, Alan points out that it is valid and we should probably fix perf userspace. Regardless, I can't see a reason why we are doing this. The code is all position independent and we never rely on the VDSO ending up at 1M (and we never place it there on 64bit tasks). Changing our link address to 0x0 fixes perf VDSO symbol resolution: 73.18% [vdso] [.] 0x000000000000060c 12.39% [vdso] [.] __kernel_gettimeofday 3.58% test [.] 00000037.plt_call.gettimeofday@@GLIBC_2.18 2.94% [vdso] [.] __kernel_datapage_offset 2.90% test [.] main We still have some local symbol resolution issues that will be fixed in a subsequent patch. Signed-off-by: Anton Blanchard Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/include/asm/vdso.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/include/asm/vdso.h b/arch/powerpc/include/asm/vdso.h index 0d9cecddf8a4..c53f5f6d1761 100644 --- a/arch/powerpc/include/asm/vdso.h +++ b/arch/powerpc/include/asm/vdso.h @@ -4,11 +4,11 @@ #ifdef __KERNEL__ /* Default link addresses for the vDSOs */ -#define VDSO32_LBASE 0x100000 -#define VDSO64_LBASE 0x100000 +#define VDSO32_LBASE 0x0 +#define VDSO64_LBASE 0x0 /* Default map addresses for 32bit vDSO */ -#define VDSO32_MBASE VDSO32_LBASE +#define VDSO32_MBASE 0x100000 #define VDSO_VERSION_STRING LINUX_2.6.15 -- cgit v1.2.3 From 24b659a13866b935eca72748ce725279bd3c4466 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Wed, 12 Feb 2014 17:18:50 +1100 Subject: powerpc: Use unstripped VDSO image for more accurate profiling data We are seeing a lot of hits in the VDSO that are not resolved by perf. A while(1) gettimeofday() loop shows the issue: 27.64% [vdso] [.] 0x000000000000060c 22.57% [vdso] [.] 0x0000000000000628 16.88% [vdso] [.] 0x0000000000000610 12.39% [vdso] [.] __kernel_gettimeofday 6.09% [vdso] [.] 0x00000000000005f8 3.58% test [.] 00000037.plt_call.gettimeofday@@GLIBC_2.18 2.94% [vdso] [.] __kernel_datapage_offset 2.90% test [.] main We are using a stripped VDSO image which means only symbols with relocation info can be resolved. There isn't a lot of point to stripping the VDSO, the debug info is only about 1kB: 4680 arch/powerpc/kernel/vdso64/vdso64.so 5815 arch/powerpc/kernel/vdso64/vdso64.so.dbg By using the unstripped image, we can resolve all the symbols in the VDSO and the perf profile data looks much better: 76.53% [vdso] [.] __do_get_tspec 12.20% [vdso] [.] __kernel_gettimeofday 5.05% [vdso] [.] __get_datapage 3.20% test [.] main 2.92% test [.] 00000037.plt_call.gettimeofday@@GLIBC_2.18 Signed-off-by: Anton Blanchard Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/kernel/vdso32/vdso32_wrapper.S | 2 +- arch/powerpc/kernel/vdso64/vdso64_wrapper.S | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/kernel/vdso32/vdso32_wrapper.S b/arch/powerpc/kernel/vdso32/vdso32_wrapper.S index 79683d0393f5..6ac107ac402a 100644 --- a/arch/powerpc/kernel/vdso32/vdso32_wrapper.S +++ b/arch/powerpc/kernel/vdso32/vdso32_wrapper.S @@ -6,7 +6,7 @@ .globl vdso32_start, vdso32_end .balign PAGE_SIZE vdso32_start: - .incbin "arch/powerpc/kernel/vdso32/vdso32.so" + .incbin "arch/powerpc/kernel/vdso32/vdso32.so.dbg" .balign PAGE_SIZE vdso32_end: diff --git a/arch/powerpc/kernel/vdso64/vdso64_wrapper.S b/arch/powerpc/kernel/vdso64/vdso64_wrapper.S index 8df9e2463007..df60fca6a13d 100644 --- a/arch/powerpc/kernel/vdso64/vdso64_wrapper.S +++ b/arch/powerpc/kernel/vdso64/vdso64_wrapper.S @@ -6,7 +6,7 @@ .globl vdso64_start, vdso64_end .balign PAGE_SIZE vdso64_start: - .incbin "arch/powerpc/kernel/vdso64/vdso64.so" + .incbin "arch/powerpc/kernel/vdso64/vdso64.so.dbg" .balign PAGE_SIZE vdso64_end: -- cgit v1.2.3 From 5b2e198e50f6ba57081586b853163ea1bb95f1a8 Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Wed, 12 Feb 2014 15:24:54 +0800 Subject: powerpc/powernv: Rework EEH reset When doing reset in order to recover the affected PE, we issue hot reset on PE primary bus if it's not root bus. Otherwise, we issue hot or fundamental reset on root port or PHB accordingly. For the later case, we didn't cover the situation where PE only includes root port and it potentially causes kernel crash upon EEH error to the PE. The patch reworks the logic of EEH reset to improve the code readability and also avoid the kernel crash. Cc: stable@vger.kernel.org Reported-by: Thadeu Lima de Souza Cascardo Signed-off-by: Gavin Shan Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/platforms/powernv/eeh-ioda.c | 29 ++++------------------------- 1 file changed, 4 insertions(+), 25 deletions(-) diff --git a/arch/powerpc/platforms/powernv/eeh-ioda.c b/arch/powerpc/platforms/powernv/eeh-ioda.c index e1e71618b70c..fcb79cffdb66 100644 --- a/arch/powerpc/platforms/powernv/eeh-ioda.c +++ b/arch/powerpc/platforms/powernv/eeh-ioda.c @@ -489,8 +489,7 @@ static int ioda_eeh_bridge_reset(struct pci_controller *hose, static int ioda_eeh_reset(struct eeh_pe *pe, int option) { struct pci_controller *hose = pe->phb; - struct eeh_dev *edev; - struct pci_dev *dev; + struct pci_bus *bus; int ret; /* @@ -519,31 +518,11 @@ static int ioda_eeh_reset(struct eeh_pe *pe, int option) if (pe->type & EEH_PE_PHB) { ret = ioda_eeh_phb_reset(hose, option); } else { - if (pe->type & EEH_PE_DEVICE) { - /* - * If it's device PE, we didn't refer to the parent - * PCI bus yet. So we have to figure it out indirectly. - */ - edev = list_first_entry(&pe->edevs, - struct eeh_dev, list); - dev = eeh_dev_to_pci_dev(edev); - dev = dev->bus->self; - } else { - /* - * If it's bus PE, the parent PCI bus is already there - * and just pick it up. - */ - dev = pe->bus->self; - } - - /* - * Do reset based on the fact that the direct upstream bridge - * is root bridge (port) or not. - */ - if (dev->bus->number == 0) + bus = eeh_pe_bus_get(pe); + if (pci_is_root_bus(bus)) ret = ioda_eeh_root_reset(hose, option); else - ret = ioda_eeh_bridge_reset(hose, dev, option); + ret = ioda_eeh_bridge_reset(hose, bus->self, option); } return ret; -- cgit v1.2.3 From 2ec5a0adf60c23bb6b0a95d3b96a8c1ff1e1aa5a Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Wed, 12 Feb 2014 15:24:55 +0800 Subject: powerpc/eeh: Cleanup on eeh_subsystem_enabled The patch cleans up variable eeh_subsystem_enabled so that we needn't refer the variable directly from external. Instead, we will use function eeh_enabled() and eeh_set_enable() to operate the variable. Signed-off-by: Gavin Shan Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/include/asm/eeh.h | 21 +++++++++++++++++++-- arch/powerpc/kernel/eeh.c | 12 ++++++------ arch/powerpc/platforms/powernv/eeh-powernv.c | 2 +- arch/powerpc/platforms/pseries/eeh_pseries.c | 2 +- 4 files changed, 27 insertions(+), 10 deletions(-) diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h index 9e39ceb1d19f..d4dd41fb951b 100644 --- a/arch/powerpc/include/asm/eeh.h +++ b/arch/powerpc/include/asm/eeh.h @@ -172,10 +172,20 @@ struct eeh_ops { }; extern struct eeh_ops *eeh_ops; -extern int eeh_subsystem_enabled; +extern bool eeh_subsystem_enabled; extern raw_spinlock_t confirm_error_lock; extern int eeh_probe_mode; +static inline bool eeh_enabled(void) +{ + return eeh_subsystem_enabled; +} + +static inline void eeh_set_enable(bool mode) +{ + eeh_subsystem_enabled = mode; +} + #define EEH_PROBE_MODE_DEV (1<<0) /* From PCI device */ #define EEH_PROBE_MODE_DEVTREE (1<<1) /* From device tree */ @@ -246,7 +256,7 @@ void eeh_remove_device(struct pci_dev *); * If this macro yields TRUE, the caller relays to eeh_check_failure() * which does further tests out of line. */ -#define EEH_POSSIBLE_ERROR(val, type) ((val) == (type)~0 && eeh_subsystem_enabled) +#define EEH_POSSIBLE_ERROR(val, type) ((val) == (type)~0 && eeh_enabled()) /* * Reads from a device which has been isolated by EEH will return @@ -257,6 +267,13 @@ void eeh_remove_device(struct pci_dev *); #else /* !CONFIG_EEH */ +static inline bool eeh_enabled(void) +{ + return false; +} + +static inline void eeh_set_enable(bool mode) { } + static inline int eeh_init(void) { return 0; diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c index 148db72a8c43..f22f7b6f6b01 100644 --- a/arch/powerpc/kernel/eeh.c +++ b/arch/powerpc/kernel/eeh.c @@ -89,7 +89,7 @@ /* Platform dependent EEH operations */ struct eeh_ops *eeh_ops = NULL; -int eeh_subsystem_enabled; +bool eeh_subsystem_enabled = false; EXPORT_SYMBOL(eeh_subsystem_enabled); /* @@ -364,7 +364,7 @@ int eeh_dev_check_failure(struct eeh_dev *edev) eeh_stats.total_mmio_ffs++; - if (!eeh_subsystem_enabled) + if (!eeh_enabled()) return 0; if (!edev) { @@ -822,7 +822,7 @@ int eeh_init(void) return ret; } - if (eeh_subsystem_enabled) + if (eeh_enabled()) pr_info("EEH: PCI Enhanced I/O Error Handling Enabled\n"); else pr_warning("EEH: No capable adapters found\n"); @@ -897,7 +897,7 @@ void eeh_add_device_late(struct pci_dev *dev) struct device_node *dn; struct eeh_dev *edev; - if (!dev || !eeh_subsystem_enabled) + if (!dev || !eeh_enabled()) return; pr_debug("EEH: Adding device %s\n", pci_name(dev)); @@ -1005,7 +1005,7 @@ void eeh_remove_device(struct pci_dev *dev) { struct eeh_dev *edev; - if (!dev || !eeh_subsystem_enabled) + if (!dev || !eeh_enabled()) return; edev = pci_dev_to_eeh_dev(dev); @@ -1045,7 +1045,7 @@ void eeh_remove_device(struct pci_dev *dev) static int proc_eeh_show(struct seq_file *m, void *v) { - if (0 == eeh_subsystem_enabled) { + if (!eeh_enabled()) { seq_printf(m, "EEH Subsystem is globally disabled\n"); seq_printf(m, "eeh_total_mmio_ffs=%llu\n", eeh_stats.total_mmio_ffs); } else { diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c b/arch/powerpc/platforms/powernv/eeh-powernv.c index a79fddc5e74e..a59788e83b8b 100644 --- a/arch/powerpc/platforms/powernv/eeh-powernv.c +++ b/arch/powerpc/platforms/powernv/eeh-powernv.c @@ -145,7 +145,7 @@ static int powernv_eeh_dev_probe(struct pci_dev *dev, void *flag) * Enable EEH explicitly so that we will do EEH check * while accessing I/O stuff */ - eeh_subsystem_enabled = 1; + eeh_set_enable(true); /* Save memory bars */ eeh_save_bars(edev); diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c index 9ef3cc8ebc11..8a8f0472d98f 100644 --- a/arch/powerpc/platforms/pseries/eeh_pseries.c +++ b/arch/powerpc/platforms/pseries/eeh_pseries.c @@ -265,7 +265,7 @@ static void *pseries_eeh_of_probe(struct device_node *dn, void *flag) enable = 1; if (enable) { - eeh_subsystem_enabled = 1; + eeh_set_enable(true); eeh_add_to_parent_pe(edev); pr_debug("%s: EEH enabled on %s PHB#%d-PE#%x, config addr#%x\n", -- cgit v1.2.3 From 66f9af83e56bfa12964d251df9d60fb571579913 Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Wed, 12 Feb 2014 15:24:56 +0800 Subject: powerpc/eeh: Disable EEH on reboot We possiblly detect EEH errors during reboot, particularly in kexec path, but it's impossible for device drivers and EEH core to handle or recover them properly. The patch registers one reboot notifier for EEH and disable EEH subsystem during reboot. That means the EEH errors is going to be cleared by hardware reset or second kernel during early stage of PCI probe. Signed-off-by: Gavin Shan Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/kernel/eeh.c | 20 ++++++++++++++++++++ arch/powerpc/platforms/powernv/eeh-ioda.c | 3 ++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c index f22f7b6f6b01..e7b76a6bf150 100644 --- a/arch/powerpc/kernel/eeh.c +++ b/arch/powerpc/kernel/eeh.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -747,6 +748,17 @@ int __exit eeh_ops_unregister(const char *name) return -EEXIST; } +static int eeh_reboot_notifier(struct notifier_block *nb, + unsigned long action, void *unused) +{ + eeh_set_enable(false); + return NOTIFY_DONE; +} + +static struct notifier_block eeh_reboot_nb = { + .notifier_call = eeh_reboot_notifier, +}; + /** * eeh_init - EEH initialization * @@ -778,6 +790,14 @@ int eeh_init(void) if (machine_is(powernv) && cnt++ <= 0) return ret; + /* Register reboot notifier */ + ret = register_reboot_notifier(&eeh_reboot_nb); + if (ret) { + pr_warn("%s: Failed to register notifier (%d)\n", + __func__, ret); + return ret; + } + /* call platform initialization function */ if (!eeh_ops) { pr_warning("%s: Platform EEH operation not found\n", diff --git a/arch/powerpc/platforms/powernv/eeh-ioda.c b/arch/powerpc/platforms/powernv/eeh-ioda.c index fcb79cffdb66..f51474336460 100644 --- a/arch/powerpc/platforms/powernv/eeh-ioda.c +++ b/arch/powerpc/platforms/powernv/eeh-ioda.c @@ -44,7 +44,8 @@ static int ioda_eeh_event(struct notifier_block *nb, /* We simply send special EEH event */ if ((changed_evts & OPAL_EVENT_PCI_ERROR) && - (events & OPAL_EVENT_PCI_ERROR)) + (events & OPAL_EVENT_PCI_ERROR) && + eeh_enabled()) eeh_send_failure_event(NULL); return 0; -- cgit v1.2.3 From 19ea80603715d473600cd993b9987bc97d042e02 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sun, 16 Feb 2014 19:29:32 -0500 Subject: ext4: don't leave i_crtime.tv_sec uninitialized If the i_crtime field is not present in the inode, don't leave the field uninitialized. Fixes: ef7f38359 ("ext4: Add nanosecond timestamps") Reported-by: Vegard Nossum Tested-by: Vegard Nossum Signed-off-by: "Theodore Ts'o" Cc: stable@vger.kernel.org --- fs/ext4/ext4.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index ece55565b9cd..d3a534fdc5ff 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -771,6 +771,8 @@ do { \ if (EXT4_FITS_IN_INODE(raw_inode, einode, xtime)) \ (einode)->xtime.tv_sec = \ (signed)le32_to_cpu((raw_inode)->xtime); \ + else \ + (einode)->xtime.tv_sec = 0; \ if (EXT4_FITS_IN_INODE(raw_inode, einode, xtime ## _extra)) \ ext4_decode_extra_time(&(einode)->xtime, \ raw_inode->xtime ## _extra); \ -- cgit v1.2.3 From 09db30805300e9ed5ad43d4d339115cf1d9c84e1 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Thu, 13 Feb 2014 19:02:33 -0700 Subject: dccp: re-enable debug macro dccp tfrc: revert This reverts 6aee49c558de ("dccp: make local variable static") since the variable tfrc_debug is referenced by the tfrc_pr_debug(fmt, ...) macro when TFRC debugging is enabled. If it is enabled, use of the macro produces a compilation error. Signed-off-by: Gerrit Renker Signed-off-by: David S. Miller --- net/dccp/ccids/lib/tfrc.c | 2 +- net/dccp/ccids/lib/tfrc.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/net/dccp/ccids/lib/tfrc.c b/net/dccp/ccids/lib/tfrc.c index c073b81a1f3e..62b5828acde0 100644 --- a/net/dccp/ccids/lib/tfrc.c +++ b/net/dccp/ccids/lib/tfrc.c @@ -8,7 +8,7 @@ #include "tfrc.h" #ifdef CONFIG_IP_DCCP_TFRC_DEBUG -static bool tfrc_debug; +bool tfrc_debug; module_param(tfrc_debug, bool, 0644); MODULE_PARM_DESC(tfrc_debug, "Enable TFRC debug messages"); #endif diff --git a/net/dccp/ccids/lib/tfrc.h b/net/dccp/ccids/lib/tfrc.h index a3d8f7c76ae0..40ee7d62b652 100644 --- a/net/dccp/ccids/lib/tfrc.h +++ b/net/dccp/ccids/lib/tfrc.h @@ -21,6 +21,7 @@ #include "packet_history.h" #ifdef CONFIG_IP_DCCP_TFRC_DEBUG +extern bool tfrc_debug; #define tfrc_pr_debug(format, a...) DCCP_PR_DEBUG(tfrc_debug, format, ##a) #else #define tfrc_pr_debug(format, a...) -- cgit v1.2.3 From 891de74d693bb4fefe2efcc6432a4a9a9bee561e Mon Sep 17 00:00:00 2001 From: Haiyang Zhang Date: Wed, 12 Feb 2014 16:54:27 -0800 Subject: hyperv: Fix the carrier status setting Without this patch, the "cat /sys/class/net/ethN/operstate" shows "unknown", and "ethtool ethN" shows "Link detected: yes", when VM boots up with or without vNIC connected. This patch fixed the problem. Signed-off-by: Haiyang Zhang Reviewed-by: K. Y. Srinivasan Acked-by: Jason Wang Signed-off-by: David S. Miller --- drivers/net/hyperv/netvsc_drv.c | 53 +++++++++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 15 deletions(-) diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index 7756118c2f0a..7141a1937360 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -88,8 +88,12 @@ static int netvsc_open(struct net_device *net) { struct net_device_context *net_device_ctx = netdev_priv(net); struct hv_device *device_obj = net_device_ctx->device_ctx; + struct netvsc_device *nvdev; + struct rndis_device *rdev; int ret = 0; + netif_carrier_off(net); + /* Open up the device */ ret = rndis_filter_open(device_obj); if (ret != 0) { @@ -99,6 +103,11 @@ static int netvsc_open(struct net_device *net) netif_start_queue(net); + nvdev = hv_get_drvdata(device_obj); + rdev = nvdev->extension; + if (!rdev->link_state) + netif_carrier_on(net); + return ret; } @@ -229,23 +238,24 @@ void netvsc_linkstatus_callback(struct hv_device *device_obj, struct net_device *net; struct net_device_context *ndev_ctx; struct netvsc_device *net_device; + struct rndis_device *rdev; net_device = hv_get_drvdata(device_obj); + rdev = net_device->extension; + + rdev->link_state = status != 1; + net = net_device->ndev; - if (!net) { - netdev_err(net, "got link status but net device " - "not initialized yet\n"); + if (!net || net->reg_state != NETREG_REGISTERED) return; - } + ndev_ctx = netdev_priv(net); if (status == 1) { - netif_carrier_on(net); - ndev_ctx = netdev_priv(net); schedule_delayed_work(&ndev_ctx->dwork, 0); schedule_delayed_work(&ndev_ctx->dwork, msecs_to_jiffies(20)); } else { - netif_carrier_off(net); + schedule_delayed_work(&ndev_ctx->dwork, 0); } } @@ -388,17 +398,35 @@ static const struct net_device_ops device_ops = { * current context when receiving RNDIS_STATUS_MEDIA_CONNECT event. So, add * another netif_notify_peers() into a delayed work, otherwise GARP packet * will not be sent after quick migration, and cause network disconnection. + * Also, we update the carrier status here. */ -static void netvsc_send_garp(struct work_struct *w) +static void netvsc_link_change(struct work_struct *w) { struct net_device_context *ndev_ctx; struct net_device *net; struct netvsc_device *net_device; + struct rndis_device *rdev; + bool notify; + + rtnl_lock(); ndev_ctx = container_of(w, struct net_device_context, dwork.work); net_device = hv_get_drvdata(ndev_ctx->device_ctx); + rdev = net_device->extension; net = net_device->ndev; - netdev_notify_peers(net); + + if (rdev->link_state) { + netif_carrier_off(net); + notify = false; + } else { + netif_carrier_on(net); + notify = true; + } + + rtnl_unlock(); + + if (notify) + netdev_notify_peers(net); } @@ -414,13 +442,10 @@ static int netvsc_probe(struct hv_device *dev, if (!net) return -ENOMEM; - /* Set initial state */ - netif_carrier_off(net); - net_device_ctx = netdev_priv(net); net_device_ctx->device_ctx = dev; hv_set_drvdata(dev, net); - INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_send_garp); + INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_link_change); INIT_WORK(&net_device_ctx->work, do_set_multicast); net->netdev_ops = &device_ops; @@ -443,8 +468,6 @@ static int netvsc_probe(struct hv_device *dev, } memcpy(net->dev_addr, device_info.mac_adr, ETH_ALEN); - netif_carrier_on(net); - ret = register_netdev(net); if (ret != 0) { pr_err("Unable to register netdev.\n"); -- cgit v1.2.3 From cd0f0b95fd2cd2b716caf5f15db73ab76992789b Mon Sep 17 00:00:00 2001 From: Duan Jiong Date: Fri, 14 Feb 2014 18:26:22 +0800 Subject: ipv4: distinguish EHOSTUNREACH from the ENETUNREACH since commit 251da413("ipv4: Cache ip_error() routes even when not forwarding."), the counter IPSTATS_MIB_INADDRERRORS can't work correctly, because the value of err was always set to ENETUNREACH. Signed-off-by: Duan Jiong Signed-off-by: David S. Miller --- net/ipv4/route.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 25071b48921c..6f6dd85bdffc 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1695,8 +1695,11 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr, fl4.daddr = daddr; fl4.saddr = saddr; err = fib_lookup(net, &fl4, &res); - if (err != 0) + if (err != 0) { + if (!IN_DEV_FORWARD(in_dev)) + err = -EHOSTUNREACH; goto no_route; + } RT_CACHE_STAT_INC(in_slow_tot); @@ -1712,8 +1715,10 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr, goto local_input; } - if (!IN_DEV_FORWARD(in_dev)) + if (!IN_DEV_FORWARD(in_dev)) { + err = -EHOSTUNREACH; goto no_route; + } if (res.type != RTN_UNICAST) goto martian_destination; -- cgit v1.2.3 From ef2820a735f74ea60335f8ba3801b844f0cb184d Mon Sep 17 00:00:00 2001 From: Matija Glavinic Pecotic Date: Fri, 14 Feb 2014 14:51:18 +0100 Subject: net: sctp: Fix a_rwnd/rwnd management to reflect real state of the receiver's buffer Implementation of (a)rwnd calculation might lead to severe performance issues and associations completely stalling. These problems are described and solution is proposed which improves lksctp's robustness in congestion state. 1) Sudden drop of a_rwnd and incomplete window recovery afterwards Data accounted in sctp_assoc_rwnd_decrease takes only payload size (sctp data), but size of sk_buff, which is blamed against receiver buffer, is not accounted in rwnd. Theoretically, this should not be the problem as actual size of buffer is double the amount requested on the socket (SO_RECVBUF). Problem here is that this will have bad scaling for data which is less then sizeof sk_buff. E.g. in 4G (LTE) networks, link interfacing radio side will have a large portion of traffic of this size (less then 100B). An example of sudden drop and incomplete window recovery is given below. Node B exhibits problematic behavior. Node A initiates association and B is configured to advertise rwnd of 10000. A sends messages of size 43B (size of typical sctp message in 4G (LTE) network). On B data is left in buffer by not reading socket in userspace. Lets examine when we will hit pressure state and declare rwnd to be 0 for scenario with above stated parameters (rwnd == 10000, chunk size == 43, each chunk is sent in separate sctp packet) Logic is implemented in sctp_assoc_rwnd_decrease: socket_buffer (see below) is maximum size which can be held in socket buffer (sk_rcvbuf). current_alloced is amount of data currently allocated (rx_count) A simple expression is given for which it will be examined after how many packets for above stated parameters we enter pressure state: We start by condition which has to be met in order to enter pressure state: socket_buffer < currently_alloced; currently_alloced is represented as size of sctp packets received so far and not yet delivered to userspace. x is the number of chunks/packets (since there is no bundling, and each chunk is delivered in separate packet, we can observe each chunk also as sctp packet, and what is important here, having its own sk_buff): socket_buffer < x*each_sctp_packet; each_sctp_packet is sctp chunk size + sizeof(struct sk_buff). socket_buffer is twice the amount of initially requested size of socket buffer, which is in case of sctp, twice the a_rwnd requested: 2*rwnd < x*(payload+sizeof(struc sk_buff)); sizeof(struct sk_buff) is 190 (3.13.0-rc4+). Above is stated that rwnd is 10000 and each payload size is 43 20000 < x(43+190); x > 20000/233; x ~> 84; After ~84 messages, pressure state is entered and 0 rwnd is advertised while received 84*43B ~= 3612B sctp data. This is why external observer notices sudden drop from 6474 to 0, as it will be now shown in example: IP A.34340 > B.12345: sctp (1) [INIT] [init tag: 1875509148] [rwnd: 81920] [OS: 10] [MIS: 65535] [init TSN: 1096057017] IP B.12345 > A.34340: sctp (1) [INIT ACK] [init tag: 3198966556] [rwnd: 10000] [OS: 10] [MIS: 10] [init TSN: 902132839] IP A.34340 > B.12345: sctp (1) [COOKIE ECHO] IP B.12345 > A.34340: sctp (1) [COOKIE ACK] IP A.34340 > B.12345: sctp (1) [DATA] (B)(E) [TSN: 1096057017] [SID: 0] [SSEQ 0] [PPID 0x18] IP B.12345 > A.34340: sctp (1) [SACK] [cum ack 1096057017] [a_rwnd 9957] [#gap acks 0] [#dup tsns 0] IP A.34340 > B.12345: sctp (1) [DATA] (B)(E) [TSN: 1096057018] [SID: 0] [SSEQ 1] [PPID 0x18] IP B.12345 > A.34340: sctp (1) [SACK] [cum ack 1096057018] [a_rwnd 9957] [#gap acks 0] [#dup tsns 0] IP A.34340 > B.12345: sctp (1) [DATA] (B)(E) [TSN: 1096057019] [SID: 0] [SSEQ 2] [PPID 0x18] IP B.12345 > A.34340: sctp (1) [SACK] [cum ack 1096057019] [a_rwnd 9914] [#gap acks 0] [#dup tsns 0] <...> IP A.34340 > B.12345: sctp (1) [DATA] (B)(E) [TSN: 1096057098] [SID: 0] [SSEQ 81] [PPID 0x18] IP B.12345 > A.34340: sctp (1) [SACK] [cum ack 1096057098] [a_rwnd 6517] [#gap acks 0] [#dup tsns 0] IP A.34340 > B.12345: sctp (1) [DATA] (B)(E) [TSN: 1096057099] [SID: 0] [SSEQ 82] [PPID 0x18] IP B.12345 > A.34340: sctp (1) [SACK] [cum ack 1096057099] [a_rwnd 6474] [#gap acks 0] [#dup tsns 0] IP A.34340 > B.12345: sctp (1) [DATA] (B)(E) [TSN: 1096057100] [SID: 0] [SSEQ 83] [PPID 0x18] --> Sudden drop IP B.12345 > A.34340: sctp (1) [SACK] [cum ack 1096057100] [a_rwnd 0] [#gap acks 0] [#dup tsns 0] At this point, rwnd_press stores current rwnd value so it can be later restored in sctp_assoc_rwnd_increase. This however doesn't happen as condition to start slowly increasing rwnd until rwnd_press is returned to rwnd is never met. This condition is not met since rwnd, after it hit 0, must first reach rwnd_press by adding amount which is read from userspace. Let us observe values in above example. Initial a_rwnd is 10000, pressure was hit when rwnd was ~6500 and the amount of actual sctp data currently waiting to be delivered to userspace is ~3500. When userspace starts to read, sctp_assoc_rwnd_increase will be blamed only for sctp data, which is ~3500. Condition is never met, and when userspace reads all data, rwnd stays on 3569. IP B.12345 > A.34340: sctp (1) [SACK] [cum ack 1096057100] [a_rwnd 1505] [#gap acks 0] [#dup tsns 0] IP B.12345 > A.34340: sctp (1) [SACK] [cum ack 1096057100] [a_rwnd 3010] [#gap acks 0] [#dup tsns 0] IP A.34340 > B.12345: sctp (1) [DATA] (B)(E) [TSN: 1096057101] [SID: 0] [SSEQ 84] [PPID 0x18] IP B.12345 > A.34340: sctp (1) [SACK] [cum ack 1096057101] [a_rwnd 3569] [#gap acks 0] [#dup tsns 0] --> At this point userspace read everything, rwnd recovered only to 3569 IP A.34340 > B.12345: sctp (1) [DATA] (B)(E) [TSN: 1096057102] [SID: 0] [SSEQ 85] [PPID 0x18] IP B.12345 > A.34340: sctp (1) [SACK] [cum ack 1096057102] [a_rwnd 3569] [#gap acks 0] [#dup tsns 0] Reproduction is straight forward, it is enough for sender to send packets of size less then sizeof(struct sk_buff) and receiver keeping them in its buffers. 2) Minute size window for associations sharing the same socket buffer In case multiple associations share the same socket, and same socket buffer (sctp.rcvbuf_policy == 0), different scenarios exist in which congestion on one of the associations can permanently drop rwnd of other association(s). Situation will be typically observed as one association suddenly having rwnd dropped to size of last packet received and never recovering beyond that point. Different scenarios will lead to it, but all have in common that one of the associations (let it be association from 1)) nearly depleted socket buffer, and the other association blames socket buffer just for the amount enough to start the pressure. This association will enter pressure state, set rwnd_press and announce 0 rwnd. When data is read by userspace, similar situation as in 1) will occur, rwnd will increase just for the size read by userspace but rwnd_press will be high enough so that association doesn't have enough credit to reach rwnd_press and restore to previous state. This case is special case of 1), being worse as there is, in the worst case, only one packet in buffer for which size rwnd will be increased. Consequence is association which has very low maximum rwnd ('minute size', in our case down to 43B - size of packet which caused pressure) and as such unusable. Scenario happened in the field and labs frequently after congestion state (link breaks, different probabilities of packet drop, packet reordering) and with scenario 1) preceding. Here is given a deterministic scenario for reproduction: >From node A establish two associations on the same socket, with rcvbuf_policy being set to share one common buffer (sctp.rcvbuf_policy == 0). On association 1 repeat scenario from 1), that is, bring it down to 0 and restore up. Observe scenario 1). Use small payload size (here we use 43). Once rwnd is 'recovered', bring it down close to 0, as in just one more packet would close it. This has as a consequence that association number 2 is able to receive (at least) one more packet which will bring it in pressure state. E.g. if association 2 had rwnd of 10000, packet received was 43, and we enter at this point into pressure, rwnd_press will have 9957. Once payload is delivered to userspace, rwnd will increase for 43, but conditions to restore rwnd to original state, just as in 1), will never be satisfied. --> Association 1, between A.y and B.12345 IP A.55915 > B.12345: sctp (1) [INIT] [init tag: 836880897] [rwnd: 10000] [OS: 10] [MIS: 65535] [init TSN: 4032536569] IP B.12345 > A.55915: sctp (1) [INIT ACK] [init tag: 2873310749] [rwnd: 81920] [OS: 10] [MIS: 10] [init TSN: 3799315613] IP A.55915 > B.12345: sctp (1) [COOKIE ECHO] IP B.12345 > A.55915: sctp (1) [COOKIE ACK] --> Association 2, between A.z and B.12346 IP A.55915 > B.12346: sctp (1) [INIT] [init tag: 534798321] [rwnd: 10000] [OS: 10] [MIS: 65535] [init TSN: 2099285173] IP B.12346 > A.55915: sctp (1) [INIT ACK] [init tag: 516668823] [rwnd: 81920] [OS: 10] [MIS: 10] [init TSN: 3676403240] IP A.55915 > B.12346: sctp (1) [COOKIE ECHO] IP B.12346 > A.55915: sctp (1) [COOKIE ACK] --> Deplete socket buffer by sending messages of size 43B over association 1 IP B.12345 > A.55915: sctp (1) [DATA] (B)(E) [TSN: 3799315613] [SID: 0] [SSEQ 0] [PPID 0x18] IP A.55915 > B.12345: sctp (1) [SACK] [cum ack 3799315613] [a_rwnd 9957] [#gap acks 0] [#dup tsns 0] <...> IP A.55915 > B.12345: sctp (1) [SACK] [cum ack 3799315696] [a_rwnd 6388] [#gap acks 0] [#dup tsns 0] IP B.12345 > A.55915: sctp (1) [DATA] (B)(E) [TSN: 3799315697] [SID: 0] [SSEQ 84] [PPID 0x18] IP A.55915 > B.12345: sctp (1) [SACK] [cum ack 3799315697] [a_rwnd 6345] [#gap acks 0] [#dup tsns 0] --> Sudden drop on 1 IP B.12345 > A.55915: sctp (1) [DATA] (B)(E) [TSN: 3799315698] [SID: 0] [SSEQ 85] [PPID 0x18] IP A.55915 > B.12345: sctp (1) [SACK] [cum ack 3799315698] [a_rwnd 0] [#gap acks 0] [#dup tsns 0] --> Here userspace read, rwnd 'recovered' to 3698, now deplete again using association 1 so there is place in buffer for only one more packet IP B.12345 > A.55915: sctp (1) [DATA] (B)(E) [TSN: 3799315799] [SID: 0] [SSEQ 186] [PPID 0x18] IP A.55915 > B.12345: sctp (1) [SACK] [cum ack 3799315799] [a_rwnd 86] [#gap acks 0] [#dup tsns 0] IP B.12345 > A.55915: sctp (1) [DATA] (B)(E) [TSN: 3799315800] [SID: 0] [SSEQ 187] [PPID 0x18] IP A.55915 > B.12345: sctp (1) [SACK] [cum ack 3799315800] [a_rwnd 43] [#gap acks 0] [#dup tsns 0] --> Socket buffer is almost depleted, but there is space for one more packet, send them over association 2, size 43B IP B.12346 > A.55915: sctp (1) [DATA] (B)(E) [TSN: 3676403240] [SID: 0] [SSEQ 0] [PPID 0x18] IP A.55915 > B.12346: sctp (1) [SACK] [cum ack 3676403240] [a_rwnd 0] [#gap acks 0] [#dup tsns 0] --> Immediate drop IP A.60995 > B.12346: sctp (1) [SACK] [cum ack 387491510] [a_rwnd 0] [#gap acks 0] [#dup tsns 0] --> Read everything from the socket, both association recover up to maximum rwnd they are capable of reaching, note that association 1 recovered up to 3698, and association 2 recovered only to 43 IP A.55915 > B.12345: sctp (1) [SACK] [cum ack 3799315800] [a_rwnd 1548] [#gap acks 0] [#dup tsns 0] IP A.55915 > B.12345: sctp (1) [SACK] [cum ack 3799315800] [a_rwnd 3053] [#gap acks 0] [#dup tsns 0] IP B.12345 > A.55915: sctp (1) [DATA] (B)(E) [TSN: 3799315801] [SID: 0] [SSEQ 188] [PPID 0x18] IP A.55915 > B.12345: sctp (1) [SACK] [cum ack 3799315801] [a_rwnd 3698] [#gap acks 0] [#dup tsns 0] IP B.12346 > A.55915: sctp (1) [DATA] (B)(E) [TSN: 3676403241] [SID: 0] [SSEQ 1] [PPID 0x18] IP A.55915 > B.12346: sctp (1) [SACK] [cum ack 3676403241] [a_rwnd 43] [#gap acks 0] [#dup tsns 0] A careful reader might wonder why it is necessary to reproduce 1) prior reproduction of 2). It is simply easier to observe when to send packet over association 2 which will push association into the pressure state. Proposed solution: Both problems share the same root cause, and that is improper scaling of socket buffer with rwnd. Solution in which sizeof(sk_buff) is taken into concern while calculating rwnd is not possible due to fact that there is no linear relationship between amount of data blamed in increase/decrease with IP packet in which payload arrived. Even in case such solution would be followed, complexity of the code would increase. Due to nature of current rwnd handling, slow increase (in sctp_assoc_rwnd_increase) of rwnd after pressure state is entered is rationale, but it gives false representation to the sender of current buffer space. Furthermore, it implements additional congestion control mechanism which is defined on implementation, and not on standard basis. Proposed solution simplifies whole algorithm having on mind definition from rfc: o Receiver Window (rwnd): This gives the sender an indication of the space available in the receiver's inbound buffer. Core of the proposed solution is given with these lines: sctp_assoc_rwnd_update: if ((asoc->base.sk->sk_rcvbuf - rx_count) > 0) asoc->rwnd = (asoc->base.sk->sk_rcvbuf - rx_count) >> 1; else asoc->rwnd = 0; We advertise to sender (half of) actual space we have. Half is in the braces depending whether you would like to observe size of socket buffer as SO_RECVBUF or twice the amount, i.e. size is the one visible from userspace, that is, from kernelspace. In this way sender is given with good approximation of our buffer space, regardless of the buffer policy - we always advertise what we have. Proposed solution fixes described problems and removes necessity for rwnd restoration algorithm. Finally, as proposed solution is simplification, some lines of code, along with some bytes in struct sctp_association are saved. Version 2 of the patch addressed comments from Vlad. Name of the function is set to be more descriptive, and two parts of code are changed, in one removing the superfluous call to sctp_assoc_rwnd_update since call would not result in update of rwnd, and the other being reordering of the code in a way that call to sctp_assoc_rwnd_update updates rwnd. Version 3 corrected change introduced in v2 in a way that existing function is not reordered/copied in line, but it is correctly called. Thanks Vlad for suggesting. Signed-off-by: Matija Glavinic Pecotic Reviewed-by: Alexander Sverdlin Acked-by: Vlad Yasevich Signed-off-by: David S. Miller --- include/net/sctp/structs.h | 14 +------- net/sctp/associola.c | 82 ++++++++++------------------------------------ net/sctp/sm_statefuns.c | 2 +- net/sctp/socket.c | 6 ---- net/sctp/ulpevent.c | 8 +++-- 5 files changed, 25 insertions(+), 87 deletions(-) diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index d992ca3145fe..6ee76c804893 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -1653,17 +1653,6 @@ struct sctp_association { /* This is the last advertised value of rwnd over a SACK chunk. */ __u32 a_rwnd; - /* Number of bytes by which the rwnd has slopped. The rwnd is allowed - * to slop over a maximum of the association's frag_point. - */ - __u32 rwnd_over; - - /* Keeps treack of rwnd pressure. This happens when we have - * a window, but not recevie buffer (i.e small packets). This one - * is releases slowly (1 PMTU at a time ). - */ - __u32 rwnd_press; - /* This is the sndbuf size in use for the association. * This corresponds to the sndbuf size for the association, * as specified in the sk->sndbuf. @@ -1892,8 +1881,7 @@ void sctp_assoc_update(struct sctp_association *old, __u32 sctp_association_get_next_tsn(struct sctp_association *); void sctp_assoc_sync_pmtu(struct sock *, struct sctp_association *); -void sctp_assoc_rwnd_increase(struct sctp_association *, unsigned int); -void sctp_assoc_rwnd_decrease(struct sctp_association *, unsigned int); +void sctp_assoc_rwnd_update(struct sctp_association *, bool); void sctp_assoc_set_primary(struct sctp_association *, struct sctp_transport *); void sctp_assoc_del_nonprimary_peers(struct sctp_association *, diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 5ae609200674..f558433537b8 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -1367,44 +1367,35 @@ static inline bool sctp_peer_needs_update(struct sctp_association *asoc) return false; } -/* Increase asoc's rwnd by len and send any window update SACK if needed. */ -void sctp_assoc_rwnd_increase(struct sctp_association *asoc, unsigned int len) +/* Update asoc's rwnd for the approximated state in the buffer, + * and check whether SACK needs to be sent. + */ +void sctp_assoc_rwnd_update(struct sctp_association *asoc, bool update_peer) { + int rx_count; struct sctp_chunk *sack; struct timer_list *timer; - if (asoc->rwnd_over) { - if (asoc->rwnd_over >= len) { - asoc->rwnd_over -= len; - } else { - asoc->rwnd += (len - asoc->rwnd_over); - asoc->rwnd_over = 0; - } - } else { - asoc->rwnd += len; - } + if (asoc->ep->rcvbuf_policy) + rx_count = atomic_read(&asoc->rmem_alloc); + else + rx_count = atomic_read(&asoc->base.sk->sk_rmem_alloc); - /* If we had window pressure, start recovering it - * once our rwnd had reached the accumulated pressure - * threshold. The idea is to recover slowly, but up - * to the initial advertised window. - */ - if (asoc->rwnd_press && asoc->rwnd >= asoc->rwnd_press) { - int change = min(asoc->pathmtu, asoc->rwnd_press); - asoc->rwnd += change; - asoc->rwnd_press -= change; - } + if ((asoc->base.sk->sk_rcvbuf - rx_count) > 0) + asoc->rwnd = (asoc->base.sk->sk_rcvbuf - rx_count) >> 1; + else + asoc->rwnd = 0; - pr_debug("%s: asoc:%p rwnd increased by %d to (%u, %u) - %u\n", - __func__, asoc, len, asoc->rwnd, asoc->rwnd_over, - asoc->a_rwnd); + pr_debug("%s: asoc:%p rwnd=%u, rx_count=%d, sk_rcvbuf=%d\n", + __func__, asoc, asoc->rwnd, rx_count, + asoc->base.sk->sk_rcvbuf); /* Send a window update SACK if the rwnd has increased by at least the * minimum of the association's PMTU and half of the receive buffer. * The algorithm used is similar to the one described in * Section 4.2.3.3 of RFC 1122. */ - if (sctp_peer_needs_update(asoc)) { + if (update_peer && sctp_peer_needs_update(asoc)) { asoc->a_rwnd = asoc->rwnd; pr_debug("%s: sending window update SACK- asoc:%p rwnd:%u " @@ -1426,45 +1417,6 @@ void sctp_assoc_rwnd_increase(struct sctp_association *asoc, unsigned int len) } } -/* Decrease asoc's rwnd by len. */ -void sctp_assoc_rwnd_decrease(struct sctp_association *asoc, unsigned int len) -{ - int rx_count; - int over = 0; - - if (unlikely(!asoc->rwnd || asoc->rwnd_over)) - pr_debug("%s: association:%p has asoc->rwnd:%u, " - "asoc->rwnd_over:%u!\n", __func__, asoc, - asoc->rwnd, asoc->rwnd_over); - - if (asoc->ep->rcvbuf_policy) - rx_count = atomic_read(&asoc->rmem_alloc); - else - rx_count = atomic_read(&asoc->base.sk->sk_rmem_alloc); - - /* If we've reached or overflowed our receive buffer, announce - * a 0 rwnd if rwnd would still be positive. Store the - * the potential pressure overflow so that the window can be restored - * back to original value. - */ - if (rx_count >= asoc->base.sk->sk_rcvbuf) - over = 1; - - if (asoc->rwnd >= len) { - asoc->rwnd -= len; - if (over) { - asoc->rwnd_press += asoc->rwnd; - asoc->rwnd = 0; - } - } else { - asoc->rwnd_over = len - asoc->rwnd; - asoc->rwnd = 0; - } - - pr_debug("%s: asoc:%p rwnd decreased by %d to (%u, %u, %u)\n", - __func__, asoc, len, asoc->rwnd, asoc->rwnd_over, - asoc->rwnd_press); -} /* Build the bind address list for the association based on info from the * local endpoint and the remote peer. diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 483dcd71b3c5..591b44d3b7de 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -6176,7 +6176,7 @@ static int sctp_eat_data(const struct sctp_association *asoc, * PMTU. In cases, such as loopback, this might be a rather * large spill over. */ - if ((!chunk->data_accepted) && (!asoc->rwnd || asoc->rwnd_over || + if ((!chunk->data_accepted) && (!asoc->rwnd || (datalen > asoc->rwnd + asoc->frag_point))) { /* If this is the next TSN, consider reneging to make diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 9e91d6e5df63..7075ac847fde 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -2092,12 +2092,6 @@ static int sctp_recvmsg(struct kiocb *iocb, struct sock *sk, sctp_skb_pull(skb, copied); skb_queue_head(&sk->sk_receive_queue, skb); - /* When only partial message is copied to the user, increase - * rwnd by that amount. If all the data in the skb is read, - * rwnd is updated when the event is freed. - */ - if (!sctp_ulpevent_is_notification(event)) - sctp_assoc_rwnd_increase(event->asoc, copied); goto out; } else if ((event->msg_flags & MSG_NOTIFICATION) || (event->msg_flags & MSG_EOR)) diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c index 85c64658bd0b..8d198ae03606 100644 --- a/net/sctp/ulpevent.c +++ b/net/sctp/ulpevent.c @@ -989,7 +989,7 @@ static void sctp_ulpevent_receive_data(struct sctp_ulpevent *event, skb = sctp_event2skb(event); /* Set the owner and charge rwnd for bytes received. */ sctp_ulpevent_set_owner(event, asoc); - sctp_assoc_rwnd_decrease(asoc, skb_headlen(skb)); + sctp_assoc_rwnd_update(asoc, false); if (!skb->data_len) return; @@ -1011,6 +1011,7 @@ static void sctp_ulpevent_release_data(struct sctp_ulpevent *event) { struct sk_buff *skb, *frag; unsigned int len; + struct sctp_association *asoc; /* Current stack structures assume that the rcv buffer is * per socket. For UDP style sockets this is not true as @@ -1035,8 +1036,11 @@ static void sctp_ulpevent_release_data(struct sctp_ulpevent *event) } done: - sctp_assoc_rwnd_increase(event->asoc, len); + asoc = event->asoc; + sctp_association_hold(asoc); sctp_ulpevent_release_owner(event); + sctp_assoc_rwnd_update(asoc, true); + sctp_association_put(asoc); } static void sctp_ulpevent_release_frag_data(struct sctp_ulpevent *event) -- cgit v1.2.3 From c321f7d7c87cdc623c87845f6378620573e57512 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Fri, 14 Feb 2014 15:32:20 +0100 Subject: drivers/net: tulip_remove_one needs to call pci_disable_device() Otherwise the device is not completely shut down. Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: David S. Miller --- drivers/net/ethernet/dec/tulip/tulip_core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/dec/tulip/tulip_core.c b/drivers/net/ethernet/dec/tulip/tulip_core.c index add05f14b38b..1642de78aac8 100644 --- a/drivers/net/ethernet/dec/tulip/tulip_core.c +++ b/drivers/net/ethernet/dec/tulip/tulip_core.c @@ -1939,6 +1939,7 @@ static void tulip_remove_one(struct pci_dev *pdev) pci_iounmap(pdev, tp->base_addr); free_netdev (dev); pci_release_regions (pdev); + pci_disable_device(pdev); /* pci_power_off (pdev, -1); */ } -- cgit v1.2.3 From 99932d4fc03a13bb3e94938fe25458fabc8f2fc3 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Sun, 16 Feb 2014 15:55:20 +0100 Subject: netdevice: add queue selection fallback handler for ndo_select_queue Add a new argument for ndo_select_queue() callback that passes a fallback handler. This gets invoked through netdev_pick_tx(); fallback handler is currently __netdev_pick_tx() as most drivers invoke this function within their customized implementation in case for skbs that don't need any special handling. This fallback handler can then be replaced on other call-sites with different queue selection methods (e.g. in packet sockets, pktgen etc). This also has the nice side-effect that __netdev_pick_tx() is then only invoked from netdev_pick_tx() and export of that function to modules can be undone. Suggested-by: David S. Miller Signed-off-by: Daniel Borkmann Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 2 +- drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 4 ++-- drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h | 2 +- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 6 +++--- drivers/net/ethernet/lantiq_etop.c | 2 +- drivers/net/ethernet/mellanox/mlx4/en_tx.c | 4 ++-- drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 2 +- drivers/net/ethernet/tile/tilegx.c | 2 +- drivers/net/team/team.c | 2 +- drivers/net/tun.c | 2 +- drivers/net/wireless/mwifiex/main.c | 2 +- drivers/staging/bcm/Bcmnet.c | 2 +- drivers/staging/netlogic/xlr_net.c | 2 +- drivers/staging/rtl8188eu/os_dep/os_intfs.c | 2 +- include/linux/netdevice.h | 9 ++++++--- net/core/flow_dissector.c | 7 +++---- net/mac80211/iface.c | 6 ++++-- 17 files changed, 31 insertions(+), 27 deletions(-) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 867664918715..1c6104d3501d 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -3707,7 +3707,7 @@ static inline int bond_slave_override(struct bonding *bond, static u16 bond_select_queue(struct net_device *dev, struct sk_buff *skb, - void *accel_priv) + void *accel_priv, select_queue_fallback_t fallback) { /* * This helper function exists to help dev_pick_tx get the correct diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index 9d7419e0390b..66c0df78c3ff 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -1873,7 +1873,7 @@ void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw) } u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb, - void *accel_priv) + void *accel_priv, select_queue_fallback_t fallback) { struct bnx2x *bp = netdev_priv(dev); @@ -1895,7 +1895,7 @@ u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb, } /* select a non-FCoE queue */ - return __netdev_pick_tx(dev, skb) % BNX2X_NUM_ETH_QUEUES(bp); + return fallback(dev, skb) % BNX2X_NUM_ETH_QUEUES(bp); } void bnx2x_set_num_queues(struct bnx2x *bp) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h index bfc58d488bb5..a89a40f88c25 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h @@ -496,7 +496,7 @@ int bnx2x_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos); /* select_queue callback */ u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb, - void *accel_priv); + void *accel_priv, select_queue_fallback_t fallback); static inline void bnx2x_update_rx_prod(struct bnx2x *bp, struct bnx2x_fastpath *fp, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 6d4ada72dfd0..18076c4178b4 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -6881,7 +6881,7 @@ static inline int ixgbe_maybe_stop_tx(struct ixgbe_ring *tx_ring, u16 size) } static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb, - void *accel_priv) + void *accel_priv, select_queue_fallback_t fallback) { struct ixgbe_fwd_adapter *fwd_adapter = accel_priv; #ifdef IXGBE_FCOE @@ -6907,7 +6907,7 @@ static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb, if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) break; default: - return __netdev_pick_tx(dev, skb); + return fallback(dev, skb); } f = &adapter->ring_feature[RING_F_FCOE]; @@ -6920,7 +6920,7 @@ static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb, return txq + f->offset; #else - return __netdev_pick_tx(dev, skb); + return fallback(dev, skb); #endif } diff --git a/drivers/net/ethernet/lantiq_etop.c b/drivers/net/ethernet/lantiq_etop.c index 8f9266c64c75..fd4b6aecf6ee 100644 --- a/drivers/net/ethernet/lantiq_etop.c +++ b/drivers/net/ethernet/lantiq_etop.c @@ -619,7 +619,7 @@ ltq_etop_set_multicast_list(struct net_device *dev) static u16 ltq_etop_select_queue(struct net_device *dev, struct sk_buff *skb, - void *accel_priv) + void *accel_priv, select_queue_fallback_t fallback) { /* we are currently only using the first queue */ return 0; diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c index 8e8a7eb43a2c..13457032d15f 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c @@ -629,7 +629,7 @@ static void build_inline_wqe(struct mlx4_en_tx_desc *tx_desc, struct sk_buff *sk } u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb, - void *accel_priv) + void *accel_priv, select_queue_fallback_t fallback) { struct mlx4_en_priv *priv = netdev_priv(dev); u16 rings_p_up = priv->num_tx_rings_p_up; @@ -641,7 +641,7 @@ u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb, if (vlan_tx_tag_present(skb)) up = vlan_tx_tag_get(skb) >> VLAN_PRIO_SHIFT; - return __netdev_pick_tx(dev, skb) % rings_p_up + up * rings_p_up; + return fallback(dev, skb) % rings_p_up + up * rings_p_up; } static void mlx4_bf_copy(void __iomem *dst, unsigned long *src, unsigned bytecnt) diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h index 3af04c3f42ea..9ca223bc90fc 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h @@ -723,7 +723,7 @@ int mlx4_en_arm_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq); void mlx4_en_tx_irq(struct mlx4_cq *mcq); u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb, - void *accel_priv); + void *accel_priv, select_queue_fallback_t fallback); netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev); int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv, diff --git a/drivers/net/ethernet/tile/tilegx.c b/drivers/net/ethernet/tile/tilegx.c index 023237a65720..17503da9f7a5 100644 --- a/drivers/net/ethernet/tile/tilegx.c +++ b/drivers/net/ethernet/tile/tilegx.c @@ -2071,7 +2071,7 @@ static int tile_net_tx(struct sk_buff *skb, struct net_device *dev) /* Return subqueue id on this core (one per core). */ static u16 tile_net_select_queue(struct net_device *dev, struct sk_buff *skb, - void *accel_priv) + void *accel_priv, select_queue_fallback_t fallback) { return smp_processor_id(); } diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index 28407426fd6f..c8624a8235ab 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -1648,7 +1648,7 @@ static netdev_tx_t team_xmit(struct sk_buff *skb, struct net_device *dev) } static u16 team_select_queue(struct net_device *dev, struct sk_buff *skb, - void *accel_priv) + void *accel_priv, select_queue_fallback_t fallback) { /* * This helper function exists to help dev_pick_tx get the correct diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 44c4db8450f0..8fe9cb7d0f72 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -366,7 +366,7 @@ static inline void tun_flow_save_rps_rxhash(struct tun_flow_entry *e, u32 hash) * hope the rxq no. may help here. */ static u16 tun_select_queue(struct net_device *dev, struct sk_buff *skb, - void *accel_priv) + void *accel_priv, select_queue_fallback_t fallback) { struct tun_struct *tun = netdev_priv(dev); struct tun_flow_entry *e; diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index 4d79761b9c87..9d3d2758ec35 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c @@ -748,7 +748,7 @@ static struct net_device_stats *mwifiex_get_stats(struct net_device *dev) static u16 mwifiex_netdev_select_wmm_queue(struct net_device *dev, struct sk_buff *skb, - void *accel_priv) + void *accel_priv, select_queue_fallback_t fallback) { skb->priority = cfg80211_classify8021d(skb, NULL); return mwifiex_1d_to_wmm_queue[skb->priority]; diff --git a/drivers/staging/bcm/Bcmnet.c b/drivers/staging/bcm/Bcmnet.c index 8dfdd2732bdc..95a2358267ba 100644 --- a/drivers/staging/bcm/Bcmnet.c +++ b/drivers/staging/bcm/Bcmnet.c @@ -40,7 +40,7 @@ static INT bcm_close(struct net_device *dev) } static u16 bcm_select_queue(struct net_device *dev, struct sk_buff *skb, - void *accel_priv) + void *accel_priv, select_queue_fallback_t fallback) { return ClassifyPacket(netdev_priv(dev), skb); } diff --git a/drivers/staging/netlogic/xlr_net.c b/drivers/staging/netlogic/xlr_net.c index eedffed17e39..6f9ac27730af 100644 --- a/drivers/staging/netlogic/xlr_net.c +++ b/drivers/staging/netlogic/xlr_net.c @@ -307,7 +307,7 @@ static netdev_tx_t xlr_net_start_xmit(struct sk_buff *skb, } static u16 xlr_net_select_queue(struct net_device *ndev, struct sk_buff *skb, - void *accel_priv) + void *accel_priv, select_queue_fallback_t fallback) { return (u16)smp_processor_id(); } diff --git a/drivers/staging/rtl8188eu/os_dep/os_intfs.c b/drivers/staging/rtl8188eu/os_dep/os_intfs.c index 68f98fa114d2..7c9ee58f47bb 100644 --- a/drivers/staging/rtl8188eu/os_dep/os_intfs.c +++ b/drivers/staging/rtl8188eu/os_dep/os_intfs.c @@ -653,7 +653,7 @@ static unsigned int rtw_classify8021d(struct sk_buff *skb) } static u16 rtw_select_queue(struct net_device *dev, struct sk_buff *skb, - void *accel_priv) + void *accel_priv, select_queue_fallback_t fallback) { struct adapter *padapter = rtw_netdev_priv(dev); struct mlme_priv *pmlmepriv = &padapter->mlmepriv; diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 21d4e6be8949..1de9c136b066 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -752,6 +752,9 @@ struct netdev_phys_port_id { unsigned char id_len; }; +typedef u16 (*select_queue_fallback_t)(struct net_device *dev, + struct sk_buff *skb); + /* * This structure defines the management hooks for network devices. * The following hooks can be defined; unless noted otherwise, they are @@ -783,7 +786,7 @@ struct netdev_phys_port_id { * Required can not be NULL. * * u16 (*ndo_select_queue)(struct net_device *dev, struct sk_buff *skb, - * void *accel_priv); + * void *accel_priv, select_queue_fallback_t fallback); * Called to decide which queue to when device supports multiple * transmit queues. * @@ -1005,7 +1008,8 @@ struct net_device_ops { struct net_device *dev); u16 (*ndo_select_queue)(struct net_device *dev, struct sk_buff *skb, - void *accel_priv); + void *accel_priv, + select_queue_fallback_t fallback); void (*ndo_change_rx_flags)(struct net_device *dev, int flags); void (*ndo_set_rx_mode)(struct net_device *dev); @@ -1551,7 +1555,6 @@ static inline void netdev_for_each_tx_queue(struct net_device *dev, struct netdev_queue *netdev_pick_tx(struct net_device *dev, struct sk_buff *skb, void *accel_priv); -u16 __netdev_pick_tx(struct net_device *dev, struct sk_buff *skb); /* * Net namespace inlines diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index 87577d447554..75fe83f590ea 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c @@ -372,7 +372,7 @@ static inline int get_xps_queue(struct net_device *dev, struct sk_buff *skb) #endif } -u16 __netdev_pick_tx(struct net_device *dev, struct sk_buff *skb) +static u16 __netdev_pick_tx(struct net_device *dev, struct sk_buff *skb) { struct sock *sk = skb->sk; int queue_index = sk_tx_queue_get(sk); @@ -392,7 +392,6 @@ u16 __netdev_pick_tx(struct net_device *dev, struct sk_buff *skb) return queue_index; } -EXPORT_SYMBOL(__netdev_pick_tx); struct netdev_queue *netdev_pick_tx(struct net_device *dev, struct sk_buff *skb, @@ -403,8 +402,8 @@ struct netdev_queue *netdev_pick_tx(struct net_device *dev, if (dev->real_num_tx_queues != 1) { const struct net_device_ops *ops = dev->netdev_ops; if (ops->ndo_select_queue) - queue_index = ops->ndo_select_queue(dev, skb, - accel_priv); + queue_index = ops->ndo_select_queue(dev, skb, accel_priv, + __netdev_pick_tx); else queue_index = __netdev_pick_tx(dev, skb); diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index d6d1f1df9119..ce1c44370610 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -1057,7 +1057,8 @@ static void ieee80211_uninit(struct net_device *dev) static u16 ieee80211_netdev_select_queue(struct net_device *dev, struct sk_buff *skb, - void *accel_priv) + void *accel_priv, + select_queue_fallback_t fallback) { return ieee80211_select_queue(IEEE80211_DEV_TO_SUB_IF(dev), skb); } @@ -1075,7 +1076,8 @@ static const struct net_device_ops ieee80211_dataif_ops = { static u16 ieee80211_monitor_select_queue(struct net_device *dev, struct sk_buff *skb, - void *accel_priv) + void *accel_priv, + select_queue_fallback_t fallback) { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_local *local = sdata->local; -- cgit v1.2.3 From b9507bdaf40e91fea2b1c0c1ee7dc627c8ee6fd6 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Sun, 16 Feb 2014 15:55:21 +0100 Subject: netdevice: move netdev_cap_txqueue for shared usage to header In order to allow users to invoke netdev_cap_txqueue, it needs to be moved into netdevice.h header file. While at it, also add kernel doc header to document the API. Signed-off-by: Daniel Borkmann Signed-off-by: David S. Miller --- include/linux/netdevice.h | 20 ++++++++++++++++++++ net/core/flow_dissector.c | 13 +------------ 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 1de9c136b066..e8eeebd49a98 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2278,6 +2278,26 @@ static inline void netdev_reset_queue(struct net_device *dev_queue) netdev_tx_reset_queue(netdev_get_tx_queue(dev_queue, 0)); } +/** + * netdev_cap_txqueue - check if selected tx queue exceeds device queues + * @dev: network device + * @queue_index: given tx queue index + * + * Returns 0 if given tx queue index >= number of device tx queues, + * otherwise returns the originally passed tx queue index. + */ +static inline u16 netdev_cap_txqueue(struct net_device *dev, u16 queue_index) +{ + if (unlikely(queue_index >= dev->real_num_tx_queues)) { + net_warn_ratelimited("%s selects TX queue %d, but real number of TX queues is %d\n", + dev->name, queue_index, + dev->real_num_tx_queues); + return 0; + } + + return queue_index; +} + /** * netif_running - test if up * @dev: network device diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index 75fe83f590ea..e29e810663d7 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c @@ -323,17 +323,6 @@ u32 __skb_get_poff(const struct sk_buff *skb) return poff; } -static inline u16 dev_cap_txqueue(struct net_device *dev, u16 queue_index) -{ - if (unlikely(queue_index >= dev->real_num_tx_queues)) { - net_warn_ratelimited("%s selects TX queue %d, but real number of TX queues is %d\n", - dev->name, queue_index, - dev->real_num_tx_queues); - return 0; - } - return queue_index; -} - static inline int get_xps_queue(struct net_device *dev, struct sk_buff *skb) { #ifdef CONFIG_XPS @@ -408,7 +397,7 @@ struct netdev_queue *netdev_pick_tx(struct net_device *dev, queue_index = __netdev_pick_tx(dev, skb); if (!accel_priv) - queue_index = dev_cap_txqueue(dev, queue_index); + queue_index = netdev_cap_txqueue(dev, queue_index); } skb_set_queue_mapping(skb, queue_index); -- cgit v1.2.3 From 0fd5d57ba3456c4d0b77d1ae64be4818b47d7545 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Sun, 16 Feb 2014 15:55:22 +0100 Subject: packet: check for ndo_select_queue during queue selection Mathias reported that on an AMD Geode LX embedded board (ALiX) with ath9k driver PACKET_QDISC_BYPASS, introduced in commit d346a3fae3ff ("packet: introduce PACKET_QDISC_BYPASS socket option"), triggers a WARN_ON() coming from the driver itself via 066dae93bdf ("ath9k: rework tx queue selection and fix queue stopping/waking"). The reason why this happened is that ndo_select_queue() call is not invoked from direct xmit path i.e. for ieee80211 subsystem that sets queue and TID (similar to 802.1d tag) which is being put into the frame through 802.11e (WMM, QoS). If that is not set, pending frame counter for e.g. ath9k can get messed up. So the WARN_ON() in ath9k is absolutely legitimate. Generally, the hw queue selection in ieee80211 depends on the type of traffic, and priorities are set according to ieee80211_ac_numbers mapping; working in a similar way as DiffServ only on a lower layer, so that the AP can favour frames that have "real-time" requirements like voice or video data frames. Therefore, check for presence of ndo_select_queue() in netdev ops and, if available, invoke it with a fallback handler to __packet_pick_tx_queue(), so that driver such as bnx2x, ixgbe, or mlx4 can still select a hw queue for transmission in relation to the current CPU while e.g. ieee80211 subsystem can make their own choices. Reported-by: Mathias Kretschmer Signed-off-by: Daniel Borkmann Cc: Jesper Dangaard Brouer Signed-off-by: David S. Miller --- net/packet/af_packet.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 6a2bb37506c5..b5dc1168f98a 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -308,11 +308,27 @@ static bool packet_use_direct_xmit(const struct packet_sock *po) return po->xmit == packet_direct_xmit; } -static u16 packet_pick_tx_queue(struct net_device *dev) +static u16 __packet_pick_tx_queue(struct net_device *dev, struct sk_buff *skb) { return (u16) raw_smp_processor_id() % dev->real_num_tx_queues; } +static void packet_pick_tx_queue(struct net_device *dev, struct sk_buff *skb) +{ + const struct net_device_ops *ops = dev->netdev_ops; + u16 queue_index; + + if (ops->ndo_select_queue) { + queue_index = ops->ndo_select_queue(dev, skb, NULL, + __packet_pick_tx_queue); + queue_index = netdev_cap_txqueue(dev, queue_index); + } else { + queue_index = __packet_pick_tx_queue(dev, skb); + } + + skb_set_queue_mapping(skb, queue_index); +} + /* register_prot_hook must be invoked with the po->bind_lock held, * or from a context in which asynchronous accesses to the packet * socket is not possible (packet_create()). @@ -2285,7 +2301,8 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) } } - skb_set_queue_mapping(skb, packet_pick_tx_queue(dev)); + packet_pick_tx_queue(dev, skb); + skb->destructor = tpacket_destruct_skb; __packet_set_status(po, ph, TP_STATUS_SENDING); packet_inc_pending(&po->tx_ring); @@ -2499,7 +2516,8 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len) skb->dev = dev; skb->priority = sk->sk_priority; skb->mark = sk->sk_mark; - skb_set_queue_mapping(skb, packet_pick_tx_queue(dev)); + + packet_pick_tx_queue(dev, skb); if (po->has_vnet_hdr) { if (vnet_hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) { -- cgit v1.2.3 From 624aef494f86ed0c58056361c06347ad62b26806 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Sun, 16 Feb 2014 17:11:10 +0100 Subject: ALSA: usb-audio: work around KEF X300A firmware bug When the driver tries to access Function Unit 10, the KEF X300A speakers' firmware apparently locks up, making even PCM streaming impossible. Work around this by ignoring this FU. Cc: Signed-off-by: Clemens Ladisch Signed-off-by: Takashi Iwai --- sound/usb/mixer_maps.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/sound/usb/mixer_maps.c b/sound/usb/mixer_maps.c index 32af6b741ef5..d1d72ff50347 100644 --- a/sound/usb/mixer_maps.c +++ b/sound/usb/mixer_maps.c @@ -328,6 +328,11 @@ static struct usbmix_name_map gamecom780_map[] = { {} }; +static const struct usbmix_name_map kef_x300a_map[] = { + { 10, NULL }, /* firmware locks up (?) when we try to access this FU */ + { 0 } +}; + /* * Control map entries */ @@ -419,6 +424,10 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = { .id = USB_ID(0x200c, 0x1018), .map = ebox44_map, }, + { + .id = USB_ID(0x27ac, 0x1000), + .map = kef_x300a_map, + }, { 0 } /* terminator */ }; -- cgit v1.2.3 From 5745d6a41a4f4aec29e2ccd591c6fb09ed73a955 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Fri, 10 Jan 2014 09:29:39 -0500 Subject: avr32: fix missing module.h causing build failure in mimc200/fram.c Causing this: In file included from arch/avr32/boards/mimc200/fram.c:13: include/linux/miscdevice.h:51: error: field 'list' has incomplete type include/linux/miscdevice.h:55: error: expected specifier-qualifier-list before 'mode_t' arch/avr32/boards/mimc200/fram.c:42: error: 'THIS_MODULE' undeclared here (not in a function) Reported-by: Fengguang Wu Cc: Haavard Skinnemoen Cc: Hans-Christian Egtvedt Signed-off-by: Paul Gortmaker Signed-off-by: Sergei Trofimovich Acked-by: Hans-Christian Egtvedt Cc: stable@vger.kernel.org --- arch/avr32/boards/mimc200/fram.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/avr32/boards/mimc200/fram.c b/arch/avr32/boards/mimc200/fram.c index 9764a1a1073e..c1466a872b9c 100644 --- a/arch/avr32/boards/mimc200/fram.c +++ b/arch/avr32/boards/mimc200/fram.c @@ -11,6 +11,7 @@ #define FRAM_VERSION "1.0" #include +#include #include #include #include -- cgit v1.2.3 From 8d80390cfc9434d5aa4fb9e5f9768a66b30cb8a6 Mon Sep 17 00:00:00 2001 From: Chen Gang Date: Sat, 1 Feb 2014 20:35:54 +0800 Subject: avr32: Makefile: add '-D__linux__' flag for gcc-4.4.7 use For avr32 cross compiler, do not define '__linux__' internally, so it will cause issue with allmodconfig. The related error: CC [M] fs/coda/psdev.o In file included from include/linux/coda.h:64, from fs/coda/psdev.c:45: include/uapi/linux/coda.h:221: error: expected specifier-qualifier-list before 'u_quad_t' The related toolchain version (which only download, not re-compile): [root@gchen linux-next]# /upstream/toolchain/download/avr32-gnu-toolchain-linux_x86/bin/avr32-gcc -v Using built-in specs. Target: avr32 Configured with: /data2/home/toolsbuild/jenkins-knuth/workspace/avr32-gnu-toolchain/src/gcc/configure --target=avr32 --host=i686-pc-linux-gnu --build=x86_64-pc-linux-gnu --prefix=/home/toolsbuild/jenkins-knuth/workspace/avr32-gnu-toolchain/avr32-gnu-toolchain-linux_x86 --enable-languages=c,c++ --disable-nls --disable-libssp --disable-libstdcxx-pch --with-dwarf2 --enable-version-specific-runtime-libs --disable-shared --enable-doc --with-mpfr-lib=/home/toolsbuild/jenkins-knuth/workspace/avr32-gnu-toolchain/avr32-gnu-toolchain-linux_x86/lib --with-mpfr-include=/home/toolsbuild/jenkins-knuth/workspace/avr32-gnu-toolchain/avr32-gnu-toolchain-linux_x86/include --with-gmp=/home/toolsbuild/jenkins-knuth/workspace/avr32-gnu-toolchain/avr32-gnu-toolchain-linux_x86 --with-mpc=/home/toolsbuild/jenkins-knuth/workspace/avr32-gnu-toolchain/avr32-gnu-toolchain-linux_x86 --enable-__cxa_atexit --disable-shared --with-newlib --with-pkgversion=AVR_32_bit_GNU_Toolchain_3.4.2_435 --with-bugurl=http://www .atmel.com/avr Thread model: single gcc version 4.4.7 (AVR_32_bit_GNU_Toolchain_3.4.2_435) Signed-off-by: Chen Gang Acked-by: Hans-Christian Egtvedt Cc: stable@vger.kernel.org --- arch/avr32/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/avr32/Makefile b/arch/avr32/Makefile index 22fb66590dcd..dba48a5d5bb9 100644 --- a/arch/avr32/Makefile +++ b/arch/avr32/Makefile @@ -11,7 +11,7 @@ all: uImage vmlinux.elf KBUILD_DEFCONFIG := atstk1002_defconfig -KBUILD_CFLAGS += -pipe -fno-builtin -mno-pic +KBUILD_CFLAGS += -pipe -fno-builtin -mno-pic -D__linux__ KBUILD_AFLAGS += -mrelax -mno-pic KBUILD_CFLAGS_MODULE += -mno-relax LDFLAGS_vmlinux += --relax -- cgit v1.2.3 From 1bbce4f3d11a6bfac0c51800f6337766f82b42da Mon Sep 17 00:00:00 2001 From: Chen Gang Date: Sun, 16 Feb 2014 19:39:30 +0800 Subject: avr32: add generic ioremap_wc() definition in io.h Need generic ioremap_wc(), or can not pass compiling with allmodconfig, the related error: CC [M] drivers/gpu/drm/drm_bufs.o drivers/gpu/drm/drm_bufs.c: In function 'drm_addmap_core': drivers/gpu/drm/drm_bufs.c:217: error: implicit declaration of function 'ioremap_wc' drivers/gpu/drm/drm_bufs.c:218: warning: assignment makes pointer from integer without a cast Signed-off-by: Chen Gang Acked-by: Hans-Christian Egtvedt --- arch/avr32/include/asm/io.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/avr32/include/asm/io.h b/arch/avr32/include/asm/io.h index fc6483f83ccc..4f5ec2bb7172 100644 --- a/arch/avr32/include/asm/io.h +++ b/arch/avr32/include/asm/io.h @@ -295,6 +295,8 @@ extern void __iounmap(void __iomem *addr); #define iounmap(addr) \ __iounmap(addr) +#define ioremap_wc ioremap_nocache + #define cached(addr) P1SEGADDR(addr) #define uncached(addr) P2SEGADDR(addr) -- cgit v1.2.3 From d7668f9d448aa757971ec3e68ecedb5ebecbddcc Mon Sep 17 00:00:00 2001 From: Chen Gang Date: Sun, 16 Feb 2014 19:36:06 +0800 Subject: avr32: add generic vga.h to Kbuild Need add generic "vga.h", or can not pass building for allmodconfig, the related error: CC [M] drivers/gpu/drm/drm_irq.o In file included from include/linux/vgaarb.h:34, from drivers/gpu/drm/drm_irq.c:42: include/video/vga.h:22:21: error: asm/vga.h: No such file or directory Signed-off-by: Chen Gang Acked-by: Hans-Christian Egtvedt --- arch/avr32/include/asm/Kbuild | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild index cfb9fe1b8df9..c7c64a63c29f 100644 --- a/arch/avr32/include/asm/Kbuild +++ b/arch/avr32/include/asm/Kbuild @@ -17,5 +17,6 @@ generic-y += scatterlist.h generic-y += sections.h generic-y += topology.h generic-y += trace_clock.h +generic-y += vga.h generic-y += xor.h generic-y += hash.h -- cgit v1.2.3 From 218eb9ed840c6279686ed6b0c3e31a083e241ff9 Mon Sep 17 00:00:00 2001 From: Archana Patni Date: Mon, 3 Feb 2014 12:44:16 +0530 Subject: HID: hid-sensor-hub: quirk for STM Sensor hub Added STM sensor hub vendor id in HID_SENSOR_HUB_ENUM_QUIRK to fix report descriptors. These devices uses old FW which uses logical 0 as minimum. In these, HID reports are not using proper collection classes. So we need to fix report descriptors,for such devices. This will not have any impact, if the FW uses logical 1 as minimum. We look for usage id for "power and report state", and modify logical minimum value to 1. This is a follow-up patch to commit id 875e36f8. Signed-off-by: Archana Patni Reviewed-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 36281689351b..00fd7452722f 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -451,6 +451,9 @@ #define USB_VENDOR_ID_INTEL_1 0x8087 #define USB_DEVICE_ID_INTEL_HID_SENSOR 0x09fa +#define USB_VENDOR_ID_STM_0 0x0483 +#define USB_DEVICE_ID_STM_HID_SENSOR 0x91d1 + #define USB_VENDOR_ID_ION 0x15e4 #define USB_DEVICE_ID_ICADE 0x0132 diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c index 46f4480035bc..9c22e14c57f0 100644 --- a/drivers/hid/hid-sensor-hub.c +++ b/drivers/hid/hid-sensor-hub.c @@ -665,6 +665,9 @@ static const struct hid_device_id sensor_hub_devices[] = { { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_INTEL_1, USB_DEVICE_ID_INTEL_HID_SENSOR), .driver_data = HID_SENSOR_HUB_ENUM_QUIRK}, + { 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, HID_ANY_ID, HID_ANY_ID) }, { } -- cgit v1.2.3 From 930cd6e46eadce8b8ed2a232ee536e5fd286c152 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Tue, 21 Jan 2014 11:22:05 +0100 Subject: batman-adv: fix soft-interface MTU computation The current MTU computation always returns a value smaller than 1500bytes even if the real interfaces have an MTU large enough to compensate the batman-adv overhead. Fix the computation by properly returning the highest admitted value. Introduced by a19d3d85e1b854e4a483a55d740a42458085560d ("batman-adv: limit local translation table max size") Reported-by: Russell Senior Signed-off-by: Antonio Quartulli Signed-off-by: Marek Lindner --- net/batman-adv/hard-interface.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c index 3d417d3641c6..b851cc580853 100644 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c @@ -241,7 +241,7 @@ int batadv_hardif_min_mtu(struct net_device *soft_iface) { struct batadv_priv *bat_priv = netdev_priv(soft_iface); const struct batadv_hard_iface *hard_iface; - int min_mtu = ETH_DATA_LEN; + int min_mtu = INT_MAX; rcu_read_lock(); list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) { @@ -256,8 +256,6 @@ int batadv_hardif_min_mtu(struct net_device *soft_iface) } rcu_read_unlock(); - atomic_set(&bat_priv->packet_size_max, min_mtu); - if (atomic_read(&bat_priv->fragmentation) == 0) goto out; @@ -268,13 +266,21 @@ int batadv_hardif_min_mtu(struct net_device *soft_iface) min_mtu = min_t(int, min_mtu, BATADV_FRAG_MAX_FRAG_SIZE); min_mtu -= sizeof(struct batadv_frag_packet); min_mtu *= BATADV_FRAG_MAX_FRAGMENTS; - atomic_set(&bat_priv->packet_size_max, min_mtu); - - /* with fragmentation enabled we can fragment external packets easily */ - min_mtu = min_t(int, min_mtu, ETH_DATA_LEN); out: - return min_mtu - batadv_max_header_len(); + /* report to the other components the maximum amount of bytes that + * batman-adv can send over the wire (without considering the payload + * overhead). For example, this value is used by TT to compute the + * maximum local table table size + */ + atomic_set(&bat_priv->packet_size_max, min_mtu); + + /* the real soft-interface MTU is computed by removing the payload + * overhead from the maximum amount of bytes that was just computed. + * + * However batman-adv does not support MTUs bigger than ETH_DATA_LEN + */ + return min_t(int, min_mtu - batadv_max_header_len(), ETH_DATA_LEN); } /* adjusts the MTU if a new interface with a smaller MTU appeared. */ -- cgit v1.2.3 From e889241f45f9cecbc84a6ffed577083ab52e62ee Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Mon, 27 Jan 2014 12:23:28 +0100 Subject: batman-adv: fix TT-TVLV parsing on OGM reception When accessing a TT-TVLV container in the OGM RX path the variable pointing to the list of changes to apply is altered by mistake. This makes the TT component read data at the wrong position in the OGM packet buffer. Fix it by removing the bogus pointer alteration. Signed-off-by: Antonio Quartulli Signed-off-by: Marek Lindner --- net/batman-adv/translation-table.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index b6071f675a3e..beba13fbd10a 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -3218,7 +3218,6 @@ static void batadv_tt_update_orig(struct batadv_priv *bat_priv, spin_lock_bh(&orig_node->tt_lock); - tt_change = (struct batadv_tvlv_tt_change *)tt_buff; batadv_tt_update_changes(bat_priv, orig_node, tt_num_changes, ttvn, tt_change); -- cgit v1.2.3 From 91c2b1a9f680ff105369d49abc7e19ca7efb33e1 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Tue, 28 Jan 2014 02:06:47 +0100 Subject: batman-adv: release vlan object after checking the CRC There is a refcounter unbalance in the CRC checking routine invoked on OGM reception. A vlan object is retrieved (thus its refcounter is increased by one) but it is never properly released. This leads to a memleak because the vlan object will never be free'd. Fix this by releasing the vlan object after having read the CRC. Reported-by: Russell Senior Reported-by: Daniel Reported-by: cmsv Signed-off-by: Antonio Quartulli Signed-off-by: Marek Lindner --- net/batman-adv/translation-table.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index beba13fbd10a..c21c5572c860 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -2262,6 +2262,7 @@ static bool batadv_tt_global_check_crc(struct batadv_orig_node *orig_node, { struct batadv_tvlv_tt_vlan_data *tt_vlan_tmp; struct batadv_orig_node_vlan *vlan; + uint32_t crc; int i; /* check if each received CRC matches the locally stored one */ @@ -2281,7 +2282,10 @@ static bool batadv_tt_global_check_crc(struct batadv_orig_node *orig_node, if (!vlan) return false; - if (vlan->tt.crc != ntohl(tt_vlan_tmp->crc)) + crc = vlan->tt.crc; + batadv_orig_node_vlan_free_ref(vlan); + + if (crc != ntohl(tt_vlan_tmp->crc)) return false; } -- cgit v1.2.3 From f1791425cf0bcda43ab9a9a37df1ad3ccb1f6654 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Thu, 30 Jan 2014 00:12:24 +0100 Subject: batman-adv: properly check pskb_may_pull return value pskb_may_pull() returns 1 on success and 0 in case of failure, therefore checking for the return value being negative does not make sense at all. This way if the function fails we will probably read beyond the current skb data buffer. Fix this by doing the proper check. Signed-off-by: Antonio Quartulli Signed-off-by: Marek Lindner --- net/batman-adv/routing.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index 1ed9f7c9ecea..c26f07368849 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@ -688,7 +688,7 @@ static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv, int is_old_ttvn; /* check if there is enough data before accessing it */ - if (pskb_may_pull(skb, hdr_len + ETH_HLEN) < 0) + if (!pskb_may_pull(skb, hdr_len + ETH_HLEN)) return 0; /* create a copy of the skb (in case of for re-routing) to modify it. */ -- cgit v1.2.3 From 08bf0ed29c7ded45c477d08618220dd200c3524a Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Wed, 29 Jan 2014 11:25:12 +0100 Subject: batman-adv: avoid potential race condition when adding a new neighbour When adding a new neighbour it is important to atomically perform the following: - check if the neighbour already exists - append the neighbour to the proper list If the two operations are not performed in an atomic context it is possible that two concurrent insertions add the same neighbour twice. Signed-off-by: Antonio Quartulli Signed-off-by: Marek Lindner --- net/batman-adv/bat_iv_ogm.c | 22 ++++++++++++++++------ net/batman-adv/originator.c | 36 ++++++++++++++++++++++++++++++++++++ net/batman-adv/originator.h | 4 ++++ 3 files changed, 56 insertions(+), 6 deletions(-) diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index 512159bf607f..094ae7ca50a0 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c @@ -266,7 +266,7 @@ batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface, struct batadv_orig_node *orig_neigh) { struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface); - struct batadv_neigh_node *neigh_node; + struct batadv_neigh_node *neigh_node, *tmp_neigh_node; neigh_node = batadv_neigh_node_new(hard_iface, neigh_addr, orig_node); if (!neigh_node) @@ -281,14 +281,24 @@ batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface, neigh_node->orig_node = orig_neigh; neigh_node->if_incoming = hard_iface; - batadv_dbg(BATADV_DBG_BATMAN, bat_priv, - "Creating new neighbor %pM for orig_node %pM on interface %s\n", - neigh_addr, orig_node->orig, hard_iface->net_dev->name); - spin_lock_bh(&orig_node->neigh_list_lock); - hlist_add_head_rcu(&neigh_node->list, &orig_node->neigh_list); + tmp_neigh_node = batadv_neigh_node_get(orig_node, hard_iface, + neigh_addr); + if (!tmp_neigh_node) { + hlist_add_head_rcu(&neigh_node->list, &orig_node->neigh_list); + } else { + kfree(neigh_node); + batadv_hardif_free_ref(hard_iface); + neigh_node = tmp_neigh_node; + } spin_unlock_bh(&orig_node->neigh_list_lock); + if (!tmp_neigh_node) + batadv_dbg(BATADV_DBG_BATMAN, bat_priv, + "Creating new neighbor %pM for orig_node %pM on interface %s\n", + neigh_addr, orig_node->orig, + hard_iface->net_dev->name); + out: return neigh_node; } diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index 6df12a2e3605..853941629dc1 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c @@ -457,6 +457,42 @@ out: return neigh_node; } +/** + * batadv_neigh_node_get - retrieve a neighbour from the list + * @orig_node: originator which the neighbour belongs to + * @hard_iface: the interface where this neighbour is connected to + * @addr: the address of the neighbour + * + * Looks for and possibly returns a neighbour belonging to this originator list + * which is connected through the provided hard interface. + * Returns NULL if the neighbour is not found. + */ +struct batadv_neigh_node * +batadv_neigh_node_get(const struct batadv_orig_node *orig_node, + const struct batadv_hard_iface *hard_iface, + const uint8_t *addr) +{ + struct batadv_neigh_node *tmp_neigh_node, *res = NULL; + + rcu_read_lock(); + hlist_for_each_entry_rcu(tmp_neigh_node, &orig_node->neigh_list, list) { + if (!batadv_compare_eth(tmp_neigh_node->addr, addr)) + continue; + + if (tmp_neigh_node->if_incoming != hard_iface) + continue; + + if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) + continue; + + res = tmp_neigh_node; + break; + } + rcu_read_unlock(); + + return res; +} + /** * batadv_orig_ifinfo_free_rcu - free the orig_ifinfo object * @rcu: rcu pointer of the orig_ifinfo object diff --git a/net/batman-adv/originator.h b/net/batman-adv/originator.h index 37be290f63f6..db3a9ed734cb 100644 --- a/net/batman-adv/originator.h +++ b/net/batman-adv/originator.h @@ -29,6 +29,10 @@ void batadv_orig_node_free_ref_now(struct batadv_orig_node *orig_node); struct batadv_orig_node *batadv_orig_node_new(struct batadv_priv *bat_priv, const uint8_t *addr); struct batadv_neigh_node * +batadv_neigh_node_get(const struct batadv_orig_node *orig_node, + const struct batadv_hard_iface *hard_iface, + const uint8_t *addr); +struct batadv_neigh_node * batadv_neigh_node_new(struct batadv_hard_iface *hard_iface, const uint8_t *neigh_addr, struct batadv_orig_node *orig_node); -- cgit v1.2.3 From b2262df7fcf2c395eca564df83238e931d88d7bf Mon Sep 17 00:00:00 2001 From: Simon Wunderlich Date: Sat, 8 Feb 2014 16:45:06 +0100 Subject: batman-adv: fix potential orig_node reference leak Since batadv_orig_node_new() sets the refcount to two, assuming that the calling function will use a reference for putting the orig_node into a hash or similar, both references must be freed if initialization of the orig_node fails. Otherwise that object may be leaked in that error case. 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 094ae7ca50a0..42cbc0a68941 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c @@ -254,6 +254,8 @@ batadv_iv_ogm_orig_get(struct batadv_priv *bat_priv, const uint8_t *addr) free_bcast_own: kfree(orig_node->bat_iv.bcast_own); free_orig_node: + /* free twice, as batadv_orig_node_new sets refcount to 2 */ + batadv_orig_node_free_ref(orig_node); batadv_orig_node_free_ref(orig_node); return NULL; -- cgit v1.2.3 From a30e22ca8464c2dc573e0144a972221c2f06c2cd Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Tue, 11 Feb 2014 17:05:06 +0100 Subject: batman-adv: fix TT CRC computation by ensuring byte order When computing the CRC on a 2byte variable the order of the bytes obviously alters the final result. This means that computing the CRC over the same value on two archs having different endianess leads to different numbers. The global and local translation table CRC computation routine makes this mistake while processing the clients VIDs. The result is a continuous CRC mismatching between nodes having different endianess. Fix this by converting the VID to Network Order before processing it. This guarantees that every node uses the same byte order. Introduced by 7ea7b4a142758deaf46c1af0ca9ceca6dd55138b ("batman-adv: make the TT CRC logic VLAN specific") Reported-by: Russel Senior Signed-off-by: Antonio Quartulli Tested-by: Russell Senior Signed-off-by: Marek Lindner --- net/batman-adv/translation-table.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index c21c5572c860..959dde721c46 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -1975,6 +1975,7 @@ static uint32_t batadv_tt_global_crc(struct batadv_priv *bat_priv, struct hlist_head *head; uint32_t i, crc_tmp, crc = 0; uint8_t flags; + __be16 tmp_vid; for (i = 0; i < hash->size; i++) { head = &hash->table[i]; @@ -2011,8 +2012,11 @@ static uint32_t batadv_tt_global_crc(struct batadv_priv *bat_priv, orig_node)) continue; - crc_tmp = crc32c(0, &tt_common->vid, - sizeof(tt_common->vid)); + /* use network order to read the VID: this ensures that + * every node reads the bytes in the same order. + */ + tmp_vid = htons(tt_common->vid); + crc_tmp = crc32c(0, &tmp_vid, sizeof(tmp_vid)); /* compute the CRC on flags that have to be kept in sync * among nodes @@ -2046,6 +2050,7 @@ static uint32_t batadv_tt_local_crc(struct batadv_priv *bat_priv, struct hlist_head *head; uint32_t i, crc_tmp, crc = 0; uint8_t flags; + __be16 tmp_vid; for (i = 0; i < hash->size; i++) { head = &hash->table[i]; @@ -2064,8 +2069,11 @@ static uint32_t batadv_tt_local_crc(struct batadv_priv *bat_priv, if (tt_common->flags & BATADV_TT_CLIENT_NEW) continue; - crc_tmp = crc32c(0, &tt_common->vid, - sizeof(tt_common->vid)); + /* use network order to read the VID: this ensures that + * every node reads the bytes in the same order. + */ + tmp_vid = htons(tt_common->vid); + crc_tmp = crc32c(0, &tmp_vid, sizeof(tmp_vid)); /* compute the CRC on flags that have to be kept in sync * among nodes -- cgit v1.2.3 From 05c3c8a636aa9ee35ce13f65afc5b665615cc786 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Tue, 11 Feb 2014 17:05:07 +0100 Subject: batman-adv: free skb on TVLV parsing success When the TVLV parsing routine succeed the skb is left untouched thus leading to a memory leak. Fix this by consuming the skb in case of success. Introduced by ef26157747d42254453f6b3ac2bd8bd3c53339c3 ("batman-adv: tvlv - basic infrastructure") Reported-by: Russel Senior Signed-off-by: Antonio Quartulli Tested-by: Russell Senior Signed-off-by: Marek Lindner --- net/batman-adv/routing.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index c26f07368849..a953d5b196a3 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@ -918,6 +918,8 @@ int batadv_recv_unicast_tvlv(struct sk_buff *skb, if (ret != NET_RX_SUCCESS) ret = batadv_route_unicast_packet(skb, recv_if); + else + consume_skb(skb); return ret; } -- cgit v1.2.3 From a5a5cb8cab526af2f6cbe9715f8ca843192f0d81 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Sat, 15 Feb 2014 02:17:20 +0100 Subject: batman-adv: avoid double free when orig_node initialization fails In the failure path of the orig_node initialization routine the orig_node->bat_iv.bcast_own field is free'd twice: first in batadv_iv_ogm_orig_get() and then later in batadv_orig_node_free_rcu(). Fix it by removing the kfree in batadv_iv_ogm_orig_get(). Signed-off-by: Antonio Quartulli Signed-off-by: Marek Lindner --- net/batman-adv/bat_iv_ogm.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index 42cbc0a68941..8323bced8e5b 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c @@ -241,18 +241,16 @@ batadv_iv_ogm_orig_get(struct batadv_priv *bat_priv, const uint8_t *addr) size = bat_priv->num_ifaces * sizeof(uint8_t); orig_node->bat_iv.bcast_own_sum = kzalloc(size, GFP_ATOMIC); if (!orig_node->bat_iv.bcast_own_sum) - goto free_bcast_own; + goto free_orig_node; hash_added = batadv_hash_add(bat_priv->orig_hash, batadv_compare_orig, batadv_choose_orig, orig_node, &orig_node->hash_entry); if (hash_added != 0) - goto free_bcast_own; + goto free_orig_node; return orig_node; -free_bcast_own: - kfree(orig_node->bat_iv.bcast_own); free_orig_node: /* free twice, as batadv_orig_node_new sets refcount to 2 */ batadv_orig_node_free_ref(orig_node); -- cgit v1.2.3 From 70b271a78beba787155d6696aacd7c4d4a251c50 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Sat, 15 Feb 2014 21:50:37 +0100 Subject: batman-adv: fix potential kernel paging error for unicast transmissions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit batadv_send_skb_prepare_unicast(_4addr) might reallocate the skb's data. If it does then our ethhdr pointer is not valid anymore in batadv_send_skb_unicast(), resulting in a kernel paging error. Fixing this by refetching the ethhdr pointer after the potential reallocation. Signed-off-by: Linus Lüssing Signed-off-by: Antonio Quartulli --- net/batman-adv/send.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c index 579f5f00a385..843febd1e519 100644 --- a/net/batman-adv/send.c +++ b/net/batman-adv/send.c @@ -254,9 +254,9 @@ static int batadv_send_skb_unicast(struct batadv_priv *bat_priv, struct batadv_orig_node *orig_node, unsigned short vid) { - struct ethhdr *ethhdr = (struct ethhdr *)skb->data; + struct ethhdr *ethhdr; struct batadv_unicast_packet *unicast_packet; - int ret = NET_XMIT_DROP; + int ret = NET_XMIT_DROP, hdr_size; if (!orig_node) goto out; @@ -265,12 +265,16 @@ static int batadv_send_skb_unicast(struct batadv_priv *bat_priv, case BATADV_UNICAST: if (!batadv_send_skb_prepare_unicast(skb, orig_node)) goto out; + + hdr_size = sizeof(*unicast_packet); break; case BATADV_UNICAST_4ADDR: if (!batadv_send_skb_prepare_unicast_4addr(bat_priv, skb, orig_node, packet_subtype)) goto out; + + hdr_size = sizeof(struct batadv_unicast_4addr_packet); break; default: /* this function supports UNICAST and UNICAST_4ADDR only. It @@ -279,6 +283,7 @@ static int batadv_send_skb_unicast(struct batadv_priv *bat_priv, goto out; } + ethhdr = (struct ethhdr *)(skb->data + hdr_size); unicast_packet = (struct batadv_unicast_packet *)skb->data; /* inform the destination node that we are still missing a correct route -- cgit v1.2.3 From 08b44656c08c8c2f73cdac2a058be2880e3361f2 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Mon, 17 Feb 2014 14:22:21 +0100 Subject: gre: add link local route when local addr is any This bug was reported by Steinar H. Gunderson and was introduced by commit f7cb8886335d ("sit/gre6: don't try to add the same route two times"). root@morgental:~# ip tunnel add foo mode gre remote 1.2.3.4 ttl 64 root@morgental:~# ip link set foo up mtu 1468 root@morgental:~# ip -6 route show dev foo fe80::/64 proto kernel metric 256 but after the above commit, no such route shows up. There is no link local route because dev->dev_addr is 0 (because local ipv4 address is 0), hence no link local address is configured. In this scenario, the link local address is added manually: 'ip -6 addr add fe80::1 dev foo' and because prefix is /128, no link local route is added by the kernel. Even if the right things to do is to add the link local address with a /64 prefix, we need to restore the previous behavior to avoid breaking userpace. Reported-by: Steinar H. Gunderson Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- net/ipv6/addrconf.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index ad235690684c..fdbfeca36d63 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -2783,6 +2783,8 @@ static void addrconf_gre_config(struct net_device *dev) ipv6_addr_set(&addr, htonl(0xFE800000), 0, 0, 0); if (!ipv6_generate_eui64(addr.s6_addr + 8, dev)) addrconf_add_linklocal(idev, &addr); + else + addrconf_prefix_route(&addr, 64, dev, 0, 0); } #endif -- cgit v1.2.3 From 292f503cade2b1d966239ef56a851e6897d1ba92 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Sun, 16 Feb 2014 21:42:56 -0500 Subject: NFSv4: Use the correct net namespace in nfs4_update_server We need to use the same net namespace that was used to resolve the hostname and sockaddr arguments. Fixes: 32e62b7c3ef09 (NFS: Add nfs4_update_server) Cc: Chuck Lever Signed-off-by: Trond Myklebust --- fs/nfs/internal.h | 3 ++- fs/nfs/nfs4client.c | 7 ++++--- fs/nfs/nfs4namespace.c | 12 ++++++------ 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index fafdddac8271..b46cf5a67329 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -176,7 +176,8 @@ extern struct nfs_server *nfs4_create_server( extern struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *, struct nfs_fh *); extern int nfs4_update_server(struct nfs_server *server, const char *hostname, - struct sockaddr *sap, size_t salen); + struct sockaddr *sap, size_t salen, + struct net *net); extern void nfs_free_server(struct nfs_server *server); extern struct nfs_server *nfs_clone_server(struct nfs_server *, struct nfs_fh *, diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c index 860ad26a5590..0e46d3d1b6cc 100644 --- a/fs/nfs/nfs4client.c +++ b/fs/nfs/nfs4client.c @@ -1135,6 +1135,7 @@ static int nfs_probe_destination(struct nfs_server *server) * @hostname: new end-point's hostname * @sap: new end-point's socket address * @salen: size of "sap" + * @net: net namespace * * The nfs_server must be quiescent before this function is invoked. * Either its session is drained (NFSv4.1+), or its transport is @@ -1143,13 +1144,13 @@ static int nfs_probe_destination(struct nfs_server *server) * Returns zero on success, or a negative errno value. */ int nfs4_update_server(struct nfs_server *server, const char *hostname, - struct sockaddr *sap, size_t salen) + struct sockaddr *sap, size_t salen, struct net *net) { struct nfs_client *clp = server->nfs_client; struct rpc_clnt *clnt = server->client; struct xprt_create xargs = { .ident = clp->cl_proto, - .net = &init_net, + .net = net, .dstaddr = sap, .addrlen = salen, .servername = hostname, @@ -1189,7 +1190,7 @@ int nfs4_update_server(struct nfs_server *server, const char *hostname, error = nfs4_set_client(server, hostname, sap, salen, buf, clp->cl_rpcclient->cl_auth->au_flavor, clp->cl_proto, clnt->cl_timeout, - clp->cl_minorversion, clp->cl_net); + clp->cl_minorversion, net); nfs_put_client(clp); if (error != 0) { nfs_server_insert_lists(server); diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c index 4e7f05d3e9db..3d5dbf80d46a 100644 --- a/fs/nfs/nfs4namespace.c +++ b/fs/nfs/nfs4namespace.c @@ -121,9 +121,8 @@ static int nfs4_validate_fspath(struct dentry *dentry, } static size_t nfs_parse_server_name(char *string, size_t len, - struct sockaddr *sa, size_t salen, struct nfs_server *server) + struct sockaddr *sa, size_t salen, struct net *net) { - struct net *net = rpc_net_ns(server->client); ssize_t ret; ret = rpc_pton(net, string, len, sa, salen); @@ -223,6 +222,7 @@ static struct vfsmount *try_location(struct nfs_clone_mount *mountdata, const struct nfs4_fs_location *location) { const size_t addr_bufsize = sizeof(struct sockaddr_storage); + struct net *net = rpc_net_ns(NFS_SB(mountdata->sb)->client); struct vfsmount *mnt = ERR_PTR(-ENOENT); char *mnt_path; unsigned int maxbuflen; @@ -248,8 +248,7 @@ static struct vfsmount *try_location(struct nfs_clone_mount *mountdata, continue; mountdata->addrlen = nfs_parse_server_name(buf->data, buf->len, - mountdata->addr, addr_bufsize, - NFS_SB(mountdata->sb)); + mountdata->addr, addr_bufsize, net); if (mountdata->addrlen == 0) continue; @@ -419,6 +418,7 @@ static int nfs4_try_replacing_one_location(struct nfs_server *server, const struct nfs4_fs_location *location) { const size_t addr_bufsize = sizeof(struct sockaddr_storage); + struct net *net = rpc_net_ns(server->client); struct sockaddr *sap; unsigned int s; size_t salen; @@ -440,7 +440,7 @@ static int nfs4_try_replacing_one_location(struct nfs_server *server, continue; salen = nfs_parse_server_name(buf->data, buf->len, - sap, addr_bufsize, server); + sap, addr_bufsize, net); if (salen == 0) continue; rpc_set_port(sap, NFS_PORT); @@ -450,7 +450,7 @@ static int nfs4_try_replacing_one_location(struct nfs_server *server, if (hostname == NULL) break; - error = nfs4_update_server(server, hostname, sap, salen); + error = nfs4_update_server(server, hostname, sap, salen, net); kfree(hostname); if (error == 0) break; -- cgit v1.2.3 From eb85569fe2d06c2fbf4de7b66c263ca095b397aa Mon Sep 17 00:00:00 2001 From: Emil Goode Date: Thu, 13 Feb 2014 17:50:19 +0100 Subject: usbnet: remove generic hard_header_len check This patch removes a generic hard_header_len check from the usbnet module that is causing dropped packages under certain circumstances for devices that send rx packets that cross urb boundaries. One example is the AX88772B which occasionally send rx packets that cross urb boundaries where the remaining partial packet is sent with no hardware header. When the buffer with a partial packet is of less number of octets than the value of hard_header_len the buffer is discarded by the usbnet module. With AX88772B this can be reproduced by using ping with a packet size between 1965-1976. The bug has been reported here: https://bugzilla.kernel.org/show_bug.cgi?id=29082 This patch introduces the following changes: - Removes the generic hard_header_len check in the rx_complete function in the usbnet module. - Introduces a ETH_HLEN check for skbs that are not cloned from within a rx_fixup callback. - For safety a hard_header_len check is added to each rx_fixup callback function that could be affected by this change. These extra checks could possibly be removed by someone who has the hardware to test. - Removes a call to dev_kfree_skb_any() and instead utilizes the dev->done list to queue skbs for cleanup. The changes place full responsibility on the rx_fixup callback functions that clone skbs to only pass valid skbs to the usbnet_skb_return function. Signed-off-by: Emil Goode Reported-by: Igor Gnatenko Signed-off-by: David S. Miller --- drivers/net/usb/ax88179_178a.c | 4 ++++ drivers/net/usb/gl620a.c | 4 ++++ drivers/net/usb/mcs7830.c | 5 +++-- drivers/net/usb/net1080.c | 4 ++++ drivers/net/usb/qmi_wwan.c | 8 ++++---- drivers/net/usb/rndis_host.c | 4 ++++ drivers/net/usb/smsc75xx.c | 4 ++++ drivers/net/usb/smsc95xx.c | 4 ++++ drivers/net/usb/sr9800.c | 4 ++++ drivers/net/usb/usbnet.c | 25 ++++++++++--------------- 10 files changed, 45 insertions(+), 21 deletions(-) diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c index d6f64dad05bc..955df81a4358 100644 --- a/drivers/net/usb/ax88179_178a.c +++ b/drivers/net/usb/ax88179_178a.c @@ -1118,6 +1118,10 @@ static int ax88179_rx_fixup(struct usbnet *dev, struct sk_buff *skb) u16 hdr_off; u32 *pkt_hdr; + /* This check is no longer done by usbnet */ + if (skb->len < dev->net->hard_header_len) + return 0; + skb_trim(skb, skb->len - 4); memcpy(&rx_hdr, skb_tail_pointer(skb), 4); le32_to_cpus(&rx_hdr); diff --git a/drivers/net/usb/gl620a.c b/drivers/net/usb/gl620a.c index e4a8a93fbaf7..1cc24e6f23e2 100644 --- a/drivers/net/usb/gl620a.c +++ b/drivers/net/usb/gl620a.c @@ -84,6 +84,10 @@ static int genelink_rx_fixup(struct usbnet *dev, struct sk_buff *skb) u32 size; u32 count; + /* This check is no longer done by usbnet */ + if (skb->len < dev->net->hard_header_len) + return 0; + header = (struct gl_header *) skb->data; // get the packet count of the received skb diff --git a/drivers/net/usb/mcs7830.c b/drivers/net/usb/mcs7830.c index a305a7b2dae6..82d844a8ebd0 100644 --- a/drivers/net/usb/mcs7830.c +++ b/drivers/net/usb/mcs7830.c @@ -526,8 +526,9 @@ static int mcs7830_rx_fixup(struct usbnet *dev, struct sk_buff *skb) { u8 status; - if (skb->len == 0) { - dev_err(&dev->udev->dev, "unexpected empty rx frame\n"); + /* This check is no longer done by usbnet */ + if (skb->len < dev->net->hard_header_len) { + dev_err(&dev->udev->dev, "unexpected tiny rx frame\n"); return 0; } diff --git a/drivers/net/usb/net1080.c b/drivers/net/usb/net1080.c index 0a85d9227775..4cbdb1307f3e 100644 --- a/drivers/net/usb/net1080.c +++ b/drivers/net/usb/net1080.c @@ -364,6 +364,10 @@ static int net1080_rx_fixup(struct usbnet *dev, struct sk_buff *skb) struct nc_trailer *trailer; u16 hdr_len, packet_len; + /* This check is no longer done by usbnet */ + if (skb->len < dev->net->hard_header_len) + return 0; + if (!(skb->len & 0x01)) { netdev_dbg(dev->net, "rx framesize %d range %d..%d mtu %d\n", skb->len, dev->net->hard_header_len, dev->hard_mtu, diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 1eddd43b2f32..313cb6cd4848 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -80,10 +80,10 @@ static int qmi_wwan_rx_fixup(struct usbnet *dev, struct sk_buff *skb) { __be16 proto; - /* usbnet rx_complete guarantees that skb->len is at least - * hard_header_len, so we can inspect the dest address without - * checking skb->len - */ + /* This check is no longer done by usbnet */ + if (skb->len < dev->net->hard_header_len) + return 0; + switch (skb->data[0] & 0xf0) { case 0x40: proto = htons(ETH_P_IP); diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c index a48bc0f20c1a..524a47a28120 100644 --- a/drivers/net/usb/rndis_host.c +++ b/drivers/net/usb/rndis_host.c @@ -492,6 +492,10 @@ EXPORT_SYMBOL_GPL(rndis_unbind); */ int rndis_rx_fixup(struct usbnet *dev, struct sk_buff *skb) { + /* This check is no longer done by usbnet */ + if (skb->len < dev->net->hard_header_len) + return 0; + /* peripheral may have batched packets to us... */ while (likely(skb->len)) { struct rndis_data_hdr *hdr = (void *)skb->data; diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c index f17b9e02dd34..d9e7892262fa 100644 --- a/drivers/net/usb/smsc75xx.c +++ b/drivers/net/usb/smsc75xx.c @@ -2106,6 +2106,10 @@ static void smsc75xx_rx_csum_offload(struct usbnet *dev, struct sk_buff *skb, static int smsc75xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) { + /* This check is no longer done by usbnet */ + if (skb->len < dev->net->hard_header_len) + return 0; + while (skb->len > 0) { u32 rx_cmd_a, rx_cmd_b, align_count, size; struct sk_buff *ax_skb; diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c index 8dd54a0f7b29..424db65e4396 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c @@ -1723,6 +1723,10 @@ static void smsc95xx_rx_csum_offload(struct sk_buff *skb) static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) { + /* This check is no longer done by usbnet */ + if (skb->len < dev->net->hard_header_len) + return 0; + while (skb->len > 0) { u32 header, align_count; struct sk_buff *ax_skb; diff --git a/drivers/net/usb/sr9800.c b/drivers/net/usb/sr9800.c index 801710883727..b94a0fbb8b3b 100644 --- a/drivers/net/usb/sr9800.c +++ b/drivers/net/usb/sr9800.c @@ -63,6 +63,10 @@ static int sr_rx_fixup(struct usbnet *dev, struct sk_buff *skb) { int offset = 0; + /* This check is no longer done by usbnet */ + if (skb->len < dev->net->hard_header_len) + return 0; + while (offset + sizeof(u32) < skb->len) { struct sk_buff *sr_skb; u16 size; diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 4671da755e7b..dd10d5817d2a 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -542,17 +542,19 @@ static inline void rx_process (struct usbnet *dev, struct sk_buff *skb) } // else network stack removes extra byte if we forced a short packet - if (skb->len) { - /* all data was already cloned from skb inside the driver */ - if (dev->driver_info->flags & FLAG_MULTI_PACKET) - dev_kfree_skb_any(skb); - else - usbnet_skb_return(dev, skb); + /* all data was already cloned from skb inside the driver */ + if (dev->driver_info->flags & FLAG_MULTI_PACKET) + goto done; + + if (skb->len < ETH_HLEN) { + dev->net->stats.rx_errors++; + dev->net->stats.rx_length_errors++; + netif_dbg(dev, rx_err, dev->net, "rx length %d\n", skb->len); + } else { + usbnet_skb_return(dev, skb); return; } - netif_dbg(dev, rx_err, dev->net, "drop\n"); - dev->net->stats.rx_errors++; done: skb_queue_tail(&dev->done, skb); } @@ -574,13 +576,6 @@ static void rx_complete (struct urb *urb) switch (urb_status) { /* success */ case 0: - if (skb->len < dev->net->hard_header_len) { - state = rx_cleanup; - dev->net->stats.rx_errors++; - dev->net->stats.rx_length_errors++; - netif_dbg(dev, rx_err, dev->net, - "rx length %d\n", skb->len); - } break; /* stalls need manual reset. this is rare ... except that -- cgit v1.2.3 From 163c8ff30dbe473abfbb24a7eac5536c87f3baa9 Mon Sep 17 00:00:00 2001 From: Jiri Bohac Date: Fri, 14 Feb 2014 18:13:50 +0100 Subject: bonding: 802.3ad: make aggregator_identifier bond-private aggregator_identifier is used to assign unique aggregator identifiers to aggregators of a bond during device enslaving. aggregator_identifier is currently a global variable that is zeroed in bond_3ad_initialize(). This sequence will lead to duplicate aggregator identifiers for eth1 and eth3: create bond0 change bond0 mode to 802.3ad enslave eth0 to bond0 //eth0 gets agg id 1 enslave eth1 to bond0 //eth1 gets agg id 2 create bond1 change bond1 mode to 802.3ad enslave eth2 to bond1 //aggregator_identifier is reset to 0 //eth2 gets agg id 1 enslave eth3 to bond0 //eth3 gets agg id 2 Fix this by making aggregator_identifier private to the bond. Signed-off-by: Jiri Bohac Acked-by: Veaceslav Falico Signed-off-by: David S. Miller --- drivers/net/bonding/bond_3ad.c | 6 ++---- drivers/net/bonding/bond_3ad.h | 1 + 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index cce1f1bf90b4..6d20fbde8d43 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@ -1796,8 +1796,6 @@ void bond_3ad_initiate_agg_selection(struct bonding *bond, int timeout) BOND_AD_INFO(bond).agg_select_timer = timeout; } -static u16 aggregator_identifier; - /** * bond_3ad_initialize - initialize a bond's 802.3ad parameters and structures * @bond: bonding struct to work on @@ -1811,7 +1809,7 @@ void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution) if (!MAC_ADDRESS_EQUAL(&(BOND_AD_INFO(bond).system.sys_mac_addr), bond->dev->dev_addr)) { - aggregator_identifier = 0; + BOND_AD_INFO(bond).aggregator_identifier = 0; BOND_AD_INFO(bond).system.sys_priority = 0xFFFF; BOND_AD_INFO(bond).system.sys_mac_addr = *((struct mac_addr *)bond->dev->dev_addr); @@ -1880,7 +1878,7 @@ void bond_3ad_bind_slave(struct slave *slave) ad_initialize_agg(aggregator); aggregator->aggregator_mac_address = *((struct mac_addr *)bond->dev->dev_addr); - aggregator->aggregator_identifier = (++aggregator_identifier); + aggregator->aggregator_identifier = ++BOND_AD_INFO(bond).aggregator_identifier; aggregator->slave = slave; aggregator->is_active = 0; aggregator->num_of_ports = 0; diff --git a/drivers/net/bonding/bond_3ad.h b/drivers/net/bonding/bond_3ad.h index 13dc9d3c5e34..f4dd9592ac62 100644 --- a/drivers/net/bonding/bond_3ad.h +++ b/drivers/net/bonding/bond_3ad.h @@ -253,6 +253,7 @@ struct ad_system { struct ad_bond_info { struct ad_system system; /* 802.3ad system structure */ u32 agg_select_timer; // Timer to select aggregator after all adapter's hand shakes + u16 aggregator_identifier; }; struct ad_slave_info { -- cgit v1.2.3 From a4b1b5877b514b276f0f31efe02388a9c2836728 Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Thu, 19 Dec 2013 12:09:32 +0100 Subject: HID: Bluetooth: hidp: make sure input buffers are big enough HID core expects the input buffers to be at least of size 4096 (HID_MAX_BUFFER_SIZE). Other sizes will result in buffer-overflows if an input-report is smaller than advertised. We could, like i2c, compute the biggest report-size instead of using HID_MAX_BUFFER_SIZE, but this will blow up if report-descriptors are changed after ->start() has been called. So lets be safe and just use the biggest buffer we have. Note that this adds an additional copy to the HIDP input path. If there is a way to make sure the skb-buf is big enough, we should use that instead. The best way would be to make hid-core honor the @size argument, though, that sounds easier than it is. So lets just fix the buffer-overflows for now and afterwards look for a faster way for all transport drivers. Signed-off-by: David Herrmann Signed-off-by: Jiri Kosina --- net/bluetooth/hidp/core.c | 16 ++++++++++++++-- net/bluetooth/hidp/hidp.h | 4 ++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index 292e619db896..d9fb93451442 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c @@ -430,6 +430,16 @@ static void hidp_del_timer(struct hidp_session *session) del_timer(&session->timer); } +static void hidp_process_report(struct hidp_session *session, + int type, const u8 *data, int len, int intr) +{ + if (len > HID_MAX_BUFFER_SIZE) + len = HID_MAX_BUFFER_SIZE; + + memcpy(session->input_buf, data, len); + hid_input_report(session->hid, type, session->input_buf, len, intr); +} + static void hidp_process_handshake(struct hidp_session *session, unsigned char param) { @@ -502,7 +512,8 @@ static int hidp_process_data(struct hidp_session *session, struct sk_buff *skb, hidp_input_report(session, skb); if (session->hid) - hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 0); + hidp_process_report(session, HID_INPUT_REPORT, + skb->data, skb->len, 0); break; case HIDP_DATA_RTYPE_OTHER: @@ -584,7 +595,8 @@ static void hidp_recv_intr_frame(struct hidp_session *session, hidp_input_report(session, skb); if (session->hid) { - hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 1); + hidp_process_report(session, HID_INPUT_REPORT, + skb->data, skb->len, 1); BT_DBG("report len %d", skb->len); } } else { diff --git a/net/bluetooth/hidp/hidp.h b/net/bluetooth/hidp/hidp.h index ab5241400cf7..8798492a6e99 100644 --- a/net/bluetooth/hidp/hidp.h +++ b/net/bluetooth/hidp/hidp.h @@ -24,6 +24,7 @@ #define __HIDP_H #include +#include #include #include #include @@ -179,6 +180,9 @@ struct hidp_session { /* Used in hidp_output_raw_report() */ int output_report_success; /* boolean */ + + /* temporary input buffer */ + u8 input_buf[HID_MAX_BUFFER_SIZE]; }; /* HIDP init defines */ -- cgit v1.2.3 From 3ccfd0a8d7062a5590923578eea829ee582beba8 Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Thu, 19 Dec 2013 12:32:24 +0100 Subject: HID: hyperv: make sure input buffer is big enough We need at least HID_MAX_BUFFER_SIZE (4096) bytes as input buffer. HID core depends on this as it requires every input report to be at least as big as advertised. Signed-off-by: David Herrmann Signed-off-by: K. Y. Srinivasan Signed-off-by: Jiri Kosina --- drivers/hid/hid-hyperv.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/hid/hid-hyperv.c b/drivers/hid/hid-hyperv.c index 8fae6d1414cc..c24908f14934 100644 --- a/drivers/hid/hid-hyperv.c +++ b/drivers/hid/hid-hyperv.c @@ -157,6 +157,7 @@ struct mousevsc_dev { u32 report_desc_size; struct hv_input_dev_info hid_dev_info; struct hid_device *hid_device; + u8 input_buf[HID_MAX_BUFFER_SIZE]; }; @@ -256,6 +257,7 @@ static void mousevsc_on_receive(struct hv_device *device, struct synthhid_msg *hid_msg; struct mousevsc_dev *input_dev = hv_get_drvdata(device); struct synthhid_input_report *input_report; + size_t len; pipe_msg = (struct pipe_prt_msg *)((unsigned long)packet + (packet->offset8 << 3)); @@ -300,9 +302,12 @@ static void mousevsc_on_receive(struct hv_device *device, (struct synthhid_input_report *)pipe_msg->data; if (!input_dev->init_complete) break; - hid_input_report(input_dev->hid_device, - HID_INPUT_REPORT, input_report->buffer, - input_report->header.size, 1); + + len = min(input_report->header.size, + (u32)sizeof(input_dev->input_buf)); + memcpy(input_dev->input_buf, input_report->buffer, len); + hid_input_report(input_dev->hid_device, HID_INPUT_REPORT, + input_dev->input_buf, len, 1); break; default: pr_err("unsupported hid msg type - type %d len %d", -- cgit v1.2.3 From e4178d809fdaee32a56833fff1f5056c99e90a1a Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 17 Feb 2014 12:24:45 -0800 Subject: printk: fix syslog() overflowing user buffer This is not a buffer overflow in the traditional sense: we don't overflow any *kernel* buffers, but we do mis-count the amount of data we copy back to user space for the SYSLOG_ACTION_READ_ALL case. In particular, if the user buffer is too small to hold everything, and *if* there is a continuation line at just the right place, we can end up giving the user more data than he asked for. The reason is that we first count up the number of bytes all the log records contains, then we walk the records again until we've skipped the records at the beginning that won't fit, and then we walk the rest of the records and copy them to the user space buffer. And in between that "skip the initial records that won't fit" and the "copy the records that *will* fit to user space", we reset the 'prev' variable that contained the record information for the last record not copied. That meant that when we started copying to user space, we now had a different character count than what we had originally calculated in the first record walk-through. The fix is to simply not clear the 'prev' flags value (in both cases where we had the same logic: syslog_print_all and kmsg_dump_get_buffer: the latter is used for pstore-like dumping) Reported-and-tested-by: Debabrata Banerjee Acked-by: Kay Sievers Cc: Greg Kroah-Hartman Cc: Jeff Mahoney Signed-off-by: Linus Torvalds --- kernel/printk/printk.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index b1d255f04135..4dae9cbe9259 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -1076,7 +1076,6 @@ static int syslog_print_all(char __user *buf, int size, bool clear) next_seq = log_next_seq; len = 0; - prev = 0; while (len >= 0 && seq < next_seq) { struct printk_log *msg = log_from_idx(idx); int textlen; @@ -2788,7 +2787,6 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog, next_idx = idx; l = 0; - prev = 0; while (seq < dumper->next_seq) { struct printk_log *msg = log_from_idx(idx); -- cgit v1.2.3 From fbc0b970ddfab4b35dad27ebaae712af680bdc7e Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Tue, 11 Feb 2014 13:01:19 +0800 Subject: ceph: properly handle XATTR_CREATE and XATTR_REPLACE return -EEXIST if XATTR_CREATE is set and xattr alread exists. return -ENODATA if XATTR_REPLACE is set but xattr does not exist. Signed-off-by: Yan, Zheng --- fs/ceph/xattr.c | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c index 898b6565ad3e..28f9793b9167 100644 --- a/fs/ceph/xattr.c +++ b/fs/ceph/xattr.c @@ -319,8 +319,7 @@ static struct ceph_vxattr *ceph_match_vxattr(struct inode *inode, static int __set_xattr(struct ceph_inode_info *ci, const char *name, int name_len, const char *val, int val_len, - int dirty, - int should_free_name, int should_free_val, + int flags, int update_xattr, struct ceph_inode_xattr **newxattr) { struct rb_node **p; @@ -349,12 +348,25 @@ static int __set_xattr(struct ceph_inode_info *ci, xattr = NULL; } + if (update_xattr) { + int err = 0; + if (xattr && (flags & XATTR_CREATE)) + err = -EEXIST; + else if (!xattr && (flags & XATTR_REPLACE)) + err = -ENODATA; + if (err) { + kfree(name); + kfree(val); + return err; + } + } + if (!xattr) { new = 1; xattr = *newxattr; xattr->name = name; xattr->name_len = name_len; - xattr->should_free_name = should_free_name; + xattr->should_free_name = update_xattr; ci->i_xattrs.count++; dout("__set_xattr count=%d\n", ci->i_xattrs.count); @@ -364,7 +376,7 @@ static int __set_xattr(struct ceph_inode_info *ci, if (xattr->should_free_val) kfree((void *)xattr->val); - if (should_free_name) { + if (update_xattr) { kfree((void *)name); name = xattr->name; } @@ -379,8 +391,8 @@ static int __set_xattr(struct ceph_inode_info *ci, xattr->val = ""; xattr->val_len = val_len; - xattr->dirty = dirty; - xattr->should_free_val = (val && should_free_val); + xattr->dirty = update_xattr; + xattr->should_free_val = (val && update_xattr); if (new) { rb_link_node(&xattr->node, parent, p); @@ -588,7 +600,7 @@ start: p += len; err = __set_xattr(ci, name, namelen, val, len, - 0, 0, 0, &xattrs[numattr]); + 0, 0, &xattrs[numattr]); if (err < 0) goto bad; @@ -892,7 +904,7 @@ int __ceph_setxattr(struct dentry *dentry, const char *name, struct ceph_inode_info *ci = ceph_inode(inode); int issued; int err; - int dirty; + int dirty = 0; int name_len = strlen(name); int val_len = size; char *newname = NULL; @@ -954,11 +966,13 @@ retry: } err = __set_xattr(ci, newname, name_len, newval, - val_len, 1, 1, 1, &xattr); + val_len, flags, 1, &xattr); - dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL); - ci->i_xattrs.dirty = true; - inode->i_ctime = CURRENT_TIME; + if (!err) { + dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL); + ci->i_xattrs.dirty = true; + inode->i_ctime = CURRENT_TIME; + } spin_unlock(&ci->i_ceph_lock); if (dirty) -- cgit v1.2.3 From bcdfeb2eb4e42b811950b9cd226109291051732a Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Tue, 11 Feb 2014 13:04:19 +0800 Subject: ceph: remove xattr when null value is given to setxattr() For the setxattr request, introduce a new flag CEPH_XATTR_REMOVE to distinguish null value case from the zero-length value case. Signed-off-by: Yan, Zheng --- fs/ceph/xattr.c | 16 ++++++++++++++-- include/linux/ceph/ceph_fs.h | 5 +++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c index 28f9793b9167..231c02b16c0c 100644 --- a/fs/ceph/xattr.c +++ b/fs/ceph/xattr.c @@ -12,6 +12,9 @@ #define XATTR_CEPH_PREFIX "ceph." #define XATTR_CEPH_PREFIX_LEN (sizeof (XATTR_CEPH_PREFIX) - 1) +static int __remove_xattr(struct ceph_inode_info *ci, + struct ceph_inode_xattr *xattr); + /* * List of handlers for synthetic system.* attributes. Other * attributes are handled directly. @@ -359,6 +362,12 @@ static int __set_xattr(struct ceph_inode_info *ci, kfree(val); return err; } + if (update_xattr < 0) { + if (xattr) + __remove_xattr(ci, xattr); + kfree(name); + return 0; + } } if (!xattr) { @@ -862,6 +871,9 @@ static int ceph_sync_setxattr(struct dentry *dentry, const char *name, dout("setxattr value=%.*s\n", (int)size, value); + if (!value) + flags |= CEPH_XATTR_REMOVE; + /* do request */ req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_SETXATTR, USE_AUTH_MDS); @@ -965,8 +977,8 @@ retry: goto retry; } - err = __set_xattr(ci, newname, name_len, newval, - val_len, flags, 1, &xattr); + err = __set_xattr(ci, newname, name_len, newval, val_len, + flags, value ? 1 : -1, &xattr); if (!err) { dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL); diff --git a/include/linux/ceph/ceph_fs.h b/include/linux/ceph/ceph_fs.h index 2623cffc73a1..25bfb0eff772 100644 --- a/include/linux/ceph/ceph_fs.h +++ b/include/linux/ceph/ceph_fs.h @@ -373,8 +373,9 @@ extern const char *ceph_mds_op_name(int op); /* * Ceph setxattr request flags. */ -#define CEPH_XATTR_CREATE 1 -#define CEPH_XATTR_REPLACE 2 +#define CEPH_XATTR_CREATE (1 << 0) +#define CEPH_XATTR_REPLACE (1 << 1) +#define CEPH_XATTR_REMOVE (1 << 31) union ceph_mds_request_args { struct { -- cgit v1.2.3 From 524186ace6c4dcc83975b858622a66888b018fd0 Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Tue, 11 Feb 2014 13:23:09 +0800 Subject: ceph: fix ceph_removexattr() Signed-off-by: Yan, Zheng --- fs/ceph/xattr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c index 231c02b16c0c..a55ec37378c6 100644 --- a/fs/ceph/xattr.c +++ b/fs/ceph/xattr.c @@ -463,7 +463,7 @@ static int __remove_xattr(struct ceph_inode_info *ci, struct ceph_inode_xattr *xattr) { if (!xattr) - return -EOPNOTSUPP; + return -ENODATA; rb_erase(&xattr->node, &ci->i_xattrs.index); -- cgit v1.2.3 From 7a92d64760541e66bf5d1131f029b82773ce3922 Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Tue, 11 Feb 2014 13:08:51 +0800 Subject: ceph: fix ceph_set_acl() If acl is equivalent to file mode permission bits, ceph_set_acl() needs to remove any existing acl xattr. Use __ceph_setxattr() to handle both setting and removing acl xattr cases, it doesn't return -ENODATA when there is no acl xattr. Signed-off-by: Yan, Zheng --- fs/ceph/acl.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/fs/ceph/acl.c b/fs/ceph/acl.c index 4c2d452c4bfc..accc9f28bc10 100644 --- a/fs/ceph/acl.c +++ b/fs/ceph/acl.c @@ -160,11 +160,7 @@ int ceph_set_acl(struct inode *inode, struct posix_acl *acl, int type) goto out_dput; } - if (value) - ret = __ceph_setxattr(dentry, name, value, size, 0); - else - ret = __ceph_removexattr(dentry, name); - + ret = __ceph_setxattr(dentry, name, value, size, 0); if (ret) { if (new_mode != old_mode) { newattrs.ia_mode = old_mode; -- cgit v1.2.3 From b20a95a0dd47c56c5d20e1c9e260293d0b87abe0 Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Tue, 11 Feb 2014 12:55:05 +0800 Subject: ceph: add missing init_acl() for mkdir() and atomic_open() Signed-off-by: Yan, Zheng --- fs/ceph/dir.c | 13 ++++++++----- fs/ceph/file.c | 1 + 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index 6da4df84ba30..2e3b30dcfc94 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c @@ -695,9 +695,8 @@ static int ceph_mknod(struct inode *dir, struct dentry *dentry, ceph_mdsc_put_request(req); if (!err) - err = ceph_init_acl(dentry, dentry->d_inode, dir); - - if (err) + ceph_init_acl(dentry, dentry->d_inode, dir); + else d_drop(dentry); return err; } @@ -735,7 +734,9 @@ static int ceph_symlink(struct inode *dir, struct dentry *dentry, if (!err && !req->r_reply_info.head->is_dentry) err = ceph_handle_notrace_create(dir, dentry); ceph_mdsc_put_request(req); - if (err) + if (!err) + ceph_init_acl(dentry, dentry->d_inode, dir); + else d_drop(dentry); return err; } @@ -776,7 +777,9 @@ static int ceph_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) err = ceph_handle_notrace_create(dir, dentry); ceph_mdsc_put_request(req); out: - if (err < 0) + if (!err) + ceph_init_acl(dentry, dentry->d_inode, dir); + else d_drop(dentry); return err; } diff --git a/fs/ceph/file.c b/fs/ceph/file.c index dfd2ce3419f8..09c7afe32e49 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -286,6 +286,7 @@ int ceph_atomic_open(struct inode *dir, struct dentry *dentry, } else { dout("atomic_open finish_open on dn %p\n", dn); if (req->r_op == CEPH_MDS_OP_CREATE && req->r_reply_info.has_create_ino) { + ceph_init_acl(dentry, dentry->d_inode, dir); *opened |= FILE_CREATED; } err = finish_open(file, dentry, ceph_open, opened); -- cgit v1.2.3 From c969d9bf91e1868d823351993216cd64dfab6a4c Mon Sep 17 00:00:00 2001 From: Guangliang Zhao Date: Sun, 16 Feb 2014 08:35:52 -0800 Subject: ceph: make ceph_forget_all_cached_acls() static inline Signed-off-by: Guangliang Zhao Reviewed-by: Alex Elder Signed-off-by: Sage Weil --- fs/ceph/acl.c | 5 ----- fs/ceph/super.h | 7 ++++++- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/fs/ceph/acl.c b/fs/ceph/acl.c index accc9f28bc10..21887d63dad5 100644 --- a/fs/ceph/acl.c +++ b/fs/ceph/acl.c @@ -54,11 +54,6 @@ static inline struct posix_acl *ceph_get_cached_acl(struct inode *inode, return acl; } -void ceph_forget_all_cached_acls(struct inode *inode) -{ - forget_all_cached_acls(inode); -} - struct posix_acl *ceph_get_acl(struct inode *inode, int type) { int size; diff --git a/fs/ceph/super.h b/fs/ceph/super.h index 19793b56d0a7..d8801a95b685 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h @@ -13,6 +13,7 @@ #include #include #include +#include #include @@ -743,7 +744,11 @@ extern const struct xattr_handler *ceph_xattr_handlers[]; struct posix_acl *ceph_get_acl(struct inode *, int); int ceph_set_acl(struct inode *inode, struct posix_acl *acl, int type); int ceph_init_acl(struct dentry *, struct inode *, struct inode *); -void ceph_forget_all_cached_acls(struct inode *inode); + +static inline void ceph_forget_all_cached_acls(struct inode *inode) +{ + forget_all_cached_acls(inode); +} #else -- cgit v1.2.3 From 45195e42c78ea91135108207dbcaf75e5556a309 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Sun, 16 Feb 2014 10:05:29 -0800 Subject: ceph: add acl, noacl options for cephfs mount Make the 'acl' option dependent on having ACL support compiled in. Make the 'noacl' option work even without it so that one can always ask it to be off and not error out on mount when it is not supported. Signed-off-by: Guangliang Zhao Signed-off-by: Sage Weil --- fs/ceph/super.c | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/fs/ceph/super.c b/fs/ceph/super.c index 2df963f1cf5a..10a4ccbf38da 100644 --- a/fs/ceph/super.c +++ b/fs/ceph/super.c @@ -144,7 +144,11 @@ enum { Opt_ino32, Opt_noino32, Opt_fscache, - Opt_nofscache + Opt_nofscache, +#ifdef CONFIG_CEPH_FS_POSIX_ACL + Opt_acl, +#endif + Opt_noacl }; static match_table_t fsopt_tokens = { @@ -172,6 +176,10 @@ static match_table_t fsopt_tokens = { {Opt_noino32, "noino32"}, {Opt_fscache, "fsc"}, {Opt_nofscache, "nofsc"}, +#ifdef CONFIG_CEPH_FS_POSIX_ACL + {Opt_acl, "acl"}, +#endif + {Opt_noacl, "noacl"}, {-1, NULL} }; @@ -271,6 +279,14 @@ static int parse_fsopt_token(char *c, void *private) case Opt_nofscache: fsopt->flags &= ~CEPH_MOUNT_OPT_FSCACHE; break; +#ifdef CONFIG_CEPH_FS_POSIX_ACL + case Opt_acl: + fsopt->sb_flags |= MS_POSIXACL; + break; +#endif + case Opt_noacl: + fsopt->sb_flags &= ~MS_POSIXACL; + break; default: BUG_ON(token); } @@ -438,6 +454,13 @@ static int ceph_show_options(struct seq_file *m, struct dentry *root) else seq_puts(m, ",nofsc"); +#ifdef CONFIG_CEPH_FS_POSIX_ACL + if (fsopt->sb_flags & MS_POSIXACL) + seq_puts(m, ",acl"); + else + seq_puts(m, ",noacl"); +#endif + if (fsopt->wsize) seq_printf(m, ",wsize=%d", fsopt->wsize); if (fsopt->rsize != CEPH_RSIZE_DEFAULT) @@ -819,9 +842,6 @@ static int ceph_set_super(struct super_block *s, void *data) s->s_flags = fsc->mount_options->sb_flags; s->s_maxbytes = 1ULL << 40; /* temp value until we get mdsmap */ -#ifdef CONFIG_CEPH_FS_POSIX_ACL - s->s_flags |= MS_POSIXACL; -#endif s->s_xattr = ceph_xattr_handlers; s->s_fs_info = fsc; @@ -911,6 +931,10 @@ static struct dentry *ceph_mount(struct file_system_type *fs_type, struct ceph_options *opt = NULL; dout("ceph_mount\n"); + +#ifdef CONFIG_CEPH_FS_POSIX_ACL + flags |= MS_POSIXACL; +#endif err = parse_mount_options(&fsopt, &opt, flags, data, dev_name, &path); if (err < 0) { res = ERR_PTR(err); -- cgit v1.2.3 From 4d5f5df673ee673851986b5a492a9752fbb39dc5 Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Thu, 13 Feb 2014 19:40:26 +0800 Subject: ceph: fix __dcache_readdir() If directory is fragmented, readdir() read its dirfrags one by one. After reading all dirfrags, the corresponding dentries are sorted in (frag_t, off) order in the dcache. If dentries of a directory are all cached, __dcache_readdir() can use the cached dentries to satisfy readdir syscall. But when checking if a given dentry is after the position of readdir, __dcache_readdir() compares numerical value of frag_t directly. This is wrong, it should use ceph_frag_compare(). Signed-off-by: Yan, Zheng --- fs/ceph/dir.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index 2e3b30dcfc94..45eda6d7a40c 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c @@ -100,6 +100,14 @@ static unsigned fpos_off(loff_t p) return p & 0xffffffff; } +static int fpos_cmp(loff_t l, loff_t r) +{ + int v = ceph_frag_compare(fpos_frag(l), fpos_frag(r)); + if (v) + return v; + return (int)(fpos_off(l) - fpos_off(r)); +} + /* * When possible, we try to satisfy a readdir by peeking at the * dcache. We make this work by carefully ordering dentries on @@ -156,7 +164,7 @@ more: if (!d_unhashed(dentry) && dentry->d_inode && ceph_snap(dentry->d_inode) != CEPH_SNAPDIR && ceph_ino(dentry->d_inode) != CEPH_INO_CEPH && - ctx->pos <= di->offset) + fpos_cmp(ctx->pos, di->offset) <= 0) break; dout(" skipping %p %.*s at %llu (%llu)%s%s\n", dentry, dentry->d_name.len, dentry->d_name.name, di->offset, -- cgit v1.2.3 From 3eca5299532ea9d6ab63b03e7aaac9071d5eed29 Mon Sep 17 00:00:00 2001 From: Tommie Gannert Date: Mon, 17 Feb 2014 20:46:04 +0000 Subject: irtty-sir.c: Do not set_termios() on irtty_close() Issuing set_termios() from irtty_close() causes kernel Oops for unplugged usb-serial devices. Since no other tty_ldisc calls set_termios() on close and no tty driver seem to check if tty->device_data is NULL or not on entry to set_termios(), the only solution I can come up with is to remove the irtty_stop_receiver() call, which only updates termios. Signed-off-by: Tommie Gannert Signed-off-by: David S. Miller --- drivers/net/irda/irtty-sir.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c index 177441afeb96..24b6dddd7f2f 100644 --- a/drivers/net/irda/irtty-sir.c +++ b/drivers/net/irda/irtty-sir.c @@ -522,7 +522,6 @@ static void irtty_close(struct tty_struct *tty) sirdev_put_instance(priv->dev); /* Stop tty */ - irtty_stop_receiver(tty, TRUE); clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); if (tty->ops->stop) tty->ops->stop(tty); -- cgit v1.2.3 From 416e2abd925d0f41dc877d1fe01489d79bdecf4c Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 17 Feb 2014 16:21:24 -0500 Subject: reiserfs: fix utterly brain-damaged indentation. This has been this way for years, and every time I stumble across it I lose my lunch. After coming across it for the nth time in the Coverity results, I had to overcome the bystander effect and do something about it. This ignores the 79 column limit in favor of making it look like C instead of gibberish. The correct thing to do here would be to lose some of the indentation by breaking this function up into several smaller ones. I might do that at some point if I have the stomach to look at this again. (Also some of those overlong ternary operations would likely be more readable as regular if's) Signed-off-by: Dave Jones Signed-off-by: Linus Torvalds --- fs/reiserfs/do_balan.c | 895 +++++++++++-------------------------------------- 1 file changed, 195 insertions(+), 700 deletions(-) diff --git a/fs/reiserfs/do_balan.c b/fs/reiserfs/do_balan.c index 2b7882b508db..9a3c68cf6026 100644 --- a/fs/reiserfs/do_balan.c +++ b/fs/reiserfs/do_balan.c @@ -324,23 +324,17 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h switch (flag) { case M_INSERT: /* insert item into L[0] */ - if (item_pos == tb->lnum[0] - 1 - && tb->lbytes != -1) { + if (item_pos == tb->lnum[0] - 1 && tb->lbytes != -1) { /* part of new item falls into L[0] */ int new_item_len; int version; - ret_val = - leaf_shift_left(tb, tb->lnum[0] - 1, - -1); + ret_val = leaf_shift_left(tb, tb->lnum[0] - 1, -1); /* Calculate item length to insert to S[0] */ - new_item_len = - ih_item_len(ih) - tb->lbytes; + new_item_len = ih_item_len(ih) - tb->lbytes; /* Calculate and check item length to insert to L[0] */ - put_ih_item_len(ih, - ih_item_len(ih) - - new_item_len); + put_ih_item_len(ih, ih_item_len(ih) - new_item_len); RFALSE(ih_item_len(ih) <= 0, "PAP-12080: there is nothing to insert into L[0]: ih_item_len=%d", @@ -349,30 +343,18 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h /* Insert new item into L[0] */ buffer_info_init_left(tb, &bi); leaf_insert_into_buf(&bi, - n + item_pos - - ret_val, ih, body, - zeros_num > - ih_item_len(ih) ? - ih_item_len(ih) : - zeros_num); + n + item_pos - ret_val, ih, body, + zeros_num > ih_item_len(ih) ? ih_item_len(ih) : zeros_num); version = ih_version(ih); /* Calculate key component, item length and body to insert into S[0] */ - set_le_ih_k_offset(ih, - le_ih_k_offset(ih) + - (tb-> - lbytes << - (is_indirect_le_ih - (ih) ? tb->tb_sb-> - s_blocksize_bits - - UNFM_P_SHIFT : - 0))); + set_le_ih_k_offset(ih, le_ih_k_offset(ih) + + (tb-> lbytes << (is_indirect_le_ih(ih) ? tb->tb_sb-> s_blocksize_bits - UNFM_P_SHIFT : 0))); put_ih_item_len(ih, new_item_len); if (tb->lbytes > zeros_num) { - body += - (tb->lbytes - zeros_num); + body += (tb->lbytes - zeros_num); zeros_num = 0; } else zeros_num -= tb->lbytes; @@ -383,15 +365,10 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h } else { /* new item in whole falls into L[0] */ /* Shift lnum[0]-1 items to L[0] */ - ret_val = - leaf_shift_left(tb, tb->lnum[0] - 1, - tb->lbytes); + ret_val = leaf_shift_left(tb, tb->lnum[0] - 1, tb->lbytes); /* Insert new item into L[0] */ buffer_info_init_left(tb, &bi); - leaf_insert_into_buf(&bi, - n + item_pos - - ret_val, ih, body, - zeros_num); + leaf_insert_into_buf(&bi, n + item_pos - ret_val, ih, body, zeros_num); tb->insert_size[0] = 0; zeros_num = 0; } @@ -399,264 +376,117 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h case M_PASTE: /* append item in L[0] */ - if (item_pos == tb->lnum[0] - 1 - && tb->lbytes != -1) { + if (item_pos == tb->lnum[0] - 1 && tb->lbytes != -1) { /* we must shift the part of the appended item */ - if (is_direntry_le_ih - (B_N_PITEM_HEAD(tbS0, item_pos))) { + if (is_direntry_le_ih(B_N_PITEM_HEAD(tbS0, item_pos))) { RFALSE(zeros_num, "PAP-12090: invalid parameter in case of a directory"); /* directory item */ if (tb->lbytes > pos_in_item) { /* new directory entry falls into L[0] */ - struct item_head - *pasted; - int l_pos_in_item = - pos_in_item; + struct item_head *pasted; + int l_pos_in_item = pos_in_item; /* Shift lnum[0] - 1 items in whole. Shift lbytes - 1 entries from given directory item */ - ret_val = - leaf_shift_left(tb, - tb-> - lnum - [0], - tb-> - lbytes - - - 1); - if (ret_val - && !item_pos) { - pasted = - B_N_PITEM_HEAD - (tb->L[0], - B_NR_ITEMS - (tb-> - L[0]) - - 1); - l_pos_in_item += - I_ENTRY_COUNT - (pasted) - - (tb-> - lbytes - - 1); + ret_val = leaf_shift_left(tb, tb->lnum[0], tb->lbytes-1); + if (ret_val && !item_pos) { + pasted = B_N_PITEM_HEAD(tb->L[0], B_NR_ITEMS(tb->L[0]) - 1); + l_pos_in_item += I_ENTRY_COUNT(pasted) - (tb->lbytes -1); } /* Append given directory entry to directory item */ buffer_info_init_left(tb, &bi); - leaf_paste_in_buffer - (&bi, - n + item_pos - - ret_val, - l_pos_in_item, - tb->insert_size[0], - body, zeros_num); + leaf_paste_in_buffer(&bi, n + item_pos - ret_val, l_pos_in_item, tb->insert_size[0], body, zeros_num); /* previous string prepared space for pasting new entry, following string pastes this entry */ /* when we have merge directory item, pos_in_item has been changed too */ /* paste new directory entry. 1 is entry number */ - leaf_paste_entries(&bi, - n + - item_pos - - - ret_val, - l_pos_in_item, - 1, - (struct - reiserfs_de_head - *) - body, - body - + - DEH_SIZE, - tb-> - insert_size - [0] - ); + leaf_paste_entries(&bi, n + item_pos - ret_val, l_pos_in_item, + 1, (struct reiserfs_de_head *) body, + body + DEH_SIZE, tb->insert_size[0]); tb->insert_size[0] = 0; } else { /* new directory item doesn't fall into L[0] */ /* Shift lnum[0]-1 items in whole. Shift lbytes directory entries from directory item number lnum[0] */ - leaf_shift_left(tb, - tb-> - lnum[0], - tb-> - lbytes); + leaf_shift_left(tb, tb->lnum[0], tb->lbytes); } /* Calculate new position to append in item body */ pos_in_item -= tb->lbytes; } else { /* regular object */ - RFALSE(tb->lbytes <= 0, - "PAP-12095: there is nothing to shift to L[0]. lbytes=%d", - tb->lbytes); - RFALSE(pos_in_item != - ih_item_len - (B_N_PITEM_HEAD - (tbS0, item_pos)), + RFALSE(tb->lbytes <= 0, "PAP-12095: there is nothing to shift to L[0]. lbytes=%d", tb->lbytes); + RFALSE(pos_in_item != ih_item_len(B_N_PITEM_HEAD(tbS0, item_pos)), "PAP-12100: incorrect position to paste: item_len=%d, pos_in_item=%d", - ih_item_len - (B_N_PITEM_HEAD - (tbS0, item_pos)), - pos_in_item); + ih_item_len(B_N_PITEM_HEAD(tbS0, item_pos)),pos_in_item); if (tb->lbytes >= pos_in_item) { /* appended item will be in L[0] in whole */ int l_n; /* this bytes number must be appended to the last item of L[h] */ - l_n = - tb->lbytes - - pos_in_item; + l_n = tb->lbytes - pos_in_item; /* Calculate new insert_size[0] */ - tb->insert_size[0] -= - l_n; + tb->insert_size[0] -= l_n; - RFALSE(tb-> - insert_size[0] <= - 0, + RFALSE(tb->insert_size[0] <= 0, "PAP-12105: there is nothing to paste into L[0]. insert_size=%d", - tb-> - insert_size[0]); - ret_val = - leaf_shift_left(tb, - tb-> - lnum - [0], - ih_item_len - (B_N_PITEM_HEAD - (tbS0, - item_pos))); + tb->insert_size[0]); + ret_val = leaf_shift_left(tb, tb->lnum[0], ih_item_len + (B_N_PITEM_HEAD(tbS0, item_pos))); /* Append to body of item in L[0] */ buffer_info_init_left(tb, &bi); leaf_paste_in_buffer - (&bi, - n + item_pos - - ret_val, - ih_item_len - (B_N_PITEM_HEAD - (tb->L[0], - n + item_pos - - ret_val)), l_n, - body, - zeros_num > - l_n ? l_n : - zeros_num); + (&bi, n + item_pos - ret_val, ih_item_len + (B_N_PITEM_HEAD(tb->L[0], n + item_pos - ret_val)), + l_n, body, + zeros_num > l_n ? l_n : zeros_num); /* 0-th item in S0 can be only of DIRECT type when l_n != 0 */ { int version; - int temp_l = - l_n; - - RFALSE - (ih_item_len - (B_N_PITEM_HEAD - (tbS0, - 0)), + int temp_l = l_n; + + RFALSE(ih_item_len(B_N_PITEM_HEAD(tbS0, 0)), "PAP-12106: item length must be 0"); - RFALSE - (comp_short_le_keys - (B_N_PKEY - (tbS0, 0), - B_N_PKEY - (tb->L[0], - n + - item_pos - - - ret_val)), + RFALSE(comp_short_le_keys(B_N_PKEY(tbS0, 0), B_N_PKEY + (tb->L[0], n + item_pos - ret_val)), "PAP-12107: items must be of the same file"); if (is_indirect_le_ih(B_N_PITEM_HEAD(tb->L[0], n + item_pos - ret_val))) { - temp_l = - l_n - << - (tb-> - tb_sb-> - s_blocksize_bits - - - UNFM_P_SHIFT); + temp_l = l_n << (tb->tb_sb-> s_blocksize_bits - UNFM_P_SHIFT); } /* update key of first item in S0 */ - version = - ih_version - (B_N_PITEM_HEAD - (tbS0, 0)); - set_le_key_k_offset - (version, - B_N_PKEY - (tbS0, 0), - le_key_k_offset - (version, - B_N_PKEY - (tbS0, - 0)) + - temp_l); + version = ih_version(B_N_PITEM_HEAD(tbS0, 0)); + set_le_key_k_offset(version, B_N_PKEY(tbS0, 0), + le_key_k_offset(version,B_N_PKEY(tbS0, 0)) + temp_l); /* update left delimiting key */ - set_le_key_k_offset - (version, - B_N_PDELIM_KEY - (tb-> - CFL[0], - tb-> - lkey[0]), - le_key_k_offset - (version, - B_N_PDELIM_KEY - (tb-> - CFL[0], - tb-> - lkey[0])) - + temp_l); + set_le_key_k_offset(version, B_N_PDELIM_KEY(tb->CFL[0], tb->lkey[0]), + le_key_k_offset(version, B_N_PDELIM_KEY(tb->CFL[0], tb->lkey[0])) + temp_l); } /* Calculate new body, position in item and insert_size[0] */ if (l_n > zeros_num) { - body += - (l_n - - zeros_num); + body += (l_n - zeros_num); zeros_num = 0; } else - zeros_num -= - l_n; + zeros_num -= l_n; pos_in_item = 0; - RFALSE - (comp_short_le_keys - (B_N_PKEY(tbS0, 0), - B_N_PKEY(tb->L[0], - B_NR_ITEMS - (tb-> - L[0]) - - 1)) - || - !op_is_left_mergeable - (B_N_PKEY(tbS0, 0), - tbS0->b_size) - || - !op_is_left_mergeable - (B_N_PDELIM_KEY - (tb->CFL[0], - tb->lkey[0]), - tbS0->b_size), + RFALSE(comp_short_le_keys(B_N_PKEY(tbS0, 0), B_N_PKEY(tb->L[0], B_NR_ITEMS(tb->L[0]) - 1)) + || !op_is_left_mergeable(B_N_PKEY(tbS0, 0), tbS0->b_size) + || !op_is_left_mergeable(B_N_PDELIM_KEY(tb->CFL[0], tb->lkey[0]), tbS0->b_size), "PAP-12120: item must be merge-able with left neighboring item"); } else { /* only part of the appended item will be in L[0] */ /* Calculate position in item for append in S[0] */ - pos_in_item -= - tb->lbytes; + pos_in_item -= tb->lbytes; - RFALSE(pos_in_item <= 0, - "PAP-12125: no place for paste. pos_in_item=%d", - pos_in_item); + RFALSE(pos_in_item <= 0, "PAP-12125: no place for paste. pos_in_item=%d", pos_in_item); /* Shift lnum[0] - 1 items in whole. Shift lbytes - 1 byte from item number lnum[0] */ - leaf_shift_left(tb, - tb-> - lnum[0], - tb-> - lbytes); + leaf_shift_left(tb, tb->lnum[0], tb->lbytes); } } } else { /* appended item will be in L[0] in whole */ @@ -665,52 +495,30 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h if (!item_pos && op_is_left_mergeable(B_N_PKEY(tbS0, 0), tbS0->b_size)) { /* if we paste into first item of S[0] and it is left mergable */ /* then increment pos_in_item by the size of the last item in L[0] */ - pasted = - B_N_PITEM_HEAD(tb->L[0], - n - 1); + pasted = B_N_PITEM_HEAD(tb->L[0], n - 1); if (is_direntry_le_ih(pasted)) - pos_in_item += - ih_entry_count - (pasted); + pos_in_item += ih_entry_count(pasted); else - pos_in_item += - ih_item_len(pasted); + pos_in_item += ih_item_len(pasted); } /* Shift lnum[0] - 1 items in whole. Shift lbytes - 1 byte from item number lnum[0] */ - ret_val = - leaf_shift_left(tb, tb->lnum[0], - tb->lbytes); + ret_val = leaf_shift_left(tb, tb->lnum[0], tb->lbytes); /* Append to body of item in L[0] */ buffer_info_init_left(tb, &bi); - leaf_paste_in_buffer(&bi, - n + item_pos - - ret_val, + leaf_paste_in_buffer(&bi, n + item_pos - ret_val, pos_in_item, tb->insert_size[0], body, zeros_num); /* if appended item is directory, paste entry */ - pasted = - B_N_PITEM_HEAD(tb->L[0], - n + item_pos - - ret_val); + pasted = B_N_PITEM_HEAD(tb->L[0], n + item_pos - ret_val); if (is_direntry_le_ih(pasted)) - leaf_paste_entries(&bi, - n + - item_pos - - ret_val, - pos_in_item, - 1, - (struct - reiserfs_de_head - *)body, - body + - DEH_SIZE, - tb-> - insert_size - [0] - ); + leaf_paste_entries(&bi, n + item_pos - ret_val, + pos_in_item, 1, + (struct reiserfs_de_head *) body, + body + DEH_SIZE, + tb->insert_size[0]); /* if appended item is indirect item, put unformatted node into un list */ if (is_indirect_le_ih(pasted)) set_ih_free_space(pasted, 0); @@ -722,13 +530,7 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h reiserfs_panic(tb->tb_sb, "PAP-12130", "lnum > 0: unexpected mode: " " %s(%d)", - (flag == - M_DELETE) ? "DELETE" : ((flag == - M_CUT) - ? "CUT" - : - "UNKNOWN"), - flag); + (flag == M_DELETE) ? "DELETE" : ((flag == M_CUT) ? "CUT" : "UNKNOWN"), flag); } } else { /* new item doesn't fall into L[0] */ @@ -748,14 +550,12 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h case M_INSERT: /* insert item */ if (n - tb->rnum[0] < item_pos) { /* new item or its part falls to R[0] */ if (item_pos == n - tb->rnum[0] + 1 && tb->rbytes != -1) { /* part of new item falls into R[0] */ - loff_t old_key_comp, old_len, - r_zeros_number; + loff_t old_key_comp, old_len, r_zeros_number; const char *r_body; int version; loff_t offset; - leaf_shift_right(tb, tb->rnum[0] - 1, - -1); + leaf_shift_right(tb, tb->rnum[0] - 1, -1); version = ih_version(ih); /* Remember key component and item length */ @@ -763,29 +563,17 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h old_len = ih_item_len(ih); /* Calculate key component and item length to insert into R[0] */ - offset = - le_ih_k_offset(ih) + - ((old_len - - tb-> - rbytes) << (is_indirect_le_ih(ih) - ? tb->tb_sb-> - s_blocksize_bits - - UNFM_P_SHIFT : 0)); + offset = le_ih_k_offset(ih) + ((old_len - tb->rbytes) << (is_indirect_le_ih(ih) ? tb->tb_sb->s_blocksize_bits - UNFM_P_SHIFT : 0)); set_le_ih_k_offset(ih, offset); put_ih_item_len(ih, tb->rbytes); /* Insert part of the item into R[0] */ buffer_info_init_right(tb, &bi); if ((old_len - tb->rbytes) > zeros_num) { r_zeros_number = 0; - r_body = - body + (old_len - - tb->rbytes) - - zeros_num; + r_body = body + (old_len - tb->rbytes) - zeros_num; } else { r_body = body; - r_zeros_number = - zeros_num - (old_len - - tb->rbytes); + r_zeros_number = zeros_num - (old_len - tb->rbytes); zeros_num -= r_zeros_number; } @@ -798,25 +586,18 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h /* Calculate key component and item length to insert into S[0] */ set_le_ih_k_offset(ih, old_key_comp); - put_ih_item_len(ih, - old_len - tb->rbytes); + put_ih_item_len(ih, old_len - tb->rbytes); tb->insert_size[0] -= tb->rbytes; } else { /* whole new item falls into R[0] */ /* Shift rnum[0]-1 items to R[0] */ - ret_val = - leaf_shift_right(tb, - tb->rnum[0] - 1, - tb->rbytes); + ret_val = leaf_shift_right(tb, tb->rnum[0] - 1, tb->rbytes); /* Insert new item into R[0] */ buffer_info_init_right(tb, &bi); - leaf_insert_into_buf(&bi, - item_pos - n + - tb->rnum[0] - 1, - ih, body, - zeros_num); + leaf_insert_into_buf(&bi, item_pos - n + tb->rnum[0] - 1, + ih, body, zeros_num); if (item_pos - n + tb->rnum[0] - 1 == 0) { replace_key(tb, tb->CFR[0], @@ -841,200 +622,97 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h RFALSE(zeros_num, "PAP-12145: invalid parameter in case of a directory"); - entry_count = - I_ENTRY_COUNT(B_N_PITEM_HEAD - (tbS0, - item_pos)); + entry_count = I_ENTRY_COUNT(B_N_PITEM_HEAD + (tbS0, item_pos)); if (entry_count - tb->rbytes < pos_in_item) /* new directory entry falls into R[0] */ { int paste_entry_position; - RFALSE(tb->rbytes - 1 >= - entry_count - || !tb-> - insert_size[0], + RFALSE(tb->rbytes - 1 >= entry_count || !tb-> insert_size[0], "PAP-12150: no enough of entries to shift to R[0]: rbytes=%d, entry_count=%d", - tb->rbytes, - entry_count); + tb->rbytes, entry_count); /* Shift rnum[0]-1 items in whole. Shift rbytes-1 directory entries from directory item number rnum[0] */ - leaf_shift_right(tb, - tb-> - rnum - [0], - tb-> - rbytes - - 1); + leaf_shift_right(tb, tb->rnum[0], tb->rbytes - 1); /* Paste given directory entry to directory item */ - paste_entry_position = - pos_in_item - - entry_count + - tb->rbytes - 1; + paste_entry_position = pos_in_item - entry_count + tb->rbytes - 1; buffer_info_init_right(tb, &bi); - leaf_paste_in_buffer - (&bi, 0, - paste_entry_position, - tb->insert_size[0], - body, zeros_num); + leaf_paste_in_buffer(&bi, 0, paste_entry_position, tb->insert_size[0], body, zeros_num); /* paste entry */ - leaf_paste_entries(&bi, - 0, - paste_entry_position, - 1, - (struct - reiserfs_de_head - *) - body, - body - + - DEH_SIZE, - tb-> - insert_size - [0] - ); - - if (paste_entry_position - == 0) { + leaf_paste_entries(&bi, 0, paste_entry_position, 1, + (struct reiserfs_de_head *) body, + body + DEH_SIZE, tb->insert_size[0]); + + if (paste_entry_position == 0) { /* change delimiting keys */ - replace_key(tb, - tb-> - CFR - [0], - tb-> - rkey - [0], - tb-> - R - [0], - 0); + replace_key(tb, tb->CFR[0], tb->rkey[0], tb->R[0],0); } tb->insert_size[0] = 0; pos_in_item++; } else { /* new directory entry doesn't fall into R[0] */ - leaf_shift_right(tb, - tb-> - rnum - [0], - tb-> - rbytes); + leaf_shift_right(tb, tb->rnum[0], tb->rbytes); } } else { /* regular object */ - int n_shift, n_rem, - r_zeros_number; + int n_shift, n_rem, r_zeros_number; const char *r_body; /* Calculate number of bytes which must be shifted from appended item */ - if ((n_shift = - tb->rbytes - - tb->insert_size[0]) < 0) + if ((n_shift = tb->rbytes - tb->insert_size[0]) < 0) n_shift = 0; - RFALSE(pos_in_item != - ih_item_len - (B_N_PITEM_HEAD - (tbS0, item_pos)), + RFALSE(pos_in_item != ih_item_len + (B_N_PITEM_HEAD(tbS0, item_pos)), "PAP-12155: invalid position to paste. ih_item_len=%d, pos_in_item=%d", - pos_in_item, - ih_item_len - (B_N_PITEM_HEAD - (tbS0, item_pos))); - - leaf_shift_right(tb, - tb->rnum[0], - n_shift); + pos_in_item, ih_item_len + (B_N_PITEM_HEAD(tbS0, item_pos))); + + leaf_shift_right(tb, tb->rnum[0], n_shift); /* Calculate number of bytes which must remain in body after appending to R[0] */ - if ((n_rem = - tb->insert_size[0] - - tb->rbytes) < 0) + if ((n_rem = tb->insert_size[0] - tb->rbytes) < 0) n_rem = 0; { int version; - unsigned long temp_rem = - n_rem; - - version = - ih_version - (B_N_PITEM_HEAD - (tb->R[0], 0)); - if (is_indirect_le_key - (version, - B_N_PKEY(tb->R[0], - 0))) { - temp_rem = - n_rem << - (tb->tb_sb-> - s_blocksize_bits - - - UNFM_P_SHIFT); + unsigned long temp_rem = n_rem; + + version = ih_version(B_N_PITEM_HEAD(tb->R[0], 0)); + if (is_indirect_le_key(version, B_N_PKEY(tb->R[0], 0))) { + temp_rem = n_rem << (tb->tb_sb->s_blocksize_bits - UNFM_P_SHIFT); } - set_le_key_k_offset - (version, - B_N_PKEY(tb->R[0], - 0), - le_key_k_offset - (version, - B_N_PKEY(tb->R[0], - 0)) + - temp_rem); - set_le_key_k_offset - (version, - B_N_PDELIM_KEY(tb-> - CFR - [0], - tb-> - rkey - [0]), - le_key_k_offset - (version, - B_N_PDELIM_KEY - (tb->CFR[0], - tb->rkey[0])) + - temp_rem); + set_le_key_k_offset(version, B_N_PKEY(tb->R[0], 0), + le_key_k_offset(version, B_N_PKEY(tb->R[0], 0)) + temp_rem); + set_le_key_k_offset(version, B_N_PDELIM_KEY(tb->CFR[0], tb->rkey[0]), + le_key_k_offset(version, B_N_PDELIM_KEY(tb->CFR[0], tb->rkey[0])) + temp_rem); } /* k_offset (B_N_PKEY(tb->R[0],0)) += n_rem; k_offset (B_N_PDELIM_KEY(tb->CFR[0],tb->rkey[0])) += n_rem;*/ - do_balance_mark_internal_dirty - (tb, tb->CFR[0], 0); + do_balance_mark_internal_dirty(tb, tb->CFR[0], 0); /* Append part of body into R[0] */ buffer_info_init_right(tb, &bi); if (n_rem > zeros_num) { r_zeros_number = 0; - r_body = - body + n_rem - - zeros_num; + r_body = body + n_rem - zeros_num; } else { r_body = body; - r_zeros_number = - zeros_num - n_rem; - zeros_num -= - r_zeros_number; + r_zeros_number = zeros_num - n_rem; + zeros_num -= r_zeros_number; } - leaf_paste_in_buffer(&bi, 0, - n_shift, - tb-> - insert_size - [0] - - n_rem, - r_body, - r_zeros_number); - - if (is_indirect_le_ih - (B_N_PITEM_HEAD - (tb->R[0], 0))) { + leaf_paste_in_buffer(&bi, 0, n_shift, + tb->insert_size[0] - n_rem, + r_body, r_zeros_number); + + if (is_indirect_le_ih(B_N_PITEM_HEAD(tb->R[0], 0))) { #if 0 RFALSE(n_rem, "PAP-12160: paste more than one unformatted node pointer"); #endif - set_ih_free_space - (B_N_PITEM_HEAD - (tb->R[0], 0), 0); + set_ih_free_space(B_N_PITEM_HEAD(tb->R[0], 0), 0); } tb->insert_size[0] = n_rem; if (!n_rem) @@ -1044,58 +722,28 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h struct item_head *pasted; - ret_val = - leaf_shift_right(tb, tb->rnum[0], - tb->rbytes); + ret_val = leaf_shift_right(tb, tb->rnum[0], tb->rbytes); /* append item in R[0] */ if (pos_in_item >= 0) { buffer_info_init_right(tb, &bi); - leaf_paste_in_buffer(&bi, - item_pos - - n + - tb-> - rnum[0], - pos_in_item, - tb-> - insert_size - [0], body, - zeros_num); + leaf_paste_in_buffer(&bi, item_pos - n + tb->rnum[0], pos_in_item, + tb->insert_size[0], body, zeros_num); } /* paste new entry, if item is directory item */ - pasted = - B_N_PITEM_HEAD(tb->R[0], - item_pos - n + - tb->rnum[0]); - if (is_direntry_le_ih(pasted) - && pos_in_item >= 0) { - leaf_paste_entries(&bi, - item_pos - - n + - tb->rnum[0], - pos_in_item, - 1, - (struct - reiserfs_de_head - *)body, - body + - DEH_SIZE, - tb-> - insert_size - [0] - ); + pasted = B_N_PITEM_HEAD(tb->R[0], item_pos - n + tb->rnum[0]); + if (is_direntry_le_ih(pasted) && pos_in_item >= 0) { + leaf_paste_entries(&bi, item_pos - n + tb->rnum[0], + pos_in_item, 1, + (struct reiserfs_de_head *) body, + body + DEH_SIZE, tb->insert_size[0]); if (!pos_in_item) { - RFALSE(item_pos - n + - tb->rnum[0], + RFALSE(item_pos - n + tb->rnum[0], "PAP-12165: directory item must be first item of node when pasting is in 0th position"); /* update delimiting keys */ - replace_key(tb, - tb->CFR[0], - tb->rkey[0], - tb->R[0], - 0); + replace_key(tb, tb->CFR[0], tb->rkey[0], tb->R[0], 0); } } @@ -1111,22 +759,16 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h default: /* cases d and t */ reiserfs_panic(tb->tb_sb, "PAP-12175", "rnum > 0: unexpected mode: %s(%d)", - (flag == - M_DELETE) ? "DELETE" : ((flag == - M_CUT) ? "CUT" - : "UNKNOWN"), - flag); + (flag == M_DELETE) ? "DELETE" : ((flag == M_CUT) ? "CUT" : "UNKNOWN"), flag); } } /* tb->rnum[0] > 0 */ RFALSE(tb->blknum[0] > 3, - "PAP-12180: blknum can not be %d. It must be <= 3", - tb->blknum[0]); + "PAP-12180: blknum can not be %d. It must be <= 3", tb->blknum[0]); RFALSE(tb->blknum[0] < 0, - "PAP-12185: blknum can not be %d. It must be >= 0", - tb->blknum[0]); + "PAP-12185: blknum can not be %d. It must be >= 0", tb->blknum[0]); /* if while adding to a node we discover that it is possible to split it in two, and merge the left part into the left neighbor and the @@ -1177,8 +819,7 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h if (n - snum[i] < item_pos) { /* new item or it's part falls to first new node S_new[i] */ if (item_pos == n - snum[i] + 1 && sbytes[i] != -1) { /* part of new item falls into S_new[i] */ - int old_key_comp, old_len, - r_zeros_number; + int old_key_comp, old_len, r_zeros_number; const char *r_body; int version; @@ -1192,15 +833,8 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h old_len = ih_item_len(ih); /* Calculate key component and item length to insert into S_new[i] */ - set_le_ih_k_offset(ih, - le_ih_k_offset(ih) + - ((old_len - - sbytes[i]) << - (is_indirect_le_ih - (ih) ? tb->tb_sb-> - s_blocksize_bits - - UNFM_P_SHIFT : - 0))); + set_le_ih_k_offset(ih, le_ih_k_offset(ih) + + ((old_len - sbytes[i]) << (is_indirect_le_ih(ih) ? tb->tb_sb-> s_blocksize_bits - UNFM_P_SHIFT : 0))); put_ih_item_len(ih, sbytes[i]); @@ -1209,39 +843,29 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h if ((old_len - sbytes[i]) > zeros_num) { r_zeros_number = 0; - r_body = - body + (old_len - - sbytes[i]) - - zeros_num; + r_body = body + (old_len - sbytes[i]) - zeros_num; } else { r_body = body; - r_zeros_number = - zeros_num - (old_len - - sbytes[i]); + r_zeros_number = zeros_num - (old_len - sbytes[i]); zeros_num -= r_zeros_number; } - leaf_insert_into_buf(&bi, 0, ih, r_body, - r_zeros_number); + leaf_insert_into_buf(&bi, 0, ih, r_body, r_zeros_number); /* Calculate key component and item length to insert into S[i] */ set_le_ih_k_offset(ih, old_key_comp); - put_ih_item_len(ih, - old_len - sbytes[i]); + put_ih_item_len(ih, old_len - sbytes[i]); tb->insert_size[0] -= sbytes[i]; } else { /* whole new item falls into S_new[i] */ /* Shift snum[0] - 1 items to S_new[i] (sbytes[i] of split item) */ leaf_move_items(LEAF_FROM_S_TO_SNEW, tb, - snum[i] - 1, sbytes[i], - S_new[i]); + snum[i] - 1, sbytes[i], S_new[i]); /* Insert new item into S_new[i] */ buffer_info_init_bh(tb, &bi, S_new[i]); - leaf_insert_into_buf(&bi, - item_pos - n + - snum[i] - 1, ih, - body, zeros_num); + leaf_insert_into_buf(&bi, item_pos - n + snum[i] - 1, + ih, body, zeros_num); zeros_num = tb->insert_size[0] = 0; } @@ -1268,150 +892,73 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h int entry_count; - entry_count = - ih_entry_count(aux_ih); + entry_count = ih_entry_count(aux_ih); - if (entry_count - sbytes[i] < - pos_in_item - && pos_in_item <= - entry_count) { + if (entry_count - sbytes[i] < pos_in_item && pos_in_item <= entry_count) { /* new directory entry falls into S_new[i] */ - RFALSE(!tb-> - insert_size[0], - "PAP-12215: insert_size is already 0"); - RFALSE(sbytes[i] - 1 >= - entry_count, + RFALSE(!tb->insert_size[0], "PAP-12215: insert_size is already 0"); + RFALSE(sbytes[i] - 1 >= entry_count, "PAP-12220: there are no so much entries (%d), only %d", - sbytes[i] - 1, - entry_count); + sbytes[i] - 1, entry_count); /* Shift snum[i]-1 items in whole. Shift sbytes[i] directory entries from directory item number snum[i] */ - leaf_move_items - (LEAF_FROM_S_TO_SNEW, - tb, snum[i], - sbytes[i] - 1, - S_new[i]); + leaf_move_items(LEAF_FROM_S_TO_SNEW, tb, snum[i], sbytes[i] - 1, S_new[i]); /* Paste given directory entry to directory item */ buffer_info_init_bh(tb, &bi, S_new[i]); - leaf_paste_in_buffer - (&bi, 0, - pos_in_item - - entry_count + - sbytes[i] - 1, - tb->insert_size[0], - body, zeros_num); + leaf_paste_in_buffer(&bi, 0, pos_in_item - entry_count + sbytes[i] - 1, + tb->insert_size[0], body, zeros_num); /* paste new directory entry */ - leaf_paste_entries(&bi, - 0, - pos_in_item - - - entry_count - + - sbytes - [i] - - 1, 1, - (struct - reiserfs_de_head - *) - body, - body - + - DEH_SIZE, - tb-> - insert_size - [0] - ); + leaf_paste_entries(&bi, 0, pos_in_item - entry_count + sbytes[i] - 1, 1, + (struct reiserfs_de_head *) body, + body + DEH_SIZE, tb->insert_size[0]); tb->insert_size[0] = 0; pos_in_item++; } else { /* new directory entry doesn't fall into S_new[i] */ - leaf_move_items - (LEAF_FROM_S_TO_SNEW, - tb, snum[i], - sbytes[i], - S_new[i]); + leaf_move_items(LEAF_FROM_S_TO_SNEW,tb, snum[i], sbytes[i], S_new[i]); } } else { /* regular object */ - int n_shift, n_rem, - r_zeros_number; + int n_shift, n_rem, r_zeros_number; const char *r_body; - RFALSE(pos_in_item != - ih_item_len - (B_N_PITEM_HEAD - (tbS0, item_pos)) - || tb->insert_size[0] <= - 0, + RFALSE(pos_in_item != ih_item_len(B_N_PITEM_HEAD(tbS0, item_pos)) || tb->insert_size[0] <= 0, "PAP-12225: item too short or insert_size <= 0"); /* Calculate number of bytes which must be shifted from appended item */ - n_shift = - sbytes[i] - - tb->insert_size[0]; + n_shift = sbytes[i] - tb->insert_size[0]; if (n_shift < 0) n_shift = 0; - leaf_move_items - (LEAF_FROM_S_TO_SNEW, tb, - snum[i], n_shift, - S_new[i]); + leaf_move_items(LEAF_FROM_S_TO_SNEW, tb, snum[i], n_shift, S_new[i]); /* Calculate number of bytes which must remain in body after append to S_new[i] */ - n_rem = - tb->insert_size[0] - - sbytes[i]; + n_rem = tb->insert_size[0] - sbytes[i]; if (n_rem < 0) n_rem = 0; /* Append part of body into S_new[0] */ buffer_info_init_bh(tb, &bi, S_new[i]); if (n_rem > zeros_num) { r_zeros_number = 0; - r_body = - body + n_rem - - zeros_num; + r_body = body + n_rem - zeros_num; } else { r_body = body; - r_zeros_number = - zeros_num - n_rem; - zeros_num -= - r_zeros_number; + r_zeros_number = zeros_num - n_rem; + zeros_num -= r_zeros_number; } - leaf_paste_in_buffer(&bi, 0, - n_shift, - tb-> - insert_size - [0] - - n_rem, - r_body, - r_zeros_number); + leaf_paste_in_buffer(&bi, 0, n_shift, + tb->insert_size[0] - n_rem, + r_body, r_zeros_number); { struct item_head *tmp; - tmp = - B_N_PITEM_HEAD(S_new - [i], - 0); + tmp = B_N_PITEM_HEAD(S_new[i], 0); if (is_indirect_le_ih (tmp)) { - set_ih_free_space - (tmp, 0); - set_le_ih_k_offset - (tmp, - le_ih_k_offset - (tmp) + - (n_rem << - (tb-> - tb_sb-> - s_blocksize_bits - - - UNFM_P_SHIFT))); + set_ih_free_space(tmp, 0); + set_le_ih_k_offset(tmp, le_ih_k_offset(tmp) + (n_rem << (tb->tb_sb->s_blocksize_bits - UNFM_P_SHIFT))); } else { - set_le_ih_k_offset - (tmp, - le_ih_k_offset - (tmp) + - n_rem); + set_le_ih_k_offset(tmp, le_ih_k_offset(tmp) + n_rem); } } @@ -1426,8 +973,7 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h struct item_head *pasted; #ifdef CONFIG_REISERFS_CHECK - struct item_head *ih_check = - B_N_PITEM_HEAD(tbS0, item_pos); + struct item_head *ih_check = B_N_PITEM_HEAD(tbS0, item_pos); if (!is_direntry_le_ih(ih_check) && (pos_in_item != ih_item_len(ih_check) @@ -1439,8 +985,7 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h "to ih_item_len"); #endif /* CONFIG_REISERFS_CHECK */ - leaf_mi = - leaf_move_items(LEAF_FROM_S_TO_SNEW, + leaf_mi = leaf_move_items(LEAF_FROM_S_TO_SNEW, tb, snum[i], sbytes[i], S_new[i]); @@ -1452,30 +997,19 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h /* paste into item */ buffer_info_init_bh(tb, &bi, S_new[i]); leaf_paste_in_buffer(&bi, - item_pos - n + - snum[i], + item_pos - n + snum[i], pos_in_item, tb->insert_size[0], body, zeros_num); - pasted = - B_N_PITEM_HEAD(S_new[i], - item_pos - n + - snum[i]); + pasted = B_N_PITEM_HEAD(S_new[i], item_pos - n + snum[i]); if (is_direntry_le_ih(pasted)) { leaf_paste_entries(&bi, - item_pos - - n + snum[i], - pos_in_item, - 1, - (struct - reiserfs_de_head - *)body, - body + - DEH_SIZE, - tb-> - insert_size - [0] + item_pos - n + snum[i], + pos_in_item, 1, + (struct reiserfs_de_head *)body, + body + DEH_SIZE, + tb->insert_size[0] ); } @@ -1495,11 +1029,7 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h default: /* cases d and t */ reiserfs_panic(tb->tb_sb, "PAP-12245", "blknum > 2: unexpected mode: %s(%d)", - (flag == - M_DELETE) ? "DELETE" : ((flag == - M_CUT) ? "CUT" - : "UNKNOWN"), - flag); + (flag == M_DELETE) ? "DELETE" : ((flag == M_CUT) ? "CUT" : "UNKNOWN"), flag); } memcpy(insert_key + i, B_N_PKEY(S_new[i], 0), KEY_SIZE); @@ -1524,9 +1054,7 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h /* If we insert the first key change the delimiting key */ if (item_pos == 0) { if (tb->CFL[0]) /* can be 0 in reiserfsck */ - replace_key(tb, tb->CFL[0], tb->lkey[0], - tbS0, 0); - + replace_key(tb, tb->CFL[0], tb->lkey[0], tbS0, 0); } break; @@ -1536,53 +1064,27 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h pasted = B_N_PITEM_HEAD(tbS0, item_pos); /* when directory, may be new entry already pasted */ if (is_direntry_le_ih(pasted)) { - if (pos_in_item >= 0 && - pos_in_item <= - ih_entry_count(pasted)) { + if (pos_in_item >= 0 && pos_in_item <= ih_entry_count(pasted)) { RFALSE(!tb->insert_size[0], "PAP-12260: insert_size is 0 already"); /* prepare space */ buffer_info_init_tbS0(tb, &bi); - leaf_paste_in_buffer(&bi, - item_pos, - pos_in_item, - tb-> - insert_size - [0], body, + leaf_paste_in_buffer(&bi, item_pos, pos_in_item, + tb->insert_size[0], body, zeros_num); /* paste entry */ - leaf_paste_entries(&bi, - item_pos, - pos_in_item, - 1, - (struct - reiserfs_de_head - *)body, - body + - DEH_SIZE, - tb-> - insert_size - [0] - ); + leaf_paste_entries(&bi, item_pos, pos_in_item, 1, + (struct reiserfs_de_head *)body, + body + DEH_SIZE, + tb->insert_size[0]); if (!item_pos && !pos_in_item) { - RFALSE(!tb->CFL[0] - || !tb->L[0], + RFALSE(!tb->CFL[0] || !tb->L[0], "PAP-12270: CFL[0]/L[0] must be specified"); - if (tb->CFL[0]) { - replace_key(tb, - tb-> - CFL - [0], - tb-> - lkey - [0], - tbS0, - 0); - - } + if (tb->CFL[0]) + replace_key(tb, tb->CFL[0], tb->lkey[0], tbS0, 0); } tb->insert_size[0] = 0; } @@ -1593,13 +1095,8 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h "PAP-12275: insert size must not be %d", tb->insert_size[0]); buffer_info_init_tbS0(tb, &bi); - leaf_paste_in_buffer(&bi, - item_pos, - pos_in_item, - tb-> - insert_size - [0], body, - zeros_num); + leaf_paste_in_buffer(&bi, item_pos, pos_in_item, + tb->insert_size[0], body, zeros_num); if (is_indirect_le_ih(pasted)) { #if 0 @@ -1611,8 +1108,7 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h tb-> insert_size[0]); #endif - set_ih_free_space - (pasted, 0); + set_ih_free_space(pasted, 0); } tb->insert_size[0] = 0; } @@ -1620,8 +1116,7 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h else { if (tb->insert_size[0]) { print_cur_tb("12285"); - reiserfs_panic(tb-> - tb_sb, + reiserfs_panic(tb->tb_sb, "PAP-12285", "insert_size " "must be 0 " -- cgit v1.2.3 From 7026f1929e18921fd67bf478f475a8fdfdff16ae Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 17 Feb 2014 15:01:47 +0000 Subject: FS-Cache: Handle removal of unadded object to the fscache_object_list rb tree When FS-Cache allocates an object, the following sequence of events can occur: -->fscache_alloc_object() -->cachefiles_alloc_object() [via cache->ops->alloc_object] <--[returns new object] -->fscache_attach_object() <--[failed] -->cachefiles_put_object() [via cache->ops->put_object] -->fscache_object_destroy() -->fscache_objlist_remove() -->rb_erase() to remove the object from fscache_object_list. resulting in a crash in the rbtree code. The problem is that the object is only added to fscache_object_list on the success path of fscache_attach_object() where it calls fscache_objlist_add(). So if fscache_attach_object() fails, the object won't have been added to the objlist rbtree. We do, however, unconditionally try to remove the object from the tree. Thanks to NeilBrown for finding this and suggesting this solution. Reported-by: NeilBrown Signed-off-by: David Howells Tested-by: (a customer of) NeilBrown Signed-off-by: Linus Torvalds --- fs/fscache/object-list.c | 5 +++++ fs/fscache/object.c | 3 +++ 2 files changed, 8 insertions(+) diff --git a/fs/fscache/object-list.c b/fs/fscache/object-list.c index e1959efad64f..b5ebc2d7d80d 100644 --- a/fs/fscache/object-list.c +++ b/fs/fscache/object-list.c @@ -50,6 +50,8 @@ void fscache_objlist_add(struct fscache_object *obj) struct fscache_object *xobj; struct rb_node **p = &fscache_object_list.rb_node, *parent = NULL; + ASSERT(RB_EMPTY_NODE(&obj->objlist_link)); + write_lock(&fscache_object_list_lock); while (*p) { @@ -75,6 +77,9 @@ void fscache_objlist_add(struct fscache_object *obj) */ void fscache_objlist_remove(struct fscache_object *obj) { + if (RB_EMPTY_NODE(&obj->objlist_link)) + return; + write_lock(&fscache_object_list_lock); BUG_ON(RB_EMPTY_ROOT(&fscache_object_list)); diff --git a/fs/fscache/object.c b/fs/fscache/object.c index 53d35c504240..d3b4539f1651 100644 --- a/fs/fscache/object.c +++ b/fs/fscache/object.c @@ -314,6 +314,9 @@ void fscache_object_init(struct fscache_object *object, object->cache = cache; object->cookie = cookie; object->parent = NULL; +#ifdef CONFIG_FSCACHE_OBJECT_LIST + RB_CLEAR_NODE(&object->objlist_link); +#endif object->oob_event_mask = 0; for (t = object->oob_table; t->events; t++) -- cgit v1.2.3 From a6254864c08109c66a194612585afc0439005286 Mon Sep 17 00:00:00 2001 From: Duan Jiong Date: Mon, 17 Feb 2014 15:23:43 +0800 Subject: ipv4: fix counter in_slow_tot since commit 89aef8921bf("ipv4: Delete routing cache."), the counter in_slow_tot can't work correctly. The counter in_slow_tot increase by one when fib_lookup() return successfully in ip_route_input_slow(), but actually the dst struct maybe not be created and cached, so we can increase in_slow_tot after the dst struct is created. Signed-off-by: Duan Jiong Signed-off-by: David S. Miller --- net/ipv4/route.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 6f6dd85bdffc..4c011ec69ed4 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1597,6 +1597,7 @@ static int __mkroute_input(struct sk_buff *skb, rth->rt_gateway = 0; rth->rt_uses_gateway = 0; INIT_LIST_HEAD(&rth->rt_uncached); + RT_CACHE_STAT_INC(in_slow_tot); rth->dst.input = ip_forward; rth->dst.output = ip_output; @@ -1701,8 +1702,6 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr, goto no_route; } - RT_CACHE_STAT_INC(in_slow_tot); - if (res.type == RTN_BROADCAST) goto brd_input; @@ -1773,6 +1772,7 @@ local_input: rth->rt_gateway = 0; rth->rt_uses_gateway = 0; INIT_LIST_HEAD(&rth->rt_uncached); + RT_CACHE_STAT_INC(in_slow_tot); if (res.type == RTN_UNREACHABLE) { rth->dst.input= ip_error; rth->dst.error= -err; -- cgit v1.2.3 From e83b366487b5582274374f8226e489cb214ae5a6 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 11 Feb 2014 17:11:04 +0000 Subject: Fix uses of dma_max_pfn() when converting to a limiting address We must use a 64-bit for this, otherwise overflowed bits get lost, and that can result in a lower than intended value set. Fixes: 8e0cb8a1f6ac ("ARM: 7797/1: mmc: Use dma_max_pfn(dev) helper for bounce_limit calculations") Fixes: 7d35496dd982 ("ARM: 7796/1: scsi: Use dma_max_pfn(dev) helper for bounce_limit calculations") Tested-Acked-by: Santosh Shilimkar Reviewed-by: Ulf Hansson Signed-off-by: Russell King --- drivers/mmc/card/queue.c | 2 +- drivers/scsi/scsi_lib.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c index 357bbc54fe4b..3e049c13429c 100644 --- a/drivers/mmc/card/queue.c +++ b/drivers/mmc/card/queue.c @@ -197,7 +197,7 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, struct mmc_queue_req *mqrq_prev = &mq->mqrq[1]; if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask) - limit = dma_max_pfn(mmc_dev(host)) << PAGE_SHIFT; + limit = (u64)dma_max_pfn(mmc_dev(host)) << PAGE_SHIFT; mq->card = card; mq->queue = blk_init_queue(mmc_request_fn, lock); diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 7bd7f0d5f050..62ec84b42e31 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1684,7 +1684,7 @@ u64 scsi_calculate_bounce_limit(struct Scsi_Host *shost) host_dev = scsi_get_device(shost); if (host_dev && host_dev->dma_mask) - bounce_limit = dma_max_pfn(host_dev) << PAGE_SHIFT; + bounce_limit = (u64)dma_max_pfn(host_dev) << PAGE_SHIFT; return bounce_limit; } -- cgit v1.2.3 From 39544ac9df20f73e49fc6b9ac19ff533388c82c0 Mon Sep 17 00:00:00 2001 From: Vinayak Kale Date: Wed, 12 Feb 2014 07:30:01 +0100 Subject: ARM: 7957/1: add DSB after icache flush in __flush_icache_all() Add DSB after icache flush to complete the cache maintenance operation. Signed-off-by: Vinayak Kale Acked-by: Catalin Marinas Cc: Signed-off-by: Russell King --- arch/arm/include/asm/cacheflush.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h index e9a49fe0284e..8b8b61685a34 100644 --- a/arch/arm/include/asm/cacheflush.h +++ b/arch/arm/include/asm/cacheflush.h @@ -212,6 +212,7 @@ extern void copy_to_user_page(struct vm_area_struct *, struct page *, static inline void __flush_icache_all(void) { __flush_icache_preferred(); + dsb(); } /* -- cgit v1.2.3 From 7d3428cd4b2ad51af86fdbdf8284ca38fa95e601 Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Wed, 29 Jan 2014 19:53:00 -0500 Subject: drm/nouveau: set irq_enabled manually Since commit 0fa9061ae8c ("drm/nouveau/mc: handle irq-related setup ourselves"), drm_device->irq_enabled remained unset. This is needed in order to properly wait for a vblank event in the generic drm code. See https://bugs.freedesktop.org/show_bug.cgi?id=74195 Reported-by: Jan Janecek Signed-off-by: Ilia Mirkin Cc: stable@vger.kernel.org # 3.10+ Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_drm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 78c8e7146d56..89c484d8ac26 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -376,6 +376,8 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags) if (ret) goto fail_device; + dev->irq_enabled = true; + /* workaround an odd issue on nvc1 by disabling the device's * nosnoop capability. hopefully won't cause issues until a * better fix is found - assuming there is one... @@ -475,6 +477,7 @@ nouveau_drm_remove(struct pci_dev *pdev) struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_object *device; + dev->irq_enabled = false; device = drm->client.base.device; drm_put_dev(dev); -- cgit v1.2.3 From fa8c9ac72fe0bcdf5bc7cc84e85cc2a1af53f9fd Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Wed, 5 Feb 2014 14:33:02 -0500 Subject: drm/nv4c/mc: nv4x igp's have a different msi rearm register MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit See https://bugs.freedesktop.org/show_bug.cgi?id=74492 Reported-by: Ronald Suggested-by: Marcin KoÅ›cielnicki Signed-off-by: Ilia Mirkin Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/Makefile | 1 + drivers/gpu/drm/nouveau/core/engine/device/nv40.c | 10 ++--- drivers/gpu/drm/nouveau/core/include/subdev/mc.h | 1 + drivers/gpu/drm/nouveau/core/subdev/mc/nv04.h | 1 + drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c | 2 +- drivers/gpu/drm/nouveau/core/subdev/mc/nv4c.c | 45 +++++++++++++++++++++++ 6 files changed, 54 insertions(+), 6 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/core/subdev/mc/nv4c.c diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile index e88145ba1bf5..d310c195bdfe 100644 --- a/drivers/gpu/drm/nouveau/Makefile +++ b/drivers/gpu/drm/nouveau/Makefile @@ -141,6 +141,7 @@ nouveau-y += core/subdev/mc/base.o nouveau-y += core/subdev/mc/nv04.o nouveau-y += core/subdev/mc/nv40.o nouveau-y += core/subdev/mc/nv44.o +nouveau-y += core/subdev/mc/nv4c.o nouveau-y += core/subdev/mc/nv50.o nouveau-y += core/subdev/mc/nv94.o nouveau-y += core/subdev/mc/nv98.o diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nv40.c b/drivers/gpu/drm/nouveau/core/engine/device/nv40.c index 1b653dd74a70..08b88591ed60 100644 --- a/drivers/gpu/drm/nouveau/core/engine/device/nv40.c +++ b/drivers/gpu/drm/nouveau/core/engine/device/nv40.c @@ -311,7 +311,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nv44_mc_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = nv4c_mc_oclass; device->oclass[NVDEV_SUBDEV_BUS ] = nv31_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = nv46_fb_oclass; @@ -334,7 +334,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nv44_mc_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = nv4c_mc_oclass; device->oclass[NVDEV_SUBDEV_BUS ] = nv31_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = nv4e_fb_oclass; @@ -357,7 +357,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nv44_mc_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = nv4c_mc_oclass; device->oclass[NVDEV_SUBDEV_BUS ] = nv31_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = nv46_fb_oclass; @@ -380,7 +380,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nv44_mc_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = nv4c_mc_oclass; device->oclass[NVDEV_SUBDEV_BUS ] = nv31_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = nv46_fb_oclass; @@ -403,7 +403,7 @@ nv40_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass; - device->oclass[NVDEV_SUBDEV_MC ] = nv44_mc_oclass; + device->oclass[NVDEV_SUBDEV_MC ] = nv4c_mc_oclass; device->oclass[NVDEV_SUBDEV_BUS ] = nv31_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = nv46_fb_oclass; diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/mc.h b/drivers/gpu/drm/nouveau/core/include/subdev/mc.h index adc88b73d911..3c6738edd127 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/mc.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/mc.h @@ -47,6 +47,7 @@ struct nouveau_mc_oclass { extern struct nouveau_oclass *nv04_mc_oclass; extern struct nouveau_oclass *nv40_mc_oclass; extern struct nouveau_oclass *nv44_mc_oclass; +extern struct nouveau_oclass *nv4c_mc_oclass; extern struct nouveau_oclass *nv50_mc_oclass; extern struct nouveau_oclass *nv94_mc_oclass; extern struct nouveau_oclass *nv98_mc_oclass; diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.h b/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.h index b0d5c31606c1..81a408e7d034 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.h +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.h @@ -14,6 +14,7 @@ int nv04_mc_ctor(struct nouveau_object *, struct nouveau_object *, extern const struct nouveau_mc_intr nv04_mc_intr[]; int nv04_mc_init(struct nouveau_object *); void nv40_mc_msi_rearm(struct nouveau_mc *); +int nv44_mc_init(struct nouveau_object *object); int nv50_mc_init(struct nouveau_object *); extern const struct nouveau_mc_intr nv50_mc_intr[]; extern const struct nouveau_mc_intr nvc0_mc_intr[]; diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c index 3bfee5c6c4f2..cc4d0d2d886e 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c @@ -24,7 +24,7 @@ #include "nv04.h" -static int +int nv44_mc_init(struct nouveau_object *object) { struct nv04_mc_priv *priv = (void *)object; diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv4c.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv4c.c new file mode 100644 index 000000000000..a75c35ccf25c --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv4c.c @@ -0,0 +1,45 @@ +/* + * Copyright 2014 Ilia Mirkin + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ilia Mirkin + */ + +#include "nv04.h" + +static void +nv4c_mc_msi_rearm(struct nouveau_mc *pmc) +{ + struct nv04_mc_priv *priv = (void *)pmc; + nv_wr08(priv, 0x088050, 0xff); +} + +struct nouveau_oclass * +nv4c_mc_oclass = &(struct nouveau_mc_oclass) { + .base.handle = NV_SUBDEV(MC, 0x4c), + .base.ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv04_mc_ctor, + .dtor = _nouveau_mc_dtor, + .init = nv44_mc_init, + .fini = _nouveau_mc_fini, + }, + .intr = nv04_mc_intr, + .msi_rearm = nv4c_mc_msi_rearm, +}.base; -- cgit v1.2.3 From b71313e14bbc0b8fc25eeff53828ab8e2aee4f25 Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Wed, 5 Feb 2014 14:33:03 -0500 Subject: drm/nv4c/vga: decode register is in a different place on nv4x igp's MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Suggested-by: Marcin KoÅ›cielnicki Signed-off-by: Ilia Mirkin Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_vga.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_vga.c b/drivers/gpu/drm/nouveau/nouveau_vga.c index 81638d7f2eff..471347edc27e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_vga.c +++ b/drivers/gpu/drm/nouveau/nouveau_vga.c @@ -14,7 +14,9 @@ nouveau_vga_set_decode(void *priv, bool state) { struct nouveau_device *device = nouveau_dev(priv); - if (device->chipset >= 0x40) + if (device->card_type == NV_40 && device->chipset >= 0x4c) + nv_wr32(device, 0x088060, state); + else if (device->chipset >= 0x40) nv_wr32(device, 0x088054, state); else nv_wr32(device, 0x001854, state); -- cgit v1.2.3 From 5ac607ec4006d61c425c7846f29de8a9d8ce4f9f Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Wed, 5 Feb 2014 14:33:04 -0500 Subject: drm/nv4c/bios: disallow retrieving from prom on nv4x igp's MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Suggested-by: Marcin KoÅ›cielnicki Signed-off-by: Ilia Mirkin Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/subdev/bios/base.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c index aa0fbbec7f08..ef0c9c4a8cc3 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c @@ -130,6 +130,10 @@ nouveau_bios_shadow_prom(struct nouveau_bios *bios) u16 pcir; int i; + /* there is no prom on nv4x IGP's */ + if (device->card_type == NV_40 && device->chipset >= 0x4c) + return; + /* enable access to rom */ if (device->card_type >= NV_50) pcireg = 0x088050; -- cgit v1.2.3 From bf787d7cdf459d2e7f673b66b69441c708f4472c Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Fri, 7 Feb 2014 22:22:57 +0900 Subject: drm/nouveau: fix ENG_RUNLIST register address Address of the ENG_RUNLIST register should be 0x002284 + (engine * 8), not 0x002284 + (engine * 4). Signed-off-by: Alexandre Courbot Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c index 9a850fe19515..54c1b5b471cd 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c @@ -112,7 +112,7 @@ nve0_fifo_runlist_update(struct nve0_fifo_priv *priv, u32 engine) nv_wr32(priv, 0x002270, cur->addr >> 12); nv_wr32(priv, 0x002274, (engine << 20) | (p >> 3)); - if (!nv_wait(priv, 0x002284 + (engine * 4), 0x00100000, 0x00000000)) + if (!nv_wait(priv, 0x002284 + (engine * 8), 0x00100000, 0x00000000)) nv_error(priv, "runlist %d update timeout\n", engine); mutex_unlock(&nv_subdev(priv)->mutex); } -- cgit v1.2.3 From a8c13aacdc20268ced05c9bb065c5d219840205e Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Sat, 8 Feb 2014 22:35:13 -0500 Subject: drm/nv50/gr: add missing nv_error parameter priv Commit ea7dce901 ("drm/nv50/gr: print mpc trap name when it's not an mp trap") added an nv_error call that was missing the priv parameter. This causes GPFs if the error is ever hit. Signed-off-by: Ilia Mirkin Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/engine/graph/nv50.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c index 30ed19c52e05..7a367c402978 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c @@ -539,7 +539,7 @@ nv50_priv_tp_trap(struct nv50_graph_priv *priv, int type, u32 ustatus_old, ustatus &= ~0x04030000; } if (ustatus && display) { - nv_error("%s - TP%d:", name, i); + nv_error(priv, "%s - TP%d:", name, i); nouveau_bitfield_print(nv50_mpc_traps, ustatus); pr_cont("\n"); ustatus = 0; -- cgit v1.2.3 From 95ca5b550ac255bf3cee108c123407785c47e3cc Mon Sep 17 00:00:00 2001 From: Emil Velikov Date: Wed, 12 Feb 2014 01:41:42 +0000 Subject: drm/nouveau/fb: use correct ram oclass for nv1a hardware commit 8613e7314ac254fdd67ed46192f021d76141e4c9 Author: Ben Skeggs Date: Mon Oct 21 08:50:25 2013 +1000 drm/nouveau/fb: remove ram oclass argument from base fb constructor Introduced a unfortunate regression by using nv10 ram oclass for nv1a hardware, causing corruption and eventually system lockup. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=74866 Reported-by: John F. Godfrey Signed-off-by: Emil Velikov Cc: stable@vger.kernel.org # 3.13+ Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/subdev/fb/nv1a.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv1a.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv1a.c index 9159a5ccee93..265d1253624a 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv1a.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv1a.c @@ -36,7 +36,7 @@ nv1a_fb_oclass = &(struct nv04_fb_impl) { .fini = _nouveau_fb_fini, }, .base.memtype = nv04_fb_memtype_valid, - .base.ram = &nv10_ram_oclass, + .base.ram = &nv1a_ram_oclass, .tile.regions = 8, .tile.init = nv10_fb_tile_init, .tile.fini = nv10_fb_tile_fini, -- cgit v1.2.3 From a7f1c1e65b68e1e1ab70898528d5977ed68a0a7d Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Thu, 13 Feb 2014 21:57:15 -0500 Subject: drm/nv50/disp: use correct register to determine DP display bpp Commit 0a0afd282f ("drm/nv50-/disp: move DP link training to core and train from supervisor") added code that uses the wrong register for computing the display bpp, used for bandwidth calculation. Adjust to use the same register as used by exec_clkcmp and nv50_disp_intr_unk20_2_dp. Reported-by: Torsten Wagner Reported-by: Michael Gulick Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=67628 Cc: stable@vger.kernel.org # 3.9+ Signed-off-by: Ilia Mirkin Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/engine/disp/nv50.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c index 940eaa5d8b9a..9ad722e4e087 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c @@ -1142,7 +1142,7 @@ nv50_disp_intr_unk20_2(struct nv50_disp_priv *priv, int head) if (conf != ~0) { if (outp.location == 0 && outp.type == DCB_OUTPUT_DP) { u32 soff = (ffs(outp.or) - 1) * 0x08; - u32 ctrl = nv_rd32(priv, 0x610798 + soff); + u32 ctrl = nv_rd32(priv, 0x610794 + soff); u32 datarate; switch ((ctrl & 0x000f0000) >> 16) { -- cgit v1.2.3 From 34d595081812da62b5357579267c4ab5eae64ac1 Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Sat, 15 Feb 2014 23:27:01 -0500 Subject: drm/nouveau: fix TTM_PL_TT memtype on pre-nv50 Commit a55409066 ("drm/nv50-: map TTM_PL_SYSTEM through a BAR for CPU access") made it possible to work with tiled memory. However mem->mm_node is not a nouveau_mem for AGP-using pre-NV50 cards, but a drm_mm_node, as created by the ttm_bo_manager_func. As such, extend the untiled check to explicitly include all pre-nv50 cards. Reported-by: Ronald Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=74613 Signed-off-by: Ilia Mirkin Tested-by: Ronald Uitermark Acked-by: Maarten Lankhorst Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_bo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 488686d490c0..4aed1714b9ab 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -1249,7 +1249,7 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) mem->bus.is_iomem = !dev->agp->cant_use_aperture; } #endif - if (!node->memtype) + if (nv_device(drm->device)->card_type < NV_50 || !node->memtype) /* untiled */ break; /* fallthrough, tiled memory */ -- cgit v1.2.3 From 92e3b40537707001d17bbad800d150ab04e53bf4 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 17 Feb 2014 20:33:01 -0500 Subject: jbd2: fix use after free in jbd2_journal_start_reserved() If start_this_handle() fails then it leads to a use after free of "handle". Signed-off-by: Dan Carpenter Signed-off-by: "Theodore Ts'o" Cc: stable@vger.kernel.org --- fs/jbd2/transaction.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index 8360674c85bc..60bb365f54a5 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c @@ -514,11 +514,13 @@ int jbd2_journal_start_reserved(handle_t *handle, unsigned int type, * similarly constrained call sites */ ret = start_this_handle(journal, handle, GFP_NOFS); - if (ret < 0) + if (ret < 0) { jbd2_journal_free_reserved(handle); + return ret; + } handle->h_type = type; handle->h_line_no = line_no; - return ret; + return 0; } EXPORT_SYMBOL(jbd2_journal_start_reserved); -- cgit v1.2.3 From 4913e0bf239dafee356bc7fab61806cc2518930c Mon Sep 17 00:00:00 2001 From: Hui Wang Date: Tue, 18 Feb 2014 10:56:46 +0800 Subject: ALSA: hda - add headset mic detect quirks for two Dell laptops When we plug a 3-ring headset on the Dell machines (Vendor ID: 0x10ec0255, Subsystem ID: 0x10280657; Vendor ID: 0x10ec0255, Subsystem ID: 0x1028065f), the headset mic can't be detected, after apply this patch, the headset mic can work well. BugLink: https://bugs.launchpad.net/bugs/1260303 Cc: David Henningsson Tested-by: Cyrus Lien Cc: stable@vger.kernel.org Signed-off-by: Hui Wang Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index a9a83b85517a..6eb903cc6237 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4308,7 +4308,9 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1028, 0x0651, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x0652, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), 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, 0x065f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x0662, "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 728a0cdf065b9f42d1ff25d94858f824bb0989ba Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Sun, 9 Feb 2014 18:43:18 +0900 Subject: drm/ttm: declare 'struct device' in ttm_page_alloc.h Declare 'struct device' explicitly in ttm_page_alloc.h as this file does not include any file declaring it. This removes the following warning: warning: 'struct device' declared inside parameter list Signed-off-by: Alexandre Courbot Reviewed-by: Thierry Reding --- include/drm/ttm/ttm_page_alloc.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/drm/ttm/ttm_page_alloc.h b/include/drm/ttm/ttm_page_alloc.h index d1f61bfe0ebe..49a828425fa2 100644 --- a/include/drm/ttm/ttm_page_alloc.h +++ b/include/drm/ttm/ttm_page_alloc.h @@ -29,6 +29,8 @@ #include #include +struct device; + /** * Initialize pool allocator. */ -- cgit v1.2.3 From 7a444d1f0b557c68f847050b33713ae7b56f25e7 Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Wed, 12 Feb 2014 22:46:25 +0900 Subject: drm/ttm: Fix memory leak in ttm_agp_backend.c This patch fix a memory leak found by cppcheck. [drivers/gpu/drm/ttm/ttm_agp_backend.c:129]: (error) Memory leak: agp_be Signed-off-by: Masanari Iida Reviewed-by: Thomas Hellstrom --- drivers/gpu/drm/ttm/ttm_agp_backend.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/ttm/ttm_agp_backend.c b/drivers/gpu/drm/ttm/ttm_agp_backend.c index 3302f99e7497..764be36397fd 100644 --- a/drivers/gpu/drm/ttm/ttm_agp_backend.c +++ b/drivers/gpu/drm/ttm/ttm_agp_backend.c @@ -126,6 +126,7 @@ struct ttm_tt *ttm_agp_tt_create(struct ttm_bo_device *bdev, agp_be->ttm.func = &ttm_agp_func; if (ttm_tt_init(&agp_be->ttm, bdev, size, page_flags, dummy_read_page)) { + kfree(agp_be); return NULL; } -- cgit v1.2.3 From b685f3b1744061aa9ad822548ba9c674de5be7c6 Mon Sep 17 00:00:00 2001 From: Tomasz Nowicki Date: Mon, 10 Feb 2014 14:00:11 +0100 Subject: ACPI / PCI: Fix memory leak in acpi_pci_irq_enable() acpi_pci_link_allocate_irq() can return negative gsi even if entry != NULL. For that case we have a memory leak, so free entry before returning from acpi_pci_irq_enable() for gsi < 0. Signed-off-by: Tomasz Nowicki Cc: All applicable [rjw: Subject and changelog] Signed-off-by: Rafael J. Wysocki --- drivers/acpi/pci_irq.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index 52d45ea2bc4f..361b40c10c3f 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -430,6 +430,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev) pin_name(pin)); } + kfree(entry); return 0; } -- cgit v1.2.3 From 67809f85d31eac600f6b28defa5386c9d2a13b1d Mon Sep 17 00:00:00 2001 From: Levente Kurusa Date: Tue, 18 Feb 2014 10:22:17 -0500 Subject: ahci: disable NCQ on Samsung pci-e SSDs on macbooks Samsung's pci-e SSDs with device ID 0x1600 which are found on some macbooks time out on NCQ commands. Blacklist NCQ on the device so that the affected machines can at least boot. Original-patch-by: Levente Kurusa Signed-off-by: Tejun Heo Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=60731 Cc: stable@vger.kernel.org --- drivers/ata/ahci.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index dc2756fb6f33..7df81576a489 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -61,6 +61,7 @@ enum board_ids { /* board IDs by feature in alphabetical order */ board_ahci, board_ahci_ign_iferr, + board_ahci_noncq, board_ahci_nosntf, board_ahci_yes_fbs, @@ -121,6 +122,13 @@ static const struct ata_port_info ahci_port_info[] = { .udma_mask = ATA_UDMA6, .port_ops = &ahci_ops, }, + [board_ahci_noncq] = { + AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ), + .flags = AHCI_FLAG_COMMON, + .pio_mask = ATA_PIO4, + .udma_mask = ATA_UDMA6, + .port_ops = &ahci_ops, + }, [board_ahci_nosntf] = { AHCI_HFLAGS (AHCI_HFLAG_NO_SNTF), .flags = AHCI_FLAG_COMMON, @@ -452,6 +460,12 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci }, /* ASM1061 */ { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci }, /* ASM1062 */ + /* + * Samsung SSDs found on some macbooks. NCQ times out. + * https://bugzilla.kernel.org/show_bug.cgi?id=60731 + */ + { PCI_VDEVICE(SAMSUNG, 0x1600), board_ahci_noncq }, + /* Enmotus */ { PCI_DEVICE(0x1c44, 0x8000), board_ahci }, -- cgit v1.2.3 From 30a70b026b4cde4e51989661ff3bd0ede08d9646 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 6 Feb 2014 21:25:37 +0200 Subject: usb: musb: fix obex in g_nokia.ko causing kernel panic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit phy_power_off() can, depending on the PHY being used, start I2C transactions which shouldn't happen in atomic context. Current call to phy_power_off() inside omap2430_runtime callbacks causes the following dump, as a fix, just don't power off the PHY in runtime. [ 18.606414] [] (__schedule+0x5c/0x50c) from [] (schedule_timeout+0x1f4/0x25c) [ 18.623809] [] (schedule_timeout+0x1f4/0x25c) from [] (wait_for_common+0xc8/0x1ac) [ 18.649291] [] (wait_for_common+0xc8/0x1ac) from [] (omap_i2c_xfer+0x338/0x488) [ 18.674499] [] (omap_i2c_xfer+0x338/0x488) from [] (__i2c_transfer+0x40/0x74) [ 18.692047] [] (__i2c_transfer+0x40/0x74) from [] (i2c_transfer+0x6c/0x90) [ 18.709320] [] (i2c_transfer+0x6c/0x90) from [] (regmap_i2c_read+0x48/0x68) [ 18.726715] [] (regmap_i2c_read+0x48/0x68) from [] (_regmap_raw_read+0x128/0x220) [ 18.752685] [] (_regmap_raw_read+0x128/0x220) from [] (regmap_raw_read+0xa0/0x130) [ 18.779052] [] (regmap_raw_read+0xa0/0x130) from [] (regmap_bulk_read+0xf8/0x16c) [ 18.805694] [] (regmap_bulk_read+0xf8/0x16c) from [] (twl_i2c_read+0xa4/0xe0) [ 18.823730] [] (twl_i2c_read+0xa4/0xe0) from [] (__twl4030_phy_power.isra.12+0x1c/0x58) [ 18.850921] [] (__twl4030_phy_power.isra.12+0x1c/0x58) from [] (twl4030_phy_power.part.14+0x80/0xc8) [ 18.879699] [] (twl4030_phy_power.part.14+0x80/0xc8) from [] (twl4030_set_suspend+0x54/0x1e8) [ 18.908325] [] (twl4030_set_suspend+0x54/0x1e8) from [] (omap2430_runtime_resume+0x5c/0x64) [ 18.937042] [] (omap2430_runtime_resume+0x5c/0x64) from [] (pm_generic_runtime_resume+0x2c/0x38) [ 18.966461] [] (pm_generic_runtime_resume+0x2c/0x38) from [] (__rpm_callback+0x54/0x80) [ 18.995117] [] (__rpm_callback+0x54/0x80) from [] (rpm_callback+0x40/0x74) [ 19.013610] [] (rpm_callback+0x40/0x74) from [] (rpm_resume+0x448/0x63c) [ 19.031921] [] (rpm_resume+0x448/0x63c) from [] (rpm_resume+0x364/0x63c) [ 19.050140] [] (rpm_resume+0x364/0x63c) from [] (__pm_runtime_resume+0x48/0x74) [ 19.077728] [] (__pm_runtime_resume+0x48/0x74) from [] (musb_gadget_pullup+0x1c/0xb4) [ 19.105895] [] (musb_gadget_pullup+0x1c/0xb4) from [] (usb_function_deactivate+0x54/0xa4 [libcomposite]) [ 19.135955] [] (usb_function_deactivate+0x54/0xa4 [libcomposite]) from [] (obex_bind+0x124/0x1d8 [usb_f_obex]) [ 19.166870] [] (obex_bind+0x124/0x1d8 [usb_f_obex]) from [] (usb_add_function+0x58/0xf4 [libcomposite]) [ 19.197143] [] (usb_add_function+0x58/0xf4 [libcomposite]) from [] (nokia_bind_config+0x204/0x250 [g_nokia]) [ 19.227905] [] (nokia_bind_config+0x204/0x250 [g_nokia]) from [] (usb_add_config+0x28/0xc0 [libcomposite]) [ 19.258483] [] (usb_add_config+0x28/0xc0 [libcomposite]) from [] (nokia_bind+0x9c/0x21c [g_nokia]) [ 19.288421] [] (nokia_bind+0x9c/0x21c [g_nokia]) from [] (composite_bind+0x74/0x180 [libcomposite]) [ 19.318420] [] (composite_bind+0x74/0x180 [libcomposite]) from [] (udc_bind_to_driver+0x2c/0xc4) [ 19.348114] [] (udc_bind_to_driver+0x2c/0xc4) from [] (usb_gadget_probe_driver+0x74/0x94) [ 19.377166] [] (usb_gadget_probe_driver+0x74/0x94) from [] (do_one_initcall+0x94/0x138) [ 19.406005] [] (do_one_initcall+0x94/0x138) from [] (load_module+0x113c/0x13c4) [ 19.434051] [] (load_module+0x113c/0x13c4) from [] (SyS_init_module+0xcc/0xec) [ 19.462127] [] (SyS_init_module+0xcc/0xec) from [] (ret_fast_syscall+0x0/0x30) [ 19.490753] Code: 0a00002e e1a00004 eb001438 e598300c (e5d3202c) [ 19.506805] ---[ end trace 060b62ec0d68a78b ]--- [ 19.523132] Kernel panic - not syncing: Fatal exception in interrupt dump is from 3.12-rc5 kernel Reported-by: Pali Rohár Signed-off-by: Ivaylo Dimitrov Signed-off-by: Felipe Balbi --- drivers/usb/musb/omap2430.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index 2a408cdaf7b2..8aa59a2c5eb2 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -659,7 +659,6 @@ static int omap2430_runtime_suspend(struct device *dev) OTG_INTERFSEL); omap2430_low_level_exit(musb); - phy_power_off(musb->phy); } return 0; @@ -674,7 +673,6 @@ static int omap2430_runtime_resume(struct device *dev) omap2430_low_level_init(musb); musb_writel(musb->mregs, OTG_INTERFSEL, musb->context.otg_interfsel); - phy_power_on(musb->phy); } return 0; -- cgit v1.2.3 From 3c4653c1f62ea5f1706084090a5a3bcf3402dc8f Mon Sep 17 00:00:00 2001 From: Ajay Kumar Gupta Date: Tue, 4 Feb 2014 15:28:06 +0200 Subject: usb: musb: host: Fix SuperSpeed hub enumeration Disables PING on status phase of control transfer. PING token is not mandatory in status phase of control transfer and so some high speed USB devices don't support it. If such devices are connected to MUSB then they would not respond to PING token causing delayed or failed enumeration. [Roger Q] Fixes enumeration issues with some Super-Speed USB hubs e.g. Dlink DUB-1340 Signed-off-by: Ajay Kumar Gupta Signed-off-by: Roger Quadros Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_host.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index ed455724017b..abb38c3833ef 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -1183,6 +1183,9 @@ irqreturn_t musb_h_ep0_irq(struct musb *musb) csr = MUSB_CSR0_H_STATUSPKT | MUSB_CSR0_TXPKTRDY; + /* disable ping token in status phase */ + csr |= MUSB_CSR0_H_DIS_PING; + /* flag status stage */ musb->ep0_stage = MUSB_EP0_STATUS; -- cgit v1.2.3 From 33f8d75f5771993ef16ed6bd56d7210f54226203 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Tue, 4 Feb 2014 15:29:33 +0200 Subject: usb: musb: core: Fix remote-wakeup resume During resume don't touch SUSPENDM/RESUME bits of POWER register while restoring controller context. These bits might be changed by the controller during resume operation and so will be different than what they were during suspend. e.g. SUSPENDM bit is set by software during USB global suspend but automatically cleared by the controller during remote wakeup or during resume. Setting this bit back while restoring context causes undesired behaviour. i.e. Babble interrupt is generated and USB is broken. Signed-off-by: Roger Quadros Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_core.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index fc192ad9cc6a..a501542dfeb5 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -2157,11 +2157,19 @@ static void musb_restore_context(struct musb *musb) void __iomem *musb_base = musb->mregs; void __iomem *ep_target_regs; void __iomem *epio; + u8 power; musb_writew(musb_base, MUSB_FRAME, musb->context.frame); musb_writeb(musb_base, MUSB_TESTMODE, musb->context.testmode); musb_write_ulpi_buscontrol(musb->mregs, musb->context.busctl); - musb_writeb(musb_base, MUSB_POWER, musb->context.power); + + /* Don't affect SUSPENDM/RESUME bits in POWER reg */ + power = musb_readb(musb_base, MUSB_POWER); + power &= MUSB_POWER_SUSPENDM | MUSB_POWER_RESUME; + musb->context.power &= ~(MUSB_POWER_SUSPENDM | MUSB_POWER_RESUME); + power |= musb->context.power; + musb_writeb(musb_base, MUSB_POWER, power); + musb_writew(musb_base, MUSB_INTRTXE, musb->intrtxe); musb_writew(musb_base, MUSB_INTRRXE, musb->intrrxe); musb_writeb(musb_base, MUSB_INTRUSBE, musb->context.intrusbe); -- cgit v1.2.3 From d246c9d55a90722fac9e7284201088eb62adcfc3 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 3 Feb 2014 13:59:38 +0530 Subject: usb: gadget: s3c2410_udc: Fix build error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pass value instead of address as expected by 'usb_ep_set_maxpacket_limit'. Fixes the following compilation error introduced by commit e117e742d310 ("usb: gadget: add "maxpacket_limit" field to struct usb_ep"): drivers/usb/gadget/s3c2410_udc.c: In function ‘s3c2410_udc_reinit’: drivers/usb/gadget/s3c2410_udc.c:1632:3: error: cannot take address of bit-field ‘maxpacket’ usb_ep_set_maxpacket_limit(&ep->ep, &ep->ep.maxpacket); Signed-off-by: Sachin Kamat Reviewed-by: Robert Baldyga Signed-off-by: Felipe Balbi --- drivers/usb/gadget/s3c2410_udc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c index f04b2c3154de..dd9678f85c58 100644 --- a/drivers/usb/gadget/s3c2410_udc.c +++ b/drivers/usb/gadget/s3c2410_udc.c @@ -1629,7 +1629,7 @@ static void s3c2410_udc_reinit(struct s3c2410_udc *dev) ep->ep.desc = NULL; ep->halted = 0; INIT_LIST_HEAD(&ep->queue); - usb_ep_set_maxpacket_limit(&ep->ep, &ep->ep.maxpacket); + usb_ep_set_maxpacket_limit(&ep->ep, ep->ep.maxpacket); } } -- cgit v1.2.3 From 30d361bf0f81ece8de42c5e0a4e560270ad72b65 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Wed, 15 Jan 2014 14:09:49 +0100 Subject: usb: musb: do not sleep in atomic context musb_port_reset() is called from musb_hub_control() which in turn holds a spinlock, so musb_port_reset() is not allowed to call msleep(). With the asynchronous work helpers in place, this is fortunately easy to fix by rescheduling the reset deassertion function to after the time when the wait period is finished. Note, however, that the MUSB_POWER_RESUME bit is only set on AM33xx processors under rare conditions such as when to another driver reporting an error during suspend. Hence, this didn't hit me yet in normal operation. Signed-off-by: Daniel Mack Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_core.c | 2 ++ drivers/usb/musb/musb_virthub.c | 20 +++++++++++++++----- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index a501542dfeb5..b49a5945c90c 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -477,6 +477,8 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, musb->port1_status |= (USB_PORT_STAT_C_SUSPEND << 16) | MUSB_PORT_STAT_RESUME; + musb->rh_timer = jiffies + + msecs_to_jiffies(20); schedule_delayed_work( &musb->finish_resume_work, 20); diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c index eb634433ef09..32f49e1efa9c 100644 --- a/drivers/usb/musb/musb_virthub.c +++ b/drivers/usb/musb/musb_virthub.c @@ -158,7 +158,6 @@ void musb_port_reset(struct musb *musb, bool do_reset) */ power = musb_readb(mbase, MUSB_POWER); if (do_reset) { - /* * If RESUME is set, we must make sure it stays minimum 20 ms. * Then we must clear RESUME and wait a bit to let musb start @@ -167,11 +166,22 @@ void musb_port_reset(struct musb *musb, bool do_reset) * detected". */ if (power & MUSB_POWER_RESUME) { - while (time_before(jiffies, musb->rh_timer)) - msleep(1); + long remain = (unsigned long) musb->rh_timer - jiffies; + + if (musb->rh_timer > 0 && remain > 0) { + /* take into account the minimum delay after resume */ + schedule_delayed_work( + &musb->deassert_reset_work, + jiffies_to_msecs(remain)); + return; + } + musb_writeb(mbase, MUSB_POWER, - power & ~MUSB_POWER_RESUME); - msleep(1); + power & ~MUSB_POWER_RESUME); + + /* Give the core 1 ms to clear MUSB_POWER_RESUME */ + schedule_delayed_work(&musb->deassert_reset_work, 1); + return; } power &= 0xf0; -- cgit v1.2.3 From 2d1f7af3d60dd09794e0738a915d272c6c27abc5 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 14 Jan 2014 15:36:29 -0800 Subject: usb: gadget: bcm63xx_udc: fix build failure on DMA channel code Commit 3dc6475 ("bcm63xx_enet: add support Broadcom BCM6345 Ethernet") changed the ENETDMA[CS] macros such that they are no longer macros, but actual register offset definitions. The bcm63xx_udc driver was not updated, and as a result, causes the following build error to pop up: CC drivers/usb/gadget/u_ether.o drivers/usb/gadget/bcm63xx_udc.c: In function 'iudma_write': drivers/usb/gadget/bcm63xx_udc.c:642:24: error: called object '0' is not a function drivers/usb/gadget/bcm63xx_udc.c: In function 'iudma_reset_channel': drivers/usb/gadget/bcm63xx_udc.c:698:46: error: called object '0' is not a function drivers/usb/gadget/bcm63xx_udc.c:700:49: error: called object '0' is not a function Fix this by updating usb_dmac_{read,write}l and usb_dmas_{read,write}l to take an extra channel argument, and use the channel width (ENETDMA_CHAN_WIDTH) to offset the register we want to access, hence doing again what the macro implicitely did for us. Cc: Kevin Cernekee Cc: Jonas Gorski Cc: Signed-off-by: Florian Fainelli Signed-off-by: Felipe Balbi --- drivers/usb/gadget/bcm63xx_udc.c | 58 ++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 26 deletions(-) diff --git a/drivers/usb/gadget/bcm63xx_udc.c b/drivers/usb/gadget/bcm63xx_udc.c index 888fbb43b338..e969eb809a85 100644 --- a/drivers/usb/gadget/bcm63xx_udc.c +++ b/drivers/usb/gadget/bcm63xx_udc.c @@ -360,24 +360,30 @@ static inline void usb_dma_writel(struct bcm63xx_udc *udc, u32 val, u32 off) bcm_writel(val, udc->iudma_regs + off); } -static inline u32 usb_dmac_readl(struct bcm63xx_udc *udc, u32 off) +static inline u32 usb_dmac_readl(struct bcm63xx_udc *udc, u32 off, int chan) { - return bcm_readl(udc->iudma_regs + IUDMA_DMAC_OFFSET + off); + return bcm_readl(udc->iudma_regs + IUDMA_DMAC_OFFSET + off + + (ENETDMA_CHAN_WIDTH * chan)); } -static inline void usb_dmac_writel(struct bcm63xx_udc *udc, u32 val, u32 off) +static inline void usb_dmac_writel(struct bcm63xx_udc *udc, u32 val, u32 off, + int chan) { - bcm_writel(val, udc->iudma_regs + IUDMA_DMAC_OFFSET + off); + bcm_writel(val, udc->iudma_regs + IUDMA_DMAC_OFFSET + off + + (ENETDMA_CHAN_WIDTH * chan)); } -static inline u32 usb_dmas_readl(struct bcm63xx_udc *udc, u32 off) +static inline u32 usb_dmas_readl(struct bcm63xx_udc *udc, u32 off, int chan) { - return bcm_readl(udc->iudma_regs + IUDMA_DMAS_OFFSET + off); + return bcm_readl(udc->iudma_regs + IUDMA_DMAS_OFFSET + off + + (ENETDMA_CHAN_WIDTH * chan)); } -static inline void usb_dmas_writel(struct bcm63xx_udc *udc, u32 val, u32 off) +static inline void usb_dmas_writel(struct bcm63xx_udc *udc, u32 val, u32 off, + int chan) { - bcm_writel(val, udc->iudma_regs + IUDMA_DMAS_OFFSET + off); + bcm_writel(val, udc->iudma_regs + IUDMA_DMAS_OFFSET + off + + (ENETDMA_CHAN_WIDTH * chan)); } static inline void set_clocks(struct bcm63xx_udc *udc, bool is_enabled) @@ -638,7 +644,7 @@ static void iudma_write(struct bcm63xx_udc *udc, struct iudma_ch *iudma, } while (!last_bd); usb_dmac_writel(udc, ENETDMAC_CHANCFG_EN_MASK, - ENETDMAC_CHANCFG_REG(iudma->ch_idx)); + ENETDMAC_CHANCFG_REG, iudma->ch_idx); } /** @@ -694,9 +700,9 @@ static void iudma_reset_channel(struct bcm63xx_udc *udc, struct iudma_ch *iudma) bcm63xx_fifo_reset_ep(udc, max(0, iudma->ep_num)); /* stop DMA, then wait for the hardware to wrap up */ - usb_dmac_writel(udc, 0, ENETDMAC_CHANCFG_REG(ch_idx)); + usb_dmac_writel(udc, 0, ENETDMAC_CHANCFG_REG, ch_idx); - while (usb_dmac_readl(udc, ENETDMAC_CHANCFG_REG(ch_idx)) & + while (usb_dmac_readl(udc, ENETDMAC_CHANCFG_REG, ch_idx) & ENETDMAC_CHANCFG_EN_MASK) { udelay(1); @@ -713,10 +719,10 @@ static void iudma_reset_channel(struct bcm63xx_udc *udc, struct iudma_ch *iudma) dev_warn(udc->dev, "forcibly halting IUDMA channel %d\n", ch_idx); usb_dmac_writel(udc, ENETDMAC_CHANCFG_BUFHALT_MASK, - ENETDMAC_CHANCFG_REG(ch_idx)); + ENETDMAC_CHANCFG_REG, ch_idx); } } - usb_dmac_writel(udc, ~0, ENETDMAC_IR_REG(ch_idx)); + usb_dmac_writel(udc, ~0, ENETDMAC_IR_REG, ch_idx); /* don't leave "live" HW-owned entries for the next guy to step on */ for (d = iudma->bd_ring; d <= iudma->end_bd; d++) @@ -728,11 +734,11 @@ static void iudma_reset_channel(struct bcm63xx_udc *udc, struct iudma_ch *iudma) /* set up IRQs, UBUS burst size, and BD base for this channel */ usb_dmac_writel(udc, ENETDMAC_IR_BUFDONE_MASK, - ENETDMAC_IRMASK_REG(ch_idx)); - usb_dmac_writel(udc, 8, ENETDMAC_MAXBURST_REG(ch_idx)); + ENETDMAC_IRMASK_REG, ch_idx); + usb_dmac_writel(udc, 8, ENETDMAC_MAXBURST_REG, ch_idx); - usb_dmas_writel(udc, iudma->bd_ring_dma, ENETDMAS_RSTART_REG(ch_idx)); - usb_dmas_writel(udc, 0, ENETDMAS_SRAM2_REG(ch_idx)); + usb_dmas_writel(udc, iudma->bd_ring_dma, ENETDMAS_RSTART_REG, ch_idx); + usb_dmas_writel(udc, 0, ENETDMAS_SRAM2_REG, ch_idx); } /** @@ -2035,7 +2041,7 @@ static irqreturn_t bcm63xx_udc_data_isr(int irq, void *dev_id) spin_lock(&udc->lock); usb_dmac_writel(udc, ENETDMAC_IR_BUFDONE_MASK, - ENETDMAC_IR_REG(iudma->ch_idx)); + ENETDMAC_IR_REG, iudma->ch_idx); bep = iudma->bep; rc = iudma_read(udc, iudma); @@ -2175,18 +2181,18 @@ static int bcm63xx_iudma_dbg_show(struct seq_file *s, void *p) seq_printf(s, " [ep%d]:\n", max_t(int, iudma_defaults[ch_idx].ep_num, 0)); seq_printf(s, " cfg: %08x; irqstat: %08x; irqmask: %08x; maxburst: %08x\n", - usb_dmac_readl(udc, ENETDMAC_CHANCFG_REG(ch_idx)), - usb_dmac_readl(udc, ENETDMAC_IR_REG(ch_idx)), - usb_dmac_readl(udc, ENETDMAC_IRMASK_REG(ch_idx)), - usb_dmac_readl(udc, ENETDMAC_MAXBURST_REG(ch_idx))); + usb_dmac_readl(udc, ENETDMAC_CHANCFG_REG, ch_idx), + usb_dmac_readl(udc, ENETDMAC_IR_REG, ch_idx), + usb_dmac_readl(udc, ENETDMAC_IRMASK_REG, ch_idx), + usb_dmac_readl(udc, ENETDMAC_MAXBURST_REG, ch_idx)); - sram2 = usb_dmas_readl(udc, ENETDMAS_SRAM2_REG(ch_idx)); - sram3 = usb_dmas_readl(udc, ENETDMAS_SRAM3_REG(ch_idx)); + sram2 = usb_dmas_readl(udc, ENETDMAS_SRAM2_REG, ch_idx); + sram3 = usb_dmas_readl(udc, ENETDMAS_SRAM3_REG, ch_idx); seq_printf(s, " base: %08x; index: %04x_%04x; desc: %04x_%04x %08x\n", - usb_dmas_readl(udc, ENETDMAS_RSTART_REG(ch_idx)), + usb_dmas_readl(udc, ENETDMAS_RSTART_REG, ch_idx), sram2 >> 16, sram2 & 0xffff, sram3 >> 16, sram3 & 0xffff, - usb_dmas_readl(udc, ENETDMAS_SRAM4_REG(ch_idx))); + usb_dmas_readl(udc, ENETDMAS_SRAM4_REG, ch_idx)); seq_printf(s, " desc: %d/%d used", iudma->n_bds_used, iudma->n_bds); -- cgit v1.2.3 From accb884b32e82f943340688c9cd30290531e73e0 Mon Sep 17 00:00:00 2001 From: Chao Bi Date: Wed, 12 Feb 2014 21:27:25 +0200 Subject: mei: set client's read_cb to NULL when flow control fails In mei_cl_read_start(), if it fails to send flow control request, it will release "cl->read_cb" but forget to set pointer to NULL, leaving "cl->read_cb" still pointing to random memory, next time this client is operated like mei_release(), it has chance to refer to this wrong pointer. Fixes: PANIC at kfree in mei_release() [228781.826904] Call Trace: [228781.829737] [] ? mei_cl_unlink+0x48/0xa0 [228781.835283] [] mei_io_cb_free+0x17/0x30 [228781.840733] [] mei_release+0xa8/0x180 [228781.845989] [] ? __fsnotify_parent+0xa0/0xf0 [228781.851925] [] __fput+0xd9/0x200 [228781.856696] [] ____fput+0xd/0x10 [228781.861467] [] task_work_run+0x81/0xb0 [228781.866821] [] do_exit+0x283/0xa00 [228781.871786] [] ? kprobe_flush_task+0x66/0xc0 [228781.877722] [] ? __dequeue_signal+0x18/0x1a0 [228781.883657] [] ? dequeue_signal+0x32/0x190 [228781.889397] [] do_group_exit+0x34/0xa0 [228781.894750] [] get_signal_to_deliver+0x206/0x610 [228781.901075] [] do_signal+0x38/0x100 [228781.906136] [] ? mei_read+0x42c/0x4e0 [228781.911393] [] ? wake_up_bit+0x30/0x30 [228781.916745] [] ? mei_poll+0x120/0x120 [228781.922001] [] ? vfs_read+0x89/0x160 [228781.927158] [] ? mei_poll+0x120/0x120 [228781.932414] [] ? fget_light+0x44/0xe0 [228781.937670] [] ? SyS_read+0x68/0x80 [228781.942730] [] do_notify_resume+0x55/0x70 [228781.948376] [] work_notifysig+0x29/0x30 [228781.953827] [] ? bad_area+0x5/0x3e Cc: stable # 3.9+ Signed-off-by: Chao Bi Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/client.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index 9b809cfc2899..89a557972d1b 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -666,7 +666,6 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length) goto err; cb->fop_type = MEI_FOP_READ; - cl->read_cb = cb; if (dev->hbuf_is_ready) { dev->hbuf_is_ready = false; if (mei_hbm_cl_flow_control_req(dev, cl)) { @@ -678,6 +677,9 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length) } else { list_add_tail(&cb->list, &dev->ctrl_wr_list.list); } + + cl->read_cb = cb; + return rets; err: mei_io_cb_free(cb); -- cgit v1.2.3 From 7d5a33b071d19314c452ca5252ecd990eb0dd696 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 3 Feb 2014 15:53:25 -0500 Subject: drm/radeon: unify bpc handling We were already storing the bpc (bits per color) information in radeon_crtc, so just use that everywhere rather than calculating it everywhere we use it. This also allows us to change it in one place if we ever want to override it. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/atombios_crtc.c | 2 +- drivers/gpu/drm/radeon/atombios_encoders.c | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index a9338c85630f..f0d409d846f2 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -559,7 +559,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, u32 adjusted_clock = mode->clock; int encoder_mode = atombios_get_encoder_mode(encoder); u32 dp_clock = mode->clock; - int bpc = radeon_get_monitor_bpc(connector); + int bpc = radeon_crtc->bpc; bool is_duallink = radeon_dig_monitor_is_duallink(encoder, mode->clock); /* reset the pll flags */ diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index a42d61571f49..2cec2ab02f80 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c @@ -464,11 +464,12 @@ atombios_tv_setup(struct drm_encoder *encoder, int action) static u8 radeon_atom_get_bpc(struct drm_encoder *encoder) { - struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); int bpc = 8; - if (connector) - bpc = radeon_get_monitor_bpc(connector); + if (encoder->crtc) { + struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); + bpc = radeon_crtc->bpc; + } switch (bpc) { case 0: -- cgit v1.2.3 From 8716ed4e7bed4e4c7e3f37940e950ddc0362f450 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 12 Feb 2014 12:48:23 -0500 Subject: drm: add DRM_CAPs for cursor size Some hardware may not support standard 64x64 cursors. Add a drm cap to query the cursor size from the kernel. Some examples include radeon CIK parts (128x128 cursors) and armada (32x64 or 64x32). This allows things like device specific ddxes to remove asics specific logic and also allows xf86-video-modesetting to work properly with hw cursors on this hardware. Default to 64 if the driver doesn't specify a size. Signed-off-by: Alex Deucher Reviewed-by: Rob Clark --- drivers/gpu/drm/drm_ioctl.c | 12 ++++++++++++ include/drm/drm_crtc.h | 3 +++ include/uapi/drm/drm.h | 2 ++ 3 files changed, 17 insertions(+) diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index dffc836144cc..f4dc9b7a3831 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -296,6 +296,18 @@ int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_priv) case DRM_CAP_ASYNC_PAGE_FLIP: req->value = dev->mode_config.async_page_flip; break; + case DRM_CAP_CURSOR_WIDTH: + if (dev->mode_config.cursor_width) + req->value = dev->mode_config.cursor_width; + else + req->value = 64; + break; + case DRM_CAP_CURSOR_HEIGHT: + if (dev->mode_config.cursor_height) + req->value = dev->mode_config.cursor_height; + else + req->value = 64; + break; default: return -EINVAL; } diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 71727b6210ae..8f3dee097579 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -907,6 +907,9 @@ struct drm_mode_config { /* whether async page flip is supported or not */ bool async_page_flip; + + /* cursor size */ + uint32_t cursor_width, cursor_height; }; #define obj_to_crtc(x) container_of(x, struct drm_crtc, base) diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h index 3c9a833992e8..b06c8ed68707 100644 --- a/include/uapi/drm/drm.h +++ b/include/uapi/drm/drm.h @@ -619,6 +619,8 @@ struct drm_gem_open { #define DRM_PRIME_CAP_EXPORT 0x2 #define DRM_CAP_TIMESTAMP_MONOTONIC 0x6 #define DRM_CAP_ASYNC_PAGE_FLIP 0x7 +#define DRM_CAP_CURSOR_WIDTH 0x8 +#define DRM_CAP_CURSOR_HEIGHT 0x9 /** DRM_IOCTL_GET_CAP ioctl argument type */ struct drm_get_cap { -- cgit v1.2.3 From bea61c59d799c23591da2b29444ecc649a8682cf Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 12 Feb 2014 12:56:53 -0500 Subject: drm/radeon: fill in DRM_CAPs for cursor size CIK parts are 128x128, older parts are 64x64. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_display.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index d680608f6f5b..fbd8b930f2be 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -571,6 +571,8 @@ static void radeon_crtc_init(struct drm_device *dev, int index) radeon_crtc->max_cursor_width = CURSOR_WIDTH; radeon_crtc->max_cursor_height = CURSOR_HEIGHT; } + dev->mode_config.cursor_width = radeon_crtc->max_cursor_width; + dev->mode_config.cursor_height = radeon_crtc->max_cursor_height; #if 0 radeon_crtc->mode_set.crtc = &radeon_crtc->base; -- cgit v1.2.3 From 78b035101999d8d071781778c019c387dc8bebb2 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 17 Feb 2014 12:50:13 -0500 Subject: drm/radeon/dpm: reduce r7xx vblank mclk threshold to 200 Most laptops seems to have a vblank period of less than 300 and mclk switching works fine. Drop the quirk and set the default threshold to 200. bug: https://bugzilla.kernel.org/show_bug.cgi?id=70701 Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/rv770_dpm.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/drivers/gpu/drm/radeon/rv770_dpm.c b/drivers/gpu/drm/radeon/rv770_dpm.c index 5b2ea8ac0731..b5f63f5e22a3 100644 --- a/drivers/gpu/drm/radeon/rv770_dpm.c +++ b/drivers/gpu/drm/radeon/rv770_dpm.c @@ -2526,14 +2526,7 @@ u32 rv770_dpm_get_mclk(struct radeon_device *rdev, bool low) bool rv770_dpm_vblank_too_short(struct radeon_device *rdev) { u32 vblank_time = r600_dpm_get_vblank_time(rdev); - u32 switch_limit = 300; - - /* quirks */ - /* ASUS K70AF */ - if ((rdev->pdev->device == 0x9553) && - (rdev->pdev->subsystem_vendor == 0x1043) && - (rdev->pdev->subsystem_device == 0x1c42)) - switch_limit = 200; + u32 switch_limit = 200; /* 300 */ /* RV770 */ /* mclk switching doesn't seem to work reliably on desktop RV770s */ -- cgit v1.2.3 From 6d8ea7de3f5035610f3bfacbe35e7b71ad1e4663 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 17 Feb 2014 14:16:31 -0500 Subject: drm/radeon: fix display tiling setup on SI Apply the same logic as CI to SI for setting up the display tiling parameters. The num banks may vary per tiling index just like CI. Bugs: https://bugs.freedesktop.org/show_bug.cgi?id=71488 https://bugs.freedesktop.org/show_bug.cgi?id=73946 https://bugs.freedesktop.org/show_bug.cgi?id=74927 Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/atombios_crtc.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index f0d409d846f2..0d19f4f94d5a 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -1176,7 +1176,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, evergreen_tiling_fields(tiling_flags, &bankw, &bankh, &mtaspect, &tile_split); /* Set NUM_BANKS. */ - if (rdev->family >= CHIP_BONAIRE) { + if (rdev->family >= CHIP_TAHITI) { unsigned tileb, index, num_banks, tile_split_bytes; /* Calculate the macrotile mode index. */ @@ -1194,13 +1194,14 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, return -EINVAL; } - num_banks = (rdev->config.cik.macrotile_mode_array[index] >> 6) & 0x3; + if (rdev->family >= CHIP_BONAIRE) + num_banks = (rdev->config.cik.macrotile_mode_array[index] >> 6) & 0x3; + else + num_banks = (rdev->config.si.tile_mode_array[index] >> 20) & 0x3; fb_format |= EVERGREEN_GRPH_NUM_BANKS(num_banks); } else { - /* SI and older. */ - if (rdev->family >= CHIP_TAHITI) - tmp = rdev->config.si.tile_config; - else if (rdev->family >= CHIP_CAYMAN) + /* NI and older. */ + if (rdev->family >= CHIP_CAYMAN) tmp = rdev->config.cayman.tile_config; else tmp = rdev->config.evergreen.tile_config; -- cgit v1.2.3 From ebc54ffe1c57067d4700f970ef88f26e18b48690 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 17 Feb 2014 23:01:30 +0300 Subject: drm/radeon: delete a stray tab Static checkers complain that probably curly braces were intended here, but actually it makes more sense to remove the extra tab. Signed-off-by: Dan Carpenter Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/evergreen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index f2b9e21ce4da..5623e7542d99 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -1680,7 +1680,7 @@ bool evergreen_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd) case RADEON_HPD_6: if (RREG32(DC_HPD6_INT_STATUS) & DC_HPDx_SENSE) connected = true; - break; + break; default: break; } -- cgit v1.2.3 From 8f53492f86f9ca66bc762be98f0a9fce9bcb319a Mon Sep 17 00:00:00 2001 From: Christian König Date: Tue, 18 Feb 2014 11:37:20 +0100 Subject: drm/radeon: fix CP semaphores on CIK MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The CP semaphore queue on CIK has a bug that triggers if uncompleted waits use the same address while a signal is still pending. Work around this by using different addresses for each sync. Signed-off-by: Christian König Cc: stable@vger.kernel.org Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon.h | 4 +++- drivers/gpu/drm/radeon/radeon_ring.c | 2 +- drivers/gpu/drm/radeon/radeon_semaphore.c | 19 ++++++++++++++++--- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 4a8ac1cd6b4c..024db37b1832 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -135,6 +135,9 @@ extern int radeon_hard_reset; /* R600+ */ #define R600_RING_TYPE_UVD_INDEX 5 +/* number of hw syncs before falling back on blocking */ +#define RADEON_NUM_SYNCS 4 + /* hardcode those limit for now */ #define RADEON_VA_IB_OFFSET (1 << 20) #define RADEON_VA_RESERVED_SIZE (8 << 20) @@ -554,7 +557,6 @@ int radeon_mode_dumb_mmap(struct drm_file *filp, /* * Semaphores. */ -/* everything here is constant */ struct radeon_semaphore { struct radeon_sa_bo *sa_bo; signed waiters; diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c index 1b783f0e6d3a..15e44a7281ab 100644 --- a/drivers/gpu/drm/radeon/radeon_ring.c +++ b/drivers/gpu/drm/radeon/radeon_ring.c @@ -139,7 +139,7 @@ int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib, } /* 64 dwords should be enough for fence too */ - r = radeon_ring_lock(rdev, ring, 64 + RADEON_NUM_RINGS * 8); + r = radeon_ring_lock(rdev, ring, 64 + RADEON_NUM_SYNCS * 8); if (r) { dev_err(rdev->dev, "scheduling IB failed (%d).\n", r); return r; diff --git a/drivers/gpu/drm/radeon/radeon_semaphore.c b/drivers/gpu/drm/radeon/radeon_semaphore.c index 2b42aa1914f2..9006b32d5eed 100644 --- a/drivers/gpu/drm/radeon/radeon_semaphore.c +++ b/drivers/gpu/drm/radeon/radeon_semaphore.c @@ -34,14 +34,15 @@ int radeon_semaphore_create(struct radeon_device *rdev, struct radeon_semaphore **semaphore) { + uint32_t *cpu_addr; int i, r; *semaphore = kmalloc(sizeof(struct radeon_semaphore), GFP_KERNEL); if (*semaphore == NULL) { return -ENOMEM; } - r = radeon_sa_bo_new(rdev, &rdev->ring_tmp_bo, - &(*semaphore)->sa_bo, 8, 8, true); + r = radeon_sa_bo_new(rdev, &rdev->ring_tmp_bo, &(*semaphore)->sa_bo, + 8 * RADEON_NUM_SYNCS, 8, true); if (r) { kfree(*semaphore); *semaphore = NULL; @@ -49,7 +50,10 @@ int radeon_semaphore_create(struct radeon_device *rdev, } (*semaphore)->waiters = 0; (*semaphore)->gpu_addr = radeon_sa_bo_gpu_addr((*semaphore)->sa_bo); - *((uint64_t*)radeon_sa_bo_cpu_addr((*semaphore)->sa_bo)) = 0; + + cpu_addr = radeon_sa_bo_cpu_addr((*semaphore)->sa_bo); + for (i = 0; i < RADEON_NUM_SYNCS; ++i) + cpu_addr[i] = 0; for (i = 0; i < RADEON_NUM_RINGS; ++i) (*semaphore)->sync_to[i] = NULL; @@ -125,6 +129,7 @@ int radeon_semaphore_sync_rings(struct radeon_device *rdev, struct radeon_semaphore *semaphore, int ring) { + unsigned count = 0; int i, r; for (i = 0; i < RADEON_NUM_RINGS; ++i) { @@ -140,6 +145,12 @@ int radeon_semaphore_sync_rings(struct radeon_device *rdev, return -EINVAL; } + if (++count > RADEON_NUM_SYNCS) { + /* not enough room, wait manually */ + radeon_fence_wait_locked(fence); + continue; + } + /* allocate enough space for sync command */ r = radeon_ring_alloc(rdev, &rdev->ring[i], 16); if (r) { @@ -164,6 +175,8 @@ int radeon_semaphore_sync_rings(struct radeon_device *rdev, radeon_ring_commit(rdev, &rdev->ring[i]); radeon_fence_note_sync(fence, ring); + + semaphore->gpu_addr += 8; } return 0; -- cgit v1.2.3 From 5b43c3cd07981619dbdb1fb935ef705a3e80955f Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 18 Feb 2014 10:14:46 -0500 Subject: drm/radeon/si: fix typo in dpm sq ramping setup inverted logic. Noticed-by: Sylvain BERTRAND Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/si_dpm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c index eafb0e6bc67e..0a2f5b4bca43 100644 --- a/drivers/gpu/drm/radeon/si_dpm.c +++ b/drivers/gpu/drm/radeon/si_dpm.c @@ -2395,7 +2395,7 @@ static int si_populate_sq_ramping_values(struct radeon_device *rdev, if (SISLANDS_DPM2_SQ_RAMP_STI_SIZE > (STI_SIZE_MASK >> STI_SIZE_SHIFT)) enable_sq_ramping = false; - if (SISLANDS_DPM2_SQ_RAMP_LTI_RATIO <= (LTI_RATIO_MASK >> LTI_RATIO_SHIFT)) + if (SISLANDS_DPM2_SQ_RAMP_LTI_RATIO > (LTI_RATIO_MASK >> LTI_RATIO_SHIFT)) enable_sq_ramping = false; for (i = 0; i < state->performance_level_count; i++) { -- cgit v1.2.3 From 21ed4947fdfe19b60a27b84162622e56439c7937 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 18 Feb 2014 10:16:28 -0500 Subject: drm/radeon/ni: fix typo in dpm sq ramping setup inverted logic. Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/ni_dpm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/ni_dpm.c b/drivers/gpu/drm/radeon/ni_dpm.c index 1217fbcbdcca..ca814276b075 100644 --- a/drivers/gpu/drm/radeon/ni_dpm.c +++ b/drivers/gpu/drm/radeon/ni_dpm.c @@ -2588,7 +2588,7 @@ static int ni_populate_sq_ramping_values(struct radeon_device *rdev, if (NISLANDS_DPM2_SQ_RAMP_STI_SIZE > (STI_SIZE_MASK >> STI_SIZE_SHIFT)) enable_sq_ramping = false; - if (NISLANDS_DPM2_SQ_RAMP_LTI_RATIO <= (LTI_RATIO_MASK >> LTI_RATIO_SHIFT)) + if (NISLANDS_DPM2_SQ_RAMP_LTI_RATIO > (LTI_RATIO_MASK >> LTI_RATIO_SHIFT)) enable_sq_ramping = false; for (i = 0; i < state->performance_level_count; i++) { -- cgit v1.2.3 From 3e8d6d85adedc59115a564c0a54b36e42087c4d9 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 13 Feb 2014 15:49:17 -0500 Subject: USB: EHCI: add delay during suspend to prevent erroneous wakeups High-speed USB connections revert back to full-speed signalling when the device goes into suspend. This takes several milliseconds, and during that time it's not possible to tell reliably whether the device has been disconnected. On some platforms, the Wake-On-Disconnect circuitry gets confused during this intermediate state. It generates a false wakeup signal, which can prevent the controller from going to sleep. To avoid this problem, this patch adds a 5-ms delay to the ehci_bus_suspend() routine if any ports have to switch over to full-speed signalling. (Actually, the delay was already present for devices using a particular kind of PHY power management; the patch merely causes the delay to be used more widely.) Signed-off-by: Alan Stern Reviewed-by: Peter Chen CC: Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-hub.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 47b858fc50b2..7ae0c4d51741 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -238,6 +238,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) int port; int mask; int changed; + bool fs_idle_delay; ehci_dbg(ehci, "suspend root hub\n"); @@ -272,6 +273,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) ehci->bus_suspended = 0; ehci->owned_ports = 0; changed = 0; + fs_idle_delay = false; port = HCS_N_PORTS(ehci->hcs_params); while (port--) { u32 __iomem *reg = &ehci->regs->port_status [port]; @@ -300,16 +302,32 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) } if (t1 != t2) { + /* + * On some controllers, Wake-On-Disconnect will + * generate false wakeup signals until the bus + * switches over to full-speed idle. For their + * sake, add a delay if we need one. + */ + if ((t2 & PORT_WKDISC_E) && + ehci_port_speed(ehci, t2) == + USB_PORT_STAT_HIGH_SPEED) + fs_idle_delay = true; ehci_writel(ehci, t2, reg); changed = 1; } } + spin_unlock_irq(&ehci->lock); + + if ((changed && ehci->has_tdi_phy_lpm) || fs_idle_delay) { + /* + * Wait for HCD to enter low-power mode or for the bus + * to switch to full-speed idle. + */ + usleep_range(5000, 5500); + } if (changed && ehci->has_tdi_phy_lpm) { - spin_unlock_irq(&ehci->lock); - msleep(5); /* 5 ms for HCD to enter low-power mode */ spin_lock_irq(&ehci->lock); - port = HCS_N_PORTS(ehci->hcs_params); while (port--) { u32 __iomem *hostpc_reg = &ehci->regs->hostpc[port]; @@ -322,8 +340,8 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) port, (t3 & HOSTPC_PHCD) ? "succeeded" : "failed"); } + spin_unlock_irq(&ehci->lock); } - spin_unlock_irq(&ehci->lock); /* Apparently some devices need a >= 1-uframe delay here */ if (ehci->bus_suspended) -- cgit v1.2.3 From 12df84d4a80278a5b1abfec3206795291da52fc9 Mon Sep 17 00:00:00 2001 From: Aleksander Morgado Date: Wed, 12 Feb 2014 16:04:45 +0100 Subject: USB: serial: option: blacklist interface 4 for Cinterion PHS8 and PXS8 This interface is to be handled by the qmi_wwan driver. CC: Hans-Christoph Schemmel CC: Christian Schmiedl CC: Nicolaus Colberg CC: David McCullough Signed-off-by: Aleksander Morgado Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 216d20affba8..68fc9fe65936 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -1526,7 +1526,8 @@ static const struct usb_device_id option_ids[] = { /* Cinterion */ { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_E) }, { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_P) }, - { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PH8) }, + { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PH8), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_AHXX) }, { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PLXX), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, -- cgit v1.2.3 From 73926db33b277c4c371edbc9fe9093adc9b2803b Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Fri, 14 Feb 2014 20:49:46 +0100 Subject: usb: musb: do not sleep in atomic context musb_port_reset() is called from musb_hub_control() which in turn holds a spinlock, so musb_port_reset() is not allowed to call msleep(). With the asynchronous work helpers in place, this is fortunately easy to fix by rescheduling the reset deassertion function to after the time when the wait period is finished. Note, however, that the MUSB_POWER_RESUME bit is only set on AM33xx processors under rare conditions such as when to another driver reporting an error during suspend. Hence, this didn't hit me yet in normal operation. Signed-off-by: Daniel Mack Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_core.c | 2 ++ drivers/usb/musb/musb_virthub.c | 20 +++++++++++++++----- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index fc192ad9cc6a..1a377cac4d4c 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -477,6 +477,8 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, musb->port1_status |= (USB_PORT_STAT_C_SUSPEND << 16) | MUSB_PORT_STAT_RESUME; + musb->rh_timer = jiffies + + msecs_to_jiffies(20); schedule_delayed_work( &musb->finish_resume_work, 20); diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c index eb634433ef09..32f49e1efa9c 100644 --- a/drivers/usb/musb/musb_virthub.c +++ b/drivers/usb/musb/musb_virthub.c @@ -158,7 +158,6 @@ void musb_port_reset(struct musb *musb, bool do_reset) */ power = musb_readb(mbase, MUSB_POWER); if (do_reset) { - /* * If RESUME is set, we must make sure it stays minimum 20 ms. * Then we must clear RESUME and wait a bit to let musb start @@ -167,11 +166,22 @@ void musb_port_reset(struct musb *musb, bool do_reset) * detected". */ if (power & MUSB_POWER_RESUME) { - while (time_before(jiffies, musb->rh_timer)) - msleep(1); + long remain = (unsigned long) musb->rh_timer - jiffies; + + if (musb->rh_timer > 0 && remain > 0) { + /* take into account the minimum delay after resume */ + schedule_delayed_work( + &musb->deassert_reset_work, + jiffies_to_msecs(remain)); + return; + } + musb_writeb(mbase, MUSB_POWER, - power & ~MUSB_POWER_RESUME); - msleep(1); + power & ~MUSB_POWER_RESUME); + + /* Give the core 1 ms to clear MUSB_POWER_RESUME */ + schedule_delayed_work(&musb->deassert_reset_work, 1); + return; } power &= 0xf0; -- cgit v1.2.3 From f2dece4499eea534c7c92e49fbf6a9bb0510cbcf Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Fri, 14 Feb 2014 20:49:47 +0100 Subject: usb: musb: correct use of schedule_delayed_work() schedule_delayed_work() takes the delay in jiffies, not msecs. Fix the caller sites in musb. This bug caused regressions with the cleanups that went in for 3.14 (8ed1fb790ea: "usb: musb: finish suspend/reset work independently from musb_hub_control()"). Signed-off-by: Daniel Mack Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_core.c | 3 ++- drivers/usb/musb/musb_virthub.c | 12 +++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 1a377cac4d4c..93eba53f6ce8 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -480,7 +480,8 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, musb->rh_timer = jiffies + msecs_to_jiffies(20); schedule_delayed_work( - &musb->finish_resume_work, 20); + &musb->finish_resume_work, + msecs_to_jiffies(20)); musb->xceiv->state = OTG_STATE_A_HOST; musb->is_active = 1; diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c index 32f49e1efa9c..e2d2d8c9891b 100644 --- a/drivers/usb/musb/musb_virthub.c +++ b/drivers/usb/musb/musb_virthub.c @@ -135,7 +135,8 @@ void musb_port_suspend(struct musb *musb, bool do_suspend) /* later, GetPortStatus will stop RESUME signaling */ musb->port1_status |= MUSB_PORT_STAT_RESUME; - schedule_delayed_work(&musb->finish_resume_work, 20); + schedule_delayed_work(&musb->finish_resume_work, + msecs_to_jiffies(20)); } } @@ -171,8 +172,7 @@ void musb_port_reset(struct musb *musb, bool do_reset) if (musb->rh_timer > 0 && remain > 0) { /* take into account the minimum delay after resume */ schedule_delayed_work( - &musb->deassert_reset_work, - jiffies_to_msecs(remain)); + &musb->deassert_reset_work, remain); return; } @@ -180,7 +180,8 @@ void musb_port_reset(struct musb *musb, bool do_reset) power & ~MUSB_POWER_RESUME); /* Give the core 1 ms to clear MUSB_POWER_RESUME */ - schedule_delayed_work(&musb->deassert_reset_work, 1); + schedule_delayed_work(&musb->deassert_reset_work, + msecs_to_jiffies(1)); return; } @@ -190,7 +191,8 @@ void musb_port_reset(struct musb *musb, bool do_reset) musb->port1_status |= USB_PORT_STAT_RESET; musb->port1_status &= ~USB_PORT_STAT_ENABLE; - schedule_delayed_work(&musb->deassert_reset_work, 50); + schedule_delayed_work(&musb->deassert_reset_work, + msecs_to_jiffies(50)); } else { dev_dbg(musb->controller, "root port reset stopped\n"); musb_writeb(mbase, MUSB_POWER, -- cgit v1.2.3 From 06c304e88907cac9b1f5b21727ff268bf1705bb5 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 17 Feb 2014 14:29:21 +0530 Subject: phy,phy-bcm-kona-usb2.c: Add dependency on HAS_IOMEM On archs like S390 or um this driver cannot build nor work. Make it depend on HAS_IOMEM to bypass build failures. drivers/phy/phy-bcm-kona-usb2.c:114: undefined reference to `devm_ioremap_resource' Signed-off-by: Richard Weinberger Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Greg Kroah-Hartman --- drivers/phy/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index afa2354f6600..79e3c7045d8d 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -61,6 +61,7 @@ config PHY_EXYNOS_DP_VIDEO config BCM_KONA_USB2_PHY tristate "Broadcom Kona USB2 PHY Driver" depends on GENERIC_PHY + depends on HAS_IOMEM help Enable this to support the Broadcom Kona USB 2.0 PHY. -- cgit v1.2.3 From f40037fd3677ae240978f469cc4155bf3ca7c076 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 17 Feb 2014 14:29:22 +0530 Subject: phy-core: phy_get: Leave error logging to the caller In various cases errors may be expected, ie probe-deferral or a call to phy_get from a driver where the use of a phy is optional. Rather then adding all sort of complicated checks for this, and/or adding special functions like devm_phy_get_optional, simply don't log an error, and let deciding if get_phy returning an error really should result in a dev_err up to the caller. Signed-off-by: Hans de Goede Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Greg Kroah-Hartman --- drivers/phy/phy-core.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c index 5f5b0f4be5be..b3555535a8c6 100644 --- a/drivers/phy/phy-core.c +++ b/drivers/phy/phy-core.c @@ -404,17 +404,11 @@ struct phy *phy_get(struct device *dev, const char *string) index = of_property_match_string(dev->of_node, "phy-names", string); phy = of_phy_get(dev, index); - if (IS_ERR(phy)) { - dev_err(dev, "unable to find phy\n"); - return phy; - } } else { phy = phy_lookup(dev, string); - if (IS_ERR(phy)) { - dev_err(dev, "unable to find phy\n"); - return phy; - } } + if (IS_ERR(phy)) + return phy; if (!try_module_get(phy->ops->owner)) return ERR_PTR(-EPROBE_DEFER); -- cgit v1.2.3 From 767a1b5d6ec4ac5335dde17100880347ed154ce2 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 17 Feb 2014 14:29:23 +0530 Subject: phy-core: Don't propagate -ENOSUPP from phy_pm_runtime_get_sync to caller The phy-core allows phy_init and phy_power_on to be called multiple times, but before this patch -ENOSUPP from phy_pm_runtime_get_sync would be propagated to the caller for the 2nd and later calls. Signed-off-by: Hans de Goede Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Greg Kroah-Hartman --- drivers/phy/phy-core.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c index b3555535a8c6..6c738376daff 100644 --- a/drivers/phy/phy-core.c +++ b/drivers/phy/phy-core.c @@ -176,6 +176,8 @@ int phy_init(struct phy *phy) dev_err(&phy->dev, "phy init failed --> %d\n", ret); goto out; } + } else { + ret = 0; /* Override possible ret == -ENOTSUPP */ } ++phy->init_count; @@ -232,6 +234,8 @@ int phy_power_on(struct phy *phy) dev_err(&phy->dev, "phy poweron failed --> %d\n", ret); goto out; } + } else { + ret = 0; /* Override possible ret == -ENOTSUPP */ } ++phy->power_count; mutex_unlock(&phy->mutex); -- cgit v1.2.3 From b51fbf9fb0c32c1a98f824ab5d6f59b17b39ef9e Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 17 Feb 2014 14:29:24 +0530 Subject: phy-core: Don't allow building phy-core as a module include/phy/phy.h has stub code in there for when building without the phy-core enabled. This is useful for generic drivers such as ahci-platform, ehci-platoform and ohci-platform which have support for driving an optional phy passed to them through the devicetree. Since on some boards this phy functionality is not needed, being able to disable the phy subsystem without needing a lot of #ifdef magic in the driver using it is quite useful. However this breaks when the module using the phy subsystem is build-in and the phy-core is not, which leads to the build failing with missing symbol errors in the linking stage of the zImage. Which leads to gems such as this being added to the Kconfig for achi_platform: depends on GENERIC_PHY || !GENERIC_PHY Rather then duplicating this code in a lot of places using the phy-core, I believe it is better to simply not allow the phy-core to be built as a module. The phy core is quite small and has no external dependencies, so always building it in when enabling it should not be an issue. Signed-off-by: Hans de Goede Acked-by: Roger Quadros Acked-by: Andrew Lunn Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Greg Kroah-Hartman --- drivers/phy/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index 79e3c7045d8d..c7a551c2d5f1 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -5,7 +5,7 @@ menu "PHY Subsystem" config GENERIC_PHY - tristate "PHY Core" + bool "PHY Core" help Generic PHY support. -- cgit v1.2.3 From 64fe1891696cdef4603b5f2d7c3a846bce8cf42b Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Mon, 17 Feb 2014 14:29:25 +0530 Subject: phy: let phy_provider_register be the last step in registering PHY Registering phy_provider before creating the PHY can result in PHY callbacks being invoked which will lead to aborts. In order to avoid this invoke phy_provider_register after phy_create and phy_set_drvdata. Reported-by: Felipe Balbi Signed-off-by: Kishon Vijay Abraham I Acked-by: Sylwester Nawrocki Signed-off-by: Greg Kroah-Hartman --- drivers/phy/phy-exynos-dp-video.c | 8 ++++---- drivers/phy/phy-exynos-mipi-video.c | 10 +++++----- drivers/phy/phy-mvebu-sata.c | 10 +++++----- drivers/phy/phy-omap-usb2.c | 10 +++++----- drivers/phy/phy-twl4030-usb.c | 10 +++++----- 5 files changed, 24 insertions(+), 24 deletions(-) diff --git a/drivers/phy/phy-exynos-dp-video.c b/drivers/phy/phy-exynos-dp-video.c index 1dbe6ce7b2ce..0786fef842e7 100644 --- a/drivers/phy/phy-exynos-dp-video.c +++ b/drivers/phy/phy-exynos-dp-video.c @@ -76,10 +76,6 @@ static int exynos_dp_video_phy_probe(struct platform_device *pdev) if (IS_ERR(state->regs)) return PTR_ERR(state->regs); - phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); - if (IS_ERR(phy_provider)) - return PTR_ERR(phy_provider); - phy = devm_phy_create(dev, &exynos_dp_video_phy_ops, NULL); if (IS_ERR(phy)) { dev_err(dev, "failed to create Display Port PHY\n"); @@ -87,6 +83,10 @@ static int exynos_dp_video_phy_probe(struct platform_device *pdev) } phy_set_drvdata(phy, state); + phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); + if (IS_ERR(phy_provider)) + return PTR_ERR(phy_provider); + return 0; } diff --git a/drivers/phy/phy-exynos-mipi-video.c b/drivers/phy/phy-exynos-mipi-video.c index 0c5efab11af1..7f139326a642 100644 --- a/drivers/phy/phy-exynos-mipi-video.c +++ b/drivers/phy/phy-exynos-mipi-video.c @@ -134,11 +134,6 @@ static int exynos_mipi_video_phy_probe(struct platform_device *pdev) dev_set_drvdata(dev, state); spin_lock_init(&state->slock); - phy_provider = devm_of_phy_provider_register(dev, - exynos_mipi_video_phy_xlate); - if (IS_ERR(phy_provider)) - return PTR_ERR(phy_provider); - for (i = 0; i < EXYNOS_MIPI_PHYS_NUM; i++) { struct phy *phy = devm_phy_create(dev, &exynos_mipi_video_phy_ops, NULL); @@ -152,6 +147,11 @@ static int exynos_mipi_video_phy_probe(struct platform_device *pdev) phy_set_drvdata(phy, &state->phys[i]); } + phy_provider = devm_of_phy_provider_register(dev, + exynos_mipi_video_phy_xlate); + if (IS_ERR(phy_provider)) + return PTR_ERR(phy_provider); + return 0; } diff --git a/drivers/phy/phy-mvebu-sata.c b/drivers/phy/phy-mvebu-sata.c index d43786f62437..d70ecd6a1b3f 100644 --- a/drivers/phy/phy-mvebu-sata.c +++ b/drivers/phy/phy-mvebu-sata.c @@ -99,17 +99,17 @@ static int phy_mvebu_sata_probe(struct platform_device *pdev) if (IS_ERR(priv->clk)) return PTR_ERR(priv->clk); - phy_provider = devm_of_phy_provider_register(&pdev->dev, - of_phy_simple_xlate); - if (IS_ERR(phy_provider)) - return PTR_ERR(phy_provider); - phy = devm_phy_create(&pdev->dev, &phy_mvebu_sata_ops, NULL); if (IS_ERR(phy)) return PTR_ERR(phy); phy_set_drvdata(phy, priv); + phy_provider = devm_of_phy_provider_register(&pdev->dev, + of_phy_simple_xlate); + if (IS_ERR(phy_provider)) + return PTR_ERR(phy_provider); + /* The boot loader may of left it on. Turn it off. */ phy_mvebu_sata_power_off(phy); diff --git a/drivers/phy/phy-omap-usb2.c b/drivers/phy/phy-omap-usb2.c index bfc5c337f99a..7699752fba11 100644 --- a/drivers/phy/phy-omap-usb2.c +++ b/drivers/phy/phy-omap-usb2.c @@ -177,11 +177,6 @@ static int omap_usb2_probe(struct platform_device *pdev) phy->phy.otg = otg; phy->phy.type = USB_PHY_TYPE_USB2; - phy_provider = devm_of_phy_provider_register(phy->dev, - of_phy_simple_xlate); - if (IS_ERR(phy_provider)) - return PTR_ERR(phy_provider); - control_node = of_parse_phandle(node, "ctrl-module", 0); if (!control_node) { dev_err(&pdev->dev, "Failed to get control device phandle\n"); @@ -214,6 +209,11 @@ static int omap_usb2_probe(struct platform_device *pdev) phy_set_drvdata(generic_phy, phy); + phy_provider = devm_of_phy_provider_register(phy->dev, + of_phy_simple_xlate); + if (IS_ERR(phy_provider)) + return PTR_ERR(phy_provider); + phy->wkupclk = devm_clk_get(phy->dev, "usb_phy_cm_clk32k"); if (IS_ERR(phy->wkupclk)) { dev_err(&pdev->dev, "unable to get usb_phy_cm_clk32k\n"); diff --git a/drivers/phy/phy-twl4030-usb.c b/drivers/phy/phy-twl4030-usb.c index daf65e68aaab..c3ace1db8136 100644 --- a/drivers/phy/phy-twl4030-usb.c +++ b/drivers/phy/phy-twl4030-usb.c @@ -695,11 +695,6 @@ static int twl4030_usb_probe(struct platform_device *pdev) otg->set_host = twl4030_set_host; otg->set_peripheral = twl4030_set_peripheral; - phy_provider = devm_of_phy_provider_register(twl->dev, - of_phy_simple_xlate); - if (IS_ERR(phy_provider)) - return PTR_ERR(phy_provider); - phy = devm_phy_create(twl->dev, &ops, init_data); if (IS_ERR(phy)) { dev_dbg(&pdev->dev, "Failed to create PHY\n"); @@ -708,6 +703,11 @@ static int twl4030_usb_probe(struct platform_device *pdev) phy_set_drvdata(phy, twl); + phy_provider = devm_of_phy_provider_register(twl->dev, + of_phy_simple_xlate); + if (IS_ERR(phy_provider)) + return PTR_ERR(phy_provider); + /* init spinlock for workqueue */ spin_lock_init(&twl->lock); -- cgit v1.2.3 From ffd5939381c609056b33b7585fb05a77b4c695f3 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Mon, 17 Feb 2014 12:11:11 +0100 Subject: net: sctp: fix sctp_connectx abi for ia32 emulation/compat mode SCTP's sctp_connectx() abi breaks for 64bit kernels compiled with 32bit emulation (e.g. ia32 emulation or x86_x32). Due to internal usage of 'struct sctp_getaddrs_old' which includes a struct sockaddr pointer, sizeof(param) check will always fail in kernel as the structure in 64bit kernel space is 4bytes larger than for user binaries compiled in 32bit mode. Thus, applications making use of sctp_connectx() won't be able to run under such circumstances. Introduce a compat interface in the kernel to deal with such situations by using a 'struct compat_sctp_getaddrs_old' structure where user data is copied into it, and then sucessively transformed into a 'struct sctp_getaddrs_old' structure with the help of compat_ptr(). That fixes sctp_connectx() abi without any changes needed in user space, and lets the SCTP test suite pass when compiled in 32bit and run on 64bit kernels. Fixes: f9c67811ebc0 ("sctp: Fix regression introduced by new sctp_connectx api") Signed-off-by: Daniel Borkmann Acked-by: Neil Horman Acked-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/socket.c | 41 ++++++++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 7075ac847fde..981aaf8b6ace 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -64,6 +64,7 @@ #include #include #include +#include #include #include @@ -1368,11 +1369,19 @@ static int sctp_setsockopt_connectx(struct sock *sk, /* * New (hopefully final) interface for the API. * We use the sctp_getaddrs_old structure so that use-space library - * can avoid any unnecessary allocations. The only defferent part + * can avoid any unnecessary allocations. The only different part * is that we store the actual length of the address buffer into the - * addrs_num structure member. That way we can re-use the existing + * addrs_num structure member. That way we can re-use the existing * code. */ +#ifdef CONFIG_COMPAT +struct compat_sctp_getaddrs_old { + sctp_assoc_t assoc_id; + s32 addr_num; + compat_uptr_t addrs; /* struct sockaddr * */ +}; +#endif + static int sctp_getsockopt_connectx3(struct sock *sk, int len, char __user *optval, int __user *optlen) @@ -1381,16 +1390,30 @@ static int sctp_getsockopt_connectx3(struct sock *sk, int len, sctp_assoc_t assoc_id = 0; int err = 0; - if (len < sizeof(param)) - return -EINVAL; +#ifdef CONFIG_COMPAT + if (is_compat_task()) { + struct compat_sctp_getaddrs_old param32; - if (copy_from_user(¶m, optval, sizeof(param))) - return -EFAULT; + if (len < sizeof(param32)) + return -EINVAL; + if (copy_from_user(¶m32, optval, sizeof(param32))) + return -EFAULT; - err = __sctp_setsockopt_connectx(sk, - (struct sockaddr __user *)param.addrs, - param.addr_num, &assoc_id); + param.assoc_id = param32.assoc_id; + param.addr_num = param32.addr_num; + param.addrs = compat_ptr(param32.addrs); + } else +#endif + { + if (len < sizeof(param)) + return -EINVAL; + if (copy_from_user(¶m, optval, sizeof(param))) + return -EFAULT; + } + err = __sctp_setsockopt_connectx(sk, (struct sockaddr __user *) + param.addrs, param.addr_num, + &assoc_id); if (err == 0 || err == -EINPROGRESS) { if (copy_to_user(optval, &assoc_id, sizeof(assoc_id))) return -EFAULT; -- cgit v1.2.3 From 5bdfff96c69a4d5ab9c49e60abf9e070ecd2acbb Mon Sep 17 00:00:00 2001 From: Lai Jiangshan Date: Sat, 15 Feb 2014 22:02:28 +0800 Subject: workqueue: ensure @task is valid across kthread_stop() When a kworker should die, the kworkre is notified through WORKER_DIE flag instead of kthread_should_stop(). This, IIRC, is primarily to keep the test synchronized inside worker_pool lock. WORKER_DIE is first set while holding pool->lock, the lock is dropped and kthread_stop() is called. Unfortunately, this means that there's a slight chance that the target kworker may see WORKER_DIE before kthread_stop() finishes and exits and frees the target task before or during kthread_stop(). Fix it by pinning the target task before setting WORKER_DIE and putting it after kthread_stop() is done. tj: Improved patch description and comment. Moved pinning above WORKER_DIE for better signify what it's protecting. CC: stable@vger.kernel.org Signed-off-by: Lai Jiangshan Signed-off-by: Tejun Heo --- kernel/workqueue.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 82ef9f3b7473..193e977a10ea 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -1851,6 +1851,12 @@ static void destroy_worker(struct worker *worker) if (worker->flags & WORKER_IDLE) pool->nr_idle--; + /* + * Once WORKER_DIE is set, the kworker may destroy itself at any + * point. Pin to ensure the task stays until we're done with it. + */ + get_task_struct(worker->task); + list_del_init(&worker->entry); worker->flags |= WORKER_DIE; @@ -1859,6 +1865,7 @@ static void destroy_worker(struct worker *worker) spin_unlock_irq(&pool->lock); kthread_stop(worker->task); + put_task_struct(worker->task); kfree(worker); spin_lock_irq(&pool->lock); -- cgit v1.2.3 From 71c5498eed06b5ac4325a525ed83aeed3e9a250a Mon Sep 17 00:00:00 2001 From: Kevin Hao Date: Tue, 18 Feb 2014 15:57:29 +0800 Subject: Revert "of: search the best compatible match first in __of_match_node()" This reverts commit 06b29e76a74b2373e6f8b5a7938b3630b9ae98b2. As pointed out by Grant Likely, we should also take the type and name into account when searching the best compatible match. That means the match with compatible, type and name should be better than the match just with the same compatible string. So revert this and we will implement another method to find the best match entry. Signed-off-by: Kevin Hao Signed-off-by: Grant Likely --- drivers/of/base.c | 43 +------------------------------------------ 1 file changed, 1 insertion(+), 42 deletions(-) diff --git a/drivers/of/base.c b/drivers/of/base.c index 10b51106c854..ba195fbce4c6 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -730,49 +730,13 @@ out: } EXPORT_SYMBOL(of_find_node_with_property); -static const struct of_device_id * -of_match_compatible(const struct of_device_id *matches, - const struct device_node *node) -{ - const char *cp; - int cplen, l; - const struct of_device_id *m; - - cp = __of_get_property(node, "compatible", &cplen); - while (cp && (cplen > 0)) { - m = matches; - while (m->name[0] || m->type[0] || m->compatible[0]) { - /* Only match for the entries without type and name */ - if (m->name[0] || m->type[0] || - of_compat_cmp(m->compatible, cp, - strlen(m->compatible))) - m++; - else - return m; - } - - /* Get node's next compatible string */ - l = strlen(cp) + 1; - cp += l; - cplen -= l; - } - - return NULL; -} - static const struct of_device_id *__of_match_node(const struct of_device_id *matches, const struct device_node *node) { - const struct of_device_id *m; - if (!matches) return NULL; - m = of_match_compatible(matches, node); - if (m) - return m; - while (matches->name[0] || matches->type[0] || matches->compatible[0]) { int match = 1; if (matches->name[0]) @@ -796,12 +760,7 @@ const struct of_device_id *__of_match_node(const struct of_device_id *matches, * @matches: array of of device match structures to search in * @node: the of device structure to match against * - * Low level utility function used by device matching. We have two ways - * of matching: - * - Try to find the best compatible match by comparing each compatible - * string of device node with all the given matches respectively. - * - If the above method failed, then try to match the compatible by using - * __of_device_is_compatible() besides the match in type and name. + * Low level utility function used by device matching. */ const struct of_device_id *of_match_node(const struct of_device_id *matches, const struct device_node *node) -- cgit v1.2.3 From d7cf0c34af067555737193b6c1aa7abaa677f29c Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 18 Feb 2014 15:20:51 +0300 Subject: af_packet: remove a stray tab in packet_set_ring() At first glance it looks like there is a missing curly brace but actually the code works the same either way. I have adjusted the indenting but left the code the same. Signed-off-by: Dan Carpenter Acked-by: Daniel Borkmann Signed-off-by: David S. Miller --- net/packet/af_packet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index b5dc1168f98a..48a6a93db296 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -3804,7 +3804,7 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, */ if (!tx_ring) init_prb_bdqc(po, rb, pg_vec, req_u, tx_ring); - break; + break; default: break; } -- cgit v1.2.3 From ce5eaf023a231ebd313ecc7e0b33278513d8ad80 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 18 Feb 2014 12:55:42 +0000 Subject: NET: fec: only enable napi if we are successful If napi is left enabled after a failed attempt to bring the interface up, we BUG: fec 2188000.ethernet eth0: no PHY, assuming direct connection to switch libphy: PHY fixed-0:00 not found fec 2188000.ethernet eth0: could not attach to PHY ------------[ cut here ]------------ kernel BUG at include/linux/netdevice.h:502! Internal error: Oops - BUG: 0 [#1] SMP ARM ... PC is at fec_enet_open+0x4d0/0x500 LR is at __dev_open+0xa4/0xfc Only enable napi after we are past all the failure paths. Signed-off-by: Russell King Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fec_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index d4782b42401b..903362a7b584 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -1778,8 +1778,6 @@ fec_enet_open(struct net_device *ndev) struct fec_enet_private *fep = netdev_priv(ndev); int ret; - napi_enable(&fep->napi); - /* I should reset the ring buffers here, but I don't yet know * a simple way to do that. */ @@ -1794,6 +1792,8 @@ fec_enet_open(struct net_device *ndev) fec_enet_free_buffers(ndev); return ret; } + + napi_enable(&fep->napi); phy_start(fep->phy_dev); netif_start_queue(ndev); fep->opened = 1; -- cgit v1.2.3 From 4b636b535d55f89077691e737930a615422113d6 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Tue, 18 Feb 2014 14:18:11 +0100 Subject: net: ethernet: update dependency and help text of mvneta With the introduction of the support for Armada 375 and Armada 38x, the hidden Kconfig option MACH_ARMADA_370_XP is being renamed to MACH_MVEBU_V7. Therefore, the dependency that was used for the mvneta driver can no longer work. This commit replaces this dependency by a dependency on PLAT_ORION, which is used similarly for the mv643xx_eth driver. In addition to this, it takes this opportunity to adjust the description and help text to indicate that the driver can is also used for Armada 38x. Note that Armada 375 cannot use this driver as it has a completely different networking unit, which will require a separate driver. Signed-off-by: Thomas Petazzoni Acked-by: Jason Cooper Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/Kconfig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/marvell/Kconfig b/drivers/net/ethernet/marvell/Kconfig index 6300fd27f2db..68e6a6613e9a 100644 --- a/drivers/net/ethernet/marvell/Kconfig +++ b/drivers/net/ethernet/marvell/Kconfig @@ -43,12 +43,12 @@ config MVMDIO This driver is used by the MV643XX_ETH and MVNETA drivers. config MVNETA - tristate "Marvell Armada 370/XP network interface support" - depends on MACH_ARMADA_370_XP + tristate "Marvell Armada 370/38x/XP network interface support" + depends on PLAT_ORION select MVMDIO ---help--- This driver supports the network interface units in the - Marvell ARMADA XP and ARMADA 370 SoC family. + Marvell ARMADA XP, ARMADA 370 and ARMADA 38x SoC family. Note that this driver is distinct from the mv643xx_eth driver, which should be used for the older Marvell SoCs -- cgit v1.2.3 From f15c586d1d9d99b04712d2b2eeee31ab29db77ff Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 18 Feb 2014 12:16:58 +0000 Subject: of_mdio: fix phy interrupt passing The of_mdiobus_register_phy() is not setting phy->irq thus causing some drivers to incorrectly assume that the PHY does not have an IRQ associated with it. Not only do some drivers report no IRQ they do not install an interrupt handler for the PHY. Simplify the code setting irq and set the phy->irq at the same time so that we cover the following issues, which should cover all the cases the code will find: - Set phy->irq if node has irq property and mdio->irq is NULL - Set phy->irq if node has no irq and mdio->irq is not NULL - Leave phy->irq as PHY_POLL default if none of the above This fixes the issue: net eth0: attached PHY 1 (IRQ -1) to driver Micrel KSZ8041RNLI to the correct: net eth0: attached PHY 1 (IRQ 416) to driver Micrel KSZ8041RNLI Signed-off-by: Ben Dooks Signed-off-by: David S. Miller --- drivers/of/of_mdio.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c index 495faccba763..5b3c24f3cde5 100644 --- a/drivers/of/of_mdio.c +++ b/drivers/of/of_mdio.c @@ -48,7 +48,7 @@ static int of_mdiobus_register_phy(struct mii_bus *mdio, struct device_node *chi { struct phy_device *phy; bool is_c45; - int rc, prev_irq; + int rc; u32 max_speed = 0; is_c45 = of_device_is_compatible(child, @@ -58,12 +58,14 @@ static int of_mdiobus_register_phy(struct mii_bus *mdio, struct device_node *chi if (!phy || IS_ERR(phy)) return 1; - if (mdio->irq) { - prev_irq = mdio->irq[addr]; - mdio->irq[addr] = - irq_of_parse_and_map(child, 0); - if (!mdio->irq[addr]) - mdio->irq[addr] = prev_irq; + rc = irq_of_parse_and_map(child, 0); + if (rc > 0) { + phy->irq = rc; + if (mdio->irq) + mdio->irq[addr] = rc; + } else { + if (mdio->irq) + phy->irq = mdio->irq[addr]; } /* Associate the OF node with the device structure so it -- cgit v1.2.3 From 22f08ad9721d4d1a92061b60026144627a60d644 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 18 Feb 2014 09:47:49 -0800 Subject: MAINTAINERS: add entry for the PHY library The PHY library has been subject to some changes, new drivers and DT interactions over the past few months. Add myself as a maintainer for the core PHY library parts and drivers. Make sure the PHY library entry also covers the Device Tree files which have a close interaction with the MDIO bus, PHY connection and Ethernet PHY mode parsing. CC: Grant Likely CC: Shaohui Xie CC: Andy Fleming Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- MAINTAINERS | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 091b50edaf35..c8b3975ee56e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3324,6 +3324,17 @@ S: Maintained F: include/linux/netfilter_bridge/ F: net/bridge/ +ETHERNET PHY LIBRARY +M: Florian Fainelli +L: netdev@vger.kernel.org +S: Maintained +F: include/linux/phy.h +F: include/linux/phy_fixed.h +F: drivers/net/phy/ +F: Documentation/networking/phy.txt +F: drivers/of/of_mdio.c +F: drivers/of/of_net.c + EXT2 FILE SYSTEM M: Jan Kara L: linux-ext4@vger.kernel.org -- cgit v1.2.3 From 532de3fc72adc2a6525c4d53c07bf81e1732083d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 13 Feb 2014 13:29:31 -0500 Subject: cgroup: update cgroup_enable_task_cg_lists() to grab siglock Currently, there's nothing preventing cgroup_enable_task_cg_lists() from missing set PF_EXITING and race against cgroup_exit(). Depending on the timing, cgroup_exit() may finish with the task still linked on css_set leading to list corruption. Fix it by grabbing siglock in cgroup_enable_task_cg_lists() so that PF_EXITING is guaranteed to be visible. This whole on-demand cg_list optimization is extremely fragile and has ample possibility to lead to bugs which can cause things like once-a-year oops during boot. I'm wondering whether the better approach would be just adding "cgroup_disable=all" handling which disables the whole cgroup rather than tempting fate with this on-demand craziness. Signed-off-by: Tejun Heo Acked-by: Li Zefan Cc: stable@vger.kernel.org --- kernel/cgroup.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 68d87103b493..105f273b6f86 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -2905,9 +2905,14 @@ static void cgroup_enable_task_cg_lists(void) * We should check if the process is exiting, otherwise * it will race with cgroup_exit() in that the list * entry won't be deleted though the process has exited. + * Do it while holding siglock so that we don't end up + * racing against cgroup_exit(). */ + spin_lock_irq(&p->sighand->siglock); if (!(p->flags & PF_EXITING) && list_empty(&p->cg_list)) list_add(&p->cg_list, &task_css_set(p)->tasks); + spin_unlock_irq(&p->sighand->siglock); + task_unlock(p); } while_each_thread(g, p); read_unlock(&tasklist_lock); -- cgit v1.2.3 From 500a91571f0a5d0d3242d83802ea2fd1faccc66e Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Sat, 15 Feb 2014 17:54:06 -0800 Subject: hwmon: (max1668) Fix writing the minimum temperature When trying to set the minimum temperature, the driver was erroneously writing the maximum temperature into the chip. Signed-off-by: Guenter Roeck Cc: stable@vger.kernel.org # v3.2+ Reviewed-by: Jean Delvare --- drivers/hwmon/max1668.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hwmon/max1668.c b/drivers/hwmon/max1668.c index a7626358c95d..029b65e6c589 100644 --- a/drivers/hwmon/max1668.c +++ b/drivers/hwmon/max1668.c @@ -243,7 +243,7 @@ static ssize_t set_temp_min(struct device *dev, data->temp_min[index] = clamp_val(temp/1000, -128, 127); if (i2c_smbus_write_byte_data(client, MAX1668_REG_LIML_WR(index), - data->temp_max[index])) + data->temp_min[index])) count = -EIO; mutex_unlock(&data->update_lock); -- cgit v1.2.3 From 763fbff2bef5d5db5a993b54c29c841432e056ec Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Thu, 13 Feb 2014 17:18:26 -0700 Subject: ARM: tegra: fix RTC0 alias for Cardhu This alias entry was evidently cut/paste from a different board, and not correctly updated to match Cardhu. Fix this. Fixes: 553c0a200e20 ("ARM: tegra: set up /aliases entries for RTCs") Signed-off-by: Stephen Warren Signed-off-by: Olof Johansson --- arch/arm/boot/dts/tegra30-cardhu.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/tegra30-cardhu.dtsi b/arch/arm/boot/dts/tegra30-cardhu.dtsi index 9104224124ee..1e156d9d0506 100644 --- a/arch/arm/boot/dts/tegra30-cardhu.dtsi +++ b/arch/arm/boot/dts/tegra30-cardhu.dtsi @@ -28,7 +28,7 @@ compatible = "nvidia,cardhu", "nvidia,tegra30"; aliases { - rtc0 = "/i2c@7000d000/tps6586x@34"; + rtc0 = "/i2c@7000d000/tps65911@2d"; rtc1 = "/rtc@7000e000"; }; -- cgit v1.2.3 From 28a9f3b078c545064dcf4b46d2c6917554d1642e Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Tue, 18 Feb 2014 10:35:05 +0800 Subject: ARM: imx6: build pm-imx6q.c independently of CONFIG_PM When building a kernel image with only CONFIG_CPU_IDLE but no CONFIG_PM, we will get the following link error. LD init/built-in.o arch/arm/mach-imx/built-in.o: In function `imx6q_enter_wait': platform-spi_imx.c:(.text+0x25c0): undefined reference to `imx6q_set_lpm' platform-spi_imx.c:(.text+0x25d4): undefined reference to `imx6q_set_lpm' arch/arm/mach-imx/built-in.o: In function `imx6q_cpuidle_init': platform-spi_imx.c:(.init.text+0x75d4): undefined reference to `imx6q_set_chicken_bit' make[1]: *** [vmlinux] Error 1 Since pm-imx6q.c has been a collection of library functions that access CCM low-power registers used by not only suspend but also cpuidle and other drivers, let's build pm-imx6q.c independently of CONFIG_PM to fix above error. Reported-by: Lucas Stach Signed-off-by: Shawn Guo Cc: stable@vger.kernel.org Acked-by: Christian Gmeiner Signed-off-by: Olof Johansson --- arch/arm/mach-imx/Makefile | 2 -- arch/arm/mach-imx/common.h | 4 +--- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index befcaf5d0574..ec419649320f 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile @@ -101,11 +101,9 @@ obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o obj-$(CONFIG_SOC_IMX6Q) += clk-imx6q.o mach-imx6q.o obj-$(CONFIG_SOC_IMX6SL) += clk-imx6sl.o mach-imx6sl.o -ifeq ($(CONFIG_PM),y) obj-$(CONFIG_SOC_IMX6Q) += pm-imx6q.o headsmp.o # i.MX6SL reuses i.MX6Q code obj-$(CONFIG_SOC_IMX6SL) += pm-imx6q.o headsmp.o -endif # i.MX5 based machines obj-$(CONFIG_MACH_MX51_BABBAGE) += mach-mx51_babbage.o diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h index 59c3b9b26bb4..baf439dc22d8 100644 --- a/arch/arm/mach-imx/common.h +++ b/arch/arm/mach-imx/common.h @@ -144,13 +144,11 @@ void imx6q_set_chicken_bit(void); void imx_cpu_die(unsigned int cpu); int imx_cpu_kill(unsigned int cpu); -#ifdef CONFIG_PM void imx6q_pm_init(void); void imx6q_pm_set_ccm_base(void __iomem *base); +#ifdef CONFIG_PM void imx5_pm_init(void); #else -static inline void imx6q_pm_init(void) {} -static inline void imx6q_pm_set_ccm_base(void __iomem *base) {} static inline void imx5_pm_init(void) {} #endif -- cgit v1.2.3 From 6964d91db2becfe80658f50584d264708ca7f49e Mon Sep 17 00:00:00 2001 From: viresh kumar Date: Mon, 17 Feb 2014 14:52:11 +0530 Subject: cpufreq: remove sysfs link when a cpu != policy->cpu, is removed Commit 42f921a (cpufreq: remove sysfs files for CPUs which failed to come back after resume) tried to do this but missed this piece of code to fix. Currently we are getting this on suspend/resume: ------------[ cut here ]------------ WARNING: CPU: 0 PID: 877 at fs/sysfs/dir.c:52 sysfs_warn_dup+0x68/0x84() sysfs: cannot create duplicate filename '/devices/system/cpu/cpu1/cpufreq' Modules linked in: brcmfmac brcmutil CPU: 0 PID: 877 Comm: test-rtc-resume Not tainted 3.14.0-rc2-00259-g9398a10cd964 #12 [] (unwind_backtrace) from [] (show_stack+0x10/0x14) [] (show_stack) from [] (dump_stack+0x80/0xcc) [] (dump_stack) from [] (warn_slowpath_common+0x64/0x88) [] (warn_slowpath_common) from [] (warn_slowpath_fmt+0x30/0x40) [] (warn_slowpath_fmt) from [] (sysfs_warn_dup+0x68/0x84) [] (sysfs_warn_dup) from [] (sysfs_do_create_link_sd+0xb0/0xb8) [] (sysfs_do_create_link_sd) from [] (__cpufreq_add_dev.isra.27+0x2a8/0x814) [] (__cpufreq_add_dev.isra.27) from [] (cpufreq_cpu_callback+0x70/0x8c) [] (cpufreq_cpu_callback) from [] (notifier_call_chain+0x44/0x84) [] (notifier_call_chain) from [] (__cpu_notify+0x28/0x44) [] (__cpu_notify) from [] (_cpu_up+0xf0/0x140) [] (_cpu_up) from [] (enable_nonboot_cpus+0x68/0xb0) [] (enable_nonboot_cpus) from [] (suspend_devices_and_enter+0x198/0x2dc) [] (suspend_devices_and_enter) from [] (pm_suspend+0x174/0x1e8) [] (pm_suspend) from [] (state_store+0x6c/0xbc) [] (state_store) from [] (kobj_attr_store+0x14/0x20) [] (kobj_attr_store) from [] (sysfs_kf_write+0x44/0x48) [] (sysfs_kf_write) from [] (kernfs_fop_write+0xb4/0x14c) [] (kernfs_fop_write) from [] (vfs_write+0xa8/0x180) [] (vfs_write) from [] (SyS_write+0x3c/0x70) [] (SyS_write) from [] (ret_fast_syscall+0x0/0x30) ---[ end trace 76969904b614c18f ]--- Fix this by removing sysfs link for cpufreq directory when cpu removed isn't policy->cpu. Revamps: 42f921a (cpufreq: remove sysfs files for CPUs which failed to come back after resume) Reported-and-tested-by: Stephen Warren Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 08ca8c9f41cd..cb003a6b72c8 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1323,8 +1323,7 @@ static int __cpufreq_remove_dev_prepare(struct device *dev, up_read(&policy->rwsem); if (cpu != policy->cpu) { - if (!frozen) - sysfs_remove_link(&dev->kobj, "cpufreq"); + sysfs_remove_link(&dev->kobj, "cpufreq"); } else if (cpus > 1) { new_cpu = cpufreq_nominate_new_policy_cpu(policy, cpu); if (new_cpu >= 0) { -- cgit v1.2.3 From c3274763bfc3bf1ececa269ed6e6c4d7ec1c3e5e Mon Sep 17 00:00:00 2001 From: "Srivatsa S. Bhat" Date: Mon, 17 Feb 2014 16:18:21 +0530 Subject: cpufreq: powernow-k8: Initialize per-cpu data-structures properly The powernow-k8 driver maintains a per-cpu data-structure called powernow_data that is used to perform the frequency transitions. It initializes this data structure only for the policy->cpu. So, accesses to this data structure by other CPUs results in various problems because they would have been uninitialized. Specifically, if a cpu (!= policy->cpu) invokes the drivers' ->get() function, it returns 0 as the KHz value, since its per-cpu memory doesn't point to anything valid. This causes problems during suspend/resume since cpufreq_update_policy() tries to enforce this (0 KHz) as the current frequency of the CPU, and this madness gets propagated to adjust_jiffies() as well. Eventually, lots of things start breaking down, including the r8169 ethernet card, in one particularly interesting case reported by Pierre Ossman. Fix this by initializing the per-cpu data-structures of all the CPUs in the policy appropriately. References: https://bugzilla.kernel.org/show_bug.cgi?id=70311 Reported-by: Pierre Ossman Signed-off-by: Srivatsa S. Bhat Cc: All applicable Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/powernow-k8.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c index e10b646634d7..6684e0342792 100644 --- a/drivers/cpufreq/powernow-k8.c +++ b/drivers/cpufreq/powernow-k8.c @@ -1076,7 +1076,7 @@ static int powernowk8_cpu_init(struct cpufreq_policy *pol) { struct powernow_k8_data *data; struct init_on_cpu init_on_cpu; - int rc; + int rc, cpu; smp_call_function_single(pol->cpu, check_supported_cpu, &rc, 1); if (rc) @@ -1140,7 +1140,9 @@ static int powernowk8_cpu_init(struct cpufreq_policy *pol) pr_debug("cpu_init done, current fid 0x%x, vid 0x%x\n", data->currfid, data->currvid); - per_cpu(powernow_data, pol->cpu) = data; + /* Point all the CPUs in this policy to the same data */ + for_each_cpu(cpu, pol->cpus) + per_cpu(powernow_data, cpu) = data; return 0; @@ -1155,6 +1157,7 @@ err_out: static int powernowk8_cpu_exit(struct cpufreq_policy *pol) { struct powernow_k8_data *data = per_cpu(powernow_data, pol->cpu); + int cpu; if (!data) return -EINVAL; @@ -1165,7 +1168,8 @@ static int powernowk8_cpu_exit(struct cpufreq_policy *pol) kfree(data->powernow_table); kfree(data); - per_cpu(powernow_data, pol->cpu) = NULL; + for_each_cpu(cpu, pol->cpus) + per_cpu(powernow_data, cpu) = NULL; return 0; } -- cgit v1.2.3 From 688b56b485578465f6619b9529d08c2b95641915 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Tue, 18 Feb 2014 23:03:31 +0100 Subject: ARM: tegra: Add head numbers to display controllers The number of the head specifies the index of the display controller unit and is required to properly configure outputs so that they receive video data from the correct source. Signed-off-by: Thierry Reding Acked-by: Stephen Warren Signed-off-by: Olof Johansson --- arch/arm/boot/dts/tegra114.dtsi | 4 ++++ arch/arm/boot/dts/tegra20.dtsi | 4 ++++ arch/arm/boot/dts/tegra30.dtsi | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/arch/arm/boot/dts/tegra114.dtsi b/arch/arm/boot/dts/tegra114.dtsi index 389e987ec281..44ec401ec366 100644 --- a/arch/arm/boot/dts/tegra114.dtsi +++ b/arch/arm/boot/dts/tegra114.dtsi @@ -57,6 +57,8 @@ resets = <&tegra_car 27>; reset-names = "dc"; + nvidia,head = <0>; + rgb { status = "disabled"; }; @@ -72,6 +74,8 @@ resets = <&tegra_car 26>; reset-names = "dc"; + nvidia,head = <1>; + rgb { status = "disabled"; }; diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi index 480ecda3416b..48d2a7f4d0c0 100644 --- a/arch/arm/boot/dts/tegra20.dtsi +++ b/arch/arm/boot/dts/tegra20.dtsi @@ -94,6 +94,8 @@ resets = <&tegra_car 27>; reset-names = "dc"; + nvidia,head = <0>; + rgb { status = "disabled"; }; @@ -109,6 +111,8 @@ resets = <&tegra_car 26>; reset-names = "dc"; + nvidia,head = <1>; + rgb { status = "disabled"; }; diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi index ed8e7700b46d..19a84e933f4e 100644 --- a/arch/arm/boot/dts/tegra30.dtsi +++ b/arch/arm/boot/dts/tegra30.dtsi @@ -170,6 +170,8 @@ resets = <&tegra_car 27>; reset-names = "dc"; + nvidia,head = <0>; + rgb { status = "disabled"; }; @@ -185,6 +187,8 @@ resets = <&tegra_car 26>; reset-names = "dc"; + nvidia,head = <1>; + rgb { status = "disabled"; }; -- cgit v1.2.3 From 8859685785bfafadf9bc922dd3a2278e59886947 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Tue, 18 Feb 2014 16:51:58 -0700 Subject: ARM: tegra: only run PL310 init on systems with one Fix tegra_init_cache() to check whether the system has a PL310 cache before touching the PL310 registers. This prevents access to non-existent registers on Tegra114 and later. Note for stable kernels: In <= v3.12, the file to patch is arch/arm/mach-tegra/common.c. Cc: # v3.9+ Signed-off-by: Stephen Warren Signed-off-by: Olof Johansson --- arch/arm/mach-tegra/tegra.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm/mach-tegra/tegra.c b/arch/arm/mach-tegra/tegra.c index 303a285d80fd..6191603379e1 100644 --- a/arch/arm/mach-tegra/tegra.c +++ b/arch/arm/mach-tegra/tegra.c @@ -73,10 +73,20 @@ u32 tegra_uart_config[3] = { static void __init tegra_init_cache(void) { #ifdef CONFIG_CACHE_L2X0 + static const struct of_device_id pl310_ids[] __initconst = { + { .compatible = "arm,pl310-cache", }, + {} + }; + + struct device_node *np; int ret; void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000; u32 aux_ctrl, cache_type; + np = of_find_matching_node(NULL, pl310_ids); + if (!np) + return; + cache_type = readl(p + L2X0_CACHE_TYPE); aux_ctrl = (cache_type & 0x700) << (17-8); aux_ctrl |= 0x7C400001; -- cgit v1.2.3 From 7a01e707a324a4585949ca3df6c7f7485d8783f2 Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Wed, 19 Feb 2014 15:33:05 +1100 Subject: xfs: xfs_sb_read_verify() doesn't flag bad crcs on primary sb My earlier commit 10e6e65 deserves a layer or two of brown paper bags. The logic in that commit means that a CRC failure on the primary superblock will *never* result in an error return. Hopefully this fixes it, so that we always return the error if it's a primary superblock, otherwise only if the filesystem has CRCs enabled. Signed-off-by: Eric Sandeen Reviewed-by: Mark Tinguely Signed-off-by: Ben Myers --- fs/xfs/xfs_sb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/xfs/xfs_sb.c b/fs/xfs/xfs_sb.c index b7c9aea77f8f..5071ccb67f07 100644 --- a/fs/xfs/xfs_sb.c +++ b/fs/xfs/xfs_sb.c @@ -614,7 +614,7 @@ xfs_sb_read_verify( if (!xfs_verify_cksum(bp->b_addr, be16_to_cpu(dsb->sb_sectsize), offsetof(struct xfs_sb, sb_crc))) { /* Only fail bad secondaries on a known V5 filesystem */ - if (bp->b_bn != XFS_SB_DADDR && + if (bp->b_bn == XFS_SB_DADDR || xfs_sb_version_hascrc(&mp->m_sb)) { error = EFSCORRUPTED; goto out_error; -- cgit v1.2.3 From 82daa86a77e592b38b7fa3f533173d1a3c1299a1 Mon Sep 17 00:00:00 2001 From: Ben Myers Date: Wed, 19 Feb 2014 15:38:22 +1100 Subject: MAINTAINERS: SGI no longer maintaining XFS SGI is stepping out of maintainer roles for xfs, xfsprogs, xfsdump, and xfstests. This removes me from the MAINTAINERS entry. Signed-off-by: Ben Myers Signed-off-by: Dave Chinner --- MAINTAINERS | 1 - 1 file changed, 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index b2cf5cfb4d29..e75188fd9676 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9715,7 +9715,6 @@ F: drivers/xen/*swiotlb* XFS FILESYSTEM P: Silicon Graphics Inc M: Dave Chinner -M: Ben Myers M: xfs@oss.sgi.com L: xfs@oss.sgi.com W: http://oss.sgi.com/projects/xfs -- cgit v1.2.3 From daba5427dad6b260256053f914de2c0b79f7a79f Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Wed, 19 Feb 2014 15:39:16 +1100 Subject: xfs: skip verification on initial "guess" superblock read When xfs_readsb() does the very first read of the superblock, it makes a guess at the length of the buffer, based on the sector size of the underlying storage. This may or may not match the filesystem sector size in sb_sectsize, so we can't i.e. do a CRC check on it; it might be too short. In fact, mounting a filesystem with sb_sectsize larger than the device sector size will cause a mount failure if CRCs are enabled, because we are checksumming a length which exceeds the buffer passed to it. So always read twice; the first time we read with NULL buffer ops to skip verification; then set the proper read length, hook up the proper verifier, and give it another go. Once we are sure that we've got the right buffer length, we can also use bp->b_length in the xfs_sb_read_verify, rather than the less-trusted on-disk sectorsize for secondary superblocks. Before this we ran the risk of passing junk to the crc32c routines, which didn't always handle extreme values. Signed-off-by: Eric Sandeen Reviewed-by: Dave Chinner Signed-off-by: Dave Chinner --- fs/xfs/xfs_mount.c | 24 ++++++++++++++++-------- fs/xfs/xfs_sb.c | 3 +-- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 02df7b408a26..f96c05669a9e 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -282,22 +282,29 @@ xfs_readsb( struct xfs_sb *sbp = &mp->m_sb; int error; int loud = !(flags & XFS_MFSI_QUIET); + const struct xfs_buf_ops *buf_ops; ASSERT(mp->m_sb_bp == NULL); ASSERT(mp->m_ddev_targp != NULL); + /* + * For the initial read, we must guess at the sector + * size based on the block device. It's enough to + * get the sb_sectsize out of the superblock and + * then reread with the proper length. + * We don't verify it yet, because it may not be complete. + */ + sector_size = xfs_getsize_buftarg(mp->m_ddev_targp); + buf_ops = NULL; + /* * Allocate a (locked) buffer to hold the superblock. * This will be kept around at all times to optimize * access to the superblock. */ - sector_size = xfs_getsize_buftarg(mp->m_ddev_targp); - reread: bp = xfs_buf_read_uncached(mp->m_ddev_targp, XFS_SB_DADDR, - BTOBB(sector_size), 0, - loud ? &xfs_sb_buf_ops - : &xfs_sb_quiet_buf_ops); + BTOBB(sector_size), 0, buf_ops); if (!bp) { if (loud) xfs_warn(mp, "SB buffer read failed"); @@ -328,12 +335,13 @@ reread: } /* - * If device sector size is smaller than the superblock size, - * re-read the superblock so the buffer is correctly sized. + * Re-read the superblock so the buffer is correctly sized, + * and properly verified. */ - if (sector_size < sbp->sb_sectsize) { + if (buf_ops == NULL) { xfs_buf_relse(bp); sector_size = sbp->sb_sectsize; + buf_ops = loud ? &xfs_sb_buf_ops : &xfs_sb_quiet_buf_ops; goto reread; } diff --git a/fs/xfs/xfs_sb.c b/fs/xfs/xfs_sb.c index 5071ccb67f07..359b19a4df42 100644 --- a/fs/xfs/xfs_sb.c +++ b/fs/xfs/xfs_sb.c @@ -611,7 +611,7 @@ xfs_sb_read_verify( XFS_SB_VERSION_5) || dsb->sb_crc != 0)) { - if (!xfs_verify_cksum(bp->b_addr, be16_to_cpu(dsb->sb_sectsize), + if (!xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length), offsetof(struct xfs_sb, sb_crc))) { /* Only fail bad secondaries on a known V5 filesystem */ if (bp->b_bn == XFS_SB_DADDR || @@ -644,7 +644,6 @@ xfs_sb_quiet_read_verify( { struct xfs_dsb *dsb = XFS_BUF_TO_SBP(bp); - if (dsb->sb_magicnum == cpu_to_be32(XFS_SB_MAGIC)) { /* XFS filesystem, verify noisily! */ xfs_sb_read_verify(bp); -- cgit v1.2.3 From 5ef11eb0700f806c4671ba33e5befa784a2f70ef Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Wed, 19 Feb 2014 15:39:35 +1100 Subject: xfs: limit superblock corruption errors to actual corruption Today, if xfs_sb_read_verify xfs_sb_verify xfs_mount_validate_sb detects superblock corruption, it'll be extremely noisy, dumping 2 stacks, 2 hexdumps, etc. This is because we call XFS_CORRUPTION_ERROR in xfs_mount_validate_sb as well as in xfs_sb_read_verify. Also, *any* errors in xfs_mount_validate_sb which are not corruption per se; things like too-big-blocksize, bad version, bad magic, v1 dirs, rw-incompat etc - things which do not return EFSCORRUPTED - will still do the whole XFS_CORRUPTION_ERROR spew when xfs_sb_read_verify sees any error at all. And it suggests to the user that they should run xfs_repair, even if the root cause of the mount failure is a simple incompatibility. I'll submit that the probably-not-corrupted errors don't warrant this much noise, so this patch removes the warning for anything other than EFSCORRUPTED returns, and replaces the lower-level XFS_CORRUPTION_ERROR with an xfs_notice(). Signed-off-by: Eric Sandeen Reviewed-by: Dave Chinner Signed-off-by: Dave Chinner --- fs/xfs/xfs_sb.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/fs/xfs/xfs_sb.c b/fs/xfs/xfs_sb.c index 359b19a4df42..1e116794bb66 100644 --- a/fs/xfs/xfs_sb.c +++ b/fs/xfs/xfs_sb.c @@ -295,8 +295,7 @@ xfs_mount_validate_sb( sbp->sb_dblocks == 0 || sbp->sb_dblocks > XFS_MAX_DBLOCKS(sbp) || sbp->sb_dblocks < XFS_MIN_DBLOCKS(sbp))) { - XFS_CORRUPTION_ERROR("SB sanity check failed", - XFS_ERRLEVEL_LOW, mp, sbp); + xfs_notice(mp, "SB sanity check failed"); return XFS_ERROR(EFSCORRUPTED); } @@ -625,7 +624,7 @@ xfs_sb_read_verify( out_error: if (error) { - if (error != EWRONGFS) + if (error == EFSCORRUPTED) XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr); xfs_buf_ioerror(bp, error); -- cgit v1.2.3 From 28fba95087a7f3d107a3a6728aef7dbfaf3fd782 Mon Sep 17 00:00:00 2001 From: Hsin-Yu Chao Date: Wed, 19 Feb 2014 14:27:07 +0800 Subject: ALSA: hda/ca0132 - setup/cleanup streams When a HDMI stream is opened with the same stream tag as a following opened stream to ca0132, audio will be heard from two ports simultaneously. Fix this issue by change to use snd_hda_codec_setup_stream and snd_hda_codec_cleanup_stream instead, so that an inactive stream can be marked as 'dirty' when found with a conflict stream tag, and then get purified. Signed-off-by: Hsin-Yu Chao Reviewed-by: Chih-Chung Chang Cc: Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_ca0132.c | 66 +++++--------------------------------------- 1 file changed, 7 insertions(+), 59 deletions(-) diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 54d14793725a..0aa72ee38d03 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -2661,60 +2661,6 @@ static bool dspload_wait_loaded(struct hda_codec *codec) return false; } -/* - * PCM stuffs - */ -static void ca0132_setup_stream(struct hda_codec *codec, hda_nid_t nid, - u32 stream_tag, - int channel_id, int format) -{ - unsigned int oldval, newval; - - if (!nid) - return; - - snd_printdd( - "ca0132_setup_stream: NID=0x%x, stream=0x%x, " - "channel=%d, format=0x%x\n", - nid, stream_tag, channel_id, format); - - /* update the format-id if changed */ - oldval = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_STREAM_FORMAT, - 0); - if (oldval != format) { - msleep(20); - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_STREAM_FORMAT, - format); - } - - oldval = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0); - newval = (stream_tag << 4) | channel_id; - if (oldval != newval) { - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_CHANNEL_STREAMID, - newval); - } -} - -static void ca0132_cleanup_stream(struct hda_codec *codec, hda_nid_t nid) -{ - unsigned int val; - - if (!nid) - return; - - snd_printdd(KERN_INFO "ca0132_cleanup_stream: NID=0x%x\n", nid); - - val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0); - if (!val) - return; - - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0); - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0); -} - /* * PCM callbacks */ @@ -2726,7 +2672,7 @@ static int ca0132_playback_pcm_prepare(struct hda_pcm_stream *hinfo, { struct ca0132_spec *spec = codec->spec; - ca0132_setup_stream(codec, spec->dacs[0], stream_tag, 0, format); + snd_hda_codec_setup_stream(codec, spec->dacs[0], stream_tag, 0, format); return 0; } @@ -2745,7 +2691,7 @@ static int ca0132_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, if (spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID]) msleep(50); - ca0132_cleanup_stream(codec, spec->dacs[0]); + snd_hda_codec_cleanup_stream(codec, spec->dacs[0]); return 0; } @@ -2824,8 +2770,8 @@ static int ca0132_capture_pcm_prepare(struct hda_pcm_stream *hinfo, { struct ca0132_spec *spec = codec->spec; - ca0132_setup_stream(codec, spec->adcs[substream->number], - stream_tag, 0, format); + snd_hda_codec_setup_stream(codec, spec->adcs[substream->number], + stream_tag, 0, format); return 0; } @@ -2839,7 +2785,7 @@ static int ca0132_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, if (spec->dsp_state == DSP_DOWNLOADING) return 0; - ca0132_cleanup_stream(codec, hinfo->nid); + snd_hda_codec_cleanup_stream(codec, hinfo->nid); return 0; } @@ -4742,6 +4688,8 @@ static int patch_ca0132(struct hda_codec *codec) return err; codec->patch_ops = ca0132_patch_ops; + codec->pcm_format_first = 1; + codec->no_sticky_stream = 1; return 0; } -- cgit v1.2.3 From 13c12dbe3a2ce17227f7ddef652b6a53c78fa51f Mon Sep 17 00:00:00 2001 From: Hsin-Yu Chao Date: Wed, 19 Feb 2014 14:30:35 +0800 Subject: ALSA: hda/ca0132 - Fix recording from mode id 0x8 Incorrect ADC is picked in ca0132_capture_pcm_prepare(), where it assumes multiple streams while there is one stream per ADC. Note that ca0132_capture_pcm_cleanup() already does the right thing. The Chromebook Pixel has a microphone under the keyboard that is attached to node id 0x8. Before this fix, recording would always go to the main internal mic (node id 0x7). Signed-off-by: Hsin-Yu Chao Reviewed-by: Dylan Reid Cc: Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_ca0132.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 0aa72ee38d03..46ecdbb9053f 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -2768,9 +2768,7 @@ static int ca0132_capture_pcm_prepare(struct hda_pcm_stream *hinfo, unsigned int format, struct snd_pcm_substream *substream) { - struct ca0132_spec *spec = codec->spec; - - snd_hda_codec_setup_stream(codec, spec->adcs[substream->number], + snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format); return 0; -- cgit v1.2.3 From 05fb7a56ad65ceaa1907bb9c66bfa1108847667f Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 23 Jan 2014 14:35:28 +0000 Subject: mfd: max8997: Naturalise cross-architecture discrepancies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If we compile the MAX8997 for a 64bit architecture we receive the following warnings: drivers/mfd/max8997.c: In function ‘max8997_i2c_get_driver_data’: drivers/mfd/max8997.c:173:10: warning: cast from pointer to integer of different size return (int)match->data; ^ Signed-off-by: Lee Jones --- drivers/mfd/max8997.c | 6 +++--- include/linux/mfd/max8997-private.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c index be88a3bf7b85..5adede0fb04c 100644 --- a/drivers/mfd/max8997.c +++ b/drivers/mfd/max8997.c @@ -164,15 +164,15 @@ static struct max8997_platform_data *max8997_i2c_parse_dt_pdata( return pd; } -static inline int max8997_i2c_get_driver_data(struct i2c_client *i2c, +static inline unsigned long max8997_i2c_get_driver_data(struct i2c_client *i2c, const struct i2c_device_id *id) { if (IS_ENABLED(CONFIG_OF) && i2c->dev.of_node) { const struct of_device_id *match; match = of_match_node(max8997_pmic_dt_match, i2c->dev.of_node); - return (int)match->data; + return (unsigned long)match->data; } - return (int)id->driver_data; + return id->driver_data; } static int max8997_i2c_probe(struct i2c_client *i2c, diff --git a/include/linux/mfd/max8997-private.h b/include/linux/mfd/max8997-private.h index ad1ae7f345ad..78c76cd4d37b 100644 --- a/include/linux/mfd/max8997-private.h +++ b/include/linux/mfd/max8997-private.h @@ -387,7 +387,7 @@ struct max8997_dev { struct i2c_client *muic; /* slave addr 0x4a */ struct mutex iolock; - int type; + unsigned long type; struct platform_device *battery; /* battery control (not fuel gauge) */ int irq; -- cgit v1.2.3 From 8bace2d5b4baa0f60b6094b53aeb79515ec94e4a Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Mon, 3 Feb 2014 08:22:30 +0000 Subject: mfd: max8998: Naturalise cross-architecture discrepancies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If we compile the MAX8998 for a 64bit architecture we receive the following warnings: drivers/mfd/max8998.c: In function ‘max8998_i2c_get_driver_data’: drivers/mfd/max8998.c:178:10: warning: cast from pointer to integer of different size return (int)match->data; ^ Signed-off-by: Lee Jones --- drivers/mfd/max8998.c | 6 +++--- include/linux/mfd/max8998-private.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/mfd/max8998.c b/drivers/mfd/max8998.c index 612ca404e150..5d5e186b5d8b 100644 --- a/drivers/mfd/max8998.c +++ b/drivers/mfd/max8998.c @@ -169,16 +169,16 @@ static struct max8998_platform_data *max8998_i2c_parse_dt_pdata( return pd; } -static inline int max8998_i2c_get_driver_data(struct i2c_client *i2c, +static inline unsigned long max8998_i2c_get_driver_data(struct i2c_client *i2c, const struct i2c_device_id *id) { if (IS_ENABLED(CONFIG_OF) && i2c->dev.of_node) { const struct of_device_id *match; match = of_match_node(max8998_dt_match, i2c->dev.of_node); - return (int)(long)match->data; + return (unsigned long)match->data; } - return (int)id->driver_data; + return id->driver_data; } static int max8998_i2c_probe(struct i2c_client *i2c, diff --git a/include/linux/mfd/max8998-private.h b/include/linux/mfd/max8998-private.h index 4ecb24b4b863..d68ada502ff3 100644 --- a/include/linux/mfd/max8998-private.h +++ b/include/linux/mfd/max8998-private.h @@ -163,7 +163,7 @@ struct max8998_dev { int ono; u8 irq_masks_cur[MAX8998_NUM_IRQ_REGS]; u8 irq_masks_cache[MAX8998_NUM_IRQ_REGS]; - int type; + unsigned long type; bool wakeup; }; -- cgit v1.2.3 From 7f8279ce04589a2e0f29b865c3af40609b0ea08d Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 23 Jan 2014 14:47:13 +0000 Subject: mfd: wm8994-core: Naturalise cross-architecture discrepancies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If we compile the WM8994 for a 64bit architecture we receive the following warnings: drivers/mfd/wm8994-core.c: In function ‘wm8994_i2c_probe’: drivers/mfd/wm8994-core.c:639:19: warning: cast from pointer to integer of different size wm8994->type = (int)of_id->data; ^ Signed-off-by: Lee Jones --- drivers/mfd/wm8994-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c index ba04f1bc70eb..e6fab94e2c8a 100644 --- a/drivers/mfd/wm8994-core.c +++ b/drivers/mfd/wm8994-core.c @@ -636,7 +636,7 @@ static int wm8994_i2c_probe(struct i2c_client *i2c, if (i2c->dev.of_node) { of_id = of_match_device(wm8994_of_match, &i2c->dev); if (of_id) - wm8994->type = (int)of_id->data; + wm8994->type = (enum wm8994_type)of_id->data; } else { wm8994->type = id->driver_data; } -- cgit v1.2.3 From 5c6fbd56d16f38fddec629e1dccdeee5ad7f5a42 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Mon, 3 Feb 2014 08:24:20 +0000 Subject: mfd: tps65217: Naturalise cross-architecture discrepancies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If we compile the TPS65217 for a 64bit architecture we receive the following warnings: drivers/mfd/tps65217.c: In function ‘tps65217_probe’: drivers/mfd/tps65217.c:173:13: warning: cast from pointer to integer of different size chip_id = (unsigned int)match->data; ^ Signed-off-by: Lee Jones --- drivers/mfd/tps65217.c | 4 ++-- include/linux/mfd/tps65217.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/mfd/tps65217.c b/drivers/mfd/tps65217.c index 966cf65c5c36..3cc4c7084b92 100644 --- a/drivers/mfd/tps65217.c +++ b/drivers/mfd/tps65217.c @@ -158,7 +158,7 @@ static int tps65217_probe(struct i2c_client *client, { struct tps65217 *tps; unsigned int version; - unsigned int chip_id = ids->driver_data; + unsigned long chip_id = ids->driver_data; const struct of_device_id *match; bool status_off = false; int ret; @@ -170,7 +170,7 @@ static int tps65217_probe(struct i2c_client *client, "Failed to find matching dt id\n"); return -EINVAL; } - chip_id = (unsigned int)(unsigned long)match->data; + chip_id = (unsigned long)match->data; status_off = of_property_read_bool(client->dev.of_node, "ti,pmic-shutdown-controller"); } diff --git a/include/linux/mfd/tps65217.h b/include/linux/mfd/tps65217.h index a5a7f0130e96..54b5458ec084 100644 --- a/include/linux/mfd/tps65217.h +++ b/include/linux/mfd/tps65217.h @@ -252,7 +252,7 @@ struct tps65217_board { struct tps65217 { struct device *dev; struct tps65217_board *pdata; - unsigned int id; + unsigned long id; struct regulator_desc desc[TPS65217_NUM_REGULATOR]; struct regulator_dev *rdev[TPS65217_NUM_REGULATOR]; struct regmap *regmap; @@ -263,7 +263,7 @@ static inline struct tps65217 *dev_to_tps65217(struct device *dev) return dev_get_drvdata(dev); } -static inline int tps65217_chip_id(struct tps65217 *tps65217) +static inline unsigned long tps65217_chip_id(struct tps65217 *tps65217) { return tps65217->id; } -- cgit v1.2.3 From 3edeb1e4b27e1553f4879e0e462724ac7cd75c62 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 26 Jan 2014 11:38:42 +0100 Subject: mfd: max14577: max14577_{suspend,resume}() should depend on CONFIG_PM_SLEEP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If CONFIG_PM_SLEEP=n: drivers/mfd/max14577.c:177: warning: ‘max14577_suspend’ defined but not used drivers/mfd/max14577.c:200: warning: ‘max14577_resume’ defined but not used Signed-off-by: Geert Uytterhoeven Signed-off-by: Lee Jones --- drivers/mfd/max14577.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/mfd/max14577.c b/drivers/mfd/max14577.c index ac514fb2b877..71aa14a6bfbb 100644 --- a/drivers/mfd/max14577.c +++ b/drivers/mfd/max14577.c @@ -173,6 +173,7 @@ static const struct i2c_device_id max14577_i2c_id[] = { }; MODULE_DEVICE_TABLE(i2c, max14577_i2c_id); +#ifdef CONFIG_PM_SLEEP static int max14577_suspend(struct device *dev) { struct i2c_client *i2c = container_of(dev, struct i2c_client, dev); @@ -208,6 +209,7 @@ static int max14577_resume(struct device *dev) return 0; } +#endif /* CONFIG_PM_SLEEP */ static struct of_device_id max14577_dt_match[] = { { .compatible = "maxim,max14577", }, -- cgit v1.2.3 From 8321bbf8906990e60cdb46be4c909a7780275942 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 26 Jan 2014 11:38:43 +0100 Subject: mfd: sec-core: sec_pmic_{suspend,resume}() should depend on CONFIG_PM_SLEEP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If CONFIG_PM_SLEEP=n: drivers/mfd/sec-core.c:349: warning: ‘sec_pmic_suspend’ defined but not used drivers/mfd/sec-core.c:371: warning: ‘sec_pmic_resume’ defined but not used Signed-off-by: Geert Uytterhoeven Signed-off-by: Lee Jones --- drivers/mfd/sec-core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c index a139798b8065..714e2135210e 100644 --- a/drivers/mfd/sec-core.c +++ b/drivers/mfd/sec-core.c @@ -315,6 +315,7 @@ static int sec_pmic_remove(struct i2c_client *i2c) return 0; } +#ifdef CONFIG_PM_SLEEP static int sec_pmic_suspend(struct device *dev) { struct i2c_client *i2c = container_of(dev, struct i2c_client, dev); @@ -349,6 +350,7 @@ static int sec_pmic_resume(struct device *dev) return 0; } +#endif /* CONFIG_PM_SLEEP */ static SIMPLE_DEV_PM_OPS(sec_pmic_pm_ops, sec_pmic_suspend, sec_pmic_resume); -- cgit v1.2.3 From 146d70caaa1b87f64597743429d7da4b8073d0c9 Mon Sep 17 00:00:00 2001 From: Andy Adamson Date: Tue, 18 Feb 2014 10:36:05 -0500 Subject: NFS fix error return in nfs4_select_rw_stateid Do not return an error when nfs4_copy_delegation_stateid succeeds. Signed-off-by: Andy Adamson Link: http://lkml.kernel.org/r/1392737765-41942-1-git-send-email-andros@netapp.com Fixes: ef1820f9be27b (NFSv4: Don't try to recover NFSv4 locks when...) Cc: NeilBrown Cc: stable@vger.kernel.org # 3.12+ Signed-off-by: Trond Myklebust --- fs/nfs/nfs4state.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index e5be72518bd7..e1a47217c05e 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -1015,8 +1015,11 @@ int nfs4_select_rw_stateid(nfs4_stateid *dst, struct nfs4_state *state, if (ret == -EIO) /* A lost lock - don't even consider delegations */ goto out; - if (nfs4_copy_delegation_stateid(dst, state->inode, fmode)) + /* returns true if delegation stateid found and copied */ + if (nfs4_copy_delegation_stateid(dst, state->inode, fmode)) { + ret = 0; goto out; + } if (ret != -ENOENT) /* nfs4_copy_delegation_stateid() didn't over-write * dst, so it still has the lock stateid which we now -- cgit v1.2.3 From 5ae8aabeaec3fe69c4fb21cbe5b17b72b35b5892 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Mon, 17 Feb 2014 10:45:36 -0800 Subject: sched_clock: Prevent callers from seeing half-updated data The generic sched_clock registration function was previously done lockless, due to the fact that it was expected to be called only once. However, now there are systems that may register multiple sched_clock sources, for which the lack of locking has casued problems: If two sched_clock sources are registered we may end up in a situation where a call to sched_clock() may be accessing the epoch cycle count for the old counter and the cycle count for the new counter. This can lead to confusing results where sched_clock() values jump and then are reset to 0 (due to the way the registration function forces the epoch_ns to be 0). Fix this by reorganizing the registration function to hold the seqlock for as short a time as possible while we update the clock_data structure for a new counter. We also put any accumulated time into epoch_ns instead of resetting the time to 0 so that the clock doesn't reset after each successful registration. [jstultz: Added extra context to the commit message] Reported-by: Will Deacon Signed-off-by: Stephen Boyd Cc: Peter Zijlstra Cc: Ingo Molnar Cc: Will Deacon Cc: Peter Zijlstra Cc: Josh Cartwright Link: http://lkml.kernel.org/r/1392662736-7803-2-git-send-email-john.stultz@linaro.org Signed-off-by: John Stultz Signed-off-by: Thomas Gleixner --- kernel/time/sched_clock.c | 46 +++++++++++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/kernel/time/sched_clock.c b/kernel/time/sched_clock.c index 0abb36464281..4d23dc4d8139 100644 --- a/kernel/time/sched_clock.c +++ b/kernel/time/sched_clock.c @@ -116,20 +116,42 @@ static enum hrtimer_restart sched_clock_poll(struct hrtimer *hrt) void __init sched_clock_register(u64 (*read)(void), int bits, unsigned long rate) { + u64 res, wrap, new_mask, new_epoch, cyc, ns; + u32 new_mult, new_shift; + ktime_t new_wrap_kt; unsigned long r; - u64 res, wrap; char r_unit; if (cd.rate > rate) return; WARN_ON(!irqs_disabled()); - read_sched_clock = read; - sched_clock_mask = CLOCKSOURCE_MASK(bits); - cd.rate = rate; /* calculate the mult/shift to convert counter ticks to ns. */ - clocks_calc_mult_shift(&cd.mult, &cd.shift, rate, NSEC_PER_SEC, 3600); + clocks_calc_mult_shift(&new_mult, &new_shift, rate, NSEC_PER_SEC, 3600); + + new_mask = CLOCKSOURCE_MASK(bits); + + /* calculate how many ns until we wrap */ + wrap = clocks_calc_max_nsecs(new_mult, new_shift, 0, new_mask); + new_wrap_kt = ns_to_ktime(wrap - (wrap >> 3)); + + /* update epoch for new counter and update epoch_ns from old counter*/ + new_epoch = read(); + cyc = read_sched_clock(); + ns = cd.epoch_ns + cyc_to_ns((cyc - cd.epoch_cyc) & sched_clock_mask, + cd.mult, cd.shift); + + raw_write_seqcount_begin(&cd.seq); + read_sched_clock = read; + sched_clock_mask = new_mask; + cd.rate = rate; + cd.wrap_kt = new_wrap_kt; + cd.mult = new_mult; + cd.shift = new_shift; + cd.epoch_cyc = new_epoch; + cd.epoch_ns = ns; + raw_write_seqcount_end(&cd.seq); r = rate; if (r >= 4000000) { @@ -141,22 +163,12 @@ void __init sched_clock_register(u64 (*read)(void), int bits, } else r_unit = ' '; - /* calculate how many ns until we wrap */ - wrap = clocks_calc_max_nsecs(cd.mult, cd.shift, 0, sched_clock_mask); - cd.wrap_kt = ns_to_ktime(wrap - (wrap >> 3)); - /* calculate the ns resolution of this counter */ - res = cyc_to_ns(1ULL, cd.mult, cd.shift); + res = cyc_to_ns(1ULL, new_mult, new_shift); + pr_info("sched_clock: %u bits at %lu%cHz, resolution %lluns, wraps every %lluns\n", bits, r, r_unit, res, wrap); - update_sched_clock(); - - /* - * Ensure that sched_clock() starts off at 0ns - */ - cd.epoch_ns = 0; - /* Enable IRQ time accounting if we have a fast enough sched_clock */ if (irqtime > 0 || (irqtime == -1 && rate >= 1000000)) enable_sched_clock_irqtime(); -- cgit v1.2.3 From 5f0e030930d715920be4de638084aaf8653867e8 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 19 Feb 2014 13:52:29 +0200 Subject: x86, tsc: Fallback to normal calibration if fast MSR calibration fails If we cannot calibrate TSC via MSR based calibration try_msr_calibrate_tsc() stores zero to fast_calibrate and returns that to the caller. This value gets then propagated further to clockevents code resulting division by zero oops like the one below: divide error: 0000 [#1] PREEMPT SMP Modules linked in: CPU: 0 PID: 1 Comm: swapper/0 Tainted: G W 3.13.0+ #47 task: ffff880075508000 ti: ffff880075506000 task.ti: ffff880075506000 RIP: 0010:[] [] clockevents_config.part.3+0x24/0xa0 RSP: 0000:ffff880075507e58 EFLAGS: 00010246 RAX: ffffffffffffffff RBX: ffff880079c0cd80 RCX: 0000000000000000 RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffffffffffffffff RBP: ffff880075507e70 R08: 0000000000000001 R09: 00000000000000be R10: 00000000000000bd R11: 0000000000000003 R12: 000000000000b008 R13: 0000000000000008 R14: 000000000000b010 R15: 0000000000000000 FS: 0000000000000000(0000) GS:ffff880079c00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b CR2: ffff880079fff000 CR3: 0000000001c0b000 CR4: 00000000001006f0 Stack: ffff880079c0cd80 000000000000b008 0000000000000008 ffff880075507e88 ffffffff810aecb0 ffff880079c0cd80 ffff880075507e98 ffffffff81030168 ffff880075507ed8 ffffffff81d1104f 00000000000000c3 0000000000000000 Call Trace: [] clockevents_config_and_register+0x20/0x30 [] setup_APIC_timer+0xc8/0xd0 [] setup_boot_APIC_clock+0x4cc/0x4d8 [] native_smp_prepare_cpus+0x3dd/0x3f0 [] kernel_init_freeable+0xc3/0x205 [] ? rest_init+0x90/0x90 [] kernel_init+0xe/0x120 [] ret_from_fork+0x7c/0xb0 [] ? rest_init+0x90/0x90 Prevent this from happening by: 1) Modifying try_msr_calibrate_tsc() to return calibration value or zero if it fails. 2) Check this return value in native_calibrate_tsc() and in case of zero fallback to use normal non-MSR based calibration. [mw: Added subject and changelog] Reported-and-tested-by: Mika Westerberg Signed-off-by: Thomas Gleixner Cc: Bin Gao Cc: One Thousand Gnomes Cc: Ingo Molnar Cc: H. Peter Anvin Link: http://lkml.kernel.org/r/1392810750-18660-1-git-send-email-mika.westerberg@linux.intel.com Signed-off-by: Mika Westerberg Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/tsc.h | 2 +- arch/x86/kernel/tsc.c | 7 ++----- arch/x86/kernel/tsc_msr.c | 28 ++++++++++++++-------------- 3 files changed, 17 insertions(+), 20 deletions(-) diff --git a/arch/x86/include/asm/tsc.h b/arch/x86/include/asm/tsc.h index 57ae63cd6ee2..94605c0e9cee 100644 --- a/arch/x86/include/asm/tsc.h +++ b/arch/x86/include/asm/tsc.h @@ -66,6 +66,6 @@ extern void tsc_save_sched_clock_state(void); extern void tsc_restore_sched_clock_state(void); /* MSR based TSC calibration for Intel Atom SoC platforms */ -int try_msr_calibrate_tsc(unsigned long *fast_calibrate); +unsigned long try_msr_calibrate_tsc(void); #endif /* _ASM_X86_TSC_H */ diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index acb3b606613e..cfbe99f88830 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -653,13 +653,10 @@ unsigned long native_calibrate_tsc(void) /* Calibrate TSC using MSR for Intel Atom SoCs */ local_irq_save(flags); - i = try_msr_calibrate_tsc(&fast_calibrate); + fast_calibrate = try_msr_calibrate_tsc(); local_irq_restore(flags); - if (i >= 0) { - if (i == 0) - pr_warn("Fast TSC calibration using MSR failed\n"); + if (fast_calibrate) return fast_calibrate; - } local_irq_save(flags); fast_calibrate = quick_pit_calibrate(); diff --git a/arch/x86/kernel/tsc_msr.c b/arch/x86/kernel/tsc_msr.c index 8b5434f4389f..5dfff5809e74 100644 --- a/arch/x86/kernel/tsc_msr.c +++ b/arch/x86/kernel/tsc_msr.c @@ -77,21 +77,18 @@ static int match_cpu(u8 family, u8 model) /* * Do MSR calibration only for known/supported CPUs. - * Return values: - * -1: CPU is unknown/unsupported for MSR based calibration - * 0: CPU is known/supported, but calibration failed - * 1: CPU is known/supported, and calibration succeeded + * + * Returns the calibration value or 0 if MSR calibration failed. */ -int try_msr_calibrate_tsc(unsigned long *fast_calibrate) +unsigned long try_msr_calibrate_tsc(void) { - int cpu_index; u32 lo, hi, ratio, freq_id, freq; + unsigned long res; + int cpu_index; cpu_index = match_cpu(boot_cpu_data.x86, boot_cpu_data.x86_model); if (cpu_index < 0) - return -1; - - *fast_calibrate = 0; + return 0; if (freq_desc_tables[cpu_index].msr_plat) { rdmsr(MSR_PLATFORM_INFO, lo, hi); @@ -103,7 +100,7 @@ int try_msr_calibrate_tsc(unsigned long *fast_calibrate) pr_info("Maximum core-clock to bus-clock ratio: 0x%x\n", ratio); if (!ratio) - return 0; + goto fail; /* Get FSB FREQ ID */ rdmsr(MSR_FSB_FREQ, lo, hi); @@ -112,16 +109,19 @@ int try_msr_calibrate_tsc(unsigned long *fast_calibrate) pr_info("Resolved frequency ID: %u, frequency: %u KHz\n", freq_id, freq); if (!freq) - return 0; + goto fail; /* TSC frequency = maximum resolved freq * maximum resolved bus ratio */ - *fast_calibrate = freq * ratio; - pr_info("TSC runs at %lu KHz\n", *fast_calibrate); + res = freq * ratio; + pr_info("TSC runs at %lu KHz\n", res); #ifdef CONFIG_X86_LOCAL_APIC lapic_timer_frequency = (freq * 1000) / HZ; pr_info("lapic_timer_frequency = %d\n", lapic_timer_frequency); #endif + return res; - return 1; +fail: + pr_warn("Fast TSC calibration using MSR failed\n"); + return 0; } -- cgit v1.2.3 From 3e11e818bfd7bd4a8e1214970337bab73ffed32d Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Wed, 19 Feb 2014 13:52:30 +0200 Subject: x86: tsc: Add missing Baytrail frequency to the table Intel Baytrail is based on Silvermont core so MSR_FSB_FREQ[2:0] == 0 means that the CPU reference clock runs at 83.3MHz. Add this missing frequency to the table. Signed-off-by: Mika Westerberg Cc: Bin Gao Cc: One Thousand Gnomes Cc: Ingo Molnar Cc: H. Peter Anvin Link: http://lkml.kernel.org/r/1392810750-18660-2-git-send-email-mika.westerberg@linux.intel.com Signed-off-by: Thomas Gleixner --- arch/x86/kernel/tsc_msr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/tsc_msr.c b/arch/x86/kernel/tsc_msr.c index 5dfff5809e74..92ae6acac8a7 100644 --- a/arch/x86/kernel/tsc_msr.c +++ b/arch/x86/kernel/tsc_msr.c @@ -53,7 +53,7 @@ static struct freq_desc freq_desc_tables[] = { /* TNG */ { 6, 0x4a, 1, { 0, FREQ_100, FREQ_133, 0, 0, 0, 0, 0 } }, /* VLV2 */ - { 6, 0x37, 1, { 0, FREQ_100, FREQ_133, FREQ_166, 0, 0, 0, 0 } }, + { 6, 0x37, 1, { FREQ_83, FREQ_100, FREQ_133, FREQ_166, 0, 0, 0, 0 } }, /* ANN */ { 6, 0x5a, 1, { FREQ_83, FREQ_100, FREQ_133, FREQ_100, 0, 0, 0, 0 } }, }; -- cgit v1.2.3 From bd8ba20597f0cfef3ef65c3fd2aa92ab23d4c8e1 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 13 Feb 2014 16:32:51 +0100 Subject: ACPI / video: Filter the _BCL table for duplicate brightness values Some devices have duplicate entries in there brightness levels table, ie on my Dell Latitude E6430 the table looks like this: [ 3.686060] acpi backlight index 0, val 80 [ 3.686095] acpi backlight index 1, val 50 [ 3.686122] acpi backlight index 2, val 5 [ 3.686147] acpi backlight index 3, val 5 [ 3.686172] acpi backlight index 4, val 5 [ 3.686197] acpi backlight index 5, val 5 [ 3.686223] acpi backlight index 6, val 5 [ 3.686248] acpi backlight index 7, val 5 [ 3.686273] acpi backlight index 8, val 6 [ 3.686332] acpi backlight index 9, val 7 [ 3.686356] acpi backlight index 10, val 8 [ 3.686380] acpi backlight index 11, val 9 etc. Notice that brightness values 0-5 are all mapped to 5. This means that if userspace writes any value between 0 and 5 to the brightness sysfs attribute and then reads it, it will always return 0, which is somewhat unexpected. This is a problem for ie gnome-settings-daemon, which uses read-modify-write logic when the users presses the brightness up or down keys. This is done this way to take brightness changes from other sources into account. On this specific laptop what happens once the brightness has been set to 0, is that gsd reads 0, adds 5, writes 5, and on the next brightness up key press again reads 0, so things get stuck at the lowest brightness setting. Filtering out the duplicate table entries, makes any write to brightness read back as the written value as one would expect, fixing this. Signed-off-by: Hans de Goede Reviewed-by: Aaron Lu Cc: All applicable Signed-off-by: Rafael J. Wysocki --- drivers/acpi/video.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index b727d105046d..ea9d914d937a 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -685,6 +685,7 @@ acpi_video_init_brightness(struct acpi_video_device *device) union acpi_object *o; struct acpi_video_device_brightness *br = NULL; int result = -EINVAL; + u32 value; if (!ACPI_SUCCESS(acpi_video_device_lcd_query_levels(device, &obj))) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Could not query available " @@ -715,7 +716,12 @@ acpi_video_init_brightness(struct acpi_video_device *device) printk(KERN_ERR PREFIX "Invalid data\n"); continue; } - br->levels[count] = (u32) o->integer.value; + value = (u32) o->integer.value; + /* Skip duplicate entries */ + if (count > 2 && br->levels[count - 1] == value) + continue; + + br->levels[count] = value; if (br->levels[count] > max_level) max_level = br->levels[count]; -- cgit v1.2.3 From 0e9f81d3b7cd0649a3bc437391b6a0650f98f844 Mon Sep 17 00:00:00 2001 From: Aaron Lu Date: Tue, 18 Feb 2014 13:54:20 +0800 Subject: ACPI / video: Add systems that should favour native backlight interface Some system's ACPI video backlight control interface is broken and the native backlight control interface should be used by default. This patch sets the use_native_backlight parameter to true for those systems so that video backlight control interface will not be created. For detailed models that are added here, reference the following list. Note that the user specified kernel cmdline option will always have the highest priority, i.e. if use_native_backlight=0 is specified and the system is in the DMI table, the video module will not skip registering backlight interface for it. Thinkpad T430s: Reported-by: Theodore Tso Reported-and-tested-by: Peter Weber References: https://bugzilla.kernel.org/show_bug.cgi?id=51231 Thinkpad X230: Reported-and-tested-by: Igor Gnatenko References: https://bugzilla.kernel.org/show_bug.cgi?id=51231 ThinkPad X1 Carbon: Reported-and-tested-by: Igor Gnatenko Lenovo Yoga 13: Reported-by: Lennart Poettering Reported-and-tested-by: Kevin Smith References: https://bugzilla.kernel.org/show_bug.cgi?id=63811 Dell Inspiron 7520: Reported-by: Rinat Ibragimov Acer Aspire 5733Z: Reported-by: References: https://bugzilla.kernel.org/show_bug.cgi?id=62941 Acer Aspire V5-431: Reported-by: Thomas Christensen References: https://bugzilla.kernel.org/show_bug.cgi?id=68751 HP ProBook 4340s: Reported-and-tested-by: Vladimir Sherenkov References: http://redmine.russianfedora.pro/issues/1258 HP EliteBook/ProBook 2013 models, ZBook and some others: Provided-by: Takashi Iwai Signed-off-by: Aaron Lu Tested-by: Mika Westerberg Signed-off-by: Rafael J. Wysocki --- drivers/acpi/blacklist.c | 8 --- drivers/acpi/video.c | 139 ++++++++++++++++++++++++++++++++++++++++++-- drivers/acpi/video_detect.c | 16 ----- 3 files changed, 134 insertions(+), 29 deletions(-) diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index 10e4964d051a..e8e4c3dfaff7 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c @@ -260,14 +260,6 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { }, { .callback = dmi_disable_osi_win8, - .ident = "Dell Inspiron 15R SE", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7520"), - }, - }, - { - .callback = dmi_disable_osi_win8, .ident = "ThinkPad Edge E530", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index ea9d914d937a..b6ba88ed31ae 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -81,11 +81,12 @@ static bool allow_duplicates; module_param(allow_duplicates, bool, 0644); /* - * For Windows 8 systems: if set ture and the GPU driver has - * registered a backlight interface, skip registering ACPI video's. + * For Windows 8 systems: used to decide if video module + * should skip registering backlight interface of its own. */ -static bool use_native_backlight = false; -module_param(use_native_backlight, bool, 0644); +static int use_native_backlight_param = -1; +module_param_named(use_native_backlight, use_native_backlight_param, int, 0444); +static bool use_native_backlight_dmi = false; static int register_count; static struct mutex video_list_lock; @@ -231,9 +232,17 @@ static int acpi_video_get_next_level(struct acpi_video_device *device, static int acpi_video_switch_brightness(struct acpi_video_device *device, int event); +static bool acpi_video_use_native_backlight(void) +{ + if (use_native_backlight_param != -1) + return use_native_backlight_param; + else + return use_native_backlight_dmi; +} + static bool acpi_video_verify_backlight_support(void) { - if (acpi_osi_is_win8() && use_native_backlight && + if (acpi_osi_is_win8() && acpi_video_use_native_backlight() && backlight_device_registered(BACKLIGHT_RAW)) return false; return acpi_video_backlight_support(); @@ -398,6 +407,12 @@ static int __init video_set_bqc_offset(const struct dmi_system_id *d) return 0; } +static int __init video_set_use_native_backlight(const struct dmi_system_id *d) +{ + use_native_backlight_dmi = true; + return 0; +} + static struct dmi_system_id video_dmi_table[] __initdata = { /* * Broken _BQC workaround http://bugzilla.kernel.org/show_bug.cgi?id=13121 @@ -442,6 +457,120 @@ static struct dmi_system_id video_dmi_table[] __initdata = { DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 7720"), }, }, + { + .callback = video_set_use_native_backlight, + .ident = "ThinkPad T430s", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T430s"), + }, + }, + { + .callback = video_set_use_native_backlight, + .ident = "ThinkPad X230", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X230"), + }, + }, + { + .callback = video_set_use_native_backlight, + .ident = "ThinkPad X1 Carbon", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X1 Carbon"), + }, + }, + { + .callback = video_set_use_native_backlight, + .ident = "Lenovo Yoga 13", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo IdeaPad Yoga 13"), + }, + }, + { + .callback = video_set_use_native_backlight, + .ident = "Dell Inspiron 7520", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_VERSION, "Inspiron 7520"), + }, + }, + { + .callback = video_set_use_native_backlight, + .ident = "Acer Aspire 5733Z", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5733Z"), + }, + }, + { + .callback = video_set_use_native_backlight, + .ident = "Acer Aspire V5-431", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "Aspire V5-431"), + }, + }, + { + .callback = video_set_use_native_backlight, + .ident = "HP ProBook 4340s", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_VERSION, "HP ProBook 4340s"), + }, + }, + { + .callback = video_set_use_native_backlight, + .ident = "HP ProBook 2013 models", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP ProBook "), + DMI_MATCH(DMI_PRODUCT_NAME, " G1"), + }, + }, + { + .callback = video_set_use_native_backlight, + .ident = "HP EliteBook 2013 models", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook "), + DMI_MATCH(DMI_PRODUCT_NAME, " G1"), + }, + }, + { + .callback = video_set_use_native_backlight, + .ident = "HP ZBook 14", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP ZBook 14"), + }, + }, + { + .callback = video_set_use_native_backlight, + .ident = "HP ZBook 15", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP ZBook 15"), + }, + }, + { + .callback = video_set_use_native_backlight, + .ident = "HP ZBook 17", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP ZBook 17"), + }, + }, + { + .callback = video_set_use_native_backlight, + .ident = "HP EliteBook 8780w", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook 8780w"), + }, + }, {} }; diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index a697b77b8865..19080c8e2f2a 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -168,22 +168,6 @@ static struct dmi_system_id video_detect_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "UL30A"), }, }, - { - .callback = video_detect_force_vendor, - .ident = "HP EliteBook Revolve 810", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook Revolve 810 G1"), - }, - }, - { - .callback = video_detect_force_vendor, - .ident = "Lenovo Yoga 13", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo IdeaPad Yoga 13"), - }, - }, { }, }; -- cgit v1.2.3 From a6940190ac15c361862a1a8f50a2072db7184749 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 18 Feb 2014 14:55:15 +0100 Subject: Revert "ACPI: Blacklist Win8 OSI for some HP laptop 2013 models" This reverts commit 2d4054d84224 (ACPI: Blacklist Win8 OSI for some HP laptop 2013 models) that is not necessary any more after previous commit 1811fcb029fa (ACPI / video: Add systems that should favour native backlight interface). Requested-by: Takashi Iwai Tested-by: Mika Westerberg Signed-off-by: Rafael J. Wysocki --- drivers/acpi/blacklist.c | 50 ------------------------------------------------ 1 file changed, 50 deletions(-) diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index e8e4c3dfaff7..afec4526c48a 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c @@ -314,56 +314,6 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { DMI_MATCH(DMI_PRODUCT_VERSION, "2349D15"), }, }, - { - .callback = dmi_disable_osi_win8, - .ident = "HP ProBook 2013 models", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP ProBook "), - DMI_MATCH(DMI_PRODUCT_NAME, " G1"), - }, - }, - { - .callback = dmi_disable_osi_win8, - .ident = "HP EliteBook 2013 models", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook "), - DMI_MATCH(DMI_PRODUCT_NAME, " G1"), - }, - }, - { - .callback = dmi_disable_osi_win8, - .ident = "HP ZBook 14", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP ZBook 14"), - }, - }, - { - .callback = dmi_disable_osi_win8, - .ident = "HP ZBook 15", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP ZBook 15"), - }, - }, - { - .callback = dmi_disable_osi_win8, - .ident = "HP ZBook 17", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP ZBook 17"), - }, - }, - { - .callback = dmi_disable_osi_win8, - .ident = "HP EliteBook 8780w", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook 8780w"), - }, - }, /* * BIOS invocation of _OSI(Linux) is almost always a BIOS bug. -- cgit v1.2.3 From 4f6500fff5f7644a03c46728fd7ef0f62fa6940b Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Thu, 13 Feb 2014 13:57:44 -0500 Subject: sparc32: fix build failure for arch_jump_label_transform In arch/sparc/Kernel/Makefile, we see: obj-$(CONFIG_SPARC64) += jump_label.o However, the Kconfig selects HAVE_ARCH_JUMP_LABEL unconditionally for all SPARC. This in turn leads to the following failure when doing allmodconfig coverage builds: kernel/built-in.o: In function `__jump_label_update': jump_label.c:(.text+0x8560c): undefined reference to `arch_jump_label_transform' kernel/built-in.o: In function `arch_jump_label_transform_static': (.text+0x85cf4): undefined reference to `arch_jump_label_transform' make: *** [vmlinux] Error 1 Change HAVE_ARCH_JUMP_LABEL to be conditional on SPARC64 so that it matches the Makefile. Signed-off-by: Paul Gortmaker Signed-off-by: David S. Miller --- arch/sparc/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index c51efdcd07a2..7d8b7e94b93b 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -27,7 +27,7 @@ config SPARC select RTC_DRV_M48T59 select HAVE_DMA_ATTRS select HAVE_DMA_API_DEBUG - select HAVE_ARCH_JUMP_LABEL + select HAVE_ARCH_JUMP_LABEL if SPARC64 select GENERIC_IRQ_SHOW select ARCH_WANT_IPC_PARSE_VERSION select GENERIC_PCI_IOMAP -- cgit v1.2.3 From a56b072fa357ab076cb6c9b52e58fbe3c709da10 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Thu, 13 Feb 2014 16:15:01 -0500 Subject: sparc32: make copy_to/from_user_page() usable from modular code While copy_to/from_user_page() users are uncommon, there is one in drivers/staging/lustre/lustre/libcfs/linux/linux-curproc.c which leads to the following: ERROR: "sparc32_cachetlb_ops" [drivers/staging/lustre/lustre/libcfs/libcfs.ko] undefined! during routine allmodconfig build coverage. The reason this happens is as follows: In arch/sparc/include/asm/cacheflush_32.h we have: #define flush_cache_page(vma,addr,pfn) \ sparc32_cachetlb_ops->cache_page(vma, addr) #define copy_to_user_page(vma, page, vaddr, dst, src, len) \ do { \ flush_cache_page(vma, vaddr, page_to_pfn(page));\ memcpy(dst, src, len); \ } while (0) #define copy_from_user_page(vma, page, vaddr, dst, src, len) \ do { \ flush_cache_page(vma, vaddr, page_to_pfn(page));\ memcpy(dst, src, len); \ } while (0) However, sparc32_cachetlb_ops isn't exported and hence the error. Signed-off-by: Paul Gortmaker Signed-off-by: David S. Miller --- arch/sparc/mm/srmmu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c index 869023abe5a4..cfbe53c17b0d 100644 --- a/arch/sparc/mm/srmmu.c +++ b/arch/sparc/mm/srmmu.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -62,6 +63,7 @@ extern unsigned long last_valid_pfn; static pgd_t *srmmu_swapper_pg_dir; const struct sparc32_cachetlb_ops *sparc32_cachetlb_ops; +EXPORT_SYMBOL(sparc32_cachetlb_ops); #ifdef CONFIG_SMP const struct sparc32_cachetlb_ops *local_ops; -- cgit v1.2.3 From 1de7ca5e844866f56bebb2fc47fa18e090677e88 Mon Sep 17 00:00:00 2001 From: Hui Wang Date: Thu, 20 Feb 2014 11:47:21 +0800 Subject: ALSA: hda - Enable front audio jacks on one HP desktop model The front headphone and mic jackes on a HP desktop model (Vendor Id: 0x111d76c7 Subsystem Id: 0x103c2b17) can not work, the codec on this machine has 8 physical ports, 6 of them are routed to rear jackes and all of them work very well, while the remaining 2 ports are routed to front headphone and mic jackes, but the corresponding pin complex node are not defined correctly. After apply this fix, the front audio jackes can work very well. [trivial fix of enum definition by tiwai] BugLink: https://bugs.launchpad.net/bugs/1282369 Cc: David Henningsson Tested-by: Gerald Yang Cc: stable@vger.kernel.org Signed-off-by: Hui Wang Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_sigmatel.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 7311badf6a94..a2f11bf8155c 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -83,6 +83,7 @@ enum { STAC_DELL_M6_BOTH, STAC_DELL_EQ, STAC_ALIENWARE_M17X, + STAC_92HD89XX_HP_FRONT_JACK, STAC_92HD73XX_MODELS }; @@ -1795,6 +1796,12 @@ static const struct hda_pintbl intel_dg45id_pin_configs[] = { {} }; +static const struct hda_pintbl stac92hd89xx_hp_front_jack_pin_configs[] = { + { 0x0a, 0x02214030 }, + { 0x0b, 0x02A19010 }, + {} +}; + static void stac92hd73xx_fixup_ref(struct hda_codec *codec, const struct hda_fixup *fix, int action) { @@ -1913,6 +1920,10 @@ static const struct hda_fixup stac92hd73xx_fixups[] = { [STAC_92HD73XX_NO_JD] = { .type = HDA_FIXUP_FUNC, .v.func = stac92hd73xx_fixup_no_jd, + }, + [STAC_92HD89XX_HP_FRONT_JACK] = { + .type = HDA_FIXUP_PINS, + .v.pins = stac92hd89xx_hp_front_jack_pin_configs, } }; @@ -1973,6 +1984,8 @@ static const struct snd_pci_quirk stac92hd73xx_fixup_tbl[] = { "Alienware M17x", STAC_ALIENWARE_M17X), SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0490, "Alienware M17x R3", STAC_DELL_EQ), + SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2b17, + "unknown HP", STAC_92HD89XX_HP_FRONT_JACK), {} /* terminator */ }; -- cgit v1.2.3 From 215a14cface21ba205f6edc813be157fdf7899b8 Mon Sep 17 00:00:00 2001 From: Kevin Hao Date: Wed, 19 Feb 2014 16:15:45 +0800 Subject: of: reimplement the matching method for __of_match_node() In the current implementation of __of_match_node(), it will compare each given match entry against all the node's compatible strings with of_device_is_compatible(). To achieve multiple compatible strings per node with ordering from specific to generic, this requires given matches to be ordered from specific to generic. For most of the drivers this is not true and also an alphabetical ordering is more sane there. Therefore, we define a following priority order for the match, and then scan all the entries to find the best match. 1. specific compatible && type && name 2. specific compatible && type 3. specific compatible && name 4. specific compatible 5. general compatible && type && name 6. general compatible && type 7. general compatible && name 8. general compatible 9. type && name 10. type 11. name v5: Fix nested locking bug v4: Short-circuit failure cases instead of mucking with score, and remove extra __of_device_is_compatible() wrapper stub. Move scoring logic directly into __of_device_is_compatible() v3: Also need to bail out when there does have a compatible member in match entry, but it doesn't match with the device node's compatible. v2: Fix the bug such as we get the same score for the following two match entries with the empty node 'name2 { };' struct of_device_id matches[] = { {.name = "name2", }, {.name = "name2", .type = "type1", }, {} }; Signed-off-by: Kevin Hao [grant.likely: added v4 changes] Signed-off-by: Grant Likely Tested-by: Paul Gortmaker Tested-by: Stephen Chivers Tested-by: Sachin Kamat --- drivers/of/base.c | 111 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 75 insertions(+), 36 deletions(-) diff --git a/drivers/of/base.c b/drivers/of/base.c index ba195fbce4c6..89e888a78899 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -342,27 +342,72 @@ struct device_node *of_get_cpu_node(int cpu, unsigned int *thread) } EXPORT_SYMBOL(of_get_cpu_node); -/** Checks if the given "compat" string matches one of the strings in - * the device's "compatible" property +/** + * __of_device_is_compatible() - Check if the node matches given constraints + * @device: pointer to node + * @compat: required compatible string, NULL or "" for any match + * @type: required device_type value, NULL or "" for any match + * @name: required node name, NULL or "" for any match + * + * Checks if the given @compat, @type and @name strings match the + * properties of the given @device. A constraints can be skipped by + * passing NULL or an empty string as the constraint. + * + * Returns 0 for no match, and a positive integer on match. The return + * value is a relative score with larger values indicating better + * matches. The score is weighted for the most specific compatible value + * to get the highest score. Matching type is next, followed by matching + * name. Practically speaking, this results in the following priority + * order for matches: + * + * 1. specific compatible && type && name + * 2. specific compatible && type + * 3. specific compatible && name + * 4. specific compatible + * 5. general compatible && type && name + * 6. general compatible && type + * 7. general compatible && name + * 8. general compatible + * 9. type && name + * 10. type + * 11. name */ static int __of_device_is_compatible(const struct device_node *device, - const char *compat) -{ - const char* cp; - int cplen, l; + const char *compat, const char *type, const char *name) +{ + struct property *prop; + const char *cp; + int index = 0, score = 0; + + /* Compatible match has highest priority */ + if (compat && compat[0]) { + prop = __of_find_property(device, "compatible", NULL); + for (cp = of_prop_next_string(prop, NULL); cp; + cp = of_prop_next_string(prop, cp), index++) { + if (of_compat_cmp(cp, compat, strlen(compat)) == 0) { + score = INT_MAX/2 - (index << 2); + break; + } + } + if (!score) + return 0; + } - cp = __of_get_property(device, "compatible", &cplen); - if (cp == NULL) - return 0; - while (cplen > 0) { - if (of_compat_cmp(cp, compat, strlen(compat)) == 0) - return 1; - l = strlen(cp) + 1; - cp += l; - cplen -= l; + /* Matching type is better than matching name */ + if (type && type[0]) { + if (!device->type || of_node_cmp(type, device->type)) + return 0; + score += 2; } - return 0; + /* Matching name is a bit better than not */ + if (name && name[0]) { + if (!device->name || of_node_cmp(name, device->name)) + return 0; + score++; + } + + return score; } /** Checks if the given "compat" string matches one of the strings in @@ -375,7 +420,7 @@ int of_device_is_compatible(const struct device_node *device, int res; raw_spin_lock_irqsave(&devtree_lock, flags); - res = __of_device_is_compatible(device, compat); + res = __of_device_is_compatible(device, compat, NULL, NULL); raw_spin_unlock_irqrestore(&devtree_lock, flags); return res; } @@ -681,10 +726,7 @@ struct device_node *of_find_compatible_node(struct device_node *from, raw_spin_lock_irqsave(&devtree_lock, flags); np = from ? from->allnext : of_allnodes; for (; np; np = np->allnext) { - if (type - && !(np->type && (of_node_cmp(np->type, type) == 0))) - continue; - if (__of_device_is_compatible(np, compatible) && + if (__of_device_is_compatible(np, compatible, type, NULL) && of_node_get(np)) break; } @@ -734,25 +776,22 @@ static const struct of_device_id *__of_match_node(const struct of_device_id *matches, const struct device_node *node) { + const struct of_device_id *best_match = NULL; + int score, best_score = 0; + if (!matches) return NULL; - while (matches->name[0] || matches->type[0] || matches->compatible[0]) { - int match = 1; - if (matches->name[0]) - match &= node->name - && !strcmp(matches->name, node->name); - if (matches->type[0]) - match &= node->type - && !strcmp(matches->type, node->type); - if (matches->compatible[0]) - match &= __of_device_is_compatible(node, - matches->compatible); - if (match) - return matches; - matches++; + for (; matches->name[0] || matches->type[0] || matches->compatible[0]; matches++) { + score = __of_device_is_compatible(node, matches->compatible, + matches->type, matches->name); + if (score > best_score) { + best_match = matches; + best_score = score; + } } - return NULL; + + return best_match; } /** -- cgit v1.2.3 From b5190516b282bee6f10569c3387d16f83447d280 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Tue, 18 Feb 2014 21:46:16 +0000 Subject: of: Move testcase FDT data into drivers/of The testcase data is usable by any platform. This patch moves it into the drivers/of directory so it can be included by any architecture. Using the test cases requires manually adding #include to the end of the boards .dtsi file and enabling CONFIG_OF_SELFTEST. Not pretty though. A useful project would be to make the testcase code easier to execute. Signed-off-by: Grant Likely --- arch/arm/boot/dts/testcases/tests-interrupts.dtsi | 58 ----------------------- arch/arm/boot/dts/testcases/tests-phandle.dtsi | 39 --------------- arch/arm/boot/dts/testcases/tests.dtsi | 2 - arch/arm/boot/dts/versatile-pb.dts | 4 +- drivers/of/testcase-data/testcases.dtsi | 2 + drivers/of/testcase-data/tests-interrupts.dtsi | 58 +++++++++++++++++++++++ drivers/of/testcase-data/tests-phandle.dtsi | 39 +++++++++++++++ scripts/Makefile.lib | 1 + 8 files changed, 102 insertions(+), 101 deletions(-) delete mode 100644 arch/arm/boot/dts/testcases/tests-interrupts.dtsi delete mode 100644 arch/arm/boot/dts/testcases/tests-phandle.dtsi delete mode 100644 arch/arm/boot/dts/testcases/tests.dtsi create mode 100644 drivers/of/testcase-data/testcases.dtsi create mode 100644 drivers/of/testcase-data/tests-interrupts.dtsi create mode 100644 drivers/of/testcase-data/tests-phandle.dtsi diff --git a/arch/arm/boot/dts/testcases/tests-interrupts.dtsi b/arch/arm/boot/dts/testcases/tests-interrupts.dtsi deleted file mode 100644 index c843720bd3e5..000000000000 --- a/arch/arm/boot/dts/testcases/tests-interrupts.dtsi +++ /dev/null @@ -1,58 +0,0 @@ - -/ { - testcase-data { - interrupts { - #address-cells = <1>; - #size-cells = <1>; - test_intc0: intc0 { - interrupt-controller; - #interrupt-cells = <1>; - }; - - test_intc1: intc1 { - interrupt-controller; - #interrupt-cells = <3>; - }; - - test_intc2: intc2 { - interrupt-controller; - #interrupt-cells = <2>; - }; - - test_intmap0: intmap0 { - #interrupt-cells = <1>; - #address-cells = <0>; - interrupt-map = <1 &test_intc0 9>, - <2 &test_intc1 10 11 12>, - <3 &test_intc2 13 14>, - <4 &test_intc2 15 16>; - }; - - test_intmap1: intmap1 { - #interrupt-cells = <2>; - interrupt-map = <0x5000 1 2 &test_intc0 15>; - }; - - interrupts0 { - interrupt-parent = <&test_intc0>; - interrupts = <1>, <2>, <3>, <4>; - }; - - interrupts1 { - interrupt-parent = <&test_intmap0>; - interrupts = <1>, <2>, <3>, <4>; - }; - - interrupts-extended0 { - reg = <0x5000 0x100>; - interrupts-extended = <&test_intc0 1>, - <&test_intc1 2 3 4>, - <&test_intc2 5 6>, - <&test_intmap0 1>, - <&test_intmap0 2>, - <&test_intmap0 3>, - <&test_intmap1 1 2>; - }; - }; - }; -}; diff --git a/arch/arm/boot/dts/testcases/tests-phandle.dtsi b/arch/arm/boot/dts/testcases/tests-phandle.dtsi deleted file mode 100644 index 0007d3cd7dc2..000000000000 --- a/arch/arm/boot/dts/testcases/tests-phandle.dtsi +++ /dev/null @@ -1,39 +0,0 @@ - -/ { - testcase-data { - phandle-tests { - provider0: provider0 { - #phandle-cells = <0>; - }; - - provider1: provider1 { - #phandle-cells = <1>; - }; - - provider2: provider2 { - #phandle-cells = <2>; - }; - - provider3: provider3 { - #phandle-cells = <3>; - }; - - consumer-a { - phandle-list = <&provider1 1>, - <&provider2 2 0>, - <0>, - <&provider3 4 4 3>, - <&provider2 5 100>, - <&provider0>, - <&provider1 7>; - phandle-list-names = "first", "second", "third"; - - phandle-list-bad-phandle = <12345678 0 0>; - phandle-list-bad-args = <&provider2 1 0>, - <&provider3 0>; - empty-property; - unterminated-string = [40 41 42 43]; - }; - }; - }; -}; diff --git a/arch/arm/boot/dts/testcases/tests.dtsi b/arch/arm/boot/dts/testcases/tests.dtsi deleted file mode 100644 index 3f123ecc9dd7..000000000000 --- a/arch/arm/boot/dts/testcases/tests.dtsi +++ /dev/null @@ -1,2 +0,0 @@ -/include/ "tests-phandle.dtsi" -/include/ "tests-interrupts.dtsi" diff --git a/arch/arm/boot/dts/versatile-pb.dts b/arch/arm/boot/dts/versatile-pb.dts index f43907c40c93..65f657711323 100644 --- a/arch/arm/boot/dts/versatile-pb.dts +++ b/arch/arm/boot/dts/versatile-pb.dts @@ -1,4 +1,4 @@ -/include/ "versatile-ab.dts" +#include / { model = "ARM Versatile PB"; @@ -47,4 +47,4 @@ }; }; -/include/ "testcases/tests.dtsi" +#include diff --git a/drivers/of/testcase-data/testcases.dtsi b/drivers/of/testcase-data/testcases.dtsi new file mode 100644 index 000000000000..3cc2f55534ac --- /dev/null +++ b/drivers/of/testcase-data/testcases.dtsi @@ -0,0 +1,2 @@ +#include "tests-phandle.dtsi" +#include "tests-interrupts.dtsi" diff --git a/drivers/of/testcase-data/tests-interrupts.dtsi b/drivers/of/testcase-data/tests-interrupts.dtsi new file mode 100644 index 000000000000..c843720bd3e5 --- /dev/null +++ b/drivers/of/testcase-data/tests-interrupts.dtsi @@ -0,0 +1,58 @@ + +/ { + testcase-data { + interrupts { + #address-cells = <1>; + #size-cells = <1>; + test_intc0: intc0 { + interrupt-controller; + #interrupt-cells = <1>; + }; + + test_intc1: intc1 { + interrupt-controller; + #interrupt-cells = <3>; + }; + + test_intc2: intc2 { + interrupt-controller; + #interrupt-cells = <2>; + }; + + test_intmap0: intmap0 { + #interrupt-cells = <1>; + #address-cells = <0>; + interrupt-map = <1 &test_intc0 9>, + <2 &test_intc1 10 11 12>, + <3 &test_intc2 13 14>, + <4 &test_intc2 15 16>; + }; + + test_intmap1: intmap1 { + #interrupt-cells = <2>; + interrupt-map = <0x5000 1 2 &test_intc0 15>; + }; + + interrupts0 { + interrupt-parent = <&test_intc0>; + interrupts = <1>, <2>, <3>, <4>; + }; + + interrupts1 { + interrupt-parent = <&test_intmap0>; + interrupts = <1>, <2>, <3>, <4>; + }; + + interrupts-extended0 { + reg = <0x5000 0x100>; + interrupts-extended = <&test_intc0 1>, + <&test_intc1 2 3 4>, + <&test_intc2 5 6>, + <&test_intmap0 1>, + <&test_intmap0 2>, + <&test_intmap0 3>, + <&test_intmap1 1 2>; + }; + }; + }; +}; diff --git a/drivers/of/testcase-data/tests-phandle.dtsi b/drivers/of/testcase-data/tests-phandle.dtsi new file mode 100644 index 000000000000..0007d3cd7dc2 --- /dev/null +++ b/drivers/of/testcase-data/tests-phandle.dtsi @@ -0,0 +1,39 @@ + +/ { + testcase-data { + phandle-tests { + provider0: provider0 { + #phandle-cells = <0>; + }; + + provider1: provider1 { + #phandle-cells = <1>; + }; + + provider2: provider2 { + #phandle-cells = <2>; + }; + + provider3: provider3 { + #phandle-cells = <3>; + }; + + consumer-a { + phandle-list = <&provider1 1>, + <&provider2 2 0>, + <0>, + <&provider3 4 4 3>, + <&provider2 5 100>, + <&provider0>, + <&provider1 7>; + phandle-list-names = "first", "second", "third"; + + phandle-list-bad-phandle = <12345678 0 0>; + phandle-list-bad-args = <&provider2 1 0>, + <&provider3 0>; + empty-property; + unterminated-string = [40 41 42 43]; + }; + }; + }; +}; diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 49392ecbef17..79c059e70860 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -152,6 +152,7 @@ ld_flags = $(LDFLAGS) $(ldflags-y) dtc_cpp_flags = -Wp,-MD,$(depfile).pre.tmp -nostdinc \ -I$(srctree)/arch/$(SRCARCH)/boot/dts \ -I$(srctree)/arch/$(SRCARCH)/boot/dts/include \ + -I$(srctree)/drivers/of/testcase-data \ -undef -D__DTS__ # Finds the multi-part object the current object will be linked into -- cgit v1.2.3 From 1f42e5dd5065963979bb53daadf5d4f1e71f0c5f Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Tue, 18 Feb 2014 21:38:55 +0000 Subject: of: Add self test for of_match_node() Adds a selftest function for the of_match_node function. of_match_node is supposed to handle precedence for the compatible property as well as the name and device_type values. This patch adds some test case data and a function that makes sure each test node matches against the correct entry of an of_device_id table. This code was written to verify the new of_match_node() implementation that is an earlier part of this series. Signed-off-by: Grant Likely Cc: Kevin Hao --- drivers/of/selftest.c | 67 +++++++++++++++++++++++++++++++ drivers/of/testcase-data/testcases.dtsi | 1 + drivers/of/testcase-data/tests-match.dtsi | 19 +++++++++ 3 files changed, 87 insertions(+) create mode 100644 drivers/of/testcase-data/tests-match.dtsi diff --git a/drivers/of/selftest.c b/drivers/of/selftest.c index e21012bde639..6643d1920985 100644 --- a/drivers/of/selftest.c +++ b/drivers/of/selftest.c @@ -300,6 +300,72 @@ static void __init of_selftest_parse_interrupts_extended(void) of_node_put(np); } +static struct of_device_id match_node_table[] = { + { .data = "A", .name = "name0", }, /* Name alone is lowest priority */ + { .data = "B", .type = "type1", }, /* followed by type alone */ + + { .data = "Ca", .name = "name2", .type = "type1", }, /* followed by both together */ + { .data = "Cb", .name = "name2", }, /* Only match when type doesn't match */ + { .data = "Cc", .name = "name2", .type = "type2", }, + + { .data = "E", .compatible = "compat3" }, + { .data = "G", .compatible = "compat2", }, + { .data = "H", .compatible = "compat2", .name = "name5", }, + { .data = "I", .compatible = "compat2", .type = "type1", }, + { .data = "J", .compatible = "compat2", .type = "type1", .name = "name8", }, + { .data = "K", .compatible = "compat2", .name = "name9", }, + {} +}; + +static struct { + const char *path; + const char *data; +} match_node_tests[] = { + { .path = "/testcase-data/match-node/name0", .data = "A", }, + { .path = "/testcase-data/match-node/name1", .data = "B", }, + { .path = "/testcase-data/match-node/a/name2", .data = "Ca", }, + { .path = "/testcase-data/match-node/b/name2", .data = "Cb", }, + { .path = "/testcase-data/match-node/c/name2", .data = "Cc", }, + { .path = "/testcase-data/match-node/name3", .data = "E", }, + { .path = "/testcase-data/match-node/name4", .data = "G", }, + { .path = "/testcase-data/match-node/name5", .data = "H", }, + { .path = "/testcase-data/match-node/name6", .data = "G", }, + { .path = "/testcase-data/match-node/name7", .data = "I", }, + { .path = "/testcase-data/match-node/name8", .data = "J", }, + { .path = "/testcase-data/match-node/name9", .data = "K", }, +}; + +static void __init of_selftest_match_node(void) +{ + struct device_node *np; + const struct of_device_id *match; + int i; + + for (i = 0; i < ARRAY_SIZE(match_node_tests); i++) { + np = of_find_node_by_path(match_node_tests[i].path); + if (!np) { + selftest(0, "missing testcase node %s\n", + match_node_tests[i].path); + continue; + } + + match = of_match_node(match_node_table, np); + if (!match) { + selftest(0, "%s didn't match anything\n", + match_node_tests[i].path); + continue; + } + + if (strcmp(match->data, match_node_tests[i].data) != 0) { + selftest(0, "%s got wrong match. expected %s, got %s\n", + match_node_tests[i].path, match_node_tests[i].data, + (const char *)match->data); + continue; + } + selftest(1, "passed"); + } +} + static int __init of_selftest(void) { struct device_node *np; @@ -316,6 +382,7 @@ static int __init of_selftest(void) of_selftest_property_match_string(); of_selftest_parse_interrupts(); of_selftest_parse_interrupts_extended(); + of_selftest_match_node(); pr_info("end of selftest - %i passed, %i failed\n", selftest_results.passed, selftest_results.failed); return 0; diff --git a/drivers/of/testcase-data/testcases.dtsi b/drivers/of/testcase-data/testcases.dtsi index 3cc2f55534ac..3a5b75a8e4d7 100644 --- a/drivers/of/testcase-data/testcases.dtsi +++ b/drivers/of/testcase-data/testcases.dtsi @@ -1,2 +1,3 @@ #include "tests-phandle.dtsi" #include "tests-interrupts.dtsi" +#include "tests-match.dtsi" diff --git a/drivers/of/testcase-data/tests-match.dtsi b/drivers/of/testcase-data/tests-match.dtsi new file mode 100644 index 000000000000..c9e541129534 --- /dev/null +++ b/drivers/of/testcase-data/tests-match.dtsi @@ -0,0 +1,19 @@ + +/ { + testcase-data { + match-node { + name0 { }; + name1 { device_type = "type1"; }; + a { name2 { device_type = "type1"; }; }; + b { name2 { }; }; + c { name2 { device_type = "type2"; }; }; + name3 { compatible = "compat3"; }; + name4 { compatible = "compat2", "compat3"; }; + name5 { compatible = "compat2", "compat3"; }; + name6 { compatible = "compat1", "compat2", "compat3"; }; + name7 { compatible = "compat2"; device_type = "type1"; }; + name8 { compatible = "compat2"; device_type = "type1"; }; + name9 { compatible = "compat2"; }; + }; + }; +}; -- cgit v1.2.3 From 972157cac528f6cfd1f7e640139287951066106e Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 20 Feb 2014 12:19:08 +0100 Subject: arm/smmu: Use irqsafe spinlock for domain lock As the lock might be used through DMA-API which is allowed in interrupt context. Signed-off-by: Joerg Roedel Acked-by: Will Deacon --- drivers/iommu/arm-smmu.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 6fe7922ecc1d..1d9ab39af29f 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -1159,6 +1159,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) struct arm_smmu_domain *smmu_domain = domain->priv; struct arm_smmu_device *device_smmu = dev->archdata.iommu; struct arm_smmu_master *master; + unsigned long flags; if (!device_smmu) { dev_err(dev, "cannot attach to SMMU, is it on the same bus?\n"); @@ -1169,7 +1170,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) * Sanity check the domain. We don't currently support domains * that cross between different SMMU chains. */ - spin_lock(&smmu_domain->lock); + spin_lock_irqsave(&smmu_domain->lock, flags); if (!smmu_domain->leaf_smmu) { /* Now that we have a master, we can finalise the domain */ ret = arm_smmu_init_domain_context(domain, dev); @@ -1184,7 +1185,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) dev_name(device_smmu->dev)); goto err_unlock; } - spin_unlock(&smmu_domain->lock); + spin_unlock_irqrestore(&smmu_domain->lock, flags); /* Looks ok, so add the device to the domain */ master = find_smmu_master(smmu_domain->leaf_smmu, dev->of_node); @@ -1194,7 +1195,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) return arm_smmu_domain_add_master(smmu_domain, master); err_unlock: - spin_unlock(&smmu_domain->lock); + spin_unlock_irqrestore(&smmu_domain->lock, flags); return ret; } @@ -1396,6 +1397,7 @@ static int arm_smmu_handle_mapping(struct arm_smmu_domain *smmu_domain, struct arm_smmu_cfg *root_cfg = &smmu_domain->root_cfg; pgd_t *pgd = root_cfg->pgd; struct arm_smmu_device *smmu = root_cfg->smmu; + unsigned long irqflags; if (root_cfg->cbar == CBAR_TYPE_S2_TRANS) { stage = 2; @@ -1418,7 +1420,7 @@ static int arm_smmu_handle_mapping(struct arm_smmu_domain *smmu_domain, if (paddr & ~output_mask) return -ERANGE; - spin_lock(&smmu_domain->lock); + spin_lock_irqsave(&smmu_domain->lock, irqflags); pgd += pgd_index(iova); end = iova + size; do { @@ -1434,7 +1436,7 @@ static int arm_smmu_handle_mapping(struct arm_smmu_domain *smmu_domain, } while (pgd++, iova != end); out_unlock: - spin_unlock(&smmu_domain->lock); + spin_unlock_irqrestore(&smmu_domain->lock, irqflags); return ret; } -- cgit v1.2.3 From 8679059e360543b7afecd228ada6566da9f304a4 Mon Sep 17 00:00:00 2001 From: Peter Chen Date: Fri, 3 Jan 2014 16:45:13 +0800 Subject: usb: gadget: printer: using gadget_is_otg to check otg support at runtime We need to use gadget_is_otg to check if the gadget is really otg support at runtime, other composite gadget drivers have already followed this method. Signed-off-by: Peter Chen Signed-off-by: Felipe Balbi --- drivers/usb/gadget/printer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c index bf7a56b6d48a..69b76efd11e9 100644 --- a/drivers/usb/gadget/printer.c +++ b/drivers/usb/gadget/printer.c @@ -1157,7 +1157,7 @@ static int __init printer_bind_config(struct usb_configuration *c) usb_gadget_set_selfpowered(gadget); - if (gadget->is_otg) { + if (gadget_is_otg(gadget)) { otg_descriptor.bmAttributes |= USB_OTG_HNP; printer_cfg_driver.descriptors = otg_desc; printer_cfg_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP; -- cgit v1.2.3 From f0f42204d0cc04a63ac61fdaa3b6a269ea0dc08b Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Mon, 20 Jan 2014 08:33:50 +0100 Subject: usb: gadget: fix NULL pointer dereference Fix possible NULL pointer dereference introduced in commit 219580e (usb: f_fs: check quirk to pad epout buf size when not aligned to maxpacketsize) In cases we do wait with: wait_event_interruptible(epfile->wait, (ep = epfile->ep)); for endpoint to be enabled, functionfs_bind() has not been called yet and epfile->ffs->gadget is still NULL and the automatic variable 'gadget' has been initialized with NULL at the point of its definition. Later on it is used as a parameter to: usb_ep_align_maybe(gadget, ep->ep, len) which in turn dereferences it. This patch fixes it by moving the actual assignment to the local 'gadget' variable after the potential waiting has completed. Signed-off-by: Andrzej Pietrasiewicz Acked-by: Michal Nazarewicz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/f_fs.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index 306a2b52125c..2b4334394076 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c @@ -585,7 +585,6 @@ static ssize_t ffs_epfile_io(struct file *file, char __user *buf, size_t len, int read) { struct ffs_epfile *epfile = file->private_data; - struct usb_gadget *gadget = epfile->ffs->gadget; struct ffs_ep *ep; char *data = NULL; ssize_t ret, data_len; @@ -621,6 +620,12 @@ static ssize_t ffs_epfile_io(struct file *file, /* Allocate & copy */ if (!halt) { + /* + * if we _do_ wait above, the epfile->ffs->gadget might be NULL + * before the waiting completes, so do not assign to 'gadget' earlier + */ + struct usb_gadget *gadget = epfile->ffs->gadget; + /* * Controller may require buffer size to be aligned to * maxpacketsize of an out endpoint. -- cgit v1.2.3 From e7d613d1db6f968514ccd7f0cbebba031e6394d2 Mon Sep 17 00:00:00 2001 From: Josh Cartwright Date: Tue, 18 Feb 2014 10:36:29 -0600 Subject: usb: phy: msm: fix compilation errors when !CONFIG_PM_SLEEP Both the PM_RUNTIME and PM_SLEEP callbacks call into the common msm_otg_{suspend,resume} routines, however these routines are only being built when CONFIG_PM_SLEEP. In addition, msm_otg_{suspend,resume} also depends on msm_hsusb_config_vddcx(), which is only built when CONFIG_PM_SLEEP. Fix the CONFIG_PM_RUNTIME, !CONFIG_PM_SLEEP case by changing the preprocessor conditional, and moving msm_hsusb_config_vddcx(). While we're here, eliminate the CONFIG_PM conditional for setting up the dev_pm_ops. This address the following errors Russell King has hit doing randconfig builds: drivers/usb/phy/phy-msm-usb.c: In function 'msm_otg_runtime_suspend': drivers/usb/phy/phy-msm-usb.c:1691:2: error: implicit declaration of function 'msm_otg_suspend' drivers/usb/phy/phy-msm-usb.c: In function 'msm_otg_runtime_resume': drivers/usb/phy/phy-msm-usb.c:1699:2: error: implicit declaration of function 'msm_otg_resume' Cc: Ivan T. Ivanov Reported-by: Russell King Signed-off-by: Josh Cartwright Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-msm-usb.c | 57 ++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 31 deletions(-) diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c index 8546c8dccd51..d204f745ed05 100644 --- a/drivers/usb/phy/phy-msm-usb.c +++ b/drivers/usb/phy/phy-msm-usb.c @@ -159,32 +159,6 @@ put_3p3: return rc; } -#ifdef CONFIG_PM_SLEEP -#define USB_PHY_SUSP_DIG_VOL 500000 -static int msm_hsusb_config_vddcx(int high) -{ - int max_vol = USB_PHY_VDD_DIG_VOL_MAX; - int min_vol; - int ret; - - if (high) - min_vol = USB_PHY_VDD_DIG_VOL_MIN; - else - min_vol = USB_PHY_SUSP_DIG_VOL; - - ret = regulator_set_voltage(hsusb_vddcx, min_vol, max_vol); - if (ret) { - pr_err("%s: unable to set the voltage for regulator " - "HSUSB_VDDCX\n", __func__); - return ret; - } - - pr_debug("%s: min_vol:%d max_vol:%d\n", __func__, min_vol, max_vol); - - return ret; -} -#endif - static int msm_hsusb_ldo_set_mode(int on) { int ret = 0; @@ -440,7 +414,32 @@ static int msm_otg_reset(struct usb_phy *phy) #define PHY_SUSPEND_TIMEOUT_USEC (500 * 1000) #define PHY_RESUME_TIMEOUT_USEC (100 * 1000) -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_PM + +#define USB_PHY_SUSP_DIG_VOL 500000 +static int msm_hsusb_config_vddcx(int high) +{ + int max_vol = USB_PHY_VDD_DIG_VOL_MAX; + int min_vol; + int ret; + + if (high) + min_vol = USB_PHY_VDD_DIG_VOL_MIN; + else + min_vol = USB_PHY_SUSP_DIG_VOL; + + ret = regulator_set_voltage(hsusb_vddcx, min_vol, max_vol); + if (ret) { + pr_err("%s: unable to set the voltage for regulator " + "HSUSB_VDDCX\n", __func__); + return ret; + } + + pr_debug("%s: min_vol:%d max_vol:%d\n", __func__, min_vol, max_vol); + + return ret; +} + static int msm_otg_suspend(struct msm_otg *motg) { struct usb_phy *phy = &motg->phy; @@ -1733,22 +1732,18 @@ static int msm_otg_pm_resume(struct device *dev) } #endif -#ifdef CONFIG_PM static const struct dev_pm_ops msm_otg_dev_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(msm_otg_pm_suspend, msm_otg_pm_resume) SET_RUNTIME_PM_OPS(msm_otg_runtime_suspend, msm_otg_runtime_resume, msm_otg_runtime_idle) }; -#endif static struct platform_driver msm_otg_driver = { .remove = msm_otg_remove, .driver = { .name = DRIVER_NAME, .owner = THIS_MODULE, -#ifdef CONFIG_PM .pm = &msm_otg_dev_pm_ops, -#endif }, }; -- cgit v1.2.3 From 9ccfaf74e766d49a64f86943f98d0a82996d4dec Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Wed, 5 Feb 2014 15:34:18 +0100 Subject: usb: musb: correct use of schedule_delayed_work() schedule_delayed_work() takes the delay in jiffies, not msecs. This bug slipped in with the recent reset logic cleanup (8ed1fb790ea: "usb: musb: finish suspend/reset work independently from musb_hub_control()"). Signed-off-by: Daniel Mack Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_core.c | 3 ++- drivers/usb/musb/musb_virthub.c | 12 +++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index b49a5945c90c..239ad0b1ceb6 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -480,7 +480,8 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, musb->rh_timer = jiffies + msecs_to_jiffies(20); schedule_delayed_work( - &musb->finish_resume_work, 20); + &musb->finish_resume_work, + msecs_to_jiffies(20)); musb->xceiv->state = OTG_STATE_A_HOST; musb->is_active = 1; diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c index 32f49e1efa9c..e2d2d8c9891b 100644 --- a/drivers/usb/musb/musb_virthub.c +++ b/drivers/usb/musb/musb_virthub.c @@ -135,7 +135,8 @@ void musb_port_suspend(struct musb *musb, bool do_suspend) /* later, GetPortStatus will stop RESUME signaling */ musb->port1_status |= MUSB_PORT_STAT_RESUME; - schedule_delayed_work(&musb->finish_resume_work, 20); + schedule_delayed_work(&musb->finish_resume_work, + msecs_to_jiffies(20)); } } @@ -171,8 +172,7 @@ void musb_port_reset(struct musb *musb, bool do_reset) if (musb->rh_timer > 0 && remain > 0) { /* take into account the minimum delay after resume */ schedule_delayed_work( - &musb->deassert_reset_work, - jiffies_to_msecs(remain)); + &musb->deassert_reset_work, remain); return; } @@ -180,7 +180,8 @@ void musb_port_reset(struct musb *musb, bool do_reset) power & ~MUSB_POWER_RESUME); /* Give the core 1 ms to clear MUSB_POWER_RESUME */ - schedule_delayed_work(&musb->deassert_reset_work, 1); + schedule_delayed_work(&musb->deassert_reset_work, + msecs_to_jiffies(1)); return; } @@ -190,7 +191,8 @@ void musb_port_reset(struct musb *musb, bool do_reset) musb->port1_status |= USB_PORT_STAT_RESET; musb->port1_status &= ~USB_PORT_STAT_ENABLE; - schedule_delayed_work(&musb->deassert_reset_work, 50); + schedule_delayed_work(&musb->deassert_reset_work, + msecs_to_jiffies(50)); } else { dev_dbg(musb->controller, "root port reset stopped\n"); musb_writeb(mbase, MUSB_POWER, -- cgit v1.2.3 From 967f038e491bc0aa469c4187aab7715ee9069ae1 Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 20 Feb 2014 16:08:12 +0000 Subject: Sparc: sparc_cpu_model isn't in asm/system.h any more [ver #2] sparc_cpu_model isn't in asm/system.h any more, so remove a comment about it. Signed-off-by: David Howells cc: "David S. Miller" cc: sparclinux@vger.kernel.org Signed-off-by: David S. Miller --- drivers/sbus/char/jsflash.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/sbus/char/jsflash.c b/drivers/sbus/char/jsflash.c index 6b4678a7900a..4ccb5d869389 100644 --- a/drivers/sbus/char/jsflash.c +++ b/drivers/sbus/char/jsflash.c @@ -507,7 +507,6 @@ static int jsflash_init(void) } /* Let us be really paranoid for modifications to probing code. */ - /* extern enum sparc_cpu sparc_cpu_model; */ /* in */ if (sparc_cpu_model != sun4m) { /* We must be on sun4m because we use MMU Bypass ASI. */ return -ENXIO; -- cgit v1.2.3 From b080e047a61f7050246ff3081f87832997170d29 Mon Sep 17 00:00:00 2001 From: Brian Campbell Date: Sun, 16 Feb 2014 22:58:12 -0500 Subject: user_namespace.c: Remove duplicated word in comment Signed-off-by: Brian Campbell Signed-off-by: Linus Torvalds --- kernel/user_namespace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c index 240fb62cf394..dd06439b9c84 100644 --- a/kernel/user_namespace.c +++ b/kernel/user_namespace.c @@ -225,7 +225,7 @@ static u32 map_id_up(struct uid_gid_map *map, u32 id) * * When there is no mapping defined for the user-namespace uid * pair INVALID_UID is returned. Callers are expected to test - * for and handle handle INVALID_UID being returned. INVALID_UID + * for and handle INVALID_UID being returned. INVALID_UID * may be tested for using uid_valid(). */ kuid_t make_kuid(struct user_namespace *ns, uid_t uid) -- cgit v1.2.3 From e284175a96e5af087ea7806b3e38282b524ff5b9 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Thu, 20 Feb 2014 17:23:16 +0800 Subject: ACPI / nouveau: fix probing regression related to _DSM Fix regression caused by commit b072e53, which breaks loading nouveau driver on optimus laptops. On some platforms, ACPI _DSM method (nouveau_op_dsm_muid, function 0) has special requirements on the fourth parameter, which is different from ACPI specifications. So revert to the private implementation to check availability of _DSM functions instead of using common acpi_check_dsm() interface. Fixes: b072e53b0a27 (ACPI / nouveau: replace open-coded _DSM code with helper functions) Reported-and-tested-by: Maarten Lankhorst [rjw: Subject] Signed-off-by: Jiang Liu Signed-off-by: Rafael J. Wysocki --- drivers/gpu/drm/nouveau/nouveau_acpi.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c index 4ef83df2b246..83face3f608f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c @@ -106,6 +106,29 @@ static int nouveau_optimus_dsm(acpi_handle handle, int func, int arg, uint32_t * return 0; } +/* + * On some platforms, _DSM(nouveau_op_dsm_muid, func0) has special + * requirements on the fourth parameter, so a private implementation + * instead of using acpi_check_dsm(). + */ +static int nouveau_check_optimus_dsm(acpi_handle handle) +{ + int result; + + /* + * Function 0 returns a Buffer containing available functions. + * The args parameter is ignored for function 0, so just put 0 in it + */ + if (nouveau_optimus_dsm(handle, 0, 0, &result)) + return 0; + + /* + * ACPI Spec v4 9.14.1: if bit 0 is zero, no function is supported. + * If the n-th bit is enabled, function n is supported + */ + return result & 1 && result & (1 << NOUVEAU_DSM_OPTIMUS_CAPS); +} + static int nouveau_dsm(acpi_handle handle, int func, int arg) { int ret = 0; @@ -207,8 +230,7 @@ static int nouveau_dsm_pci_probe(struct pci_dev *pdev) 1 << NOUVEAU_DSM_POWER)) retval |= NOUVEAU_DSM_HAS_MUX; - if (acpi_check_dsm(dhandle, nouveau_op_dsm_muid, 0x00000100, - 1 << NOUVEAU_DSM_OPTIMUS_CAPS)) + if (nouveau_check_optimus_dsm(dhandle)) retval |= NOUVEAU_DSM_HAS_OPT; if (retval & NOUVEAU_DSM_HAS_OPT) { -- cgit v1.2.3 From acc3d5cec84f82ebea535fa0bd9500ac3df2aee9 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Thu, 20 Feb 2014 12:58:15 -0700 Subject: regulator: core: Change dummy supplies error message to a warning Change "dummy supplies not allowed" error message to warning instead, as this is a just warning message with no change to the behavior. [Added a CC to stable since some other bug fixes cause this to come up more frequently on PCs which is how it was noticed -- broonie] Signed-off-by: Shuah Khan Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- drivers/regulator/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index b38a6b669e8c..74e9fb2e52e7 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1352,7 +1352,7 @@ static struct regulator *_regulator_get(struct device *dev, const char *id, goto found; /* Don't log an error when called from regulator_get_optional() */ } else if (!have_full_constraints() || exclusive) { - dev_err(dev, "dummy supplies not allowed\n"); + dev_warn(dev, "dummy supplies not allowed\n"); } mutex_unlock(®ulator_list_mutex); -- cgit v1.2.3 From 4042e7570cff740460b75c6fc604c629621d3dd2 Mon Sep 17 00:00:00 2001 From: Dirk Brandewie Date: Wed, 12 Feb 2014 10:01:06 -0800 Subject: intel_pstate: Use LFM bus ratio as min ratio/P state LFM (max efficiency ratio) is the max frequency at minimum voltage supported by the processor. Using LFM as the minimum P state increases performmance without affecting power. By not using P states below LFM we avoid using P states that are less power efficient. Signed-off-by: Dirk Brandewie Cc: 3.13+ # 3.13+ Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/intel_pstate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index c788abf1c457..deb04cc64ba1 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -357,7 +357,7 @@ static int byt_get_min_pstate(void) { u64 value; rdmsrl(BYT_RATIOS, value); - return value & 0xFF; + return (value >> 8) & 0xFF; } static int byt_get_max_pstate(void) -- cgit v1.2.3 From 61d8d2abc15e9232c3914c55502b73e559366583 Mon Sep 17 00:00:00 2001 From: Dirk Brandewie Date: Wed, 12 Feb 2014 10:01:07 -0800 Subject: intel_pstate: Add support for Baytrail turbo P states A documentation update exposed the existance of the turbo ratio register. Update baytrail support to use the turbo range. Signed-off-by: Dirk Brandewie Cc: 3.13+ # 3.13+ Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/intel_pstate.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index deb04cc64ba1..e90816105921 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -34,8 +34,10 @@ #define SAMPLE_COUNT 3 -#define BYT_RATIOS 0x66a -#define BYT_VIDS 0x66b +#define BYT_RATIOS 0x66a +#define BYT_VIDS 0x66b +#define BYT_TURBO_RATIOS 0x66c + #define FRAC_BITS 8 #define int_tofp(X) ((int64_t)(X) << FRAC_BITS) @@ -367,6 +369,13 @@ static int byt_get_max_pstate(void) return (value >> 16) & 0xFF; } +static int byt_get_turbo_pstate(void) +{ + u64 value; + rdmsrl(BYT_TURBO_RATIOS, value); + return value & 0x3F; +} + static void byt_set_pstate(struct cpudata *cpudata, int pstate) { u64 val; @@ -469,7 +478,7 @@ static struct cpu_defaults byt_params = { .funcs = { .get_max = byt_get_max_pstate, .get_min = byt_get_min_pstate, - .get_turbo = byt_get_max_pstate, + .get_turbo = byt_get_turbo_pstate, .set = byt_set_pstate, .get_vid = byt_get_vid, }, -- cgit v1.2.3 From 0cb1c3e853e0d0f996f4e11863407bf31e6b7343 Mon Sep 17 00:00:00 2001 From: Stanislav Kholmanskikh Date: Mon, 27 Jan 2014 11:04:33 +0400 Subject: watchdog: w83697hf_wdt: return ENODEV if no device was found Most WDT driver modules return ENODEV during modprobe if no valid device was found, but w83697hf_wdt returns EIO. Let w83697hf_wdt return ENODEV. Signed-off-by: Stanislav Kholmanskikh Reviewed-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/w83697hf_wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/watchdog/w83697hf_wdt.c b/drivers/watchdog/w83697hf_wdt.c index aaf2995d37f4..68b45fc9ba6a 100644 --- a/drivers/watchdog/w83697hf_wdt.c +++ b/drivers/watchdog/w83697hf_wdt.c @@ -402,7 +402,7 @@ static int __init wdt_init(void) if (!found) { pr_err("No W83697HF/HG could be found\n"); - ret = -EIO; + ret = -ENODEV; goto out; } -- cgit v1.2.3 From 3d5f35bdfdef5fd627afe9b4bf9c4f32d17f4593 Mon Sep 17 00:00:00 2001 From: Juri Lelli Date: Thu, 20 Feb 2014 09:19:39 +0100 Subject: sched/deadline: Fix bad accounting of nr_running Rostedt writes: My test suite was locking up hard when enabling mmiotracer. This was due to the mmiotracer placing all but one CPU offline. I found this out when I was able to reproduce the bug with just my stress-cpu-hotplug test. This bug baffled me because it would not always trigger, and would only trigger on the first run after boot up. The stress-cpu-hotplug test would crash hard the first run, or never crash at all. But a new reboot may cause it to crash on the first run again. I spent all week bisecting this, as I couldn't find a consistent reproducer. I finally narrowed it down to the sched deadline patches, and even more peculiar, to the commit that added the sched deadline boot up self test to the latency tracer. Then it dawned on me to what the bug was. All it took was to run a task under sched deadline to screw up the CPU hot plugging. This explained why it would lock up only on the first run of the stress-cpu-hotplug test. The bug happened when the boot up self test of the schedule latency tracer would test a deadline task. The deadline task would corrupt something that would cause CPU hotplug to fail. If it didn't corrupt it, the stress test would always work (there's no other sched deadline tasks that would run to cause problems). If it did corrupt on boot up, the first test would lockup hard. I proved this theory by running my deadline test program on another box, and then run the stress-cpu-hotplug test, and it would now consistently lock up. I could run stress-cpu-hotplug over and over with no problem, but once I ran the deadline test, the next run of the stress-cpu-hotplug would lock hard. After adding lots of tracing to the code, I found the cause. The function tracer showed that migrate_tasks() was stuck in an infinite loop, where rq->nr_running never equaled 1 to break out of it. When I added a trace_printk() to see what that number was, it was 335 and never decrementing! Looking at the deadline code I found: static void __dequeue_task_dl(struct rq *rq, struct task_struct *p, int flags) { dequeue_dl_entity(&p->dl); dequeue_pushable_dl_task(rq, p); } static void dequeue_task_dl(struct rq *rq, struct task_struct *p, int flags) { update_curr_dl(rq); __dequeue_task_dl(rq, p, flags); dec_nr_running(rq); } And this: if (dl_runtime_exceeded(rq, dl_se)) { __dequeue_task_dl(rq, curr, 0); if (likely(start_dl_timer(dl_se, curr->dl.dl_boosted))) dl_se->dl_throttled = 1; else enqueue_task_dl(rq, curr, ENQUEUE_REPLENISH); if (!is_leftmost(curr, &rq->dl)) resched_task(curr); } Notice how we call __dequeue_task_dl() and in the else case we call enqueue_task_dl()? Also notice that dequeue_task_dl() has underscores where enqueue_task_dl() does not. The enqueue_task_dl() calls inc_nr_running(rq), but __dequeue_task_dl() does not. This is where we get nr_running out of sync. [snip] Another point where nr_running can get out of sync is when the dl_timer fires: dl_se->dl_throttled = 0; if (p->on_rq) { enqueue_task_dl(rq, p, ENQUEUE_REPLENISH); if (task_has_dl_policy(rq->curr)) check_preempt_curr_dl(rq, p, 0); else resched_task(rq->curr); This patch does two things: - correctly accounts for throttled tasks (that are now considered !running); - fixes the bug, updating nr_running from {inc,dec}_dl_tasks(), since we risk to update it twice in some situations (e.g., a task is dequeued while it has exceeded its budget). Cc: mingo@redhat.com Cc: torvalds@linux-foundation.org Cc: akpm@linux-foundation.org Reported-by: Steven Rostedt Reviewed-by: Steven Rostedt Tested-by: Steven Rostedt Signed-off-by: Juri Lelli Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1392884379-13744-1-git-send-email-juri.lelli@gmail.com Signed-off-by: Thomas Gleixner --- kernel/sched/deadline.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c index 0dd5e0971a07..b819577c21de 100644 --- a/kernel/sched/deadline.c +++ b/kernel/sched/deadline.c @@ -717,6 +717,7 @@ void inc_dl_tasks(struct sched_dl_entity *dl_se, struct dl_rq *dl_rq) WARN_ON(!dl_prio(prio)); dl_rq->dl_nr_running++; + inc_nr_running(rq_of_dl_rq(dl_rq)); inc_dl_deadline(dl_rq, deadline); inc_dl_migration(dl_se, dl_rq); @@ -730,6 +731,7 @@ void dec_dl_tasks(struct sched_dl_entity *dl_se, struct dl_rq *dl_rq) WARN_ON(!dl_prio(prio)); WARN_ON(!dl_rq->dl_nr_running); dl_rq->dl_nr_running--; + dec_nr_running(rq_of_dl_rq(dl_rq)); dec_dl_deadline(dl_rq, dl_se->deadline); dec_dl_migration(dl_se, dl_rq); @@ -836,8 +838,6 @@ static void enqueue_task_dl(struct rq *rq, struct task_struct *p, int flags) if (!task_current(rq, p) && p->nr_cpus_allowed > 1) enqueue_pushable_dl_task(rq, p); - - inc_nr_running(rq); } static void __dequeue_task_dl(struct rq *rq, struct task_struct *p, int flags) @@ -850,8 +850,6 @@ static void dequeue_task_dl(struct rq *rq, struct task_struct *p, int flags) { update_curr_dl(rq); __dequeue_task_dl(rq, p, flags); - - dec_nr_running(rq); } /* -- cgit v1.2.3 From 4df1638cfaf9b2b7ad993979a41965acab9cd156 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Wed, 19 Feb 2014 13:53:35 -0500 Subject: sched/deadline: Fix overflow to handle period==0 and deadline!=0 While debugging the crash with the bad nr_running accounting, I hit another bug where, after running my sched deadline test, I was getting failures to take a CPU offline. It was giving me a -EBUSY error. Adding a bunch of trace_printk()s around, I found that the cpu notifier that called sched_cpu_inactive() was returning a failure. The overflow value was coming up negative? Talking this over with Juri, the problem is that the total_bw update was suppose to be made by dl_overflow() which, during my tests, seemed to not be called. Adding more trace_printk()s, it wasn't that it wasn't called, but it exited out right away with the check of new_bw being equal to p->dl.dl_bw. The new_bw calculates the ratio between period and runtime. The bug is that if you set a deadline, you do not need to set a period if you plan on the period being equal to the deadline. That is, if period is zero and deadline is not, then the system call should set the period to be equal to the deadline. This is done elsewhere in the code. The fix is easy, check if period is set, and if it is not, then use the deadline. Cc: Juri Lelli Cc: Ingo Molnar Cc: Linus Torvalds Cc: Andrew Morton Signed-off-by: Steven Rostedt Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/20140219135335.7e74abd4@gandalf.local.home Signed-off-by: Thomas Gleixner --- kernel/sched/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index b46131ef6aab..24914488da41 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -1952,7 +1952,7 @@ static int dl_overflow(struct task_struct *p, int policy, { struct dl_bw *dl_b = dl_bw_of(task_cpu(p)); - u64 period = attr->sched_period; + u64 period = attr->sched_period ?: attr->sched_deadline; u64 runtime = attr->sched_runtime; u64 new_bw = dl_policy(policy) ? to_ratio(period, runtime) : 0; int cpus, err = -1; -- cgit v1.2.3 From e9e7cb38c21c80c82af4b16608bb4c8c5ec6a28e Mon Sep 17 00:00:00 2001 From: Juri Lelli Date: Tue, 11 Feb 2014 09:24:26 +0100 Subject: sched/core: Fix sched_rt_global_validate Don't compare sysctl_sched_rt_runtime against sysctl_sched_rt_period if the former is equal to RUNTIME_INF, otherwise disabling -rt bandwidth management (with CONFIG_RT_GROUP_SCHED=n) fails. Cc: Ingo Molnar Signed-off-by: Juri Lelli Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1392107067-19907-2-git-send-email-juri.lelli@gmail.com Signed-off-by: Thomas Gleixner --- kernel/sched/core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 24914488da41..98d33c105252 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -7475,7 +7475,8 @@ static int sched_rt_global_validate(void) if (sysctl_sched_rt_period <= 0) return -EINVAL; - if (sysctl_sched_rt_runtime > sysctl_sched_rt_period) + if ((sysctl_sched_rt_runtime != RUNTIME_INF) && + (sysctl_sched_rt_runtime > sysctl_sched_rt_period)) return -EINVAL; return 0; -- cgit v1.2.3 From 495163420ab5398c84af96ca3eae2c6aa4a140da Mon Sep 17 00:00:00 2001 From: Juri Lelli Date: Tue, 11 Feb 2014 09:24:27 +0100 Subject: sched/core: Make dl_b->lock IRQ safe Fix this lockdep warning: [ 44.804600] ========================================================= [ 44.805746] [ INFO: possible irq lock inversion dependency detected ] [ 44.805746] 3.14.0-rc2-test+ #14 Not tainted [ 44.805746] --------------------------------------------------------- [ 44.805746] bash/3674 just changed the state of lock: [ 44.805746] (&dl_b->lock){+.....}, at: [] sched_rt_handler+0x132/0x248 [ 44.805746] but this lock was taken by another, HARDIRQ-safe lock in the past: [ 44.805746] (&rq->lock){-.-.-.} and interrupts could create inverse lock ordering between them. [ 44.805746] [ 44.805746] other info that might help us debug this: [ 44.805746] Possible interrupt unsafe locking scenario: [ 44.805746] [ 44.805746] CPU0 CPU1 [ 44.805746] ---- ---- [ 44.805746] lock(&dl_b->lock); [ 44.805746] local_irq_disable(); [ 44.805746] lock(&rq->lock); [ 44.805746] lock(&dl_b->lock); [ 44.805746] [ 44.805746] lock(&rq->lock); by making dl_b->lock acquiring always IRQ safe. Cc: Ingo Molnar Signed-off-by: Juri Lelli Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1392107067-19907-3-git-send-email-juri.lelli@gmail.com Signed-off-by: Thomas Gleixner --- kernel/sched/core.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 98d33c105252..33d030a133d2 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -7422,6 +7422,7 @@ static int sched_dl_global_constraints(void) u64 period = global_rt_period(); u64 new_bw = to_ratio(period, runtime); int cpu, ret = 0; + unsigned long flags; /* * Here we want to check the bandwidth not being set to some @@ -7435,10 +7436,10 @@ static int sched_dl_global_constraints(void) for_each_possible_cpu(cpu) { struct dl_bw *dl_b = dl_bw_of(cpu); - raw_spin_lock(&dl_b->lock); + raw_spin_lock_irqsave(&dl_b->lock, flags); if (new_bw < dl_b->total_bw) ret = -EBUSY; - raw_spin_unlock(&dl_b->lock); + raw_spin_unlock_irqrestore(&dl_b->lock, flags); if (ret) break; @@ -7451,6 +7452,7 @@ static void sched_dl_do_global(void) { u64 new_bw = -1; int cpu; + unsigned long flags; def_dl_bandwidth.dl_period = global_rt_period(); def_dl_bandwidth.dl_runtime = global_rt_runtime(); @@ -7464,9 +7466,9 @@ static void sched_dl_do_global(void) for_each_possible_cpu(cpu) { struct dl_bw *dl_b = dl_bw_of(cpu); - raw_spin_lock(&dl_b->lock); + raw_spin_lock_irqsave(&dl_b->lock, flags); dl_b->bw = new_bw; - raw_spin_unlock(&dl_b->lock); + raw_spin_unlock_irqrestore(&dl_b->lock, flags); } } -- cgit v1.2.3 From 3cf1962cdbf6b3a9e3ef21116d215bbab350ea37 Mon Sep 17 00:00:00 2001 From: Rik van Riel Date: Tue, 18 Feb 2014 17:12:44 -0500 Subject: sched,numa: add cond_resched to task_numa_work Normally task_numa_work scans over a fairly small amount of memory, but it is possible to run into a large unpopulated part of virtual memory, with no pages mapped. In that case, task_numa_work can run for a while, and it may make sense to reschedule as required. Cc: akpm@linux-foundation.org Cc: Andrea Arcangeli Signed-off-by: Rik van Riel Reported-by: Xing Gang Tested-by: Chegu Vinod Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1392761566-24834-2-git-send-email-riel@redhat.com Signed-off-by: Thomas Gleixner --- kernel/sched/fair.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 966cc2bfcb77..78157099b167 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -1757,6 +1757,8 @@ void task_numa_work(struct callback_head *work) start = end; if (pages <= 0) goto out; + + cond_resched(); } while (end != vma->vm_end); } -- cgit v1.2.3 From 4efbc454ba68def5ef285b26ebfcfdb605b52755 Mon Sep 17 00:00:00 2001 From: Vegard Nossum Date: Sun, 16 Feb 2014 22:24:17 +0100 Subject: sched: Fix information leak in sys_sched_getattr() We're copying the on-stack structure to userspace, but forgot to give the right number of bytes to copy. This allows the calling process to obtain up to PAGE_SIZE bytes from the stack (and possibly adjacent kernel memory). This fix copies only as much as we actually have on the stack (attr->size defaults to the size of the struct) and leaves the rest of the userspace-provided buffer untouched. Found using kmemcheck + trinity. Fixes: d50dde5a10f30 ("sched: Add new scheduler syscalls to support an extended scheduling parameters ABI") Cc: Dario Faggioli Cc: Juri Lelli Cc: Ingo Molnar Signed-off-by: Vegard Nossum Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1392585857-10725-1-git-send-email-vegard.nossum@oracle.com Signed-off-by: Thomas Gleixner --- kernel/sched/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 33d030a133d2..a6e7470166c7 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -3786,7 +3786,7 @@ static int sched_read_attr(struct sched_attr __user *uattr, attr->size = usize; } - ret = copy_to_user(uattr, attr, usize); + ret = copy_to_user(uattr, attr, attr->size); if (ret) return -EFAULT; -- cgit v1.2.3 From 6d35ab48090b10c5ea5604ed5d6e91f302dc6060 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Fri, 14 Feb 2014 17:19:29 +0100 Subject: sched: Add 'flags' argument to sched_{set,get}attr() syscalls Because of a recent syscall design debate; its deemed appropriate for each syscall to have a flags argument for future extension; without immediately requiring new syscalls. Cc: juri.lelli@gmail.com Cc: Ingo Molnar Suggested-by: Michael Kerrisk Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/20140214161929.GL27965@twins.programming.kicks-ass.net Signed-off-by: Thomas Gleixner --- include/linux/syscalls.h | 6 ++++-- kernel/sched/core.c | 11 ++++++----- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 40ed9e9a77e5..a747a77ea584 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -281,13 +281,15 @@ asmlinkage long sys_sched_setscheduler(pid_t pid, int policy, asmlinkage long sys_sched_setparam(pid_t pid, struct sched_param __user *param); asmlinkage long sys_sched_setattr(pid_t pid, - struct sched_attr __user *attr); + struct sched_attr __user *attr, + unsigned int flags); asmlinkage long sys_sched_getscheduler(pid_t pid); asmlinkage long sys_sched_getparam(pid_t pid, struct sched_param __user *param); asmlinkage long sys_sched_getattr(pid_t pid, struct sched_attr __user *attr, - unsigned int size); + unsigned int size, + unsigned int flags); asmlinkage long sys_sched_setaffinity(pid_t pid, unsigned int len, unsigned long __user *user_mask_ptr); asmlinkage long sys_sched_getaffinity(pid_t pid, unsigned int len, diff --git a/kernel/sched/core.c b/kernel/sched/core.c index a6e7470166c7..6edbef296ece 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -3661,13 +3661,14 @@ SYSCALL_DEFINE2(sched_setparam, pid_t, pid, struct sched_param __user *, param) * @pid: the pid in question. * @uattr: structure containing the extended parameters. */ -SYSCALL_DEFINE2(sched_setattr, pid_t, pid, struct sched_attr __user *, uattr) +SYSCALL_DEFINE3(sched_setattr, pid_t, pid, struct sched_attr __user *, uattr, + unsigned int, flags) { struct sched_attr attr; struct task_struct *p; int retval; - if (!uattr || pid < 0) + if (!uattr || pid < 0 || flags) return -EINVAL; if (sched_copy_attr(uattr, &attr)) @@ -3804,8 +3805,8 @@ err_size: * @uattr: structure containing the extended parameters. * @size: sizeof(attr) for fwd/bwd comp. */ -SYSCALL_DEFINE3(sched_getattr, pid_t, pid, struct sched_attr __user *, uattr, - unsigned int, size) +SYSCALL_DEFINE4(sched_getattr, pid_t, pid, struct sched_attr __user *, uattr, + unsigned int, size, unsigned int, flags) { struct sched_attr attr = { .size = sizeof(struct sched_attr), @@ -3814,7 +3815,7 @@ SYSCALL_DEFINE3(sched_getattr, pid_t, pid, struct sched_attr __user *, uattr, int retval; if (!uattr || pid < 0 || size > PAGE_SIZE || - size < SCHED_ATTR_SIZE_VER0) + size < SCHED_ATTR_SIZE_VER0 || flags) return -EINVAL; rcu_read_lock(); -- cgit v1.2.3 From 82b95800b256205cff2eeab5bbd03430d2d0f20d Mon Sep 17 00:00:00 2001 From: Boris Ostrovsky Date: Mon, 17 Feb 2014 09:12:33 -0500 Subject: sched/deadline: Test for CPU's presence explicitly A hot-removed CPU may have ID that is numerically larger than the number of existing CPUs in the system (e.g. we can unplug CPU 4 from a system that has CPUs 0, 1 and 4). Thus the WARN_ONs should check whether the CPU in question is currently present, not whether its ID value is less than num_present_cpus(). Cc: Ingo Molnar Cc: Juri Lelli Cc: Steven Rostedt Reported-by: Konrad Rzeszutek Wilk Signed-off-by: Boris Ostrovsky Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1392646353-1874-1-git-send-email-boris.ostrovsky@oracle.com Signed-off-by: Thomas Gleixner --- kernel/sched/cpudeadline.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/sched/cpudeadline.c b/kernel/sched/cpudeadline.c index 045fc74e3f09..5b8838b56d1c 100644 --- a/kernel/sched/cpudeadline.c +++ b/kernel/sched/cpudeadline.c @@ -70,7 +70,7 @@ static void cpudl_heapify(struct cpudl *cp, int idx) static void cpudl_change_key(struct cpudl *cp, int idx, u64 new_dl) { - WARN_ON(idx > num_present_cpus() || idx == IDX_INVALID); + WARN_ON(!cpu_present(idx) || idx == IDX_INVALID); if (dl_time_before(new_dl, cp->elements[idx].dl)) { cp->elements[idx].dl = new_dl; @@ -117,7 +117,7 @@ int cpudl_find(struct cpudl *cp, struct task_struct *p, } out: - WARN_ON(best_cpu > num_present_cpus() && best_cpu != -1); + WARN_ON(!cpu_present(best_cpu) && best_cpu != -1); return best_cpu; } @@ -137,7 +137,7 @@ void cpudl_set(struct cpudl *cp, int cpu, u64 dl, int is_valid) int old_idx, new_cpu; unsigned long flags; - WARN_ON(cpu > num_present_cpus()); + WARN_ON(!cpu_present(cpu)); raw_spin_lock_irqsave(&cp->lock, flags); old_idx = cp->cpu_to_idx[cpu]; -- cgit v1.2.3 From 995b9ea440862def83e8fcb1b498e68f93d4af59 Mon Sep 17 00:00:00 2001 From: Kirill Tkhai Date: Tue, 18 Feb 2014 02:24:13 +0400 Subject: sched/deadline: Remove useless dl_nr_total In deadline class we do not have group scheduling like in RT. dl_nr_total is the same as dl_nr_running. So, one of them should be removed. Cc: Ingo Molnar Cc: Juri Lelli Signed-off-by: Kirill Tkhai Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/368631392675853@web20h.yandex.ru Signed-off-by: Thomas Gleixner --- kernel/sched/deadline.c | 4 +--- kernel/sched/sched.h | 1 - 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c index b819577c21de..15cbc17fbf84 100644 --- a/kernel/sched/deadline.c +++ b/kernel/sched/deadline.c @@ -121,7 +121,7 @@ static inline void dl_clear_overload(struct rq *rq) static void update_dl_migration(struct dl_rq *dl_rq) { - if (dl_rq->dl_nr_migratory && dl_rq->dl_nr_total > 1) { + if (dl_rq->dl_nr_migratory && dl_rq->dl_nr_running > 1) { if (!dl_rq->overloaded) { dl_set_overload(rq_of_dl_rq(dl_rq)); dl_rq->overloaded = 1; @@ -137,7 +137,6 @@ static void inc_dl_migration(struct sched_dl_entity *dl_se, struct dl_rq *dl_rq) struct task_struct *p = dl_task_of(dl_se); dl_rq = &rq_of_dl_rq(dl_rq)->dl; - dl_rq->dl_nr_total++; if (p->nr_cpus_allowed > 1) dl_rq->dl_nr_migratory++; @@ -149,7 +148,6 @@ static void dec_dl_migration(struct sched_dl_entity *dl_se, struct dl_rq *dl_rq) struct task_struct *p = dl_task_of(dl_se); dl_rq = &rq_of_dl_rq(dl_rq)->dl; - dl_rq->dl_nr_total--; if (p->nr_cpus_allowed > 1) dl_rq->dl_nr_migratory--; diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index c2119fd20f8b..f964add50f38 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -462,7 +462,6 @@ struct dl_rq { } earliest_dl; unsigned long dl_nr_migratory; - unsigned long dl_nr_total; int overloaded; /* -- cgit v1.2.3 From e194fd8a5d8e0a7eeed239a8534460724b62fe2d Mon Sep 17 00:00:00 2001 From: Arve HjønnevÃ¥g Date: Mon, 17 Feb 2014 13:58:29 -0800 Subject: staging: binder: Fix death notifications MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The change (008fa749e0fe5b2fffd20b7fe4891bb80d072c6a) that moved the node release code to a separate function broke death notifications in some cases. When it encountered a reference without a death notification request, it would skip looking at the remaining references, and therefore fail to send death notifications for them. Cc: Colin Cross Cc: Android Kernel Team Cc: stable # 3.10 Signed-off-by: Arve HjønnevÃ¥g Signed-off-by: John Stultz Signed-off-by: Jeremy Compostella Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/binder.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index eaec1dab7fe4..1432d956769c 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -2904,7 +2904,7 @@ static int binder_node_release(struct binder_node *node, int refs) refs++; if (!ref->death) - goto out; + continue; death++; @@ -2917,7 +2917,6 @@ static int binder_node_release(struct binder_node *node, int refs) BUG(); } -out: binder_debug(BINDER_DEBUG_DEAD_BINDER, "node %d now dead, refs %d, death %d\n", node->debug_id, refs, death); -- cgit v1.2.3 From 5bf5dbeda2454296f1984adfbfc8e6f5965ac389 Mon Sep 17 00:00:00 2001 From: Matthieu CASTET Date: Wed, 19 Feb 2014 13:46:31 +0800 Subject: usb: chipidea: need to mask when writting endptflush and endptprime ENDPTFLUSH and ENDPTPRIME registers are set by software and clear by hardware. There is a bit for each endpoint. When we are setting a bit for an endpoint we should make sure we do not touch other endpoint bit. There is a race condition if the hardware clear the bit between the read and the write in hw_write. Cc: stable # 3.11+ Signed-off-by: Peter Chen Signed-off-by: Matthieu CASTET Tested-by: Michael Grzeschik Signed-off-by: Greg Kroah-Hartman --- drivers/usb/chipidea/udc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index 80de2f88ed2c..4ab2cb62dfce 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -105,7 +105,7 @@ static int hw_ep_flush(struct ci_hdrc *ci, int num, int dir) do { /* flush any pending transfer */ - hw_write(ci, OP_ENDPTFLUSH, BIT(n), BIT(n)); + hw_write(ci, OP_ENDPTFLUSH, ~0, BIT(n)); while (hw_read(ci, OP_ENDPTFLUSH, BIT(n))) cpu_relax(); } while (hw_read(ci, OP_ENDPTSTAT, BIT(n))); @@ -205,7 +205,7 @@ static int hw_ep_prime(struct ci_hdrc *ci, int num, int dir, int is_ctrl) if (is_ctrl && dir == RX && hw_read(ci, OP_ENDPTSETUPSTAT, BIT(num))) return -EAGAIN; - hw_write(ci, OP_ENDPTPRIME, BIT(n), BIT(n)); + hw_write(ci, OP_ENDPTPRIME, ~0, BIT(n)); while (hw_read(ci, OP_ENDPTPRIME, BIT(n))) cpu_relax(); -- cgit v1.2.3 From a3ef2229c94ff70998724cb64b9cb4c77db9e950 Mon Sep 17 00:00:00 2001 From: Markus Metzger Date: Fri, 14 Feb 2014 16:44:08 -0800 Subject: perf, nmi: Fix unknown NMI warning When using BTS on Core i7-4*, I get the below kernel warning. $ perf record -c 1 -e branches:u ls Message from syslogd@labpc1501 at Nov 11 15:49:25 ... kernel:[ 438.317893] Uhhuh. NMI received for unknown reason 31 on CPU 2. Message from syslogd@labpc1501 at Nov 11 15:49:25 ... kernel:[ 438.317920] Do you have a strange power saving mode enabled? Message from syslogd@labpc1501 at Nov 11 15:49:25 ... kernel:[ 438.317945] Dazed and confused, but trying to continue Make intel_pmu_handle_irq() take the full exit path when returning early. Cc: eranian@google.com Cc: peterz@infradead.org Cc: mingo@kernel.org Signed-off-by: Markus Metzger Signed-off-by: Andi Kleen Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1392425048-5309-1-git-send-email-andi@firstfloor.org Signed-off-by: Thomas Gleixner --- arch/x86/kernel/cpu/perf_event_intel.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index 0fa4f242f050..698ae77d6f18 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c @@ -1361,10 +1361,8 @@ static int intel_pmu_handle_irq(struct pt_regs *regs) intel_pmu_disable_all(); handled = intel_pmu_drain_bts_buffer(); status = intel_pmu_get_status(); - if (!status) { - intel_pmu_enable_all(0); - return handled; - } + if (!status) + goto done; loops = 0; again: -- cgit v1.2.3 From c9b08884c9c98929ec2d8abafd78e89062d01ee7 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 3 Feb 2014 14:29:03 +0100 Subject: perf/x86: Correctly use FEATURE_PDCM The current code simply assumes Intel Arch PerfMon v2+ to have the IA32_PERF_CAPABILITIES MSR; the SDM specifies that we should check CPUID[1].ECX[15] (aka, FEATURE_PDCM) instead. This was found by KVM which implements v2+ but didn't provide the capabilities MSR. Change the code to DTRT; KVM will also implement the MSR and return 0. Cc: pbonzini@redhat.com Reported-by: "Michael S. Tsirkin" Suggested-by: Eduardo Habkost Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/20140203132903.GI8874@twins.programming.kicks-ass.net Signed-off-by: Thomas Gleixner --- arch/x86/kernel/cpu/perf_event_intel.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index 698ae77d6f18..aa333d966886 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c @@ -2308,10 +2308,7 @@ __init int intel_pmu_init(void) if (version > 1) x86_pmu.num_counters_fixed = max((int)edx.split.num_counters_fixed, 3); - /* - * v2 and above have a perf capabilities MSR - */ - if (version > 1) { + if (boot_cpu_has(X86_FEATURE_PDCM)) { u64 capabilities; rdmsrl(MSR_IA32_PERF_CAPABILITIES, capabilities); -- cgit v1.2.3 From 337397f3afc911d94d1d71371a36a53ce218b41f Mon Sep 17 00:00:00 2001 From: Stephane Eranian Date: Wed, 19 Feb 2014 14:10:18 +0100 Subject: perf/x86/uncore: Fix IVT/SNB-EP uncore CBOX NID filter table This patch updates the CBOX PMU filters mapping tables for SNB-EP and IVT (model 45 and 62 respectively). The NID umask always comes in addition to another umask. When set, the NID filter is applied. The current mapping tables were missing some code/umask combinations to account for the NID umask. This patch fixes that. Cc: mingo@elte.hu Cc: ak@linux.intel.com Reviewed-by: Yan, Zheng Signed-off-by: Stephane Eranian Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/20140219131018.GA24475@quad Signed-off-by: Thomas Gleixner --- arch/x86/kernel/cpu/perf_event_intel_uncore.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c index 29c248799ced..c88f7f4b03ee 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c @@ -501,8 +501,11 @@ static struct extra_reg snbep_uncore_cbox_extra_regs[] = { SNBEP_CBO_EVENT_EXTRA_REG(SNBEP_CBO_PMON_CTL_TID_EN, SNBEP_CBO_PMON_CTL_TID_EN, 0x1), SNBEP_CBO_EVENT_EXTRA_REG(0x0334, 0xffff, 0x4), + SNBEP_CBO_EVENT_EXTRA_REG(0x4334, 0xffff, 0x6), SNBEP_CBO_EVENT_EXTRA_REG(0x0534, 0xffff, 0x4), + SNBEP_CBO_EVENT_EXTRA_REG(0x4534, 0xffff, 0x6), SNBEP_CBO_EVENT_EXTRA_REG(0x0934, 0xffff, 0x4), + SNBEP_CBO_EVENT_EXTRA_REG(0x4934, 0xffff, 0x6), SNBEP_CBO_EVENT_EXTRA_REG(0x4134, 0xffff, 0x6), SNBEP_CBO_EVENT_EXTRA_REG(0x0135, 0xffff, 0x8), SNBEP_CBO_EVENT_EXTRA_REG(0x0335, 0xffff, 0x8), @@ -1178,10 +1181,15 @@ static struct extra_reg ivt_uncore_cbox_extra_regs[] = { SNBEP_CBO_EVENT_EXTRA_REG(SNBEP_CBO_PMON_CTL_TID_EN, SNBEP_CBO_PMON_CTL_TID_EN, 0x1), SNBEP_CBO_EVENT_EXTRA_REG(0x1031, 0x10ff, 0x2), + SNBEP_CBO_EVENT_EXTRA_REG(0x1134, 0xffff, 0x4), + SNBEP_CBO_EVENT_EXTRA_REG(0x4134, 0xffff, 0xc), + SNBEP_CBO_EVENT_EXTRA_REG(0x5134, 0xffff, 0xc), SNBEP_CBO_EVENT_EXTRA_REG(0x0334, 0xffff, 0x4), + SNBEP_CBO_EVENT_EXTRA_REG(0x4334, 0xffff, 0xc), SNBEP_CBO_EVENT_EXTRA_REG(0x0534, 0xffff, 0x4), + SNBEP_CBO_EVENT_EXTRA_REG(0x4534, 0xffff, 0xc), SNBEP_CBO_EVENT_EXTRA_REG(0x0934, 0xffff, 0x4), - SNBEP_CBO_EVENT_EXTRA_REG(0x4134, 0xffff, 0xc), + SNBEP_CBO_EVENT_EXTRA_REG(0x4934, 0xffff, 0xc), SNBEP_CBO_EVENT_EXTRA_REG(0x0135, 0xffff, 0x10), SNBEP_CBO_EVENT_EXTRA_REG(0x0335, 0xffff, 0x10), SNBEP_CBO_EVENT_EXTRA_REG(0x2135, 0xffff, 0x10), -- cgit v1.2.3 From d86e9af6336c0ad586a5dbd70064253d40bbb5ff Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Fri, 7 Feb 2014 00:41:58 +0100 Subject: irqchip: orion: Fix getting generic chip pointer. Enabling SPARSE_IRQ shows up a bug in the irq-orion bridge interrupt handler. The bridge interrupt is implemented using a single generic chip. Thus the parameter passed to irq_get_domain_generic_chip() should always be zero. Signed-off-by: Andrew Lunn Acked-by: Sebastian Hesselbarth Fixes: 9dbd90f17e4f ("irqchip: Add support for Marvell Orion SoCs") Cc: # v3.11+ Signed-off-by: Jason Cooper --- drivers/irqchip/irq-orion.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/irqchip/irq-orion.c b/drivers/irqchip/irq-orion.c index 0dfdc5c824a1..8e41be62812e 100644 --- a/drivers/irqchip/irq-orion.c +++ b/drivers/irqchip/irq-orion.c @@ -111,7 +111,8 @@ IRQCHIP_DECLARE(orion_intc, "marvell,orion-intc", orion_irq_init); static void orion_bridge_irq_handler(unsigned int irq, struct irq_desc *desc) { struct irq_domain *d = irq_get_handler_data(irq); - struct irq_chip_generic *gc = irq_get_domain_generic_chip(d, irq); + + struct irq_chip_generic *gc = irq_get_domain_generic_chip(d, 0); u32 stat = readl_relaxed(gc->reg_base + ORION_BRIDGE_IRQ_CAUSE) & gc->mask_cache; -- cgit v1.2.3 From 08221fc4e7aa585a59de90c0354da3e8d3e88d94 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 21 Feb 2014 13:12:38 +0100 Subject: regulator: max14577: Fix invalid return value on DT parse success This fixes bug introduced in 667a6b7a (regulator: max14577: Add missing of_node_put). The DTS parsing function returned number of matched regulators as success status which then was compared against 0 in probe. Result was a probe fail after successful parsing the DTS: max14577-regulator: probe of max14577-regulator failed with error 2 Signed-off-by: Krzysztof Kozlowski Reviwed-by: Sachin Kamat Signed-off-by: Mark Brown --- drivers/regulator/max14577.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/max14577.c b/drivers/regulator/max14577.c index 186df8785a91..e0619526708c 100644 --- a/drivers/regulator/max14577.c +++ b/drivers/regulator/max14577.c @@ -166,9 +166,10 @@ static int max14577_regulator_dt_parse_pdata(struct platform_device *pdev) ret = of_regulator_match(&pdev->dev, np, max14577_regulator_matches, MAX14577_REG_MAX); - if (ret < 0) { + if (ret < 0) dev_err(&pdev->dev, "Error parsing regulator init data: %d\n", ret); - } + else + ret = 0; of_node_put(np); -- cgit v1.2.3 From 5c0a2450d695bbe32b1fb81c07751bcbea64f084 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 22 Feb 2014 14:31:04 -0800 Subject: Revert "tty: Set correct tty name in 'active' sysfs attribute" This reverts commit d8a5dc3033af2fd6d16030d2ee4fbd073460fe54. This breaks plymouth installs, either because plymouth is using the file "incorrectly" or because the patch is incorrect. Either way, this needs to be reverted until it is all figured out. Reported-by: Josh Boyer Reported-by: Ray Strode Cc: Lennart Poettering Cc: Kay Sievers Cc: Jiri Slaby Cc: David Herrmann Cc: Werner Fink Cc: Hannes Reinecke Cc: stable Signed-off-by: Greg Kroah-Hartman --- Documentation/ABI/testing/sysfs-tty | 3 +-- drivers/tty/tty_io.c | 25 +++++++------------------ 2 files changed, 8 insertions(+), 20 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-tty b/Documentation/ABI/testing/sysfs-tty index a2ccec35ffce..ad22fb0ee765 100644 --- a/Documentation/ABI/testing/sysfs-tty +++ b/Documentation/ABI/testing/sysfs-tty @@ -3,8 +3,7 @@ Date: Nov 2010 Contact: Kay Sievers Description: Shows the list of currently configured - tty devices used for the console, - like 'tty1 ttyS0'. + console devices, like 'tty1 ttyS0'. The last entry in the file is the active device connected to /dev/console. The file supports poll() to detect virtual diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index bd2715a9d8e5..c74a00ad7add 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -1267,17 +1267,16 @@ static void pty_line_name(struct tty_driver *driver, int index, char *p) * @p: output buffer of at least 7 bytes * * Generate a name from a driver reference and write it to the output - * buffer. Return the number of bytes written. + * buffer. * * Locking: None */ -static ssize_t tty_line_name(struct tty_driver *driver, int index, char *p) +static void tty_line_name(struct tty_driver *driver, int index, char *p) { if (driver->flags & TTY_DRIVER_UNNUMBERED_NODE) - return sprintf(p, "%s", driver->name); + strcpy(p, driver->name); else - return sprintf(p, "%s%d", driver->name, - index + driver->name_base); + sprintf(p, "%s%d", driver->name, index + driver->name_base); } /** @@ -3546,19 +3545,9 @@ static ssize_t show_cons_active(struct device *dev, if (i >= ARRAY_SIZE(cs)) break; } - while (i--) { - struct tty_driver *driver; - const char *name = cs[i]->name; - int index = cs[i]->index; - - driver = cs[i]->device(cs[i], &index); - if (driver) { - count += tty_line_name(driver, index, buf + count); - count += sprintf(buf + count, "%c", i ? ' ':'\n'); - } else - count += sprintf(buf + count, "%s%d%c", - name, index, i ? ' ':'\n'); - } + while (i--) + count += sprintf(buf + count, "%s%d%c", + cs[i]->name, cs[i]->index, i ? ' ':'\n'); console_unlock(); return count; -- cgit v1.2.3 From a3db2bba6d1933a1398357ba6728c743bdab03e1 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Fri, 14 Feb 2014 10:15:03 -0500 Subject: MAINTAINERS: add additional ARM BCM281xx/BCM11xxx maintainer Add myself as an additional maintainer for the Broadcom mobile SoCs. Signed-off-by: Matt Porter Acked-by: Christian Daudt Signed-off-by: Olof Johansson --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index fb08dcececf1..1d6e219ce68d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1860,6 +1860,7 @@ F: drivers/net/ethernet/broadcom/bnx2x/ BROADCOM BCM281XX/BCM11XXX ARM ARCHITECTURE M: Christian Daudt +M: Matt Porter L: bcm-kernel-feedback-list@broadcom.com T: git git://git.github.com/broadcom/bcm11351 S: Maintained -- cgit v1.2.3 From cfbf8d4857c26a8a307fb7cd258074c9dcd8c691 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 23 Feb 2014 17:40:03 -0800 Subject: Linux 3.14-rc4 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 893d6f0e875b..831b36a6b0a1 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 3 PATCHLEVEL = 14 SUBLEVEL = 0 -EXTRAVERSION = -rc3 +EXTRAVERSION = -rc4 NAME = Shuffling Zombie Juror # *DOCUMENTATION* -- cgit v1.2.3 From af3c0380ebb1de0cd688a9e02d75da3cc79e43f6 Mon Sep 17 00:00:00 2001 From: Florian Vaussard Date: Fri, 7 Mar 2014 20:22:11 +0100 Subject: ARM: dts: overo: reorganize include files Currently, overo-related include files are organized as follow: omap3-overo.dtsi | | omap34xx.dtsi omap3-overo-tobi-common.dtsi omap36xx.dtsi | | | | --------------- --------------- | | omap3-overo-tobi.dts omap3-overo-storm-tobi.dts This is unpractical when one has to deal with SoC-specific pinmux belonging to the omap3_pmx_core2 (defined in omap34xx/omap36xx), for pins related to the processor board. With the current hierarchy, such pinmux has to be defined in the expansion board's .dts, which is not logical. This patches reorganizes the files to add (yet another) abstraction layer between the processor and the expansion boards. omap34xx.dtsi omap3-overo-base.dtsi omap36xx.dtsi | | | | --------------- --------------- | | omap3-overo.dtsi omap3-overo-storm.dtsi | | -------- ------ | omap3-overo-tobi-common.dtsi | | | | | --------------- --------------- | | omap3-overo-tobi.dts omap3-overo-storm-tobi.dts Signed-off-by: Florian Vaussard Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap3-overo-base.dtsi | 94 ++++++++++++++++++++++++++ arch/arm/boot/dts/omap3-overo-storm-tobi.dts | 2 +- arch/arm/boot/dts/omap3-overo-storm.dtsi | 11 +++ arch/arm/boot/dts/omap3-overo-tobi-common.dtsi | 2 - arch/arm/boot/dts/omap3-overo-tobi.dts | 2 +- arch/arm/boot/dts/omap3-overo.dtsi | 89 +----------------------- 6 files changed, 110 insertions(+), 90 deletions(-) create mode 100644 arch/arm/boot/dts/omap3-overo-base.dtsi create mode 100644 arch/arm/boot/dts/omap3-overo-storm.dtsi diff --git a/arch/arm/boot/dts/omap3-overo-base.dtsi b/arch/arm/boot/dts/omap3-overo-base.dtsi new file mode 100644 index 000000000000..597099907f8e --- /dev/null +++ b/arch/arm/boot/dts/omap3-overo-base.dtsi @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2012 Florian Vaussard, EPFL Mobots group + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* + * The Gumstix Overo must be combined with an expansion board. + */ + +/ { + pwmleds { + compatible = "pwm-leds"; + + overo { + label = "overo:blue:COM"; + pwms = <&twl_pwmled 1 7812500>; + max-brightness = <127>; + linux,default-trigger = "mmc0"; + }; + }; + + sound { + compatible = "ti,omap-twl4030"; + ti,model = "overo"; + + ti,mcbsp = <&mcbsp2>; + ti,codec = <&twl_audio>; + }; +}; + +&i2c1 { + clock-frequency = <2600000>; + + twl: twl@48 { + reg = <0x48>; + interrupts = <7>; /* SYS_NIRQ cascaded to intc */ + interrupt-parent = <&intc>; + + twl_audio: audio { + compatible = "ti,twl4030-audio"; + codec { + }; + }; + }; +}; + +#include "twl4030.dtsi" +#include "twl4030_omap3.dtsi" + +/* i2c2 pins are used for gpio */ +&i2c2 { + status = "disabled"; +}; + +/* on board microSD slot */ +&mmc1 { + vmmc-supply = <&vmmc1>; + bus-width = <4>; +}; + +/* optional on board WiFi */ +&mmc2 { + bus-width = <4>; +}; + +&twl_gpio { + ti,use-leds; +}; + +&usb_otg_hs { + interface-type = <0>; + usb-phy = <&usb2_phy>; + phys = <&usb2_phy>; + phy-names = "usb2-phy"; + mode = <3>; + power = <50>; +}; + +&omap3_pmx_core { + uart3_pins: pinmux_uart3_pins { + pinctrl-single,pins = < + 0x16e (PIN_INPUT | PIN_OFF_WAKEUPENABLE | MUX_MODE0) /* uart3_rx_irrx.uart3_rx_irrx */ + 0x170 (PIN_OUTPUT | MUX_MODE0) /* uart3_tx_irtx.uart3_tx_irtx */ + >; + }; +}; + +&uart3 { + pinctrl-names = "default"; + pinctrl-0 = <&uart3_pins>; +}; diff --git a/arch/arm/boot/dts/omap3-overo-storm-tobi.dts b/arch/arm/boot/dts/omap3-overo-storm-tobi.dts index 966b5c9cd96a..879383acad87 100644 --- a/arch/arm/boot/dts/omap3-overo-storm-tobi.dts +++ b/arch/arm/boot/dts/omap3-overo-storm-tobi.dts @@ -12,7 +12,7 @@ /dts-v1/; -#include "omap36xx.dtsi" +#include "omap3-overo-storm.dtsi" #include "omap3-overo-tobi-common.dtsi" / { diff --git a/arch/arm/boot/dts/omap3-overo-storm.dtsi b/arch/arm/boot/dts/omap3-overo-storm.dtsi new file mode 100644 index 000000000000..c30efb30f829 --- /dev/null +++ b/arch/arm/boot/dts/omap3-overo-storm.dtsi @@ -0,0 +1,11 @@ +/* + * Copyright (C) 2014 Florian Vaussard, EPFL Mobots group + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include "omap36xx.dtsi" +#include "omap3-overo-base.dtsi" + diff --git a/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi b/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi index 4edc013a91c1..9b4a6d25a9ea 100644 --- a/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi +++ b/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi @@ -10,8 +10,6 @@ * Tobi expansion board is manufactured by Gumstix Inc. */ -#include "omap3-overo.dtsi" - / { leds { compatible = "gpio-leds"; diff --git a/arch/arm/boot/dts/omap3-overo-tobi.dts b/arch/arm/boot/dts/omap3-overo-tobi.dts index de5653e1b5ca..fd6400efcdee 100644 --- a/arch/arm/boot/dts/omap3-overo-tobi.dts +++ b/arch/arm/boot/dts/omap3-overo-tobi.dts @@ -12,7 +12,7 @@ /dts-v1/; -#include "omap34xx.dtsi" +#include "omap3-overo.dtsi" #include "omap3-overo-tobi-common.dtsi" / { diff --git a/arch/arm/boot/dts/omap3-overo.dtsi b/arch/arm/boot/dts/omap3-overo.dtsi index 597099907f8e..7bbda683ee0a 100644 --- a/arch/arm/boot/dts/omap3-overo.dtsi +++ b/arch/arm/boot/dts/omap3-overo.dtsi @@ -1,94 +1,11 @@ /* - * Copyright (C) 2012 Florian Vaussard, EPFL Mobots group + * Copyright (C) 2014 Florian Vaussard, EPFL Mobots group * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -/* - * The Gumstix Overo must be combined with an expansion board. - */ - -/ { - pwmleds { - compatible = "pwm-leds"; - - overo { - label = "overo:blue:COM"; - pwms = <&twl_pwmled 1 7812500>; - max-brightness = <127>; - linux,default-trigger = "mmc0"; - }; - }; - - sound { - compatible = "ti,omap-twl4030"; - ti,model = "overo"; - - ti,mcbsp = <&mcbsp2>; - ti,codec = <&twl_audio>; - }; -}; - -&i2c1 { - clock-frequency = <2600000>; - - twl: twl@48 { - reg = <0x48>; - interrupts = <7>; /* SYS_NIRQ cascaded to intc */ - interrupt-parent = <&intc>; - - twl_audio: audio { - compatible = "ti,twl4030-audio"; - codec { - }; - }; - }; -}; - -#include "twl4030.dtsi" -#include "twl4030_omap3.dtsi" - -/* i2c2 pins are used for gpio */ -&i2c2 { - status = "disabled"; -}; - -/* on board microSD slot */ -&mmc1 { - vmmc-supply = <&vmmc1>; - bus-width = <4>; -}; - -/* optional on board WiFi */ -&mmc2 { - bus-width = <4>; -}; - -&twl_gpio { - ti,use-leds; -}; - -&usb_otg_hs { - interface-type = <0>; - usb-phy = <&usb2_phy>; - phys = <&usb2_phy>; - phy-names = "usb2-phy"; - mode = <3>; - power = <50>; -}; - -&omap3_pmx_core { - uart3_pins: pinmux_uart3_pins { - pinctrl-single,pins = < - 0x16e (PIN_INPUT | PIN_OFF_WAKEUPENABLE | MUX_MODE0) /* uart3_rx_irrx.uart3_rx_irrx */ - 0x170 (PIN_OUTPUT | MUX_MODE0) /* uart3_tx_irtx.uart3_tx_irtx */ - >; - }; -}; +#include "omap34xx.dtsi" +#include "omap3-overo-base.dtsi" -&uart3 { - pinctrl-names = "default"; - pinctrl-0 = <&uart3_pins>; -}; -- cgit v1.2.3 From bbde8f24366ba0a5a144321c684dd4671bfa253f Mon Sep 17 00:00:00 2001 From: Florian Vaussard Date: Fri, 7 Mar 2014 20:22:12 +0100 Subject: ARM: dts: omap3-tobi: Add missing pinctrl Add missing pinctrl entries: - i2c3 Signed-off-by: Florian Vaussard Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap3-overo-tobi-common.dtsi | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi b/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi index 9b4a6d25a9ea..7375cda0f5c9 100644 --- a/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi +++ b/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi @@ -33,6 +33,15 @@ }; }; +&omap3_pmx_core { + i2c3_pins: pinmux_i2c3_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x21c2, PIN_INPUT | MUX_MODE0) /* i2c3_scl.i2c3_scl */ + OMAP3_CORE1_IOPAD(0x21c4, PIN_INPUT | MUX_MODE0) /* i2c3_sda.i2c3_sda */ + >; + }; +}; + &gpmc { ranges = <5 0 0x2c000000 0x1000000>; /* CS5 */ @@ -70,6 +79,8 @@ }; &i2c3 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c3_pins>; clock-frequency = <100000>; }; -- cgit v1.2.3 From fc1772262a84fe5069aebb9a91f9e2997951dec6 Mon Sep 17 00:00:00 2001 From: Florian Vaussard Date: Fri, 7 Mar 2014 20:22:13 +0100 Subject: ARM: dts: omap3-overo: Add missing pinctrl Add missing pinctrl entries for: - i2c1 - mmc1 Signed-off-by: Florian Vaussard Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap3-overo-base.dtsi | 40 +++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/arch/arm/boot/dts/omap3-overo-base.dtsi b/arch/arm/boot/dts/omap3-overo-base.dtsi index 597099907f8e..aea64c09d02b 100644 --- a/arch/arm/boot/dts/omap3-overo-base.dtsi +++ b/arch/arm/boot/dts/omap3-overo-base.dtsi @@ -31,7 +31,36 @@ }; }; +&omap3_pmx_core { + uart3_pins: pinmux_uart3_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x219e, PIN_INPUT | PIN_OFF_WAKEUPENABLE | MUX_MODE0) /* uart3_rx_irrx.uart3_rx_irrx */ + OMAP3_CORE1_IOPAD(0x21a0, PIN_OUTPUT | MUX_MODE0) /* uart3_tx_irtx.uart3_tx_irtx */ + >; + }; + + i2c1_pins: pinmux_i2c1_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x21ba, PIN_INPUT | MUX_MODE0) /* i2c1_scl.i2c1_scl */ + OMAP3_CORE1_IOPAD(0x21bc, PIN_INPUT | MUX_MODE0) /* i2c1_sda.i2c1_sda */ + >; + }; + + mmc1_pins: pinmux_mmc1_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x2144, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_clk.sdmmc1_clk */ + OMAP3_CORE1_IOPAD(0x2146, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_cmd.sdmmc1_cmd */ + OMAP3_CORE1_IOPAD(0x2148, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_dat0.sdmmc1_dat0 */ + OMAP3_CORE1_IOPAD(0x214a, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_dat1.sdmmc1_dat1 */ + OMAP3_CORE1_IOPAD(0x214c, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_dat2.sdmmc1_dat2 */ + OMAP3_CORE1_IOPAD(0x214e, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_dat3.sdmmc1_dat3 */ + >; + }; +}; + &i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins>; clock-frequency = <2600000>; twl: twl@48 { @@ -57,6 +86,8 @@ /* on board microSD slot */ &mmc1 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc1_pins>; vmmc-supply = <&vmmc1>; bus-width = <4>; }; @@ -79,15 +110,6 @@ power = <50>; }; -&omap3_pmx_core { - uart3_pins: pinmux_uart3_pins { - pinctrl-single,pins = < - 0x16e (PIN_INPUT | PIN_OFF_WAKEUPENABLE | MUX_MODE0) /* uart3_rx_irrx.uart3_rx_irrx */ - 0x170 (PIN_OUTPUT | MUX_MODE0) /* uart3_tx_irtx.uart3_tx_irtx */ - >; - }; -}; - &uart3 { pinctrl-names = "default"; pinctrl-0 = <&uart3_pins>; -- cgit v1.2.3 From 94647a30124e2c7243ffcd780862ed591ae36450 Mon Sep 17 00:00:00 2001 From: Florian Vaussard Date: Fri, 7 Mar 2014 20:22:14 +0100 Subject: ARM: dts: omap3-overo: Enable WiFi/BT combo MMC2 is used by the on-board WiFi module populated on some boards (based on Marvell Libertas 8688 SDIO). The Bluetooth is connected to UART2. Signed-off-by: Florian Vaussard Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap3-overo-base.dtsi | 72 ++++++++++++++++++++++++++++++++ arch/arm/boot/dts/omap3-overo-storm.dtsi | 8 ++++ arch/arm/boot/dts/omap3-overo.dtsi | 8 ++++ 3 files changed, 88 insertions(+) diff --git a/arch/arm/boot/dts/omap3-overo-base.dtsi b/arch/arm/boot/dts/omap3-overo-base.dtsi index aea64c09d02b..edac70e9204c 100644 --- a/arch/arm/boot/dts/omap3-overo-base.dtsi +++ b/arch/arm/boot/dts/omap3-overo-base.dtsi @@ -29,9 +29,50 @@ ti,mcbsp = <&mcbsp2>; ti,codec = <&twl_audio>; }; + + /* Regulator to trigger the nPoweron signal of the Wifi module */ + w3cbw003c_npoweron: regulator-w3cbw003c-npoweron { + compatible = "regulator-fixed"; + regulator-name = "regulator-w3cbw003c-npoweron"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpio2 22 GPIO_ACTIVE_HIGH>; /* gpio_54: nPoweron */ + enable-active-high; + }; + + /* Regulator to trigger the nReset signal of the Wifi module */ + w3cbw003c_wifi_nreset: regulator-w3cbw003c-wifi-nreset { + pinctrl-names = "default"; + pinctrl-0 = <&w3cbw003c_pins &w3cbw003c_2_pins>; + compatible = "regulator-fixed"; + regulator-name = "regulator-w3cbw003c-wifi-nreset"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpio1 16 GPIO_ACTIVE_HIGH>; /* gpio_16: WiFi nReset */ + startup-delay-us = <10000>; + }; + + /* Regulator to trigger the nReset signal of the Bluetooth module */ + w3cbw003c_bt_nreset: regulator-w3cbw003c-bt-nreset { + compatible = "regulator-fixed"; + regulator-name = "regulator-w3cbw003c-bt-nreset"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpio6 4 GPIO_ACTIVE_HIGH>; /* gpio_164: BT nReset */ + startup-delay-us = <10000>; + }; }; &omap3_pmx_core { + uart2_pins: pinmux_uart2_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x216c, PIN_INPUT | MUX_MODE1) /* mcbsp3_dx.uart2_cts */ + OMAP3_CORE1_IOPAD(0x216e, PIN_OUTPUT | MUX_MODE1) /* mcbsp3_dr.uart2_rts */ + OMAP3_CORE1_IOPAD(0x2170, PIN_OUTPUT | MUX_MODE1) /* mcbsp3_clk.uart2_tx */ + OMAP3_CORE1_IOPAD(0x2172, PIN_INPUT | MUX_MODE1) /* mcbsp3_fsx.uart2_rx */ + >; + }; + uart3_pins: pinmux_uart3_pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x219e, PIN_INPUT | PIN_OFF_WAKEUPENABLE | MUX_MODE0) /* uart3_rx_irrx.uart3_rx_irrx */ @@ -56,6 +97,25 @@ OMAP3_CORE1_IOPAD(0x214e, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_dat3.sdmmc1_dat3 */ >; }; + + mmc2_pins: pinmux_mmc2_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x2158, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_clk.sdmmc2_clk */ + OMAP3_CORE1_IOPAD(0x215a, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_cmd.sdmmc2_cmd */ + OMAP3_CORE1_IOPAD(0x215c, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_dat0.sdmmc2_dat0 */ + OMAP3_CORE1_IOPAD(0x215e, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_dat1.sdmmc2_dat1 */ + OMAP3_CORE1_IOPAD(0x2160, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_dat2.sdmmc2_dat2 */ + OMAP3_CORE1_IOPAD(0x2162, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_dat3.sdmmc2_dat3 */ + >; + }; + + /* WiFi/BT combo */ + w3cbw003c_pins: pinmux_w3cbw003c_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x20b4, PIN_OUTPUT | MUX_MODE4) /* gpmc_ncs3.gpio_54 */ + OMAP3_CORE1_IOPAD(0x219c, PIN_OUTPUT | MUX_MODE4) /* uart3_rts_sd.gpio_164 */ + >; + }; }; &i2c1 { @@ -94,7 +154,14 @@ /* optional on board WiFi */ &mmc2 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc2_pins>; + vmmc-supply = <&w3cbw003c_npoweron>; + vqmmc-supply = <&w3cbw003c_bt_nreset>; + vmmc_aux-supply = <&w3cbw003c_wifi_nreset>; bus-width = <4>; + cap-sdio-irq; + non-removable; }; &twl_gpio { @@ -110,6 +177,11 @@ power = <50>; }; +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&uart2_pins>; +}; + &uart3 { pinctrl-names = "default"; pinctrl-0 = <&uart3_pins>; diff --git a/arch/arm/boot/dts/omap3-overo-storm.dtsi b/arch/arm/boot/dts/omap3-overo-storm.dtsi index c30efb30f829..c235ae8780c1 100644 --- a/arch/arm/boot/dts/omap3-overo-storm.dtsi +++ b/arch/arm/boot/dts/omap3-overo-storm.dtsi @@ -9,3 +9,11 @@ #include "omap36xx.dtsi" #include "omap3-overo-base.dtsi" +&omap3_pmx_core2 { + w3cbw003c_2_pins: pinmux_w3cbw003c_2_pins { + pinctrl-single,pins = < + OMAP3630_CORE2_IOPAD(0x25e0, PIN_OUTPUT | MUX_MODE4) /* etk_d2.gpio_16 */ + >; + }; +}; + diff --git a/arch/arm/boot/dts/omap3-overo.dtsi b/arch/arm/boot/dts/omap3-overo.dtsi index 7bbda683ee0a..95c59b21b4f6 100644 --- a/arch/arm/boot/dts/omap3-overo.dtsi +++ b/arch/arm/boot/dts/omap3-overo.dtsi @@ -9,3 +9,11 @@ #include "omap34xx.dtsi" #include "omap3-overo-base.dtsi" +&omap3_pmx_core2 { + w3cbw003c_2_pins: pinmux_w3cbw003c_2_pins { + pinctrl-single,pins = < + OMAP3430_CORE2_IOPAD(0x25e0, PIN_OUTPUT | MUX_MODE4) /* etk_d2.gpio_16 */ + >; + }; +}; + -- cgit v1.2.3 From dd4051bd2daaeedfd1bff32ee2ee6f4107b2257a Mon Sep 17 00:00:00 2001 From: Florian Vaussard Date: Fri, 7 Mar 2014 20:22:15 +0100 Subject: ARM: dts: omap3-overo: Add HSUSB PHY Add the High-Speed USB PHY. Signed-off-by: Florian Vaussard Acked-by: Roger Quadros Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap3-overo-base.dtsi | 44 ++++++++++++++++++++++++++++++++ arch/arm/boot/dts/omap3-overo-storm.dtsi | 16 ++++++++++++ arch/arm/boot/dts/omap3-overo.dtsi | 16 ++++++++++++ 3 files changed, 76 insertions(+) diff --git a/arch/arm/boot/dts/omap3-overo-base.dtsi b/arch/arm/boot/dts/omap3-overo-base.dtsi index edac70e9204c..13d1ad215494 100644 --- a/arch/arm/boot/dts/omap3-overo-base.dtsi +++ b/arch/arm/boot/dts/omap3-overo-base.dtsi @@ -30,6 +30,24 @@ ti,codec = <&twl_audio>; }; + /* HS USB Port 2 Power */ + hsusb2_power: hsusb2_power_reg { + compatible = "regulator-fixed"; + regulator-name = "hsusb2_vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&gpio6 8 0>; /* gpio_168: vbus enable */ + startup-delay-us = <70000>; + enable-active-high; + }; + + /* HS USB Host PHY on PORT 2 */ + hsusb2_phy: hsusb2_phy { + compatible = "usb-nop-xceiv"; + reset-gpios = <&gpio6 23 GPIO_ACTIVE_LOW>; /* gpio_183 */ + vcc-supply = <&hsusb2_power>; + }; + /* Regulator to trigger the nPoweron signal of the Wifi module */ w3cbw003c_npoweron: regulator-w3cbw003c-npoweron { compatible = "regulator-fixed"; @@ -64,6 +82,11 @@ }; &omap3_pmx_core { + pinctrl-names = "default"; + pinctrl-0 = < + &hsusb2_pins + >; + uart2_pins: pinmux_uart2_pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x216c, PIN_INPUT | MUX_MODE1) /* mcbsp3_dx.uart2_cts */ @@ -116,6 +139,19 @@ OMAP3_CORE1_IOPAD(0x219c, PIN_OUTPUT | MUX_MODE4) /* uart3_rts_sd.gpio_164 */ >; }; + + hsusb2_pins: pinmux_hsusb2_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x21d4, PIN_INPUT_PULLDOWN | MUX_MODE3) /* mcspi1_cs3.hsusb2_data2 */ + OMAP3_CORE1_IOPAD(0x21d6, PIN_INPUT_PULLDOWN | MUX_MODE3) /* mcspi2_clk.hsusb2_data7 */ + OMAP3_CORE1_IOPAD(0x21d8, PIN_INPUT_PULLDOWN | MUX_MODE3) /* mcspi2_simo.hsusb2_data4 */ + OMAP3_CORE1_IOPAD(0x21da, PIN_INPUT_PULLDOWN | MUX_MODE3) /* mcspi2_somi.hsusb2_data5 */ + OMAP3_CORE1_IOPAD(0x21dc, PIN_INPUT_PULLDOWN | MUX_MODE3) /* mcspi2_cs0.hsusb2_data6 */ + OMAP3_CORE1_IOPAD(0x21de, PIN_INPUT_PULLDOWN | MUX_MODE3) /* mcspi2_cs1.hsusb2_data3 */ + OMAP3_CORE1_IOPAD(0x21be, PIN_OUTPUT | MUX_MODE4) /* i2c2_scl.gpio_168 */ + OMAP3_CORE1_IOPAD(0x21c0, PIN_OUTPUT | MUX_MODE4) /* i2c2_sda.gpio_183 */ + >; + }; }; &i2c1 { @@ -177,6 +213,14 @@ power = <50>; }; +&usbhshost { + port2-mode = "ehci-phy"; +}; + +&usbhsehci { + phys = <0 &hsusb2_phy>; +}; + &uart2 { pinctrl-names = "default"; pinctrl-0 = <&uart2_pins>; diff --git a/arch/arm/boot/dts/omap3-overo-storm.dtsi b/arch/arm/boot/dts/omap3-overo-storm.dtsi index c235ae8780c1..6cb418b4124a 100644 --- a/arch/arm/boot/dts/omap3-overo-storm.dtsi +++ b/arch/arm/boot/dts/omap3-overo-storm.dtsi @@ -10,6 +10,22 @@ #include "omap3-overo-base.dtsi" &omap3_pmx_core2 { + pinctrl-names = "default"; + pinctrl-0 = < + &hsusb2_2_pins + >; + + hsusb2_2_pins: pinmux_hsusb2_2_pins { + pinctrl-single,pins = < + OMAP3630_CORE2_IOPAD(0x25f0, PIN_OUTPUT | MUX_MODE3) /* etk_d10.hsusb2_clk */ + OMAP3630_CORE2_IOPAD(0x25f2, PIN_OUTPUT | MUX_MODE3) /* etk_d11.hsusb2_stp */ + OMAP3630_CORE2_IOPAD(0x25f4, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d12.hsusb2_dir */ + OMAP3630_CORE2_IOPAD(0x25f6, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d13.hsusb2_nxt */ + OMAP3630_CORE2_IOPAD(0x25f8, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d14.hsusb2_data0 */ + OMAP3630_CORE2_IOPAD(0x25fa, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d15.hsusb2_data1 */ + >; + }; + w3cbw003c_2_pins: pinmux_w3cbw003c_2_pins { pinctrl-single,pins = < OMAP3630_CORE2_IOPAD(0x25e0, PIN_OUTPUT | MUX_MODE4) /* etk_d2.gpio_16 */ diff --git a/arch/arm/boot/dts/omap3-overo.dtsi b/arch/arm/boot/dts/omap3-overo.dtsi index 95c59b21b4f6..c37b1301115b 100644 --- a/arch/arm/boot/dts/omap3-overo.dtsi +++ b/arch/arm/boot/dts/omap3-overo.dtsi @@ -10,6 +10,22 @@ #include "omap3-overo-base.dtsi" &omap3_pmx_core2 { + pinctrl-names = "default"; + pinctrl-0 = < + &hsusb2_2_pins + >; + + hsusb2_2_pins: pinmux_hsusb2_2_pins { + pinctrl-single,pins = < + OMAP3430_CORE2_IOPAD(0x25f0, PIN_OUTPUT | MUX_MODE3) /* etk_d10.hsusb2_clk */ + OMAP3430_CORE2_IOPAD(0x25f2, PIN_OUTPUT | MUX_MODE3) /* etk_d11.hsusb2_stp */ + OMAP3430_CORE2_IOPAD(0x25f4, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d12.hsusb2_dir */ + OMAP3430_CORE2_IOPAD(0x25f6, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d13.hsusb2_nxt */ + OMAP3430_CORE2_IOPAD(0x25f8, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d14.hsusb2_data0 */ + OMAP3430_CORE2_IOPAD(0x25fa, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d15.hsusb2_data1 */ + >; + }; + w3cbw003c_2_pins: pinmux_w3cbw003c_2_pins { pinctrl-single,pins = < OMAP3430_CORE2_IOPAD(0x25e0, PIN_OUTPUT | MUX_MODE4) /* etk_d2.gpio_16 */ -- cgit v1.2.3 From aac9aa37e55bdf1f4e9e67402e5027907e221718 Mon Sep 17 00:00:00 2001 From: Florian Vaussard Date: Fri, 7 Mar 2014 20:22:16 +0100 Subject: ARM: dts: omap: Add common file for SMSC9221 Some devices (SMSC9217, SMSC9218 and SMSC9221 at least) have better timings, allowing a higher transfer speed. Create a common file with these timings. Performance results with iperf: - omap-gpmc-smsc911x.dtsi => 54.9 Mbps - omap-gpmc-smsc9221.dtsi => 92.7 Mbps Signed-off-by: Florian Vaussard Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap-gpmc-smsc9221.dtsi | 58 +++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 arch/arm/boot/dts/omap-gpmc-smsc9221.dtsi diff --git a/arch/arm/boot/dts/omap-gpmc-smsc9221.dtsi b/arch/arm/boot/dts/omap-gpmc-smsc9221.dtsi new file mode 100644 index 000000000000..73e272fadc20 --- /dev/null +++ b/arch/arm/boot/dts/omap-gpmc-smsc9221.dtsi @@ -0,0 +1,58 @@ +/* + * Common file for GPMC connected smsc9221 on omaps + * + * Compared to smsc911x, smsc9221 (and others like smsc9217 + * or smsc 9218) has faster timings, leading to higher + * bandwidth. + * + * Note that the board specifc DTS file needs to specify + * ranges, pinctrl, reg, interrupt parent and interrupts. + */ + +/ { + vddvario: regulator-vddvario { + compatible = "regulator-fixed"; + regulator-name = "vddvario"; + regulator-always-on; + }; + + vdd33a: regulator-vdd33a { + compatible = "regulator-fixed"; + regulator-name = "vdd33a"; + regulator-always-on; + }; +}; + +&gpmc { + ethernet@gpmc { + compatible = "smsc,lan9221","smsc,lan9115"; + bank-width = <2>; + + gpmc,mux-add-data; + gpmc,cs-on-ns = <0>; + gpmc,cs-rd-off-ns = <42>; + gpmc,cs-wr-off-ns = <36>; + gpmc,adv-on-ns = <6>; + gpmc,adv-rd-off-ns = <12>; + gpmc,adv-wr-off-ns = <12>; + gpmc,oe-on-ns = <0>; + gpmc,oe-off-ns = <42>; + gpmc,we-on-ns = <0>; + gpmc,we-off-ns = <36>; + gpmc,rd-cycle-ns = <60>; + gpmc,wr-cycle-ns = <54>; + gpmc,access-ns = <36>; + gpmc,page-burst-access-ns = <0>; + gpmc,bus-turnaround-ns = <0>; + gpmc,cycle2cycle-delay-ns = <0>; + gpmc,wr-data-mux-bus-ns = <18>; + gpmc,wr-access-ns = <42>; + gpmc,cycle2cycle-samecsen; + gpmc,cycle2cycle-diffcsen; + + vddvario-supply = <&vddvario>; + vdd33a-supply = <&vdd33a>; + reg-io-width = <4>; + smsc,save-mac-address; + }; +}; -- cgit v1.2.3 From c3fba2d05b4d87aae6380e81b118a6b82bfcfa5a Mon Sep 17 00:00:00 2001 From: Florian Vaussard Date: Fri, 7 Mar 2014 20:22:17 +0100 Subject: ARM: dts: omap3-tobi: Use include file omap-gpmc-smsc9221 Use the timings provided by omap-gpmc-smsc9221. This does not change the timings, but it avoids code duplication. Signed-off-by: Florian Vaussard Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap3-overo-tobi-common.dtsi | 42 ++------------------------ 1 file changed, 3 insertions(+), 39 deletions(-) diff --git a/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi b/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi index 7375cda0f5c9..e7f2ac76c226 100644 --- a/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi +++ b/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi @@ -19,18 +19,6 @@ linux,default-trigger = "heartbeat"; }; }; - - 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 { @@ -42,39 +30,15 @@ }; }; +#include "omap-gpmc-smsc9221.dtsi" + &gpmc { ranges = <5 0 0x2c000000 0x1000000>; /* CS5 */ - ethernet@5,0 { - compatible = "smsc,lan9221", "smsc,lan9115"; + ethernet@gpmc { reg = <5 0 0xff>; - bank-width = <2>; - - gpmc,mux-add-data; - gpmc,cs-on-ns = <0>; - gpmc,cs-rd-off-ns = <42>; - gpmc,cs-wr-off-ns = <36>; - gpmc,adv-on-ns = <6>; - gpmc,adv-rd-off-ns = <12>; - gpmc,adv-wr-off-ns = <12>; - gpmc,oe-on-ns = <0>; - gpmc,oe-off-ns = <42>; - gpmc,we-on-ns = <0>; - gpmc,we-off-ns = <36>; - gpmc,rd-cycle-ns = <60>; - gpmc,wr-cycle-ns = <54>; - gpmc,access-ns = <36>; - gpmc,page-burst-access-ns = <0>; - gpmc,bus-turnaround-ns = <0>; - gpmc,cycle2cycle-delay-ns = <0>; - gpmc,wr-data-mux-bus-ns = <18>; - gpmc,wr-access-ns = <42>; - gpmc,cycle2cycle-samecsen; - gpmc,cycle2cycle-diffcsen; - interrupt-parent = <&gpio6>; interrupts = <16 IRQ_TYPE_LEVEL_LOW>; /* GPIO 176 */ - reg-io-width = <4>; }; }; -- cgit v1.2.3 From 7a5cfb2744523a1e3742c5b91a5e670a9d27323e Mon Sep 17 00:00:00 2001 From: Florian Vaussard Date: Fri, 7 Mar 2014 20:22:18 +0100 Subject: ARM: dts: omap3-tobi: Add AT24C01 EEPROM Add the AT24C01 EEPROM node populated on most Gumstix expansion board. Signed-off-by: Florian Vaussard Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap3-overo-tobi-common.dtsi | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi b/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi index e7f2ac76c226..0312d2240db3 100644 --- a/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi +++ b/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi @@ -46,6 +46,13 @@ pinctrl-names = "default"; pinctrl-0 = <&i2c3_pins>; clock-frequency = <100000>; + + /* optional 1K EEPROM with revision information */ + eeprom@51 { + compatible = "atmel,24c01"; + reg = <0x51>; + pagesize = <8>; + }; }; &mmc3 { -- cgit v1.2.3 From 1afb89746ca0e5b5d24dcb119c084516a0a4fd36 Mon Sep 17 00:00:00 2001 From: Florian Vaussard Date: Fri, 7 Mar 2014 20:22:19 +0100 Subject: ARM: dts: overo: Push uart3 pinmux down to expansion board UART3 is used by expansion boards to get a tty console. Thus, the pinmux should be defined by expansion boards, instead of being imposed by the processor board. Signed-off-by: Florian Vaussard Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap3-overo-base.dtsi | 11 ----------- arch/arm/boot/dts/omap3-overo-tobi-common.dtsi | 13 +++++++++++++ 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/arch/arm/boot/dts/omap3-overo-base.dtsi b/arch/arm/boot/dts/omap3-overo-base.dtsi index 13d1ad215494..d36bf0250a05 100644 --- a/arch/arm/boot/dts/omap3-overo-base.dtsi +++ b/arch/arm/boot/dts/omap3-overo-base.dtsi @@ -96,13 +96,6 @@ >; }; - uart3_pins: pinmux_uart3_pins { - pinctrl-single,pins = < - OMAP3_CORE1_IOPAD(0x219e, PIN_INPUT | PIN_OFF_WAKEUPENABLE | MUX_MODE0) /* uart3_rx_irrx.uart3_rx_irrx */ - OMAP3_CORE1_IOPAD(0x21a0, PIN_OUTPUT | MUX_MODE0) /* uart3_tx_irtx.uart3_tx_irtx */ - >; - }; - i2c1_pins: pinmux_i2c1_pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21ba, PIN_INPUT | MUX_MODE0) /* i2c1_scl.i2c1_scl */ @@ -226,7 +219,3 @@ pinctrl-0 = <&uart2_pins>; }; -&uart3 { - pinctrl-names = "default"; - pinctrl-0 = <&uart3_pins>; -}; diff --git a/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi b/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi index 0312d2240db3..384e87d7f3bb 100644 --- a/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi +++ b/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi @@ -28,6 +28,13 @@ OMAP3_CORE1_IOPAD(0x21c4, PIN_INPUT | MUX_MODE0) /* i2c3_sda.i2c3_sda */ >; }; + + uart3_pins: pinmux_uart3_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x219e, PIN_INPUT | PIN_OFF_WAKEUPENABLE | MUX_MODE0) /* uart3_rx_irrx.uart3_rx_irrx */ + OMAP3_CORE1_IOPAD(0x21a0, PIN_OUTPUT | MUX_MODE0) /* uart3_tx_irtx.uart3_tx_irtx */ + >; + }; }; #include "omap-gpmc-smsc9221.dtsi" @@ -58,3 +65,9 @@ &mmc3 { status = "disabled"; }; + +&uart3 { + pinctrl-names = "default"; + pinctrl-0 = <&uart3_pins>; +}; + -- cgit v1.2.3 From 385306cc3ec98e2e4bccf3391da5b3dd0a26edb6 Mon Sep 17 00:00:00 2001 From: Florian Vaussard Date: Tue, 11 Mar 2014 13:20:29 +0100 Subject: ARM: dts: overo: Create a file for common Gumstix peripherals Gumstix expansion boards share a couple of peripherals: - uart3 is used for the console - AT24C01 EEPROM on i2c3 Use this file for overo-tobi. Signed-off-by: Florian Vaussard Signed-off-by: Tony Lindgren --- .../boot/dts/omap3-overo-common-peripherals.dtsi | 50 ++++++++++++++++++++++ arch/arm/boot/dts/omap3-overo-tobi-common.dtsi | 40 +---------------- 2 files changed, 52 insertions(+), 38 deletions(-) create mode 100644 arch/arm/boot/dts/omap3-overo-common-peripherals.dtsi diff --git a/arch/arm/boot/dts/omap3-overo-common-peripherals.dtsi b/arch/arm/boot/dts/omap3-overo-common-peripherals.dtsi new file mode 100644 index 000000000000..bca81ae0e646 --- /dev/null +++ b/arch/arm/boot/dts/omap3-overo-common-peripherals.dtsi @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2014 Florian Vaussard, EPFL Mobots group + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* + * Peripherals common to all Gumstix Overo boards (Tobi, Summit, Palo43,...) + */ + +&omap3_pmx_core { + i2c3_pins: pinmux_i2c3_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x21c2, PIN_INPUT | MUX_MODE0) /* i2c3_scl.i2c3_scl */ + OMAP3_CORE1_IOPAD(0x21c4, PIN_INPUT | MUX_MODE0) /* i2c3_sda.i2c3_sda */ + >; + }; + + uart3_pins: pinmux_uart3_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x219e, PIN_INPUT | PIN_OFF_WAKEUPENABLE | MUX_MODE0) /* uart3_rx_irrx.uart3_rx_irrx */ + OMAP3_CORE1_IOPAD(0x21a0, PIN_OUTPUT | MUX_MODE0) /* uart3_tx_irtx.uart3_tx_irtx */ + >; + }; +}; + +&i2c3 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c3_pins>; + clock-frequency = <100000>; + + /* optional 1K EEPROM with revision information */ + eeprom@51 { + compatible = "atmel,24c01"; + reg = <0x51>; + pagesize = <8>; + }; +}; + +&mmc3 { + status = "disabled"; +}; + +&uart3 { + pinctrl-names = "default"; + pinctrl-0 = <&uart3_pins>; +}; + diff --git a/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi b/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi index 384e87d7f3bb..060eb7710870 100644 --- a/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi +++ b/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi @@ -10,6 +10,8 @@ * Tobi expansion board is manufactured by Gumstix Inc. */ +#include "omap3-overo-common-peripherals.dtsi" + / { leds { compatible = "gpio-leds"; @@ -21,22 +23,6 @@ }; }; -&omap3_pmx_core { - i2c3_pins: pinmux_i2c3_pins { - pinctrl-single,pins = < - OMAP3_CORE1_IOPAD(0x21c2, PIN_INPUT | MUX_MODE0) /* i2c3_scl.i2c3_scl */ - OMAP3_CORE1_IOPAD(0x21c4, PIN_INPUT | MUX_MODE0) /* i2c3_sda.i2c3_sda */ - >; - }; - - uart3_pins: pinmux_uart3_pins { - pinctrl-single,pins = < - OMAP3_CORE1_IOPAD(0x219e, PIN_INPUT | PIN_OFF_WAKEUPENABLE | MUX_MODE0) /* uart3_rx_irrx.uart3_rx_irrx */ - OMAP3_CORE1_IOPAD(0x21a0, PIN_OUTPUT | MUX_MODE0) /* uart3_tx_irtx.uart3_tx_irtx */ - >; - }; -}; - #include "omap-gpmc-smsc9221.dtsi" &gpmc { @@ -49,25 +35,3 @@ }; }; -&i2c3 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c3_pins>; - clock-frequency = <100000>; - - /* optional 1K EEPROM with revision information */ - eeprom@51 { - compatible = "atmel,24c01"; - reg = <0x51>; - pagesize = <8>; - }; -}; - -&mmc3 { - status = "disabled"; -}; - -&uart3 { - pinctrl-names = "default"; - pinctrl-0 = <&uart3_pins>; -}; - -- cgit v1.2.3 From 72a5cf147d65271c65ae1c864ba130d817e12aea Mon Sep 17 00:00:00 2001 From: Florian Vaussard Date: Tue, 11 Mar 2014 13:20:30 +0100 Subject: ARM: dts: overo: Add LIS33DE accelerometer The LIS33DE accelerometer is used on several Gumstix expansion boards, thus add the DT node to omap3-overo-common-peripherals.dtsi. For the boards that do not have the accelerometer (like Tobi), mark the status as disabled. Signed-off-by: Florian Vaussard Signed-off-by: Tony Lindgren --- .../boot/dts/omap3-overo-common-peripherals.dtsi | 44 ++++++++++++++++++++++ arch/arm/boot/dts/omap3-overo-tobi-common.dtsi | 4 ++ 2 files changed, 48 insertions(+) diff --git a/arch/arm/boot/dts/omap3-overo-common-peripherals.dtsi b/arch/arm/boot/dts/omap3-overo-common-peripherals.dtsi index bca81ae0e646..5831bcc52966 100644 --- a/arch/arm/boot/dts/omap3-overo-common-peripherals.dtsi +++ b/arch/arm/boot/dts/omap3-overo-common-peripherals.dtsi @@ -10,6 +10,22 @@ * Peripherals common to all Gumstix Overo boards (Tobi, Summit, Palo43,...) */ +/ { + lis33_3v3: lis33-3v3-reg { + compatible = "regulator-fixed"; + regulator-name = "lis33-3v3-reg"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + lis33_1v8: lis33-1v8-reg { + compatible = "regulator-fixed"; + regulator-name = "lis33-1v8-reg"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; +}; + &omap3_pmx_core { i2c3_pins: pinmux_i2c3_pins { pinctrl-single,pins = < @@ -37,6 +53,34 @@ reg = <0x51>; pagesize = <8>; }; + + lis33de: lis33de@1d { + compatible = "st,lis33de", "st,lis3lv02d"; + reg = <0x1d>; + Vdd-supply = <&lis33_1v8>; + Vdd_IO-supply = <&lis33_3v3>; + + st,click-single-x; + st,click-single-y; + st,click-single-z; + st,click-thresh-x = <10>; + st,click-thresh-y = <10>; + st,click-thresh-z = <10>; + st,irq1-click; + st,irq2-click; + st,wakeup-x-lo; + st,wakeup-x-hi; + st,wakeup-y-lo; + st,wakeup-y-hi; + st,wakeup-z-lo; + st,wakeup-z-hi; + st,min-limit-x = <120>; + st,min-limit-y = <120>; + st,min-limit-z = <140>; + st,max-limit-x = <550>; + st,max-limit-y = <550>; + st,max-limit-z = <750>; + }; }; &mmc3 { diff --git a/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi b/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi index 060eb7710870..13df50b39442 100644 --- a/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi +++ b/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi @@ -35,3 +35,7 @@ }; }; +&lis33de { + status = "disabled"; +}; + -- cgit v1.2.3 From 22888e02a2962d5e46ea53e4744fce2df6fa0433 Mon Sep 17 00:00:00 2001 From: Florian Vaussard Date: Tue, 11 Mar 2014 13:20:31 +0100 Subject: ARM: dts: Add support for the Overo Palo43 Palo43 is an expansion board for Gumstix Overo products. Signed-off-by: Florian Vaussard Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/Makefile | 2 + arch/arm/boot/dts/omap3-overo-palo43-common.dtsi | 53 ++++++++++++++++++++++++ arch/arm/boot/dts/omap3-overo-palo43.dts | 38 +++++++++++++++++ arch/arm/boot/dts/omap3-overo-storm-palo43.dts | 38 +++++++++++++++++ 4 files changed, 131 insertions(+) create mode 100644 arch/arm/boot/dts/omap3-overo-palo43-common.dtsi create mode 100644 arch/arm/boot/dts/omap3-overo-palo43.dts create mode 100644 arch/arm/boot/dts/omap3-overo-storm-palo43.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 032030361bef..98d508d09703 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -209,6 +209,8 @@ dtb-$(CONFIG_ARCH_OMAP2PLUS) += omap2420-h4.dtb \ omap3-n900.dtb \ omap3-n9.dtb \ omap3-n950.dtb \ + omap3-overo-palo43.dtb \ + omap3-overo-storm-palo43.dtb \ omap3-overo-tobi.dtb \ omap3-overo-storm-tobi.dtb \ omap3-gta04.dtb \ diff --git a/arch/arm/boot/dts/omap3-overo-palo43-common.dtsi b/arch/arm/boot/dts/omap3-overo-palo43-common.dtsi new file mode 100644 index 000000000000..abea232825b9 --- /dev/null +++ b/arch/arm/boot/dts/omap3-overo-palo43-common.dtsi @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2014 Florian Vaussard, EPFL Mobots group + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* + * Palo43 expansion board is manufactured by Gumstix Inc. + */ + +#include "omap3-overo-common-peripherals.dtsi" + +#include + +/ { + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_pins>; + heartbeat { + label = "overo:red:gpio21"; + gpios = <&gpio1 21 GPIO_ACTIVE_LOW>; /* gpio_21 */ + linux,default-trigger = "heartbeat"; + }; + gpio22 { + label = "overo:blue:gpio22"; + gpios = <&gpio1 22 GPIO_ACTIVE_LOW>; /* gpio_22 */ + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + pinctrl-names = "default"; + pinctrl-0 = <&button_pins>; + #address-cells = <1>; + #size-cells = <0>; + button0@23 { + label = "button0"; + linux,code = ; + gpios = <&gpio1 23 GPIO_ACTIVE_LOW>; /* gpio_23 */ + gpio-key,wakeup; + }; + button1@14 { + label = "button1"; + linux,code = ; + gpios = <&gpio1 14 GPIO_ACTIVE_LOW>; /* gpio_14 */ + gpio-key,wakeup; + }; + }; +}; + diff --git a/arch/arm/boot/dts/omap3-overo-palo43.dts b/arch/arm/boot/dts/omap3-overo-palo43.dts new file mode 100644 index 000000000000..cedb103b4b66 --- /dev/null +++ b/arch/arm/boot/dts/omap3-overo-palo43.dts @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2014 Florian Vaussard, EPFL Mobots group + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* + * Palo43 expansion board is manufactured by Gumstix Inc. + */ + +/dts-v1/; + +#include "omap3-overo.dtsi" +#include "omap3-overo-palo43-common.dtsi" + +/ { + model = "OMAP35xx Gumstix Overo on Palo43"; + compatible = "gumstix,omap3-overo-palo43", "gumstix,omap3-overo", "ti,omap3430", "ti,omap3"; +}; + +&omap3_pmx_core2 { + led_pins: pinmux_led_pins { + pinctrl-single,pins = < + OMAP3430_CORE2_IOPAD(0x25ea, PIN_OUTPUT | MUX_MODE4) /* etk_d7.gpio_21 */ + OMAP3430_CORE2_IOPAD(0x25ec, PIN_OUTPUT | MUX_MODE4) /* etk_d8.gpio_22 */ + >; + }; + + button_pins: pinmux_button_pins { + pinctrl-single,pins = < + OMAP3430_CORE2_IOPAD(0x25ee, PIN_INPUT | MUX_MODE4) /* etk_d9.gpio_23 */ + OMAP3430_CORE2_IOPAD(0x25dc, PIN_INPUT | MUX_MODE4) /* etk_d0.gpio_14 */ + >; + }; +}; + diff --git a/arch/arm/boot/dts/omap3-overo-storm-palo43.dts b/arch/arm/boot/dts/omap3-overo-storm-palo43.dts new file mode 100644 index 000000000000..b585d8fbc347 --- /dev/null +++ b/arch/arm/boot/dts/omap3-overo-storm-palo43.dts @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2014 Florian Vaussard, EPFL Mobots group + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* + * Palo43 expansion board is manufactured by Gumstix Inc. + */ + +/dts-v1/; + +#include "omap3-overo-storm.dtsi" +#include "omap3-overo-palo43-common.dtsi" + +/ { + model = "OMAP36xx/AM37xx/DM37xx Gumstix Overo on Palo43"; + compatible = "gumstix,omap3-overo-palo43", "gumstix,omap3-overo", "ti,omap36xx", "ti,omap3"; +}; + +&omap3_pmx_core2 { + led_pins: pinmux_led_pins { + pinctrl-single,pins = < + OMAP3630_CORE2_IOPAD(0x25ea, PIN_OUTPUT | MUX_MODE4) /* etk_d7.gpio_21 */ + OMAP3630_CORE2_IOPAD(0x25ec, PIN_OUTPUT | MUX_MODE4) /* etk_d8.gpio_22 */ + >; + }; + + button_pins: pinmux_button_pins { + pinctrl-single,pins = < + OMAP3630_CORE2_IOPAD(0x25ee, PIN_INPUT | MUX_MODE4) /* etk_d9.gpio_23 */ + OMAP3630_CORE2_IOPAD(0x25dc, PIN_INPUT | MUX_MODE4) /* etk_d0.gpio_14 */ + >; + }; +}; + -- cgit v1.2.3 From 2185bc7509daf7b453aa631fbba47844ed3a969e Mon Sep 17 00:00:00 2001 From: Florian Vaussard Date: Tue, 11 Mar 2014 13:20:32 +0100 Subject: ARM: dts: Add support for the Overo Gallop43 Gallop43 is an expansion board for Gumstix Overo products. Signed-off-by: Florian Vaussard Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/Makefile | 2 + arch/arm/boot/dts/omap3-overo-gallop43-common.dtsi | 57 ++++++++++++++++++++++ arch/arm/boot/dts/omap3-overo-gallop43.dts | 38 +++++++++++++++ arch/arm/boot/dts/omap3-overo-storm-gallop43.dts | 38 +++++++++++++++ 4 files changed, 135 insertions(+) create mode 100644 arch/arm/boot/dts/omap3-overo-gallop43-common.dtsi create mode 100644 arch/arm/boot/dts/omap3-overo-gallop43.dts create mode 100644 arch/arm/boot/dts/omap3-overo-storm-gallop43.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 98d508d09703..bd7821b26452 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -209,6 +209,8 @@ dtb-$(CONFIG_ARCH_OMAP2PLUS) += omap2420-h4.dtb \ omap3-n900.dtb \ omap3-n9.dtb \ omap3-n950.dtb \ + omap3-overo-gallop43.dtb \ + omap3-overo-storm-gallop43.dtb \ omap3-overo-palo43.dtb \ omap3-overo-storm-palo43.dtb \ omap3-overo-tobi.dtb \ diff --git a/arch/arm/boot/dts/omap3-overo-gallop43-common.dtsi b/arch/arm/boot/dts/omap3-overo-gallop43-common.dtsi new file mode 100644 index 000000000000..5e848c26986b --- /dev/null +++ b/arch/arm/boot/dts/omap3-overo-gallop43-common.dtsi @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2014 Florian Vaussard, EPFL Mobots group + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* + * Gallop43 expansion board is manufactured by Gumstix Inc. + */ + +#include "omap3-overo-common-peripherals.dtsi" + +#include + +/ { + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_pins>; + heartbeat { + label = "overo:red:gpio21"; + gpios = <&gpio1 21 GPIO_ACTIVE_LOW>; /* gpio_21 */ + linux,default-trigger = "heartbeat"; + }; + gpio22 { + label = "overo:blue:gpio22"; + gpios = <&gpio1 22 GPIO_ACTIVE_LOW>; /* gpio_22 */ + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + pinctrl-names = "default"; + pinctrl-0 = <&button_pins>; + #address-cells = <1>; + #size-cells = <0>; + button0@23 { + label = "button0"; + linux,code = ; + gpios = <&gpio1 23 GPIO_ACTIVE_LOW>; /* gpio_23 */ + gpio-key,wakeup; + }; + button1@14 { + label = "button1"; + linux,code = ; + gpios = <&gpio1 14 GPIO_ACTIVE_LOW>; /* gpio_14 */ + gpio-key,wakeup; + }; + }; +}; + +&usbhshost { + status = "disabled"; +}; + diff --git a/arch/arm/boot/dts/omap3-overo-gallop43.dts b/arch/arm/boot/dts/omap3-overo-gallop43.dts new file mode 100644 index 000000000000..241f5c1914e0 --- /dev/null +++ b/arch/arm/boot/dts/omap3-overo-gallop43.dts @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2014 Florian Vaussard, EPFL Mobots group + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* + * Gallop43 expansion board is manufactured by Gumstix Inc. + */ + +/dts-v1/; + +#include "omap3-overo.dtsi" +#include "omap3-overo-gallop43-common.dtsi" + +/ { + model = "OMAP35xx Gumstix Overo on Gallop43"; + compatible = "gumstix,omap3-overo-gallop43", "gumstix,omap3-overo", "ti,omap3430", "ti,omap3"; +}; + +&omap3_pmx_core2 { + led_pins: pinmux_led_pins { + pinctrl-single,pins = < + OMAP3430_CORE2_IOPAD(0x25ea, PIN_OUTPUT | MUX_MODE4) /* etk_d7.gpio_21 */ + OMAP3430_CORE2_IOPAD(0x25ec, PIN_OUTPUT | MUX_MODE4) /* etk_d8.gpio_22 */ + >; + }; + + button_pins: pinmux_button_pins { + pinctrl-single,pins = < + OMAP3430_CORE2_IOPAD(0x25ee, PIN_INPUT | MUX_MODE4) /* etk_d9.gpio_23 */ + OMAP3430_CORE2_IOPAD(0x25dc, PIN_INPUT | MUX_MODE4) /* etk_d0.gpio_14 */ + >; + }; +}; + diff --git a/arch/arm/boot/dts/omap3-overo-storm-gallop43.dts b/arch/arm/boot/dts/omap3-overo-storm-gallop43.dts new file mode 100644 index 000000000000..a1b57e0cf37f --- /dev/null +++ b/arch/arm/boot/dts/omap3-overo-storm-gallop43.dts @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2014 Florian Vaussard, EPFL Mobots group + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* + * Gallop43 expansion board is manufactured by Gumstix Inc. + */ + +/dts-v1/; + +#include "omap3-overo-storm.dtsi" +#include "omap3-overo-gallop43-common.dtsi" + +/ { + model = "OMAP36xx/AM37xx/DM37xx Gumstix Overo on Gallop43"; + compatible = "gumstix,omap3-overo-gallop43", "gumstix,omap3-overo", "ti,omap36xx", "ti,omap3"; +}; + +&omap3_pmx_core2 { + led_pins: pinmux_led_pins { + pinctrl-single,pins = < + OMAP3630_CORE2_IOPAD(0x25ea, PIN_OUTPUT | MUX_MODE4) /* etk_d7.gpio_21 */ + OMAP3630_CORE2_IOPAD(0x25ec, PIN_OUTPUT | MUX_MODE4) /* etk_d8.gpio_22 */ + >; + }; + + button_pins: pinmux_button_pins { + pinctrl-single,pins = < + OMAP3630_CORE2_IOPAD(0x25ee, PIN_INPUT | MUX_MODE4) /* etk_d9.gpio_23 */ + OMAP3630_CORE2_IOPAD(0x25dc, PIN_INPUT | MUX_MODE4) /* etk_d0.gpio_14 */ + >; + }; +}; + -- cgit v1.2.3 From 2e591ca01cdb174a18ebc7685001bbb403c6d53d Mon Sep 17 00:00:00 2001 From: Florian Vaussard Date: Tue, 11 Mar 2014 13:20:33 +0100 Subject: ARM: dts: Add support for the Overo Alto35 Alto35 is an expansion board for Gumstix Overo products. Signed-off-by: Florian Vaussard Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/Makefile | 2 + arch/arm/boot/dts/omap3-overo-alto35-common.dtsi | 77 ++++++++++++++++++++++++ arch/arm/boot/dts/omap3-overo-alto35.dts | 22 +++++++ arch/arm/boot/dts/omap3-overo-storm-alto35.dts | 21 +++++++ 4 files changed, 122 insertions(+) create mode 100644 arch/arm/boot/dts/omap3-overo-alto35-common.dtsi create mode 100644 arch/arm/boot/dts/omap3-overo-alto35.dts create mode 100644 arch/arm/boot/dts/omap3-overo-storm-alto35.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index bd7821b26452..de5cfcc45cc9 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -209,6 +209,8 @@ dtb-$(CONFIG_ARCH_OMAP2PLUS) += omap2420-h4.dtb \ omap3-n900.dtb \ omap3-n9.dtb \ omap3-n950.dtb \ + omap3-overo-alto35.dtb \ + omap3-overo-storm-alto35.dtb \ omap3-overo-gallop43.dtb \ omap3-overo-storm-gallop43.dtb \ omap3-overo-palo43.dtb \ diff --git a/arch/arm/boot/dts/omap3-overo-alto35-common.dtsi b/arch/arm/boot/dts/omap3-overo-alto35-common.dtsi new file mode 100644 index 000000000000..19d64864a109 --- /dev/null +++ b/arch/arm/boot/dts/omap3-overo-alto35-common.dtsi @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2014 Florian Vaussard, EPFL Mobots group + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* + * Alto35 expansion board is manufactured by Gumstix Inc. + */ + +#include "omap3-overo-common-peripherals.dtsi" + +#include + +/ { + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_pins>; + gpio148 { + label = "overo:red:gpio148"; + gpios = <&gpio5 20 GPIO_ACTIVE_HIGH>; /* gpio 148 */ + }; + gpio150 { + label = "overo:yellow:gpio150"; + gpios = <&gpio5 22 GPIO_ACTIVE_HIGH>; /* gpio 150 */ + }; + gpio151 { + label = "overo:blue:gpio151"; + gpios = <&gpio5 23 GPIO_ACTIVE_HIGH>; /* gpio 151 */ + }; + gpio170 { + label = "overo:green:gpio170"; + gpios = <&gpio6 10 GPIO_ACTIVE_HIGH>; /* gpio 170 */ + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&button_pins>; + button0@10 { + label = "button0"; + linux,code = ; + gpios = <&gpio1 10 GPIO_ACTIVE_LOW>; /* gpio_10 */ + gpio-key,wakeup; + }; + }; +}; + +&omap3_pmx_core { + led_pins: pinmux_led_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x217c, PIN_OUTPUT | MUX_MODE4) /* uart1_tx.gpio_148 */ + OMAP3_CORE1_IOPAD(0x2180, PIN_OUTPUT | MUX_MODE4) /* uart1_cts.gpio_150 */ + OMAP3_CORE1_IOPAD(0x2182, PIN_OUTPUT | MUX_MODE4) /* uart1_rx.gpio_151 */ + OMAP3_CORE1_IOPAD(0x21c6, PIN_OUTPUT | MUX_MODE4) /* hdq_sio.gpio_170 */ + >; + }; +}; + +&omap3_pmx_wkup { + button_pins: pinmux_button_pins { + pinctrl-single,pins = < + OMAP3_WKUP_IOPAD(0x2a18, PIN_INPUT | MUX_MODE4) /* sys_clkout1.gpio_10 */ + >; + }; +}; + +&usbhshost { + status = "disabled"; +}; + diff --git a/arch/arm/boot/dts/omap3-overo-alto35.dts b/arch/arm/boot/dts/omap3-overo-alto35.dts new file mode 100644 index 000000000000..a3249eb7501d --- /dev/null +++ b/arch/arm/boot/dts/omap3-overo-alto35.dts @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2014 Florian Vaussard, EPFL Mobots group + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* + * Alto35 expansion board is manufactured by Gumstix Inc. + */ + +/dts-v1/; + +#include "omap3-overo.dtsi" +#include "omap3-overo-alto35-common.dtsi" + +/ { + model = "OMAP35xx Gumstix Overo on Alto35"; + compatible = "gumstix,omap3-overo-alto35", "gumstix,omap3-overo", "ti,omap3430", "ti,omap3"; +}; + diff --git a/arch/arm/boot/dts/omap3-overo-storm-alto35.dts b/arch/arm/boot/dts/omap3-overo-storm-alto35.dts new file mode 100644 index 000000000000..e9cae52afc25 --- /dev/null +++ b/arch/arm/boot/dts/omap3-overo-storm-alto35.dts @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2014 Florian Vaussard, EPFL Mobots group + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* + * Alto35 expansion board is manufactured by Gumstix Inc. + */ + +/dts-v1/; + +#include "omap3-overo-storm.dtsi" +#include "omap3-overo-alto35-common.dtsi" + +/ { + model = "OMAP36xx/AM37xx/DM37xx Gumstix Overo on Alto35"; + compatible = "gumstix,omap3-overo-alto35", "gumstix,omap3-overo", "ti,omap36xx", "ti,omap3"; +}; -- cgit v1.2.3 From 1c29b9e664e0f7988b3cb475c568e9a923ccf452 Mon Sep 17 00:00:00 2001 From: Florian Vaussard Date: Tue, 11 Mar 2014 13:20:34 +0100 Subject: ARM: dts: Add support for the Overo Chestnut43 Chestnut43 is an expansion board for Gumstix Overo products. Signed-off-by: Florian Vaussard Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/Makefile | 2 + .../boot/dts/omap3-overo-chestnut43-common.dtsi | 69 ++++++++++++++++++++++ arch/arm/boot/dts/omap3-overo-chestnut43.dts | 38 ++++++++++++ arch/arm/boot/dts/omap3-overo-storm-chestnut43.dts | 38 ++++++++++++ 4 files changed, 147 insertions(+) create mode 100644 arch/arm/boot/dts/omap3-overo-chestnut43-common.dtsi create mode 100644 arch/arm/boot/dts/omap3-overo-chestnut43.dts create mode 100644 arch/arm/boot/dts/omap3-overo-storm-chestnut43.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index de5cfcc45cc9..7742e6919133 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -211,6 +211,8 @@ dtb-$(CONFIG_ARCH_OMAP2PLUS) += omap2420-h4.dtb \ omap3-n950.dtb \ omap3-overo-alto35.dtb \ omap3-overo-storm-alto35.dtb \ + omap3-overo-chestnut43.dtb \ + omap3-overo-storm-chestnut43.dtb \ omap3-overo-gallop43.dtb \ omap3-overo-storm-gallop43.dtb \ omap3-overo-palo43.dtb \ diff --git a/arch/arm/boot/dts/omap3-overo-chestnut43-common.dtsi b/arch/arm/boot/dts/omap3-overo-chestnut43-common.dtsi new file mode 100644 index 000000000000..19de6ff79686 --- /dev/null +++ b/arch/arm/boot/dts/omap3-overo-chestnut43-common.dtsi @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2014 Florian Vaussard, EPFL Mobots group + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* + * Chestnut43 expansion board is manufactured by Gumstix Inc. + */ + +#include "omap3-overo-common-peripherals.dtsi" + +#include + +/ { + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_pins>; + heartbeat { + label = "overo:red:gpio21"; + gpios = <&gpio1 21 GPIO_ACTIVE_LOW>; /* gpio_21 */ + linux,default-trigger = "heartbeat"; + }; + gpio22 { + label = "overo:blue:gpio22"; + gpios = <&gpio1 22 GPIO_ACTIVE_LOW>; /* gpio_22 */ + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + pinctrl-names = "default"; + pinctrl-0 = <&button_pins>; + #address-cells = <1>; + #size-cells = <0>; + button0@23 { + label = "button0"; + linux,code = ; + gpios = <&gpio1 23 GPIO_ACTIVE_LOW>; /* gpio_23 */ + gpio-key,wakeup; + }; + button1@14 { + label = "button1"; + linux,code = ; + gpios = <&gpio1 14 GPIO_ACTIVE_LOW>; /* gpio_14 */ + gpio-key,wakeup; + }; + }; +}; + +#include "omap-gpmc-smsc9221.dtsi" + +&gpmc { + ranges = <5 0 0x2c000000 0x1000000>; /* CS5 */ + + ethernet@gpmc { + reg = <5 0 0xff>; + interrupt-parent = <&gpio6>; + interrupts = <16 IRQ_TYPE_LEVEL_LOW>; /* GPIO 176 */ + }; +}; + +&lis33de { + status = "disabled"; +}; + diff --git a/arch/arm/boot/dts/omap3-overo-chestnut43.dts b/arch/arm/boot/dts/omap3-overo-chestnut43.dts new file mode 100644 index 000000000000..fe0824aca3c0 --- /dev/null +++ b/arch/arm/boot/dts/omap3-overo-chestnut43.dts @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2014 Florian Vaussard, EPFL Mobots group + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* + * Chestnut43 expansion board is manufactured by Gumstix Inc. + */ + +/dts-v1/; + +#include "omap3-overo.dtsi" +#include "omap3-overo-chestnut43-common.dtsi" + +/ { + model = "OMAP35xx Gumstix Overo on Chestnut43"; + compatible = "gumstix,omap3-overo-chestnut43", "gumstix,omap3-overo", "ti,omap3430", "ti,omap3"; +}; + +&omap3_pmx_core2 { + led_pins: pinmux_led_pins { + pinctrl-single,pins = < + OMAP3430_CORE2_IOPAD(0x25ea, PIN_OUTPUT | MUX_MODE4) /* etk_d7.gpio_21 */ + OMAP3430_CORE2_IOPAD(0x25ec, PIN_OUTPUT | MUX_MODE4) /* etk_d8.gpio_22 */ + >; + }; + + button_pins: pinmux_button_pins { + pinctrl-single,pins = < + OMAP3430_CORE2_IOPAD(0x25ee, PIN_INPUT | MUX_MODE4) /* etk_d9.gpio_23 */ + OMAP3430_CORE2_IOPAD(0x25dc, PIN_INPUT | MUX_MODE4) /* etk_d0.gpio_14 */ + >; + }; +}; + diff --git a/arch/arm/boot/dts/omap3-overo-storm-chestnut43.dts b/arch/arm/boot/dts/omap3-overo-storm-chestnut43.dts new file mode 100644 index 000000000000..7d82fdfd9909 --- /dev/null +++ b/arch/arm/boot/dts/omap3-overo-storm-chestnut43.dts @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2014 Florian Vaussard, EPFL Mobots group + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* + * Chestnut43 expansion board is manufactured by Gumstix Inc. + */ + +/dts-v1/; + +#include "omap3-overo-storm.dtsi" +#include "omap3-overo-chestnut43-common.dtsi" + +/ { + model = "OMAP36xx/AM37xx/DM37xx Gumstix Overo on Chestnut43"; + compatible = "gumstix,omap3-overo-chestnut43", "gumstix,omap3-overo", "ti,omap36xx", "ti,omap3"; +}; + +&omap3_pmx_core2 { + led_pins: pinmux_led_pins { + pinctrl-single,pins = < + OMAP3630_CORE2_IOPAD(0x25ea, PIN_OUTPUT | MUX_MODE4) /* etk_d7.gpio_21 */ + OMAP3630_CORE2_IOPAD(0x25ec, PIN_OUTPUT | MUX_MODE4) /* etk_d8.gpio_22 */ + >; + }; + + button_pins: pinmux_button_pins { + pinctrl-single,pins = < + OMAP3630_CORE2_IOPAD(0x25ee, PIN_INPUT | MUX_MODE4) /* etk_d9.gpio_23 */ + OMAP3630_CORE2_IOPAD(0x25dc, PIN_INPUT | MUX_MODE4) /* etk_d0.gpio_14 */ + >; + }; +}; + -- cgit v1.2.3 From 28b191118c11719bb27db621425a70be28a40e08 Mon Sep 17 00:00:00 2001 From: Florian Vaussard Date: Tue, 11 Mar 2014 13:20:35 +0100 Subject: ARM: dts: Add support for the Overo Summit Summit is an expansion board for Gumstix Overo products. Signed-off-by: Florian Vaussard Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/Makefile | 2 ++ arch/arm/boot/dts/omap3-overo-storm-summit.dts | 30 +++++++++++++++++++++++ arch/arm/boot/dts/omap3-overo-summit-common.dtsi | 31 ++++++++++++++++++++++++ arch/arm/boot/dts/omap3-overo-summit.dts | 30 +++++++++++++++++++++++ 4 files changed, 93 insertions(+) create mode 100644 arch/arm/boot/dts/omap3-overo-storm-summit.dts create mode 100644 arch/arm/boot/dts/omap3-overo-summit-common.dtsi create mode 100644 arch/arm/boot/dts/omap3-overo-summit.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 7742e6919133..6565a7d9a618 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -217,6 +217,8 @@ dtb-$(CONFIG_ARCH_OMAP2PLUS) += omap2420-h4.dtb \ omap3-overo-storm-gallop43.dtb \ omap3-overo-palo43.dtb \ omap3-overo-storm-palo43.dtb \ + omap3-overo-summit.dtb \ + omap3-overo-storm-summit.dtb \ omap3-overo-tobi.dtb \ omap3-overo-storm-tobi.dtb \ omap3-gta04.dtb \ diff --git a/arch/arm/boot/dts/omap3-overo-storm-summit.dts b/arch/arm/boot/dts/omap3-overo-storm-summit.dts new file mode 100644 index 000000000000..a0d7fd8369d7 --- /dev/null +++ b/arch/arm/boot/dts/omap3-overo-storm-summit.dts @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2014 Florian Vaussard, EPFL Mobots group + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* + * Summit expansion board is manufactured by Gumstix Inc. + */ + +/dts-v1/; + +#include "omap3-overo-storm.dtsi" +#include "omap3-overo-summit-common.dtsi" + +/ { + model = "OMAP36xx/AM37xx/DM37xx Gumstix Overo on Summit"; + compatible = "gumstix,omap3-overo-summit", "gumstix,omap3-overo", "ti,omap36xx", "ti,omap3"; +}; + +&omap3_pmx_core2 { + led_pins: pinmux_led_pins { + pinctrl-single,pins = < + OMAP3630_CORE2_IOPAD(0x25ea, PIN_OUTPUT | MUX_MODE4) /* etk_d7.gpio_21 */ + >; + }; +}; + diff --git a/arch/arm/boot/dts/omap3-overo-summit-common.dtsi b/arch/arm/boot/dts/omap3-overo-summit-common.dtsi new file mode 100644 index 000000000000..999d1cd4a09f --- /dev/null +++ b/arch/arm/boot/dts/omap3-overo-summit-common.dtsi @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2014 Florian Vaussard, EPFL Mobots group + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* + * Summit expansion board is manufactured by Gumstix Inc. + */ + +#include "omap3-overo-common-peripherals.dtsi" + +/ { + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_pins>; + heartbeat { + label = "overo:red:gpio21"; + gpios = <&gpio1 21 GPIO_ACTIVE_LOW>; /* gpio_21 */ + linux,default-trigger = "heartbeat"; + }; + }; +}; + +&lis33de { + status = "disabled"; +}; + diff --git a/arch/arm/boot/dts/omap3-overo-summit.dts b/arch/arm/boot/dts/omap3-overo-summit.dts new file mode 100644 index 000000000000..69765609455a --- /dev/null +++ b/arch/arm/boot/dts/omap3-overo-summit.dts @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2014 Florian Vaussard, EPFL Mobots group + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* + * Summit expansion board is manufactured by Gumstix Inc. + */ + +/dts-v1/; + +#include "omap3-overo.dtsi" +#include "omap3-overo-summit-common.dtsi" + +/ { + model = "OMAP35xx Gumstix Overo on Summit"; + compatible = "gumstix,omap3-overo-summit", "gumstix,omap3-overo", "ti,omap3430", "ti,omap3"; +}; + +&omap3_pmx_core2 { + led_pins: pinmux_led_pins { + pinctrl-single,pins = < + OMAP3430_CORE2_IOPAD(0x25ea, PIN_OUTPUT | MUX_MODE4) /* etk_d7.gpio_21 */ + >; + }; +}; + -- cgit v1.2.3