From 83d5f3246fc05a629278240c09688fd9960b97db Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Wed, 11 Dec 2013 18:45:00 +0000 Subject: staging:iio:ad799x fix incorrect endianness specification for buffer elements Due to use of the IIO_ST macro, the endianness element of scan_type was not being set. The result is that it will default to the cpu endianness whereas this driver will fill the buffer with big endian data. Thus for little endian machines, userspace will miss interpret the data. Signed-off-by: Jonathan Cameron Acked-by: Lars-Peter Clausen diff --git a/drivers/staging/iio/adc/ad799x_core.c b/drivers/staging/iio/adc/ad799x_core.c index 9428be8..bad4c8a 100644 --- a/drivers/staging/iio/adc/ad799x_core.c +++ b/drivers/staging/iio/adc/ad799x_core.c @@ -409,7 +409,13 @@ static const struct iio_event_spec ad799x_events[] = { .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ .scan_index = (_index), \ - .scan_type = IIO_ST('u', _realbits, 16, 12 - (_realbits)), \ + .scan_type = { \ + .sign = 'u', \ + .realbits = (_realbits), \ + .storagebits = 16, \ + .shift = 12 - (_realbits), \ + .endianness = IIO_BE, \ + }, \ .event_spec = _ev_spec, \ .num_event_specs = _num_ev_spec, \ } -- cgit v0.10.2 From e9ed104de68c345c9a827225e93c74c6894613a9 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Wed, 1 Jan 2014 13:07:00 +0000 Subject: staging:iio:impedance:ad5933: correct error check iio_kfifo_allocate returns NULL in case of error. The semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @@ expression *x; identifier f; statement S1,S2; @@ *x = f(...); if (x) { <+... when != if (...) S1 else S2 -ENOMEM ...+> } // Signed-off-by: Julia Lawall Signed-off-by: Jonathan Cameron cc: stable@vger.kernel.org diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c index 0a4298b..2b96665 100644 --- a/drivers/staging/iio/impedance-analyzer/ad5933.c +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c @@ -629,7 +629,7 @@ static int ad5933_register_ring_funcs_and_init(struct iio_dev *indio_dev) struct iio_buffer *buffer; buffer = iio_kfifo_allocate(indio_dev); - if (buffer) + if (!buffer) return -ENOMEM; iio_device_attach_buffer(indio_dev, buffer); -- cgit v0.10.2 From 66c65d90db1004356281db6ead988e2e38ba9e37 Mon Sep 17 00:00:00 2001 From: Craig Markwardt <> Date: Wed, 1 Jan 2014 15:38:52 +0000 Subject: iio: Fix a buffer overflow in iio_utils.h example code This was originally reported by Craig Markwardt on Zubair Lutfullah's blog and Zubair forwarded it to linux-iio@vger.kernel.org. No email address known. The code first counted the number of enabled channels, then created an array to hold information about them. The code that filled this array then stored whether a given element was enabled inside the array. Curriously this element was never used. Craig's patch added a local temporary variable to avoid the buffer overrun. Jonathan then removed the original enabled element of the structure as it was not needed at all. Signed-off-by: Zubair Lutfullah Signed-off-by: Jonathan Cameron diff --git a/drivers/staging/iio/Documentation/iio_utils.h b/drivers/staging/iio/Documentation/iio_utils.h index 35154d6..c9fedb7 100644 --- a/drivers/staging/iio/Documentation/iio_utils.h +++ b/drivers/staging/iio/Documentation/iio_utils.h @@ -77,7 +77,6 @@ struct iio_channel_info { uint64_t mask; unsigned be; unsigned is_signed; - unsigned enabled; unsigned location; }; @@ -335,6 +334,7 @@ inline int build_channel_array(const char *device_dir, while (ent = readdir(dp), ent != NULL) { if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"), "_en") == 0) { + int current_enabled = 0; current = &(*ci_array)[count++]; ret = asprintf(&filename, "%s/%s", scan_el_dir, ent->d_name); @@ -350,10 +350,10 @@ inline int build_channel_array(const char *device_dir, ret = -errno; goto error_cleanup_array; } - fscanf(sysfsfp, "%u", ¤t->enabled); + fscanf(sysfsfp, "%u", ¤t_enabled); fclose(sysfsfp); - if (!current->enabled) { + if (!current_enabled) { free(filename); count--; continue; -- cgit v0.10.2 From 38408d056188be29a6c4e17f3703c796551bb330 Mon Sep 17 00:00:00 2001 From: Hartmut Knaack Date: Wed, 1 Jan 2014 23:04:00 +0000 Subject: staging:iio:ad799x fix error_free_irq which was freeing an irq that may not have been requested Only free an IRQ in error_free_irq, if it has been requested previously. Signed-off-by: Hartmut Knaack Acked-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron Cc: stable@vger.kernel.org diff --git a/drivers/staging/iio/adc/ad799x_core.c b/drivers/staging/iio/adc/ad799x_core.c index bad4c8a..c1b601ac 100644 --- a/drivers/staging/iio/adc/ad799x_core.c +++ b/drivers/staging/iio/adc/ad799x_core.c @@ -594,7 +594,8 @@ static int ad799x_probe(struct i2c_client *client, return 0; error_free_irq: - free_irq(client->irq, indio_dev); + if (client->irq > 0) + free_irq(client->irq, indio_dev); error_cleanup_ring: ad799x_ring_cleanup(indio_dev); error_disable_reg: -- cgit v0.10.2 From 3b5c1635d12a670a0fea5542ada5bceb6536ae85 Mon Sep 17 00:00:00 2001 From: Ivaylo Dimitrov Date: Mon, 13 Jan 2014 17:24:00 +0000 Subject: iio: tsl2563: Use the correct channel2 member Use the correct channel2 member instead of channel when dealing with sysfs reads/writes Signed-off-by: Ivaylo Dimitrov Acked-by: Peter Meerwald Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/light/tsl2563.c b/drivers/iio/light/tsl2563.c index 5e5d9de..2be6df3 100644 --- a/drivers/iio/light/tsl2563.c +++ b/drivers/iio/light/tsl2563.c @@ -460,10 +460,14 @@ static int tsl2563_write_raw(struct iio_dev *indio_dev, { struct tsl2563_chip *chip = iio_priv(indio_dev); - if (chan->channel == IIO_MOD_LIGHT_BOTH) + if (mask != IIO_CHAN_INFO_CALIBSCALE) + return -EINVAL; + if (chan->channel2 == IIO_MOD_LIGHT_BOTH) chip->calib0 = calib_from_sysfs(val); - else + else if (chan->channel2 == IIO_MOD_LIGHT_IR) chip->calib1 = calib_from_sysfs(val); + else + return -EINVAL; return 0; } @@ -472,14 +476,14 @@ static int tsl2563_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, - long m) + long mask) { int ret = -EINVAL; u32 calib0, calib1; struct tsl2563_chip *chip = iio_priv(indio_dev); mutex_lock(&chip->lock); - switch (m) { + switch (mask) { case IIO_CHAN_INFO_RAW: case IIO_CHAN_INFO_PROCESSED: switch (chan->type) { @@ -498,7 +502,7 @@ static int tsl2563_read_raw(struct iio_dev *indio_dev, ret = tsl2563_get_adc(chip); if (ret) goto error_ret; - if (chan->channel == 0) + if (chan->channel2 == IIO_MOD_LIGHT_BOTH) *val = chip->data0; else *val = chip->data1; @@ -510,7 +514,7 @@ static int tsl2563_read_raw(struct iio_dev *indio_dev, break; case IIO_CHAN_INFO_CALIBSCALE: - if (chan->channel == 0) + if (chan->channel2 == IIO_MOD_LIGHT_BOTH) *val = calib_to_sysfs(chip->calib0); else *val = calib_to_sysfs(chip->calib1); -- cgit v0.10.2 From 1c51eb0bcf3489f72e1923241db7b6993442b13f Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Tue, 14 Jan 2014 15:45:00 +0000 Subject: staging:iio:spear_adc: Add dependency on HAS_IOMEM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On archs like S390 or um this driver cannot build nor work. Make it depend on HAS_IOMEM to bypass build failures. drivers/staging/iio/adc/spear_adc.c: In function ‘spear_adc_probe’: drivers/staging/iio/adc/spear_adc.c:393:2: error: implicit declaration of function ‘iounmap’ [-Werror=implicit-function-declaration Signed-off-by: Richard Weinberger Signed-off-by: Jonathan Cameron diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig index e3d6430..7d5d675 100644 --- a/drivers/staging/iio/adc/Kconfig +++ b/drivers/staging/iio/adc/Kconfig @@ -128,6 +128,7 @@ config MXS_LRADC config SPEAR_ADC tristate "ST SPEAr ADC" depends on PLAT_SPEAR || COMPILE_TEST + depends on HAS_IOMEM help Say yes here to build support for the integrated ADC inside the ST SPEAr SoC. Provides direct access via sysfs. -- cgit v0.10.2 From 8c314da583c9d5c67fe59aa8c92f94f15cb8de90 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Tue, 14 Jan 2014 15:45:00 +0000 Subject: staging:iio:lpc32xx_adc: 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/built-in.o: In function `lpc32xx_adc_probe': drivers/staging/iio/adc/lpc32xx_adc.c:149: undefined reference to `devm_ioremap' Signed-off-by: Richard Weinberger Signed-off-by: Jonathan Cameron diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig index 7d5d675..3633298 100644 --- a/drivers/staging/iio/adc/Kconfig +++ b/drivers/staging/iio/adc/Kconfig @@ -103,6 +103,7 @@ config AD7280 config LPC32XX_ADC tristate "NXP LPC32XX ADC" depends on ARCH_LPC32XX || COMPILE_TEST + depends on HAS_IOMEM help Say yes here to build support for the integrated ADC inside the LPC32XX SoC. Note that this feature uses the same hardware as the -- cgit v0.10.2 From 1aa9578c1a9450fb21501c4f549f5b1edb557e6d Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Fri, 17 Jan 2014 15:38:12 -0800 Subject: xhci: Fix resume issues on Renesas chips in Samsung laptops Don Zickus writes: Some co-workers of mine bought Samsung laptops that had mostly usb3 ports. Those ports did not resume correctly (the driver would timeout communicating and fail). This led to frustration as suspend/resume is a common use for laptops. Poking around, I applied the reset on resume quirk to this chipset and the resume started working. Reloading the xhci_hcd module had been the temporary workaround. Signed-off-by: Sarah Sharp Reported-by: Don Zickus Tested-by: Prarit Bhargava Cc: stable # 2.6.37 diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 3c898c1..04f986d 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -142,6 +142,11 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) "QUIRK: Resetting on resume"); xhci->quirks |= XHCI_TRUST_TX_LENGTH; } + if (pdev->vendor == PCI_VENDOR_ID_RENESAS && + pdev->device == 0x0015 && + pdev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG && + pdev->subsystem_device == 0xc0cd) + xhci->quirks |= XHCI_RESET_ON_RESUME; if (pdev->vendor == PCI_VENDOR_ID_VIA) xhci->quirks |= XHCI_RESET_ON_RESUME; } -- cgit v0.10.2 From 140e3026a57ab7d830dab2f2c57796c222db0ea9 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Wed, 22 Jan 2014 13:35:02 -0800 Subject: Revert "usbcore: set lpm_capable field for LPM capable root hubs" Commit 9df89d85b407690afa46ddfbccc80bec6869971d "usbcore: set lpm_capable field for LPM capable root hubs" was created under the assumption that all USB host controllers should have USB 3.0 Link PM enabled for all devices under the hosts. Unfortunately, that's not the case. The xHCI driver relies on knowledge of the host hardware scheduler to calculate the LPM U1/U2 timeout values, and it only sets lpm_capable to one for Intel host controllers (that have the XHCI_LPM_SUPPORT quirk set). When LPM is enabled for some Fresco Logic hosts, it causes failures with a AgeStar 3UBT USB 3.0 hard drive dock: Jan 11 13:59:03 sg-laptop kernel: usb 3-1: new SuperSpeed USB device number 2 using xhci_hcd Jan 11 13:59:03 sg-laptop kernel: usb 3-1: Set SEL for device-initiated U1 failed. Jan 11 13:59:08 sg-laptop kernel: usb 3-1: Set SEL for device-initiated U2 failed. Jan 11 13:59:08 sg-laptop kernel: usb-storage 3-1:1.0: USB Mass Storage device detected Jan 11 13:59:08 sg-laptop mtp-probe[613]: checking bus 3, device 2: "/sys/devices/pci0000:00/0000:00:1c.3/0000:04:00.0/usb3/3-1" Jan 11 13:59:08 sg-laptop mtp-probe[613]: bus: 3, device: 2 was not an MTP device Jan 11 13:59:08 sg-laptop kernel: scsi6 : usb-storage 3-1:1.0 Jan 11 13:59:13 sg-laptop kernel: usb 3-1: Set SEL for device-initiated U1 failed. Jan 11 13:59:18 sg-laptop kernel: usb 3-1: Set SEL for device-initiated U2 failed. Jan 11 13:59:18 sg-laptop kernel: usbcore: registered new interface driver usb-storage Jan 11 13:59:40 sg-laptop kernel: usb 3-1: reset SuperSpeed USB device number 2 using xhci_hcd Jan 11 13:59:41 sg-laptop kernel: usb 3-1: device descriptor read/8, error -71 Jan 11 13:59:41 sg-laptop kernel: usb 3-1: reset SuperSpeed USB device number 2 using xhci_hcd Jan 11 13:59:46 sg-laptop kernel: usb 3-1: device descriptor read/8, error -110 Jan 11 13:59:46 sg-laptop kernel: scsi 6:0:0:0: Device offlined - not ready after error recovery Jan 11 13:59:46 sg-laptop kernel: usb 3-1: USB disconnect, device number 2 lspci for the affected host: 04:00.0 0c03: 1b73:1000 (rev 04) (prog-if 30 [XHCI]) Subsystem: 1043:1039 Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx- Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- SERR- Reported-by: Sergey Galanov Cc: stable@vger.kernel.org diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 199aaea..2518c32 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1032,7 +1032,6 @@ static int register_root_hub(struct usb_hcd *hcd) dev_name(&usb_dev->dev), retval); return retval; } - usb_dev->lpm_capable = usb_device_supports_lpm(usb_dev); } retval = usb_new_device (usb_dev); diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index babba88..64ea219 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -128,7 +128,7 @@ struct usb_hub *usb_hub_to_struct_hub(struct usb_device *hdev) return usb_get_intfdata(hdev->actconfig->interface[0]); } -int usb_device_supports_lpm(struct usb_device *udev) +static int usb_device_supports_lpm(struct usb_device *udev) { /* USB 2.1 (and greater) devices indicate LPM support through * their USB 2.0 Extended Capabilities BOS descriptor. @@ -149,11 +149,6 @@ int usb_device_supports_lpm(struct usb_device *udev) "Power management will be impacted.\n"); return 0; } - - /* udev is root hub */ - if (!udev->parent) - return 1; - if (udev->parent->lpm_capable) return 1; diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index c493836..8238577 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -35,7 +35,6 @@ extern int usb_get_device_descriptor(struct usb_device *dev, unsigned int size); extern int usb_get_bos_descriptor(struct usb_device *dev); extern void usb_release_bos_descriptor(struct usb_device *dev); -extern int usb_device_supports_lpm(struct usb_device *udev); extern char *usb_cache_string(struct usb_device *udev, int index); extern int usb_set_configuration(struct usb_device *dev, int configuration); extern int usb_choose_configuration(struct usb_device *udev); -- cgit v0.10.2 From 1b5e1c6e6e728774ba7a1e8286d4833e4a16e918 Mon Sep 17 00:00:00 2001 From: Matthias Brugger Date: Fri, 17 Jan 2014 18:02:38 +0100 Subject: power: ds2782_battery: Typo in comment Change missleading comment to actual shift value provided by the chip. Signed-off-by: Matthias Brugger diff --git a/drivers/power/ds2782_battery.c b/drivers/power/ds2782_battery.c index 5631748..041f9b6 100644 --- a/drivers/power/ds2782_battery.c +++ b/drivers/power/ds2782_battery.c @@ -192,7 +192,7 @@ static int ds2786_get_voltage(struct ds278x_info *info, int *voltage_uV) /* * Voltage is measured in units of 1.22mV. The voltage is stored as - * a 10-bit number plus sign, in the upper bits of a 16-bit register + * a 12-bit number plus sign, in the upper bits of a 16-bit register */ err = ds278x_read_reg16(info, DS278x_REG_VOLT_MSB, &raw); if (err) -- cgit v0.10.2 From 4fa99230eade164137d94178b12e1e5f1c3d2bdd Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 7 Jan 2014 21:12:29 +0800 Subject: isp1704_charger: remove useless check in isp1704_charger_probe() Neither devm_usb_get_phy_by_phandle() nor devm_usb_get_phy() can return a NULL result, so remove the useless !isp->phy check. Signed-off-by: Wei Yongjun diff --git a/drivers/power/isp1704_charger.c b/drivers/power/isp1704_charger.c index 80edb7d..0b4cf9d 100644 --- a/drivers/power/isp1704_charger.c +++ b/drivers/power/isp1704_charger.c @@ -444,8 +444,6 @@ static int isp1704_charger_probe(struct platform_device *pdev) ret = PTR_ERR(isp->phy); goto fail0; } - if (!isp->phy) - goto fail0; isp->dev = &pdev->dev; platform_set_drvdata(pdev, isp); -- cgit v0.10.2 From 4f8dd2c10bec8a6c1928c3ce00ac68dba5a5d667 Mon Sep 17 00:00:00 2001 From: Sebastian Reichel Date: Sat, 11 Jan 2014 01:47:48 +0100 Subject: dt: binding documentation for bq2415x charger Add devicetree binding documentation for bq2415x charger. Signed-off-by: Sebastian Reichel Acked-by: Pavel Machek diff --git a/Documentation/devicetree/bindings/power/bq2415x.txt b/Documentation/devicetree/bindings/power/bq2415x.txt new file mode 100644 index 0000000..d0327f0 --- /dev/null +++ b/Documentation/devicetree/bindings/power/bq2415x.txt @@ -0,0 +1,47 @@ +Binding for TI bq2415x Li-Ion Charger + +Required properties: +- compatible: Should contain one of the following: + * "ti,bq24150" + * "ti,bq24150" + * "ti,bq24150a" + * "ti,bq24151" + * "ti,bq24151a" + * "ti,bq24152" + * "ti,bq24153" + * "ti,bq24153a" + * "ti,bq24155" + * "ti,bq24156" + * "ti,bq24156a" + * "ti,bq24158" +- reg: integer, i2c address of the device. +- ti,current-limit: integer, initial maximum current charger can pull + from power supply in mA. +- ti,weak-battery-voltage: integer, weak battery voltage threshold in mV. + The chip will use slow precharge if battery voltage + is below this value. +- ti,battery-regulation-voltage: integer, maximum charging voltage in mV. +- ti,charge-current: integer, maximum charging current in mA. +- ti,termination-current: integer, charge will be terminated when current in + constant-voltage phase drops below this value (in mA). +- ti,resistor-sense: integer, value of sensing resistor in milliohm. + +Optional properties: +- ti,usb-charger-detection: phandle to usb charger detection device. + (required for auto mode) + +Example from Nokia N900: + +bq24150a { + compatible = "ti,bq24150a"; + reg = <0x6b>; + + ti,current-limit = <100>; + ti,weak-battery-voltage = <3400>; + ti,battery-regulation-voltage = <4200>; + ti,charge-current = <650>; + ti,termination-current = <100>; + ti,resistor-sense = <68>; + + ti,usb-charger-detection = <&isp1704>; +}; -- cgit v0.10.2 From 6e5f52674ff0756e61a8879f6232b9ac33735cba Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Sat, 25 Jan 2014 22:36:13 +0200 Subject: spi: spi.h: clarify the documentation of transfer_one Explicitly note the transfer_one and transfer_one_message are mutually exclusive, to make the text a little more newcomers friendly. Signed-off-by: Baruch Siach Signed-off-by: Mark Brown diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index a1d4ca2..ad050f0 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -287,7 +287,10 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv) * - return 1 if the transfer is still in progress. When * the driver is finished with this transfer it must * call spi_finalize_current_transfer() so the subsystem - * can issue the next transfer + * can issue the next transfer. Note: transfer_one and + * transfer_one_message are mutually exclusive; when both + * are set, the generic subsystem does not call your + * transfer_one callback. * @unprepare_message: undo any work done by prepare_message(). * @cs_gpios: Array of GPIOs to use as chip select lines; one per CS * number. Any individual value may be -ENOENT for CS lines that -- cgit v0.10.2 From 18cc0adb132b390d026c574deec29bf182aede51 Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Sat, 25 Jan 2014 22:36:14 +0200 Subject: spi: document the transfer_one spi_master callback Signed-off-by: Baruch Siach Signed-off-by: Mark Brown diff --git a/Documentation/spi/spi-summary b/Documentation/spi/spi-summary index f72e0d1..dcaad47 100644 --- a/Documentation/spi/spi-summary +++ b/Documentation/spi/spi-summary @@ -545,6 +545,21 @@ SPI MASTER METHODS spi_finalize_current_message() so the subsystem can issue the next transfer. This may sleep. + master->transfer_one(struct spi_master *master, struct spi_device *spi, + struct spi_transfer *transfer) + The subsystem calls the driver to transfer a single transfer while + queuing transfers that arrive in the meantime. When the driver is + finished with this transfer, it must call + spi_finalize_current_transfer() so the subsystem can issue the next + transfer. This may sleep. Note: transfer_one and transfer_one_message + are mutually exclusive; when both are set, the generic subsystem does + not call your transfer_one callback. + + Return values: + negative errno: error + 0: transfer is finished + 1: transfer is still in progress + DEPRECATED METHODS master->transfer(struct spi_device *spi, struct spi_message *message) -- cgit v0.10.2 From e9305331f64ab9e5210baa4307355635c5e849f4 Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Sat, 25 Jan 2014 22:36:15 +0200 Subject: spi: correct the transfer_one_message documentation wording The transfer_one_message callback handles messages, not transfers. Signed-off-by: Baruch Siach Signed-off-by: Mark Brown diff --git a/Documentation/spi/spi-summary b/Documentation/spi/spi-summary index dcaad47..7982bcc 100644 --- a/Documentation/spi/spi-summary +++ b/Documentation/spi/spi-summary @@ -543,7 +543,7 @@ SPI MASTER METHODS queuing transfers that arrive in the meantime. When the driver is finished with this message, it must call spi_finalize_current_message() so the subsystem can issue the next - transfer. This may sleep. + message. This may sleep. master->transfer_one(struct spi_master *master, struct spi_device *spi, struct spi_transfer *transfer) diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index ad050f0..4203c66 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -273,7 +273,7 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv) * message while queuing transfers that arrive in the meantime. When the * driver is finished with this message, it must call * spi_finalize_current_message() so the subsystem can issue the next - * transfer + * message * @unprepare_transfer_hardware: there are currently no more messages on the * queue so the subsystem notifies the driver that it may relax the * hardware by issuing this call -- cgit v0.10.2 From 1f802f8249a0da536877842c43c7204064c4de8b Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 28 Jan 2014 10:33:03 +0100 Subject: spi: Fix crash with double message finalisation on error handling This reverts commit e120cc0dcf2880a4c5c0a6cb27b655600a1cfa1d. It causes a NULL pointer dereference with drivers using the generic spi_transfer_one_message(), which always calls spi_finalize_current_message(), which zeroes master->cur_msg. Drivers implementing transfer_one_message() theirselves must always call spi_finalize_current_message(), even if the transfer failed: * @transfer_one_message: the subsystem calls the driver to transfer a single * message while queuing transfers that arrive in the meantime. When the * driver is finished with this message, it must call * spi_finalize_current_message() so the subsystem can issue the next * transfer Signed-off-by: Geert Uytterhoeven Signed-off-by: Mark Brown diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 63613a9..26f4afd 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -745,9 +745,7 @@ static void spi_pump_messages(struct kthread_work *work) ret = master->transfer_one_message(master, master->cur_msg); if (ret) { dev_err(&master->dev, - "failed to transfer one message from queue: %d\n", ret); - master->cur_msg->status = ret; - spi_finalize_current_message(master); + "failed to transfer one message from queue\n"); return; } } -- cgit v0.10.2 From dbb0dd021dc282fe65c4f66c86821419850c43cc Mon Sep 17 00:00:00 2001 From: Jose Alonso Date: Sun, 26 Jan 2014 08:54:18 -0200 Subject: s390/qdio: for_each macro correctness I observed that there are for_each macros that do an extra memory access beyond the defined area. Normally this does not cause problems. But, this can cause exceptions. For example: if the area is allocated at the end of a page and the next page is not accessible. For correctness, I suggest changing the arguments of the 'for loop' like others 'for_each' do in the kernel. Signed-off-by: Jose Alonso Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h index 8acaae1..a563e4c 100644 --- a/drivers/s390/cio/qdio.h +++ b/drivers/s390/cio/qdio.h @@ -359,14 +359,12 @@ static inline int multicast_outbound(struct qdio_q *q) #define need_siga_sync_out_after_pci(q) \ (unlikely(q->irq_ptr->siga_flag.sync_out_after_pci)) -#define for_each_input_queue(irq_ptr, q, i) \ - for (i = 0, q = irq_ptr->input_qs[0]; \ - i < irq_ptr->nr_input_qs; \ - q = irq_ptr->input_qs[++i]) -#define for_each_output_queue(irq_ptr, q, i) \ - for (i = 0, q = irq_ptr->output_qs[0]; \ - i < irq_ptr->nr_output_qs; \ - q = irq_ptr->output_qs[++i]) +#define for_each_input_queue(irq_ptr, q, i) \ + for (i = 0; i < irq_ptr->nr_input_qs && \ + ({ q = irq_ptr->input_qs[i]; 1; }); i++) +#define for_each_output_queue(irq_ptr, q, i) \ + for (i = 0; i < irq_ptr->nr_output_qs && \ + ({ q = irq_ptr->output_qs[i]; 1; }); i++) #define prev_buf(bufnr) \ ((bufnr + QDIO_MAX_BUFFERS_MASK) & QDIO_MAX_BUFFERS_MASK) -- cgit v0.10.2 From 0f308f4f9e3ddd85869bb128e37f8dd08f3f513c Mon Sep 17 00:00:00 2001 From: Ursula Braun Date: Tue, 28 Jan 2014 13:06:47 +0100 Subject: s390/qdio: correct program-controlled interruption checking Get rid of compile warning in qdio_int_handler_pci() when checking for program-controlled interruption on outbound queues. Signed-off-by: Ursula Braun Reviewed-by: Heiko Carstens Signed-off-by: Martin Schwidefsky diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index c883a08..77466c4 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c @@ -996,7 +996,7 @@ static void qdio_int_handler_pci(struct qdio_irq *irq_ptr) } } - if (!pci_out_supported(q)) + if (!(irq_ptr->qib.ac & QIB_AC_OUTBOUND_PCI_SUPPORTED)) return; for_each_output_queue(irq_ptr, q, i) { -- cgit v0.10.2 From b7c5b1aa2836c933ab03f90391619ebdc9112e46 Mon Sep 17 00:00:00 2001 From: Gerald Schaefer Date: Tue, 28 Jan 2014 18:40:12 +0100 Subject: s390/appldata: restore missing init_virt_timer() Commit 27f6b416 "s390/vtimer: rework virtual timer interface" removed the call to init_virt_timer() by mistake, which is added again by this patch. Signed-off-by: Gerald Schaefer Signed-off-by: Martin Schwidefsky diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c index 4c4a1ce..47c8630 100644 --- a/arch/s390/appldata/appldata_base.c +++ b/arch/s390/appldata/appldata_base.c @@ -529,6 +529,7 @@ static int __init appldata_init(void) { int rc; + init_virt_timer(&appldata_timer); appldata_timer.function = appldata_timer_function; appldata_timer.data = (unsigned long) &appldata_work; -- cgit v0.10.2 From 0e4b949e6620689b1d3142e20bca2c9d1f918fda Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 14 Jan 2014 11:44:09 +0100 Subject: can: flexcan: fix flexcan driver build for big endian on ARM and little endian on PowerPc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is no reason to disallow building the driver on big-endian ARM kernels. Furthermore, the current behavior is actually broken on little-endian PowerPC as well. The choice of register accessor functions must purely depend on the CPU architecture, not which endianess the CPU is running on. Note that we nowadays allow both big-endian ARM and little-endian PowerPC kernels. With this patch applied, we will do the right thing in all four combinations. Signed-off-by: Arnd Bergmann Cc: Guenter Roeck Cc: Lothar Waßmann Signed-off-by: Marc Kleine-Budde diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig index d447b88..9e7d95d 100644 --- a/drivers/net/can/Kconfig +++ b/drivers/net/can/Kconfig @@ -104,7 +104,7 @@ config CAN_JANZ_ICAN3 config CAN_FLEXCAN tristate "Support for Freescale FLEXCAN based chips" - depends on (ARM && CPU_LITTLE_ENDIAN) || PPC + depends on ARM || PPC ---help--- Say Y here if you want to support for Freescale FlexCAN. diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index aaed97b..320bef2 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -235,9 +235,12 @@ static const struct can_bittiming_const flexcan_bittiming_const = { }; /* - * Abstract off the read/write for arm versus ppc. + * Abstract off the read/write for arm versus ppc. This + * assumes that PPC uses big-endian registers and everything + * else uses little-endian registers, independent of CPU + * endianess. */ -#if defined(__BIG_ENDIAN) +#if defined(CONFIG_PPC) static inline u32 flexcan_read(void __iomem *addr) { return in_be32(addr); -- cgit v0.10.2 From bb5ecb0c63ac88b6f39029f75c47f4be4e352e8d Mon Sep 17 00:00:00 2001 From: Rostislav Lisovy Date: Fri, 24 Jan 2014 13:17:37 +0100 Subject: can: Propagate SO_PRIORITY of raw sockets to skbs This allows controlling certain queueing disciplines by setting the socket's SO_PRIORITY option. For example, with the default pfifo_fast queueing discipline, which provides three priorities, socket priority TC_PRIO_CONTROL means higher than default and TC_PRIO_BULK means lower than default. Signed-off-by: Rostislav Lisovy Signed-off-by: Michal Sojka Acked-by: Oliver Hartkopp Signed-off-by: Marc Kleine-Budde diff --git a/net/can/raw.c b/net/can/raw.c index 07d72d8..8be757c 100644 --- a/net/can/raw.c +++ b/net/can/raw.c @@ -715,6 +715,7 @@ static int raw_sendmsg(struct kiocb *iocb, struct socket *sock, skb->dev = dev; skb->sk = sk; + skb->priority = sk->sk_priority; err = can_send(skb, ro->loopback); -- cgit v0.10.2 From 73615c8669ef1c497c942cae0d5079b95824332a Mon Sep 17 00:00:00 2001 From: "Ira W. Snyder" Date: Wed, 29 Jan 2014 09:58:25 -0800 Subject: can: janz-ican3: fix uninitialized variable warnings Analysis of the code shows that the struct ican3_msg variable cannot be used uninitialized. Error conditions are checked and the loop terminates before calling the ican3_handle_message() function with an uninitialized value. Signed-off-by: Ira W. Snyder Acked-by: Oliver Hartkopp Signed-off-by: Marc Kleine-Budde diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c index e24e669..07f0ba0 100644 --- a/drivers/net/can/janz-ican3.c +++ b/drivers/net/can/janz-ican3.c @@ -1322,7 +1322,7 @@ static int ican3_napi(struct napi_struct *napi, int budget) /* process all communication messages */ while (true) { - struct ican3_msg msg; + struct ican3_msg uninitialized_var(msg); ret = ican3_recv_msg(mod, &msg); if (ret) break; -- cgit v0.10.2 From 947174476701fbc84ea8c7ec9664270f9d80b076 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Tue, 28 Jan 2014 16:57:39 -0800 Subject: bcache: fix BUG_ON due to integer overflow with GC_SECTORS_USED The BUG_ON at the end of __bch_btree_mark_key can be triggered due to an integer overflow error: BITMASK(GC_SECTORS_USED, struct bucket, gc_mark, 2, 13); ... SET_GC_SECTORS_USED(g, min_t(unsigned, GC_SECTORS_USED(g) + KEY_SIZE(k), (1 << 14) - 1)); BUG_ON(!GC_SECTORS_USED(g)); In bcache.h, the SECTORS_USED bitfield is defined to be 13 bits wide. While the SET_ code tries to ensure that the field doesn't overflow by clamping it to (1<<14)-1 == 16383, this is incorrect because 16383 requires 14 bits. Therefore, if GC_SECTORS_USED() + KEY_SIZE() = 8192, the SET_ statement tries to store 8192 into a 13-bit field. In a 13-bit field, 8192 becomes zero, thus triggering the BUG_ON. Therefore, create a field width constant and a max value constant, and use those to create the bitfield and check the inputs to SET_GC_SECTORS_USED. Arguably the BITMASK() template ought to have BUG_ON checks for too-large values, but that's a separate patch. Signed-off-by: Darrick J. Wong diff --git a/drivers/md/bcache/bcache.h b/drivers/md/bcache/bcache.h index 0c707e4..a4c7306 100644 --- a/drivers/md/bcache/bcache.h +++ b/drivers/md/bcache/bcache.h @@ -210,7 +210,9 @@ BITMASK(GC_MARK, struct bucket, gc_mark, 0, 2); #define GC_MARK_RECLAIMABLE 0 #define GC_MARK_DIRTY 1 #define GC_MARK_METADATA 2 -BITMASK(GC_SECTORS_USED, struct bucket, gc_mark, 2, 13); +#define GC_SECTORS_USED_SIZE 13 +#define MAX_GC_SECTORS_USED (~(~0ULL << GC_SECTORS_USED_SIZE)) +BITMASK(GC_SECTORS_USED, struct bucket, gc_mark, 2, GC_SECTORS_USED_SIZE); BITMASK(GC_MOVE, struct bucket, gc_mark, 15, 1); #include "journal.h" diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c index 98cc0a8..7d42118 100644 --- a/drivers/md/bcache/btree.c +++ b/drivers/md/bcache/btree.c @@ -1167,7 +1167,7 @@ uint8_t __bch_btree_mark_key(struct cache_set *c, int level, struct bkey *k) /* guard against overflow */ SET_GC_SECTORS_USED(g, min_t(unsigned, GC_SECTORS_USED(g) + KEY_SIZE(k), - (1 << 14) - 1)); + MAX_GC_SECTORS_USED)); BUG_ON(!GC_SECTORS_USED(g)); } -- cgit v0.10.2 From 3572324af0f4ef877545e5a17bd3e788551f166a Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Fri, 10 Jan 2014 18:53:02 -0800 Subject: bcache: Minor fixes from kbuild robot Signed-off-by: Kent Overstreet diff --git a/drivers/md/bcache/bset.c b/drivers/md/bcache/bset.c index 4f6b594..3f74b4b 100644 --- a/drivers/md/bcache/bset.c +++ b/drivers/md/bcache/bset.c @@ -23,7 +23,7 @@ void bch_dump_bset(struct btree_keys *b, struct bset *i, unsigned set) for (k = i->start; k < bset_bkey_last(i); k = next) { next = bkey_next(k); - printk(KERN_ERR "block %u key %zi/%u: ", set, + printk(KERN_ERR "block %u key %li/%u: ", set, (uint64_t *) k - i->d, i->keys); if (b->ops->key_dump) @@ -1185,9 +1185,12 @@ static void __btree_sort(struct btree_keys *b, struct btree_iter *iter, struct bset *out = (void *) __get_free_pages(__GFP_NOWARN|GFP_NOIO, order); if (!out) { + struct page *outp; + BUG_ON(order > state->page_order); - out = page_address(mempool_alloc(state->pool, GFP_NOIO)); + outp = mempool_alloc(state->pool, GFP_NOIO); + out = page_address(outp); used_mempool = true; order = state->page_order; } diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c index 7d42118..5f9c2a6 100644 --- a/drivers/md/bcache/btree.c +++ b/drivers/md/bcache/btree.c @@ -1805,7 +1805,7 @@ static bool btree_insert_key(struct btree *b, struct bkey *k, static size_t insert_u64s_remaining(struct btree *b) { - ssize_t ret = bch_btree_keys_u64s_remaining(&b->keys); + long ret = bch_btree_keys_u64s_remaining(&b->keys); /* * Might land in the middle of an existing extent and have to split it diff --git a/drivers/md/bcache/extents.c b/drivers/md/bcache/extents.c index c3ead58..416d1a3 100644 --- a/drivers/md/bcache/extents.c +++ b/drivers/md/bcache/extents.c @@ -194,7 +194,7 @@ err: mutex_unlock(&b->c->bucket_lock); bch_extent_to_text(buf, sizeof(buf), k); btree_bug(b, -"inconsistent btree pointer %s: bucket %li pin %i prio %i gen %i last_gc %i mark %llu gc_gen %i", +"inconsistent btree pointer %s: bucket %zi pin %i prio %i gen %i last_gc %i mark %llu gc_gen %i", buf, PTR_BUCKET_NR(b->c, k, i), atomic_read(&g->pin), g->prio, g->gen, g->last_gc, GC_MARK(g), g->gc_gen); return true; diff --git a/drivers/md/bcache/sysfs.c b/drivers/md/bcache/sysfs.c index c6ab693..d8458d4 100644 --- a/drivers/md/bcache/sysfs.c +++ b/drivers/md/bcache/sysfs.c @@ -416,7 +416,7 @@ static int btree_bset_stats(struct btree_op *b_op, struct btree *b) return MAP_CONTINUE; } -int bch_bset_print_stats(struct cache_set *c, char *buf) +static int bch_bset_print_stats(struct cache_set *c, char *buf) { struct bset_stats_op op; int ret; -- cgit v0.10.2 From e3b4825b85eab879b618af6ea18529ca7ab9a64f Mon Sep 17 00:00:00 2001 From: Nicholas Swenson Date: Thu, 12 Dec 2013 12:53:28 -0800 Subject: bcache: bugfix - gc thread now gets woken when cache is full Signed-off-by: Nicholas Swenson diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c index fcdb59f..675229b 100644 --- a/drivers/md/bcache/request.c +++ b/drivers/md/bcache/request.c @@ -354,14 +354,14 @@ static void bch_data_insert_start(struct closure *cl) struct data_insert_op *op = container_of(cl, struct data_insert_op, cl); struct bio *bio = op->bio, *n; - if (op->bypass) - return bch_data_invalidate(cl); - if (atomic_sub_return(bio_sectors(bio), &op->c->sectors_to_gc) < 0) { set_gc_sectors(op->c); wake_up_gc(op->c); } + if (op->bypass) + return bch_data_invalidate(cl); + /* * Journal writes are marked REQ_FLUSH; if the original write was a * flush, it'll wait on the journal write. -- cgit v0.10.2 From 477632dff5c7deaa165701f441e9a4bd33e22b18 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Wed, 29 Jan 2014 14:02:00 -0800 Subject: Revert "xhci: replace xhci_write_64() with writeq()" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 7dd09a1af2c7150269350aaa567a11b06e831003. Many xHCI host controllers can only handle 32-bit addresses, and writing 64-bits at a time causes them to fail. Rafał reports that USB devices simply do not enumerate, and reverting this patch helps. Branimir reports that his host controller doesn't respond to an Enable Slot command and dies: [ 75.576160] xhci_hcd 0000:03:00.0: Timeout while waiting for a slot [ 88.991634] xhci_hcd 0000:03:00.0: Stopped the command ring failed, maybe the host is dead [ 88.991748] xhci_hcd 0000:03:00.0: Abort command ring failed [ 88.991845] xhci_hcd 0000:03:00.0: HC died; cleaning up [ 93.985489] xhci_hcd 0000:03:00.0: Timeout while waiting for a slot [ 93.985494] xhci_hcd 0000:03:00.0: Abort the command ring, but the xHCI is dead. [ 98.982586] xhci_hcd 0000:03:00.0: Timeout while waiting for a slot [ 98.982591] xhci_hcd 0000:03:00.0: Abort the command ring, but the xHCI is dead. [ 103.979696] xhci_hcd 0000:03:00.0: Timeout while waiting for a slot [ 103.979702] xhci_hcd 0000:03:00.0: Abort the command ring, but the xHCI is dead Signed-off-by: Sarah Sharp Reported-by: Rafał Miłecki Reported-by: Branimir Maksimovic Cc: Xenia Ragiadakou diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 873c272..4b87026 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1967,7 +1967,7 @@ static void xhci_set_hc_event_deq(struct xhci_hcd *xhci) xhci_dbg_trace(xhci, trace_xhci_dbg_init, "// Write event ring dequeue pointer, " "preserving EHB bit"); - writeq(((u64) deq & (u64) ~ERST_PTR_MASK) | temp, + xhci_write_64(xhci, ((u64) deq & (u64) ~ERST_PTR_MASK) | temp, &xhci->ir_set->erst_dequeue); } @@ -2269,7 +2269,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) xhci_dbg_trace(xhci, trace_xhci_dbg_init, "// Device context base array address = 0x%llx (DMA), %p (virt)", (unsigned long long)xhci->dcbaa->dma, xhci->dcbaa); - writeq(dma, &xhci->op_regs->dcbaa_ptr); + xhci_write_64(xhci, dma, &xhci->op_regs->dcbaa_ptr); /* * Initialize the ring segment pool. The ring must be a contiguous @@ -2318,7 +2318,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) xhci->cmd_ring->cycle_state; xhci_dbg_trace(xhci, trace_xhci_dbg_init, "// Setting command ring address to 0x%x", val); - writeq(val_64, &xhci->op_regs->cmd_ring); + xhci_write_64(xhci, val_64, &xhci->op_regs->cmd_ring); xhci_dbg_cmd_ptrs(xhci); xhci->lpm_command = xhci_alloc_command(xhci, true, true, flags); @@ -2399,7 +2399,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) val_64 = readq(&xhci->ir_set->erst_base); val_64 &= ERST_PTR_MASK; val_64 |= (xhci->erst.erst_dma_addr & (u64) ~ERST_PTR_MASK); - writeq(val_64, &xhci->ir_set->erst_base); + xhci_write_64(xhci, val_64, &xhci->ir_set->erst_base); /* Set the event ring dequeue address */ xhci_set_hc_event_deq(xhci); diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index a0b248c..e19fae9 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -313,7 +313,8 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci) return 0; } xhci->cmd_ring_state = CMD_RING_STATE_ABORTED; - writeq(temp_64 | CMD_RING_ABORT, &xhci->op_regs->cmd_ring); + xhci_write_64(xhci, temp_64 | CMD_RING_ABORT, + &xhci->op_regs->cmd_ring); /* Section 4.6.1.2 of xHCI 1.0 spec says software should * time the completion od all xHCI commands, including @@ -2865,7 +2866,8 @@ hw_died: * the event ring should be empty. */ temp_64 = readq(&xhci->ir_set->erst_dequeue); - writeq(temp_64 | ERST_EHB, &xhci->ir_set->erst_dequeue); + xhci_write_64(xhci, temp_64 | ERST_EHB, + &xhci->ir_set->erst_dequeue); spin_unlock(&xhci->lock); return IRQ_HANDLED; @@ -2892,7 +2894,7 @@ hw_died: /* Clear the event handler busy flag (RW1C); event ring is empty. */ temp_64 |= ERST_EHB; - writeq(temp_64, &xhci->ir_set->erst_dequeue); + xhci_write_64(xhci, temp_64, &xhci->ir_set->erst_dequeue); spin_unlock(&xhci->lock); diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index ad36439..ebbe52c 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -769,11 +769,11 @@ static void xhci_restore_registers(struct xhci_hcd *xhci) { writel(xhci->s3.command, &xhci->op_regs->command); writel(xhci->s3.dev_nt, &xhci->op_regs->dev_notification); - writeq(xhci->s3.dcbaa_ptr, &xhci->op_regs->dcbaa_ptr); + xhci_write_64(xhci, xhci->s3.dcbaa_ptr, &xhci->op_regs->dcbaa_ptr); writel(xhci->s3.config_reg, &xhci->op_regs->config_reg); writel(xhci->s3.erst_size, &xhci->ir_set->erst_size); - writeq(xhci->s3.erst_base, &xhci->ir_set->erst_base); - writeq(xhci->s3.erst_dequeue, &xhci->ir_set->erst_dequeue); + xhci_write_64(xhci, xhci->s3.erst_base, &xhci->ir_set->erst_base); + xhci_write_64(xhci, xhci->s3.erst_dequeue, &xhci->ir_set->erst_dequeue); writel(xhci->s3.irq_pending, &xhci->ir_set->irq_pending); writel(xhci->s3.irq_control, &xhci->ir_set->irq_control); } @@ -792,7 +792,7 @@ static void xhci_set_cmd_ring_deq(struct xhci_hcd *xhci) xhci_dbg_trace(xhci, trace_xhci_dbg_init, "// Setting command ring address to 0x%llx", (long unsigned long) val_64); - writeq(val_64, &xhci->op_regs->cmd_ring); + xhci_write_64(xhci, val_64, &xhci->op_regs->cmd_ring); } /* diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index f8416639..60def15 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -28,15 +28,6 @@ #include #include -/* - * Registers should always be accessed with double word or quad word accesses. - * - * Some xHCI implementations may support 64-bit address pointers. Registers - * with 64-bit address pointers should be written to with dword accesses by - * writing the low dword first (ptr[0]), then the high dword (ptr[1]) second. - * xHCI implementations that do not support 64-bit address pointers will ignore - * the high dword, and write order is irrelevant. - */ #include /* Code sharing between pci-quirks and xhci hcd */ @@ -1614,6 +1605,26 @@ static inline struct usb_hcd *xhci_to_hcd(struct xhci_hcd *xhci) #define xhci_warn_ratelimited(xhci, fmt, args...) \ dev_warn_ratelimited(xhci_to_hcd(xhci)->self.controller , fmt , ## args) +/* + * Registers should always be accessed with double word or quad word accesses. + * + * Some xHCI implementations may support 64-bit address pointers. Registers + * with 64-bit address pointers should be written to with dword accesses by + * writing the low dword first (ptr[0]), then the high dword (ptr[1]) second. + * xHCI implementations that do not support 64-bit address pointers will ignore + * the high dword, and write order is irrelevant. + */ +static inline void xhci_write_64(struct xhci_hcd *xhci, + const u64 val, __le64 __iomem *regs) +{ + __u32 __iomem *ptr = (__u32 __iomem *) regs; + u32 val_lo = lower_32_bits(val); + u32 val_hi = upper_32_bits(val); + + writel(val_lo, ptr); + writel(val_hi, ptr + 1); +} + static inline int xhci_link_trb_quirk(struct xhci_hcd *xhci) { return xhci->quirks & XHCI_LINK_TRB_QUIRK; -- cgit v0.10.2 From aac5c4226e7136c331ed384c25d5560204da10a0 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 29 Jan 2014 16:16:39 +0300 Subject: KVM: return an error code in kvm_vm_ioctl_register_coalesced_mmio() If kvm_io_bus_register_dev() fails then it returns success but it should return an error code. I also did a little cleanup like removing an impossible NULL test. Cc: stable@vger.kernel.org Fixes: 2b3c246a682c ('KVM: Make coalesced mmio use a device per zone') Signed-off-by: Dan Carpenter Signed-off-by: Paolo Bonzini diff --git a/virt/kvm/coalesced_mmio.c b/virt/kvm/coalesced_mmio.c index 88b2fe3..00d8642 100644 --- a/virt/kvm/coalesced_mmio.c +++ b/virt/kvm/coalesced_mmio.c @@ -154,17 +154,13 @@ int kvm_vm_ioctl_register_coalesced_mmio(struct kvm *kvm, list_add_tail(&dev->list, &kvm->coalesced_zones); mutex_unlock(&kvm->slots_lock); - return ret; + return 0; out_free_dev: mutex_unlock(&kvm->slots_lock); - kfree(dev); - if (dev == NULL) - return -ENXIO; - - return 0; + return ret; } int kvm_vm_ioctl_unregister_coalesced_mmio(struct kvm *kvm, -- cgit v0.10.2 From 2cac613be8d4d661edd359cdab3c474286c4f5f0 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Thu, 30 Jan 2014 16:50:42 +0200 Subject: drm/i915: vlv: fix DP PHY lockup due to invalid PP sequencer setup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Atm we setup the HW panel power sequencer logic both for eDP and DP ports. On eDP we then go on and start the power on sequence and commence with link training when it's ready. On DP we don't do the power on sequencing but do the link training immediately. At this point the DP PHY block gets stuck, since - supposedly - it is waiting for the power on sequence to finish. The actual register write that seems to hold off the PHY is PIPEX_PP_ON_DELAYS[Panel Control Port Select]. Writing here a non-0 value eventually sets PIPEX_PP_STATUS[Require Asset Status] to 1 and blocks the PHY until the panel power on is ready. Fix this by not doing any PP sequencing setup for DP ports. Thanks to Ville Syrjälä, Jesse Barnes and Todd Previte for the help in tracking this down. Note that on older gmch platforms (where we have lvds instead of edp) we've hacked around this by writing the magic ABCD unlock key to PP registers, which disables the hw sanity checks. For edp all platforms thus far had the pch split, with the edp port in the north display complex and the PP registers on the pch the hw sanity checks (expressed through the "Require Asset Status" bit) was never functional, hence never a real issue. This regression has been introduce in commit bf13e81b904a37d94d83dd6c3b53a147719a3ead Author: Jani Nikula Date: Fri Sep 6 07:40:05 2013 +0300 drm/i915: add support for per-pipe power sequencing on vlv Signed-off-by: Imre Deak [danvet: Add note about the bigger story here.] Cc: stable@vger.kernel.org Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 5ede4e8..c00b6e3 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1869,10 +1869,12 @@ static void vlv_pre_enable_dp(struct intel_encoder *encoder) mutex_unlock(&dev_priv->dpio_lock); - /* init power sequencer on this pipe and port */ - intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq); - intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, - &power_seq); + if (is_edp(intel_dp)) { + /* init power sequencer on this pipe and port */ + intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq); + intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, + &power_seq); + } intel_enable_dp(encoder); -- cgit v0.10.2 From a4243402274343d8e596fb0b25674e52088a7488 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 20 Jan 2014 23:46:38 +0100 Subject: iwlwifi: mvm: make local pointer non-static The address pointer used in the function shouldn't be static since it's local data only. Having it static causes races if a single machine has two devices, as the pointer would be shared between instances. Signed-off-by: Johannes Berg Signed-off-by: Emmanuel Grumbach diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c index ec18121..3397f59 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/iwlwifi/mvm/sta.c @@ -652,7 +652,7 @@ int iwl_mvm_send_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif, { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); static const u8 _baddr[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - static const u8 *baddr = _baddr; + const u8 *baddr = _baddr; lockdep_assert_held(&mvm->mutex); -- cgit v0.10.2 From 0822afe8ebb9389997ef677447c7b08e08797de9 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 16 Jan 2014 09:18:07 +0100 Subject: iwlwifi: mvm: disable scheduled scan The iwlwifi scheduled scan implementation doesn't adhere to the userspace API correctly - the API assumes that any new incoming 'incompatible' request (like scan or remain-on-channel for this driver) will just cancel the scheduled scan. Instead our driver relies on userspace cancelling it, thus breaking existing wpa_s versions. Cc: stable@vger.kernel.org [3.13] Fixes: 35a000b7c1bb ("iwlwifi: mvm: support sched scan if supported by the fw") Signed-off-by: Johannes Berg Signed-off-by: Emmanuel Grumbach diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index c49b507..6bf9766 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -246,7 +246,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) else hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; - if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_SCHED_SCAN) { + if (0 && mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_SCHED_SCAN) { hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; hw->wiphy->max_sched_scan_ssids = PROBE_OPTION_MAX; hw->wiphy->max_match_sets = IWL_SCAN_MAX_PROFILES; -- cgit v0.10.2 From b900a87b2eb90c0b9586496c82a323a1b8832d73 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 23 Jan 2014 11:55:16 +0200 Subject: iwlwifi: mvm: print the version of the firmware when it asserts This can be useful to be able to spot the firmware version from the error reports without needing to fetch it from another place. Cc: [3.10+] Signed-off-by: Emmanuel Grumbach Reviewed-by: Johannes Berg Signed-off-by: Emmanuel Grumbach diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c index a4a5e25..86989df 100644 --- a/drivers/net/wireless/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/iwlwifi/mvm/utils.c @@ -411,6 +411,8 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm) mvm->status, table.valid); } + IWL_ERR(mvm, "Loaded firmware version: %s\n", mvm->fw->fw_version); + trace_iwlwifi_dev_ucode_error(trans->dev, table.error_id, table.tsf_low, table.data1, table.data2, table.data3, table.blink1, table.blink2, table.ilink1, -- cgit v0.10.2 From f7690915ccce98553c5425b51e6b5a6c51e27f4e Mon Sep 17 00:00:00 2001 From: Oren Givon Date: Thu, 23 Jan 2014 01:19:33 +0200 Subject: iwlwifi: add more 7265 HW IDs Add 6 new HW IDs for the 7265 series. Cc: [3.13] Signed-off-by: Oren Givon Signed-off-by: Emmanuel Grumbach diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c index 3040924..f47bcbe 100644 --- a/drivers/net/wireless/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/iwlwifi/pcie/drv.c @@ -359,20 +359,25 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { /* 7265 Series */ {IWL_PCI_DEVICE(0x095A, 0x5010, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x5110, iwl7265_2ac_cfg)}, + {IWL_PCI_DEVICE(0x095A, 0x5112, iwl7265_2ac_cfg)}, + {IWL_PCI_DEVICE(0x095A, 0x5100, iwl7265_2ac_cfg)}, + {IWL_PCI_DEVICE(0x095A, 0x510A, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095B, 0x5310, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095B, 0x5302, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095B, 0x5210, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x5012, iwl7265_2ac_cfg)}, - {IWL_PCI_DEVICE(0x095A, 0x500A, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x5410, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x5400, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x1010, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x5000, iwl7265_2n_cfg)}, + {IWL_PCI_DEVICE(0x095A, 0x500A, iwl7265_2n_cfg)}, {IWL_PCI_DEVICE(0x095B, 0x5200, iwl7265_2n_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x5002, iwl7265_n_cfg)}, {IWL_PCI_DEVICE(0x095B, 0x5202, iwl7265_n_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x9010, iwl7265_2ac_cfg)}, + {IWL_PCI_DEVICE(0x095A, 0x9012, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x9110, iwl7265_2ac_cfg)}, + {IWL_PCI_DEVICE(0x095A, 0x9112, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x9210, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x9510, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x9310, iwl7265_2ac_cfg)}, -- cgit v0.10.2 From 6e0bbe5ee845e185d237ec4f266b7be495c50eb6 Mon Sep 17 00:00:00 2001 From: David Spinadel Date: Mon, 30 Dec 2013 09:59:45 +0200 Subject: iwlwifi: mvm: notify match found without filtering Configure scheduled scan to notify match found on every beacon or probe response if the scan request doesn't contain valid ssid list for filtering. Without this configuration the FW passes all beacons to the host but doesn't notify the stack that the scan results are ready for processing. Signed-off-by: David Spinadel Reviewed-by: Alexander Bondar Reviewed-by: Johannes Berg Signed-off-by: Emmanuel Grumbach diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h index 73cbba7..9426905 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h @@ -504,6 +504,7 @@ struct iwl_scan_offload_profile { * @match_notify: clients waiting for match found notification * @pass_match: clients waiting for the results * @active_clients: active clients bitmap - enum scan_framework_client + * @any_beacon_notify: clients waiting for match notification without match */ struct iwl_scan_offload_profile_cfg { struct iwl_scan_offload_profile profiles[IWL_SCAN_MAX_PROFILES]; @@ -512,7 +513,8 @@ struct iwl_scan_offload_profile_cfg { u8 match_notify; u8 pass_match; u8 active_clients; - u8 reserved[3]; + u8 any_beacon_notify; + u8 reserved[2]; } __packed; /** diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index 0e00079..c35f35c 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c @@ -807,6 +807,8 @@ int iwl_mvm_config_sched_scan_profiles(struct iwl_mvm *mvm, profile_cfg->active_clients = SCAN_CLIENT_SCHED_SCAN; profile_cfg->pass_match = SCAN_CLIENT_SCHED_SCAN; profile_cfg->match_notify = SCAN_CLIENT_SCHED_SCAN; + if (!req->n_match_sets || !req->match_sets[0].ssid.ssid_len) + profile_cfg->any_beacon_notify = SCAN_CLIENT_SCHED_SCAN; for (i = 0; i < req->n_match_sets; i++) { profile = &profile_cfg->profiles[i]; -- cgit v0.10.2 From 9bb0c1adc52ca3c7026811a6630a3c78eec1f135 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Mon, 20 Jan 2014 15:21:26 +0200 Subject: iwlwifi: mvm: don't leak a station when we drain We had a bug that prevented us from removing a station after we entered the drain flow: We assign sta to be NULL if it was an error value. Then we tested it against -EBUSY, but forget to retrieve the value again from mvm->fw_id_to_mac_id[sta_id]. Due to this bug, we ended up never removing the STA from the firmware. This led to an firmware assert when we remove the GO vif. Reviewed-by: Johannes Berg Signed-off-by: Emmanuel Grumbach diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c index 90378c2..4df12fa 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/iwlwifi/mvm/tx.c @@ -659,8 +659,14 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, rcu_read_lock(); sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]); + /* + * sta can't be NULL otherwise it'd mean that the sta has been freed in + * the firmware while we still have packets for it in the Tx queues. + */ + if (WARN_ON_ONCE(!sta)) + goto out; - if (!IS_ERR_OR_NULL(sta)) { + if (!IS_ERR(sta)) { mvmsta = iwl_mvm_sta_from_mac80211(sta); if (tid != IWL_TID_NON_QOS) { @@ -675,7 +681,6 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, spin_unlock_bh(&mvmsta->lock); } } else { - sta = NULL; mvmsta = NULL; } @@ -683,42 +688,38 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, * If the txq is not an AMPDU queue, there is no chance we freed * several skbs. Check that out... */ - if (txq_id < mvm->first_agg_queue && !WARN_ON(skb_freed > 1) && - atomic_sub_and_test(skb_freed, &mvm->pending_frames[sta_id])) { - if (mvmsta) { - /* - * If there are no pending frames for this STA, notify - * mac80211 that this station can go to sleep in its - * STA table. - */ - if (mvmsta->vif->type == NL80211_IFTYPE_AP) - ieee80211_sta_block_awake(mvm->hw, sta, false); - /* - * We might very well have taken mvmsta pointer while - * the station was being removed. The remove flow might - * have seen a pending_frame (because we didn't take - * the lock) even if now the queues are drained. So make - * really sure now that this the station is not being - * removed. If it is, run the drain worker to remove it. - */ - spin_lock_bh(&mvmsta->lock); - sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]); - if (!sta || PTR_ERR(sta) == -EBUSY) { - /* - * Station disappeared in the meantime: - * so we are draining. - */ - set_bit(sta_id, mvm->sta_drained); - schedule_work(&mvm->sta_drained_wk); - } - spin_unlock_bh(&mvmsta->lock); - } else if (!mvmsta && PTR_ERR(sta) == -EBUSY) { - /* Tx response without STA, so we are draining */ - set_bit(sta_id, mvm->sta_drained); - schedule_work(&mvm->sta_drained_wk); - } + if (txq_id >= mvm->first_agg_queue) + goto out; + + /* We can't free more than one frame at once on a shared queue */ + WARN_ON(skb_freed > 1); + + /* If we have still frames from this STA nothing to do here */ + if (!atomic_sub_and_test(skb_freed, &mvm->pending_frames[sta_id])) + goto out; + + if (mvmsta && mvmsta->vif->type == NL80211_IFTYPE_AP) { + /* + * If there are no pending frames for this STA, notify + * mac80211 that this station can go to sleep in its + * STA table. + * If mvmsta is not NULL, sta is valid. + */ + ieee80211_sta_block_awake(mvm->hw, sta, false); + } + + if (PTR_ERR(sta) == -EBUSY || PTR_ERR(sta) == -ENOENT) { + /* + * We are draining and this was the last packet - pre_rcu_remove + * has been called already. We might be after the + * synchronize_net already. + * Don't rely on iwl_mvm_rm_sta to see the empty Tx queues. + */ + set_bit(sta_id, mvm->sta_drained); + schedule_work(&mvm->sta_drained_wk); } +out: rcu_read_unlock(); } -- cgit v0.10.2 From d835502f3dacad1638d516ab156d66f0ba377cf5 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Tue, 31 Dec 2013 11:38:27 +0800 Subject: percpu_ida: fix a live lock steal_tags only happens when free tags is more than half of the total tags. This is too strict and can cause live lock. I found that if one cpu has free tags, but other cpu can't steal (thread is bound to specific cpus), threads which want to allocate tags are always sleeping. I found this when I run next patch, but this could happen without it I think. I did performance test too with null_blk. Two cases (each cpu has enough percpu tags, or total tags are limited), no performance changes were observed. Signed-off-by: Shaohua Li Signed-off-by: Jens Axboe diff --git a/lib/percpu_ida.c b/lib/percpu_ida.c index 9d054bf..85f43b1 100644 --- a/lib/percpu_ida.c +++ b/lib/percpu_ida.c @@ -54,9 +54,7 @@ static inline void move_tags(unsigned *dst, unsigned *dst_nr, /* * Try to steal tags from a remote cpu's percpu freelist. * - * We first check how many percpu freelists have tags - we don't steal tags - * unless enough percpu freelists have tags on them that it's possible more than - * half the total tags could be stuck on remote percpu freelists. + * We first check how many percpu freelists have tags * * Then we iterate through the cpus until we find some tags - we don't attempt * to find the "best" cpu to steal from, to keep cacheline bouncing to a @@ -69,8 +67,7 @@ static inline void steal_tags(struct percpu_ida *pool, struct percpu_ida_cpu *remote; for (cpus_have_tags = cpumask_weight(&pool->cpus_have_tags); - cpus_have_tags * pool->percpu_max_size > pool->nr_tags / 2; - cpus_have_tags--) { + cpus_have_tags; cpus_have_tags--) { cpu = cpumask_next(cpu, &pool->cpus_have_tags); if (cpu >= nr_cpu_ids) { -- cgit v0.10.2 From f0276924fa35a3607920a58cf5d878212824b951 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Tue, 31 Dec 2013 11:38:50 +0800 Subject: blk-mq: Don't reserve a tag for flush request Reserving a tag (request) for flush to avoid dead lock is a overkill. A tag is valuable resource. We can track the number of flush requests and disallow having too many pending flush requests allocated. With this patch, blk_mq_alloc_request_pinned() could do a busy nop (but not a dead loop) if too many pending requests are allocated and new flush request is allocated. But this should not be a problem, too many pending flush requests are very rare case. I verified this can fix the deadlock caused by too many pending flush requests. Signed-off-by: Shaohua Li Signed-off-by: Jens Axboe diff --git a/block/blk-flush.c b/block/blk-flush.c index 9288aaf..9143e85 100644 --- a/block/blk-flush.c +++ b/block/blk-flush.c @@ -284,9 +284,8 @@ static void mq_flush_work(struct work_struct *work) q = container_of(work, struct request_queue, mq_flush_work); - /* We don't need set REQ_FLUSH_SEQ, it's for consistency */ rq = blk_mq_alloc_request(q, WRITE_FLUSH|REQ_FLUSH_SEQ, - __GFP_WAIT|GFP_ATOMIC, true); + __GFP_WAIT|GFP_ATOMIC, false); rq->cmd_type = REQ_TYPE_FS; rq->end_io = flush_end_io; @@ -408,8 +407,11 @@ void blk_insert_flush(struct request *rq) /* * @policy now records what operations need to be done. Adjust * REQ_FLUSH and FUA for the driver. + * We keep REQ_FLUSH for mq to track flush requests. For !FUA, + * we never dispatch the request directly. */ - rq->cmd_flags &= ~REQ_FLUSH; + if (rq->cmd_flags & REQ_FUA) + rq->cmd_flags &= ~REQ_FLUSH; if (!(fflags & REQ_FUA)) rq->cmd_flags &= ~REQ_FUA; diff --git a/block/blk-mq.c b/block/blk-mq.c index 57039fc..9072d0a 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -194,9 +194,27 @@ static void blk_mq_rq_ctx_init(struct request_queue *q, struct blk_mq_ctx *ctx, } static struct request *__blk_mq_alloc_request(struct blk_mq_hw_ctx *hctx, - gfp_t gfp, bool reserved) + gfp_t gfp, bool reserved, + int rw) { - return blk_mq_alloc_rq(hctx, gfp, reserved); + struct request *req; + bool is_flush = false; + /* + * flush need allocate a request, leave at least one request for + * non-flush IO to avoid deadlock + */ + if ((rw & REQ_FLUSH) && !(rw & REQ_FLUSH_SEQ)) { + if (atomic_inc_return(&hctx->pending_flush) >= + hctx->queue_depth - hctx->reserved_tags - 1) { + atomic_dec(&hctx->pending_flush); + return NULL; + } + is_flush = true; + } + req = blk_mq_alloc_rq(hctx, gfp, reserved); + if (!req && is_flush) + atomic_dec(&hctx->pending_flush); + return req; } static struct request *blk_mq_alloc_request_pinned(struct request_queue *q, @@ -209,7 +227,7 @@ static struct request *blk_mq_alloc_request_pinned(struct request_queue *q, struct blk_mq_ctx *ctx = blk_mq_get_ctx(q); struct blk_mq_hw_ctx *hctx = q->mq_ops->map_queue(q, ctx->cpu); - rq = __blk_mq_alloc_request(hctx, gfp & ~__GFP_WAIT, reserved); + rq = __blk_mq_alloc_request(hctx, gfp & ~__GFP_WAIT, reserved, rw); if (rq) { blk_mq_rq_ctx_init(q, ctx, rq, rw); break; @@ -272,6 +290,9 @@ static void __blk_mq_free_request(struct blk_mq_hw_ctx *hctx, const int tag = rq->tag; struct request_queue *q = rq->q; + if ((rq->cmd_flags & REQ_FLUSH) && !(rq->cmd_flags & REQ_FLUSH_SEQ)) + atomic_dec(&hctx->pending_flush); + blk_mq_rq_init(hctx, rq); blk_mq_put_tag(hctx->tags, tag); @@ -900,14 +921,14 @@ static void blk_mq_make_request(struct request_queue *q, struct bio *bio) hctx = q->mq_ops->map_queue(q, ctx->cpu); trace_block_getrq(q, bio, rw); - rq = __blk_mq_alloc_request(hctx, GFP_ATOMIC, false); + rq = __blk_mq_alloc_request(hctx, GFP_ATOMIC, false, bio->bi_rw); if (likely(rq)) - blk_mq_rq_ctx_init(q, ctx, rq, rw); + blk_mq_rq_ctx_init(q, ctx, rq, bio->bi_rw); else { blk_mq_put_ctx(ctx); trace_block_sleeprq(q, bio, rw); - rq = blk_mq_alloc_request_pinned(q, rw, __GFP_WAIT|GFP_ATOMIC, - false); + rq = blk_mq_alloc_request_pinned(q, bio->bi_rw, + __GFP_WAIT|GFP_ATOMIC, false); ctx = rq->mq_ctx; hctx = q->mq_ops->map_queue(q, ctx->cpu); } @@ -1184,7 +1205,9 @@ static int blk_mq_init_hw_queues(struct request_queue *q, hctx->queue_num = i; hctx->flags = reg->flags; hctx->queue_depth = reg->queue_depth; + hctx->reserved_tags = reg->reserved_tags; hctx->cmd_size = reg->cmd_size; + atomic_set(&hctx->pending_flush, 0); blk_mq_init_cpu_notifier(&hctx->cpu_notifier, blk_mq_hctx_notify, hctx); @@ -1309,15 +1332,6 @@ struct request_queue *blk_mq_init_queue(struct blk_mq_reg *reg, reg->queue_depth = BLK_MQ_MAX_DEPTH; } - /* - * Set aside a tag for flush requests. It will only be used while - * another flush request is in progress but outside the driver. - * - * TODO: only allocate if flushes are supported - */ - reg->queue_depth++; - reg->reserved_tags++; - if (reg->queue_depth < (reg->reserved_tags + BLK_MQ_TAG_MIN)) return ERR_PTR(-EINVAL); diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h index 161b231..1e8f16f 100644 --- a/include/linux/blk-mq.h +++ b/include/linux/blk-mq.h @@ -36,12 +36,15 @@ struct blk_mq_hw_ctx { struct list_head page_list; struct blk_mq_tags *tags; + atomic_t pending_flush; + unsigned long queued; unsigned long run; #define BLK_MQ_MAX_DISPATCH_ORDER 10 unsigned long dispatched[BLK_MQ_MAX_DISPATCH_ORDER]; unsigned int queue_depth; + unsigned int reserved_tags; unsigned int numa_node; unsigned int cmd_size; /* per-request extra data */ -- cgit v0.10.2 From 556ee818c06f37b2e583af0363e6b16d0e0270de Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 29 Jan 2014 14:56:16 -0700 Subject: block: __elv_next_request() shouldn't call into the elevator if bypassing request_queue bypassing is used to suppress higher-level function of a request_queue so that they can be switched, reconfigured and shut down. A request_queue does the followings while bypassing. * bypasses elevator and io_cq association and queues requests directly to the FIFO dispatch queue. * bypasses block cgroup request_list lookup and always uses the root request_list. Once confirmed to be bypassing, specific elevator and block cgroup policy implementations can assume that nothing is in flight for them and perform various operations which would be dangerous otherwise. Such confirmation is acheived by short-circuiting all new requests directly to the dispatch queue and waiting for all the requests which were issued before to finish. Unfortunately, while the request allocating and draining sides were properly handled, we forgot to actually plug the request dispatch path. Even after bypassing mode is confirmed, if the attached driver tries to fetch a request and the dispatch queue is empty, __elv_next_request() would invoke the current elevator's elevator_dispatch_fn() callback. As all in-flight requests were drained, the elevator wouldn't contain any request but once bypass is confirmed we don't even know whether the elevator is even there. It might be in the process of being switched and half torn down. Frank Mayhar reports that this actually happened while switching elevators, leading to an oops. Let's fix it by making __elv_next_request() avoid invoking the elevator_dispatch_fn() callback if the queue is bypassing. It already avoids invoking the callback if the queue is dying. As a dying queue is guaranteed to be bypassing, we can simply replace blk_queue_dying() check with blk_queue_bypass(). Reported-by: Frank Mayhar References: http://lkml.kernel.org/g/1390319905.20232.38.camel@bobble.lax.corp.google.com Cc: stable@vger.kernel.org Tested-by: Frank Mayhar Signed-off-by: Jens Axboe diff --git a/block/blk.h b/block/blk.h index c90e1d8..d23b415 100644 --- a/block/blk.h +++ b/block/blk.h @@ -113,7 +113,7 @@ static inline struct request *__elv_next_request(struct request_queue *q) q->flush_queue_delayed = 1; return NULL; } - if (unlikely(blk_queue_dying(q)) || + if (unlikely(blk_queue_bypass(q)) || !q->elevator->type->ops.elevator_dispatch_fn(q, 0)) return NULL; } -- cgit v0.10.2 From f7b2e4032d52deff480e0c303fbd9180276f8dfc Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Thu, 30 Jan 2014 13:27:49 -0800 Subject: Revert "xhci: replace xhci_read_64() with readq()" This reverts commit e8b373326d8efcaf9ec1da8b618556c89bd5ffc4. Many xHCI host controllers can only handle 32-bit addresses, and writing 64-bits at a time causes them to fail. Reading 64-bits at a time may also cause them to return 0xffffffff, so revert this commit as well. Signed-off-by: Sarah Sharp diff --git a/drivers/usb/host/xhci-dbg.c b/drivers/usb/host/xhci-dbg.c index b016d38..eb009a4 100644 --- a/drivers/usb/host/xhci-dbg.c +++ b/drivers/usb/host/xhci-dbg.c @@ -203,12 +203,12 @@ void xhci_print_ir_set(struct xhci_hcd *xhci, int set_num) addr, (unsigned int)temp); addr = &ir_set->erst_base; - temp_64 = readq(addr); + temp_64 = xhci_read_64(xhci, addr); xhci_dbg(xhci, " %p: ir_set.erst_base = @%08llx\n", addr, temp_64); addr = &ir_set->erst_dequeue; - temp_64 = readq(addr); + temp_64 = xhci_read_64(xhci, addr); xhci_dbg(xhci, " %p: ir_set.erst_dequeue = @%08llx\n", addr, temp_64); } @@ -412,7 +412,7 @@ void xhci_dbg_cmd_ptrs(struct xhci_hcd *xhci) { u64 val; - val = readq(&xhci->op_regs->cmd_ring); + val = xhci_read_64(xhci, &xhci->op_regs->cmd_ring); xhci_dbg(xhci, "// xHC command ring deq ptr low bits + flags = @%08x\n", lower_32_bits(val)); xhci_dbg(xhci, "// xHC command ring deq ptr high bits = @%08x\n", diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 4b87026..bce4391 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1958,7 +1958,7 @@ static void xhci_set_hc_event_deq(struct xhci_hcd *xhci) xhci_warn(xhci, "WARN something wrong with SW event ring " "dequeue ptr.\n"); /* Update HC event ring dequeue pointer */ - temp = readq(&xhci->ir_set->erst_dequeue); + temp = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); temp &= ERST_PTR_MASK; /* Don't clear the EHB bit (which is RW1C) because * there might be more events to service. @@ -2312,7 +2312,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) (unsigned long long)xhci->cmd_ring->first_seg->dma); /* Set the address in the Command Ring Control register */ - val_64 = readq(&xhci->op_regs->cmd_ring); + val_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring); val_64 = (val_64 & (u64) CMD_RING_RSVD_BITS) | (xhci->cmd_ring->first_seg->dma & (u64) ~CMD_RING_RSVD_BITS) | xhci->cmd_ring->cycle_state; @@ -2396,7 +2396,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) xhci_dbg_trace(xhci, trace_xhci_dbg_init, "// Set ERST base address for ir_set 0 = 0x%llx", (unsigned long long)xhci->erst.erst_dma_addr); - val_64 = readq(&xhci->ir_set->erst_base); + val_64 = xhci_read_64(xhci, &xhci->ir_set->erst_base); val_64 &= ERST_PTR_MASK; val_64 |= (xhci->erst.erst_dma_addr & (u64) ~ERST_PTR_MASK); xhci_write_64(xhci, val_64, &xhci->ir_set->erst_base); diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index e19fae9..909b32a 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -307,7 +307,7 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci) return 0; } - temp_64 = readq(&xhci->op_regs->cmd_ring); + temp_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring); if (!(temp_64 & CMD_RING_RUNNING)) { xhci_dbg(xhci, "Command ring had been stopped\n"); return 0; @@ -2865,7 +2865,7 @@ hw_died: /* Clear the event handler busy flag (RW1C); * the event ring should be empty. */ - temp_64 = readq(&xhci->ir_set->erst_dequeue); + temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); xhci_write_64(xhci, temp_64 | ERST_EHB, &xhci->ir_set->erst_dequeue); spin_unlock(&xhci->lock); @@ -2879,7 +2879,7 @@ hw_died: */ while (xhci_handle_event(xhci) > 0) {} - temp_64 = readq(&xhci->ir_set->erst_dequeue); + temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); /* If necessary, update the HW's version of the event ring deq ptr. */ if (event_ring_deq != xhci->event_ring->dequeue) { deq = xhci_trb_virt_to_dma(xhci->event_ring->deq_seg, diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index ebbe52c..3712359 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -611,7 +611,7 @@ int xhci_run(struct usb_hcd *hcd) xhci_dbg(xhci, "Event ring:\n"); xhci_debug_ring(xhci, xhci->event_ring); xhci_dbg_ring_ptrs(xhci, xhci->event_ring); - temp_64 = readq(&xhci->ir_set->erst_dequeue); + temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); temp_64 &= ~ERST_PTR_MASK; xhci_dbg_trace(xhci, trace_xhci_dbg_init, "ERST deq = 64'h%0lx", (long unsigned int) temp_64); @@ -756,11 +756,11 @@ static void xhci_save_registers(struct xhci_hcd *xhci) { xhci->s3.command = readl(&xhci->op_regs->command); xhci->s3.dev_nt = readl(&xhci->op_regs->dev_notification); - xhci->s3.dcbaa_ptr = readq(&xhci->op_regs->dcbaa_ptr); + xhci->s3.dcbaa_ptr = xhci_read_64(xhci, &xhci->op_regs->dcbaa_ptr); xhci->s3.config_reg = readl(&xhci->op_regs->config_reg); xhci->s3.erst_size = readl(&xhci->ir_set->erst_size); - xhci->s3.erst_base = readq(&xhci->ir_set->erst_base); - xhci->s3.erst_dequeue = readq(&xhci->ir_set->erst_dequeue); + xhci->s3.erst_base = xhci_read_64(xhci, &xhci->ir_set->erst_base); + xhci->s3.erst_dequeue = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); xhci->s3.irq_pending = readl(&xhci->ir_set->irq_pending); xhci->s3.irq_control = readl(&xhci->ir_set->irq_control); } @@ -783,7 +783,7 @@ static void xhci_set_cmd_ring_deq(struct xhci_hcd *xhci) u64 val_64; /* step 2: initialize command ring buffer */ - val_64 = readq(&xhci->op_regs->cmd_ring); + val_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring); val_64 = (val_64 & (u64) CMD_RING_RSVD_BITS) | (xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg, xhci->cmd_ring->dequeue) & @@ -3842,7 +3842,7 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev, if (ret) { return ret; } - temp_64 = readq(&xhci->op_regs->dcbaa_ptr); + temp_64 = xhci_read_64(xhci, &xhci->op_regs->dcbaa_ptr); xhci_dbg_trace(xhci, trace_xhci_dbg_address, "Op regs DCBAA ptr = %#016llx", temp_64); xhci_dbg_trace(xhci, trace_xhci_dbg_address, diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 60def15..9154fd6 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -28,8 +28,6 @@ #include #include -#include - /* Code sharing between pci-quirks and xhci hcd */ #include "xhci-ext-caps.h" #include "pci-quirks.h" @@ -1614,6 +1612,14 @@ static inline struct usb_hcd *xhci_to_hcd(struct xhci_hcd *xhci) * xHCI implementations that do not support 64-bit address pointers will ignore * the high dword, and write order is irrelevant. */ +static inline u64 xhci_read_64(const struct xhci_hcd *xhci, + __le64 __iomem *regs) +{ + __u32 __iomem *ptr = (__u32 __iomem *) regs; + u64 val_lo = readl(ptr); + u64 val_hi = readl(ptr + 1); + return val_lo + (val_hi << 32); +} static inline void xhci_write_64(struct xhci_hcd *xhci, const u64 val, __le64 __iomem *regs) { -- cgit v0.10.2 From f8d56d8f892be43a2404356073e16401eb5a42e6 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Wed, 29 Jan 2014 11:32:37 +0100 Subject: net: eth: cpsw: Correctly attach to GPIO bitbang MDIO driver When the GPIO bitbang MDIO driver is used instead of the Davinci MDIO driver we need to configure the phy_id string differently. Otherwise this string looks like this "gpio.6" instead of "gpio-0" and the PHY is not found when phy_connect() is called. Signed-off-by: Stefan Roese Cc: Lukas Stockmann Cc: Mugunthan V N Acked-by: Mugunthan V N Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index bde63e3..1d860ce 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@ -1878,8 +1878,18 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data, mdio_node = of_find_node_by_phandle(be32_to_cpup(parp)); phyid = be32_to_cpup(parp+1); mdio = of_find_device_by_node(mdio_node); - snprintf(slave_data->phy_id, sizeof(slave_data->phy_id), - PHY_ID_FMT, mdio->name, phyid); + + if (strncmp(mdio->name, "gpio", 4) == 0) { + /* GPIO bitbang MDIO driver attached */ + struct mii_bus *bus = dev_get_drvdata(&mdio->dev); + + snprintf(slave_data->phy_id, sizeof(slave_data->phy_id), + PHY_ID_FMT, bus->id, phyid); + } else { + /* davinci MDIO driver attached */ + snprintf(slave_data->phy_id, sizeof(slave_data->phy_id), + PHY_ID_FMT, mdio->name, phyid); + } mac_addr = of_get_mac_address(slave_node); if (mac_addr) -- cgit v0.10.2 From b5aaab12b2b4bc4acab7384c17a87f3406e5047d Mon Sep 17 00:00:00 2001 From: Or Gerlitz Date: Wed, 29 Jan 2014 18:08:59 +0200 Subject: net/ipv4: Use non-atomic allocation of udp offloads structure instance Since udp_add_offload() can be called from non-sleepable context e.g under this call tree from the vxlan driver use case: vxlan_socket_create() <-- holds the spinlock -> vxlan_notify_add_rx_port() -> udp_add_offload() <-- schedules we should allocate the udp_offloads structure in atomic manner. Fixes: b582ef0 ('net: Add GRO support for UDP encapsulating protocols') Reported-by: Dan Carpenter Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c index 25f5cee..2ffea6f 100644 --- a/net/ipv4/udp_offload.c +++ b/net/ipv4/udp_offload.c @@ -101,7 +101,7 @@ out: int udp_add_offload(struct udp_offload *uo) { struct udp_offload_priv __rcu **head = &udp_offload_base; - struct udp_offload_priv *new_offload = kzalloc(sizeof(*new_offload), GFP_KERNEL); + struct udp_offload_priv *new_offload = kzalloc(sizeof(*new_offload), GFP_ATOMIC); if (!new_offload) return -ENOMEM; -- cgit v0.10.2 From 920a0fde5a32fd40b4d3c94ad72f7fc7039db8e3 Mon Sep 17 00:00:00 2001 From: Or Gerlitz Date: Wed, 29 Jan 2014 18:10:10 +0200 Subject: net/vxlan: Go over all candidate streams for GRO matching The loop in vxlan_gro_receive() over the current set of candidates for coalescing was wrongly aborted once a match was found. In rare cases, this can cause a false-positives matching in the next layer GRO checks. Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 026a313..3d6cd1c 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -596,10 +596,8 @@ static struct sk_buff **vxlan_gro_receive(struct sk_buff **head, struct sk_buff NAPI_GRO_CB(p)->same_flow = 0; continue; } - goto found; } -found: type = eh->h_proto; rcu_read_lock(); -- cgit v0.10.2 From 0ae89beb283a0db5980d1d4781c7d7be2f2810d6 Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Thu, 30 Jan 2014 10:11:28 +0100 Subject: can: add destructor for self generated skbs Self generated skbuffs in net/can/bcm.c are setting a skb->sk reference but no explicit destructor which is enforced since Linux 3.11 with commit 376c7311bdb6 (net: add a temporary sanity check in skb_orphan()). This patch adds some helper functions to make sure that a destructor is properly defined when a sock reference is assigned to a CAN related skb. To create an unshared skb owned by the original sock a common helper function has been introduced to replace open coded functions to create CAN echo skbs. Signed-off-by: Oliver Hartkopp Tested-by: Andre Naujoks Reviewed-by: Eric Dumazet Signed-off-by: David S. Miller diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c index 13a9098..fc59bc6 100644 --- a/drivers/net/can/dev.c +++ b/drivers/net/can/dev.c @@ -323,19 +323,10 @@ void can_put_echo_skb(struct sk_buff *skb, struct net_device *dev, } if (!priv->echo_skb[idx]) { - struct sock *srcsk = skb->sk; - if (atomic_read(&skb->users) != 1) { - struct sk_buff *old_skb = skb; - - skb = skb_clone(old_skb, GFP_ATOMIC); - kfree_skb(old_skb); - if (!skb) - return; - } else - skb_orphan(skb); - - skb->sk = srcsk; + skb = can_create_echo_skb(skb); + if (!skb) + return; /* make settings for echo to reduce code in irq context */ skb->protocol = htons(ETH_P_CAN); diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c index e24e669..2124c679 100644 --- a/drivers/net/can/janz-ican3.c +++ b/drivers/net/can/janz-ican3.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -1133,20 +1134,9 @@ static void ican3_handle_message(struct ican3_dev *mod, struct ican3_msg *msg) */ static void ican3_put_echo_skb(struct ican3_dev *mod, struct sk_buff *skb) { - struct sock *srcsk = skb->sk; - - if (atomic_read(&skb->users) != 1) { - struct sk_buff *old_skb = skb; - - skb = skb_clone(old_skb, GFP_ATOMIC); - kfree_skb(old_skb); - if (!skb) - return; - } else { - skb_orphan(skb); - } - - skb->sk = srcsk; + skb = can_create_echo_skb(skb); + if (!skb) + return; /* save this skb for tx interrupt echo handling */ skb_queue_tail(&mod->echoq, skb); diff --git a/drivers/net/can/vcan.c b/drivers/net/can/vcan.c index 0a2a5ee..4e94057 100644 --- a/drivers/net/can/vcan.c +++ b/drivers/net/can/vcan.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include @@ -109,25 +110,23 @@ static netdev_tx_t vcan_tx(struct sk_buff *skb, struct net_device *dev) stats->rx_packets++; stats->rx_bytes += cfd->len; } - kfree_skb(skb); + consume_skb(skb); return NETDEV_TX_OK; } /* perform standard echo handling for CAN network interfaces */ if (loop) { - struct sock *srcsk = skb->sk; - skb = skb_share_check(skb, GFP_ATOMIC); + skb = can_create_echo_skb(skb); if (!skb) return NETDEV_TX_OK; /* receive with packet counting */ - skb->sk = srcsk; vcan_rx(skb, dev); } else { /* no looped packets => no counting */ - kfree_skb(skb); + consume_skb(skb); } return NETDEV_TX_OK; } diff --git a/include/linux/can/skb.h b/include/linux/can/skb.h index 2f0543f..f9bbbb4 100644 --- a/include/linux/can/skb.h +++ b/include/linux/can/skb.h @@ -11,7 +11,9 @@ #define CAN_SKB_H #include +#include #include +#include /* * The struct can_skb_priv is used to transport additional information along @@ -42,4 +44,40 @@ static inline void can_skb_reserve(struct sk_buff *skb) skb_reserve(skb, sizeof(struct can_skb_priv)); } +static inline void can_skb_destructor(struct sk_buff *skb) +{ + sock_put(skb->sk); +} + +static inline void can_skb_set_owner(struct sk_buff *skb, struct sock *sk) +{ + if (sk) { + sock_hold(sk); + skb->destructor = can_skb_destructor; + skb->sk = sk; + } +} + +/* + * returns an unshared skb owned by the original sock to be echo'ed back + */ +static inline struct sk_buff *can_create_echo_skb(struct sk_buff *skb) +{ + if (skb_shared(skb)) { + struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC); + + if (likely(nskb)) { + can_skb_set_owner(nskb, skb->sk); + consume_skb(skb); + return nskb; + } else { + kfree_skb(skb); + return NULL; + } + } + + /* we can assume to have an unshared skb with proper owner */ + return skb; +} + #endif /* CAN_SKB_H */ diff --git a/net/can/af_can.c b/net/can/af_can.c index d249874..a27f8aa 100644 --- a/net/can/af_can.c +++ b/net/can/af_can.c @@ -57,6 +57,7 @@ #include #include #include +#include #include #include #include @@ -290,7 +291,7 @@ int can_send(struct sk_buff *skb, int loop) return -ENOMEM; } - newskb->sk = skb->sk; + can_skb_set_owner(newskb, skb->sk); newskb->ip_summed = CHECKSUM_UNNECESSARY; newskb->pkt_type = PACKET_BROADCAST; } diff --git a/net/can/bcm.c b/net/can/bcm.c index 3fc737b..dcb75c0 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c @@ -268,7 +268,7 @@ static void bcm_can_tx(struct bcm_op *op) /* send with loopback */ skb->dev = dev; - skb->sk = op->sk; + can_skb_set_owner(skb, op->sk); can_send(skb, 1); /* update statistics */ @@ -1223,7 +1223,7 @@ static int bcm_tx_send(struct msghdr *msg, int ifindex, struct sock *sk) can_skb_prv(skb)->ifindex = dev->ifindex; skb->dev = dev; - skb->sk = sk; + can_skb_set_owner(skb, sk); err = can_send(skb, 1); /* send with loopback */ dev_put(dev); -- cgit v0.10.2 From 8a85ac4bd8052e53f15fc0d646cc2b2b64438016 Mon Sep 17 00:00:00 2001 From: Venkat Venkatsubra Date: Thu, 30 Jan 2014 13:28:47 -0800 Subject: rds: The maintainer needs to be updated. Signed-off-by: Venkat Venkatsubra Signed-off-by: David S. Miller diff --git a/MAINTAINERS b/MAINTAINERS index a31a6e3..fce05c4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7175,7 +7175,7 @@ S: Maintained F: drivers/net/ethernet/rdc/r6040.c RDS - RELIABLE DATAGRAM SOCKETS -M: Venkat Venkatsubra +M: Chien Yen L: rds-devel@oss.oracle.com (moderated for non-subscribers) S: Supported F: net/rds/ -- cgit v0.10.2 From 2b6e0ca175fe4a20f21ba82b1e7ccc71029c4dd4 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Thu, 30 Jan 2014 10:51:04 +0000 Subject: e100: Fix "disabling already-disabled device" warning In https://bugzilla.redhat.com/show_bug.cgi?id=994438 and https://bugzilla.redhat.com/show_bug.cgi?id=970480 we received different reports of e100 throwing the following warning: [] ? pci_disable_device+0x85/0x90 [] warn_slowpath_fmt+0x33/0x40 [] pci_disable_device+0x85/0x90 [] __e100_shutdown+0x80/0x120 [e100] [] ? check_preempt_curr+0x65/0x90 [] e100_suspend+0x16/0x30 [e100] [] pci_legacy_suspend+0x2b/0xb0 [] ? wait_for_completion+0x1f/0xd0 [] ? pci_pm_poweroff+0xb0/0xb0 [] pci_pm_freeze+0x94/0xa0 [] dpm_run_callback+0x37/0x80 [] ? pm_wakeup_pending+0xc4/0x140 [] __device_suspend+0xb2/0x1f0 [] async_suspend+0x1f/0x90 [] async_run_entry_fn+0x35/0x140 [] ? wake_up_process+0x1f/0x40 [] process_one_work+0x115/0x370 [] ? start_worker+0x25/0x30 [] ? manage_workers.isra.27+0x1a5/0x250 [] worker_thread+0xfe/0x330 [] ? manage_workers.isra.27+0x250/0x250 [] kthread+0x94/0xa0 [] ret_from_kernel_thread+0x1b/0x28 [] ? insert_kthread_work+0x30/0x30 This patch removes pci_disable_device() from __e100_shutdown(). pci_clear_master() is enough. Signed-off-by: Michele Baldessari Tested-by: Mark Harig Signed-off-by: Aaron Brown Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/intel/e100.c b/drivers/net/ethernet/intel/e100.c index cbaba44..bf7a01e 100644 --- a/drivers/net/ethernet/intel/e100.c +++ b/drivers/net/ethernet/intel/e100.c @@ -3034,7 +3034,7 @@ static void __e100_shutdown(struct pci_dev *pdev, bool *enable_wake) *enable_wake = false; } - pci_disable_device(pdev); + pci_clear_master(pdev); } static int __e100_power_off(struct pci_dev *pdev, bool wake) -- cgit v0.10.2 From ac323d8d807060f7c95a685a9fe861e7b6300993 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 30 Jan 2014 14:32:45 +0100 Subject: power: max17040: Fix NULL pointer dereference when there is no platform_data Fix NULL pointer dereference of "chip->pdata" if platform_data was not supplied to the driver. The driver during probe stored the pointer to the platform_data: chip->pdata = client->dev.platform_data; Later it was dereferenced in max17040_get_online() and max17040_get_status(). If platform_data was not supplied, the NULL pointer exception would happen: [ 6.626094] Unable to handle kernel of a at virtual address 00000000 [ 6.628557] pgd = c0004000 [ 6.632868] [00000000] *pgd=66262564 [ 6.634636] Unable to handle kernel paging request at virtual address e6262000 [ 6.642014] pgd = de468000 [ 6.644700] [e6262000] *pgd=00000000 [ 6.648265] Internal error: Oops: 5 [#1] PREEMPT SMP ARM [ 6.653552] Modules linked in: [ 6.656598] CPU: 0 PID: 31 Comm: kworker/0:1 Not tainted 3.10.14-02717-gc58b4b4 #505 [ 6.664334] Workqueue: events max17040_work [ 6.668488] task: dfa11b80 ti: df9f6000 task.ti: df9f6000 [ 6.673873] PC is at show_pte+0x80/0xb8 [ 6.677687] LR is at show_pte+0x3c/0xb8 [ 6.681503] pc : [] lr : [] psr: 600f0113 [ 6.681503] sp : df9f7d58 ip : 600f0113 fp : 00000009 [ 6.692965] r10: 00000000 r9 : 00000000 r8 : dfa11b80 [ 6.698171] r7 : df9f7ea0 r6 : e6262000 r5 : 00000000 r4 : 00000000 [ 6.704680] r3 : 00000000 r2 : e6262000 r1 : 600f0193 r0 : c05b3750 [ 6.711194] Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment kernel [ 6.718485] Control: 10c53c7d Table: 5e46806a DAC: 00000015 [ 6.724218] Process kworker/0:1 (pid: 31, stack limit = 0xdf9f6238) [ 6.730465] Stack: (0xdf9f7d58 to 0xdf9f8000) [ 6.914325] [] (show_pte+0x80/0xb8) from [] (__do_kernel_fault.part.9+0x44/0x74) [ 6.923425] [] (__do_kernel_fault.part.9+0x44/0x74) from [] (do_page_fault+0x2c4/0x360) [ 6.933144] [] (do_page_fault+0x2c4/0x360) from [] (do_DataAbort+0x34/0x9c) [ 6.941825] [] (do_DataAbort+0x34/0x9c) from [] (__dabt_svc+0x38/0x60) [ 6.950058] Exception stack(0xdf9f7ea0 to 0xdf9f7ee8) [ 6.955099] 7ea0: df0c1790 00000000 00000002 00000000 df0c1794 df0c1790 df0c1790 00000042 [ 6.963271] 7ec0: df0c1794 00000001 00000000 00000009 00000000 df9f7ee8 c0306268 c0306270 [ 6.971419] 7ee0: a00f0113 ffffffff [ 6.974902] [] (__dabt_svc+0x38/0x60) from [] (max17040_work+0x8c/0x144) [ 6.983317] [] (max17040_work+0x8c/0x144) from [] (process_one_work+0x138/0x440) [ 6.992429] [] (process_one_work+0x138/0x440) from [] (worker_thread+0x134/0x3b8) [ 7.001628] [] (worker_thread+0x134/0x3b8) from [] (kthread+0xa4/0xb0) [ 7.009875] [] (kthread+0xa4/0xb0) from [] (ret_from_fork+0x14/0x2c) [ 7.017943] Code: e1a03005 e2422480 e0826104 e59f002c (e7922104) [ 7.024017] ---[ end trace 73bc7006b9cc5c79 ]--- Signed-off-by: Krzysztof Kozlowski Fixes: c6f4a42de60b981dd210de01cd3e575835e3158e Cc: diff --git a/drivers/power/max17040_battery.c b/drivers/power/max17040_battery.c index c7ff6d6..0fbac86 100644 --- a/drivers/power/max17040_battery.c +++ b/drivers/power/max17040_battery.c @@ -148,7 +148,7 @@ static void max17040_get_online(struct i2c_client *client) { struct max17040_chip *chip = i2c_get_clientdata(client); - if (chip->pdata->battery_online) + if (chip->pdata && chip->pdata->battery_online) chip->online = chip->pdata->battery_online(); else chip->online = 1; @@ -158,7 +158,8 @@ static void max17040_get_status(struct i2c_client *client) { struct max17040_chip *chip = i2c_get_clientdata(client); - if (!chip->pdata->charger_online || !chip->pdata->charger_enable) { + if (!chip->pdata || !chip->pdata->charger_online + || !chip->pdata->charger_enable) { chip->status = POWER_SUPPLY_STATUS_UNKNOWN; return; } -- cgit v0.10.2 From fba9110c47855050b38a5a19bbcd3728b5f21bfe Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Fri, 31 Jan 2014 09:41:04 +0400 Subject: net: ethoc: implement basic ethtool operations The following methods are implemented: - get link state (standard implementation); - get timestamping info (standard implementation). Signed-off-by: Max Filippov Reviewed-by: Florian Fainelli Reviewed-by: Ben Hutchings Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/ethoc.c b/drivers/net/ethernet/ethoc.c index 4de8cfd..0623c20 100644 --- a/drivers/net/ethernet/ethoc.c +++ b/drivers/net/ethernet/ethoc.c @@ -890,6 +890,11 @@ out: return NETDEV_TX_OK; } +const struct ethtool_ops ethoc_ethtool_ops = { + .get_link = ethtool_op_get_link, + .get_ts_info = ethtool_op_get_ts_info, +}; + static const struct net_device_ops ethoc_netdev_ops = { .ndo_open = ethoc_open, .ndo_stop = ethoc_stop, @@ -1111,6 +1116,7 @@ static int ethoc_probe(struct platform_device *pdev) netdev->netdev_ops = ðoc_netdev_ops; netdev->watchdog_timeo = ETHOC_TIMEOUT; netdev->features |= 0; + netdev->ethtool_ops = ðoc_ethtool_ops; /* setup NAPI */ netif_napi_add(netdev, &priv->napi, ethoc_poll, 64); -- cgit v0.10.2 From 01cd7d578e01d342b1c06f0dc41c00b445415753 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Fri, 31 Jan 2014 09:41:05 +0400 Subject: net: ethoc: implement ethtool get/set settings Signed-off-by: Max Filippov Reviewed-by: Ben Hutchings Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/ethoc.c b/drivers/net/ethernet/ethoc.c index 0623c20..779d3c3 100644 --- a/drivers/net/ethernet/ethoc.c +++ b/drivers/net/ethernet/ethoc.c @@ -890,7 +890,31 @@ out: return NETDEV_TX_OK; } +static int ethoc_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct ethoc *priv = netdev_priv(dev); + struct phy_device *phydev = priv->phy; + + if (!phydev) + return -EOPNOTSUPP; + + return phy_ethtool_gset(phydev, cmd); +} + +static int ethoc_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct ethoc *priv = netdev_priv(dev); + struct phy_device *phydev = priv->phy; + + if (!phydev) + return -EOPNOTSUPP; + + return phy_ethtool_sset(phydev, cmd); +} + const struct ethtool_ops ethoc_ethtool_ops = { + .get_settings = ethoc_get_settings, + .set_settings = ethoc_set_settings, .get_link = ethtool_op_get_link, .get_ts_info = ethtool_op_get_ts_info, }; -- cgit v0.10.2 From 1112909f76650e1d4c6de44b80c2d044c7c11e59 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Fri, 31 Jan 2014 09:41:06 +0400 Subject: net: ethoc: implement ethtool get registers Signed-off-by: Max Filippov Reviewed-by: Florian Fainelli Reviewed-by: Ben Hutchings Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/ethoc.c b/drivers/net/ethernet/ethoc.c index 779d3c3..5da32a7 100644 --- a/drivers/net/ethernet/ethoc.c +++ b/drivers/net/ethernet/ethoc.c @@ -51,6 +51,7 @@ MODULE_PARM_DESC(buffer_size, "DMA buffer allocation size"); #define ETH_HASH0 0x48 #define ETH_HASH1 0x4c #define ETH_TXCTRL 0x50 +#define ETH_END 0x54 /* mode register */ #define MODER_RXEN (1 << 0) /* receive enable */ @@ -912,9 +913,28 @@ static int ethoc_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) return phy_ethtool_sset(phydev, cmd); } +static int ethoc_get_regs_len(struct net_device *netdev) +{ + return ETH_END; +} + +static void ethoc_get_regs(struct net_device *dev, struct ethtool_regs *regs, + void *p) +{ + struct ethoc *priv = netdev_priv(dev); + u32 *regs_buff = p; + unsigned i; + + regs->version = 0; + for (i = 0; i < ETH_END / sizeof(u32); ++i) + regs_buff[i] = ethoc_read(priv, i * sizeof(u32)); +} + const struct ethtool_ops ethoc_ethtool_ops = { .get_settings = ethoc_get_settings, .set_settings = ethoc_set_settings, + .get_regs_len = ethoc_get_regs_len, + .get_regs = ethoc_get_regs, .get_link = ethtool_op_get_link, .get_ts_info = ethtool_op_get_ts_info, }; -- cgit v0.10.2 From bee7bacd18612564b85dc0b3e54063316c5bb32d Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Fri, 31 Jan 2014 09:41:07 +0400 Subject: net: ethoc: implement ethtool get/set ring parameters TX and RX rings share memory and descriptors. Maximal number of descriptors reported is one less than the total available nuber of descriptors. For the set operation the requested number of TX descriptors is rounded down to the nearest power of two (driver logic requirement). Signed-off-by: Max Filippov Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/ethoc.c b/drivers/net/ethernet/ethoc.c index 5da32a7..f9c1cf5 100644 --- a/drivers/net/ethernet/ethoc.c +++ b/drivers/net/ethernet/ethoc.c @@ -180,6 +180,7 @@ MODULE_PARM_DESC(buffer_size, "DMA buffer allocation size"); * @membase: pointer to buffer memory region * @dma_alloc: dma allocated buffer size * @io_region_size: I/O memory region size + * @num_bd: number of buffer descriptors * @num_tx: number of send buffers * @cur_tx: last send buffer written * @dty_tx: last buffer actually sent @@ -200,6 +201,7 @@ struct ethoc { int dma_alloc; resource_size_t io_region_size; + unsigned int num_bd; unsigned int num_tx; unsigned int cur_tx; unsigned int dty_tx; @@ -930,12 +932,60 @@ static void ethoc_get_regs(struct net_device *dev, struct ethtool_regs *regs, regs_buff[i] = ethoc_read(priv, i * sizeof(u32)); } +static void ethoc_get_ringparam(struct net_device *dev, + struct ethtool_ringparam *ring) +{ + struct ethoc *priv = netdev_priv(dev); + + ring->rx_max_pending = priv->num_bd - 1; + ring->rx_mini_max_pending = 0; + ring->rx_jumbo_max_pending = 0; + ring->tx_max_pending = priv->num_bd - 1; + + ring->rx_pending = priv->num_rx; + ring->rx_mini_pending = 0; + ring->rx_jumbo_pending = 0; + ring->tx_pending = priv->num_tx; +} + +static int ethoc_set_ringparam(struct net_device *dev, + struct ethtool_ringparam *ring) +{ + struct ethoc *priv = netdev_priv(dev); + + if (ring->tx_pending < 1 || ring->rx_pending < 1 || + ring->tx_pending + ring->rx_pending > priv->num_bd) + return -EINVAL; + if (ring->rx_mini_pending || ring->rx_jumbo_pending) + return -EINVAL; + + if (netif_running(dev)) { + netif_tx_disable(dev); + ethoc_disable_rx_and_tx(priv); + ethoc_disable_irq(priv, INT_MASK_TX | INT_MASK_RX); + synchronize_irq(dev->irq); + } + + priv->num_tx = rounddown_pow_of_two(ring->tx_pending); + priv->num_rx = ring->rx_pending; + ethoc_init_ring(priv, dev->mem_start); + + if (netif_running(dev)) { + ethoc_enable_irq(priv, INT_MASK_TX | INT_MASK_RX); + ethoc_enable_rx_and_tx(priv); + netif_wake_queue(dev); + } + return 0; +} + const struct ethtool_ops ethoc_ethtool_ops = { .get_settings = ethoc_get_settings, .set_settings = ethoc_set_settings, .get_regs_len = ethoc_get_regs_len, .get_regs = ethoc_get_regs, .get_link = ethtool_op_get_link, + .get_ringparam = ethoc_get_ringparam, + .set_ringparam = ethoc_set_ringparam, .get_ts_info = ethtool_op_get_ts_info, }; @@ -1065,6 +1115,7 @@ static int ethoc_probe(struct platform_device *pdev) ret = -ENODEV; goto error; } + priv->num_bd = num_bd; /* num_tx must be a power of two */ priv->num_tx = rounddown_pow_of_two(num_bd >> 1); priv->num_rx = num_bd - priv->num_tx; -- cgit v0.10.2 From 4fe46b9a4d0b5eef96867e6d5134159e5a65d2a5 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Fri, 31 Jan 2014 09:50:12 +0200 Subject: vxlan: remove extra newline after function definition Signed-off-by: Daniel Baluta Signed-off-by: David S. Miller diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 3d6cd1c..b0f705c 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -469,7 +469,6 @@ static inline struct hlist_head *vxlan_fdb_head(struct vxlan_dev *vxlan, /* Look up Ethernet address in forwarding table */ static struct vxlan_fdb *__vxlan_find_mac(struct vxlan_dev *vxlan, const u8 *mac) - { struct hlist_head *head = vxlan_fdb_head(vxlan, mac); struct vxlan_fdb *f; -- cgit v0.10.2 From 8e2a866ef214af4e104ec8d593e3269d8fe66d19 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Tue, 28 Jan 2014 12:27:31 +0200 Subject: iwlwifi: mvm: BT Coex - disable BT when TXing probe request in scan Not doing so will let BT kill our probe requests leading to failures in scan. Cc: [3.10+] Reviewed-by: Johannes Berg Signed-off-by: Emmanuel Grumbach diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index c35f35c..742afc4 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c @@ -344,7 +344,8 @@ int iwl_mvm_scan_request(struct iwl_mvm *mvm, iwl_mvm_scan_fill_ssids(cmd, req, basic_ssid ? 1 : 0); - cmd->tx_cmd.tx_flags = cpu_to_le32(TX_CMD_FLG_SEQ_CTL); + cmd->tx_cmd.tx_flags = cpu_to_le32(TX_CMD_FLG_SEQ_CTL | + TX_CMD_FLG_BT_DIS); cmd->tx_cmd.sta_id = mvm->aux_sta.sta_id; cmd->tx_cmd.life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE); cmd->tx_cmd.rate_n_flags = -- cgit v0.10.2 From c512865446e6dd5b6e91e81187e75b734ad7cfc7 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 5 Dec 2013 22:42:55 +0200 Subject: iwlwifi: mvm: don't allow A band if SKU forbids it The driver wasn't reading the NVM properly. While this didn't lead to any issue until now, it seems that there is an old version of the NVM in the wild. In this version, the A band channels appear to be valid but the SKU capabilities (another field of the NVM) says that A band isn't supported at all. With this specific version of the NVM, the driver would think that A band is supported while the HW / firmware don't. This leads to asserts. Cc: [3.10+] Reviewed-by: Johannes Berg Signed-off-by: Emmanuel Grumbach diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c index f06f4cb..725e954d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c @@ -182,6 +182,11 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, for (ch_idx = 0; ch_idx < IWL_NUM_CHANNELS; ch_idx++) { ch_flags = __le16_to_cpup(nvm_ch_flags + ch_idx); + + if (ch_idx >= NUM_2GHZ_CHANNELS && + !data->sku_cap_band_52GHz_enable) + ch_flags &= ~NVM_CHANNEL_VALID; + if (!(ch_flags & NVM_CHANNEL_VALID)) { IWL_DEBUG_EEPROM(dev, "Ch. %d Flags %x [%sGHz] - No traffic\n", -- cgit v0.10.2 From 7288ca07b638db485abec5752bd6b1faed1c33ef Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sat, 25 Jan 2014 18:14:44 +0100 Subject: drm/i2c: tda998x: fix bad value in the AIF The AIF has an uninitialized byte. This patch clears the whole buffer before filling it. Tested-by: Russell King Acked-by: Russell King Signed-off-by: Jean-Francois Moine Signed-off-by: Russell King diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c index 400b0c4..e620826 100644 --- a/drivers/gpu/drm/i2c/tda998x_drv.c +++ b/drivers/gpu/drm/i2c/tda998x_drv.c @@ -528,10 +528,10 @@ tda998x_write_aif(struct drm_encoder *encoder, struct tda998x_encoder_params *p) { uint8_t buf[PB(5) + 1]; + memset(buf, 0, sizeof(buf)); buf[HB(0)] = 0x84; buf[HB(1)] = 0x01; buf[HB(2)] = 10; - buf[PB(0)] = 0; buf[PB(1)] = p->audio_frame[1] & 0x07; /* CC */ buf[PB(2)] = p->audio_frame[2] & 0x1c; /* SF */ buf[PB(4)] = p->audio_frame[4]; -- cgit v0.10.2 From 6ae668cc19e8b18df28cd67b3448d9abd79284a4 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sat, 25 Jan 2014 18:14:43 +0100 Subject: drm/i2c: tda998x: check the CEC device creation This patch checks if the CEC device is well created at intialization time. Tested-by: Russell King Acked-by: Russell King Signed-off-by: Jean-Francois Moine Signed-off-by: Russell King diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c index e620826..c37180a 100644 --- a/drivers/gpu/drm/i2c/tda998x_drv.c +++ b/drivers/gpu/drm/i2c/tda998x_drv.c @@ -1144,6 +1144,8 @@ tda998x_encoder_init(struct i2c_client *client, priv->current_page = 0; priv->cec = i2c_new_dummy(client->adapter, 0x34); + if (!priv->cec) + return -ENODEV; priv->dpms = DRM_MODE_DPMS_OFF; encoder_slave->slave_priv = priv; -- cgit v0.10.2 From fc275a74eb816c12d4fc226344e734872ed0b2f9 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sat, 25 Jan 2014 18:14:42 +0100 Subject: drm/i2c: tda998x: free the CEC device on encoder_destroy The cec i2c device is created in tda998x_encoder_init() when the DRM driver starts. This patch frees it when the DRM driver is unloaded. Tested-by: Russell King Acked-by: Russell King Signed-off-by: Jean-Francois Moine Signed-off-by: Russell King diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c index c37180a..de0572e 100644 --- a/drivers/gpu/drm/i2c/tda998x_drv.c +++ b/drivers/gpu/drm/i2c/tda998x_drv.c @@ -1094,6 +1094,8 @@ tda998x_encoder_destroy(struct drm_encoder *encoder) { struct tda998x_priv *priv = to_tda998x_priv(encoder); drm_i2c_encoder_destroy(encoder); + if (priv->cec) + i2c_unregister_device(priv->cec); kfree(priv); } -- cgit v0.10.2 From 2eb4c7b1e7f275fe833aabe0a251b8e3f767fb08 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sat, 25 Jan 2014 18:14:45 +0100 Subject: drm/i2c: tda998x: force the page register at startup time This patch forces the page register to be set on the first I/O operation. Tested-by: Russell King Acked-by: Russell King Signed-off-by: Jean-Francois Moine Signed-off-by: Russell King diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c index de0572e..e871a42 100644 --- a/drivers/gpu/drm/i2c/tda998x_drv.c +++ b/drivers/gpu/drm/i2c/tda998x_drv.c @@ -1144,7 +1144,7 @@ tda998x_encoder_init(struct i2c_client *client, priv->vip_cntrl_1 = VIP_CNTRL_1_SWAP_C(0) | VIP_CNTRL_1_SWAP_D(1); priv->vip_cntrl_2 = VIP_CNTRL_2_SWAP_E(4) | VIP_CNTRL_2_SWAP_F(5); - priv->current_page = 0; + priv->current_page = 0xff; priv->cec = i2c_new_dummy(client->adapter, 0x34); if (!priv->cec) return -ENODEV; -- cgit v0.10.2 From 3ae471f73a1d581e078b5b06d08d7b82833a093f Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sat, 25 Jan 2014 18:14:36 +0100 Subject: drm/i2c: tda998x: set the PLL division factor in range 0..3 The predivider division factor of the register PLL_SERIAL_2 is in the range 0..3, the value 0 being used for a division by 1. Tested-by: Russell King Acked-by: Russell King Signed-off-by: Jean-Francois Moine Signed-off-by: Russell King diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c index e871a42..a65250b 100644 --- a/drivers/gpu/drm/i2c/tda998x_drv.c +++ b/drivers/gpu/drm/i2c/tda998x_drv.c @@ -208,7 +208,7 @@ struct tda998x_priv { # define PLL_SERIAL_1_SRL_IZ(x) (((x) & 3) << 1) # define PLL_SERIAL_1_SRL_MAN_IZ (1 << 6) #define REG_PLL_SERIAL_2 REG(0x02, 0x01) /* read/write */ -# define PLL_SERIAL_2_SRL_NOSC(x) (((x) & 3) << 0) +# define PLL_SERIAL_2_SRL_NOSC(x) ((x) << 0) # define PLL_SERIAL_2_SRL_PR(x) (((x) & 0xf) << 4) #define REG_PLL_SERIAL_3 REG(0x02, 0x02) /* read/write */ # define PLL_SERIAL_3_SRL_CCIR (1 << 0) @@ -824,6 +824,11 @@ tda998x_encoder_mode_set(struct drm_encoder *encoder, } div = 148500 / mode->clock; + if (div != 0) { + div--; + if (div > 3) + div = 3; + } /* mute the audio FIFO: */ reg_set(encoder, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_FIFO); -- cgit v0.10.2 From 2e9a3fc3a360ac180f5b4c3c4416a0d0dec60dd8 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sat, 25 Jan 2014 18:14:37 +0100 Subject: drm/i2c: tda998x: fix the ENABLE_SPACE register This patch fixes the ENABLE_SPACE register, the value of which was inverted. Tested-by: Russell King Acked-by: Russell King Signed-off-by: Jean-Francois Moine Signed-off-by: Russell King diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c index a65250b..fa18cf3 100644 --- a/drivers/gpu/drm/i2c/tda998x_drv.c +++ b/drivers/gpu/drm/i2c/tda998x_drv.c @@ -918,7 +918,7 @@ tda998x_encoder_mode_set(struct drm_encoder *encoder, if (priv->rev == TDA19988) { /* let incoming pixels fill the active space (if any) */ - reg_write(encoder, REG_ENABLE_SPACE, 0x01); + reg_write(encoder, REG_ENABLE_SPACE, 0x00); } /* must be last register set: */ -- cgit v0.10.2 From 57789d69c5e7cdfdad6c0f1c54ab17240d800ac2 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Sat, 1 Feb 2014 16:35:42 -0600 Subject: ARM: hisi: fix kconfig warning on HAVE_ARM_TWD Commit "ARM: hisi: don't select SMP" introduced a kconfig warning: warning: (ARCH_HI3xxx) selects HAVE_ARM_TWD which has unmet direct dependencies (SMP) Fix HAVE_ARM_TWD to depend on SMP. Signed-off-by: Rob Herring Signed-off-by: Olof Johansson diff --git a/arch/arm/mach-hisi/Kconfig b/arch/arm/mach-hisi/Kconfig index 8f4649b..1abae5f 100644 --- a/arch/arm/mach-hisi/Kconfig +++ b/arch/arm/mach-hisi/Kconfig @@ -8,7 +8,7 @@ config ARCH_HI3xxx select CLKSRC_OF select GENERIC_CLOCKEVENTS select HAVE_ARM_SCU - select HAVE_ARM_TWD + select HAVE_ARM_TWD if SMP select HAVE_SMP select PINCTRL select PINCTRL_SINGLE -- cgit v0.10.2 From e803d988662ff365c2ed3c2d10a0aad811c1f492 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Sat, 1 Feb 2014 16:35:43 -0600 Subject: ARM: moxart: move DMA_OF selection to driver Move the DMA_OF selection to the DMA driver to fix kconfig warning: warning: (ARCH_MOXART) selects DMA_OF which has unmet direct dependencies (DMADEVICES && OF) Signed-off-by: Rob Herring Signed-off-by: Olof Johansson diff --git a/arch/arm/mach-moxart/Kconfig b/arch/arm/mach-moxart/Kconfig index ba470d6..3795ae2 100644 --- a/arch/arm/mach-moxart/Kconfig +++ b/arch/arm/mach-moxart/Kconfig @@ -2,7 +2,6 @@ config ARCH_MOXART bool "MOXA ART SoC" if ARCH_MULTI_V4T select CPU_FA526 select ARM_DMA_MEM_BUFFERABLE - select DMA_OF select USE_OF select CLKSRC_OF select CLKSRC_MMIO diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 9bed1a2..605b016 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -346,6 +346,7 @@ config MOXART_DMA tristate "MOXART DMA support" depends on ARCH_MOXART select DMA_ENGINE + select DMA_OF select DMA_VIRTUAL_CHANNELS help Enable support for the MOXA ART SoC DMA controller. -- cgit v0.10.2 From 8b7dfa7dc701a27ac8ea4c4dfc0dbc8dce4825de Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Sat, 1 Feb 2014 16:35:44 -0600 Subject: ARM: fix HAVE_ARM_TWD selection for OMAP and shmobile The selection of HAVE_ARM_TWD for OMAP and shmobile depend on LOCAL_TIMER which no longer exists. They should depend on SMP instead. Cc: Tony Lindgren Cc: Simon Horman Cc: Magnus Damm Signed-off-by: Rob Herring Signed-off-by: Olof Johansson diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index 653b489..e2ce4f8 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -54,7 +54,7 @@ config SOC_OMAP5 select ARM_GIC select CPU_V7 select HAVE_ARM_SCU if SMP - select HAVE_ARM_TWD if LOCAL_TIMERS + select HAVE_ARM_TWD if SMP select HAVE_SMP select HAVE_ARM_ARCH_TIMER select ARM_ERRATA_798181 if SMP diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig index 3386406..05fa505 100644 --- a/arch/arm/mach-shmobile/Kconfig +++ b/arch/arm/mach-shmobile/Kconfig @@ -8,7 +8,7 @@ config ARCH_SHMOBILE_MULTI select CPU_V7 select GENERIC_CLOCKEVENTS select HAVE_ARM_SCU if SMP - select HAVE_ARM_TWD if LOCAL_TIMERS + select HAVE_ARM_TWD if SMP select HAVE_SMP select ARM_GIC select MIGHT_HAVE_CACHE_L2X0 -- cgit v0.10.2 From cffcc92e966911e3ea9320fac943f545a353f2e0 Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Thu, 23 Jan 2014 08:50:38 +0200 Subject: gpio: xtensa: fix build when XCHAL_HAVE_CP is 0 In xtensa coprocessors may exist without coprocessor context, i.e. they cannot be disabled/enabled. In this case the RSR_CPENABLE/WSR_CPENABLE are undefined, thus breaking the build. Fix the build by adding dummy versions of enable_cp/disable_cp in this case. Reported-by: Fengguang Wu Signed-off-by: Baruch Siach Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-xtensa.c b/drivers/gpio/gpio-xtensa.c index 1d136ec..7081304 100644 --- a/drivers/gpio/gpio-xtensa.c +++ b/drivers/gpio/gpio-xtensa.c @@ -40,6 +40,8 @@ #error GPIO32 option is not enabled for your xtensa core variant #endif +#if XCHAL_HAVE_CP + static inline unsigned long enable_cp(unsigned long *cpenable) { unsigned long flags; @@ -57,6 +59,20 @@ static inline void disable_cp(unsigned long flags, unsigned long cpenable) local_irq_restore(flags); } +#else + +static inline unsigned long enable_cp(unsigned long *cpenable) +{ + *cpenable = 0; /* avoid uninitialized value warning */ + return 0; +} + +static inline void disable_cp(unsigned long flags, unsigned long cpenable) +{ +} + +#endif /* XCHAL_HAVE_CP */ + static int xtensa_impwire_get_direction(struct gpio_chip *gc, unsigned offset) { return 1; /* input only */ -- cgit v0.10.2 From 375f5fb2e4609b0577778db90e2fc40a2d709cac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20L=C3=B3pez?= Date: Wed, 29 Jan 2014 22:36:38 -0300 Subject: of: add vendor prefix for Allwinner Technology MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have been using the "allwinner" prefix for everything so far; let's document it here. Signed-off-by: Emilio López Signed-off-by: Rob Herring diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 3f900cd..e1d1a22 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -8,6 +8,7 @@ ad Avionic Design GmbH adi Analog Devices, Inc. aeroflexgaisler Aeroflex Gaisler AB ak Asahi Kasei Corp. +allwinner Allwinner Technology Co., Ltd. altr Altera Corp. amcc Applied Micro Circuits Corporation (APM, formally AMCC) amstaos AMS-Taos Inc. -- cgit v0.10.2 From d5f93b8ad01e23d4351cc66c855d09cc5c5cf42c Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Wed, 18 Dec 2013 17:41:16 -0600 Subject: of: Update qcom vendor prefix description Update vendor description to be the full name of the corporate entity that produces the SoCs associated with this prefix. Acked-by: Olof Johansson Signed-off-by: Kumar Gala Signed-off-by: Rob Herring diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index e1d1a22..6f2a022 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -65,7 +65,7 @@ phytec PHYTEC Messtechnik GmbH picochip Picochip Ltd powervr PowerVR (deprecated, use img) qca Qualcomm Atheros, Inc. -qcom Qualcomm, Inc. +qcom Qualcomm Technologies, Inc ralink Mediatek/Ralink Technology Corp. ramtron Ramtron International realtek Realtek Semiconductor Corp. -- cgit v0.10.2 From b2d960e4061986c6aab2269103d61e8408dcc71d Mon Sep 17 00:00:00 2001 From: Marek Belisko Date: Sat, 25 Jan 2014 22:38:44 +0100 Subject: of: add vendor prefix for Honeywell Signed-off-by: Marek Belisko Signed-off-by: Rob Herring diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 6f2a022..ba43b52 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -41,6 +41,7 @@ gmt Global Mixed-mode Technology, Inc. gumstix Gumstix, Inc. haoyu Haoyu Microelectronic Co. Ltd. hisilicon Hisilicon Limited. +honeywell Honeywell hp Hewlett Packard ibm International Business Machines (IBM) idt Integrated Device Technologies, Inc. -- cgit v0.10.2 From b045d37bd68c20ca88123c2b363cac5e3dae815f Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 3 Feb 2014 12:52:14 -0800 Subject: ip_tunnel: fix panic in ip_tunnel_xmit() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Setting rt variable to NULL at the beginning of ip_tunnel_xmit() missed possible use of this variable as a scratch value. Also fixes a possible dst leak in tunnel_dst_check() : If we had to call tunnel_dst_reset(), we forgot to release the reference on dst. Merges tunnel_dst_get()/tunnel_dst_check() into a single tunnel_rtable_get() function for clarity. Many thanks to Tommi for his report and tests. Fixes: 7d442fab0a67 ("ipv4: Cache dst in tunnels") Reported-by: Tommi Rantala Signed-off-by: Eric Dumazet Tested-by: Tommi Rantala Cc: Tom Herbert Cc: Maciej Żenczykowski Signed-off-by: David S. Miller diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index bd28f38..50228be 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c @@ -101,28 +101,22 @@ static void tunnel_dst_reset_all(struct ip_tunnel *t) __tunnel_dst_set(per_cpu_ptr(t->dst_cache, i), NULL); } -static struct dst_entry *tunnel_dst_get(struct ip_tunnel *t) +static struct rtable *tunnel_rtable_get(struct ip_tunnel *t, u32 cookie) { struct dst_entry *dst; rcu_read_lock(); dst = rcu_dereference(this_cpu_ptr(t->dst_cache)->dst); - if (dst) + if (dst) { + if (dst->obsolete && dst->ops->check(dst, cookie) == NULL) { + rcu_read_unlock(); + tunnel_dst_reset(t); + return NULL; + } dst_hold(dst); - rcu_read_unlock(); - return dst; -} - -static struct dst_entry *tunnel_dst_check(struct ip_tunnel *t, u32 cookie) -{ - struct dst_entry *dst = tunnel_dst_get(t); - - if (dst && dst->obsolete && dst->ops->check(dst, cookie) == NULL) { - tunnel_dst_reset(t); - return NULL; } - - return dst; + rcu_read_unlock(); + return (struct rtable *)dst; } /* Often modified stats are per cpu, other are shared (netdev->stats) */ @@ -584,7 +578,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi4 fl4; u8 tos, ttl; __be16 df; - struct rtable *rt = NULL; /* Route to the other host */ + struct rtable *rt; /* Route to the other host */ unsigned int max_headroom; /* The extra header space needed */ __be32 dst; int err; @@ -657,8 +651,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, init_tunnel_flow(&fl4, protocol, dst, tnl_params->saddr, tunnel->parms.o_key, RT_TOS(tos), tunnel->parms.link); - if (connected) - rt = (struct rtable *)tunnel_dst_check(tunnel, 0); + rt = connected ? tunnel_rtable_get(tunnel, 0) : NULL; if (!rt) { rt = ip_route_output_key(tunnel->net, &fl4); -- cgit v0.10.2 From 2a971354e74f3837d14b9c8d7f7983b0c9c330e4 Mon Sep 17 00:00:00 2001 From: Michal Kubecek Date: Thu, 30 Jan 2014 08:50:20 +0100 Subject: ipvs: fix AF assignment in ip_vs_conn_new() If a fwmark is passed to ip_vs_conn_new(), it is passed in vaddr, not daddr. Therefore we should set AF to AF_UNSPEC in vaddr assignment (like we do in ip_vs_ct_in_get()), otherwise we may copy only first 4 bytes of an IPv6 address into cp->daddr. Signed-off-by: Bogdano Arendartchuk Signed-off-by: Michal Kubecek Acked-by: Julian Anastasov Signed-off-by: Simon Horman diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c index 59a1a85..a8eb0a8 100644 --- a/net/netfilter/ipvs/ip_vs_conn.c +++ b/net/netfilter/ipvs/ip_vs_conn.c @@ -871,11 +871,11 @@ ip_vs_conn_new(const struct ip_vs_conn_param *p, cp->protocol = p->protocol; ip_vs_addr_set(p->af, &cp->caddr, p->caddr); cp->cport = p->cport; - ip_vs_addr_set(p->af, &cp->vaddr, p->vaddr); - cp->vport = p->vport; - /* proto should only be IPPROTO_IP if d_addr is a fwmark */ + /* proto should only be IPPROTO_IP if p->vaddr is a fwmark */ ip_vs_addr_set(p->protocol == IPPROTO_IP ? AF_UNSPEC : p->af, - &cp->daddr, daddr); + &cp->vaddr, p->vaddr); + cp->vport = p->vport; + ip_vs_addr_set(p->af, &cp->daddr, daddr); cp->dport = dport; cp->flags = flags; cp->fwmark = fwmark; -- cgit v0.10.2 From d7736ff5be31edaa4fe5ab62810c64529a24b149 Mon Sep 17 00:00:00 2001 From: Michael Holzheu Date: Thu, 30 Jan 2014 16:14:02 +0100 Subject: s390/dump: Fix dump memory detection Dumps created by kdump or zfcpdump can contain invalid memory holes when dumping z/VM systems that have memory pressure. For example: # zgetdump -i /proc/vmcore. Memory map: 0000000000000000 - 0000000000bfffff (12 MB) 0000000000e00000 - 00000000014fffff (7 MB) 000000000bd00000 - 00000000f3bfffff (3711 MB) The memory detection function find_memory_chunks() issues tprot to find valid memory chunks. In case of CMM it can happen that pages are marked as unstable via set_page_unstable() in arch_free_page(). If z/VM has released that pages, tprot returns -EFAULT and indicates a memory hole. So fix this and switch off CMM in case of kdump or zfcpdump. Cc: Signed-off-by: Michael Holzheu Signed-off-by: Martin Schwidefsky diff --git a/arch/s390/mm/page-states.c b/arch/s390/mm/page-states.c index a90d45e..27c50f4 100644 --- a/arch/s390/mm/page-states.c +++ b/arch/s390/mm/page-states.c @@ -12,6 +12,8 @@ #include #include #include +#include +#include #define ESSA_SET_STABLE 1 #define ESSA_SET_UNUSED 2 @@ -41,6 +43,14 @@ void __init cmma_init(void) if (!cmma_flag) return; + /* + * Disable CMM for dump, otherwise the tprot based memory + * detection can fail because of unstable pages. + */ + if (OLDMEM_BASE || ipl_info.type == IPL_TYPE_FCP_DUMP) { + cmma_flag = 0; + return; + } asm volatile( " .insn rrf,0xb9ab0000,%1,%1,0,0\n" "0: la %0,0\n" -- cgit v0.10.2 From e290c3434b70b2eb200f9a54d992b7c4fd938879 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 21 Jan 2014 16:10:09 +0100 Subject: spi: rspi: Document support for Renesas QSPI in Kconfig As of commit 5ce0ba88650f2606244a761d92e2b725f4ab3583 ("spi: rcar: add Renesas QSPI support on RSPI") the rspi driver handles Renesas QSPI, too, but this was not reflected in the Kconfig help text. Signed-off-by: Geert Uytterhoeven Signed-off-by: Mark Brown diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index ba9310b..581ee2a 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -376,10 +376,10 @@ config SPI_PXA2XX_PCI def_tristate SPI_PXA2XX && PCI config SPI_RSPI - tristate "Renesas RSPI controller" + tristate "Renesas RSPI/QSPI controller" depends on (SUPERH && SH_DMAE_BASE) || ARCH_SHMOBILE help - SPI driver for Renesas RSPI blocks. + SPI driver for Renesas RSPI and QSPI blocks. config SPI_S3C24XX tristate "Samsung S3C24XX series SPI" -- cgit v0.10.2 From 89258a97531124cd1e212f7a8ed44fccf8f9a891 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 4 Feb 2014 19:57:38 +0100 Subject: MAINTAINERS: Update drm/i915 git repo Moved to a common location so that Jani also can push to it, to avoid moving it every time I go on vacation. Please update autobuilders and everything else pointing at the drm-intel.git repo, the old one won't be updated any more. Cc: Dave Airlie Cc: Jani Nikula Signed-off-by: Daniel Vetter diff --git a/MAINTAINERS b/MAINTAINERS index 31a0462..e3aaf27 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2832,7 +2832,7 @@ M: Jani Nikula L: intel-gfx@lists.freedesktop.org L: dri-devel@lists.freedesktop.org Q: http://patchwork.freedesktop.org/project/intel-gfx/ -T: git git://people.freedesktop.org/~danvet/drm-intel +T: git git://anongit.freedesktop.org/drm-intel S: Supported F: drivers/gpu/drm/i915/ F: include/drm/i915* -- cgit v0.10.2 From 48b8f6315a6a230f859fcae8ef4a0ccf4f48e802 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 31 Jan 2014 15:49:07 +0200 Subject: drm: add DRM_INFO_ONCE() to print a one-time DRM_INFO() message Just like DRM_INFO(), but only do it once. Signed-off-by: Jani Nikula Reviewed-by: Chris Wilson Acked-by: Dave Airlie Signed-off-by: Daniel Vetter diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 04086c5..04a7f31 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -199,6 +199,9 @@ int drm_err(const char *func, const char *format, ...); #define DRM_INFO(fmt, ...) \ printk(KERN_INFO "[" DRM_NAME "] " fmt, ##__VA_ARGS__) +#define DRM_INFO_ONCE(fmt, ...) \ + printk_once(KERN_INFO "[" DRM_NAME "] " fmt, ##__VA_ARGS__) + /** * Debug output. * -- cgit v0.10.2 From bdde5c6a258a702bdfa7d1f4ae804a7bc405e788 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 31 Jan 2014 15:49:08 +0200 Subject: drm/i915: demote opregion excessive timeout WARN_ONCE to DRM_INFO_ONCE The WARN_ONCE is a bit too verbose, make it a DRM_INFO_ONCE. While at it, add a #define for MAX_DSLP and make the message a bit more informative. v2: use DRM_INFO_ONCE, add MAX_DSLP, pimp the message. Suggested-by: Chris Wilson Signed-off-by: Jani Nikula Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c index 37e9a96..6845960 100644 --- a/drivers/gpu/drm/i915/intel_opregion.c +++ b/drivers/gpu/drm/i915/intel_opregion.c @@ -227,6 +227,8 @@ struct opregion_asle { #define ACPI_DIGITAL_OUTPUT (3<<8) #define ACPI_LVDS_OUTPUT (4<<8) +#define MAX_DSLP 1500 + #ifdef CONFIG_ACPI static int swsci(struct drm_device *dev, u32 function, u32 parm, u32 *parm_out) { @@ -261,10 +263,11 @@ static int swsci(struct drm_device *dev, u32 function, u32 parm, u32 *parm_out) /* The spec says 2ms should be the default, but it's too small * for some machines. */ dslp = 50; - } else if (dslp > 500) { + } else if (dslp > MAX_DSLP) { /* Hey bios, trust must be earned. */ - WARN_ONCE(1, "excessive driver sleep timeout (DSPL) %u\n", dslp); - dslp = 500; + DRM_INFO_ONCE("ACPI BIOS requests an excessive sleep of %u ms, " + "using %u ms instead\n", dslp, MAX_DSLP); + dslp = MAX_DSLP; } /* The spec tells us to do this, but we are the only user... */ -- cgit v0.10.2 From 2fa4cb905605c863bf570027233af7afd8149ae4 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Tue, 28 Jan 2014 09:14:48 +0100 Subject: ath9k_htc: make ->sta_rc_update atomic for most calls sta_rc_update() callback must be atomic, hence we can not take mutexes or do other operations, which can sleep in ath9k_htc_sta_rc_update(). I think we can just return from ath9k_htc_sta_rc_update(), if it is called without IEEE80211_RC_SUPP_RATES_CHANGED bit. That will help with scheduling while atomic bug for most cases (except mesh and IBSS modes). For mesh and IBSS I do not see other solution like creating additional workqueue, because sending firmware command require us to sleep, but this can be done in additional patch. Patch partially fixes bug: https://bugzilla.redhat.com/show_bug.cgi?id=990955 Cc: stable@vger.kernel.org Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 608d739..a57af9b 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -1315,21 +1315,22 @@ static void ath9k_htc_sta_rc_update(struct ieee80211_hw *hw, struct ath_common *common = ath9k_hw_common(priv->ah); struct ath9k_htc_target_rate trate; + if (!(changed & IEEE80211_RC_SUPP_RATES_CHANGED)) + return; + mutex_lock(&priv->mutex); ath9k_htc_ps_wakeup(priv); - if (changed & IEEE80211_RC_SUPP_RATES_CHANGED) { - memset(&trate, 0, sizeof(struct ath9k_htc_target_rate)); - ath9k_htc_setup_rate(priv, sta, &trate); - if (!ath9k_htc_send_rate_cmd(priv, &trate)) - ath_dbg(common, CONFIG, - "Supported rates for sta: %pM updated, rate caps: 0x%X\n", - sta->addr, be32_to_cpu(trate.capflags)); - else - ath_dbg(common, CONFIG, - "Unable to update supported rates for sta: %pM\n", - sta->addr); - } + memset(&trate, 0, sizeof(struct ath9k_htc_target_rate)); + ath9k_htc_setup_rate(priv, sta, &trate); + if (!ath9k_htc_send_rate_cmd(priv, &trate)) + ath_dbg(common, CONFIG, + "Supported rates for sta: %pM updated, rate caps: 0x%X\n", + sta->addr, be32_to_cpu(trate.capflags)); + else + ath_dbg(common, CONFIG, + "Unable to update supported rates for sta: %pM\n", + sta->addr); ath9k_htc_ps_restore(priv); mutex_unlock(&priv->mutex); -- cgit v0.10.2 From 58e33a219298c5ba0f88ce9a7d0f448eb3ae884a Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 29 Jan 2014 17:42:37 +0100 Subject: rt2800: disable PS by default on USB We have disabled it currently on other buses. PS can cause some issues, not necessarily with our driver but on AP, that are not easy to debug. Since behaviour differs on rt2800usb and rt2800pci, user usually blame for malfunction rt2800usb driver, whereas issue is on AP side. Signed-off-by: Stanislaw Gruszka Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index b8f5b06..7f8b5d1 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -7458,10 +7458,9 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) u32 reg; /* - * Disable powersaving as default on PCI devices. + * Disable powersaving as default. */ - if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev)) - rt2x00dev->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; + rt2x00dev->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; /* * Initialize all hw fields. -- cgit v0.10.2 From 8b0df00fe650197ac47c42ba71b2588334a529be Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 29 Jan 2014 17:54:17 +0100 Subject: rt2500: disable PS by default It is know that PS cause issues on that old devices, disable it by default. Signed-off-by: Stanislaw Gruszka Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index abc5f56..2f1cd92 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1877,6 +1877,11 @@ static int rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) EEPROM_MAC_ADDR_0)); /* + * Disable powersaving as default. + */ + rt2x00dev->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; + + /* * Initialize hw_mode information. */ spec->supported_bands = SUPPORT_BAND_2GHZ; diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 9f16824..d849d59 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1706,6 +1706,11 @@ static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_PS_NULLFUNC_STACK; + /* + * Disable powersaving as default. + */ + rt2x00dev->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; + SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev); SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, rt2x00_eeprom_addr(rt2x00dev, -- cgit v0.10.2 From 6bca610d97b6139a1d7598b8009da9d339daa50f Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Thu, 30 Jan 2014 09:14:53 +0100 Subject: ath9k_htc: Do not support PowerSave by default It is a copy/paste of patch provided by Sujith for ath9k. "Even though we make sure PowerSave is not enabled by default by disabling the flag, WIPHY_FLAG_PS_ON_BY_DEFAULT on init, PS could be enabled by userspace based on various factors like battery usage etc. Since PS in ath9k is just broken and has been untested for years, remove support for it, but allow a user to explicitly enable it using a module parameter." Cc: stable@vger.kernel.org Signed-off-by: Oleksij Rempel Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index f4e1de2..c57d6b8 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -34,6 +34,10 @@ static int ath9k_htc_btcoex_enable; module_param_named(btcoex_enable, ath9k_htc_btcoex_enable, int, 0444); MODULE_PARM_DESC(btcoex_enable, "Enable wifi-BT coexistence"); +static int ath9k_ps_enable; +module_param_named(ps_enable, ath9k_ps_enable, int, 0444); +MODULE_PARM_DESC(ps_enable, "Enable WLAN PowerSave"); + #define CHAN2G(_freq, _idx) { \ .center_freq = (_freq), \ .hw_value = (_idx), \ @@ -725,12 +729,14 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, IEEE80211_HW_SPECTRUM_MGMT | IEEE80211_HW_HAS_RATE_CONTROL | IEEE80211_HW_RX_INCLUDES_FCS | - IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_PS_NULLFUNC_STACK | IEEE80211_HW_REPORTS_TX_ACK_STATUS | IEEE80211_HW_MFP_CAPABLE | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING; + if (ath9k_ps_enable) + hw->flags |= IEEE80211_HW_SUPPORTS_PS; + hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC) | -- cgit v0.10.2 From 4fcfc7443d072582b5047b8b391d711590e5645c Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Sun, 2 Feb 2014 10:55:18 +0100 Subject: ar5523: fix usb id for Gigaset. Raw id and FW id should be switched. Tested-by: Oleksij Rempel Signed-off-by: Oleksij Rempel Cc: stable@vger.kernel.org Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ar5523/ar5523.c b/drivers/net/wireless/ath/ar5523/ar5523.c index 8aa20df..507d9a9 100644 --- a/drivers/net/wireless/ath/ar5523/ar5523.c +++ b/drivers/net/wireless/ath/ar5523/ar5523.c @@ -1764,7 +1764,7 @@ static struct usb_device_id ar5523_id_table[] = { AR5523_DEVICE_UG(0x07d1, 0x3a07), /* D-Link / WUA-2340 rev A1 */ AR5523_DEVICE_UG(0x1690, 0x0712), /* Gigaset / AR5523 */ AR5523_DEVICE_UG(0x1690, 0x0710), /* Gigaset / SMCWUSBTG */ - AR5523_DEVICE_UG(0x129b, 0x160c), /* Gigaset / USB stick 108 + AR5523_DEVICE_UG(0x129b, 0x160b), /* Gigaset / USB stick 108 (CyberTAN Technology) */ AR5523_DEVICE_UG(0x16ab, 0x7801), /* Globalsun / AR5523_1 */ AR5523_DEVICE_UX(0x16ab, 0x7811), /* Globalsun / AR5523_2 */ -- cgit v0.10.2 From a243de48558397f438e299178cac29f6da8fc0ce Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Mon, 3 Feb 2014 11:45:51 +0100 Subject: ath9k_htc: avoid scheduling while atomic on sta_rc_update mac80211 ->sta_rc_update() callback must be atomic. Since we have to take mutex and do other operations that can sleep when sending fimrware commands to device, the only option to satisfy atomicity requirement of ->sta_rc_update(), that I can see, is introduce work_struct and defer uploading new rates to that work. Tested-by: Oleksij Rempel Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 58da346..99a2031 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -262,6 +262,8 @@ enum tid_aggr_state { struct ath9k_htc_sta { u8 index; enum tid_aggr_state tid_state[ATH9K_HTC_MAX_TID]; + struct work_struct rc_update_work; + struct ath9k_htc_priv *htc_priv; }; #define ATH9K_HTC_RXBUF 256 diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index a57af9b..c9254a6 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -1270,18 +1270,50 @@ static void ath9k_htc_configure_filter(struct ieee80211_hw *hw, mutex_unlock(&priv->mutex); } +static void ath9k_htc_sta_rc_update_work(struct work_struct *work) +{ + struct ath9k_htc_sta *ista = + container_of(work, struct ath9k_htc_sta, rc_update_work); + struct ieee80211_sta *sta = + container_of((void *)ista, struct ieee80211_sta, drv_priv); + struct ath9k_htc_priv *priv = ista->htc_priv; + struct ath_common *common = ath9k_hw_common(priv->ah); + struct ath9k_htc_target_rate trate; + + mutex_lock(&priv->mutex); + ath9k_htc_ps_wakeup(priv); + + memset(&trate, 0, sizeof(struct ath9k_htc_target_rate)); + ath9k_htc_setup_rate(priv, sta, &trate); + if (!ath9k_htc_send_rate_cmd(priv, &trate)) + ath_dbg(common, CONFIG, + "Supported rates for sta: %pM updated, rate caps: 0x%X\n", + sta->addr, be32_to_cpu(trate.capflags)); + else + ath_dbg(common, CONFIG, + "Unable to update supported rates for sta: %pM\n", + sta->addr); + + ath9k_htc_ps_restore(priv); + mutex_unlock(&priv->mutex); +} + static int ath9k_htc_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { struct ath9k_htc_priv *priv = hw->priv; + struct ath9k_htc_sta *ista = (struct ath9k_htc_sta *) sta->drv_priv; int ret; mutex_lock(&priv->mutex); ath9k_htc_ps_wakeup(priv); ret = ath9k_htc_add_station(priv, vif, sta); - if (!ret) + if (!ret) { + INIT_WORK(&ista->rc_update_work, ath9k_htc_sta_rc_update_work); + ista->htc_priv = priv; ath9k_htc_init_rate(priv, sta); + } ath9k_htc_ps_restore(priv); mutex_unlock(&priv->mutex); @@ -1293,12 +1325,13 @@ static int ath9k_htc_sta_remove(struct ieee80211_hw *hw, struct ieee80211_sta *sta) { struct ath9k_htc_priv *priv = hw->priv; - struct ath9k_htc_sta *ista; + struct ath9k_htc_sta *ista = (struct ath9k_htc_sta *) sta->drv_priv; int ret; + cancel_work_sync(&ista->rc_update_work); + mutex_lock(&priv->mutex); ath9k_htc_ps_wakeup(priv); - ista = (struct ath9k_htc_sta *) sta->drv_priv; htc_sta_drain(priv->htc, ista->index); ret = ath9k_htc_remove_station(priv, vif, sta); ath9k_htc_ps_restore(priv); @@ -1311,29 +1344,12 @@ static void ath9k_htc_sta_rc_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, u32 changed) { - struct ath9k_htc_priv *priv = hw->priv; - struct ath_common *common = ath9k_hw_common(priv->ah); - struct ath9k_htc_target_rate trate; + struct ath9k_htc_sta *ista = (struct ath9k_htc_sta *) sta->drv_priv; if (!(changed & IEEE80211_RC_SUPP_RATES_CHANGED)) return; - mutex_lock(&priv->mutex); - ath9k_htc_ps_wakeup(priv); - - memset(&trate, 0, sizeof(struct ath9k_htc_target_rate)); - ath9k_htc_setup_rate(priv, sta, &trate); - if (!ath9k_htc_send_rate_cmd(priv, &trate)) - ath_dbg(common, CONFIG, - "Supported rates for sta: %pM updated, rate caps: 0x%X\n", - sta->addr, be32_to_cpu(trate.capflags)); - else - ath_dbg(common, CONFIG, - "Unable to update supported rates for sta: %pM\n", - sta->addr); - - ath9k_htc_ps_restore(priv); - mutex_unlock(&priv->mutex); + schedule_work(&ista->rc_update_work); } static int ath9k_htc_conf_tx(struct ieee80211_hw *hw, -- cgit v0.10.2 From 3683a07b29d2bddebb903f1400860c77d8e423f3 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 4 Feb 2014 08:37:52 +0530 Subject: ath9k: Fix build error on ARM Use mdelay instead of udelay to fix this error: ERROR: "__bad_udelay" [drivers/net/wireless/ath/ath9k/ath9k_hw.ko] undefined! make[1]: *** [__modpost] Error 1 make: *** [modules] Error 2 Reported-by: Josh Boyer Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index fbf43c0..11eab9f 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1316,7 +1316,7 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type) if (AR_SREV_9300_20_OR_LATER(ah)) udelay(50); else if (AR_SREV_9100(ah)) - udelay(10000); + mdelay(10); else udelay(100); @@ -2051,9 +2051,8 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah) REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN); - if (AR_SREV_9100(ah)) - udelay(10000); + mdelay(10); else udelay(50); -- cgit v0.10.2 From 8298383c2cd5a6d0639f1bb1781fba181bd20154 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 4 Feb 2014 08:37:53 +0530 Subject: ath9k: Do not support PowerSave by default Even though we make sure PowerSave is not enabled by default by disabling the flag, WIPHY_FLAG_PS_ON_BY_DEFAULT on init, PS could be enabled by userspace based on various factors like battery usage etc. Since PS in ath9k is just broken and has been untested for years, remove support for it, but allow a user to explicitly enable it using a module parameter. Cc: stable@vger.kernel.org Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index c36de30..1fc2e5a 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -57,6 +57,10 @@ static int ath9k_bt_ant_diversity; module_param_named(bt_ant_diversity, ath9k_bt_ant_diversity, int, 0444); MODULE_PARM_DESC(bt_ant_diversity, "Enable WLAN/BT RX antenna diversity"); +static int ath9k_ps_enable; +module_param_named(ps_enable, ath9k_ps_enable, int, 0444); +MODULE_PARM_DESC(ps_enable, "Enable WLAN PowerSave"); + bool is_ath9k_unloaded; /* We use the hw_value as an index into our private channel structure */ @@ -903,13 +907,15 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_PS_NULLFUNC_STACK | IEEE80211_HW_SPECTRUM_MGMT | IEEE80211_HW_REPORTS_TX_ACK_STATUS | IEEE80211_HW_SUPPORTS_RC_TABLE | IEEE80211_HW_SUPPORTS_HT_CCK_RATES; + if (ath9k_ps_enable) + hw->flags |= IEEE80211_HW_SUPPORTS_PS; + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) { hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION; -- cgit v0.10.2 From 4cfe9a8d58292dc8e32a8093a95187d47507d394 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 4 Feb 2014 08:37:54 +0530 Subject: ath9k: Fix TX power calculation The commit, "ath9k_hw: Fix incorrect Tx control power in AR9003 template" fixed the incorrect values in the eeprom templates, but if boards have already been calibrated with incorrect values, they would still be using the wrong TX power. Fix this by assigning a default value in such cases. Cc: Rajkumar Manoharan Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 25243cb..b8daff7 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -5065,6 +5065,10 @@ static u16 ar9003_hw_get_max_edge_power(struct ar9300_eeprom *eep, break; } } + + if (is2GHz && !twiceMaxEdgePower) + twiceMaxEdgePower = 60; + return twiceMaxEdgePower; } -- cgit v0.10.2 From f7db1588d6028c97c098bb6445eaabc56a25fed8 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 20 Jan 2014 23:22:07 +0800 Subject: spi: nuc900: Set SPI_LSB_FIRST for master->mode_bits if hw->pdata->lsb is true Otherwise, spi_setup() fails with unsupported mode bits message. Signed-off-by: Axel Lin Signed-off-by: Mark Brown Cc: stable@vger.kernel.org diff --git a/drivers/spi/spi-nuc900.c b/drivers/spi/spi-nuc900.c index 5040630..bae97ff 100644 --- a/drivers/spi/spi-nuc900.c +++ b/drivers/spi/spi-nuc900.c @@ -361,6 +361,8 @@ static int nuc900_spi_probe(struct platform_device *pdev) init_completion(&hw->done); master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; + if (hw->pdata->lsb) + master->mode_bits |= SPI_LSB_FIRST; master->num_chipselect = hw->pdata->num_cs; master->bus_num = hw->pdata->bus_num; hw->bitbang.master = hw->master; -- cgit v0.10.2 From 861e0f5bae1c4f4026b58ca10fa3b0fc02f1540c Mon Sep 17 00:00:00 2001 From: Andre Heider Date: Tue, 4 Feb 2014 21:27:44 +0100 Subject: usb: dwc2: bail out early when booting with "nousb" Add usb_disabled() check to prevent kernel oops when booting with "nousb" in the cmdline: Unable to handle kernel NULL pointer dereference at virtual address 00000030 ... PC is at bus_add_device+0xe0/0x18c LR is at device_add_groups+0x1c/0x20 ... [] (bus_add_device) from [] (device_add+0x41c/0x538) [] (device_add) from [] (usb_new_device+0x270/0x35c) [] (usb_new_device) from [] (usb_add_hcd+0x4fc/0x760) [] (usb_add_hcd) from [] (dwc2_hcd_init+0x434/0x510) [] (dwc2_hcd_init) from [] (dwc2_driver_probe+0x130/0x170) [] (dwc2_driver_probe) from [] (platform_drv_probe+0x28/0x58) Signed-off-by: Andre Heider Acked-by: Paul Zimmerman Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c index d01d0d3..eaba547 100644 --- a/drivers/usb/dwc2/platform.c +++ b/drivers/usb/dwc2/platform.c @@ -124,6 +124,9 @@ static int dwc2_driver_probe(struct platform_device *dev) int retval; int irq; + if (usb_disabled()) + return -ENODEV; + match = of_match_device(dwc2_of_match_table, &dev->dev); if (match && match->data) { params = match->data; -- cgit v0.10.2 From a23666c49938bba08df3654fc66cd051587f7673 Mon Sep 17 00:00:00 2001 From: Paul Zimmerman Date: Tue, 4 Feb 2014 11:42:15 -0800 Subject: usb: dwc2: fix role switch breakage Commit beb7e592bc "staging: dwc2: add check on dwc2_core_reset return" broke the B -> A role switching on OTG-enabled platforms. This commit fixes it. Reported-by: Dinh Nguyen Tested-by: Dinh Nguyen Signed-off-by: Paul Zimmerman Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c index 8565d87..1d12988 100644 --- a/drivers/usb/dwc2/core.c +++ b/drivers/usb/dwc2/core.c @@ -216,7 +216,7 @@ static int dwc2_hs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) int retval = 0; if (!select_phy) - return -ENODEV; + return 0; usbcfg = readl(hsotg->regs + GUSBCFG); -- cgit v0.10.2 From 51b1b6491752ac066ee8d32cc66042fcc955fef6 Mon Sep 17 00:00:00 2001 From: Paul Zimmerman Date: Tue, 4 Feb 2014 11:21:24 -0800 Subject: usb: dwc2: fix memory corruption in dwc2 driver The move from the staging tree to the main tree exposed a longstanding memory corruption bug in the dwc2 driver. The reordering of the driver initialization caused the dwc2 driver to corrupt the initialization data of the sdhci driver on the Raspberry Pi platform, which made the bug show up. The error is in calling to_usb_device(hsotg->dev), since ->dev is not a member of struct usb_device. The easiest fix is to just remove the offending code, since it is not really needed. Thanks to Stephen Warren for tracking down the cause of this. Reported-by: Andre Heider Tested-by: Stephen Warren Signed-off-by: Paul Zimmerman Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c index f59484d..4d918ed 100644 --- a/drivers/usb/dwc2/hcd.c +++ b/drivers/usb/dwc2/hcd.c @@ -2565,25 +2565,14 @@ static void _dwc2_hcd_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep) { struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); - int is_control = usb_endpoint_xfer_control(&ep->desc); - int is_out = usb_endpoint_dir_out(&ep->desc); - int epnum = usb_endpoint_num(&ep->desc); - struct usb_device *udev; unsigned long flags; dev_dbg(hsotg->dev, "DWC OTG HCD EP RESET: bEndpointAddress=0x%02x\n", ep->desc.bEndpointAddress); - udev = to_usb_device(hsotg->dev); - spin_lock_irqsave(&hsotg->lock, flags); - - usb_settoggle(udev, epnum, is_out, 0); - if (is_control) - usb_settoggle(udev, epnum, !is_out, 0); dwc2_hcd_endpoint_reset(hsotg, ep); - spin_unlock_irqrestore(&hsotg->lock, flags); } -- cgit v0.10.2 From 67847baee056892dc35efb9c3fd05ae7f075588c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Tue, 14 Jan 2014 18:56:54 +0100 Subject: usb: ftdi_sio: add Mindstorms EV3 console adapter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: stable Signed-off-by: Bjørn Mork Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index ce0d7b0..0f3248a 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -152,6 +152,7 @@ static const struct usb_device_id id_table_combined[] = { { USB_DEVICE(FTDI_VID, FTDI_CANUSB_PID) }, { USB_DEVICE(FTDI_VID, FTDI_CANDAPTER_PID) }, { USB_DEVICE(FTDI_VID, FTDI_NXTCAM_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_EV3CON_PID) }, { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_0_PID) }, { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_1_PID) }, { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_2_PID) }, diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index a7019d1..eb03021 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -50,6 +50,7 @@ #define TI_XDS100V2_PID 0xa6d0 #define FTDI_NXTCAM_PID 0xABB8 /* NXTCam for Mindstorms NXT */ +#define FTDI_EV3CON_PID 0xABB9 /* Mindstorms EV3 Console Adapter */ /* US Interface Navigator (http://www.usinterface.com/) */ #define FTDI_USINT_CAT_PID 0xb810 /* Navigator CAT and 2nd PTT lines */ -- cgit v0.10.2 From e9d123a50b30f2b7b487d46df8820c3ae1d589ff Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 28 Jan 2014 09:53:50 -0500 Subject: usb: phy: move some error messages to debug the PHY layer is supposed to be optional, considering some PHY have no control bus for SW to poke around. After commit 1ae5799 (usb: hcd: Initialize USB phy if needed) any HCD which didn't provide a PHY driver would emit annoying error messages. In this patch we're decreasing those messages to debugging only and we also add a PHY prefix or use dev_dbg so we know where they're coming from. Reported-by: Josh Boyer Signed-off-by: Felipe Balbi Signed-off-by: Josh Boyer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/phy/phy.c b/drivers/usb/phy/phy.c index e6f61e4..8afa813 100644 --- a/drivers/usb/phy/phy.c +++ b/drivers/usb/phy/phy.c @@ -130,7 +130,7 @@ struct usb_phy *usb_get_phy(enum usb_phy_type type) phy = __usb_find_phy(&phy_list, type); if (IS_ERR(phy) || !try_module_get(phy->dev->driver->owner)) { - pr_err("unable to find transceiver of type %s\n", + pr_debug("PHY: unable to find transceiver of type %s\n", usb_phy_type_string(type)); goto err0; } @@ -228,7 +228,7 @@ struct usb_phy *usb_get_phy_dev(struct device *dev, u8 index) phy = __usb_find_phy_dev(dev, &phy_bind_list, index); if (IS_ERR(phy) || !try_module_get(phy->dev->driver->owner)) { - pr_err("unable to find transceiver\n"); + dev_dbg(dev, "unable to find transceiver\n"); goto err0; } @@ -424,10 +424,8 @@ int usb_bind_phy(const char *dev_name, u8 index, unsigned long flags; phy_bind = kzalloc(sizeof(*phy_bind), GFP_KERNEL); - if (!phy_bind) { - pr_err("phy_bind(): No memory for phy_bind"); + if (!phy_bind) return -ENOMEM; - } phy_bind->dev_name = dev_name; phy_bind->phy_dev_name = phy_dev_name; -- cgit v0.10.2 From a9c143c82608bee2a36410caa56d82cd86bdc7fa Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 30 Jan 2014 10:20:29 -0500 Subject: usb-storage: restrict bcdDevice range for Super Top in Cypress ATACB The Cypress ATACB unusual-devs entry for the Super Top SATA bridge causes problems. Although it was originally reported only for bcdDevice = 0x160, its range was much larger. This resulted in a bug report for bcdDevice 0x220, so the range was capped at 0x219. Now Milan reports errors with bcdDevice 0x150. Therefore this patch restricts the range to just 0x160. Signed-off-by: Alan Stern Reported-and-tested-by: Milan Svoboda CC: Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/storage/unusual_cypress.h b/drivers/usb/storage/unusual_cypress.h index 65a6a75..82e8ed0 100644 --- a/drivers/usb/storage/unusual_cypress.h +++ b/drivers/usb/storage/unusual_cypress.h @@ -31,7 +31,7 @@ UNUSUAL_DEV( 0x04b4, 0x6831, 0x0000, 0x9999, "Cypress ISD-300LP", USB_SC_CYP_ATACB, USB_PR_DEVICE, NULL, 0), -UNUSUAL_DEV( 0x14cd, 0x6116, 0x0000, 0x0219, +UNUSUAL_DEV( 0x14cd, 0x6116, 0x0160, 0x0160, "Super Top", "USB 2.0 SATA BRIDGE", USB_SC_CYP_ATACB, USB_PR_DEVICE, NULL, 0), -- cgit v0.10.2 From c5637e5119c43452a00e27c274356b072263ecbb Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 21 Jan 2014 10:38:45 -0500 Subject: usb-storage: add unusual-devs entry for BlackBerry 9000 This patch adds an unusual-devs entry for the BlackBerry 9000. This fixes Bugzilla #22442. Signed-off-by: Alan Stern Reported-by: Moritz Moeller-Herrmann Tested-by: Moritz Moeller-Herrmann Cc: stable Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index ad06255..adbeb25 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1455,6 +1455,13 @@ UNUSUAL_DEV( 0x0f88, 0x042e, 0x0100, 0x0100, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_CAPACITY ), +/* Reported by Moritz Moeller-Herrmann */ +UNUSUAL_DEV( 0x0fca, 0x8004, 0x0201, 0x0201, + "Research In Motion", + "BlackBerry Bold 9000", + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_MAX_SECTORS_64 ), + /* Reported by Michael Stattmann */ UNUSUAL_DEV( 0x0fce, 0xd008, 0x0000, 0x0000, "Sony Ericsson", -- cgit v0.10.2 From 2240c365108adbc4100a55654a5707e8e877a401 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3f=20Ralovich?= Date: Fri, 24 Jan 2014 12:18:35 +0100 Subject: USB: simple: add Dynastream ANT USB-m Stick device support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for ANT USB-m Stick from Dynastream Innovations, by listing USB pid [34366.944805] usb 6-1: New USB device found, idVendor=0fcf, idProduct=1009 [34366.944817] usb 6-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3 [34366.944824] usb 6-1: Product: ANT USB-m Stick [34366.944831] usb 6-1: Manufacturer: Dynastream Innovations Device reported (https://code.google.com/p/antpm/issues/detail?id=5) to work through: $ modprobe usbserial vendor=0x0fcf product=0x1009 Signed-off-by: Kristóf Ralovich Signed-off-by: Johan Hovold Cc: stable Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/usb-serial-simple.c b/drivers/usb/serial/usb-serial-simple.c index f112b07..fb79775 100644 --- a/drivers/usb/serial/usb-serial-simple.c +++ b/drivers/usb/serial/usb-serial-simple.c @@ -71,7 +71,8 @@ DEVICE(hp4x, HP4X_IDS); /* Suunto ANT+ USB Driver */ #define SUUNTO_IDS() \ - { USB_DEVICE(0x0fcf, 0x1008) } + { USB_DEVICE(0x0fcf, 0x1008) }, \ + { USB_DEVICE(0x0fcf, 0x1009) } /* Dynastream ANT USB-m Stick */ DEVICE(suunto, SUUNTO_IDS); /* Siemens USB/MPI adapter */ -- cgit v0.10.2 From 823d12c95c666fa7ab7dad208d735f6bc6afabdc Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 30 Jan 2014 10:43:22 -0500 Subject: usb-storage: enable multi-LUN scanning when needed People sometimes create their own custom-configured kernels and forget to enable CONFIG_SCSI_MULTI_LUN. This causes problems when they plug in a USB storage device (such as a card reader) with more than one LUN. Fortunately, we can tell fairly easily when a storage device claims to have more than one LUN. When that happens, this patch asks the SCSI layer to probe all the LUNs automatically, regardless of the config setting. The patch also updates the Kconfig help text for usb-storage, explaining that CONFIG_SCSI_MULTI_LUN may be necessary. Signed-off-by: Alan Stern Reported-by: Thomas Raschbacher CC: Matthew Dharm CC: James Bottomley Cc: stable Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index 8470e1b..1dd0604 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -18,7 +18,9 @@ config USB_STORAGE This option depends on 'SCSI' support being enabled, but you probably also need 'SCSI device support: SCSI disk support' - (BLK_DEV_SD) for most USB storage devices. + (BLK_DEV_SD) for most USB storage devices. Some devices also + will require 'Probe all LUNs on each SCSI device' + (SCSI_MULTI_LUN). To compile this driver as a module, choose M here: the module will be called usb-storage. diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index 18509e6..9d38ddc 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c @@ -78,6 +78,8 @@ static const char* host_info(struct Scsi_Host *host) static int slave_alloc (struct scsi_device *sdev) { + struct us_data *us = host_to_us(sdev->host); + /* * Set the INQUIRY transfer length to 36. We don't use any of * the extra data and many devices choke if asked for more or @@ -102,6 +104,10 @@ static int slave_alloc (struct scsi_device *sdev) */ blk_queue_update_dma_alignment(sdev->request_queue, (512 - 1)); + /* Tell the SCSI layer if we know there is more than one LUN */ + if (us->protocol == USB_PR_BULK && us->max_lun > 0) + sdev->sdev_bflags |= BLIST_FORCELUN; + return 0; } -- cgit v0.10.2 From 1877db75589a895bbdc4c4c3f23558e57b521141 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 5 Feb 2014 12:17:01 +1100 Subject: md/raid1: restore ability for check and repair to fix read errors. commit 30bc9b53878a9921b02e3b5bc4283ac1c6de102a md/raid1: fix bio handling problems in process_checks() Move the bio_reset() to a point before where BIO_UPTODATE is checked, so that check now always report that the bio is uptodate, even if it is not. This causes process_check() to sometimes treat read-errors as successful matches so the good data isn't written out. This patch preserves the flag until it is needed. Bug was introduced in 3.11, but backported to 3.10-stable (as it fixed an even worse bug). So suitable for any -stable since 3.10. Reported-and-tested-by: Michael Tokarev Cc: stable@vger.kernel.org (3.10+) Fixed: 30bc9b53878a9921b02e3b5bc4283ac1c6de102a Signed-off-by: NeilBrown diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index fd3a2a1..4a6ca1c 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -1953,11 +1953,15 @@ static int process_checks(struct r1bio *r1_bio) for (i = 0; i < conf->raid_disks * 2; i++) { int j; int size; + int uptodate; struct bio *b = r1_bio->bios[i]; if (b->bi_end_io != end_sync_read) continue; - /* fixup the bio for reuse */ + /* fixup the bio for reuse, but preserve BIO_UPTODATE */ + uptodate = test_bit(BIO_UPTODATE, &b->bi_flags); bio_reset(b); + if (!uptodate) + clear_bit(BIO_UPTODATE, &b->bi_flags); b->bi_vcnt = vcnt; b->bi_iter.bi_size = r1_bio->sectors << 9; b->bi_iter.bi_sector = r1_bio->sector + @@ -1990,11 +1994,14 @@ static int process_checks(struct r1bio *r1_bio) int j; struct bio *pbio = r1_bio->bios[primary]; struct bio *sbio = r1_bio->bios[i]; + int uptodate = test_bit(BIO_UPTODATE, &sbio->bi_flags); if (sbio->bi_end_io != end_sync_read) continue; + /* Now we can 'fixup' the BIO_UPTODATE flag */ + set_bit(BIO_UPTODATE, &sbio->bi_flags); - if (test_bit(BIO_UPTODATE, &sbio->bi_flags)) { + if (uptodate) { for (j = vcnt; j-- ; ) { struct page *p, *s; p = pbio->bi_io_vec[j].bv_page; @@ -2009,7 +2016,7 @@ static int process_checks(struct r1bio *r1_bio) if (j >= 0) atomic64_add(r1_bio->sectors, &mddev->resync_mismatches); if (j < 0 || (test_bit(MD_RECOVERY_CHECK, &mddev->recovery) - && test_bit(BIO_UPTODATE, &sbio->bi_flags))) { + && uptodate)) { /* No need to write to this device. */ sbio->bi_end_io = NULL; rdev_dec_pending(conf->mirrors[i].rdev, mddev); -- cgit v0.10.2 From 00503b6f702eaf23e7257d6287da72805d7d014c Mon Sep 17 00:00:00 2001 From: dingtianhong Date: Sat, 25 Jan 2014 13:00:29 +0800 Subject: bonding: fail_over_mac should only affect AB mode at enslave and removal processing According to bonding.txt, the fail_over_ma should only affect active-backup mode, but I found that the fail_over_mac could be set to active or follow in all modes, this will cause new slave could not be set to bond's MAC address at enslave processing and restore its own MAC address at removal processing. The correct way to fix the problem is that we should not add restrictions when setting options, just need to modify the bond enslave and removal processing to check the mode in addition to fail_over_mac when setting a slave's MAC during enslavement. The change active slave processing already only calls the fail_over_mac function when in active-backup mode. Thanks for Jay's suggestion. The patch also modify the pr_warning() to pr_warn(). Cc: Jay Vosburgh Cc: Veaceslav Falico Cc: Andy Gospodarek Signed-off-by: Ding Tianhong Signed-off-by: David S. Miller diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 4c08018..8e6dd13 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1270,9 +1270,13 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) if (slave_ops->ndo_set_mac_address == NULL) { if (!bond_has_slaves(bond)) { - pr_warning("%s: Warning: The first slave device specified does not support setting the MAC address. Setting fail_over_mac to active.", - bond_dev->name); - bond->params.fail_over_mac = BOND_FOM_ACTIVE; + pr_warn("%s: Warning: The first slave device specified does not support setting the MAC address.\n", + bond_dev->name); + if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) { + bond->params.fail_over_mac = BOND_FOM_ACTIVE; + pr_warn("%s: Setting fail_over_mac to active for active-backup mode.\n", + bond_dev->name); + } } else if (bond->params.fail_over_mac != BOND_FOM_ACTIVE) { pr_err("%s: Error: The slave device specified does not support setting the MAC address, but fail_over_mac is not set to active.\n", bond_dev->name); @@ -1315,7 +1319,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) */ memcpy(new_slave->perm_hwaddr, slave_dev->dev_addr, ETH_ALEN); - if (!bond->params.fail_over_mac) { + if (!bond->params.fail_over_mac || + bond->params.mode != BOND_MODE_ACTIVEBACKUP) { /* * Set slave to master's mac address. The application already * set the master's mac address to that of the first slave @@ -1579,7 +1584,8 @@ err_close: dev_close(slave_dev); err_restore_mac: - if (!bond->params.fail_over_mac) { + if (!bond->params.fail_over_mac || + bond->params.mode != BOND_MODE_ACTIVEBACKUP) { /* XXX TODO - fom follow mode needs to change master's * MAC if this slave's MAC is in use by the bond, or at * least print a warning. @@ -1672,7 +1678,8 @@ static int __bond_release_one(struct net_device *bond_dev, bond->current_arp_slave = NULL; - if (!all && !bond->params.fail_over_mac) { + if (!all && (!bond->params.fail_over_mac || + bond->params.mode != BOND_MODE_ACTIVEBACKUP)) { if (ether_addr_equal_64bits(bond_dev->dev_addr, slave->perm_hwaddr) && bond_has_slaves(bond)) pr_warn("%s: Warning: the permanent HWaddr of %s - %pM - is still in use by %s. Set the HWaddr of %s to a different address to avoid conflicts.\n", @@ -1769,7 +1776,8 @@ static int __bond_release_one(struct net_device *bond_dev, /* close slave before restoring its mac address */ dev_close(slave_dev); - if (bond->params.fail_over_mac != BOND_FOM_ACTIVE) { + if (bond->params.fail_over_mac != BOND_FOM_ACTIVE || + bond->params.mode != BOND_MODE_ACTIVEBACKUP) { /* restore original ("permanent") mac address */ memcpy(addr.sa_data, slave->perm_hwaddr, ETH_ALEN); addr.sa_family = slave_dev->type; -- cgit v0.10.2 From cc689aaa7abf33b2ccb02482e5e17885ea8903d1 Mon Sep 17 00:00:00 2001 From: dingtianhong Date: Sat, 25 Jan 2014 13:00:57 +0800 Subject: bonding: fail_over_mac should only affect AB mode in bond_set_mac_address() The fail_over_mac could be set to active or follow in any time for all modes, so if the fail_over_mac is not none and the current mode is not active-backup, the bond_set_mac_address() could not change the master and slave's MAC address. In bond_set_mac_address(), the fail_over_mac should only affect AB mode, so modify to check the mode in addition to fail_over_mac when setting bond's MAC address. Cc: Jay Vosburgh Cc: Veaceslav Falico Cc: Andy Gospodarek Signed-off-by: Ding Tianhong Signed-off-by: David S. Miller diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 8e6dd13..35f7e90 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -3439,7 +3439,8 @@ static int bond_set_mac_address(struct net_device *bond_dev, void *addr) /* If fail_over_mac is enabled, do nothing and return success. * Returning an error causes ifenslave to fail. */ - if (bond->params.fail_over_mac) + if (bond->params.fail_over_mac && + bond->params.mode == BOND_MODE_ACTIVEBACKUP) return 0; if (!is_valid_ether_addr(sa->sa_data)) -- cgit v0.10.2 From a664a4f7aa4f01ca8728e3ec43618327416fc8ff Mon Sep 17 00:00:00 2001 From: Shlomo Pongratz Date: Sun, 2 Feb 2014 15:42:10 +0200 Subject: net/ipv4: Use proper RCU APIs for writer-side in udp_offload.c RCU writer side should use rcu_dereference_protected() and not rcu_dereference(), fix that. This also removes the "suspicious RCU usage" warning seen when running with CONFIG_PROVE_RCU. Also, don't use rcu_assign_pointer/rcu_dereference for pointers which are invisible beyond the udp offload code. Fixes: b582ef0 ('net: Add GRO support for UDP encapsulating protocols') Reported-by: Eric Dumazet Cc: Eric Dumazet Signed-off-by: Or Gerlitz Signed-off-by: Shlomo Pongratz Acked-by: Eric Dumazet Signed-off-by: David S. Miller diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c index 2ffea6f..88b4023 100644 --- a/net/ipv4/udp_offload.c +++ b/net/ipv4/udp_offload.c @@ -17,6 +17,8 @@ static DEFINE_SPINLOCK(udp_offload_lock); static struct udp_offload_priv __rcu *udp_offload_base __read_mostly; +#define udp_deref_protected(X) rcu_dereference_protected(X, lockdep_is_held(&udp_offload_lock)) + struct udp_offload_priv { struct udp_offload *offload; struct rcu_head rcu; @@ -100,7 +102,6 @@ out: int udp_add_offload(struct udp_offload *uo) { - struct udp_offload_priv __rcu **head = &udp_offload_base; struct udp_offload_priv *new_offload = kzalloc(sizeof(*new_offload), GFP_ATOMIC); if (!new_offload) @@ -109,8 +110,8 @@ int udp_add_offload(struct udp_offload *uo) new_offload->offload = uo; spin_lock(&udp_offload_lock); - rcu_assign_pointer(new_offload->next, rcu_dereference(*head)); - rcu_assign_pointer(*head, new_offload); + new_offload->next = udp_offload_base; + rcu_assign_pointer(udp_offload_base, new_offload); spin_unlock(&udp_offload_lock); return 0; @@ -130,12 +131,12 @@ void udp_del_offload(struct udp_offload *uo) spin_lock(&udp_offload_lock); - uo_priv = rcu_dereference(*head); + uo_priv = udp_deref_protected(*head); for (; uo_priv != NULL; - uo_priv = rcu_dereference(*head)) { - + uo_priv = udp_deref_protected(*head)) { if (uo_priv->offload == uo) { - rcu_assign_pointer(*head, rcu_dereference(uo_priv->next)); + rcu_assign_pointer(*head, + udp_deref_protected(uo_priv->next)); goto unlock; } head = &uo_priv->next; -- cgit v0.10.2 From e2e2f51dd0254fa0002bcd1c5fda180348163f09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20S=C3=B8rensen?= Date: Mon, 3 Feb 2014 15:36:35 +0100 Subject: net:phy:dp83640: Declare that TX timestamping possible MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Set the SKBTX_IN_PROGRESS bit in tx_flags dp83640_txtstamp when doing tx timestamps as per Documentation/networking/timestamping.txt. Signed-off-by: Stefan Sørensen Acked-by: Richard Cochran Signed-off-by: David S. Miller diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c index 547725f..3f882ee 100644 --- a/drivers/net/phy/dp83640.c +++ b/drivers/net/phy/dp83640.c @@ -1281,6 +1281,7 @@ static void dp83640_txtstamp(struct phy_device *phydev, } /* fall through */ case HWTSTAMP_TX_ON: + skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; skb_queue_tail(&dp83640->tx_queue, skb); schedule_work(&dp83640->ts_work); break; -- cgit v0.10.2 From 80671bd2a91b81b8e06634e8309ce94df688c42c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20S=C3=B8rensen?= Date: Mon, 3 Feb 2014 15:36:50 +0100 Subject: net:phy:dp83640: Do not hardcode timestamping event edge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently the external timestamping code is hardcoded to use the rising edge even though the hardware has configurable event edge detection. This patch changes the code to use falling edge detection if PTP_FALLING_EDGE is set in the user supplied flags. Signed-off-by: Stefan Sørensen Acked-by: Richard Cochran Signed-off-by: David S. Miller diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c index 3f882ee..e347c8a 100644 --- a/drivers/net/phy/dp83640.c +++ b/drivers/net/phy/dp83640.c @@ -437,7 +437,10 @@ static int ptp_dp83640_enable(struct ptp_clock_info *ptp, if (on) { gpio_num = gpio_tab[EXTTS0_GPIO + index]; evnt |= (gpio_num & EVNT_GPIO_MASK) << EVNT_GPIO_SHIFT; - evnt |= EVNT_RISE; + if (rq->extts.flags & PTP_FALLING_EDGE) + evnt |= EVNT_FALL; + else + evnt |= EVNT_RISE; } ext_write(0, phydev, PAGE5, PTP_EVNT, evnt); return 0; -- cgit v0.10.2 From 62ad968402466c4777a6634c86010e86521bc745 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20S=C3=B8rensen?= Date: Mon, 3 Feb 2014 15:36:58 +0100 Subject: net:phy:dp83640: Initialize PTP clocks at device init. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The trigger and events functionality can be useful even if packet timestamping is not used, but the required PTP clock is only enabled when packet timestamping is started. This patch moves the clock enable to when the interface is configured. Signed-off-by: Stefan Sørensen Acked-by: Richard Cochran Signed-off-by: David S. Miller diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c index e347c8a..9414fa2 100644 --- a/drivers/net/phy/dp83640.c +++ b/drivers/net/phy/dp83640.c @@ -1061,6 +1061,13 @@ static void dp83640_remove(struct phy_device *phydev) kfree(dp83640); } +static int dp83640_config_init(struct phy_device *phydev) +{ + enable_status_frames(phydev, true); + ext_write(0, phydev, PAGE4, PTP_CTL, PTP_ENABLE); + return 0; +} + static int dp83640_ack_interrupt(struct phy_device *phydev) { int err = phy_read(phydev, MII_DP83640_MISR); @@ -1198,11 +1205,6 @@ static int dp83640_hwtstamp(struct phy_device *phydev, struct ifreq *ifr) mutex_lock(&dp83640->clock->extreg_lock); - if (dp83640->hwts_tx_en || dp83640->hwts_rx_en) { - enable_status_frames(phydev, true); - ext_write(0, phydev, PAGE4, PTP_CTL, PTP_ENABLE); - } - ext_write(0, phydev, PAGE5, PTP_TXCFG0, txcfg0); ext_write(0, phydev, PAGE5, PTP_RXCFG0, rxcfg0); @@ -1334,6 +1336,7 @@ static struct phy_driver dp83640_driver = { .flags = PHY_HAS_INTERRUPT, .probe = dp83640_probe, .remove = dp83640_remove, + .config_init = dp83640_config_init, .config_aneg = genphy_config_aneg, .read_status = genphy_read_status, .ack_interrupt = dp83640_ack_interrupt, -- cgit v0.10.2 From 5273e3a5ca94fbeb8e07d31203069220d5e682aa Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 3 Feb 2014 12:35:46 -0800 Subject: net: phy: ensure Gigabit features are masked off if requested When a Gigabit PHY device is connected to a 10/100Mbits capable Ethernet MAC, the driver will restrict the phydev->supported modes to mask off Gigabit. If the Gigabit PHY comes out of reset with the Gigabit features set by default in MII_CTRL1000, it will keep advertising these feature, so by the time we call genphy_config_advert(), the condition on phydev->supported having the Gigabit features on is false, and we do not update MII_CTRL1000 with updated values, and we keep advertising Gigabit features, eventually configuring the PHY for Gigabit whilst the Ethernet MAC does not support that. This patches fixes the problem by ensuring that the Gigabit feature bits are always cleared in MII_CTRL1000, if the PHY happens to be a Gigabit PHY, and then, if Gigabit features are supported, setting those and updating MII_CTRL1000 accordingly. Reported-by: Max Filippov Signed-off-by: Florian Fainelli Tested-by: Max Filippov Signed-off-by: David S. Miller diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 4b03e63..82514e7 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -719,7 +719,7 @@ int phy_resume(struct phy_device *phydev) static int genphy_config_advert(struct phy_device *phydev) { u32 advertise; - int oldadv, adv; + int oldadv, adv, bmsr; int err, changed = 0; /* Only allow advertising what this PHY supports */ @@ -744,26 +744,36 @@ static int genphy_config_advert(struct phy_device *phydev) changed = 1; } + bmsr = phy_read(phydev, MII_BMSR); + if (bmsr < 0) + return bmsr; + + /* Per 802.3-2008, Section 22.2.4.2.16 Extended status all + * 1000Mbits/sec capable PHYs shall have the BMSR_ESTATEN bit set to a + * logical 1. + */ + if (!(bmsr & BMSR_ESTATEN)) + return changed; + /* Configure gigabit if it's supported */ + adv = phy_read(phydev, MII_CTRL1000); + if (adv < 0) + return adv; + + oldadv = adv; + adv &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); + if (phydev->supported & (SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full)) { - adv = phy_read(phydev, MII_CTRL1000); - if (adv < 0) - return adv; - - oldadv = adv; - adv &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); adv |= ethtool_adv_to_mii_ctrl1000_t(advertise); - - if (adv != oldadv) { - err = phy_write(phydev, MII_CTRL1000, adv); - - if (err < 0) - return err; + if (adv != oldadv) changed = 1; - } } + err = phy_write(phydev, MII_CTRL1000, adv); + if (err < 0) + return err; + return changed; } -- cgit v0.10.2 From 445a48cc9df90775d6479ef4c73d3a90184af4ed Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Tue, 4 Feb 2014 03:33:09 +0400 Subject: net: ethoc: don't advertise gigabit speed on attached PHY OpenCores 10/100 Mbps MAC does not support speeds above 100 Mbps, but does not disable advertisement when PHY supports them. This results in non-functioning network when the MAC is connected to a gigabit PHY connected to a gigabit switch. The fix is to disable gigabit speed advertisement on attached PHY unconditionally. Signed-off-by: Max Filippov Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/ethoc.c b/drivers/net/ethernet/ethoc.c index f9c1cf5..0a8533c 100644 --- a/drivers/net/ethernet/ethoc.c +++ b/drivers/net/ethernet/ethoc.c @@ -691,6 +691,11 @@ static int ethoc_mdio_probe(struct net_device *dev) } priv->phy = phy; + phy->advertising &= ~(ADVERTISED_1000baseT_Full | + ADVERTISED_1000baseT_Half); + phy->supported &= ~(SUPPORTED_1000baseT_Full | + SUPPORTED_1000baseT_Half); + return 0; } -- cgit v0.10.2 From a13aff0641a92dc0b95136e32526e2ce81ffc4ef Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Tue, 4 Feb 2014 03:33:10 +0400 Subject: net: ethoc: set up MII management bus clock MII management bus clock is derived from the MAC clock by dividing it by MIIMODER register CLKDIV field value. This value may need to be set up in case it is undefined or its default value is too high (and communication with PHY is too slow) or too low (and communication with PHY is impossible). The value of CLKDIV is not specified directly, but is derived from the MAC clock for the default MII management bus frequency of 2.5MHz. The MAC clock may be specified in the platform data, or in the 'clocks' device tree attribute. Signed-off-by: Max Filippov Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/ethoc.c b/drivers/net/ethernet/ethoc.c index 0a8533c..55e0fa0 100644 --- a/drivers/net/ethernet/ethoc.c +++ b/drivers/net/ethernet/ethoc.c @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -219,6 +220,7 @@ struct ethoc { struct phy_device *phy; struct mii_bus *mdio; + struct clk *clk; s8 phy_id; }; @@ -1021,6 +1023,8 @@ static int ethoc_probe(struct platform_device *pdev) int num_bd; int ret = 0; bool random_mac = false; + struct ethoc_platform_data *pdata = dev_get_platdata(&pdev->dev); + u32 eth_clkfreq = pdata ? pdata->eth_clkfreq : 0; /* allocate networking device */ netdev = alloc_etherdev(sizeof(struct ethoc)); @@ -1135,8 +1139,7 @@ static int ethoc_probe(struct platform_device *pdev) } /* Allow the platform setup code to pass in a MAC address. */ - if (dev_get_platdata(&pdev->dev)) { - struct ethoc_platform_data *pdata = dev_get_platdata(&pdev->dev); + if (pdata) { memcpy(netdev->dev_addr, pdata->hwaddr, IFHWADDRLEN); priv->phy_id = pdata->phy_id; } else { @@ -1174,6 +1177,27 @@ static int ethoc_probe(struct platform_device *pdev) if (random_mac) netdev->addr_assign_type = NET_ADDR_RANDOM; + /* Allow the platform setup code to adjust MII management bus clock. */ + if (!eth_clkfreq) { + struct clk *clk = devm_clk_get(&pdev->dev, NULL); + + if (!IS_ERR(clk)) { + priv->clk = clk; + clk_prepare_enable(clk); + eth_clkfreq = clk_get_rate(clk); + } + } + if (eth_clkfreq) { + u32 clkdiv = MIIMODER_CLKDIV(eth_clkfreq / 2500000 + 1); + + if (!clkdiv) + clkdiv = 2; + dev_dbg(&pdev->dev, "setting MII clkdiv to %u\n", clkdiv); + ethoc_write(priv, MIIMODER, + (ethoc_read(priv, MIIMODER) & MIIMODER_NOPRE) | + clkdiv); + } + /* register MII bus */ priv->mdio = mdiobus_alloc(); if (!priv->mdio) { @@ -1239,6 +1263,8 @@ free_mdio: kfree(priv->mdio->irq); mdiobus_free(priv->mdio); free: + if (priv->clk) + clk_disable_unprepare(priv->clk); free_netdev(netdev); out: return ret; @@ -1263,6 +1289,8 @@ static int ethoc_remove(struct platform_device *pdev) kfree(priv->mdio->irq); mdiobus_free(priv->mdio); } + if (priv->clk) + clk_disable_unprepare(priv->clk); unregister_netdev(netdev); free_netdev(netdev); } diff --git a/include/net/ethoc.h b/include/net/ethoc.h index 96f3789..2a2d6bb 100644 --- a/include/net/ethoc.h +++ b/include/net/ethoc.h @@ -16,6 +16,7 @@ struct ethoc_platform_data { u8 hwaddr[IFHWADDRLEN]; s8 phy_id; + u32 eth_clkfreq; }; #endif /* !LINUX_NET_ETHOC_H */ -- cgit v0.10.2 From 61950e82b384cbe581f7e9cb668f77dc1d8cef35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20S=C3=B8rensen?= Date: Tue, 4 Feb 2014 08:46:36 +0100 Subject: ptp: Allow selecting trigger/event index in testptp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently the trigger/event is hardcoded to 0, this patch adds a new command line argument -i to select an arbitrary trigger/ event. Signed-off-by: Stefan Sørensen Acked-by: Richard Cochran Signed-off-by: David S. Miller diff --git a/Documentation/ptp/testptp.c b/Documentation/ptp/testptp.c index a74d0a8..4aba043 100644 --- a/Documentation/ptp/testptp.c +++ b/Documentation/ptp/testptp.c @@ -117,6 +117,7 @@ static void usage(char *progname) " -f val adjust the ptp clock frequency by 'val' ppb\n" " -g get the ptp clock time\n" " -h prints this message\n" + " -i val index for event/trigger\n" " -k val measure the time offset between system and phc clock\n" " for 'val' times (Maximum 25)\n" " -p val enable output with a period of 'val' nanoseconds\n" @@ -154,6 +155,7 @@ int main(int argc, char *argv[]) int capabilities = 0; int extts = 0; int gettime = 0; + int index = 0; int oneshot = 0; int pct_offset = 0; int n_samples = 0; @@ -167,7 +169,7 @@ int main(int argc, char *argv[]) progname = strrchr(argv[0], '/'); progname = progname ? 1+progname : argv[0]; - while (EOF != (c = getopt(argc, argv, "a:A:cd:e:f:ghk:p:P:sSt:v"))) { + while (EOF != (c = getopt(argc, argv, "a:A:cd:e:f:ghi:k:p:P:sSt:v"))) { switch (c) { case 'a': oneshot = atoi(optarg); @@ -190,6 +192,9 @@ int main(int argc, char *argv[]) case 'g': gettime = 1; break; + case 'i': + index = atoi(optarg); + break; case 'k': pct_offset = 1; n_samples = atoi(optarg); @@ -301,7 +306,7 @@ int main(int argc, char *argv[]) if (extts) { memset(&extts_request, 0, sizeof(extts_request)); - extts_request.index = 0; + extts_request.index = index; extts_request.flags = PTP_ENABLE_FEATURE; if (ioctl(fd, PTP_EXTTS_REQUEST, &extts_request)) { perror("PTP_EXTTS_REQUEST"); @@ -375,7 +380,7 @@ int main(int argc, char *argv[]) return -1; } memset(&perout_request, 0, sizeof(perout_request)); - perout_request.index = 0; + perout_request.index = index; perout_request.start.sec = ts.tv_sec + 2; perout_request.start.nsec = 0; perout_request.period.sec = 0; -- cgit v0.10.2 From 6049f2530cf2cb48a6fe8735309cc0b97aa7f700 Mon Sep 17 00:00:00 2001 From: Fernando Luis Vazquez Cao Date: Tue, 4 Feb 2014 19:35:02 +0900 Subject: rtnetlink: fix oops in rtnl_link_get_slave_info_data_size We should check whether rtnetlink link operations are defined before calling get_slave_size(). Without this, the following oops can occur when adding a tap device to OVS. [ 87.839553] BUG: unable to handle kernel NULL pointer dereference at 00000000000000a8 [ 87.839595] IP: [] if_nlmsg_size+0xf0/0x220 [...] [ 87.840651] Call Trace: [ 87.840664] [] ? rtmsg_ifinfo+0x2b/0x100 [ 87.840688] [] ? __netdev_adjacent_dev_insert+0x150/0x1a0 [ 87.840718] [] ? rtnetlink_event+0x30/0x40 [ 87.840742] [] ? notifier_call_chain+0x44/0x70 [ 87.840768] [] ? __netdev_upper_dev_link+0x3c6/0x3f0 [ 87.840798] [] ? netdev_create+0xcc/0x160 [openvswitch] [ 87.840828] [] ? ovs_vport_add+0x4a/0xd0 [openvswitch] [ 87.840857] [] ? new_vport+0x9/0x50 [openvswitch] [ 87.840884] [] ? ovs_vport_cmd_new+0x11e/0x210 [openvswitch] [ 87.840915] [] ? genl_family_rcv_msg+0x19a/0x360 [ 87.840941] [] ? genl_family_rcv_msg+0x360/0x360 [ 87.840967] [] ? genl_rcv_msg+0x79/0xc0 [ 87.840991] [] ? __kmalloc_reserve.isra.25+0x29/0x80 [ 87.841018] [] ? netlink_rcv_skb+0xa9/0xc0 [ 87.841042] [] ? genl_rcv+0x1f/0x30 [ 87.841064] [] ? netlink_unicast+0xe8/0x1e0 [ 87.841088] [] ? netlink_sendmsg+0x31a/0x750 [ 87.841113] [] ? sock_sendmsg+0x86/0xc0 [ 87.841136] [] ? __netdev_update_features+0x4d/0x200 [ 87.841163] [] ? ethtool_get_value+0x2e/0x50 [ 87.841188] [] ? ___sys_sendmsg+0x359/0x370 [ 87.841212] [] ? dev_ioctl+0x1a6/0x5c0 [ 87.841236] [] ? autoremove_wake_function+0x30/0x30 [ 87.841264] [] ? sock_do_ioctl+0x3d/0x50 [ 87.841288] [] ? sock_ioctl+0x1e8/0x2c0 [ 87.841312] [] ? do_vfs_ioctl+0x2cf/0x4b0 [ 87.841335] [] ? __sys_sendmsg+0x39/0x70 [ 87.841362] [] ? system_call_fastpath+0x16/0x1b [ 87.841386] Code: c0 74 10 48 89 ef ff d0 83 c0 07 83 e0 fc 48 98 49 01 c7 48 89 ef e8 d0 d6 fe ff 48 85 c0 0f 84 df 00 00 00 48 8b 90 08 07 00 00 <48> 8b 8a a8 00 00 00 31 d2 48 85 c9 74 0c 48 89 ee 48 89 c7 ff [ 87.841529] RIP [] if_nlmsg_size+0xf0/0x220 [ 87.841555] RSP [ 87.841569] CR2: 00000000000000a8 [ 87.851442] ---[ end trace e42ab217691b4fc2 ]--- Signed-off-by: Fernando Luis Vazquez Cao Acked-by: Jiri Pirko Signed-off-by: David S. Miller diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 393b1bc..048dc8d 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -374,7 +374,7 @@ static size_t rtnl_link_get_slave_info_data_size(const struct net_device *dev) if (!master_dev) return 0; ops = master_dev->rtnl_link_ops; - if (!ops->get_slave_size) + if (!ops || !ops->get_slave_size) return 0; /* IFLA_INFO_SLAVE_DATA + nested data */ return nla_total_size(sizeof(struct nlattr)) + -- cgit v0.10.2 From fbd3a77d813f211060f86cc7a2f8416caf0e03b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Tue, 4 Feb 2014 13:04:33 +0100 Subject: net: qmi_wwan: add Netgear Aircard 340U MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This device was mentioned in an OpenWRT forum. Seems to have a "standard" Sierra Wireless ifnumber to function layout: 0: qcdm 2: nmea 3: modem 8: qmi 9: storage Signed-off-by: Bjørn Mork Signed-off-by: David S. Miller diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 23bdd5b..ef4a45a 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -723,6 +723,7 @@ static const struct usb_device_id products[] = { {QMI_FIXED_INTF(0x1199, 0x68a2, 8)}, /* Sierra Wireless MC7710 in QMI mode */ {QMI_FIXED_INTF(0x1199, 0x68a2, 19)}, /* Sierra Wireless MC7710 in QMI mode */ {QMI_FIXED_INTF(0x1199, 0x901c, 8)}, /* Sierra Wireless EM7700 */ + {QMI_FIXED_INTF(0x1199, 0x9051, 8)}, /* Netgear AirCard 340U */ {QMI_FIXED_INTF(0x1bbb, 0x011e, 4)}, /* Telekom Speedstick LTE II (Alcatel One Touch L100V LTE) */ {QMI_FIXED_INTF(0x2357, 0x0201, 4)}, /* TP-LINK HSUPA Modem MA180 */ {QMI_FIXED_INTF(0x2357, 0x9000, 4)}, /* TP-LINK MA260 */ -- cgit v0.10.2 From e8c37aff2a392c31fefa62ec045058a0877c45a1 Mon Sep 17 00:00:00 2001 From: Dmitry Kravkov Date: Tue, 4 Feb 2014 17:43:03 +0200 Subject: bnx2x: fix L2-GRE TCP issues When configuring GRE tunnel using OVS, tcp stream is distributed over all RSS queues which may cause TCP reordering. It happens since OVS uses L2GRE protocol when kernel gre uses IPGRE. Patch defaults gre tunnel to L2GRE which allows proper RSS for L2GRE packets and (implicitly) disables RSS for IPGRE traffic. Signed-off-by: Dmitry Kravkov Signed-off-by: Ariel Elior Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h index 17d1689..bfc58d4 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h @@ -936,7 +936,7 @@ static inline int bnx2x_func_start(struct bnx2x *bp) else /* CHIP_IS_E1X */ start_params->network_cos_mode = FW_WRR; - start_params->gre_tunnel_mode = IPGRE_TUNNEL; + start_params->gre_tunnel_mode = L2GRE_TUNNEL; start_params->gre_tunnel_rss = GRE_INNER_HEADERS_RSS; return bnx2x_func_state_change(bp, &func_params); -- cgit v0.10.2 From bce3ea81d5b2a33ed0e275d58a45f10ce95cbd50 Mon Sep 17 00:00:00 2001 From: David Vrabel Date: Tue, 4 Feb 2014 18:50:26 +0000 Subject: xen-netfront: handle backend CLOSED without CLOSING Backend drivers shouldn't transistion to CLOSED unless the frontend is CLOSED. If a backend does transition to CLOSED too soon then the frontend may not see the CLOSING state and will not properly shutdown. So, treat an unexpected backend CLOSED state the same as CLOSING. Signed-off-by: David Vrabel Acked-by: Konrad Rzeszutek Wilk Signed-off-by: David S. Miller diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index ff04d4f..f9daa9e 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -1832,7 +1832,6 @@ static void netback_changed(struct xenbus_device *dev, case XenbusStateReconfiguring: case XenbusStateReconfigured: case XenbusStateUnknown: - case XenbusStateClosed: break; case XenbusStateInitWait: @@ -1847,6 +1846,10 @@ static void netback_changed(struct xenbus_device *dev, netdev_notify_peers(netdev); break; + case XenbusStateClosed: + if (dev->state == XenbusStateClosed) + break; + /* Missed the backend's CLOSING state -- fallthrough */ case XenbusStateClosing: xenbus_frontend_closed(dev); break; -- cgit v0.10.2 From 04c2facad8fee66c981a51852806d8923336f362 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Tue, 4 Feb 2014 18:33:11 +0100 Subject: drivers: phy: Make NULL a valid phy reference The common clock framework considers NULL a valid clock reference. This makes handling optional clocks simple, in that if the optional clock is not available, a NULL reference can be used in the place of a real clock, simplifying the clock consumer. Extend this concept to the phy consumer API. A NULL can be passed to the release calls, the phy_init() and phy_exit() calls, and phy_power_on() and phy_power_off() and a NOP is performed. Signed-off-by: Andrew Lunn Tested-by: Gregory CLEMENT Acked-by: Kishon Vijay Abraham I Signed-off-by: Jason Cooper diff --git a/Documentation/phy.txt b/Documentation/phy.txt index 0103e4b..2e24b99 100644 --- a/Documentation/phy.txt +++ b/Documentation/phy.txt @@ -84,6 +84,12 @@ The only difference between the two APIs is that devm_phy_get associates the device with the PHY using devres on successful PHY get. On driver detach, release function is invoked on the the devres data and devres data is freed. +It should be noted that NULL is a valid phy reference. All phy +consumer calls on the NULL phy become NOPs. That is the release calls, +the phy_init() and phy_exit() calls, and phy_power_on() and +phy_power_off() calls are all NOP when applied to a NULL phy. The NULL +phy is useful in devices for handling optional phy devices. + 5. Releasing a reference to the PHY When the controller no longer needs the PHY, it has to release the reference diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c index 645c867..a9cdeee2 100644 --- a/drivers/phy/phy-core.c +++ b/drivers/phy/phy-core.c @@ -162,6 +162,9 @@ int phy_init(struct phy *phy) { int ret; + if (!phy) + return 0; + ret = phy_pm_runtime_get_sync(phy); if (ret < 0 && ret != -ENOTSUPP) return ret; @@ -187,6 +190,9 @@ int phy_exit(struct phy *phy) { int ret; + if (!phy) + return 0; + ret = phy_pm_runtime_get_sync(phy); if (ret < 0 && ret != -ENOTSUPP) return ret; @@ -212,6 +218,9 @@ int phy_power_on(struct phy *phy) { int ret; + if (!phy) + return 0; + ret = phy_pm_runtime_get_sync(phy); if (ret < 0 && ret != -ENOTSUPP) return ret; @@ -240,6 +249,9 @@ int phy_power_off(struct phy *phy) { int ret; + if (!phy) + return 0; + mutex_lock(&phy->mutex); if (phy->power_count == 1 && phy->ops->power_off) { ret = phy->ops->power_off(phy); @@ -308,7 +320,7 @@ err0: */ void phy_put(struct phy *phy) { - if (IS_ERR(phy)) + if (!phy || IS_ERR(phy)) return; module_put(phy->ops->owner); @@ -328,6 +340,9 @@ void devm_phy_put(struct device *dev, struct phy *phy) { int r; + if (!phy) + return; + r = devres_destroy(dev, devm_phy_release, devm_phy_match, phy); dev_WARN_ONCE(dev, r, "couldn't find PHY resource\n"); } -- cgit v0.10.2 From 788a4d56ff378bff0b8e685d03a962b36903a149 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Tue, 4 Feb 2014 18:33:12 +0100 Subject: drivers: phy: Add support for optional phys Add devm_phy_optional_get and phy_optional_get, which should be used when the phy is optional. They does not return an error when the phy does not exist, rather they returns NULL, which is considered as a valid phy, but results in NOPs when used with the consumer API. Signed-off-by: Andrew Lunn Tested-by: Gregory CLEMENT Acked-by: Kishon Vijay Abraham I Signed-off-by: Jason Cooper diff --git a/Documentation/phy.txt b/Documentation/phy.txt index 2e24b99..ebff6ee 100644 --- a/Documentation/phy.txt +++ b/Documentation/phy.txt @@ -75,14 +75,20 @@ Before the controller can make use of the PHY, it has to get a reference to it. This framework provides the following APIs to get a reference to the PHY. struct phy *phy_get(struct device *dev, const char *string); +struct phy *phy_optional_get(struct device *dev, const char *string); struct phy *devm_phy_get(struct device *dev, const char *string); - -phy_get and devm_phy_get can be used to get the PHY. In the case of dt boot, -the string arguments should contain the phy name as given in the dt data and -in the case of non-dt boot, it should contain the label of the PHY. -The only difference between the two APIs is that devm_phy_get associates the -device with the PHY using devres on successful PHY get. On driver detach, -release function is invoked on the the devres data and devres data is freed. +struct phy *devm_phy_optional_get(struct device *dev, const char *string); + +phy_get, phy_optional_get, devm_phy_get and devm_phy_optional_get can +be used to get the PHY. In the case of dt boot, the string arguments +should contain the phy name as given in the dt data and in the case of +non-dt boot, it should contain the label of the PHY. The two +devm_phy_get associates the device with the PHY using devres on +successful PHY get. On driver detach, release function is invoked on +the the devres data and devres data is freed. phy_optional_get and +devm_phy_optional_get should be used when the phy is optional. These +two functions will never return -ENODEV, but instead returns NULL when +the phy cannot be found. It should be noted that NULL is a valid phy reference. All phy consumer calls on the NULL phy become NOPs. That is the release calls, diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c index a9cdeee2..5f5b0f4 100644 --- a/drivers/phy/phy-core.c +++ b/drivers/phy/phy-core.c @@ -426,6 +426,27 @@ struct phy *phy_get(struct device *dev, const char *string) EXPORT_SYMBOL_GPL(phy_get); /** + * phy_optional_get() - lookup and obtain a reference to an optional phy. + * @dev: device that requests this phy + * @string: the phy name as given in the dt data or the name of the controller + * port for non-dt case + * + * Returns the phy driver, after getting a refcount to it; or + * NULL if there is no such phy. The caller is responsible for + * calling phy_put() to release that count. + */ +struct phy *phy_optional_get(struct device *dev, const char *string) +{ + struct phy *phy = phy_get(dev, string); + + if (PTR_ERR(phy) == -ENODEV) + phy = NULL; + + return phy; +} +EXPORT_SYMBOL_GPL(phy_optional_get); + +/** * devm_phy_get() - lookup and obtain a reference to a phy. * @dev: device that requests this phy * @string: the phy name as given in the dt data or phy device name @@ -456,6 +477,30 @@ struct phy *devm_phy_get(struct device *dev, const char *string) EXPORT_SYMBOL_GPL(devm_phy_get); /** + * devm_phy_optional_get() - lookup and obtain a reference to an optional phy. + * @dev: device that requests this phy + * @string: the phy name as given in the dt data or phy device name + * for non-dt case + * + * Gets the phy using phy_get(), and associates a device with it using + * devres. On driver detach, release function is invoked on the devres + * data, then, devres data is freed. This differs to devm_phy_get() in + * that if the phy does not exist, it is not considered an error and + * -ENODEV will not be returned. Instead the NULL phy is returned, + * which can be passed to all other phy consumer calls. + */ +struct phy *devm_phy_optional_get(struct device *dev, const char *string) +{ + struct phy *phy = devm_phy_get(dev, string); + + if (PTR_ERR(phy) == -ENODEV) + phy = NULL; + + return phy; +} +EXPORT_SYMBOL_GPL(devm_phy_optional_get); + +/** * phy_create() - create a new phy * @dev: device that is creating the new phy * @ops: function pointers for performing phy operations diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h index e273e5a..3f83459 100644 --- a/include/linux/phy/phy.h +++ b/include/linux/phy/phy.h @@ -146,7 +146,9 @@ static inline void phy_set_bus_width(struct phy *phy, int bus_width) phy->attrs.bus_width = bus_width; } struct phy *phy_get(struct device *dev, const char *string); +struct phy *phy_optional_get(struct device *dev, const char *string); struct phy *devm_phy_get(struct device *dev, const char *string); +struct phy *devm_phy_optional_get(struct device *dev, const char *string); void phy_put(struct phy *phy); void devm_phy_put(struct device *dev, struct phy *phy); struct phy *of_phy_simple_xlate(struct device *dev, @@ -232,11 +234,23 @@ static inline struct phy *phy_get(struct device *dev, const char *string) return ERR_PTR(-ENOSYS); } +static inline struct phy *phy_optional_get(struct device *dev, + const char *string) +{ + return ERR_PTR(-ENOSYS); +} + static inline struct phy *devm_phy_get(struct device *dev, const char *string) { return ERR_PTR(-ENOSYS); } +static inline struct phy *devm_phy_optional_get(struct device *dev, + const char *string) +{ + return ERR_PTR(-ENOSYS); +} + static inline void phy_put(struct phy *phy) { } -- cgit v0.10.2 From 90aa2997029fa623fe9e3ec3a469a00a34130237 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Tue, 4 Feb 2014 18:33:13 +0100 Subject: ata: sata_mv: Fix probe failures with optional phys Make use of devm_phy_optional_get() in order to fix probe failures on Armada 370, XP and others, when there is no phy driver available. Signed-off-by: Andrew Lunn Tested-by: Gregory CLEMENT Acked-by: Tejun Heo Acked-by: Kishon Vijay Abraham I Signed-off-by: Jason Cooper diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 20a7517..52b8181 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -4126,12 +4126,14 @@ static int mv_platform_probe(struct platform_device *pdev) clk_prepare_enable(hpriv->port_clks[port]); sprintf(port_number, "port%d", port); - hpriv->port_phys[port] = devm_phy_get(&pdev->dev, port_number); + hpriv->port_phys[port] = devm_phy_optional_get(&pdev->dev, + port_number); if (IS_ERR(hpriv->port_phys[port])) { rc = PTR_ERR(hpriv->port_phys[port]); hpriv->port_phys[port] = NULL; - if ((rc != -EPROBE_DEFER) && (rc != -ENODEV)) - dev_warn(&pdev->dev, "error getting phy"); + if (rc != -EPROBE_DEFER) + dev_warn(&pdev->dev, "error getting phy %d", + rc); goto err; } else phy_power_on(hpriv->port_phys[port]); -- cgit v0.10.2 From aea0bb4f8ee513537ad84b9f3f609f96e272d98e Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 14 Jan 2014 16:27:49 +0000 Subject: openvswitch: Pad OVS_PACKET_ATTR_PACKET if linear copy was performed While the zerocopy method is correctly omitted if user space does not support unaligned Netlink messages. The attribute is still not padded correctly as skb_zerocopy() will not ensure padding and the attribute size is no longer pre calculated though nla_reserve() which ensured padding previously. This patch applies appropriate padding if a linear data copy was performed in skb_zerocopy(). Signed-off-by: Thomas Graf Acked-by: Zoltan Kiss Signed-off-by: Jesse Gross diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index df46928..d1a73a6 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c @@ -466,6 +466,14 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb, skb_zerocopy(user_skb, skb, skb->len, hlen); + /* Pad OVS_PACKET_ATTR_PACKET if linear copy was performed */ + if (!(dp->user_features & OVS_DP_F_UNALIGNED)) { + size_t plen = NLA_ALIGN(user_skb->len) - user_skb->len; + + if (plen > 0) + memset(skb_put(user_skb, plen), 0, plen); + } + ((struct nlmsghdr *) user_skb->data)->nlmsg_len = user_skb->len; err = genlmsg_unicast(ovs_dp_get_net(dp), user_skb, upcall_info->portid); -- cgit v0.10.2 From e80857cce82da31e41a6599fc888dfc92e0167cc Mon Sep 17 00:00:00 2001 From: Andy Zhou Date: Tue, 21 Jan 2014 09:31:04 -0800 Subject: openvswitch: Fix kernel panic on ovs_flow_free Both mega flow mask's reference counter and per flow table mask list should only be accessed when holding ovs_mutex() lock. However this is not true with ovs_flow_table_flush(). The patch fixes this bug. Reported-by: Joe Stringer Signed-off-by: Andy Zhou Signed-off-by: Jesse Gross diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index d1a73a6..e1b337e 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c @@ -55,6 +55,7 @@ #include "datapath.h" #include "flow.h" +#include "flow_table.h" #include "flow_netlink.h" #include "vport-internal_dev.h" #include "vport-netdev.h" @@ -160,7 +161,6 @@ static void destroy_dp_rcu(struct rcu_head *rcu) { struct datapath *dp = container_of(rcu, struct datapath, rcu); - ovs_flow_tbl_destroy(&dp->table); free_percpu(dp->stats_percpu); release_net(ovs_dp_get_net(dp)); kfree(dp->ports); @@ -1287,7 +1287,7 @@ err_destroy_ports_array: err_destroy_percpu: free_percpu(dp->stats_percpu); err_destroy_table: - ovs_flow_tbl_destroy(&dp->table); + ovs_flow_tbl_destroy(&dp->table, false); err_free_dp: release_net(ovs_dp_get_net(dp)); kfree(dp); @@ -1314,10 +1314,13 @@ static void __dp_destroy(struct datapath *dp) list_del_rcu(&dp->list_node); /* OVSP_LOCAL is datapath internal port. We need to make sure that - * all port in datapath are destroyed first before freeing datapath. + * all ports in datapath are destroyed first before freeing datapath. */ ovs_dp_detach_port(ovs_vport_ovsl(dp, OVSP_LOCAL)); + /* RCU destroy the flow table */ + ovs_flow_tbl_destroy(&dp->table, true); + call_rcu(&dp->rcu, destroy_dp_rcu); } diff --git a/net/openvswitch/flow_table.c b/net/openvswitch/flow_table.c index c58a0fe..bd14052 100644 --- a/net/openvswitch/flow_table.c +++ b/net/openvswitch/flow_table.c @@ -153,29 +153,27 @@ static void rcu_free_flow_callback(struct rcu_head *rcu) flow_free(flow); } -static void flow_mask_del_ref(struct sw_flow_mask *mask, bool deferred) +void ovs_flow_free(struct sw_flow *flow, bool deferred) { - if (!mask) + if (!flow) return; - BUG_ON(!mask->ref_count); - mask->ref_count--; + ASSERT_OVSL(); - if (!mask->ref_count) { - list_del_rcu(&mask->list); - if (deferred) - kfree_rcu(mask, rcu); - else - kfree(mask); - } -} + if (flow->mask) { + struct sw_flow_mask *mask = flow->mask; -void ovs_flow_free(struct sw_flow *flow, bool deferred) -{ - if (!flow) - return; + BUG_ON(!mask->ref_count); + mask->ref_count--; - flow_mask_del_ref(flow->mask, deferred); + if (!mask->ref_count) { + list_del_rcu(&mask->list); + if (deferred) + kfree_rcu(mask, rcu); + else + kfree(mask); + } + } if (deferred) call_rcu(&flow->rcu, rcu_free_flow_callback); @@ -188,26 +186,9 @@ static void free_buckets(struct flex_array *buckets) flex_array_free(buckets); } + static void __table_instance_destroy(struct table_instance *ti) { - int i; - - if (ti->keep_flows) - goto skip_flows; - - for (i = 0; i < ti->n_buckets; i++) { - struct sw_flow *flow; - struct hlist_head *head = flex_array_get(ti->buckets, i); - struct hlist_node *n; - int ver = ti->node_ver; - - hlist_for_each_entry_safe(flow, n, head, hash_node[ver]) { - hlist_del(&flow->hash_node[ver]); - ovs_flow_free(flow, false); - } - } - -skip_flows: free_buckets(ti->buckets); kfree(ti); } @@ -258,20 +239,38 @@ static void flow_tbl_destroy_rcu_cb(struct rcu_head *rcu) static void table_instance_destroy(struct table_instance *ti, bool deferred) { + int i; + if (!ti) return; + if (ti->keep_flows) + goto skip_flows; + + for (i = 0; i < ti->n_buckets; i++) { + struct sw_flow *flow; + struct hlist_head *head = flex_array_get(ti->buckets, i); + struct hlist_node *n; + int ver = ti->node_ver; + + hlist_for_each_entry_safe(flow, n, head, hash_node[ver]) { + hlist_del_rcu(&flow->hash_node[ver]); + ovs_flow_free(flow, deferred); + } + } + +skip_flows: if (deferred) call_rcu(&ti->rcu, flow_tbl_destroy_rcu_cb); else __table_instance_destroy(ti); } -void ovs_flow_tbl_destroy(struct flow_table *table) +void ovs_flow_tbl_destroy(struct flow_table *table, bool deferred) { struct table_instance *ti = ovsl_dereference(table->ti); - table_instance_destroy(ti, false); + table_instance_destroy(ti, deferred); } struct sw_flow *ovs_flow_tbl_dump_next(struct table_instance *ti, @@ -504,16 +503,11 @@ static struct sw_flow_mask *mask_alloc(void) mask = kmalloc(sizeof(*mask), GFP_KERNEL); if (mask) - mask->ref_count = 0; + mask->ref_count = 1; return mask; } -static void mask_add_ref(struct sw_flow_mask *mask) -{ - mask->ref_count++; -} - static bool mask_equal(const struct sw_flow_mask *a, const struct sw_flow_mask *b) { @@ -554,9 +548,11 @@ static int flow_mask_insert(struct flow_table *tbl, struct sw_flow *flow, mask->key = new->key; mask->range = new->range; list_add_rcu(&mask->list, &tbl->mask_list); + } else { + BUG_ON(!mask->ref_count); + mask->ref_count++; } - mask_add_ref(mask); flow->mask = mask; return 0; } diff --git a/net/openvswitch/flow_table.h b/net/openvswitch/flow_table.h index 1996e34..baaeb10 100644 --- a/net/openvswitch/flow_table.h +++ b/net/openvswitch/flow_table.h @@ -60,7 +60,7 @@ void ovs_flow_free(struct sw_flow *, bool deferred); int ovs_flow_tbl_init(struct flow_table *); int ovs_flow_tbl_count(struct flow_table *table); -void ovs_flow_tbl_destroy(struct flow_table *table); +void ovs_flow_tbl_destroy(struct flow_table *table, bool deferred); int ovs_flow_tbl_flush(struct flow_table *flow_table); int ovs_flow_tbl_insert(struct flow_table *table, struct sw_flow *flow, -- cgit v0.10.2 From 45fb9c35b27c9982e9a55d04ed0a5230a2d0b306 Mon Sep 17 00:00:00 2001 From: Daniele Di Proietto Date: Thu, 23 Jan 2014 10:47:35 -0800 Subject: openvswitch: Fix ovs_dp_cmd_msg_size() commit 43d4be9cb55f3bac5253e9289996fd9d735531db (openvswitch: Allow user space to announce ability to accept unaligned Netlink messages) introduced OVS_DP_ATTR_USER_FEATURES netlink attribute in datapath responses, but the attribute size was not taken into account in ovs_dp_cmd_msg_size(). Signed-off-by: Daniele Di Proietto Signed-off-by: Jesse Gross diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index e1b337e..58689dd 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c @@ -1087,6 +1087,7 @@ static size_t ovs_dp_cmd_msg_size(void) msgsize += nla_total_size(IFNAMSIZ); msgsize += nla_total_size(sizeof(struct ovs_dp_stats)); msgsize += nla_total_size(sizeof(struct ovs_dp_megaflow_stats)); + msgsize += nla_total_size(sizeof(u32)); /* OVS_DP_ATTR_USER_FEATURES */ return msgsize; } -- cgit v0.10.2 From e4c6d7595403e943a3afc334eb8c0efcd840043a Mon Sep 17 00:00:00 2001 From: Pravin B Shelar Date: Fri, 31 Jan 2014 09:43:23 -0800 Subject: openvswitch: Fix ovs_flow_free() ovs-lock assert. ovs_flow_free() is not called under ovs-lock during packet execute path (ovs_packet_cmd_execute()). Since packet execute does not touch flow->mask, there is no need to take that lock either. So move assert in case where flow->mask is checked. Found by code inspection. Signed-off-by: Pravin B Shelar Signed-off-by: Jesse Gross diff --git a/net/openvswitch/flow_table.c b/net/openvswitch/flow_table.c index bd14052..3c268b3 100644 --- a/net/openvswitch/flow_table.c +++ b/net/openvswitch/flow_table.c @@ -158,11 +158,13 @@ void ovs_flow_free(struct sw_flow *flow, bool deferred) if (!flow) return; - ASSERT_OVSL(); - if (flow->mask) { struct sw_flow_mask *mask = flow->mask; + /* ovs-lock is required to protect mask-refcount and + * mask list. + */ + ASSERT_OVSL(); BUG_ON(!mask->ref_count); mask->ref_count--; -- cgit v0.10.2 From c14e0953ca51dbcb8d1ac92acbdcff23d0caa158 Mon Sep 17 00:00:00 2001 From: Andy Zhou Date: Sun, 2 Feb 2014 17:08:06 -0800 Subject: openvswitch: Suppress error messages on megaflow updates With subfacets, we'd expect megaflow updates message to carry the original micro flow. If not, EINVAL is returned and kernel logs an error message. Now that the user space subfacet layer is removed, it is expected that flow updates can arrive with a micro flow other than the original. Change the return code to EEXIST and remove the kernel error log message. Reported-by: Ben Pfaff Signed-off-by: Andy Zhou Signed-off-by: Jesse Gross diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index 58689dd..e9a48ba 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c @@ -860,11 +860,8 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info) goto err_unlock_ovs; /* The unmasked key has to be the same for flow updates. */ - error = -EINVAL; - if (!ovs_flow_cmp_unmasked_key(flow, &match)) { - OVS_NLERR("Flow modification message rejected, unmasked key does not match.\n"); + if (!ovs_flow_cmp_unmasked_key(flow, &match)) goto err_unlock_ovs; - } /* Update actions. */ old_acts = ovsl_dereference(flow->sf_acts); -- cgit v0.10.2 From 84a34575fe7c87278e4e00f016aa5b624dcb9171 Mon Sep 17 00:00:00 2001 From: "xinhui.pan" Date: Fri, 31 Jan 2014 13:08:01 -0800 Subject: gpio: intel-mid: fix the incorrect return of idle callback intel_gpio_runtime_idle should return correct error code if it do fail. make it more correct even though -EBUSY is the most possible return value. Signed-off-by: bo.he Signed-off-by: xinhui.pan Signed-off-by: David Cohen Reviewed-by: Felipe Balbi Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-intel-mid.c b/drivers/gpio/gpio-intel-mid.c index d1b50ef..e585163 100644 --- a/drivers/gpio/gpio-intel-mid.c +++ b/drivers/gpio/gpio-intel-mid.c @@ -394,8 +394,8 @@ static const struct irq_domain_ops intel_gpio_irq_ops = { static int intel_gpio_runtime_idle(struct device *dev) { - pm_schedule_suspend(dev, 500); - return -EBUSY; + int err = pm_schedule_suspend(dev, 500); + return err ?: -EBUSY; } static const struct dev_pm_ops intel_gpio_pm_ops = { -- cgit v0.10.2 From 6f587c9f7bbb50a2dc5ad7bdc43392cf608e0857 Mon Sep 17 00:00:00 2001 From: Markus Mayer Date: Mon, 3 Feb 2014 13:43:00 -0800 Subject: gpio: bcm281xx: Update MODULE_AUTHOR Add Broadcom's upstreaming mailing list address to MODULE_AUTHOR. Signed-off-by: Markus Mayer Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-bcm-kona.c b/drivers/gpio/gpio-bcm-kona.c index 233d088..f32357e 100644 --- a/drivers/gpio/gpio-bcm-kona.c +++ b/drivers/gpio/gpio-bcm-kona.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2013 Broadcom Corporation + * Copyright (C) 2012-2014 Broadcom Corporation * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -657,6 +657,6 @@ static struct platform_driver bcm_kona_gpio_driver = { module_platform_driver(bcm_kona_gpio_driver); -MODULE_AUTHOR("Broadcom"); +MODULE_AUTHOR("Broadcom Corporation "); MODULE_DESCRIPTION("Broadcom Kona GPIO Driver"); MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From 8d7f6690cedb83456edd41c9bd583783f0703bf0 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Mon, 3 Feb 2014 17:37:15 +0100 Subject: s390: fix kernel crash due to linkage stack instructions The kernel currently crashes with a low-address-protection exception if a user space process executes an instruction that tries to use the linkage stack. Set the base-ASTE origin and the subspace-ASTE origin of the dispatchable-unit-control-table to point to a dummy ASTE. Set up control register 15 to point to an empty linkage stack with no room left. A user space process with a linkage stack instruction will still crash but with a different exception which is correctly translated to a segmentation fault instead of a kernel oops. Signed-off-by: Martin Schwidefsky diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S index b9e25ae..d7c0050 100644 --- a/arch/s390/kernel/head64.S +++ b/arch/s390/kernel/head64.S @@ -59,7 +59,7 @@ ENTRY(startup_continue) .quad 0 # cr12: tracing off .quad 0 # cr13: home space segment table .quad 0xc0000000 # cr14: machine check handling off - .quad 0 # cr15: linkage stack operations + .quad .Llinkage_stack # cr15: linkage stack operations .Lpcmsk:.quad 0x0000000180000000 .L4malign:.quad 0xffffffffffc00000 .Lscan2g:.quad 0x80000000 + 0x20000 - 8 # 2GB + 128K - 8 @@ -67,12 +67,15 @@ ENTRY(startup_continue) .Lparmaddr: .quad PARMAREA .align 64 -.Lduct: .long 0,0,0,0,.Lduald,0,0,0 +.Lduct: .long 0,.Laste,.Laste,0,.Lduald,0,0,0 .long 0,0,0,0,0,0,0,0 +.Laste: .quad 0,0xffffffffffffffff,0,0,0,0,0,0 .align 128 .Lduald:.rept 8 .long 0x80000000,0,0,0 # invalid access-list entries .endr +.Llinkage_stack: + .long 0,0,0x89000000,0,0,0,0x8a000000,0 ENTRY(_ehead) -- cgit v0.10.2 From 21708c991eaea76080a9700117181c0d467af9fc Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 4 Feb 2014 17:39:15 +0800 Subject: gpio: clps711x: Add module alias to support module auto loading commit 55fe14ab872a "GPIO: clps711x: Rewrite driver for using generic GPIO code" allows this driver to be built as a module. Thus add module alias to support module auto loading. Signed-off-by: Axel Lin Signed-off-by: Linus Walleij diff --git a/drivers/gpio/gpio-clps711x.c b/drivers/gpio/gpio-clps711x.c index d355027..3c2ba2ad 100644 --- a/drivers/gpio/gpio-clps711x.c +++ b/drivers/gpio/gpio-clps711x.c @@ -97,3 +97,4 @@ module_platform_driver(clps711x_gpio_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Alexander Shiyan "); MODULE_DESCRIPTION("CLPS711X GPIO driver"); +MODULE_ALIAS("platform:clps711x-gpio"); -- cgit v0.10.2 From 90d16a43d50c6557ea8d6b7d3b597025c932ad92 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 4 Feb 2014 18:59:41 +0800 Subject: gpio: tb10x: GPIO_TB10X needs to select GENERIC_IRQ_CHIP gpio-tb10x driver uses generic irq chip APIs (irq_alloc_domain_generic_chips, irq_remove_generic_chip), so it needs to select GENERIC_IRQ_CHIP to avoid build error. Signed-off-by: Axel Lin Signed-off-by: Linus Walleij diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 6973387..903f24d 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -403,6 +403,7 @@ config GPIO_GRGPIO config GPIO_TB10X bool + select GENERIC_IRQ_CHIP select OF_GPIO comment "I2C GPIO expanders:" -- cgit v0.10.2 From 2a53bfb3e0fb6aa6b1ac93e5979a040a4b57ea8b Mon Sep 17 00:00:00 2001 From: Arturo Borrero Date: Fri, 17 Jan 2014 02:28:45 +0100 Subject: netfilter: nft_ct: fix unconditional dump of 'dir' attr We want to make sure that the information that we get from the kernel can be reinjected without troubles. The kernel shouldn't return an attribute that is not required, or even prohibited. Dumping unconditionally NFTA_CT_DIRECTION could lead an application in userspace to interpret that the attribute was originally set, while it was not. Signed-off-by: Arturo Borrero Gonzalez Signed-off-by: Pablo Neira Ayuso diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c index 917052e..feaf0f3 100644 --- a/net/netfilter/nft_ct.c +++ b/net/netfilter/nft_ct.c @@ -311,8 +311,19 @@ static int nft_ct_get_dump(struct sk_buff *skb, const struct nft_expr *expr) goto nla_put_failure; if (nla_put_be32(skb, NFTA_CT_KEY, htonl(priv->key))) goto nla_put_failure; - if (nla_put_u8(skb, NFTA_CT_DIRECTION, priv->dir)) - goto nla_put_failure; + + switch (priv->key) { + case NFT_CT_PROTOCOL: + case NFT_CT_SRC: + case NFT_CT_DST: + case NFT_CT_PROTO_SRC: + case NFT_CT_PROTO_DST: + if (nla_put_u8(skb, NFTA_CT_DIRECTION, priv->dir)) + goto nla_put_failure; + default: + break; + } + return 0; nla_put_failure: -- cgit v0.10.2 From 3dd7279fb6db05ec5a088cd0cae6ba22580a82bd Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 25 Jan 2014 08:04:07 +0000 Subject: netfilter: nf_tables: fix oops when deleting a chain with references The following commands trigger an oops: # nft -i nft> add table filter nft> add chain filter input { type filter hook input priority 0; } nft> add chain filter test nft> add rule filter input jump test nft> delete chain filter test We need to check the chain use counter before allowing destruction since we might have references from sets or jump rules. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=69341 Reported-by: Matthew Ife Tested-by: Matthew Ife Signed-off-by: Patrick McHardy Signed-off-by: Pablo Neira Ayuso diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 117bbaad..9ce3053 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -1045,7 +1045,7 @@ static int nf_tables_delchain(struct sock *nlsk, struct sk_buff *skb, if (IS_ERR(chain)) return PTR_ERR(chain); - if (!list_empty(&chain->rules)) + if (!list_empty(&chain->rules) || chain->use > 0) return -EBUSY; list_del(&chain->list); -- cgit v0.10.2 From c6825c0976fa7893692e0e43b09740b419b23c09 Mon Sep 17 00:00:00 2001 From: Andrey Vagin Date: Wed, 29 Jan 2014 19:34:14 +0100 Subject: netfilter: nf_conntrack: fix RCU race in nf_conntrack_find_get Lets look at destroy_conntrack: hlist_nulls_del_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode); ... nf_conntrack_free(ct) kmem_cache_free(net->ct.nf_conntrack_cachep, ct); net->ct.nf_conntrack_cachep is created with SLAB_DESTROY_BY_RCU. The hash is protected by rcu, so readers look up conntracks without locks. A conntrack is removed from the hash, but in this moment a few readers still can use the conntrack. Then this conntrack is released and another thread creates conntrack with the same address and the equal tuple. After this a reader starts to validate the conntrack: * It's not dying, because a new conntrack was created * nf_ct_tuple_equal() returns true. But this conntrack is not initialized yet, so it can not be used by two threads concurrently. In this case BUG_ON may be triggered from nf_nat_setup_info(). Florian Westphal suggested to check the confirm bit too. I think it's right. task 1 task 2 task 3 nf_conntrack_find_get ____nf_conntrack_find destroy_conntrack hlist_nulls_del_rcu nf_conntrack_free kmem_cache_free __nf_conntrack_alloc kmem_cache_alloc memset(&ct->tuplehash[IP_CT_DIR_MAX], if (nf_ct_is_dying(ct)) if (!nf_ct_tuple_equal() I'm not sure, that I have ever seen this race condition in a real life. Currently we are investigating a bug, which is reproduced on a few nodes. In our case one conntrack is initialized from a few tasks concurrently, we don't have any other explanation for this. <2>[46267.083061] kernel BUG at net/ipv4/netfilter/nf_nat_core.c:322! ... <4>[46267.083951] RIP: 0010:[] [] nf_nat_setup_info+0x564/0x590 [nf_nat] ... <4>[46267.085549] Call Trace: <4>[46267.085622] [] alloc_null_binding+0x5b/0xa0 [iptable_nat] <4>[46267.085697] [] nf_nat_rule_find+0x5c/0x80 [iptable_nat] <4>[46267.085770] [] nf_nat_fn+0x111/0x260 [iptable_nat] <4>[46267.085843] [] nf_nat_out+0x48/0xd0 [iptable_nat] <4>[46267.085919] [] nf_iterate+0x69/0xb0 <4>[46267.085991] [] ? ip_finish_output+0x0/0x2f0 <4>[46267.086063] [] nf_hook_slow+0x74/0x110 <4>[46267.086133] [] ? ip_finish_output+0x0/0x2f0 <4>[46267.086207] [] ? dst_output+0x0/0x20 <4>[46267.086277] [] ip_output+0xa4/0xc0 <4>[46267.086346] [] raw_sendmsg+0x8b4/0x910 <4>[46267.086419] [] inet_sendmsg+0x4a/0xb0 <4>[46267.086491] [] ? sock_update_classid+0x3a/0x50 <4>[46267.086562] [] sock_sendmsg+0x117/0x140 <4>[46267.086638] [] ? _spin_unlock_bh+0x1b/0x20 <4>[46267.086712] [] ? autoremove_wake_function+0x0/0x40 <4>[46267.086785] [] ? do_ip_setsockopt+0x90/0xd80 <4>[46267.086858] [] ? call_function_interrupt+0xe/0x20 <4>[46267.086936] [] ? ub_slab_ptr+0x20/0x90 <4>[46267.087006] [] ? ub_slab_ptr+0x20/0x90 <4>[46267.087081] [] ? kmem_cache_alloc+0xd8/0x1e0 <4>[46267.087151] [] sys_sendto+0x139/0x190 <4>[46267.087229] [] ? sock_setsockopt+0x16d/0x6f0 <4>[46267.087303] [] ? audit_syscall_entry+0x1d7/0x200 <4>[46267.087378] [] ? __audit_syscall_exit+0x265/0x290 <4>[46267.087454] [] ? compat_sys_setsockopt+0x75/0x210 <4>[46267.087531] [] compat_sys_socketcall+0x13f/0x210 <4>[46267.087607] [] ia32_sysret+0x0/0x5 <4>[46267.087676] Code: 91 20 e2 01 75 29 48 89 de 4c 89 f7 e8 56 fa ff ff 85 c0 0f 84 68 fc ff ff 0f b6 4d c6 41 8b 45 00 e9 4d fb ff ff e8 7c 19 e9 e0 <0f> 0b eb fe f6 05 17 91 20 e2 80 74 ce 80 3d 5f 2e 00 00 00 74 <1>[46267.088023] RIP [] nf_nat_setup_info+0x564/0x590 Cc: Eric Dumazet Cc: Florian Westphal Cc: Pablo Neira Ayuso Cc: Patrick McHardy Cc: Jozsef Kadlecsik Cc: "David S. Miller" Cc: Cyrill Gorcunov Signed-off-by: Andrey Vagin Acked-by: Eric Dumazet Signed-off-by: Pablo Neira Ayuso diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 8824ed0..4d1fb5d 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -312,6 +312,21 @@ static void death_by_timeout(unsigned long ul_conntrack) nf_ct_delete((struct nf_conn *)ul_conntrack, 0, 0); } +static inline bool +nf_ct_key_equal(struct nf_conntrack_tuple_hash *h, + const struct nf_conntrack_tuple *tuple, + u16 zone) +{ + struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h); + + /* A conntrack can be recreated with the equal tuple, + * so we need to check that the conntrack is confirmed + */ + return nf_ct_tuple_equal(tuple, &h->tuple) && + nf_ct_zone(ct) == zone && + nf_ct_is_confirmed(ct); +} + /* * Warning : * - Caller must take a reference on returned object @@ -333,8 +348,7 @@ ____nf_conntrack_find(struct net *net, u16 zone, local_bh_disable(); begin: hlist_nulls_for_each_entry_rcu(h, n, &net->ct.hash[bucket], hnnode) { - if (nf_ct_tuple_equal(tuple, &h->tuple) && - nf_ct_zone(nf_ct_tuplehash_to_ctrack(h)) == zone) { + if (nf_ct_key_equal(h, tuple, zone)) { NF_CT_STAT_INC(net, found); local_bh_enable(); return h; @@ -372,8 +386,7 @@ begin: !atomic_inc_not_zero(&ct->ct_general.use))) h = NULL; else { - if (unlikely(!nf_ct_tuple_equal(tuple, &h->tuple) || - nf_ct_zone(ct) != zone)) { + if (unlikely(!nf_ct_key_equal(h, tuple, zone))) { nf_ct_put(ct); goto begin; } -- cgit v0.10.2 From 662372e42e46d9bbfcb83e1cce81f6b33cebaddd Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Mon, 3 Feb 2014 08:53:44 -0600 Subject: of: restructure for_each macros to fix compile warnings Commit 00b2c76a6a "include/linux/of.h: make for_each_child_of_node() reference its args when CONFIG_OF=n" fixed warnings for unused variables, but introduced variable "used uninitialized" warnings. Simply initializing the variables would result in "set but not used" warnings with W=1. Fix both types of warnings by making all the for_each macros unconditional and rely on the dummy static inline functions to initialize and reference any variables. Reported-by: Geert Uytterhoeven Cc: David Howells Signed-off-by: Rob Herring Acked-by: Grant Likely diff --git a/include/linux/of.h b/include/linux/of.h index 70c64ba..435cb99 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -169,35 +169,15 @@ static inline const char *of_node_full_name(const struct device_node *np) extern struct device_node *of_find_node_by_name(struct device_node *from, const char *name); -#define for_each_node_by_name(dn, name) \ - for (dn = of_find_node_by_name(NULL, name); dn; \ - dn = of_find_node_by_name(dn, name)) extern struct device_node *of_find_node_by_type(struct device_node *from, const char *type); -#define for_each_node_by_type(dn, type) \ - for (dn = of_find_node_by_type(NULL, type); dn; \ - dn = of_find_node_by_type(dn, type)) extern struct device_node *of_find_compatible_node(struct device_node *from, const char *type, const char *compat); -#define for_each_compatible_node(dn, type, compatible) \ - for (dn = of_find_compatible_node(NULL, type, compatible); dn; \ - dn = of_find_compatible_node(dn, type, compatible)) extern struct device_node *of_find_matching_node_and_match( struct device_node *from, const struct of_device_id *matches, const struct of_device_id **match); -static inline struct device_node *of_find_matching_node( - struct device_node *from, - const struct of_device_id *matches) -{ - return of_find_matching_node_and_match(from, matches, NULL); -} -#define for_each_matching_node(dn, matches) \ - for (dn = of_find_matching_node(NULL, matches); dn; \ - dn = of_find_matching_node(dn, matches)) -#define for_each_matching_node_and_match(dn, matches, match) \ - for (dn = of_find_matching_node_and_match(NULL, matches, match); \ - dn; dn = of_find_matching_node_and_match(dn, matches, match)) + extern struct device_node *of_find_node_by_path(const char *path); extern struct device_node *of_find_node_by_phandle(phandle handle); extern struct device_node *of_get_parent(const struct device_node *node); @@ -209,43 +189,11 @@ extern struct device_node *of_get_next_available_child( extern struct device_node *of_get_child_by_name(const struct device_node *node, const char *name); -#define for_each_child_of_node(parent, child) \ - for (child = of_get_next_child(parent, NULL); child != NULL; \ - child = of_get_next_child(parent, child)) - -#define for_each_available_child_of_node(parent, child) \ - for (child = of_get_next_available_child(parent, NULL); child != NULL; \ - child = of_get_next_available_child(parent, child)) - -static inline int of_get_child_count(const struct device_node *np) -{ - struct device_node *child; - int num = 0; - - for_each_child_of_node(np, child) - num++; - - return num; -} - -static inline int of_get_available_child_count(const struct device_node *np) -{ - struct device_node *child; - int num = 0; - - for_each_available_child_of_node(np, child) - num++; - - return num; -} /* cache lookup */ extern struct device_node *of_find_next_cache_node(const struct device_node *); extern struct device_node *of_find_node_with_property( struct device_node *from, const char *prop_name); -#define for_each_node_with_property(dn, prop_name) \ - for (dn = of_find_node_with_property(NULL, prop_name); dn; \ - dn = of_find_node_with_property(dn, prop_name)) extern struct property *of_find_property(const struct device_node *np, const char *name, @@ -367,42 +315,53 @@ static inline struct device_node *of_find_node_by_name(struct device_node *from, return NULL; } -static inline struct device_node *of_get_parent(const struct device_node *node) +static inline struct device_node *of_find_node_by_type(struct device_node *from, + const char *type) { return NULL; } -static inline bool of_have_populated_dt(void) +static inline struct device_node *of_find_matching_node_and_match( + struct device_node *from, + const struct of_device_id *matches, + const struct of_device_id **match) { - return false; + return NULL; } -/* Kill an unused variable warning on a device_node pointer */ -static inline void __of_use_dn(const struct device_node *np) +static inline struct device_node *of_get_parent(const struct device_node *node) { + return NULL; } -#define for_each_child_of_node(parent, child) \ - while (__of_use_dn(parent), __of_use_dn(child), 0) +static inline struct device_node *of_get_next_child( + const struct device_node *node, struct device_node *prev) +{ + return NULL; +} -#define for_each_available_child_of_node(parent, child) \ - while (0) +static inline struct device_node *of_get_next_available_child( + const struct device_node *node, struct device_node *prev) +{ + return NULL; +} -static inline struct device_node *of_get_child_by_name( - const struct device_node *node, - const char *name) +static inline struct device_node *of_find_node_with_property( + struct device_node *from, const char *prop_name) { return NULL; } -static inline int of_get_child_count(const struct device_node *np) +static inline bool of_have_populated_dt(void) { - return 0; + return false; } -static inline int of_get_available_child_count(const struct device_node *np) +static inline struct device_node *of_get_child_by_name( + const struct device_node *node, + const char *name) { - return 0; + return NULL; } static inline int of_device_is_compatible(const struct device_node *device, @@ -569,6 +528,13 @@ extern int of_node_to_nid(struct device_node *np); static inline int of_node_to_nid(struct device_node *device) { return 0; } #endif +static inline struct device_node *of_find_matching_node( + struct device_node *from, + const struct of_device_id *matches) +{ + return of_find_matching_node_and_match(from, matches, NULL); +} + /** * of_property_read_bool - Findfrom a property * @np: device node from which the property value is to be read. @@ -618,6 +584,55 @@ static inline int of_property_read_u32(const struct device_node *np, s; \ s = of_prop_next_string(prop, s)) +#define for_each_node_by_name(dn, name) \ + for (dn = of_find_node_by_name(NULL, name); dn; \ + dn = of_find_node_by_name(dn, name)) +#define for_each_node_by_type(dn, type) \ + for (dn = of_find_node_by_type(NULL, type); dn; \ + dn = of_find_node_by_type(dn, type)) +#define for_each_compatible_node(dn, type, compatible) \ + for (dn = of_find_compatible_node(NULL, type, compatible); dn; \ + dn = of_find_compatible_node(dn, type, compatible)) +#define for_each_matching_node(dn, matches) \ + for (dn = of_find_matching_node(NULL, matches); dn; \ + dn = of_find_matching_node(dn, matches)) +#define for_each_matching_node_and_match(dn, matches, match) \ + for (dn = of_find_matching_node_and_match(NULL, matches, match); \ + dn; dn = of_find_matching_node_and_match(dn, matches, match)) + +#define for_each_child_of_node(parent, child) \ + for (child = of_get_next_child(parent, NULL); child != NULL; \ + child = of_get_next_child(parent, child)) +#define for_each_available_child_of_node(parent, child) \ + for (child = of_get_next_available_child(parent, NULL); child != NULL; \ + child = of_get_next_available_child(parent, child)) + +#define for_each_node_with_property(dn, prop_name) \ + for (dn = of_find_node_with_property(NULL, prop_name); dn; \ + dn = of_find_node_with_property(dn, prop_name)) + +static inline int of_get_child_count(const struct device_node *np) +{ + struct device_node *child; + int num = 0; + + for_each_child_of_node(np, child) + num++; + + return num; +} + +static inline int of_get_available_child_count(const struct device_node *np) +{ + struct device_node *child; + int num = 0; + + for_each_available_child_of_node(np, child) + num++; + + return num; +} + #if defined(CONFIG_PROC_FS) && defined(CONFIG_PROC_DEVICETREE) extern void proc_device_tree_add_node(struct device_node *, struct proc_dir_entry *); extern void proc_device_tree_add_prop(struct proc_dir_entry *pde, struct property *prop); -- cgit v0.10.2 From 14e2abb732e485ee57d9d5b2cb8884652238e5c1 Mon Sep 17 00:00:00 2001 From: Kleber Sacilotto de Souza Date: Mon, 3 Feb 2014 13:31:03 -0200 Subject: of: fix PCI bus match for PCIe slots On IBM pseries systems the device_type device-tree property of a PCIe bridge contains the string "pciex". The of_bus_pci_match() function was looking only for "pci" on this property, so in such cases the bus matching code was falling back to the default bus, causing problems on functions that should be using "assigned-addresses" for region address translation. This patch fixes the problem by also looking for "pciex" on the PCI bus match function. v2: added comment Signed-off-by: Kleber Sacilotto de Souza Acked-by: Grant Likely Cc: stable@vger.kernel.org Signed-off-by: Rob Herring diff --git a/drivers/of/address.c b/drivers/of/address.c index d3dd41c..1a54f1f 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c @@ -99,11 +99,12 @@ static unsigned int of_bus_default_get_flags(const __be32 *addr) static int of_bus_pci_match(struct device_node *np) { /* + * "pciex" is PCI Express * "vci" is for the /chaos bridge on 1st-gen PCI powermacs * "ht" is hypertransport */ - return !strcmp(np->type, "pci") || !strcmp(np->type, "vci") || - !strcmp(np->type, "ht"); + return !strcmp(np->type, "pci") || !strcmp(np->type, "pciex") || + !strcmp(np->type, "vci") || !strcmp(np->type, "ht"); } static void of_bus_pci_count_cells(struct device_node *np, -- cgit v0.10.2 From e066755163aaa4ae880a82d586e958051cf97c11 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Thu, 30 Jan 2014 15:18:46 +0100 Subject: dt-bindings: add vendor-prefix for neonode Neonode Inc. is the Manufacturer of the zforce infraread touchscreens used in a lot of ebook readers and supported by the zforce_ts driver. Signed-off-by: Heiko Stuebner Signed-off-by: Rob Herring diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index ba43b52..0f6ff61 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -57,6 +57,7 @@ maxim Maxim Integrated Products microchip Microchip Technology Inc. mosaixtech Mosaix Technologies, Inc. national National Semiconductor +neonode Neonode Inc. nintendo Nintendo nvidia NVIDIA nxp NXP Semiconductors -- cgit v0.10.2 From 1db73ae39a97797b7d929eca2af469f82fbb337a Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 3 Feb 2014 09:27:40 +0100 Subject: of/device: Nullify match table in of_match_device() for CONFIG_OF=n If the of_device_id table inside a device driver is protected by #ifdef CONFIG_OF, the driver still has to provide a dummy declaration of the table, or wrap it inside of_match_ptr(), when calling of_match_device() in the CONFIG_OF=n case, else the driver fails to compile with e.g. drivers/spi/spi-rspi.c: In function 'rspi_probe': drivers/spi/spi-rspi.c:1203:26: error: 'rspi_of_match' undeclared (first use in this function) drivers/spi/spi-rspi.c:1203:26: note: each undeclared identifier is reported only once for each function it appears in Make of_match_device() nullify the table pointer if CONFIG_OF=n to fix this. Reported-by: Yoshihiro Shimoda Signed-off-by: Geert Uytterhoeven Signed-off-by: Rob Herring diff --git a/include/linux/of_device.h b/include/linux/of_device.h index 8d7dd67..ef37021 100644 --- a/include/linux/of_device.h +++ b/include/linux/of_device.h @@ -78,11 +78,13 @@ static inline int of_device_uevent_modalias(struct device *dev, static inline void of_device_node_put(struct device *dev) { } -static inline const struct of_device_id *of_match_device( +static inline const struct of_device_id *__of_match_device( const struct of_device_id *matches, const struct device *dev) { return NULL; } +#define of_match_device(matches, dev) \ + __of_match_device(of_match_ptr(matches), (dev)) static inline struct device_node *of_cpu_device_node_get(int cpu) { -- cgit v0.10.2 From 7896052d90d7de899fd3a34c0b34e91941e2f2ea Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Fri, 13 Dec 2013 09:11:01 -0500 Subject: drm/msm: fix inconsequential typo Small typo I noticed in the mdp4_plane code.. no consequence because PIPE_SRC_XY and PIPE_DST_XY have same register layout. Signed-off-by: Rob Clark diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c index 2406027..1e893dd 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c @@ -170,8 +170,8 @@ int mdp4_plane_mode_set(struct drm_plane *plane, MDP4_PIPE_DST_SIZE_HEIGHT(crtc_h)); mdp4_write(mdp4_kms, REG_MDP4_PIPE_DST_XY(pipe), - MDP4_PIPE_SRC_XY_X(crtc_x) | - MDP4_PIPE_SRC_XY_Y(crtc_y)); + MDP4_PIPE_DST_XY_X(crtc_x) | + MDP4_PIPE_DST_XY_Y(crtc_y)); mdp4_plane_set_scanout(plane, fb); -- cgit v0.10.2 From 37033a7689b01d0c46f9cc450bdf9f02d86b7e57 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Fri, 13 Dec 2013 10:38:54 -0500 Subject: drm/msm/mdp5: fix ref leaks in error paths Signed-off-by: Rob Clark diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c index 71a3b23..f279402 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c @@ -296,6 +296,7 @@ static int mdp5_crtc_mode_set(struct drm_crtc *crtc, x << 16, y << 16, mode->hdisplay << 16, mode->vdisplay << 16); if (ret) { + drm_framebuffer_unreference(crtc->fb); dev_err(crtc->dev->dev, "%s: failed to set mode on plane: %d\n", mdp5_crtc->name, ret); return ret; @@ -343,11 +344,15 @@ static int mdp5_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, 0, 0, mode->hdisplay, mode->vdisplay, x << 16, y << 16, mode->hdisplay << 16, mode->vdisplay << 16); + if (ret) { + drm_framebuffer_unreference(crtc->fb); + return ret; + } update_fb(crtc, crtc->fb); update_scanout(crtc, crtc->fb); - return ret; + return 0; } static void mdp5_crtc_load_lut(struct drm_crtc *crtc) -- cgit v0.10.2 From b69720c0f5d417310fbfd59c2d681bd90430a4f5 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Fri, 13 Dec 2013 10:41:07 -0500 Subject: drm/msm/mdp4: pageflip fixes Backport a few fixes found in the course of getting mdp5 working. There is a window of time after pageflip is requested, before we start scanning out the new fb (ie. while we are waiting for gpu). During that time we need to continue holding a reference to the still-current scanout fb, to avoid the backing gem bo's from being destroyed. Possibly a common mdp_crtc parent class could be useful to share some of this logic between mdp4_crtc and mdp5_crtc. OTOH, this all can be removed from the driver once atomic is in place, as plane/crtc updates get deferred until all fb's are ready before calling in to .page_flip(), etc. Signed-off-by: Rob Clark diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c index 1964f4f..ed739e8 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c @@ -57,9 +57,16 @@ struct mdp4_crtc { #define PENDING_FLIP 0x2 atomic_t pending; - /* the fb that we currently hold a scanout ref to: */ + /* the fb that we logically (from PoV of KMS API) hold a ref + * to. Which we may not yet be scanning out (we may still + * be scanning out previous in case of page_flip while waiting + * for gpu rendering to complete: + */ struct drm_framebuffer *fb; + /* the fb that we currently hold a scanout ref to: */ + struct drm_framebuffer *scanout_fb; + /* for unref'ing framebuffers after scanout completes: */ struct drm_flip_work unref_fb_work; @@ -77,24 +84,73 @@ static struct mdp4_kms *get_kms(struct drm_crtc *crtc) return to_mdp4_kms(to_mdp_kms(priv->kms)); } -static void update_fb(struct drm_crtc *crtc, bool async, - struct drm_framebuffer *new_fb) +static void request_pending(struct drm_crtc *crtc, uint32_t pending) { struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc); - struct drm_framebuffer *old_fb = mdp4_crtc->fb; - if (old_fb) - drm_flip_work_queue(&mdp4_crtc->unref_fb_work, old_fb); + atomic_or(pending, &mdp4_crtc->pending); + mdp_irq_register(&get_kms(crtc)->base, &mdp4_crtc->vblank); +} + +static void crtc_flush(struct drm_crtc *crtc) +{ + struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc); + struct mdp4_kms *mdp4_kms = get_kms(crtc); + uint32_t i, flush = 0; + + for (i = 0; i < ARRAY_SIZE(mdp4_crtc->planes); i++) { + struct drm_plane *plane = mdp4_crtc->planes[i]; + if (plane) { + enum mdp4_pipe pipe_id = mdp4_plane_pipe(plane); + flush |= pipe2flush(pipe_id); + } + } + flush |= ovlp2flush(mdp4_crtc->ovlp); + + DBG("%s: flush=%08x", mdp4_crtc->name, flush); + + mdp4_write(mdp4_kms, REG_MDP4_OVERLAY_FLUSH, flush); +} + +static void update_fb(struct drm_crtc *crtc, struct drm_framebuffer *new_fb) +{ + struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc); + struct drm_framebuffer *old_fb = mdp4_crtc->fb; /* grab reference to incoming scanout fb: */ drm_framebuffer_reference(new_fb); mdp4_crtc->base.fb = new_fb; mdp4_crtc->fb = new_fb; - if (!async) { - /* enable vblank to pick up the old_fb */ - mdp_irq_register(&get_kms(crtc)->base, &mdp4_crtc->vblank); - } + if (old_fb) + drm_flip_work_queue(&mdp4_crtc->unref_fb_work, old_fb); +} + +/* unlike update_fb(), take a ref to the new scanout fb *before* updating + * plane, then call this. Needed to ensure we don't unref the buffer that + * is actually still being scanned out. + * + * Note that this whole thing goes away with atomic.. since we can defer + * calling into driver until rendering is done. + */ +static void update_scanout(struct drm_crtc *crtc, struct drm_framebuffer *fb) +{ + struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc); + + /* flush updates, to make sure hw is updated to new scanout fb, + * so that we can safely queue unref to current fb (ie. next + * vblank we know hw is done w/ previous scanout_fb). + */ + crtc_flush(crtc); + + if (mdp4_crtc->scanout_fb) + drm_flip_work_queue(&mdp4_crtc->unref_fb_work, + mdp4_crtc->scanout_fb); + + mdp4_crtc->scanout_fb = fb; + + /* enable vblank to complete flip: */ + request_pending(crtc, PENDING_FLIP); } /* if file!=NULL, this is preclose potential cancel-flip path */ @@ -120,34 +176,6 @@ static void complete_flip(struct drm_crtc *crtc, struct drm_file *file) spin_unlock_irqrestore(&dev->event_lock, flags); } -static void crtc_flush(struct drm_crtc *crtc) -{ - struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc); - struct mdp4_kms *mdp4_kms = get_kms(crtc); - uint32_t i, flush = 0; - - for (i = 0; i < ARRAY_SIZE(mdp4_crtc->planes); i++) { - struct drm_plane *plane = mdp4_crtc->planes[i]; - if (plane) { - enum mdp4_pipe pipe_id = mdp4_plane_pipe(plane); - flush |= pipe2flush(pipe_id); - } - } - flush |= ovlp2flush(mdp4_crtc->ovlp); - - DBG("%s: flush=%08x", mdp4_crtc->name, flush); - - mdp4_write(mdp4_kms, REG_MDP4_OVERLAY_FLUSH, flush); -} - -static void request_pending(struct drm_crtc *crtc, uint32_t pending) -{ - struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc); - - atomic_or(pending, &mdp4_crtc->pending); - mdp_irq_register(&get_kms(crtc)->base, &mdp4_crtc->vblank); -} - static void pageflip_cb(struct msm_fence_cb *cb) { struct mdp4_crtc *mdp4_crtc = @@ -158,11 +186,9 @@ static void pageflip_cb(struct msm_fence_cb *cb) if (!fb) return; + drm_framebuffer_reference(fb); mdp4_plane_set_scanout(mdp4_crtc->plane, fb); - crtc_flush(crtc); - - /* enable vblank to complete flip: */ - request_pending(crtc, PENDING_FLIP); + update_scanout(crtc, fb); } static void unref_fb_worker(struct drm_flip_work *work, void *val) @@ -320,6 +346,20 @@ static int mdp4_crtc_mode_set(struct drm_crtc *crtc, mode->vsync_end, mode->vtotal, mode->type, mode->flags); + /* grab extra ref for update_scanout() */ + drm_framebuffer_reference(crtc->fb); + + ret = mdp4_plane_mode_set(mdp4_crtc->plane, crtc, crtc->fb, + 0, 0, mode->hdisplay, mode->vdisplay, + x << 16, y << 16, + mode->hdisplay << 16, mode->vdisplay << 16); + if (ret) { + drm_framebuffer_unreference(crtc->fb); + dev_err(crtc->dev->dev, "%s: failed to set mode on plane: %d\n", + mdp4_crtc->name, ret); + return ret; + } + mdp4_write(mdp4_kms, REG_MDP4_DMA_SRC_SIZE(dma), MDP4_DMA_SRC_SIZE_WIDTH(mode->hdisplay) | MDP4_DMA_SRC_SIZE_HEIGHT(mode->vdisplay)); @@ -341,24 +381,15 @@ static int mdp4_crtc_mode_set(struct drm_crtc *crtc, mdp4_write(mdp4_kms, REG_MDP4_OVLP_CFG(ovlp), 1); - update_fb(crtc, false, crtc->fb); - - ret = mdp4_plane_mode_set(mdp4_crtc->plane, crtc, crtc->fb, - 0, 0, mode->hdisplay, mode->vdisplay, - x << 16, y << 16, - mode->hdisplay << 16, mode->vdisplay << 16); - if (ret) { - dev_err(crtc->dev->dev, "%s: failed to set mode on plane: %d\n", - mdp4_crtc->name, ret); - return ret; - } - if (dma == DMA_E) { mdp4_write(mdp4_kms, REG_MDP4_DMA_E_QUANT(0), 0x00ff0000); mdp4_write(mdp4_kms, REG_MDP4_DMA_E_QUANT(1), 0x00ff0000); mdp4_write(mdp4_kms, REG_MDP4_DMA_E_QUANT(2), 0x00ff0000); } + update_fb(crtc, crtc->fb); + update_scanout(crtc, crtc->fb); + return 0; } @@ -385,13 +416,24 @@ static int mdp4_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc); struct drm_plane *plane = mdp4_crtc->plane; struct drm_display_mode *mode = &crtc->mode; + int ret; - update_fb(crtc, false, crtc->fb); + /* grab extra ref for update_scanout() */ + drm_framebuffer_reference(crtc->fb); - return mdp4_plane_mode_set(plane, crtc, crtc->fb, + ret = mdp4_plane_mode_set(plane, crtc, crtc->fb, 0, 0, mode->hdisplay, mode->vdisplay, x << 16, y << 16, mode->hdisplay << 16, mode->vdisplay << 16); + if (ret) { + drm_framebuffer_unreference(crtc->fb); + return ret; + } + + update_fb(crtc, crtc->fb); + update_scanout(crtc, crtc->fb); + + return 0; } static void mdp4_crtc_load_lut(struct drm_crtc *crtc) @@ -419,7 +461,7 @@ static int mdp4_crtc_page_flip(struct drm_crtc *crtc, mdp4_crtc->event = event; spin_unlock_irqrestore(&dev->event_lock, flags); - update_fb(crtc, true, new_fb); + update_fb(crtc, new_fb); return msm_gem_queue_inactive_cb(obj, &mdp4_crtc->pageflip_cb); } @@ -713,6 +755,7 @@ struct drm_crtc *mdp4_crtc_init(struct drm_device *dev, crtc = &mdp4_crtc->base; mdp4_crtc->plane = plane; + mdp4_crtc->id = id; mdp4_crtc->ovlp = ovlp_id; mdp4_crtc->dma = dma_id; -- cgit v0.10.2 From aa1b0e59d3096f4602afeb114a3b3be505889a26 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Fri, 13 Dec 2013 10:49:25 -0500 Subject: drm/msm/mdp4: cursor fixes It seems we need to update all cursor registers from vblank. This appears to be the cause of intermittent underflows when enabling/ disabling cursor. Signed-off-by: Rob Clark diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c index ed739e8..84c5b13 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c @@ -39,6 +39,7 @@ struct mdp4_crtc { spinlock_t lock; bool stale; uint32_t width, height; + uint32_t x, y; /* next cursor to scan-out: */ uint32_t next_iova; @@ -484,12 +485,12 @@ static int mdp4_crtc_set_property(struct drm_crtc *crtc, static void update_cursor(struct drm_crtc *crtc) { struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc); + struct mdp4_kms *mdp4_kms = get_kms(crtc); enum mdp4_dma dma = mdp4_crtc->dma; unsigned long flags; spin_lock_irqsave(&mdp4_crtc->cursor.lock, flags); if (mdp4_crtc->cursor.stale) { - struct mdp4_kms *mdp4_kms = get_kms(crtc); struct drm_gem_object *next_bo = mdp4_crtc->cursor.next_bo; struct drm_gem_object *prev_bo = mdp4_crtc->cursor.scanout_bo; uint32_t iova = mdp4_crtc->cursor.next_iova; @@ -521,6 +522,11 @@ static void update_cursor(struct drm_crtc *crtc) mdp4_crtc->cursor.scanout_bo = next_bo; mdp4_crtc->cursor.stale = false; } + + mdp4_write(mdp4_kms, REG_MDP4_DMA_CURSOR_POS(dma), + MDP4_DMA_CURSOR_POS_X(mdp4_crtc->cursor.x) | + MDP4_DMA_CURSOR_POS_Y(mdp4_crtc->cursor.y)); + spin_unlock_irqrestore(&mdp4_crtc->cursor.lock, flags); } @@ -572,6 +578,7 @@ static int mdp4_crtc_cursor_set(struct drm_crtc *crtc, drm_gem_object_unreference_unlocked(old_bo); } + crtc_flush(crtc); request_pending(crtc, PENDING_CURSOR); return 0; @@ -584,12 +591,15 @@ fail: static int mdp4_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) { struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc); - struct mdp4_kms *mdp4_kms = get_kms(crtc); - enum mdp4_dma dma = mdp4_crtc->dma; + unsigned long flags; - mdp4_write(mdp4_kms, REG_MDP4_DMA_CURSOR_POS(dma), - MDP4_DMA_CURSOR_POS_X(x) | - MDP4_DMA_CURSOR_POS_Y(y)); + spin_lock_irqsave(&mdp4_crtc->cursor.lock, flags); + mdp4_crtc->cursor.x = x; + mdp4_crtc->cursor.y = y; + spin_unlock_irqrestore(&mdp4_crtc->cursor.lock, flags); + + crtc_flush(crtc); + request_pending(crtc, PENDING_CURSOR); return 0; } -- cgit v0.10.2 From 9999f105e76977d97304d7cb2030a52d96800d69 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Tue, 4 Feb 2014 14:17:32 -0500 Subject: drm/msm: fix deadlock in bo create fail path We already hold struct_mutex here. Signed-off-by: Rob Clark diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index d8d60c9..3da8264 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -644,7 +644,7 @@ struct drm_gem_object *msm_gem_new(struct drm_device *dev, fail: if (obj) - drm_gem_object_unreference_unlocked(obj); + drm_gem_object_unreference(obj); return ERR_PTR(ret); } -- cgit v0.10.2 From 860a445c25aa2f99aa5881603a1f4ed2cec64025 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 4 Feb 2014 22:59:09 +0100 Subject: DT: Add vendor prefix for Spansion Inc. This is already in active use in several DTS files. Signed-off-by: Geert Uytterhoeven Signed-off-by: Rob Herring diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 0f6ff61..40ce2df 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -81,6 +81,7 @@ silabs Silicon Laboratories simtek sirf SiRF Technology, Inc. snps Synopsys, Inc. +spansion Spansion Inc. st STMicroelectronics ste ST-Ericsson stericsson ST-Ericsson -- cgit v0.10.2 From 829d9315c46a2be57a8fb40c89aeb7db61513d96 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Mon, 3 Feb 2014 13:07:24 +0100 Subject: netfilter: nf_nat_h323: fix crash in nf_ct_unlink_expect_report() Similar bug fixed in SIP module in 3f509c6 ("netfilter: nf_nat_sip: fix incorrect handling of EBUSY for RTCP expectation"). BUG: unable to handle kernel paging request at 00100104 IP: [] nf_ct_unlink_expect_report+0x57/0xf0 [nf_conntrack] ... Call Trace: [] ? del_timer+0x48/0x70 [] nf_ct_remove_expectations+0x47/0x60 [nf_conntrack] [] nf_ct_delete_from_lists+0x59/0x90 [nf_conntrack] [] death_by_timeout+0x14e/0x1c0 [nf_conntrack] [] ? nf_conntrack_set_hashsize+0x190/0x190 [nf_conntrack] [] call_timer_fn+0x1d/0x80 [] run_timer_softirq+0x18e/0x1a0 [] ? nf_conntrack_set_hashsize+0x190/0x190 [nf_conntrack] [] __do_softirq+0xa3/0x170 [] ? __local_bh_enable+0x70/0x70 [] ? irq_exit+0x67/0xa0 [] ? do_IRQ+0x46/0xb0 [] ? clockevents_notify+0x35/0x110 [] ? common_interrupt+0x2c/0x40 [] ? cpuidle_enter_state+0x41/0xf0 [] ? cpuidle_idle_call+0x8b/0x100 [] ? arch_cpu_idle+0x8/0x30 [] ? cpu_idle_loop+0x4b/0x140 [] ? cpu_startup_entry+0x18/0x20 [] ? rest_init+0x5d/0x70 [] ? start_kernel+0x2ec/0x2f2 [] ? repair_env_string+0x5b/0x5b [] ? i386_start_kernel+0x33/0x35 Signed-off-by: Alexey Dobriyan Signed-off-by: Pablo Neira Ayuso diff --git a/net/ipv4/netfilter/nf_nat_h323.c b/net/ipv4/netfilter/nf_nat_h323.c index 9eea059d..574f7eb 100644 --- a/net/ipv4/netfilter/nf_nat_h323.c +++ b/net/ipv4/netfilter/nf_nat_h323.c @@ -229,7 +229,10 @@ static int nat_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct, ret = nf_ct_expect_related(rtcp_exp); if (ret == 0) break; - else if (ret != -EBUSY) { + else if (ret == -EBUSY) { + nf_ct_unexpect_related(rtp_exp); + continue; + } else if (ret < 0) { nf_ct_unexpect_related(rtp_exp); nated_port = 0; break; -- cgit v0.10.2 From e53376bef2cd97d3e3f61fdc677fb8da7d03d0da Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 3 Feb 2014 20:01:53 +0100 Subject: netfilter: nf_conntrack: don't release a conntrack with non-zero refcnt With this patch, the conntrack refcount is initially set to zero and it is bumped once it is added to any of the list, so we fulfill Eric's golden rule which is that all released objects always have a refcount that equals zero. Andrey Vagin reports that nf_conntrack_free can't be called for a conntrack with non-zero ref-counter, because it can race with nf_conntrack_find_get(). A conntrack slab is created with SLAB_DESTROY_BY_RCU. Non-zero ref-counter says that this conntrack is used. So when we release a conntrack with non-zero counter, we break this assumption. CPU1 CPU2 ____nf_conntrack_find() nf_ct_put() destroy_conntrack() ... init_conntrack __nf_conntrack_alloc (set use = 1) atomic_inc_not_zero(&ct->use) (use = 2) if (!l4proto->new(ct, skb, dataoff, timeouts)) nf_conntrack_free(ct); (use = 2 !!!) ... __nf_conntrack_alloc (set use = 1) if (!nf_ct_key_equal(h, tuple, zone)) nf_ct_put(ct); (use = 0) destroy_conntrack() /* continue to work with CT */ After applying the path "[PATCH] netfilter: nf_conntrack: fix RCU race in nf_conntrack_find_get" another bug was triggered in destroy_conntrack(): <4>[67096.759334] ------------[ cut here ]------------ <2>[67096.759353] kernel BUG at net/netfilter/nf_conntrack_core.c:211! ... <4>[67096.759837] Pid: 498649, comm: atdd veid: 666 Tainted: G C --------------- 2.6.32-042stab084.18 #1 042stab084_18 /DQ45CB <4>[67096.759932] RIP: 0010:[] [] destroy_conntrack+0x15c/0x190 [nf_conntrack] <4>[67096.760255] Call Trace: <4>[67096.760255] [] nf_conntrack_destroy+0x17/0x30 <4>[67096.760255] [] nf_conntrack_find_get+0x85/0x130 [nf_conntrack] <4>[67096.760255] [] nf_conntrack_in+0x352/0xb60 [nf_conntrack] <4>[67096.760255] [] ipv4_conntrack_local+0x51/0x60 [nf_conntrack_ipv4] <4>[67096.760255] [] nf_iterate+0x69/0xb0 <4>[67096.760255] [] ? dst_output+0x0/0x20 <4>[67096.760255] [] nf_hook_slow+0x74/0x110 <4>[67096.760255] [] ? dst_output+0x0/0x20 <4>[67096.760255] [] raw_sendmsg+0x775/0x910 <4>[67096.760255] [] ? flush_tlb_others_ipi+0x128/0x130 <4>[67096.760255] [] ? apic_timer_interrupt+0xe/0x20 <4>[67096.760255] [] ? apic_timer_interrupt+0xe/0x20 <4>[67096.760255] [] inet_sendmsg+0x4a/0xb0 <4>[67096.760255] [] ? sock_sendmsg+0x13/0x140 <4>[67096.760255] [] sock_sendmsg+0x117/0x140 <4>[67096.760255] [] ? native_smp_send_reschedule+0x49/0x60 <4>[67096.760255] [] ? _spin_unlock_bh+0x1b/0x20 <4>[67096.760255] [] ? autoremove_wake_function+0x0/0x40 <4>[67096.760255] [] ? do_ip_setsockopt+0x90/0xd80 <4>[67096.760255] [] ? apic_timer_interrupt+0xe/0x20 <4>[67096.760255] [] ? apic_timer_interrupt+0xe/0x20 <4>[67096.760255] [] sys_sendto+0x139/0x190 <4>[67096.760255] [] ? audit_syscall_entry+0x1d7/0x200 <4>[67096.760255] [] ? __audit_syscall_exit+0x265/0x290 <4>[67096.760255] [] compat_sys_socketcall+0x13f/0x210 <4>[67096.760255] [] ia32_sysret+0x0/0x5 I have reused the original title for the RFC patch that Andrey posted and most of the original patch description. Cc: Eric Dumazet Cc: Andrew Vagin Cc: Florian Westphal Reported-by: Andrew Vagin Signed-off-by: Pablo Neira Ayuso Reviewed-by: Eric Dumazet Acked-by: Andrew Vagin diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index 01ea6ee..b2ac624 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h @@ -284,6 +284,8 @@ extern unsigned int nf_conntrack_max; extern unsigned int nf_conntrack_hash_rnd; void init_nf_conntrack_hash_rnd(void); +void nf_conntrack_tmpl_insert(struct net *net, struct nf_conn *tmpl); + #define NF_CT_STAT_INC(net, count) __this_cpu_inc((net)->ct.stat->count) #define NF_CT_STAT_INC_ATOMIC(net, count) this_cpu_inc((net)->ct.stat->count) diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 4d1fb5d..356bef5 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -448,7 +448,9 @@ nf_conntrack_hash_check_insert(struct nf_conn *ct) goto out; add_timer(&ct->timeout); - nf_conntrack_get(&ct->ct_general); + smp_wmb(); + /* The caller holds a reference to this object */ + atomic_set(&ct->ct_general.use, 2); __nf_conntrack_hash_insert(ct, hash, repl_hash); NF_CT_STAT_INC(net, insert); spin_unlock_bh(&nf_conntrack_lock); @@ -462,6 +464,21 @@ out: } EXPORT_SYMBOL_GPL(nf_conntrack_hash_check_insert); +/* deletion from this larval template list happens via nf_ct_put() */ +void nf_conntrack_tmpl_insert(struct net *net, struct nf_conn *tmpl) +{ + __set_bit(IPS_TEMPLATE_BIT, &tmpl->status); + __set_bit(IPS_CONFIRMED_BIT, &tmpl->status); + nf_conntrack_get(&tmpl->ct_general); + + spin_lock_bh(&nf_conntrack_lock); + /* Overload tuple linked list to put us in template list. */ + hlist_nulls_add_head_rcu(&tmpl->tuplehash[IP_CT_DIR_ORIGINAL].hnnode, + &net->ct.tmpl); + spin_unlock_bh(&nf_conntrack_lock); +} +EXPORT_SYMBOL_GPL(nf_conntrack_tmpl_insert); + /* Confirm a connection given skb; places it in hash table */ int __nf_conntrack_confirm(struct sk_buff *skb) @@ -733,11 +750,10 @@ __nf_conntrack_alloc(struct net *net, u16 zone, nf_ct_zone->id = zone; } #endif - /* - * changes to lookup keys must be done before setting refcnt to 1 + /* Because we use RCU lookups, we set ct_general.use to zero before + * this is inserted in any list. */ - smp_wmb(); - atomic_set(&ct->ct_general.use, 1); + atomic_set(&ct->ct_general.use, 0); return ct; #ifdef CONFIG_NF_CONNTRACK_ZONES @@ -761,6 +777,11 @@ void nf_conntrack_free(struct nf_conn *ct) { struct net *net = nf_ct_net(ct); + /* A freed object has refcnt == 0, that's + * the golden rule for SLAB_DESTROY_BY_RCU + */ + NF_CT_ASSERT(atomic_read(&ct->ct_general.use) == 0); + nf_ct_ext_destroy(ct); nf_ct_ext_free(ct); kmem_cache_free(net->ct.nf_conntrack_cachep, ct); @@ -856,6 +877,9 @@ init_conntrack(struct net *net, struct nf_conn *tmpl, NF_CT_STAT_INC(net, new); } + /* Now it is inserted into the unconfirmed list, bump refcount */ + nf_conntrack_get(&ct->ct_general); + /* Overload tuple linked list to put us in unconfirmed list. */ hlist_nulls_add_head_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode, &net->ct.unconfirmed); diff --git a/net/netfilter/nf_synproxy_core.c b/net/netfilter/nf_synproxy_core.c index 9858e3e..52e20c9 100644 --- a/net/netfilter/nf_synproxy_core.c +++ b/net/netfilter/nf_synproxy_core.c @@ -363,9 +363,8 @@ static int __net_init synproxy_net_init(struct net *net) goto err2; if (!nfct_synproxy_ext_add(ct)) goto err2; - __set_bit(IPS_TEMPLATE_BIT, &ct->status); - __set_bit(IPS_CONFIRMED_BIT, &ct->status); + nf_conntrack_tmpl_insert(net, ct); snet->tmpl = ct; snet->stats = alloc_percpu(struct synproxy_stats); @@ -390,7 +389,7 @@ static void __net_exit synproxy_net_exit(struct net *net) { struct synproxy_net *snet = synproxy_pernet(net); - nf_conntrack_free(snet->tmpl); + nf_ct_put(snet->tmpl); synproxy_proc_exit(net); free_percpu(snet->stats); } diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c index 5929be6..75747ae 100644 --- a/net/netfilter/xt_CT.c +++ b/net/netfilter/xt_CT.c @@ -228,12 +228,7 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par, goto err3; } - __set_bit(IPS_TEMPLATE_BIT, &ct->status); - __set_bit(IPS_CONFIRMED_BIT, &ct->status); - - /* Overload tuple linked list to put us in template list. */ - hlist_nulls_add_head_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode, - &par->net->ct.tmpl); + nf_conntrack_tmpl_insert(par->net, ct); out: info->ct = ct; return 0; -- cgit v0.10.2 From 53b70287ddf487a38b7cbf0a10db28f40714b799 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 5 Feb 2014 12:26:22 +0100 Subject: netfilter: nf_tables: fix overrun in nf_tables_set_alloc_name() The map that is used to allocate anonymous sets is indeed BITS_PER_BYTE * PAGE_SIZE long. Signed-off-by: Patrick McHardy Signed-off-by: Pablo Neira Ayuso diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 9ce3053..2a22a18 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -1989,13 +1989,13 @@ static int nf_tables_set_alloc_name(struct nft_ctx *ctx, struct nft_set *set, if (!sscanf(i->name, name, &tmp)) continue; - if (tmp < 0 || tmp > BITS_PER_LONG * PAGE_SIZE) + if (tmp < 0 || tmp >= BITS_PER_BYTE * PAGE_SIZE) continue; set_bit(tmp, inuse); } - n = find_first_zero_bit(inuse, BITS_PER_LONG * PAGE_SIZE); + n = find_first_zero_bit(inuse, BITS_PER_BYTE * PAGE_SIZE); free_page((unsigned long)inuse); } -- cgit v0.10.2 From 667a6b7a620ec6e0c1e6689b8c6531c51ce6cdfa Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 5 Feb 2014 17:56:27 +0100 Subject: regulator: max14577: Add missing of_node_put Decrease the reference count for 'regulators' device_node, obtained by of_get_child_by_name(). Signed-off-by: Krzysztof Kozlowski Signed-off-by: Mark Brown diff --git a/drivers/regulator/max14577.c b/drivers/regulator/max14577.c index b1078ba3..186df87 100644 --- a/drivers/regulator/max14577.c +++ b/drivers/regulator/max14577.c @@ -168,10 +168,11 @@ static int max14577_regulator_dt_parse_pdata(struct platform_device *pdev) MAX14577_REG_MAX); if (ret < 0) { dev_err(&pdev->dev, "Error parsing regulator init data: %d\n", ret); - return ret; } - return 0; + of_node_put(np); + + return ret; } static inline struct regulator_init_data *match_init_data(int index) -- cgit v0.10.2 From f948dcf9e9973c05d957bc65b3185682f45feda3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Tue, 4 Feb 2014 13:02:31 +0100 Subject: usb: qcserial: add Netgear Aircard 340U MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This device was mentioned in an OpenWRT forum. Seems to have a "standard" Sierra Wireless ifnumber to function layout: 0: qcdm 2: nmea 3: modem 8: qmi 9: storage Cc: Signed-off-by: Bjørn Mork Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index c65437c..968a402 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -139,6 +139,9 @@ static const struct usb_device_id id_table[] = { {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x901c, 0)}, /* Sierra Wireless EM7700 Device Management */ {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x901c, 2)}, /* Sierra Wireless EM7700 NMEA */ {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x901c, 3)}, /* Sierra Wireless EM7700 Modem */ + {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x9051, 0)}, /* Netgear AirCard 340U Device Management */ + {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x9051, 2)}, /* Netgear AirCard 340U NMEA */ + {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x9051, 3)}, /* Netgear AirCard 340U Modem */ { } /* Terminating entry */ }; -- cgit v0.10.2 From 76f24e3f39a1a94bab0d54e98899d64abcd9f69c Mon Sep 17 00:00:00 2001 From: Ulrich Hahn Date: Sun, 2 Feb 2014 14:42:52 +0100 Subject: USB: ftdi_sio: add Tagsys RFID Reader IDs Adding two more IDs to the ftdi_sio usb serial driver. It now connects Tagsys RFID readers. There might be more IDs out there for other Tagsys models. Signed-off-by: Ulrich Hahn Cc: Johan Hovold Cc: stable Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 0f3248a..ee1f00f 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -192,6 +192,8 @@ static const struct usb_device_id id_table_combined[] = { { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) }, { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) }, { USB_DEVICE(FTDI_VID, FTDI_SPROG_II) }, + { USB_DEVICE(FTDI_VID, FTDI_TAGSYS_LP101_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_TAGSYS_P200X_PID) }, { USB_DEVICE(FTDI_VID, FTDI_LENZ_LIUSB_PID) }, { USB_DEVICE(FTDI_VID, FTDI_XF_632_PID) }, { USB_DEVICE(FTDI_VID, FTDI_XF_634_PID) }, diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index eb03021..1e2d369 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -364,6 +364,12 @@ /* Sprog II (Andrew Crosland's SprogII DCC interface) */ #define FTDI_SPROG_II 0xF0C8 +/* + * Two of the Tagsys RFID Readers + */ +#define FTDI_TAGSYS_LP101_PID 0xF0E9 /* Tagsys L-P101 RFID*/ +#define FTDI_TAGSYS_P200X_PID 0xF0EE /* Tagsys Medio P200x RFID*/ + /* an infrared receiver for user access control with IR tags */ #define FTDI_PIEGROUP_PID 0xF208 /* Product Id */ -- cgit v0.10.2 From 7f196caffbf2dc96cc145bf5d2ef5ef8a7b4f687 Mon Sep 17 00:00:00 2001 From: Christian Engelmayer Date: Tue, 28 Jan 2014 22:22:27 +0100 Subject: usb: core: Fix potential memory leak adding dyn USBdevice IDs Fix a memory leak in the usb_store_new_id() error paths. When bailing out due to sanity checks, the function left the already allocated usb_dynid struct in place. This regression was introduced by the following commits: c63fe8f6 (usb: core: add sanity checks when using bInterfaceClass with new_id) 1b9fb31f (usb: core: check for valid id_table when using the RefId feature) 52a6966c (usb: core: bail out if user gives an unknown RefId when using new_id) Detected by Coverity: CID 1162604. Signed-off-by: Christian Engelmayer Acked-by: Wolfram Sang Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 5d01558..ab90a01 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -63,8 +63,10 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids, dynid->id.idProduct = idProduct; dynid->id.match_flags = USB_DEVICE_ID_MATCH_DEVICE; if (fields > 2 && bInterfaceClass) { - if (bInterfaceClass > 255) - return -EINVAL; + if (bInterfaceClass > 255) { + retval = -EINVAL; + goto fail; + } dynid->id.bInterfaceClass = (u8)bInterfaceClass; dynid->id.match_flags |= USB_DEVICE_ID_MATCH_INT_CLASS; @@ -73,17 +75,21 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids, if (fields > 4) { const struct usb_device_id *id = id_table; - if (!id) - return -ENODEV; + if (!id) { + retval = -ENODEV; + goto fail; + } for (; id->match_flags; id++) if (id->idVendor == refVendor && id->idProduct == refProduct) break; - if (id->match_flags) + if (id->match_flags) { dynid->id.driver_info = id->driver_info; - else - return -ENODEV; + } else { + retval = -ENODEV; + goto fail; + } } spin_lock(&dynids->lock); @@ -95,6 +101,10 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids, if (retval) return retval; return count; + +fail: + kfree(dynid); + return retval; } EXPORT_SYMBOL_GPL(usb_store_new_id); -- cgit v0.10.2 From b5ea14924718864d64f4cb12a6d901ffeb2972ad Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 17 Dec 2013 19:10:27 +0000 Subject: imx-drm: imx-drm-core: use the crtc drm device for vblank There are a couple of ways to get at the drm_device for the vblank operations. One of them is via the private imxdrm structure, the other is via the DRM crtc structure, which also stores a pointer. Use the DRM method instead of our own method. Signed-off-by: Russell King Acked-by: Shawn Guo Tested-by: Shawn Guo Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/imx-drm/imx-drm-core.c b/drivers/staging/imx-drm/imx-drm-core.c index 09ef5fb8..830f76f5 100644 --- a/drivers/staging/imx-drm/imx-drm-core.c +++ b/drivers/staging/imx-drm/imx-drm-core.c @@ -142,19 +142,19 @@ EXPORT_SYMBOL_GPL(imx_drm_crtc_panel_format); int imx_drm_crtc_vblank_get(struct imx_drm_crtc *imx_drm_crtc) { - return drm_vblank_get(imx_drm_crtc->imxdrm->drm, imx_drm_crtc->pipe); + return drm_vblank_get(imx_drm_crtc->crtc->dev, imx_drm_crtc->pipe); } EXPORT_SYMBOL_GPL(imx_drm_crtc_vblank_get); void imx_drm_crtc_vblank_put(struct imx_drm_crtc *imx_drm_crtc) { - drm_vblank_put(imx_drm_crtc->imxdrm->drm, imx_drm_crtc->pipe); + drm_vblank_put(imx_drm_crtc->crtc->dev, imx_drm_crtc->pipe); } EXPORT_SYMBOL_GPL(imx_drm_crtc_vblank_put); void imx_drm_handle_vblank(struct imx_drm_crtc *imx_drm_crtc) { - drm_handle_vblank(imx_drm_crtc->imxdrm->drm, imx_drm_crtc->pipe); + drm_handle_vblank(imx_drm_crtc->crtc->dev, imx_drm_crtc->pipe); } EXPORT_SYMBOL_GPL(imx_drm_handle_vblank); -- cgit v0.10.2 From 020a9ea7c2206be4382a09cbafc7c3bdf5bbf8a5 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 17 Dec 2013 19:10:47 +0000 Subject: imx-drm: imx-drm-core: avoid going the long route round for drm_device We have the drm_device available, so rather than storing it and then using the stored version, us the one we already have available to us. Signed-off-by: Russell King Acked-by: Shawn Guo Tested-by: Shawn Guo Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/imx-drm/imx-drm-core.c b/drivers/staging/imx-drm/imx-drm-core.c index 830f76f5..87d08f4 100644 --- a/drivers/staging/imx-drm/imx-drm-core.c +++ b/drivers/staging/imx-drm/imx-drm-core.c @@ -88,9 +88,9 @@ static int imx_drm_driver_unload(struct drm_device *drm) imx_drm_device_put(); - drm_vblank_cleanup(imxdrm->drm); - drm_kms_helper_poll_fini(imxdrm->drm); - drm_mode_config_cleanup(imxdrm->drm); + drm_vblank_cleanup(drm); + drm_kms_helper_poll_fini(drm); + drm_mode_config_cleanup(drm); return 0; } @@ -424,15 +424,15 @@ static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags) mutex_lock(&imxdrm->mutex); - drm_kms_helper_poll_init(imxdrm->drm); + drm_kms_helper_poll_init(drm); /* setup the grouping for the legacy output */ - ret = drm_mode_group_init_legacy_group(imxdrm->drm, - &imxdrm->drm->primary->mode_group); + ret = drm_mode_group_init_legacy_group(drm, + &drm->primary->mode_group); if (ret) goto err_kms; - ret = drm_vblank_init(imxdrm->drm, MAX_CRTC); + ret = drm_vblank_init(drm, MAX_CRTC); if (ret) goto err_kms; @@ -441,7 +441,7 @@ static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags) * by drm timer once a current process gives up ownership of * vblank event.(after drm_vblank_put function is called) */ - imxdrm->drm->vblank_disable_allowed = true; + drm->vblank_disable_allowed = true; if (!imx_drm_device_get()) { ret = -EINVAL; -- cgit v0.10.2 From ec9557d752e8758297ddecb34d0aca264616ecb2 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 17 Dec 2013 19:11:07 +0000 Subject: imx-drm: imx-drm-core: merge imx_drm_crtc_register() into imx_drm_add_crtc() There's no reason for this to be a separate function; merge the two together. Signed-off-by: Russell King Acked-by: Shawn Guo Tested-by: Shawn Guo Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/imx-drm/imx-drm-core.c b/drivers/staging/imx-drm/imx-drm-core.c index 87d08f4..236ed66 100644 --- a/drivers/staging/imx-drm/imx-drm-core.c +++ b/drivers/staging/imx-drm/imx-drm-core.c @@ -370,29 +370,6 @@ static void imx_drm_connector_unregister( } /* - * register a crtc to the drm core - */ -static int imx_drm_crtc_register(struct imx_drm_crtc *imx_drm_crtc) -{ - struct imx_drm_device *imxdrm = __imx_drm_device(); - int ret; - - ret = drm_mode_crtc_set_gamma_size(imx_drm_crtc->crtc, 256); - if (ret) - return ret; - - drm_crtc_helper_add(imx_drm_crtc->crtc, - imx_drm_crtc->imx_drm_helper_funcs.crtc_helper_funcs); - - drm_crtc_init(imxdrm->drm, imx_drm_crtc->crtc, - imx_drm_crtc->imx_drm_helper_funcs.crtc_funcs); - - drm_mode_group_reinit(imxdrm->drm); - - return 0; -} - -/* * Called by the CRTC driver when all CRTCs are registered. This * puts all the pieces together and initializes the driver. * Once this is called no more CRTCs can be registered since @@ -536,10 +513,18 @@ int imx_drm_add_crtc(struct drm_crtc *crtc, *new_crtc = imx_drm_crtc; - ret = imx_drm_crtc_register(imx_drm_crtc); + ret = drm_mode_crtc_set_gamma_size(imx_drm_crtc->crtc, 256); if (ret) goto err_register; + drm_crtc_helper_add(crtc, + imx_drm_crtc->imx_drm_helper_funcs.crtc_helper_funcs); + + drm_crtc_init(imxdrm->drm, crtc, + imx_drm_crtc->imx_drm_helper_funcs.crtc_funcs); + + drm_mode_group_reinit(imxdrm->drm); + imx_drm_update_possible_crtcs(); mutex_unlock(&imxdrm->mutex); -- cgit v0.10.2 From 5a819ed6d4bb803ee609b4ceedd7c8efbbfa65e0 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 28 Jan 2014 10:33:16 +0530 Subject: staging: imx-drm: Fix build error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of redefining the enums, use the standard ones already available to avoid the following build errors: drivers/staging/imx-drm/imx-hdmi.c:56:13: error: nested redefinition of ‘enum hdmi_colorimetry’ drivers/staging/imx-drm/imx-hdmi.c:56:13: error: redeclaration of ‘enum hdmi_colorimetry’ In file included from include/drm/drm_crtc.h:33:0, from include/drm/drmP.h:710, from drivers/staging/imx-drm/imx-hdmi.c:24: include/linux/hdmi.h:48:6: note: originally defined here Reported-by: Josh Boyer Signed-off-by: Sachin Kamat Cc: Guennadi Liakhovetski Reviewed-by: Fabio Estevam Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/imx-drm/imx-hdmi.c b/drivers/staging/imx-drm/imx-hdmi.c index f3a1f5e..62ce0e8 100644 --- a/drivers/staging/imx-drm/imx-hdmi.c +++ b/drivers/staging/imx-drm/imx-hdmi.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -52,11 +53,6 @@ enum hdmi_datamap { YCbCr422_12B = 0x12, }; -enum hdmi_colorimetry { - ITU601, - ITU709, -}; - enum imx_hdmi_devtype { IMX6Q_HDMI, IMX6DL_HDMI, @@ -489,12 +485,12 @@ static void imx_hdmi_update_csc_coeffs(struct imx_hdmi *hdmi) if (is_color_space_conversion(hdmi)) { if (hdmi->hdmi_data.enc_out_format == RGB) { - if (hdmi->hdmi_data.colorimetry == ITU601) + if (hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_601) csc_coeff = &csc_coeff_rgb_out_eitu601; else csc_coeff = &csc_coeff_rgb_out_eitu709; } else if (hdmi->hdmi_data.enc_in_format == RGB) { - if (hdmi->hdmi_data.colorimetry == ITU601) + if (hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_601) csc_coeff = &csc_coeff_rgb_in_eitu601; else csc_coeff = &csc_coeff_rgb_in_eitu709; @@ -1140,16 +1136,16 @@ static void hdmi_config_AVI(struct imx_hdmi *hdmi) /* Set up colorimetry */ if (hdmi->hdmi_data.enc_out_format == XVYCC444) { colorimetry = HDMI_FC_AVICONF1_COLORIMETRY_EXTENDED_INFO; - if (hdmi->hdmi_data.colorimetry == ITU601) + if (hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_601) ext_colorimetry = HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC601; - else /* hdmi->hdmi_data.colorimetry == ITU709 */ + else /*hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_709*/ ext_colorimetry = HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC709; } else if (hdmi->hdmi_data.enc_out_format != RGB) { - if (hdmi->hdmi_data.colorimetry == ITU601) + if (hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_601) colorimetry = HDMI_FC_AVICONF1_COLORIMETRY_SMPTE; - else /* hdmi->hdmi_data.colorimetry == ITU709 */ + else /*hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_709*/ colorimetry = HDMI_FC_AVICONF1_COLORIMETRY_ITUR; ext_colorimetry = HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC601; } else { /* Carries no data */ @@ -1379,9 +1375,9 @@ static int imx_hdmi_setup(struct imx_hdmi *hdmi, struct drm_display_mode *mode) (hdmi->vic == 21) || (hdmi->vic == 22) || (hdmi->vic == 2) || (hdmi->vic == 3) || (hdmi->vic == 17) || (hdmi->vic == 18)) - hdmi->hdmi_data.colorimetry = ITU601; + hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_601; else - hdmi->hdmi_data.colorimetry = ITU709; + hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_709; if ((hdmi->vic == 10) || (hdmi->vic == 11) || (hdmi->vic == 12) || (hdmi->vic == 13) || -- cgit v0.10.2 From ec2c9935688fbd5eaa7c975e3e21562c3da77363 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 5 Feb 2014 15:03:35 +0000 Subject: netfilter: nf_tables: fix potential oops when dumping sets Commit c9c8e48597 (netfilter: nf_tables: dump sets in all existing families) changed nft_ctx_init_from_setattr() to only look up the address family if it is not NFPROTO_UNSPEC. However if it is NFPROTO_UNSPEC and a table attribute is given, nftables_afinfo_lookup() will dereference the NULL afi pointer. Fix by checking for non-NULL afi and also move a check added by that commit to the proper position. Signed-off-by: Patrick McHardy Signed-off-by: Pablo Neira Ayuso diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 2a22a18..3c5a219 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -1943,6 +1943,9 @@ static int nft_ctx_init_from_setattr(struct nft_ctx *ctx, } if (nla[NFTA_SET_TABLE] != NULL) { + if (afi == NULL) + return -EAFNOSUPPORT; + table = nf_tables_table_lookup(afi, nla[NFTA_SET_TABLE]); if (IS_ERR(table)) return PTR_ERR(table); @@ -2428,6 +2431,8 @@ static int nf_tables_delset(struct sock *nlsk, struct sk_buff *skb, struct nft_ctx ctx; int err; + if (nfmsg->nfgen_family == NFPROTO_UNSPEC) + return -EAFNOSUPPORT; if (nla[NFTA_SET_TABLE] == NULL) return -EINVAL; @@ -2435,9 +2440,6 @@ static int nf_tables_delset(struct sock *nlsk, struct sk_buff *skb, if (err < 0) return err; - if (nfmsg->nfgen_family == NFPROTO_UNSPEC) - return -EAFNOSUPPORT; - set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME]); if (IS_ERR(set)) return PTR_ERR(set); -- cgit v0.10.2 From 51292c0735eb2d9e29115cbf6264845e19a6c77d Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 5 Feb 2014 15:03:36 +0000 Subject: netfilter: nft_ct: fix missing NFT_CT_L3PROTOCOL key in validity checks The key was missing in the list of valid keys, add it. Signed-off-by: Patrick McHardy Signed-off-by: Pablo Neira Ayuso diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c index feaf0f3..46e2754 100644 --- a/net/netfilter/nft_ct.c +++ b/net/netfilter/nft_ct.c @@ -226,6 +226,7 @@ static int nft_ct_init_validate_get(const struct nft_expr *expr, if (tb[NFTA_CT_DIRECTION] != NULL) return -EINVAL; break; + case NFT_CT_L3PROTOCOL: case NFT_CT_PROTOCOL: case NFT_CT_SRC: case NFT_CT_DST: -- cgit v0.10.2 From 64d46806b6218c97f68742c5663a8ae3a5fbe838 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 5 Feb 2014 15:03:37 +0000 Subject: netfilter: nf_tables: add AF specific expression support For the reject module, we need to add AF-specific implementations to get rid of incorrect module dependencies. Try to load an AF-specific module first and fall back to generic modules. Signed-off-by: Patrick McHardy Signed-off-by: Pablo Neira Ayuso diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h index 57c8ff7..0f68e47 100644 --- a/include/net/netfilter/nf_tables.h +++ b/include/net/netfilter/nf_tables.h @@ -252,6 +252,7 @@ void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set, * @owner: module reference * @policy: netlink attribute policy * @maxattr: highest netlink attribute number + * @family: address family for AF-specific types */ struct nft_expr_type { const struct nft_expr_ops *(*select_ops)(const struct nft_ctx *, @@ -262,6 +263,7 @@ struct nft_expr_type { struct module *owner; const struct nla_policy *policy; unsigned int maxattr; + u8 family; }; /** @@ -529,6 +531,9 @@ void nft_unregister_expr(struct nft_expr_type *); #define MODULE_ALIAS_NFT_CHAIN(family, name) \ MODULE_ALIAS("nft-chain-" __stringify(family) "-" name) +#define MODULE_ALIAS_NFT_AF_EXPR(family, name) \ + MODULE_ALIAS("nft-expr-" __stringify(family) "-" name) + #define MODULE_ALIAS_NFT_EXPR(name) \ MODULE_ALIAS("nft-expr-" name) diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 3c5a219..113c469 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -1114,35 +1114,45 @@ void nft_unregister_expr(struct nft_expr_type *type) } EXPORT_SYMBOL_GPL(nft_unregister_expr); -static const struct nft_expr_type *__nft_expr_type_get(struct nlattr *nla) +static const struct nft_expr_type *__nft_expr_type_get(u8 family, + struct nlattr *nla) { const struct nft_expr_type *type; list_for_each_entry(type, &nf_tables_expressions, list) { - if (!nla_strcmp(nla, type->name)) + if (!nla_strcmp(nla, type->name) && + (!type->family || type->family == family)) return type; } return NULL; } -static const struct nft_expr_type *nft_expr_type_get(struct nlattr *nla) +static const struct nft_expr_type *nft_expr_type_get(u8 family, + struct nlattr *nla) { const struct nft_expr_type *type; if (nla == NULL) return ERR_PTR(-EINVAL); - type = __nft_expr_type_get(nla); + type = __nft_expr_type_get(family, nla); if (type != NULL && try_module_get(type->owner)) return type; #ifdef CONFIG_MODULES if (type == NULL) { nfnl_unlock(NFNL_SUBSYS_NFTABLES); + request_module("nft-expr-%u-%.*s", family, + nla_len(nla), (char *)nla_data(nla)); + nfnl_lock(NFNL_SUBSYS_NFTABLES); + if (__nft_expr_type_get(family, nla)) + return ERR_PTR(-EAGAIN); + + nfnl_unlock(NFNL_SUBSYS_NFTABLES); request_module("nft-expr-%.*s", nla_len(nla), (char *)nla_data(nla)); nfnl_lock(NFNL_SUBSYS_NFTABLES); - if (__nft_expr_type_get(nla)) + if (__nft_expr_type_get(family, nla)) return ERR_PTR(-EAGAIN); } #endif @@ -1193,7 +1203,7 @@ static int nf_tables_expr_parse(const struct nft_ctx *ctx, if (err < 0) return err; - type = nft_expr_type_get(tb[NFTA_EXPR_NAME]); + type = nft_expr_type_get(ctx->afi->family, tb[NFTA_EXPR_NAME]); if (IS_ERR(type)) return PTR_ERR(type); -- cgit v0.10.2 From 9ab9831b4c59d379a17f92a6157c7e921811dea2 Mon Sep 17 00:00:00 2001 From: Zoltan Kiss Date: Tue, 4 Feb 2014 19:54:37 +0000 Subject: xen-netback: Fix Rx stall due to race condition The recent patch to fix receive side flow control (11b57f90257c1d6a91cee720151b69e0c2020cf6: xen-netback: stop vif thread spinning if frontend is unresponsive) solved the spinning thread problem, however caused an another one. The receive side can stall, if: - [THREAD] xenvif_rx_action sets rx_queue_stopped to true - [INTERRUPT] interrupt happens, and sets rx_event to true - [THREAD] then xenvif_kthread sets rx_event to false - [THREAD] rx_work_todo doesn't return true anymore Also, if interrupt sent but there is still no room in the ring, it take quite a long time until xenvif_rx_action realize it. This patch ditch that two variable, and rework rx_work_todo. If the thread finds it can't fit more skb's into the ring, it saves the last slot estimation into rx_last_skb_slots, otherwise it's kept as 0. Then rx_work_todo will check if: - there is something to send to the ring (like before) - there is space for the topmost packet in the queue I think that's more natural and optimal thing to test than two bool which are set somewhere else. Signed-off-by: Zoltan Kiss Reviewed-by: Paul Durrant Acked-by: Wei Liu Signed-off-by: David S. Miller diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h index 4c76bcb..ae413a2 100644 --- a/drivers/net/xen-netback/common.h +++ b/drivers/net/xen-netback/common.h @@ -143,11 +143,7 @@ struct xenvif { char rx_irq_name[IFNAMSIZ+4]; /* DEVNAME-rx */ struct xen_netif_rx_back_ring rx; struct sk_buff_head rx_queue; - bool rx_queue_stopped; - /* Set when the RX interrupt is triggered by the frontend. - * The worker thread may need to wake the queue. - */ - bool rx_event; + RING_IDX rx_last_skb_slots; /* This array is allocated seperately as it is large */ struct gnttab_copy *grant_copy_op; diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index b9de31e..7669d49 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@ -100,7 +100,6 @@ static irqreturn_t xenvif_rx_interrupt(int irq, void *dev_id) { struct xenvif *vif = dev_id; - vif->rx_event = true; xenvif_kick_thread(vif); return IRQ_HANDLED; diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index 6b62c3e..e5284bc 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -476,7 +476,6 @@ static void xenvif_rx_action(struct xenvif *vif) unsigned long offset; struct skb_cb_overlay *sco; bool need_to_notify = false; - bool ring_full = false; struct netrx_pending_operations npo = { .copy = vif->grant_copy_op, @@ -486,7 +485,7 @@ static void xenvif_rx_action(struct xenvif *vif) skb_queue_head_init(&rxq); while ((skb = skb_dequeue(&vif->rx_queue)) != NULL) { - int max_slots_needed; + RING_IDX max_slots_needed; int i; /* We need a cheap worse case estimate for the number of @@ -509,9 +508,10 @@ static void xenvif_rx_action(struct xenvif *vif) if (!xenvif_rx_ring_slots_available(vif, max_slots_needed)) { skb_queue_head(&vif->rx_queue, skb); need_to_notify = true; - ring_full = true; + vif->rx_last_skb_slots = max_slots_needed; break; - } + } else + vif->rx_last_skb_slots = 0; sco = (struct skb_cb_overlay *)skb->cb; sco->meta_slots_used = xenvif_gop_skb(skb, &npo); @@ -522,8 +522,6 @@ static void xenvif_rx_action(struct xenvif *vif) BUG_ON(npo.meta_prod > ARRAY_SIZE(vif->meta)); - vif->rx_queue_stopped = !npo.copy_prod && ring_full; - if (!npo.copy_prod) goto done; @@ -1473,8 +1471,8 @@ static struct xen_netif_rx_response *make_rx_response(struct xenvif *vif, static inline int rx_work_todo(struct xenvif *vif) { - return (!skb_queue_empty(&vif->rx_queue) && !vif->rx_queue_stopped) || - vif->rx_event; + return !skb_queue_empty(&vif->rx_queue) && + xenvif_rx_ring_slots_available(vif, vif->rx_last_skb_slots); } static inline int tx_work_todo(struct xenvif *vif) @@ -1560,8 +1558,6 @@ int xenvif_kthread(void *data) if (!skb_queue_empty(&vif->rx_queue)) xenvif_rx_action(vif); - vif->rx_event = false; - if (skb_queue_empty(&vif->rx_queue) && netif_queue_stopped(vif->dev)) xenvif_start_queue(vif); -- cgit v0.10.2 From cc4723ca316742891954efa346298e7c747c0d17 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 5 Feb 2014 15:03:38 +0000 Subject: netfilter: nft_reject: split up reject module into IPv4 and IPv6 specifc parts Currently the nft_reject module depends on symbols from ipv6. This is wrong since no generic module should force IPv6 support to be loaded. Split up the module into AF-specific and a generic part. Signed-off-by: Patrick McHardy Signed-off-by: Pablo Neira Ayuso diff --git a/include/net/netfilter/nft_reject.h b/include/net/netfilter/nft_reject.h new file mode 100644 index 0000000..ecda759 --- /dev/null +++ b/include/net/netfilter/nft_reject.h @@ -0,0 +1,17 @@ +#ifndef _NFT_REJECT_H_ +#define _NFT_REJECT_H_ + +struct nft_reject { + enum nft_reject_types type:8; + u8 icmp_code; +}; + +extern const struct nla_policy nft_reject_policy[]; + +int nft_reject_init(const struct nft_ctx *ctx, + const struct nft_expr *expr, + const struct nlattr * const tb[]); + +int nft_reject_dump(struct sk_buff *skb, const struct nft_expr *expr); + +#endif diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index 81c6910..a26ce03 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig @@ -61,6 +61,11 @@ config NFT_CHAIN_NAT_IPV4 packet transformations such as the source, destination address and source and destination ports. +config NFT_REJECT_IPV4 + depends on NF_TABLES_IPV4 + default NFT_REJECT + tristate + config NF_TABLES_ARP depends on NF_TABLES tristate "ARP nf_tables support" diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile index c16be9d..90b8240 100644 --- a/net/ipv4/netfilter/Makefile +++ b/net/ipv4/netfilter/Makefile @@ -30,6 +30,7 @@ obj-$(CONFIG_NF_NAT_PROTO_GRE) += nf_nat_proto_gre.o obj-$(CONFIG_NF_TABLES_IPV4) += nf_tables_ipv4.o obj-$(CONFIG_NFT_CHAIN_ROUTE_IPV4) += nft_chain_route_ipv4.o obj-$(CONFIG_NFT_CHAIN_NAT_IPV4) += nft_chain_nat_ipv4.o +obj-$(CONFIG_NFT_REJECT_IPV4) += nft_reject_ipv4.o obj-$(CONFIG_NF_TABLES_ARP) += nf_tables_arp.o # generic IP tables diff --git a/net/ipv4/netfilter/nft_reject_ipv4.c b/net/ipv4/netfilter/nft_reject_ipv4.c new file mode 100644 index 0000000..e935d8d --- /dev/null +++ b/net/ipv4/netfilter/nft_reject_ipv4.c @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2008-2009 Patrick McHardy + * Copyright (c) 2013 Eric Leblond + * + * 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. + * + * Development of this code funded by Astaro AG (http://www.astaro.com/) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void nft_reject_ipv4_eval(const struct nft_expr *expr, + struct nft_data data[NFT_REG_MAX + 1], + const struct nft_pktinfo *pkt) +{ + struct nft_reject *priv = nft_expr_priv(expr); + + switch (priv->type) { + case NFT_REJECT_ICMP_UNREACH: + nf_send_unreach(pkt->skb, priv->icmp_code); + break; + case NFT_REJECT_TCP_RST: + nf_send_reset(pkt->skb, pkt->ops->hooknum); + break; + } + + data[NFT_REG_VERDICT].verdict = NF_DROP; +} + +static struct nft_expr_type nft_reject_ipv4_type; +static const struct nft_expr_ops nft_reject_ipv4_ops = { + .type = &nft_reject_ipv4_type, + .size = NFT_EXPR_SIZE(sizeof(struct nft_reject)), + .eval = nft_reject_ipv4_eval, + .init = nft_reject_init, + .dump = nft_reject_dump, +}; + +static struct nft_expr_type nft_reject_ipv4_type __read_mostly = { + .family = NFPROTO_IPV4, + .name = "reject", + .ops = &nft_reject_ipv4_ops, + .policy = nft_reject_policy, + .maxattr = NFTA_REJECT_MAX, + .owner = THIS_MODULE, +}; + +static int __init nft_reject_ipv4_module_init(void) +{ + return nft_register_expr(&nft_reject_ipv4_type); +} + +static void __exit nft_reject_ipv4_module_exit(void) +{ + nft_unregister_expr(&nft_reject_ipv4_type); +} + +module_init(nft_reject_ipv4_module_init); +module_exit(nft_reject_ipv4_module_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Patrick McHardy "); +MODULE_ALIAS_NFT_AF_EXPR(AF_INET, "reject"); diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig index 35750df..4bff1f2 100644 --- a/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig @@ -50,6 +50,11 @@ config NFT_CHAIN_NAT_IPV6 packet transformations such as the source, destination address and source and destination ports. +config NFT_REJECT_IPV6 + depends on NF_TABLES_IPV6 + default NFT_REJECT + tristate + config IP6_NF_IPTABLES tristate "IP6 tables support (required for filtering)" depends on INET && IPV6 diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile index d1b4928..70d3dd6 100644 --- a/net/ipv6/netfilter/Makefile +++ b/net/ipv6/netfilter/Makefile @@ -27,6 +27,7 @@ obj-$(CONFIG_NF_DEFRAG_IPV6) += nf_defrag_ipv6.o obj-$(CONFIG_NF_TABLES_IPV6) += nf_tables_ipv6.o obj-$(CONFIG_NFT_CHAIN_ROUTE_IPV6) += nft_chain_route_ipv6.o obj-$(CONFIG_NFT_CHAIN_NAT_IPV6) += nft_chain_nat_ipv6.o +obj-$(CONFIG_NFT_REJECT_IPV6) += nft_reject_ipv6.o # matches obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o diff --git a/net/ipv6/netfilter/nft_reject_ipv6.c b/net/ipv6/netfilter/nft_reject_ipv6.c new file mode 100644 index 0000000..f732859 --- /dev/null +++ b/net/ipv6/netfilter/nft_reject_ipv6.c @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2008-2009 Patrick McHardy + * Copyright (c) 2013 Eric Leblond + * + * 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. + * + * Development of this code funded by Astaro AG (http://www.astaro.com/) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void nft_reject_ipv6_eval(const struct nft_expr *expr, + struct nft_data data[NFT_REG_MAX + 1], + const struct nft_pktinfo *pkt) +{ + struct nft_reject *priv = nft_expr_priv(expr); + struct net *net = dev_net((pkt->in != NULL) ? pkt->in : pkt->out); + + switch (priv->type) { + case NFT_REJECT_ICMP_UNREACH: + nf_send_unreach6(net, pkt->skb, priv->icmp_code, + pkt->ops->hooknum); + break; + case NFT_REJECT_TCP_RST: + nf_send_reset6(net, pkt->skb, pkt->ops->hooknum); + break; + } + + data[NFT_REG_VERDICT].verdict = NF_DROP; +} + +static struct nft_expr_type nft_reject_ipv6_type; +static const struct nft_expr_ops nft_reject_ipv6_ops = { + .type = &nft_reject_ipv6_type, + .size = NFT_EXPR_SIZE(sizeof(struct nft_reject)), + .eval = nft_reject_ipv6_eval, + .init = nft_reject_init, + .dump = nft_reject_dump, +}; + +static struct nft_expr_type nft_reject_ipv6_type __read_mostly = { + .family = NFPROTO_IPV6, + .name = "reject", + .ops = &nft_reject_ipv6_ops, + .policy = nft_reject_policy, + .maxattr = NFTA_REJECT_MAX, + .owner = THIS_MODULE, +}; + +static int __init nft_reject_ipv6_module_init(void) +{ + return nft_register_expr(&nft_reject_ipv6_type); +} + +static void __exit nft_reject_ipv6_module_exit(void) +{ + nft_unregister_expr(&nft_reject_ipv6_type); +} + +module_init(nft_reject_ipv6_module_init); +module_exit(nft_reject_ipv6_module_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Patrick McHardy "); +MODULE_ALIAS_NFT_AF_EXPR(AF_INET6, "reject"); diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index c374675..ed8b50e 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig @@ -513,7 +513,6 @@ config NFT_QUEUE config NFT_REJECT depends on NF_TABLES - depends on NF_TABLES_IPV6 || !NF_TABLES_IPV6 default m if NETFILTER_ADVANCED=n tristate "Netfilter nf_tables reject support" help diff --git a/net/netfilter/nft_reject.c b/net/netfilter/nft_reject.c index 5e204711..f3448c2 100644 --- a/net/netfilter/nft_reject.c +++ b/net/netfilter/nft_reject.c @@ -16,65 +16,23 @@ #include #include #include -#include -#include +#include -#if IS_ENABLED(CONFIG_NF_TABLES_IPV6) -#include -#endif - -struct nft_reject { - enum nft_reject_types type:8; - u8 icmp_code; - u8 family; -}; - -static void nft_reject_eval(const struct nft_expr *expr, - struct nft_data data[NFT_REG_MAX + 1], - const struct nft_pktinfo *pkt) -{ - struct nft_reject *priv = nft_expr_priv(expr); -#if IS_ENABLED(CONFIG_NF_TABLES_IPV6) - struct net *net = dev_net((pkt->in != NULL) ? pkt->in : pkt->out); -#endif - switch (priv->type) { - case NFT_REJECT_ICMP_UNREACH: - if (priv->family == NFPROTO_IPV4) - nf_send_unreach(pkt->skb, priv->icmp_code); -#if IS_ENABLED(CONFIG_NF_TABLES_IPV6) - else if (priv->family == NFPROTO_IPV6) - nf_send_unreach6(net, pkt->skb, priv->icmp_code, - pkt->ops->hooknum); -#endif - break; - case NFT_REJECT_TCP_RST: - if (priv->family == NFPROTO_IPV4) - nf_send_reset(pkt->skb, pkt->ops->hooknum); -#if IS_ENABLED(CONFIG_NF_TABLES_IPV6) - else if (priv->family == NFPROTO_IPV6) - nf_send_reset6(net, pkt->skb, pkt->ops->hooknum); -#endif - break; - } - - data[NFT_REG_VERDICT].verdict = NF_DROP; -} - -static const struct nla_policy nft_reject_policy[NFTA_REJECT_MAX + 1] = { +const struct nla_policy nft_reject_policy[NFTA_REJECT_MAX + 1] = { [NFTA_REJECT_TYPE] = { .type = NLA_U32 }, [NFTA_REJECT_ICMP_CODE] = { .type = NLA_U8 }, }; +EXPORT_SYMBOL_GPL(nft_reject_policy); -static int nft_reject_init(const struct nft_ctx *ctx, - const struct nft_expr *expr, - const struct nlattr * const tb[]) +int nft_reject_init(const struct nft_ctx *ctx, + const struct nft_expr *expr, + const struct nlattr * const tb[]) { struct nft_reject *priv = nft_expr_priv(expr); if (tb[NFTA_REJECT_TYPE] == NULL) return -EINVAL; - priv->family = ctx->afi->family; priv->type = ntohl(nla_get_be32(tb[NFTA_REJECT_TYPE])); switch (priv->type) { case NFT_REJECT_ICMP_UNREACH: @@ -89,8 +47,9 @@ static int nft_reject_init(const struct nft_ctx *ctx, return 0; } +EXPORT_SYMBOL_GPL(nft_reject_init); -static int nft_reject_dump(struct sk_buff *skb, const struct nft_expr *expr) +int nft_reject_dump(struct sk_buff *skb, const struct nft_expr *expr) { const struct nft_reject *priv = nft_expr_priv(expr); @@ -109,37 +68,7 @@ static int nft_reject_dump(struct sk_buff *skb, const struct nft_expr *expr) nla_put_failure: return -1; } - -static struct nft_expr_type nft_reject_type; -static const struct nft_expr_ops nft_reject_ops = { - .type = &nft_reject_type, - .size = NFT_EXPR_SIZE(sizeof(struct nft_reject)), - .eval = nft_reject_eval, - .init = nft_reject_init, - .dump = nft_reject_dump, -}; - -static struct nft_expr_type nft_reject_type __read_mostly = { - .name = "reject", - .ops = &nft_reject_ops, - .policy = nft_reject_policy, - .maxattr = NFTA_REJECT_MAX, - .owner = THIS_MODULE, -}; - -static int __init nft_reject_module_init(void) -{ - return nft_register_expr(&nft_reject_type); -} - -static void __exit nft_reject_module_exit(void) -{ - nft_unregister_expr(&nft_reject_type); -} - -module_init(nft_reject_module_init); -module_exit(nft_reject_module_exit); +EXPORT_SYMBOL_GPL(nft_reject_dump); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Patrick McHardy "); -MODULE_ALIAS_NFT_EXPR("reject"); -- cgit v0.10.2 From 05513e9e33dbded8124567466a444d32173eecc6 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 5 Feb 2014 15:03:39 +0000 Subject: netfilter: nf_tables: add reject module for NFPROTO_INET Add a reject module for NFPROTO_INET. It does nothing but dispatch to the AF-specific modules based on the hook family. Signed-off-by: Patrick McHardy Signed-off-by: Pablo Neira Ayuso diff --git a/include/net/netfilter/nft_reject.h b/include/net/netfilter/nft_reject.h index ecda759..36b0da2 100644 --- a/include/net/netfilter/nft_reject.h +++ b/include/net/netfilter/nft_reject.h @@ -14,4 +14,12 @@ int nft_reject_init(const struct nft_ctx *ctx, int nft_reject_dump(struct sk_buff *skb, const struct nft_expr *expr); +void nft_reject_ipv4_eval(const struct nft_expr *expr, + struct nft_data data[NFT_REG_MAX + 1], + const struct nft_pktinfo *pkt); + +void nft_reject_ipv6_eval(const struct nft_expr *expr, + struct nft_data data[NFT_REG_MAX + 1], + const struct nft_pktinfo *pkt); + #endif diff --git a/net/ipv4/netfilter/nft_reject_ipv4.c b/net/ipv4/netfilter/nft_reject_ipv4.c index e935d8d..e79718a 100644 --- a/net/ipv4/netfilter/nft_reject_ipv4.c +++ b/net/ipv4/netfilter/nft_reject_ipv4.c @@ -20,9 +20,9 @@ #include #include -static void nft_reject_ipv4_eval(const struct nft_expr *expr, - struct nft_data data[NFT_REG_MAX + 1], - const struct nft_pktinfo *pkt) +void nft_reject_ipv4_eval(const struct nft_expr *expr, + struct nft_data data[NFT_REG_MAX + 1], + const struct nft_pktinfo *pkt) { struct nft_reject *priv = nft_expr_priv(expr); @@ -37,6 +37,7 @@ static void nft_reject_ipv4_eval(const struct nft_expr *expr, data[NFT_REG_VERDICT].verdict = NF_DROP; } +EXPORT_SYMBOL_GPL(nft_reject_ipv4_eval); static struct nft_expr_type nft_reject_ipv4_type; static const struct nft_expr_ops nft_reject_ipv4_ops = { diff --git a/net/ipv6/netfilter/nft_reject_ipv6.c b/net/ipv6/netfilter/nft_reject_ipv6.c index f732859..0bc19fa 100644 --- a/net/ipv6/netfilter/nft_reject_ipv6.c +++ b/net/ipv6/netfilter/nft_reject_ipv6.c @@ -19,9 +19,9 @@ #include #include -static void nft_reject_ipv6_eval(const struct nft_expr *expr, - struct nft_data data[NFT_REG_MAX + 1], - const struct nft_pktinfo *pkt) +void nft_reject_ipv6_eval(const struct nft_expr *expr, + struct nft_data data[NFT_REG_MAX + 1], + const struct nft_pktinfo *pkt) { struct nft_reject *priv = nft_expr_priv(expr); struct net *net = dev_net((pkt->in != NULL) ? pkt->in : pkt->out); @@ -38,6 +38,7 @@ static void nft_reject_ipv6_eval(const struct nft_expr *expr, data[NFT_REG_VERDICT].verdict = NF_DROP; } +EXPORT_SYMBOL_GPL(nft_reject_ipv6_eval); static struct nft_expr_type nft_reject_ipv6_type; static const struct nft_expr_ops nft_reject_ipv6_ops = { diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index ed8b50e..e9410d1 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig @@ -520,6 +520,11 @@ config NFT_REJECT explicitly deny and notify via TCP reset/ICMP informational errors unallowed traffic. +config NFT_REJECT_INET + depends on NF_TABLES_INET + default NFT_REJECT + tristate + config NFT_COMPAT depends on NF_TABLES depends on NETFILTER_XTABLES diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index ee9c4de..bffdad7 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile @@ -79,6 +79,7 @@ obj-$(CONFIG_NFT_LIMIT) += nft_limit.o obj-$(CONFIG_NFT_NAT) += nft_nat.o obj-$(CONFIG_NFT_QUEUE) += nft_queue.o obj-$(CONFIG_NFT_REJECT) += nft_reject.o +obj-$(CONFIG_NFT_REJECT_INET) += nft_reject_inet.o obj-$(CONFIG_NFT_RBTREE) += nft_rbtree.o obj-$(CONFIG_NFT_HASH) += nft_hash.o obj-$(CONFIG_NFT_COUNTER) += nft_counter.o diff --git a/net/netfilter/nft_reject_inet.c b/net/netfilter/nft_reject_inet.c new file mode 100644 index 0000000..8a310f2 --- /dev/null +++ b/net/netfilter/nft_reject_inet.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2014 Patrick McHardy + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +static void nft_reject_inet_eval(const struct nft_expr *expr, + struct nft_data data[NFT_REG_MAX + 1], + const struct nft_pktinfo *pkt) +{ + switch (pkt->ops->pf) { + case NFPROTO_IPV4: + nft_reject_ipv4_eval(expr, data, pkt); + case NFPROTO_IPV6: + nft_reject_ipv6_eval(expr, data, pkt); + } +} + +static struct nft_expr_type nft_reject_inet_type; +static const struct nft_expr_ops nft_reject_inet_ops = { + .type = &nft_reject_inet_type, + .size = NFT_EXPR_SIZE(sizeof(struct nft_reject)), + .eval = nft_reject_inet_eval, + .init = nft_reject_init, + .dump = nft_reject_dump, +}; + +static struct nft_expr_type nft_reject_inet_type __read_mostly = { + .family = NFPROTO_INET, + .name = "reject", + .ops = &nft_reject_inet_ops, + .policy = nft_reject_policy, + .maxattr = NFTA_REJECT_MAX, + .owner = THIS_MODULE, +}; + +static int __init nft_reject_inet_module_init(void) +{ + return nft_register_expr(&nft_reject_inet_type); +} + +static void __exit nft_reject_inet_module_exit(void) +{ + nft_unregister_expr(&nft_reject_inet_type); +} + +module_init(nft_reject_inet_module_init); +module_exit(nft_reject_inet_module_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Patrick McHardy "); +MODULE_ALIAS_NFT_AF_EXPR(1, "reject"); -- cgit v0.10.2 From 2f617435c3a6fe3f39efb9ae2baa77de2d6c97b8 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 12 Jan 2014 11:06:37 +0200 Subject: mac80211: move roc cookie assignment earlier ieee80211_start_roc_work() might add a new roc to existing roc, and tell cfg80211 it has already started. However, this might happen before the roc cookie was set, resulting in REMAIN_ON_CHANNEL (started) event with null cookie. Consequently, it can make wpa_supplicant go out of sync. Fix it by setting the roc cookie earlier. Cc: stable@vger.kernel.org Signed-off-by: Eliad Peller Signed-off-by: Johannes Berg diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index f9ae9b8..94b4acb 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -2638,6 +2638,24 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, INIT_DELAYED_WORK(&roc->work, ieee80211_sw_roc_work); INIT_LIST_HEAD(&roc->dependents); + /* + * cookie is either the roc cookie (for normal roc) + * or the SKB (for mgmt TX) + */ + if (!txskb) { + /* local->mtx protects this */ + local->roc_cookie_counter++; + roc->cookie = local->roc_cookie_counter; + /* wow, you wrapped 64 bits ... more likely a bug */ + if (WARN_ON(roc->cookie == 0)) { + roc->cookie = 1; + local->roc_cookie_counter++; + } + *cookie = roc->cookie; + } else { + *cookie = (unsigned long)txskb; + } + /* if there's one pending or we're scanning, queue this one */ if (!list_empty(&local->roc_list) || local->scanning || local->radar_detect_enabled) @@ -2772,24 +2790,6 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, if (!queued) list_add_tail(&roc->list, &local->roc_list); - /* - * cookie is either the roc cookie (for normal roc) - * or the SKB (for mgmt TX) - */ - if (!txskb) { - /* local->mtx protects this */ - local->roc_cookie_counter++; - roc->cookie = local->roc_cookie_counter; - /* wow, you wrapped 64 bits ... more likely a bug */ - if (WARN_ON(roc->cookie == 0)) { - roc->cookie = 1; - local->roc_cookie_counter++; - } - *cookie = roc->cookie; - } else { - *cookie = (unsigned long)txskb; - } - return 0; } -- cgit v0.10.2 From f12cb2893069495726c21a4b0178705dacfecfe0 Mon Sep 17 00:00:00 2001 From: Pontus Fuchs Date: Thu, 16 Jan 2014 15:00:40 +0100 Subject: nl80211: Reset split_start when netlink skb is exhausted When the netlink skb is exhausted split_start is left set. In the subsequent retry, with a larger buffer, the dump is continued from the failing point instead of from the beginning. This was causing my rt28xx based USB dongle to now show up when running "iw list" with an old iw version without split dump support. Cc: stable@vger.kernel.org Fixes: 3713b4e364ef ("nl80211: allow splitting wiphy information in dumps") Signed-off-by: Pontus Fuchs [avoid the entire workaround when state->split is set] Signed-off-by: Johannes Berg diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 7a74259..6ea960b 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -1719,9 +1719,10 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb) * We can then retry with the larger buffer. */ if ((ret == -ENOBUFS || ret == -EMSGSIZE) && - !skb->len && + !skb->len && !state->split && cb->min_dump_alloc < 4096) { cb->min_dump_alloc = 4096; + state->split_start = 0; rtnl_unlock(); return 1; } -- cgit v0.10.2 From 5a6aa705ffdd97552ff756bbfa7d5a3b62a6c690 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 23 Jan 2014 16:32:29 +0100 Subject: cfg80211: re-enable 5/10 MHz support Unfortunately I forgot this during the merge window, but the patch seems small enough to go in as a fix. The userspace API bug that was the reason for disabling it has long been fixed. Signed-off-by: Johannes Berg diff --git a/net/wireless/core.c b/net/wireless/core.c index d89dee2..77fe4c7 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -440,9 +440,6 @@ int wiphy_register(struct wiphy *wiphy) int i; u16 ifmodes = wiphy->interface_modes; - /* support for 5/10 MHz is broken due to nl80211 API mess - disable */ - wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_5_10_MHZ; - /* * There are major locking problems in nl80211/mac80211 for CSA, * disable for all drivers until this has been reworked. -- cgit v0.10.2 From 8ffcc704c963b4157391bd87a4544cdfd18b574d Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 23 Jan 2014 14:28:16 +0200 Subject: mac80211: avoid deadlock revealed by lockdep MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit sdata->u.ap.request_smps_work can’t be flushed synchronously under wdev_lock(wdev) since ieee80211_request_smps_ap_work itself locks the same lock. While at it, reset the driver_smps_mode when the ap is stopped to its default: OFF. This solves: ====================================================== [ INFO: possible circular locking dependency detected ] 3.12.0-ipeer+ #2 Tainted: G O ------------------------------------------------------- rmmod/2867 is trying to acquire lock: ((&sdata->u.ap.request_smps_work)){+.+...}, at: [] flush_work+0x0/0x90 but task is already holding lock: (&wdev->mtx){+.+.+.}, at: [] cfg80211_stop_ap+0x26/0x230 [cfg80211] which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #1 (&wdev->mtx){+.+.+.}: [] lock_acquire+0x79/0xe0 [] mutex_lock_nested+0x4a/0x360 [] ieee80211_request_smps_ap_work+0x2b/0x50 [mac80211] [] process_one_work+0x198/0x450 [] worker_thread+0xf9/0x320 [] kthread+0x9f/0xb0 [] ret_from_kernel_thread+0x1b/0x28 -> #0 ((&sdata->u.ap.request_smps_work)){+.+...}: [] __lock_acquire+0x183f/0x1910 [] lock_acquire+0x79/0xe0 [] flush_work+0x47/0x90 [] __cancel_work_timer+0x67/0xe0 [] cancel_work_sync+0xf/0x20 [] ieee80211_stop_ap+0x8c/0x340 [mac80211] [] cfg80211_stop_ap+0x8c/0x230 [cfg80211] [] cfg80211_leave+0x79/0x100 [cfg80211] [] cfg80211_netdev_notifier_call+0xf2/0x4f0 [cfg80211] [] notifier_call_chain+0x59/0x130 [] __raw_notifier_call_chain+0x1e/0x30 [] raw_notifier_call_chain+0x1f/0x30 [] call_netdevice_notifiers_info+0x33/0x70 [] call_netdevice_notifiers+0x13/0x20 [] __dev_close_many+0x34/0xb0 [] dev_close_many+0x6e/0xc0 [] rollback_registered_many+0xa7/0x1f0 [] unregister_netdevice_many+0x14/0x60 [] ieee80211_remove_interfaces+0xe9/0x170 [mac80211] [] ieee80211_unregister_hw+0x56/0x110 [mac80211] [] iwl_op_mode_mvm_stop+0x26/0xe0 [iwlmvm] [] _iwl_op_mode_stop+0x3a/0x70 [iwlwifi] [] iwl_opmode_deregister+0x6f/0x90 [iwlwifi] [] __exit_compat+0xd/0x19 [iwlmvm] [] SyS_delete_module+0x179/0x2b0 [] sysenter_do_call+0x12/0x32 Fixes: 687da132234f ("mac80211: implement SMPS for AP") Cc: [3.13] Reported-by: Ilan Peer Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 94b4acb..33acdca 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1090,8 +1090,6 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) kfree(sdata->u.ap.next_beacon); sdata->u.ap.next_beacon = NULL; - cancel_work_sync(&sdata->u.ap.request_smps_work); - /* turn off carrier for this interface and dependent VLANs */ list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) netif_carrier_off(vlan->dev); @@ -1103,6 +1101,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) kfree_rcu(old_beacon, rcu_head); if (old_probe_resp) kfree_rcu(old_probe_resp, rcu_head); + sdata->u.ap.driver_smps_mode = IEEE80211_SMPS_OFF; __sta_info_flush(sdata, true); ieee80211_free_keys(sdata, true); diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index fab7b91..70dd013 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c @@ -466,7 +466,9 @@ void ieee80211_request_smps_ap_work(struct work_struct *work) u.ap.request_smps_work); sdata_lock(sdata); - __ieee80211_request_smps_ap(sdata, sdata->u.ap.driver_smps_mode); + if (sdata_dereference(sdata->u.ap.beacon, sdata)) + __ieee80211_request_smps_ap(sdata, + sdata->u.ap.driver_smps_mode); sdata_unlock(sdata); } diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 3dfd20a..ae2eb14 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -770,12 +770,19 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, ieee80211_roc_purge(local, sdata); - if (sdata->vif.type == NL80211_IFTYPE_STATION) + switch (sdata->vif.type) { + case NL80211_IFTYPE_STATION: ieee80211_mgd_stop(sdata); - - if (sdata->vif.type == NL80211_IFTYPE_ADHOC) + break; + case NL80211_IFTYPE_ADHOC: ieee80211_ibss_stop(sdata); - + break; + case NL80211_IFTYPE_AP: + cancel_work_sync(&sdata->u.ap.request_smps_work); + break; + default: + break; + } /* * Remove all stations associated with this interface. -- cgit v0.10.2 From a617302c531eaf497ccd02a61d380efc119ba999 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 22 Jan 2014 11:14:18 +0200 Subject: cfg80211: fix scan done race When an interface/wdev is removed, any ongoing scan should be cancelled by the driver. This will make it call cfg80211, which only queues a work struct. If interface/wdev removal is quick enough, this can leave the scan request pending and processed only after the interface is gone, causing a use-after-free. Fix this by making sure the scan request is not pending after the interface is destroyed. We can't flush or cancel the work item due to locking concerns, but when it'll run it shouldn't find anything to do. This leaves a potential issue, if a new scan gets requested before the work runs, it prematurely stops the running scan, potentially causing another crash. I'll fix that in the next patch. This was particularly observed with P2P_DEVICE wdevs, likely because freeing them is quicker than freeing netdevs. Reported-by: Andrei Otcheretianski Fixes: 4a58e7c38443 ("cfg80211: don't "leak" uncompleted scans") Signed-off-by: Johannes Berg diff --git a/net/wireless/core.c b/net/wireless/core.c index 77fe4c7..02ed00d 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -203,8 +203,11 @@ void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev, rdev->opencount--; - WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev && - !rdev->scan_req->notified); + if (rdev->scan_req && rdev->scan_req->wdev == wdev) { + if (WARN_ON(!rdev->scan_req->notified)) + rdev->scan_req->aborted = true; + ___cfg80211_scan_done(rdev); + } } static int cfg80211_rfkill_set_block(void *data, bool blocked) @@ -856,8 +859,11 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, break; case NETDEV_DOWN: cfg80211_update_iface_num(rdev, wdev->iftype, -1); - WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev && - !rdev->scan_req->notified); + if (rdev->scan_req && rdev->scan_req->wdev == wdev) { + if (WARN_ON(!rdev->scan_req->notified)) + rdev->scan_req->aborted = true; + ___cfg80211_scan_done(rdev); + } if (WARN_ON(rdev->sched_scan_req && rdev->sched_scan_req->dev == wdev->netdev)) { -- cgit v0.10.2 From f9d15d162b3acf28f85b3ac05c4883e5ed588d28 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 22 Jan 2014 11:14:19 +0200 Subject: cfg80211: send scan results from work queue Due to the previous commit, when a scan finishes, it is in theory possible to hit the following sequence: 1. interface starts being removed 2. scan is cancelled by driver and cfg80211 is notified 3. scan done work is scheduled 4. interface is removed completely, rdev->scan_req is freed, event sent to userspace but scan done work remains pending 5. new scan is requested on another virtual interface 6. scan done work runs, freeing the still-running scan To fix this situation, hang on to the scan done message and block new scans while that is the case, and only send the message from the work function, regardless of whether the scan_req is already freed from interface removal. This makes step 5 above impossible and changes step 6 to be 5. scan done work runs, sending the scan done message As this can't work for wext, so we send the message immediately, but this shouldn't be an issue since we still return -EBUSY. Signed-off-by: Johannes Berg diff --git a/net/wireless/core.c b/net/wireless/core.c index 02ed00d..010892b 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -206,7 +206,7 @@ void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev, if (rdev->scan_req && rdev->scan_req->wdev == wdev) { if (WARN_ON(!rdev->scan_req->notified)) rdev->scan_req->aborted = true; - ___cfg80211_scan_done(rdev); + ___cfg80211_scan_done(rdev, false); } } @@ -862,7 +862,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, if (rdev->scan_req && rdev->scan_req->wdev == wdev) { if (WARN_ON(!rdev->scan_req->notified)) rdev->scan_req->aborted = true; - ___cfg80211_scan_done(rdev); + ___cfg80211_scan_done(rdev, false); } if (WARN_ON(rdev->sched_scan_req && diff --git a/net/wireless/core.h b/net/wireless/core.h index 37ec16d..f1d193b 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -62,6 +62,7 @@ struct cfg80211_registered_device { struct rb_root bss_tree; u32 bss_generation; struct cfg80211_scan_request *scan_req; /* protected by RTNL */ + struct sk_buff *scan_msg; struct cfg80211_sched_scan_request *sched_scan_req; unsigned long suspend_at; struct work_struct scan_done_wk; @@ -361,7 +362,8 @@ int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, struct key_params *params, int key_idx, bool pairwise, const u8 *mac_addr); void __cfg80211_scan_done(struct work_struct *wk); -void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev); +void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, + bool send_message); void __cfg80211_sched_scan_results(struct work_struct *wk); int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev, bool driver_initiated); diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 6ea960b..4fe2e6e 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -5245,7 +5245,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) if (!rdev->ops->scan) return -EOPNOTSUPP; - if (rdev->scan_req) { + if (rdev->scan_req || rdev->scan_msg) { err = -EBUSY; goto unlock; } @@ -10012,40 +10012,31 @@ void nl80211_send_scan_start(struct cfg80211_registered_device *rdev, NL80211_MCGRP_SCAN, GFP_KERNEL); } -void nl80211_send_scan_done(struct cfg80211_registered_device *rdev, - struct wireless_dev *wdev) +struct sk_buff *nl80211_build_scan_msg(struct cfg80211_registered_device *rdev, + struct wireless_dev *wdev, bool aborted) { struct sk_buff *msg; msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) - return; + return NULL; if (nl80211_send_scan_msg(msg, rdev, wdev, 0, 0, 0, - NL80211_CMD_NEW_SCAN_RESULTS) < 0) { + aborted ? NL80211_CMD_SCAN_ABORTED : + NL80211_CMD_NEW_SCAN_RESULTS) < 0) { nlmsg_free(msg); - return; + return NULL; } - genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0, - NL80211_MCGRP_SCAN, GFP_KERNEL); + return msg; } -void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev, - struct wireless_dev *wdev) +void nl80211_send_scan_result(struct cfg80211_registered_device *rdev, + struct sk_buff *msg) { - struct sk_buff *msg; - - msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) return; - if (nl80211_send_scan_msg(msg, rdev, wdev, 0, 0, 0, - NL80211_CMD_SCAN_ABORTED) < 0) { - nlmsg_free(msg); - return; - } - genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0, NL80211_MCGRP_SCAN, GFP_KERNEL); } diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index b1b2313..7579974 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h @@ -8,10 +8,10 @@ void nl80211_exit(void); void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev); void nl80211_send_scan_start(struct cfg80211_registered_device *rdev, struct wireless_dev *wdev); -void nl80211_send_scan_done(struct cfg80211_registered_device *rdev, - struct wireless_dev *wdev); -void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev, - struct wireless_dev *wdev); +struct sk_buff *nl80211_build_scan_msg(struct cfg80211_registered_device *rdev, + struct wireless_dev *wdev, bool aborted); +void nl80211_send_scan_result(struct cfg80211_registered_device *rdev, + struct sk_buff *msg); void nl80211_send_sched_scan(struct cfg80211_registered_device *rdev, struct net_device *netdev, u32 cmd); void nl80211_send_sched_scan_results(struct cfg80211_registered_device *rdev, diff --git a/net/wireless/scan.c b/net/wireless/scan.c index b528e31..d1ed4ae 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -161,18 +161,25 @@ static void __cfg80211_bss_expire(struct cfg80211_registered_device *dev, dev->bss_generation++; } -void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev) +void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, + bool send_message) { struct cfg80211_scan_request *request; struct wireless_dev *wdev; + struct sk_buff *msg; #ifdef CONFIG_CFG80211_WEXT union iwreq_data wrqu; #endif ASSERT_RTNL(); - request = rdev->scan_req; + if (rdev->scan_msg) { + nl80211_send_scan_result(rdev, rdev->scan_msg); + rdev->scan_msg = NULL; + return; + } + request = rdev->scan_req; if (!request) return; @@ -186,18 +193,16 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev) if (wdev->netdev) cfg80211_sme_scan_done(wdev->netdev); - if (request->aborted) { - nl80211_send_scan_aborted(rdev, wdev); - } else { - if (request->flags & NL80211_SCAN_FLAG_FLUSH) { - /* flush entries from previous scans */ - spin_lock_bh(&rdev->bss_lock); - __cfg80211_bss_expire(rdev, request->scan_start); - spin_unlock_bh(&rdev->bss_lock); - } - nl80211_send_scan_done(rdev, wdev); + if (!request->aborted && + request->flags & NL80211_SCAN_FLAG_FLUSH) { + /* flush entries from previous scans */ + spin_lock_bh(&rdev->bss_lock); + __cfg80211_bss_expire(rdev, request->scan_start); + spin_unlock_bh(&rdev->bss_lock); } + msg = nl80211_build_scan_msg(rdev, wdev, request->aborted); + #ifdef CONFIG_CFG80211_WEXT if (wdev->netdev && !request->aborted) { memset(&wrqu, 0, sizeof(wrqu)); @@ -211,6 +216,11 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev) rdev->scan_req = NULL; kfree(request); + + if (!send_message) + rdev->scan_msg = msg; + else + nl80211_send_scan_result(rdev, msg); } void __cfg80211_scan_done(struct work_struct *wk) @@ -221,7 +231,7 @@ void __cfg80211_scan_done(struct work_struct *wk) scan_done_wk); rtnl_lock(); - ___cfg80211_scan_done(rdev); + ___cfg80211_scan_done(rdev, true); rtnl_unlock(); } @@ -1079,7 +1089,7 @@ int cfg80211_wext_siwscan(struct net_device *dev, if (IS_ERR(rdev)) return PTR_ERR(rdev); - if (rdev->scan_req) { + if (rdev->scan_req || rdev->scan_msg) { err = -EBUSY; goto out; } @@ -1481,7 +1491,7 @@ int cfg80211_wext_giwscan(struct net_device *dev, if (IS_ERR(rdev)) return PTR_ERR(rdev); - if (rdev->scan_req) + if (rdev->scan_req || rdev->scan_msg) return -EAGAIN; res = ieee80211_scan_results(rdev, info, extra, data->length); diff --git a/net/wireless/sme.c b/net/wireless/sme.c index a635091..f04d4c3 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c @@ -67,7 +67,7 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev) ASSERT_RDEV_LOCK(rdev); ASSERT_WDEV_LOCK(wdev); - if (rdev->scan_req) + if (rdev->scan_req || rdev->scan_msg) return -EBUSY; if (wdev->conn->params.channel) -- cgit v0.10.2 From 0297ea17bf7879fb5846fafd1be4c0471e72848d Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Mon, 27 Jan 2014 11:07:42 +0200 Subject: mac80211: release the channel in error path in start_ap When the driver cannot start the AP or when the assignement of the beacon goes wrong, we need to unassign the vif. Cc: stable@vger.kernel.org Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 33acdca..453e974 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1021,8 +1021,10 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, IEEE80211_P2P_OPPPS_ENABLE_BIT; err = ieee80211_assign_beacon(sdata, ¶ms->beacon); - if (err < 0) + if (err < 0) { + ieee80211_vif_release_channel(sdata); return err; + } changed |= err; err = drv_start_ap(sdata->local, sdata); @@ -1032,6 +1034,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, if (old) kfree_rcu(old, rcu_head); RCU_INIT_POINTER(sdata->u.ap.beacon, NULL); + ieee80211_vif_release_channel(sdata); return err; } -- cgit v0.10.2 From d4c80d9df6d1e4473b1409e4d220ca3d1612125c Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Thu, 30 Jan 2014 14:17:28 +0530 Subject: mac80211: Fix IBSS disconnect Currently, when a station leaves an IBSS network, the corresponding BSS is not dropped from cfg80211 if there are other active stations in the network. But, the small window that is present when trying to determine a station's status based on IEEE80211_IBSS_MERGE_INTERVAL introduces a race. Instead of trying to keep the BSS, always remove it when leaving an IBSS network. There is not much benefit to retain the BSS entry since it will be added with a subsequent join operation. This fixes an issue where a dangling BSS entry causes ath9k to wait for a beacon indefinitely. Cc: Reported-by: Simon Wunderlich Signed-off-by: Sujith Manoharan Signed-off-by: Johannes Berg diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 771080e..2796a19 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -695,12 +695,9 @@ static void ieee80211_ibss_disconnect(struct ieee80211_sub_if_data *sdata) struct cfg80211_bss *cbss; struct beacon_data *presp; struct sta_info *sta; - int active_ibss; u16 capability; - active_ibss = ieee80211_sta_active_ibss(sdata); - - if (!active_ibss && !is_zero_ether_addr(ifibss->bssid)) { + if (!is_zero_ether_addr(ifibss->bssid)) { capability = WLAN_CAPABILITY_IBSS; if (ifibss->privacy) -- cgit v0.10.2 From 338f977f4eb441e69bb9a46eaa0ac715c931a67f Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sat, 1 Feb 2014 00:16:23 +0100 Subject: mac80211: fix fragmentation code, particularly for encryption The "new" fragmentation code (since my rewrite almost 5 years ago) erroneously sets skb->len rather than using skb_trim() to adjust the length of the first fragment after copying out all the others. This leaves the skb tail pointer pointing to after where the data originally ended, and thus causes the encryption MIC to be written at that point, rather than where it belongs: immediately after the data. The impact of this is that if software encryption is done, then a) encryption doesn't work for the first fragment, the connection becomes unusable as the first fragment will never be properly verified at the receiver, the MIC is practically guaranteed to be wrong b) we leak up to 8 bytes of plaintext (!) of the packet out into the air This is only mitigated by the fact that many devices are capable of doing encryption in hardware, in which case this can't happen as the tail pointer is irrelevant in that case. Additionally, fragmentation is not used very frequently and would normally have to be configured manually. Fix this by using skb_trim() properly. Cc: stable@vger.kernel.org Fixes: 2de8e0d999b8 ("mac80211: rewrite fragmentation") Reported-by: Jouni Malinen Signed-off-by: Johannes Berg diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 27c990b..97a02d3 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -878,7 +878,7 @@ static int ieee80211_fragment(struct ieee80211_tx_data *tx, } /* adjust first fragment's length */ - skb->len = hdrlen + per_fragm; + skb_trim(skb, hdrlen + per_fragm); return 0; } -- cgit v0.10.2 From fab57a6cc227468ca9e6a4c7ff8d3b10727785ee Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 29 Jan 2014 13:28:02 +0100 Subject: mac80211: fix virtual monitor interface iteration During channel context assignment, the interface should be found by interface iteration, so we need to assign the pointer before the channel context. Reported-by: Emmanuel Grumbach Tested-by: Emmanuel Grumbach Signed-off-by: Johannes Berg diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index ae2eb14..d6d1f1d 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -418,20 +418,24 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local) return ret; } + mutex_lock(&local->iflist_mtx); + rcu_assign_pointer(local->monitor_sdata, sdata); + mutex_unlock(&local->iflist_mtx); + mutex_lock(&local->mtx); ret = ieee80211_vif_use_channel(sdata, &local->monitor_chandef, IEEE80211_CHANCTX_EXCLUSIVE); mutex_unlock(&local->mtx); if (ret) { + mutex_lock(&local->iflist_mtx); + rcu_assign_pointer(local->monitor_sdata, NULL); + mutex_unlock(&local->iflist_mtx); + synchronize_net(); drv_remove_interface(local, sdata); kfree(sdata); return ret; } - mutex_lock(&local->iflist_mtx); - rcu_assign_pointer(local->monitor_sdata, sdata); - mutex_unlock(&local->iflist_mtx); - return 0; } -- cgit v0.10.2 From a3485d088516be4c2ae2890e8ad64321481f2857 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 4 Feb 2014 13:42:10 +0100 Subject: gpio: consumer.h: Move forward declarations outside #ifdef Make sure that the forward declared structs in gpio/consumer.h are also visible on the else branch of the CONFIG_GPIOLIB #ifdef. Fixes the following warnings and their associated errors when CONFIG_GPIOLIB is not selected: include/linux/gpio/consumer.h:67:14: warning: 'struct device' declared inside parameter list include/linux/gpio/consumer.h:67:14: warning: its scope is only this definition or declaration, which is probably not what you want [...] Signed-off-by: Lars-Peter Clausen Reviewed-by: Alexandre Courbot Signed-off-by: Linus Walleij diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h index 4d34dbb..7a8144f 100644 --- a/include/linux/gpio/consumer.h +++ b/include/linux/gpio/consumer.h @@ -4,8 +4,6 @@ #include #include -#ifdef CONFIG_GPIOLIB - struct device; struct gpio_chip; @@ -18,6 +16,8 @@ struct gpio_chip; */ struct gpio_desc; +#ifdef CONFIG_GPIOLIB + /* Acquire and dispose GPIOs */ struct gpio_desc *__must_check gpiod_get(struct device *dev, const char *con_id); -- cgit v0.10.2 From 1bc8927cc5b57c4d9198e4c4ac6b426b7c7d72c7 Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Wed, 5 Feb 2014 13:36:05 +0100 Subject: s390/cio: improve cio_commit_config The modify subchannel wrapper cio_commit_config can fail when (unexpected) status is pending on the subchannel. Callers of cio_commit_config (that operated on enabled subchannels) needed to do error handling for that case (clear the unexpected status with test subchannel and retry). This error handling is missing in some code paths and caused online setting of devices to fail. Fix this for all callers by moving the error handling inside cio_commit_config. Reviewed-by: Peter Oberparleiter Signed-off-by: Sebastian Ott Signed-off-by: Martin Schwidefsky diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 88e35d8..8ee88c4 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c @@ -342,8 +342,9 @@ static int cio_check_config(struct subchannel *sch, struct schib *schib) */ int cio_commit_config(struct subchannel *sch) { - struct schib schib; int ccode, retry, ret = 0; + struct schib schib; + struct irb irb; if (stsch_err(sch->schid, &schib) || !css_sch_is_valid(&schib)) return -ENODEV; @@ -367,7 +368,10 @@ int cio_commit_config(struct subchannel *sch) ret = -EAGAIN; break; case 1: /* status pending */ - return -EBUSY; + ret = -EBUSY; + if (tsch(sch->schid, &irb)) + return ret; + break; case 2: /* busy */ udelay(100); /* allow for recovery */ ret = -EBUSY; @@ -403,7 +407,6 @@ EXPORT_SYMBOL_GPL(cio_update_schib); */ int cio_enable_subchannel(struct subchannel *sch, u32 intparm) { - int retry; int ret; CIO_TRACE_EVENT(2, "ensch"); @@ -418,20 +421,14 @@ int cio_enable_subchannel(struct subchannel *sch, u32 intparm) sch->config.isc = sch->isc; sch->config.intparm = intparm; - for (retry = 0; retry < 3; retry++) { + ret = cio_commit_config(sch); + if (ret == -EIO) { + /* + * Got a program check in msch. Try without + * the concurrent sense bit the next time. + */ + sch->config.csense = 0; ret = cio_commit_config(sch); - if (ret == -EIO) { - /* - * Got a program check in msch. Try without - * the concurrent sense bit the next time. - */ - sch->config.csense = 0; - } else if (ret == -EBUSY) { - struct irb irb; - if (tsch(sch->schid, &irb) != 0) - break; - } else - break; } CIO_HEX_EVENT(2, &ret, sizeof(ret)); return ret; @@ -444,7 +441,6 @@ EXPORT_SYMBOL_GPL(cio_enable_subchannel); */ int cio_disable_subchannel(struct subchannel *sch) { - int retry; int ret; CIO_TRACE_EVENT(2, "dissch"); @@ -456,16 +452,8 @@ int cio_disable_subchannel(struct subchannel *sch) return -ENODEV; sch->config.ena = 0; + ret = cio_commit_config(sch); - for (retry = 0; retry < 3; retry++) { - ret = cio_commit_config(sch); - if (ret == -EBUSY) { - struct irb irb; - if (tsch(sch->schid, &irb) != 0) - break; - } else - break; - } CIO_HEX_EVENT(2, &ret, sizeof(ret)); return ret; } -- cgit v0.10.2 From b8ecbee67c732ef9fc47fcf50aed6b7bb6231d98 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 6 Feb 2014 09:17:41 +0000 Subject: netfilter: nf_tables: fix log/queue expressions for NFPROTO_INET The log and queue expressions both store the family during ->init() and use it to deliver packets. This is wrong when used in NFPROTO_INET since they should both deliver to the actual AF of the packet, not the dummy NFPROTO_INET. Use the family from the hook ops to fix this. Signed-off-by: Patrick McHardy Signed-off-by: Pablo Neira Ayuso diff --git a/net/netfilter/nft_log.c b/net/netfilter/nft_log.c index 5af7901..26c5154 100644 --- a/net/netfilter/nft_log.c +++ b/net/netfilter/nft_log.c @@ -23,7 +23,6 @@ static const char *nft_log_null_prefix = ""; struct nft_log { struct nf_loginfo loginfo; char *prefix; - int family; }; static void nft_log_eval(const struct nft_expr *expr, @@ -33,7 +32,7 @@ static void nft_log_eval(const struct nft_expr *expr, const struct nft_log *priv = nft_expr_priv(expr); struct net *net = dev_net(pkt->in ? pkt->in : pkt->out); - nf_log_packet(net, priv->family, pkt->ops->hooknum, pkt->skb, pkt->in, + nf_log_packet(net, pkt->ops->pf, pkt->ops->hooknum, pkt->skb, pkt->in, pkt->out, &priv->loginfo, "%s", priv->prefix); } @@ -52,8 +51,6 @@ static int nft_log_init(const struct nft_ctx *ctx, struct nf_loginfo *li = &priv->loginfo; const struct nlattr *nla; - priv->family = ctx->afi->family; - nla = tb[NFTA_LOG_PREFIX]; if (nla != NULL) { priv->prefix = kmalloc(nla_len(nla) + 1, GFP_KERNEL); diff --git a/net/netfilter/nft_queue.c b/net/netfilter/nft_queue.c index cbea473..e8ae2f6 100644 --- a/net/netfilter/nft_queue.c +++ b/net/netfilter/nft_queue.c @@ -25,7 +25,6 @@ struct nft_queue { u16 queuenum; u16 queues_total; u16 flags; - u8 family; }; static void nft_queue_eval(const struct nft_expr *expr, @@ -43,7 +42,7 @@ static void nft_queue_eval(const struct nft_expr *expr, queue = priv->queuenum + cpu % priv->queues_total; } else { queue = nfqueue_hash(pkt->skb, queue, - priv->queues_total, priv->family, + priv->queues_total, pkt->ops->pf, jhash_initval); } } @@ -71,7 +70,6 @@ static int nft_queue_init(const struct nft_ctx *ctx, return -EINVAL; init_hashrandom(&jhash_initval); - priv->family = ctx->afi->family; priv->queuenum = ntohs(nla_get_be16(tb[NFTA_QUEUE_NUM])); if (tb[NFTA_QUEUE_TOTAL] != NULL) -- cgit v0.10.2 From 0165d9325d6a3cf856e2cbbe64a0f4635ac75893 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Sat, 25 Jan 2014 14:03:51 +0100 Subject: netfilter: nf_tables: fix racy rule deletion We may lost race if we flush the rule-set (which happens asynchronously via call_rcu) and we try to remove the table (that userspace assumes to be empty). Fix this by recovering synchronous rule and chain deletion. This was introduced time ago before we had no batch support, and synchronous rule deletion performance was not good. Now that we have the batch support, we can just postpone the purge of old rule in a second step in the commit phase. All object deletions are synchronous after this patch. As a side effect, we save memory as we don't need rcu_head per rule anymore. Cc: Patrick McHardy Reported-by: Arturo Borrero Gonzalez Signed-off-by: Pablo Neira Ayuso diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h index 0f68e47..e7e14ff 100644 --- a/include/net/netfilter/nf_tables.h +++ b/include/net/netfilter/nf_tables.h @@ -322,7 +322,6 @@ static inline void *nft_expr_priv(const struct nft_expr *expr) * struct nft_rule - nf_tables rule * * @list: used internally - * @rcu_head: used internally for rcu * @handle: rule handle * @genmask: generation mask * @dlen: length of expression data @@ -330,7 +329,6 @@ static inline void *nft_expr_priv(const struct nft_expr *expr) */ struct nft_rule { struct list_head list; - struct rcu_head rcu_head; u64 handle:46, genmask:2, dlen:16; @@ -391,7 +389,6 @@ enum nft_chain_flags { * * @rules: list of rules in the chain * @list: used internally - * @rcu_head: used internally * @net: net namespace that this chain belongs to * @table: table that this chain belongs to * @handle: chain handle @@ -403,7 +400,6 @@ enum nft_chain_flags { struct nft_chain { struct list_head rules; struct list_head list; - struct rcu_head rcu_head; struct net *net; struct nft_table *table; u64 handle; diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 113c469..3a2e480 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -1008,10 +1008,8 @@ notify: return 0; } -static void nf_tables_rcu_chain_destroy(struct rcu_head *head) +static void nf_tables_chain_destroy(struct nft_chain *chain) { - struct nft_chain *chain = container_of(head, struct nft_chain, rcu_head); - BUG_ON(chain->use > 0); if (chain->flags & NFT_BASE_CHAIN) { @@ -1059,7 +1057,9 @@ static int nf_tables_delchain(struct sock *nlsk, struct sk_buff *skb, family); /* Make sure all rule references are gone before this is released */ - call_rcu(&chain->rcu_head, nf_tables_rcu_chain_destroy); + synchronize_rcu(); + + nf_tables_chain_destroy(chain); return 0; } @@ -1531,9 +1531,8 @@ err: return err; } -static void nf_tables_rcu_rule_destroy(struct rcu_head *head) +static void nf_tables_rule_destroy(struct nft_rule *rule) { - struct nft_rule *rule = container_of(head, struct nft_rule, rcu_head); struct nft_expr *expr; /* @@ -1548,11 +1547,6 @@ static void nf_tables_rcu_rule_destroy(struct rcu_head *head) kfree(rule); } -static void nf_tables_rule_destroy(struct nft_rule *rule) -{ - call_rcu(&rule->rcu_head, nf_tables_rcu_rule_destroy); -} - #define NFT_RULE_MAXEXPRS 128 static struct nft_expr_info *info; @@ -1819,9 +1813,6 @@ static int nf_tables_commit(struct sk_buff *skb) synchronize_rcu(); list_for_each_entry_safe(rupd, tmp, &net->nft.commit_list, list) { - /* Delete this rule from the dirty list */ - list_del(&rupd->list); - /* This rule was inactive in the past and just became active. * Clear the next bit of the genmask since its meaning has * changed, now it is the future. @@ -1832,6 +1823,7 @@ static int nf_tables_commit(struct sk_buff *skb) rupd->chain, rupd->rule, NFT_MSG_NEWRULE, 0, rupd->family); + list_del(&rupd->list); kfree(rupd); continue; } @@ -1841,7 +1833,15 @@ static int nf_tables_commit(struct sk_buff *skb) nf_tables_rule_notify(skb, rupd->nlh, rupd->table, rupd->chain, rupd->rule, NFT_MSG_DELRULE, 0, rupd->family); + } + + /* Make sure we don't see any packet traversing old rules */ + synchronize_rcu(); + + /* Now we can safely release unused old rules */ + list_for_each_entry_safe(rupd, tmp, &net->nft.commit_list, list) { nf_tables_rule_destroy(rupd->rule); + list_del(&rupd->list); kfree(rupd); } @@ -1854,20 +1854,26 @@ static int nf_tables_abort(struct sk_buff *skb) struct nft_rule_trans *rupd, *tmp; list_for_each_entry_safe(rupd, tmp, &net->nft.commit_list, list) { - /* Delete all rules from the dirty list */ - list_del(&rupd->list); - if (!nft_rule_is_active_next(net, rupd->rule)) { nft_rule_clear(net, rupd->rule); + list_del(&rupd->list); kfree(rupd); continue; } /* This rule is inactive, get rid of it */ list_del_rcu(&rupd->rule->list); + } + + /* Make sure we don't see any packet accessing aborted rules */ + synchronize_rcu(); + + list_for_each_entry_safe(rupd, tmp, &net->nft.commit_list, list) { nf_tables_rule_destroy(rupd->rule); + list_del(&rupd->list); kfree(rupd); } + return 0; } -- cgit v0.10.2 From 80d767d770fd9c697e434fd080c2db7b5c60c6dd Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Fri, 24 Jan 2014 16:41:36 -0500 Subject: time: Fix overflow when HZ is smaller than 60 When compiling for the IA-64 ski emulator, HZ is set to 32 because the emulation is slow and we don't want to waste too many cycles processing timers. Alpha also has an option to set HZ to 32. This causes integer underflow in kernel/time/jiffies.c: kernel/time/jiffies.c:66:2: warning: large integer implicitly truncated to unsigned type [-Woverflow] .mult = NSEC_PER_JIFFY << JIFFIES_SHIFT, /* details above */ ^ This patch reduces the JIFFIES_SHIFT value to avoid the overflow. Signed-off-by: Mikulas Patocka Link: http://lkml.kernel.org/r/alpine.LRH.2.02.1401241639100.23871@file01.intranet.prod.int.rdu2.redhat.com Cc: stable@vger.kernel.org Signed-off-by: Thomas Gleixner diff --git a/kernel/time/jiffies.c b/kernel/time/jiffies.c index 7a925ba..a6a5bf5 100644 --- a/kernel/time/jiffies.c +++ b/kernel/time/jiffies.c @@ -51,7 +51,13 @@ * HZ shrinks, so values greater than 8 overflow 32bits when * HZ=100. */ +#if HZ < 34 +#define JIFFIES_SHIFT 6 +#elif HZ < 67 +#define JIFFIES_SHIFT 7 +#else #define JIFFIES_SHIFT 8 +#endif static cycle_t jiffies_read(struct clocksource *cs) { -- cgit v0.10.2 From ad037c1f4ae6f9258f27fddb679ceb703ff07a88 Mon Sep 17 00:00:00 2001 From: Tim Kryger Date: Tue, 4 Feb 2014 16:15:04 -0800 Subject: clocksource: Kona: Print warning rather than panic Since there may be other clocksources available, this driver should not trigger a panic simply because it can not determine the frequency of an external clock. This change refactors the driver to allow a warning to be printed in this case instead. Signed-off-by: Tim Kryger Reviewed-by: Markus Mayer Reviewed-by: Matt Porter Cc: Christian Daudt Cc: Daniel Lezcano Link: http://lkml.kernel.org/r/1391559304-26558-1-git-send-email-tim.kryger@linaro.org Signed-off-by: Thomas Gleixner diff --git a/drivers/clocksource/bcm_kona_timer.c b/drivers/clocksource/bcm_kona_timer.c index 974b2db..0595dc6 100644 --- a/drivers/clocksource/bcm_kona_timer.c +++ b/drivers/clocksource/bcm_kona_timer.c @@ -99,31 +99,6 @@ kona_timer_get_counter(void *timer_base, uint32_t *msw, uint32_t *lsw) return; } -static void __init kona_timers_init(struct device_node *node) -{ - u32 freq; - struct clk *external_clk; - - external_clk = of_clk_get_by_name(node, NULL); - - if (!IS_ERR(external_clk)) { - arch_timer_rate = clk_get_rate(external_clk); - clk_prepare_enable(external_clk); - } else if (!of_property_read_u32(node, "clock-frequency", &freq)) { - arch_timer_rate = freq; - } else { - panic("unable to determine clock-frequency"); - } - - /* Setup IRQ numbers */ - timers.tmr_irq = irq_of_parse_and_map(node, 0); - - /* Setup IO addresses */ - timers.tmr_regs = of_iomap(node, 0); - - kona_timer_disable_and_clear(timers.tmr_regs); -} - static int kona_timer_set_next_event(unsigned long clc, struct clock_event_device *unused) { @@ -198,7 +173,34 @@ static struct irqaction kona_timer_irq = { static void __init kona_timer_init(struct device_node *node) { - kona_timers_init(node); + u32 freq; + struct clk *external_clk; + + if (!of_device_is_available(node)) { + pr_info("Kona Timer v1 marked as disabled in device tree\n"); + return; + } + + external_clk = of_clk_get_by_name(node, NULL); + + if (!IS_ERR(external_clk)) { + arch_timer_rate = clk_get_rate(external_clk); + clk_prepare_enable(external_clk); + } else if (!of_property_read_u32(node, "clock-frequency", &freq)) { + arch_timer_rate = freq; + } else { + pr_err("Kona Timer v1 unable to determine clock-frequency"); + return; + } + + /* Setup IRQ numbers */ + timers.tmr_irq = irq_of_parse_and_map(node, 0); + + /* Setup IO addresses */ + timers.tmr_regs = of_iomap(node, 0); + + kona_timer_disable_and_clear(timers.tmr_regs); + kona_timer_clockevents_init(); setup_irq(timers.tmr_irq, &kona_timer_irq); kona_timer_set_next_event((arch_timer_rate / HZ), NULL); -- cgit v0.10.2 From b927e1c20462c1ad9caf4c4fa3a30e838a2d4037 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Thu, 30 Jan 2014 19:01:16 +0100 Subject: drm/radeon: fix UVD IRQ support on SI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwise decoding isn't really useable. bug: https://bugs.freedesktop.org/show_bug.cgi?id=71448 Signed-off-by: Christian König Cc: stable@vger.kernel.org Signed-off-by: Alex Deucher diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 09ec4f6..8357832 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -6338,6 +6338,10 @@ restart_ih: break; } break; + case 124: /* UVD */ + DRM_DEBUG("IH: UVD int: 0x%08x\n", src_data); + radeon_fence_process(rdev, R600_RING_TYPE_UVD_INDEX); + break; case 146: case 147: addr = RREG32(VM_CONTEXT1_PROTECTION_FAULT_ADDR); -- cgit v0.10.2 From 858a41c853cef2cb01de34dae334c19c1c15b237 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 30 Jan 2014 14:35:04 -0500 Subject: drm/radeon: fix UVD IRQ support on 7xx Otherwise decoding isn't really useable. Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 56140b4..cdbc417 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -3991,6 +3991,10 @@ restart_ih: break; } break; + case 124: /* UVD */ + DRM_DEBUG("IH: UVD int: 0x%08x\n", src_data); + radeon_fence_process(rdev, R600_RING_TYPE_UVD_INDEX); + break; case 176: /* CP_INT in ring buffer */ case 177: /* CP_INT in IB1 */ case 178: /* CP_INT in IB2 */ -- cgit v0.10.2 From 9f3f63f24c901cad831e78bbb738df61a1c4ff02 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 30 Jan 2014 11:19:22 -0500 Subject: drm/radeon/dpm: use the driver state for dpm debugfs For btc and newer, we may modify the power state depending on the circumstances. Use the modified state rather than the base state. Signed-off-by: Alex Deucher diff --git a/drivers/gpu/drm/radeon/btc_dpm.c b/drivers/gpu/drm/radeon/btc_dpm.c index 0fbd36f..05ad469 100644 --- a/drivers/gpu/drm/radeon/btc_dpm.c +++ b/drivers/gpu/drm/radeon/btc_dpm.c @@ -2756,6 +2756,37 @@ void btc_dpm_fini(struct radeon_device *rdev) r600_free_extended_power_table(rdev); } +void btc_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev, + struct seq_file *m) +{ + struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev); + struct radeon_ps *rps = &eg_pi->current_rps; + struct rv7xx_ps *ps = rv770_get_ps(rps); + struct rv7xx_pl *pl; + u32 current_index = + (RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_PROFILE_INDEX_MASK) >> + CURRENT_PROFILE_INDEX_SHIFT; + + if (current_index > 2) { + seq_printf(m, "invalid dpm profile %d\n", current_index); + } else { + if (current_index == 0) + pl = &ps->low; + else if (current_index == 1) + pl = &ps->medium; + else /* current_index == 2 */ + pl = &ps->high; + seq_printf(m, "uvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk); + if (rdev->family >= CHIP_CEDAR) { + seq_printf(m, "power level %d sclk: %u mclk: %u vddc: %u vddci: %u\n", + current_index, pl->sclk, pl->mclk, pl->vddc, pl->vddci); + } else { + seq_printf(m, "power level %d sclk: %u mclk: %u vddc: %u\n", + current_index, pl->sclk, pl->mclk, pl->vddc); + } + } +} + u32 btc_dpm_get_sclk(struct radeon_device *rdev, bool low) { struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev); diff --git a/drivers/gpu/drm/radeon/btcd.h b/drivers/gpu/drm/radeon/btcd.h index 29e32de..9c65be2 100644 --- a/drivers/gpu/drm/radeon/btcd.h +++ b/drivers/gpu/drm/radeon/btcd.h @@ -44,6 +44,10 @@ # define DYN_SPREAD_SPECTRUM_EN (1 << 23) # define AC_DC_SW (1 << 24) +#define TARGET_AND_CURRENT_PROFILE_INDEX 0x66c +# define CURRENT_PROFILE_INDEX_MASK (0xf << 4) +# define CURRENT_PROFILE_INDEX_SHIFT 4 + #define CG_BIF_REQ_AND_RSP 0x7f4 #define CG_CLIENT_REQ(x) ((x) << 0) #define CG_CLIENT_REQ_MASK (0xff << 0) diff --git a/drivers/gpu/drm/radeon/ni_dpm.c b/drivers/gpu/drm/radeon/ni_dpm.c index c351226..22c3391 100644 --- a/drivers/gpu/drm/radeon/ni_dpm.c +++ b/drivers/gpu/drm/radeon/ni_dpm.c @@ -4322,7 +4322,8 @@ void ni_dpm_print_power_state(struct radeon_device *rdev, void ni_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev, struct seq_file *m) { - struct radeon_ps *rps = rdev->pm.dpm.current_ps; + struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev); + struct radeon_ps *rps = &eg_pi->current_rps; struct ni_ps *ps = ni_get_ps(rps); struct rv7xx_pl *pl; u32 current_index = diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index f74db43..dda02bf 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c @@ -1555,7 +1555,7 @@ static struct radeon_asic btc_asic = { .get_sclk = &btc_dpm_get_sclk, .get_mclk = &btc_dpm_get_mclk, .print_power_state = &rv770_dpm_print_power_state, - .debugfs_print_current_performance_level = &rv770_dpm_debugfs_print_current_performance_level, + .debugfs_print_current_performance_level = &btc_dpm_debugfs_print_current_performance_level, .force_performance_level = &rv770_dpm_force_performance_level, .vblank_too_short = &btc_dpm_vblank_too_short, }, diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index b3bc433..ae637cf 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -551,6 +551,8 @@ void btc_dpm_fini(struct radeon_device *rdev); u32 btc_dpm_get_sclk(struct radeon_device *rdev, bool low); u32 btc_dpm_get_mclk(struct radeon_device *rdev, bool low); bool btc_dpm_vblank_too_short(struct radeon_device *rdev); +void btc_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev, + struct seq_file *m); int sumo_dpm_init(struct radeon_device *rdev); int sumo_dpm_enable(struct radeon_device *rdev); int sumo_dpm_late_enable(struct radeon_device *rdev); diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c index 0471501..eafb0e6 100644 --- a/drivers/gpu/drm/radeon/si_dpm.c +++ b/drivers/gpu/drm/radeon/si_dpm.c @@ -6472,7 +6472,8 @@ void si_dpm_fini(struct radeon_device *rdev) void si_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev, struct seq_file *m) { - struct radeon_ps *rps = rdev->pm.dpm.current_ps; + struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev); + struct radeon_ps *rps = &eg_pi->current_rps; struct ni_ps *ps = ni_get_ps(rps); struct rv7xx_pl *pl; u32 current_index = diff --git a/drivers/gpu/drm/radeon/sumo_dpm.c b/drivers/gpu/drm/radeon/sumo_dpm.c index f121efe..8b47b3cd 100644 --- a/drivers/gpu/drm/radeon/sumo_dpm.c +++ b/drivers/gpu/drm/radeon/sumo_dpm.c @@ -1807,7 +1807,7 @@ void sumo_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev struct seq_file *m) { struct sumo_power_info *pi = sumo_get_pi(rdev); - struct radeon_ps *rps = rdev->pm.dpm.current_ps; + struct radeon_ps *rps = &pi->current_rps; struct sumo_ps *ps = sumo_get_ps(rps); struct sumo_pl *pl; u32 current_index = diff --git a/drivers/gpu/drm/radeon/trinity_dpm.c b/drivers/gpu/drm/radeon/trinity_dpm.c index 2d44719..2da0e17 100644 --- a/drivers/gpu/drm/radeon/trinity_dpm.c +++ b/drivers/gpu/drm/radeon/trinity_dpm.c @@ -1926,7 +1926,8 @@ void trinity_dpm_print_power_state(struct radeon_device *rdev, void trinity_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev, struct seq_file *m) { - struct radeon_ps *rps = rdev->pm.dpm.current_ps; + struct trinity_power_info *pi = trinity_get_pi(rdev); + struct radeon_ps *rps = &pi->current_rps; struct trinity_ps *ps = trinity_get_ps(rps); struct trinity_pl *pl; u32 current_index = -- cgit v0.10.2 From 299302294e109aec5e7f54ea61a9816c555c2106 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 30 Jan 2014 13:11:47 -0500 Subject: drm/radeon/dpm: use stored max_vddc rather than looking it up When we parse the power tables use the stored mac_vddc value rather than lookig it up manually each time. Signed-off-by: Alex Deucher diff --git a/drivers/gpu/drm/radeon/ni_dpm.c b/drivers/gpu/drm/radeon/ni_dpm.c index 22c3391..1217fbc 100644 --- a/drivers/gpu/drm/radeon/ni_dpm.c +++ b/drivers/gpu/drm/radeon/ni_dpm.c @@ -3945,7 +3945,6 @@ static void ni_parse_pplib_clock_info(struct radeon_device *rdev, struct rv7xx_power_info *pi = rv770_get_pi(rdev); struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev); struct ni_ps *ps = ni_get_ps(rps); - u16 vddc; struct rv7xx_pl *pl = &ps->performance_levels[index]; ps->performance_level_count = index + 1; @@ -3961,8 +3960,8 @@ static void ni_parse_pplib_clock_info(struct radeon_device *rdev, /* patch up vddc if necessary */ if (pl->vddc == 0xff01) { - if (radeon_atom_get_max_vddc(rdev, 0, 0, &vddc) == 0) - pl->vddc = vddc; + if (pi->max_vddc) + pl->vddc = pi->max_vddc; } if (rps->class & ATOM_PPLIB_CLASSIFICATION_ACPI) { diff --git a/drivers/gpu/drm/radeon/rv770_dpm.c b/drivers/gpu/drm/radeon/rv770_dpm.c index 80c595a..5b2ea8a 100644 --- a/drivers/gpu/drm/radeon/rv770_dpm.c +++ b/drivers/gpu/drm/radeon/rv770_dpm.c @@ -2174,7 +2174,6 @@ static void rv7xx_parse_pplib_clock_info(struct radeon_device *rdev, struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev); struct rv7xx_ps *ps = rv770_get_ps(rps); u32 sclk, mclk; - u16 vddc; struct rv7xx_pl *pl; switch (index) { @@ -2214,8 +2213,8 @@ static void rv7xx_parse_pplib_clock_info(struct radeon_device *rdev, /* patch up vddc if necessary */ if (pl->vddc == 0xff01) { - if (radeon_atom_get_max_vddc(rdev, 0, 0, &vddc) == 0) - pl->vddc = vddc; + if (pi->max_vddc) + pl->vddc = pi->max_vddc; } if (rps->class & ATOM_PPLIB_CLASSIFICATION_ACPI) { -- cgit v0.10.2 From 4dbffb8f21999c2156ddac00186810f1dfd9eb1a Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 30 Jan 2014 14:06:05 -0500 Subject: drm/radeon: remove useless return Signed-off-by: Alex Deucher diff --git a/drivers/gpu/drm/radeon/uvd_v2_2.c b/drivers/gpu/drm/radeon/uvd_v2_2.c index 824550d..d177100 100644 --- a/drivers/gpu/drm/radeon/uvd_v2_2.c +++ b/drivers/gpu/drm/radeon/uvd_v2_2.c @@ -57,7 +57,6 @@ void uvd_v2_2_fence_emit(struct radeon_device *rdev, radeon_ring_write(ring, 0); radeon_ring_write(ring, PACKET0(UVD_GPCOM_VCPU_CMD, 0)); radeon_ring_write(ring, 2); - return; } /** -- cgit v0.10.2 From 7c7e867cf0f74c4c79649605b964510041f1a8bf Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 30 Jan 2014 21:17:30 -0500 Subject: drm/radeon/dpm: fix uninitialized read from stack in kv_dpm_late_enable If we take the false branch of the if quoted in the diff below, we end up doing a return ret, without ever having initialized it. Picked up by coverity. Signed-off-by: Dave Jones Signed-off-by: Alex Deucher diff --git a/drivers/gpu/drm/radeon/kv_dpm.c b/drivers/gpu/drm/radeon/kv_dpm.c index b6e01d5..351db36 100644 --- a/drivers/gpu/drm/radeon/kv_dpm.c +++ b/drivers/gpu/drm/radeon/kv_dpm.c @@ -1223,7 +1223,7 @@ int kv_dpm_enable(struct radeon_device *rdev) int kv_dpm_late_enable(struct radeon_device *rdev) { - int ret; + int ret = 0; if (rdev->irq.installed && r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) { -- cgit v0.10.2 From 2b4db05e7e2f1efc71e36a9dc1adf5ba164a2330 Mon Sep 17 00:00:00 2001 From: "andrea.merello" Date: Wed, 5 Feb 2014 22:38:05 +0100 Subject: rtl8180: Add error check for pci_map_single return value in RX path In original code the old RX DMA buffer is unmapped and processed and at the end of the isr a new buffer is mapped with pci_map_single and attached to the RX descriptor. If pci_map_single fails then the RX descriptor remains with no valid DMA buffer attached. In this condition the DMA will target where it shouldn't with obvious evil consequences. Simply avoiding re-arming the descriptor will prevent buggy DMA but it will result soon in RX stuck. This patch move the DMA mapping of the new buffer at the beginning of the ISR (and it adds error check for pci_map_single success/fail). If the DMA mapping fails then we do not unmap the old buffer and we re-arm the descriptor without processing it, with the old DMA buffer still attached. In this way we lose the currently RX-ed packet, but whenever next calls to pci_map_single will succeed again,then the RX process will go on without stuck. Signed-off-by: andrea merello Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/rtl818x/rtl8180/dev.c b/drivers/net/wireless/rtl818x/rtl8180/dev.c index 8ec17aa..fad616a 100644 --- a/drivers/net/wireless/rtl818x/rtl8180/dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180/dev.c @@ -107,6 +107,7 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev) struct rtl8180_priv *priv = dev->priv; unsigned int count = 32; u8 signal, agc, sq; + dma_addr_t mapping; while (count--) { struct rtl8180_rx_desc *entry = &priv->rx_ring[priv->rx_idx]; @@ -128,6 +129,17 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev) if (unlikely(!new_skb)) goto done; + mapping = pci_map_single(priv->pdev, + skb_tail_pointer(new_skb), + MAX_RX_SIZE, PCI_DMA_FROMDEVICE); + + if (pci_dma_mapping_error(priv->pdev, mapping)) { + kfree_skb(new_skb); + dev_err(&priv->pdev->dev, "RX DMA map error\n"); + + goto done; + } + pci_unmap_single(priv->pdev, *((dma_addr_t *)skb->cb), MAX_RX_SIZE, PCI_DMA_FROMDEVICE); @@ -158,9 +170,7 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev) skb = new_skb; priv->rx_buf[priv->rx_idx] = skb; - *((dma_addr_t *) skb->cb) = - pci_map_single(priv->pdev, skb_tail_pointer(skb), - MAX_RX_SIZE, PCI_DMA_FROMDEVICE); + *((dma_addr_t *) skb->cb) = mapping; } done: -- cgit v0.10.2 From 348f7d4adee97f222e3ad9ff97956ca3793d11c6 Mon Sep 17 00:00:00 2001 From: "andrea.merello" Date: Wed, 5 Feb 2014 22:38:06 +0100 Subject: rtl8180: Add error check for pci_map_single return value in TX path Orignal code will not detect a DMA mapping failure, causing the HW to attempt a DMA from an invalid address. This patch add the error check and eventually simply drops the TX packet if we can't map it for DMA. Signed-off-by: andrea merello Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/rtl818x/rtl8180/dev.c b/drivers/net/wireless/rtl818x/rtl8180/dev.c index fad616a..3867d14 100644 --- a/drivers/net/wireless/rtl818x/rtl8180/dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180/dev.c @@ -276,6 +276,13 @@ static void rtl8180_tx(struct ieee80211_hw *dev, mapping = pci_map_single(priv->pdev, skb->data, skb->len, PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(priv->pdev, mapping)) { + kfree_skb(skb); + dev_err(&priv->pdev->dev, "TX DMA mapping error\n"); + return; + + } + tx_flags = RTL818X_TX_DESC_FLAG_OWN | RTL818X_TX_DESC_FLAG_FS | RTL818X_TX_DESC_FLAG_LS | (ieee80211_get_tx_rate(dev, info)->hw_value << 24) | -- cgit v0.10.2 From d02f8575f1a38b3180a76a8ae0857dfde67f5ead Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 6 Feb 2014 14:22:21 -0500 Subject: drm/radeon: add missing include in btc_dpm.c Fixes a compile error with debugfs disabled. Signed-off-by: Alex Deucher diff --git a/drivers/gpu/drm/radeon/btc_dpm.c b/drivers/gpu/drm/radeon/btc_dpm.c index 05ad469..ea103cc 100644 --- a/drivers/gpu/drm/radeon/btc_dpm.c +++ b/drivers/gpu/drm/radeon/btc_dpm.c @@ -29,6 +29,7 @@ #include "cypress_dpm.h" #include "btc_dpm.h" #include "atom.h" +#include #define MC_CG_ARB_FREQ_F0 0x0a #define MC_CG_ARB_FREQ_F1 0x0b -- cgit v0.10.2 From 6ca605f7c70895a35737435f17ae9cc5e36f1466 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 16 Jan 2014 11:31:26 +0530 Subject: drm/exynos: Fix freeing issues in exynos_drm_drv.c Fixes the following errors: drivers/gpu/drm/exynos/exynos_drm_drv.c:182 exynos_drm_open() error: double free of 'file_priv' drivers/gpu/drm/exynos/exynos_drm_drv.c:188 exynos_drm_open() error: dereferencing freed memory 'file_priv' Signed-off-by: Sachin Kamat Signed-off-by: Inki Dae diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index 9d096a0..215131a 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -171,22 +171,24 @@ static int exynos_drm_open(struct drm_device *dev, struct drm_file *file) file->driver_priv = file_priv; ret = exynos_drm_subdrv_open(dev, file); - if (ret) { - kfree(file_priv); - file->driver_priv = NULL; - } + if (ret) + goto out; anon_filp = anon_inode_getfile("exynos_gem", &exynos_drm_gem_fops, NULL, 0); if (IS_ERR(anon_filp)) { - kfree(file_priv); - return PTR_ERR(anon_filp); + ret = PTR_ERR(anon_filp); + goto out; } anon_filp->f_mode = FMODE_READ | FMODE_WRITE; file_priv->anon_filp = anon_filp; return ret; +out: + kfree(file_priv); + file->driver_priv = NULL; + return ret; } static void exynos_drm_preclose(struct drm_device *dev, -- cgit v0.10.2 From 86ac5b84efa87c3ed741dd73597f8c29bba53da2 Mon Sep 17 00:00:00 2001 From: Tushar Behera Date: Thu, 16 Jan 2014 11:57:57 +0530 Subject: drm/exynos: Fix multiplatform breakage for ipp/gsc There is no need to include "plat/map-base.h" in ipp driver. Remove this and enable this driver for multi-platform. However gsc driver is not multiplatform compliant yet, so make the compilation conditional upon !ARCH_MULTIPLATFORM. Signed-off-by: Tushar Behera Signed-off-by: Inki Dae diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig index f227f54..6e1a1a2 100644 --- a/drivers/gpu/drm/exynos/Kconfig +++ b/drivers/gpu/drm/exynos/Kconfig @@ -51,7 +51,7 @@ config DRM_EXYNOS_G2D config DRM_EXYNOS_IPP bool "Exynos DRM IPP" - depends on DRM_EXYNOS && !ARCH_MULTIPLATFORM + depends on DRM_EXYNOS help Choose this option if you want to use IPP feature for DRM. @@ -69,6 +69,6 @@ config DRM_EXYNOS_ROTATOR config DRM_EXYNOS_GSC bool "Exynos DRM GSC" - depends on DRM_EXYNOS_IPP && ARCH_EXYNOS5 + depends on DRM_EXYNOS_IPP && ARCH_EXYNOS5 && !ARCH_MULTIPLATFORM help Choose this option if you want to use Exynos GSC for DRM. diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.c b/drivers/gpu/drm/exynos/exynos_drm_ipp.c index d519a4e..eefb429 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_ipp.c +++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include -- cgit v0.10.2 From 5cdbc8d993074ffda3d3be68935b8afe3ff96b9e Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 16 Jan 2014 10:00:22 +0530 Subject: drm/exynos: Remove unnecessary semicolon Semicolon after a switch statement is not needed. Signed-off-by: Sachin Kamat Signed-off-by: Inki Dae diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c index 380aec2..6c1885e 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c @@ -607,7 +607,7 @@ static enum g2d_reg_type g2d_get_reg_type(int reg_offset) reg_type = REG_TYPE_NONE; DRM_ERROR("Unknown register offset![%d]\n", reg_offset); break; - }; + } return reg_type; } -- cgit v0.10.2 From 4fe25b822bca31aa9bf97c1a56747443f0d7d239 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 16 Jan 2014 10:00:23 +0530 Subject: drm/exynos: Fix trivial typo Changed quf -> qbuf. Signed-off-by: Sachin Kamat Signed-off-by: Inki Dae diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.c b/drivers/gpu/drm/exynos/exynos_drm_ipp.c index eefb429..09312b8 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_ipp.c +++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.c @@ -825,7 +825,7 @@ static void ipp_put_event(struct drm_exynos_ipp_cmd_node *c_node, DRM_DEBUG_KMS("count[%d]e[0x%x]\n", count++, (int)e); /* - * quf == NULL condition means all event deletion. + * qbuf == NULL condition means all event deletion. * stop operations want to delete all event list. * another case delete only same buf id. */ -- cgit v0.10.2 From d34d59bda242cf97b90161ea5fe339f0daf0cc33 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 4 Feb 2014 08:40:18 +0530 Subject: drm/exynos: Convert to use the standard hdmi.h header Remove local definitions and use the ones provided by hdmi.h. Signed-off-by: Sachin Kamat Signed-off-by: Inki Dae diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index a0e10ae..c021ddc 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -34,6 +34,7 @@ #include #include #include +#include #include @@ -59,19 +60,6 @@ #define HDMI_AUI_VERSION 0x01 #define HDMI_AUI_LENGTH 0x0A -/* HDMI infoframe to configure HDMI out packet header, AUI and AVI */ -enum HDMI_PACKET_TYPE { - /* refer to Table 5-8 Packet Type in HDMI specification v1.4a */ - /* InfoFrame packet type */ - HDMI_PACKET_TYPE_INFOFRAME = 0x80, - /* Vendor-Specific InfoFrame */ - HDMI_PACKET_TYPE_VSI = HDMI_PACKET_TYPE_INFOFRAME + 1, - /* Auxiliary Video information InfoFrame */ - HDMI_PACKET_TYPE_AVI = HDMI_PACKET_TYPE_INFOFRAME + 2, - /* Audio information InfoFrame */ - HDMI_PACKET_TYPE_AUI = HDMI_PACKET_TYPE_INFOFRAME + 4 -}; - enum hdmi_type { HDMI_TYPE13, HDMI_TYPE14, @@ -379,12 +367,6 @@ static const struct hdmiphy_config hdmiphy_v14_configs[] = { }, }; -struct hdmi_infoframe { - enum HDMI_PACKET_TYPE type; - u8 ver; - u8 len; -}; - static inline u32 hdmi_reg_read(struct hdmi_context *hdata, u32 reg_id) { return readl(hdata->regs + reg_id); @@ -682,7 +664,7 @@ static u8 hdmi_chksum(struct hdmi_context *hdata, } static void hdmi_reg_infoframe(struct hdmi_context *hdata, - struct hdmi_infoframe *infoframe) + union hdmi_infoframe *infoframe) { u32 hdr_sum; u8 chksum; @@ -700,13 +682,15 @@ static void hdmi_reg_infoframe(struct hdmi_context *hdata, return; } - switch (infoframe->type) { - case HDMI_PACKET_TYPE_AVI: + switch (infoframe->any.type) { + case HDMI_INFOFRAME_TYPE_AVI: hdmi_reg_writeb(hdata, HDMI_AVI_CON, HDMI_AVI_CON_EVERY_VSYNC); - hdmi_reg_writeb(hdata, HDMI_AVI_HEADER0, infoframe->type); - hdmi_reg_writeb(hdata, HDMI_AVI_HEADER1, infoframe->ver); - hdmi_reg_writeb(hdata, HDMI_AVI_HEADER2, infoframe->len); - hdr_sum = infoframe->type + infoframe->ver + infoframe->len; + hdmi_reg_writeb(hdata, HDMI_AVI_HEADER0, infoframe->any.type); + hdmi_reg_writeb(hdata, HDMI_AVI_HEADER1, + infoframe->any.version); + hdmi_reg_writeb(hdata, HDMI_AVI_HEADER2, infoframe->any.length); + hdr_sum = infoframe->any.type + infoframe->any.version + + infoframe->any.length; /* Output format zero hardcoded ,RGB YBCR selection */ hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(1), 0 << 5 | @@ -722,18 +706,20 @@ static void hdmi_reg_infoframe(struct hdmi_context *hdata, hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(4), vic); chksum = hdmi_chksum(hdata, HDMI_AVI_BYTE(1), - infoframe->len, hdr_sum); + infoframe->any.length, hdr_sum); DRM_DEBUG_KMS("AVI checksum = 0x%x\n", chksum); hdmi_reg_writeb(hdata, HDMI_AVI_CHECK_SUM, chksum); break; - case HDMI_PACKET_TYPE_AUI: + case HDMI_INFOFRAME_TYPE_AUDIO: hdmi_reg_writeb(hdata, HDMI_AUI_CON, 0x02); - hdmi_reg_writeb(hdata, HDMI_AUI_HEADER0, infoframe->type); - hdmi_reg_writeb(hdata, HDMI_AUI_HEADER1, infoframe->ver); - hdmi_reg_writeb(hdata, HDMI_AUI_HEADER2, infoframe->len); - hdr_sum = infoframe->type + infoframe->ver + infoframe->len; + hdmi_reg_writeb(hdata, HDMI_AUI_HEADER0, infoframe->any.type); + hdmi_reg_writeb(hdata, HDMI_AUI_HEADER1, + infoframe->any.version); + hdmi_reg_writeb(hdata, HDMI_AUI_HEADER2, infoframe->any.length); + hdr_sum = infoframe->any.type + infoframe->any.version + + infoframe->any.length; chksum = hdmi_chksum(hdata, HDMI_AUI_BYTE(1), - infoframe->len, hdr_sum); + infoframe->any.length, hdr_sum); DRM_DEBUG_KMS("AUI checksum = 0x%x\n", chksum); hdmi_reg_writeb(hdata, HDMI_AUI_CHECK_SUM, chksum); break; @@ -985,7 +971,7 @@ static void hdmi_conf_reset(struct hdmi_context *hdata) static void hdmi_conf_init(struct hdmi_context *hdata) { - struct hdmi_infoframe infoframe; + union hdmi_infoframe infoframe; /* disable HPD interrupts from HDMI IP block, use GPIO instead */ hdmi_reg_writemask(hdata, HDMI_INTC_CON, 0, HDMI_INTC_EN_GLOBAL | @@ -1021,14 +1007,14 @@ static void hdmi_conf_init(struct hdmi_context *hdata) hdmi_reg_writeb(hdata, HDMI_V13_AUI_CON, 0x02); hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 0x04); } else { - infoframe.type = HDMI_PACKET_TYPE_AVI; - infoframe.ver = HDMI_AVI_VERSION; - infoframe.len = HDMI_AVI_LENGTH; + infoframe.any.type = HDMI_INFOFRAME_TYPE_AVI; + infoframe.any.version = HDMI_AVI_VERSION; + infoframe.any.length = HDMI_AVI_LENGTH; hdmi_reg_infoframe(hdata, &infoframe); - infoframe.type = HDMI_PACKET_TYPE_AUI; - infoframe.ver = HDMI_AUI_VERSION; - infoframe.len = HDMI_AUI_LENGTH; + infoframe.any.type = HDMI_INFOFRAME_TYPE_AUDIO; + infoframe.any.version = HDMI_AUI_VERSION; + infoframe.any.length = HDMI_AUI_LENGTH; hdmi_reg_infoframe(hdata, &infoframe); /* enable AVI packet every vsync, fixes purple line problem */ -- cgit v0.10.2 From 4dae1686782d52084893421b89ff1aa61e223aaf Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Sun, 2 Feb 2014 14:49:11 +0100 Subject: net: ethernet: sunxi: Add new compatibles The Allwinner A10 compatibles were following a slightly different compatible patterns than the rest of the SoCs for historical reasons. Add compatibles matching the other pattern to the ethernet driver for consistency, and keep the older one for backward compatibility. Signed-off-by: Maxime Ripard Signed-off-by: David S. Miller diff --git a/Documentation/devicetree/bindings/net/allwinner,sun4i-emac.txt b/Documentation/devicetree/bindings/net/allwinner,sun4i-emac.txt index b90bfcd..863d5b81 100644 --- a/Documentation/devicetree/bindings/net/allwinner,sun4i-emac.txt +++ b/Documentation/devicetree/bindings/net/allwinner,sun4i-emac.txt @@ -1,7 +1,8 @@ * Allwinner EMAC ethernet controller Required properties: -- compatible: should be "allwinner,sun4i-emac". +- compatible: should be "allwinner,sun4i-a10-emac" (Deprecated: + "allwinner,sun4i-emac") - reg: address and length of the register set for the device. - interrupts: interrupt for the device - phy: A phandle to a phy node defining the PHY address (as the reg @@ -14,7 +15,7 @@ Optional properties: Example: emac: ethernet@01c0b000 { - compatible = "allwinner,sun4i-emac"; + compatible = "allwinner,sun4i-a10-emac"; reg = <0x01c0b000 0x1000>; interrupts = <55>; clocks = <&ahb_gates 17>; diff --git a/drivers/net/ethernet/allwinner/sun4i-emac.c b/drivers/net/ethernet/allwinner/sun4i-emac.c index 0cc2143..511f6ee 100644 --- a/drivers/net/ethernet/allwinner/sun4i-emac.c +++ b/drivers/net/ethernet/allwinner/sun4i-emac.c @@ -929,6 +929,9 @@ static int emac_resume(struct platform_device *dev) } static const struct of_device_id emac_of_match[] = { + {.compatible = "allwinner,sun4i-a10-emac",}, + + /* Deprecated */ {.compatible = "allwinner,sun4i-emac",}, {}, }; -- cgit v0.10.2 From efe205704fa8435b7bca495138dd2dbd973e0c28 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Sun, 2 Feb 2014 14:49:12 +0100 Subject: net: phy: sunxi: Add new compatibles The Allwinner A10 compatibles were following a slightly different compatible patterns than the rest of the SoCs for historical reasons. Add compatibles matching the other pattern to the mdio driver for consistency, and keep the older one for backward compatibility. Signed-off-by: Maxime Ripard Signed-off-by: David S. Miller diff --git a/Documentation/devicetree/bindings/net/allwinner,sun4i-mdio.txt b/Documentation/devicetree/bindings/net/allwinner,sun4i-mdio.txt index 00b9f9a..4ec5641 100644 --- a/Documentation/devicetree/bindings/net/allwinner,sun4i-mdio.txt +++ b/Documentation/devicetree/bindings/net/allwinner,sun4i-mdio.txt @@ -1,7 +1,8 @@ * Allwinner A10 MDIO Ethernet Controller interface Required properties: -- compatible: should be "allwinner,sun4i-mdio". +- compatible: should be "allwinner,sun4i-a10-mdio" + (Deprecated: "allwinner,sun4i-mdio"). - reg: address and length of the register set for the device. Optional properties: @@ -9,7 +10,7 @@ Optional properties: Example at the SoC level: mdio@01c0b080 { - compatible = "allwinner,sun4i-mdio"; + compatible = "allwinner,sun4i-a10-mdio"; reg = <0x01c0b080 0x14>; #address-cells = <1>; #size-cells = <0>; diff --git a/drivers/net/phy/mdio-sun4i.c b/drivers/net/phy/mdio-sun4i.c index bb88bc7..9367acc 100644 --- a/drivers/net/phy/mdio-sun4i.c +++ b/drivers/net/phy/mdio-sun4i.c @@ -170,6 +170,9 @@ static int sun4i_mdio_remove(struct platform_device *pdev) } static const struct of_device_id sun4i_mdio_dt_ids[] = { + { .compatible = "allwinner,sun4i-a10-mdio" }, + + /* Deprecated */ { .compatible = "allwinner,sun4i-mdio" }, { } }; -- cgit v0.10.2 From 1c70e099ac80ee779ffac66a6169ad936425fe41 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Sun, 2 Feb 2014 14:49:13 +0100 Subject: ARM: sunxi: dt: Convert to the new net compatibles Switch the device tree to the new compatibles introduced in the ethernet and mdio drivers to have a common pattern accross all Allwinner SoCs. Signed-off-by: Maxime Ripard Signed-off-by: David S. Miller diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi index 040bb0e..10666ca 100644 --- a/arch/arm/boot/dts/sun4i-a10.dtsi +++ b/arch/arm/boot/dts/sun4i-a10.dtsi @@ -315,7 +315,7 @@ ranges; emac: ethernet@01c0b000 { - compatible = "allwinner,sun4i-emac"; + compatible = "allwinner,sun4i-a10-emac"; reg = <0x01c0b000 0x1000>; interrupts = <55>; clocks = <&ahb_gates 17>; @@ -323,7 +323,7 @@ }; mdio@01c0b080 { - compatible = "allwinner,sun4i-mdio"; + compatible = "allwinner,sun4i-a10-mdio"; reg = <0x01c0b080 0x14>; status = "disabled"; #address-cells = <1>; diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi index ea16054..6496159 100644 --- a/arch/arm/boot/dts/sun5i-a10s.dtsi +++ b/arch/arm/boot/dts/sun5i-a10s.dtsi @@ -278,7 +278,7 @@ ranges; emac: ethernet@01c0b000 { - compatible = "allwinner,sun4i-emac"; + compatible = "allwinner,sun4i-a10-emac"; reg = <0x01c0b000 0x1000>; interrupts = <55>; clocks = <&ahb_gates 17>; @@ -286,7 +286,7 @@ }; mdio@01c0b080 { - compatible = "allwinner,sun4i-mdio"; + compatible = "allwinner,sun4i-a10-mdio"; reg = <0x01c0b080 0x14>; status = "disabled"; #address-cells = <1>; diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi index 119f066..9ff0948 100644 --- a/arch/arm/boot/dts/sun7i-a20.dtsi +++ b/arch/arm/boot/dts/sun7i-a20.dtsi @@ -340,7 +340,7 @@ ranges; emac: ethernet@01c0b000 { - compatible = "allwinner,sun4i-emac"; + compatible = "allwinner,sun4i-a10-emac"; reg = <0x01c0b000 0x1000>; interrupts = <0 55 4>; clocks = <&ahb_gates 17>; @@ -348,7 +348,7 @@ }; mdio@01c0b080 { - compatible = "allwinner,sun4i-mdio"; + compatible = "allwinner,sun4i-a10-mdio"; reg = <0x01c0b080 0x14>; status = "disabled"; #address-cells = <1>; -- cgit v0.10.2 From 597b506816337842ae76e739982b1b6fc19f35df Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Tue, 4 Feb 2014 19:43:32 +0400 Subject: net: irda: ep7211-sir: Remove driver This patch removes old and unsupported CLPS711X IrDA driver. Support for IrDA for CLPS711X serial port now provided by commit 4a33f1f59abd (serial: clps711x: Add support for N_IRDA line discipline), so IrDA-mode can be turned ON with "irattach" tool through "irtty" driver. Signed-off-by: Alexander Shiyan Signed-off-by: David S. Miller diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig index 2dc82f1..3da44d5 100644 --- a/drivers/net/irda/Kconfig +++ b/drivers/net/irda/Kconfig @@ -210,13 +210,6 @@ config KINGSUN_DONGLE To compile it as a module, choose M here: the module will be called kingsun-sir. -config EP7211_DONGLE - tristate "Cirrus Logic clps711x I/R support" - depends on IRTTY_SIR && ARCH_CLPS711X && IRDA - help - Say Y here if you want to build support for the Cirrus logic - EP7211 chipset's infrared module. - config KSDAZZLE_DONGLE tristate "KingSun Dazzle IrDA-USB dongle" depends on IRDA && USB diff --git a/drivers/net/irda/Makefile b/drivers/net/irda/Makefile index dfc6453..be8ab5b 100644 --- a/drivers/net/irda/Makefile +++ b/drivers/net/irda/Makefile @@ -35,7 +35,6 @@ obj-$(CONFIG_MCP2120_DONGLE) += mcp2120-sir.o obj-$(CONFIG_ACT200L_DONGLE) += act200l-sir.o obj-$(CONFIG_MA600_DONGLE) += ma600-sir.o obj-$(CONFIG_TOIM3232_DONGLE) += toim3232-sir.o -obj-$(CONFIG_EP7211_DONGLE) += ep7211-sir.o obj-$(CONFIG_KINGSUN_DONGLE) += kingsun-sir.o obj-$(CONFIG_KSDAZZLE_DONGLE) += ksdazzle-sir.o obj-$(CONFIG_KS959_DONGLE) += ks959-sir.o diff --git a/drivers/net/irda/ep7211-sir.c b/drivers/net/irda/ep7211-sir.c deleted file mode 100644 index 5fe1f4d..0000000 --- a/drivers/net/irda/ep7211-sir.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * IR port driver for the Cirrus Logic CLPS711X processors - * - * Copyright 2001, Blue Mug Inc. All rights reserved. - * Copyright 2007, Samuel Ortiz - */ - -#include -#include - -#include - -#include "sir-dev.h" - -static int clps711x_dongle_open(struct sir_dev *dev) -{ - unsigned int syscon; - - /* Turn on the SIR encoder. */ - syscon = clps_readl(SYSCON1); - syscon |= SYSCON1_SIREN; - clps_writel(syscon, SYSCON1); - - return 0; -} - -static int clps711x_dongle_close(struct sir_dev *dev) -{ - unsigned int syscon; - - /* Turn off the SIR encoder. */ - syscon = clps_readl(SYSCON1); - syscon &= ~SYSCON1_SIREN; - clps_writel(syscon, SYSCON1); - - return 0; -} - -static struct dongle_driver clps711x_dongle = { - .owner = THIS_MODULE, - .driver_name = "EP7211 IR driver", - .type = IRDA_EP7211_DONGLE, - .open = clps711x_dongle_open, - .close = clps711x_dongle_close, -}; - -static int clps711x_sir_probe(struct platform_device *pdev) -{ - return irda_register_dongle(&clps711x_dongle); -} - -static int clps711x_sir_remove(struct platform_device *pdev) -{ - return irda_unregister_dongle(&clps711x_dongle); -} - -static struct platform_driver clps711x_sir_driver = { - .driver = { - .name = "sir-clps711x", - .owner = THIS_MODULE, - }, - .probe = clps711x_sir_probe, - .remove = clps711x_sir_remove, -}; -module_platform_driver(clps711x_sir_driver); - -MODULE_AUTHOR("Samuel Ortiz "); -MODULE_DESCRIPTION("EP7211 IR dongle driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("irda-dongle-13"); /* IRDA_EP7211_DONGLE */ -- cgit v0.10.2 From 1c8bb760b632b4328f06066a6813f3758e54d8cb Mon Sep 17 00:00:00 2001 From: James M Leddy Date: Tue, 4 Feb 2014 15:10:59 -0500 Subject: bnx2[x]: Make module parameters readable Occasionally users want to know what parameters their Broadcom drivers are running with. For example, a user may want to know if MSI is disabled. This patch has been compile tested. Signed-off-by: James M Leddy Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c index 9d2deda..cda25ac 100644 --- a/drivers/net/ethernet/broadcom/bnx2.c +++ b/drivers/net/ethernet/broadcom/bnx2.c @@ -85,7 +85,7 @@ MODULE_FIRMWARE(FW_RV2P_FILE_09_Ax); static int disable_msi = 0; -module_param(disable_msi, int, 0); +module_param(disable_msi, int, S_IRUGO); MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)"); typedef enum { diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index c9c445e..7d43822 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -95,29 +95,29 @@ MODULE_FIRMWARE(FW_FILE_NAME_E1H); MODULE_FIRMWARE(FW_FILE_NAME_E2); int bnx2x_num_queues; -module_param_named(num_queues, bnx2x_num_queues, int, 0); +module_param_named(num_queues, bnx2x_num_queues, int, S_IRUGO); MODULE_PARM_DESC(num_queues, " Set number of queues (default is as a number of CPUs)"); static int disable_tpa; -module_param(disable_tpa, int, 0); +module_param(disable_tpa, int, S_IRUGO); MODULE_PARM_DESC(disable_tpa, " Disable the TPA (LRO) feature"); static int int_mode; -module_param(int_mode, int, 0); +module_param(int_mode, int, S_IRUGO); MODULE_PARM_DESC(int_mode, " Force interrupt mode other than MSI-X " "(1 INT#x; 2 MSI)"); static int dropless_fc; -module_param(dropless_fc, int, 0); +module_param(dropless_fc, int, S_IRUGO); MODULE_PARM_DESC(dropless_fc, " Pause on exhausted host ring"); static int mrrs = -1; -module_param(mrrs, int, 0); +module_param(mrrs, int, S_IRUGO); MODULE_PARM_DESC(mrrs, " Force Max Read Req Size (0..3) (for debug)"); static int debug; -module_param(debug, int, 0); +module_param(debug, int, S_IRUGO); MODULE_PARM_DESC(debug, " Default debug msglevel"); struct workqueue_struct *bnx2x_wq; -- cgit v0.10.2 From 63b5f152eb4a5bb79b9caf7ec37b4201d12f6e66 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 5 Feb 2014 08:38:25 +0100 Subject: ipv4: Fix runtime WARNING in rtmsg_ifa() On m68k/ARAnyM: WARNING: CPU: 0 PID: 407 at net/ipv4/devinet.c:1599 0x316a99() Modules linked in: CPU: 0 PID: 407 Comm: ifconfig Not tainted 3.13.0-atari-09263-g0c71d68014d1 #1378 Stack from 10c4fdf0: 10c4fdf0 002ffabb 000243e8 00000000 008ced6c 00024416 00316a99 0000063f 00316a99 00000009 00000000 002501b4 00316a99 0000063f c0a86117 00000080 c0a86117 00ad0c90 00250a5a 00000014 00ad0c90 00000000 00000000 00000001 00b02dd0 00356594 00000000 00356594 c0a86117 eff6c9e4 008ced6c 00000002 008ced60 0024f9b4 00250b52 00ad0c90 00000000 00000000 00252390 00ad0c90 eff6c9e4 0000004f 00000000 00000000 eff6c9e4 8000e25c eff6c9e4 80001020 Call Trace: [<000243e8>] warn_slowpath_common+0x52/0x6c [<00024416>] warn_slowpath_null+0x14/0x1a [<002501b4>] rtmsg_ifa+0xdc/0xf0 [<00250a5a>] __inet_insert_ifa+0xd6/0x1c2 [<0024f9b4>] inet_abc_len+0x0/0x42 [<00250b52>] inet_insert_ifa+0xc/0x12 [<00252390>] devinet_ioctl+0x2ae/0x5d6 Adding some debugging code reveals that net_fill_ifaddr() fails in put_cacheinfo(skb, ifa->ifa_cstamp, ifa->ifa_tstamp, preferred, valid)) nla_put complains: lib/nlattr.c:454: skb_tailroom(skb) = 12, nla_total_size(attrlen) = 20 Apparently commit 5c766d642bcaffd0c2a5b354db2068515b3846cf ("ipv4: introduce address lifetime") forgot to take into account the addition of struct ifa_cacheinfo in inet_nlmsg_size(). Hence add it, like is already done for ipv6. Suggested-by: Cong Wang Signed-off-by: Geert Uytterhoeven Signed-off-by: Cong Wang Signed-off-by: David S. Miller diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index ac2dff3..bdbf68b 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -1443,7 +1443,8 @@ static size_t inet_nlmsg_size(void) + nla_total_size(4) /* IFA_LOCAL */ + nla_total_size(4) /* IFA_BROADCAST */ + nla_total_size(IFNAMSIZ) /* IFA_LABEL */ - + nla_total_size(4); /* IFA_FLAGS */ + + nla_total_size(4) /* IFA_FLAGS */ + + nla_total_size(sizeof(struct ifa_cacheinfo)); /* IFA_CACHEINFO */ } static inline u32 cstamp_delta(unsigned long cstamp) -- cgit v0.10.2 From c6e27f2f3cf2631aae6f1f6fae1a7ab083fdb024 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 5 Feb 2014 16:29:21 +0300 Subject: tg3: cleanup an error path in tg3_phy_reset_5703_4_5() In the original code, if tg3_readphy() fails then it does an unnecessary check to verify "err" is still zero and then returns -EBUSY. My static checker complains about the unnecessary "if (!err)" check and anyway it is better to propagate the -EBUSY error code from tg3_readphy() instead of hard coding it here. And really the original code is confusing to look at. Signed-off-by: Dan Carpenter Acked-by: Nithin Nayak Sujir Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index e2ca03e..c466e12 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -2609,13 +2609,14 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp) tg3_writephy(tp, MII_CTRL1000, phy9_orig); - if (!tg3_readphy(tp, MII_TG3_EXT_CTRL, ®32)) { - reg32 &= ~0x3000; - tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32); - } else if (!err) - err = -EBUSY; + err = tg3_readphy(tp, MII_TG3_EXT_CTRL, ®32); + if (err) + return err; - return err; + reg32 &= ~0x3000; + tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32); + + return 0; } static void tg3_carrier_off(struct tg3 *tp) -- cgit v0.10.2 From c6993dfd7db9b0c6b7ca7503a56fda9236a4710f Mon Sep 17 00:00:00 2001 From: Nithin Sujir Date: Thu, 6 Feb 2014 14:13:05 -0800 Subject: tg3: Fix deadlock in tg3_change_mtu() Quoting David Vrabel - "5780 cards cannot have jumbo frames and TSO enabled together. When jumbo frames are enabled by setting the MTU, the TSO feature must be cleared. This is done indirectly by calling netdev_update_features() which will call tg3_fix_features() to actually clear the flags. netdev_update_features() will also trigger a new netlink message for the feature change event which will result in a call to tg3_get_stats64() which deadlocks on the tg3 lock." tg3_set_mtu() does not need to be under the tg3 lock since converting the flags to use set_bit(). Move it out to after tg3_netif_stop(). Reported-by: David Vrabel Tested-by: David Vrabel Signed-off-by: Michael Chan Signed-off-by: Nithin Nayak Sujir Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index c466e12..3167ed6 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -14114,12 +14114,12 @@ static int tg3_change_mtu(struct net_device *dev, int new_mtu) tg3_netif_stop(tp); + tg3_set_mtu(dev, tp, new_mtu); + tg3_full_lock(tp, 1); tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); - tg3_set_mtu(dev, tp, new_mtu); - /* Reset PHY, otherwise the read DMA engine will be in a mode that * breaks all requests to 256 bytes. */ -- cgit v0.10.2 From 656493d6e730690b76d6e74253d0208841cf4dd9 Mon Sep 17 00:00:00 2001 From: Yuval Mintz Date: Wed, 5 Feb 2014 16:07:12 +0200 Subject: bnx2x: Allow VF rss on higher PFs bnx2x driver uses incorrect PF identifier to configure (in HW) the VF interrupt scheme; As a result, in multi-function mode the configuration for PFs with a high index (4+) will overflow and the PF will erroneously configure a single ISR scheme for its VFs. As a result, if such a VF uses multiple queues, interrupt generation will stop after VF receives an Rx packet or sends a Tx packet on a queue other than queue[0]. Signed-off-by: Yuval Mintz Signed-off-by: Ariel Elior Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c index aec5ef2..e42f48d 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c @@ -1446,12 +1446,12 @@ static void bnx2x_vf_igu_reset(struct bnx2x *bp, struct bnx2x_virtf *vf) if (vf->cfg_flags & VF_CFG_INT_SIMD) val |= IGU_VF_CONF_SINGLE_ISR_EN; val &= ~IGU_VF_CONF_PARENT_MASK; - val |= BP_FUNC(bp) << IGU_VF_CONF_PARENT_SHIFT; /* parent PF */ + val |= (BP_ABS_FUNC(bp) >> 1) << IGU_VF_CONF_PARENT_SHIFT; REG_WR(bp, IGU_REG_VF_CONFIGURATION, val); DP(BNX2X_MSG_IOV, - "value in IGU_REG_VF_CONFIGURATION of vf %d after write %x\n", - vf->abs_vfid, REG_RD(bp, IGU_REG_VF_CONFIGURATION)); + "value in IGU_REG_VF_CONFIGURATION of vf %d after write is 0x%08x\n", + vf->abs_vfid, val); bnx2x_pretend_func(bp, BP_ABS_FUNC(bp)); -- cgit v0.10.2 From 3d55f44f563de2ab83209e8ead48d922b0d56a65 Mon Sep 17 00:00:00 2001 From: hayeswang Date: Thu, 6 Feb 2014 11:55:48 +0800 Subject: r8152: fix the submission of the interrupt transfer The submission of the interrupt transfer should be done after setting the bit of WORK_ENABLE, otherwise the callback function would have the opportunity to be returned directly. Clear the bit of WORK_ENABLE before killing the interrupt transfer. Signed-off-by: Hayes Wang Signed-off-by: David S. Miller diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index e8fac73..d89dbe3 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -2273,22 +2273,21 @@ static int rtl8152_open(struct net_device *netdev) struct r8152 *tp = netdev_priv(netdev); int res = 0; + rtl8152_set_speed(tp, AUTONEG_ENABLE, + tp->mii.supports_gmii ? SPEED_1000 : SPEED_100, + DUPLEX_FULL); + tp->speed = 0; + netif_carrier_off(netdev); + netif_start_queue(netdev); + set_bit(WORK_ENABLE, &tp->flags); res = usb_submit_urb(tp->intr_urb, GFP_KERNEL); if (res) { if (res == -ENODEV) netif_device_detach(tp->netdev); netif_warn(tp, ifup, netdev, "intr_urb submit failed: %d\n", res); - return res; } - rtl8152_set_speed(tp, AUTONEG_ENABLE, - tp->mii.supports_gmii ? SPEED_1000 : SPEED_100, - DUPLEX_FULL); - tp->speed = 0; - netif_carrier_off(netdev); - netif_start_queue(netdev); - set_bit(WORK_ENABLE, &tp->flags); return res; } @@ -2298,8 +2297,8 @@ static int rtl8152_close(struct net_device *netdev) struct r8152 *tp = netdev_priv(netdev); int res = 0; - usb_kill_urb(tp->intr_urb); clear_bit(WORK_ENABLE, &tp->flags); + usb_kill_urb(tp->intr_urb); cancel_delayed_work_sync(&tp->schedule); netif_stop_queue(netdev); tasklet_disable(&tp->tl); -- cgit v0.10.2 From 661dbf34129cecd20879cb7b1cbe936911da0f02 Mon Sep 17 00:00:00 2001 From: Matija Glavinic Pecotic Date: Thu, 6 Feb 2014 08:30:10 +0100 Subject: net: sctp: fix initialization of local source address on accepted ipv6 sockets commit efe4208f47f907b86f528788da711e8ab9dea44d: 'ipv6: make lookups simpler and faster' broke initialization of local source address on accepted ipv6 sockets. Before the mentioned commit receive address was copied along with the contents of ipv6_pinfo in sctp_v6_create_accept_sk. Now when it is moved, it has to be copied separately. This also fixes lksctp's ipv6 regression in a sense that test_getname_v6, TC5 - 'getsockname on a connected server socket' now passes. Signed-off-by: Matija Glavinic Pecotic Signed-off-by: David S. Miller diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 0f6259a..2b1738e 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -662,6 +662,8 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk, */ sctp_v6_to_sk_daddr(&asoc->peer.primary_addr, newsk); + newsk->sk_v6_rcv_saddr = sk->sk_v6_rcv_saddr; + sk_refcnt_debug_inc(newsk); if (newsk->sk_prot->init(newsk)) { -- cgit v0.10.2 From cd139781546f22c41276045f6464c51074b50c40 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 6 Feb 2014 11:03:08 +0300 Subject: isdn/hisax: hex vs decimal typo in prfeatureind() This is a static checker fix, but judging from the context then I think hexidecimal 0x80 is intended here instead of decimal 80. Signed-off-by: Dan Carpenter Signed-off-by: David S. Miller diff --git a/drivers/isdn/hisax/q931.c b/drivers/isdn/hisax/q931.c index af1b020..b420f8b 100644 --- a/drivers/isdn/hisax/q931.c +++ b/drivers/isdn/hisax/q931.c @@ -810,7 +810,7 @@ prfeatureind(char *dest, u_char *p) dp += sprintf(dp, " octet 3 "); dp += prbits(dp, *p, 8, 8); *dp++ = '\n'; - if (!(*p++ & 80)) { + if (!(*p++ & 0x80)) { dp += sprintf(dp, " octet 4 "); dp += prbits(dp, *p++, 8, 8); *dp++ = '\n'; -- cgit v0.10.2 From ee262ad827f89e2dc7851ec2986953b5b125c6bc Mon Sep 17 00:00:00 2001 From: Jan Moskyto Matejka Date: Thu, 6 Feb 2014 12:10:00 +0100 Subject: inet: defines IPPROTO_* needed for module alias generation Commit cfd280c91253 ("net: sync some IP headers with glibc") changed a set of define's to an enum (with no explanation why) which introduced a bug in module mip6 where aliases are generated using the IPPROTO_* defines; mip6 doesn't load if require_module called with the aliases from xfrm_get_type(). Reverting this change back to define's to fix the aliases. modinfo mip6 (before this change) alias: xfrm-type-10-IPPROTO_DSTOPTS alias: xfrm-type-10-IPPROTO_ROUTING modinfo mip6 (after this change) alias: xfrm-type-10-43 alias: xfrm-type-10-60 Signed-off-by: Jan Moskyto Matejka Signed-off-by: David S. Miller diff --git a/include/uapi/linux/in6.h b/include/uapi/linux/in6.h index 633b93c..e9a1d2d 100644 --- a/include/uapi/linux/in6.h +++ b/include/uapi/linux/in6.h @@ -128,22 +128,13 @@ struct in6_flowlabel_req { * IPV6 extension headers */ #if __UAPI_DEF_IPPROTO_V6 -enum { - IPPROTO_HOPOPTS = 0, /* IPv6 hop-by-hop options */ -#define IPPROTO_HOPOPTS IPPROTO_HOPOPTS - IPPROTO_ROUTING = 43, /* IPv6 routing header */ -#define IPPROTO_ROUTING IPPROTO_ROUTING - IPPROTO_FRAGMENT = 44, /* IPv6 fragmentation header */ -#define IPPROTO_FRAGMENT IPPROTO_FRAGMENT - IPPROTO_ICMPV6 = 58, /* ICMPv6 */ -#define IPPROTO_ICMPV6 IPPROTO_ICMPV6 - IPPROTO_NONE = 59, /* IPv6 no next header */ -#define IPPROTO_NONE IPPROTO_NONE - IPPROTO_DSTOPTS = 60, /* IPv6 destination options */ -#define IPPROTO_DSTOPTS IPPROTO_DSTOPTS - IPPROTO_MH = 135, /* IPv6 mobility header */ -#define IPPROTO_MH IPPROTO_MH -}; +#define IPPROTO_HOPOPTS 0 /* IPv6 hop-by-hop options */ +#define IPPROTO_ROUTING 43 /* IPv6 routing header */ +#define IPPROTO_FRAGMENT 44 /* IPv6 fragmentation header */ +#define IPPROTO_ICMPV6 58 /* ICMPv6 */ +#define IPPROTO_NONE 59 /* IPv6 no next header */ +#define IPPROTO_DSTOPTS 60 /* IPv6 destination options */ +#define IPPROTO_MH 135 /* IPv6 mobility header */ #endif /* __UAPI_DEF_IPPROTO_V6 */ /* -- cgit v0.10.2 From 4ccd0bb9bf136911f85a5c1eeb6bdcc259cde5e4 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 6 Feb 2014 15:53:19 +0300 Subject: hso: remove some dead code It seems like this function was intended to have special handling for urb statuses of -ENOENT and -ECONNRESET. But now it just prints some debugging and returns at the start of the function. I have removed the dead code, it's still in the git history if anyone wants to revive it. Signed-off-by: Dan Carpenter Signed-off-by: David S. Miller diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 1a48234..660bd5e 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -1201,16 +1201,18 @@ static void hso_std_serial_read_bulk_callback(struct urb *urb) struct hso_serial *serial = urb->context; int status = urb->status; + D4("\n--- Got serial_read_bulk callback %02x ---", status); + /* sanity check */ if (!serial) { D1("serial == NULL"); return; - } else if (status) { + } + if (status) { handle_usb_error(status, __func__, serial->parent); return; } - D4("\n--- Got serial_read_bulk callback %02x ---", status); D1("Actual length = %d\n", urb->actual_length); DUMP1(urb->transfer_buffer, urb->actual_length); @@ -1218,25 +1220,13 @@ static void hso_std_serial_read_bulk_callback(struct urb *urb) if (serial->port.count == 0) return; - if (status == 0) { - if (serial->parent->port_spec & HSO_INFO_CRC_BUG) - fix_crc_bug(urb, serial->in_endp->wMaxPacketSize); - /* Valid data, handle RX data */ - spin_lock(&serial->serial_lock); - serial->rx_urb_filled[hso_urb_to_index(serial, urb)] = 1; - put_rxbuf_data_and_resubmit_bulk_urb(serial); - spin_unlock(&serial->serial_lock); - } else if (status == -ENOENT || status == -ECONNRESET) { - /* Unlinked - check for throttled port. */ - D2("Port %d, successfully unlinked urb", serial->minor); - spin_lock(&serial->serial_lock); - serial->rx_urb_filled[hso_urb_to_index(serial, urb)] = 0; - hso_resubmit_rx_bulk_urb(serial, urb); - spin_unlock(&serial->serial_lock); - } else { - D2("Port %d, status = %d for read urb", serial->minor, status); - return; - } + if (serial->parent->port_spec & HSO_INFO_CRC_BUG) + fix_crc_bug(urb, serial->in_endp->wMaxPacketSize); + /* Valid data, handle RX data */ + spin_lock(&serial->serial_lock); + serial->rx_urb_filled[hso_urb_to_index(serial, urb)] = 1; + put_rxbuf_data_and_resubmit_bulk_urb(serial); + spin_unlock(&serial->serial_lock); } /* -- cgit v0.10.2 From 440b87eac4ca21ccb3f56e7b1f126e0eebcc0f84 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Thu, 6 Feb 2014 11:45:12 -0500 Subject: drivers/net: fix build warning in ethernet/sfc/tx.c Commit ee45fd92c739db5b7950163d91dfe5f016af6d24 ("sfc: Use TX PIO for sufficiently small packets") introduced the following warning: drivers/net/ethernet/sfc/tx.c: In function 'efx_enqueue_skb': drivers/net/ethernet/sfc/tx.c:432:1: warning: label 'finish_packet' defined but not used Stick the label inside the same #ifdef that the code which calls it uses. Note that this is only seen for arch that do not set ARCH_HAS_IOREMAP_WC, such as arm, mips, sparc, ..., as the others enable the write combining code and hence use the label. Cc: Jon Cooper Cc: Ben Hutchings Signed-off-by: Paul Gortmaker Acked-by: Shradha Shah Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/sfc/tx.c b/drivers/net/ethernet/sfc/tx.c index c49d1fb..75d11fa 100644 --- a/drivers/net/ethernet/sfc/tx.c +++ b/drivers/net/ethernet/sfc/tx.c @@ -429,7 +429,9 @@ netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb) } /* Transfer ownership of the skb to the final buffer */ +#ifdef EFX_USE_PIO finish_packet: +#endif buffer->skb = skb; buffer->flags = EFX_TX_BUF_SKB | dma_flags; -- cgit v0.10.2 From 00fe11b3c67dc670fe6391d22f1fe64e7c99a8ec Mon Sep 17 00:00:00 2001 From: Sabrina Dubroca Date: Thu, 6 Feb 2014 18:34:12 +0100 Subject: netpoll: fix netconsole IPv6 setup Currently, to make netconsole start over IPv6, the source address needs to be specified. Without a source address, netpoll_parse_options assumes we're setting up over IPv4 and the destination IPv6 address is rejected. Check if the IP version has been forced by a source address before checking for a version mismatch when parsing the destination address. Signed-off-by: Sabrina Dubroca Acked-by: Cong Wang Signed-off-by: David S. Miller diff --git a/net/core/netpoll.c b/net/core/netpoll.c index c03f3de..a664f78 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -948,6 +948,7 @@ int netpoll_parse_options(struct netpoll *np, char *opt) { char *cur=opt, *delim; int ipv6; + bool ipversion_set = false; if (*cur != '@') { if ((delim = strchr(cur, '@')) == NULL) @@ -960,6 +961,7 @@ int netpoll_parse_options(struct netpoll *np, char *opt) cur++; if (*cur != '/') { + ipversion_set = true; if ((delim = strchr(cur, '/')) == NULL) goto parse_failed; *delim = 0; @@ -1002,7 +1004,7 @@ int netpoll_parse_options(struct netpoll *np, char *opt) ipv6 = netpoll_parse_ip_addr(cur, &np->remote_ip); if (ipv6 < 0) goto parse_failed; - else if (np->ipv6 != (bool)ipv6) + else if (ipversion_set && np->ipv6 != (bool)ipv6) goto parse_failed; else np->ipv6 = (bool)ipv6; -- cgit v0.10.2 From ed98df3361f059db42786c830ea96e2d18b8d4db Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 6 Feb 2014 10:42:42 -0800 Subject: net: use __GFP_NORETRY for high order allocations sock_alloc_send_pskb() & sk_page_frag_refill() have a loop trying high order allocations to prepare skb with low number of fragments as this increases performance. Problem is that under memory pressure/fragmentation, this can trigger OOM while the intent was only to try the high order allocations, then fallback to order-0 allocations. We had various reports from unexpected regressions. According to David, setting __GFP_NORETRY should be fine, as the asynchronous compaction is still enabled, and this will prevent OOM from kicking as in : CFSClientEventm invoked oom-killer: gfp_mask=0x42d0, order=3, oom_adj=0, oom_score_adj=0, oom_score_badness=2 (enabled),memcg_scoring=disabled CFSClientEventm Call Trace: [] dump_header+0xe1/0x23e [] oom_kill_process+0x6a/0x323 [] out_of_memory+0x4b3/0x50d [] __alloc_pages_may_oom+0xa2/0xc7 [] __alloc_pages_nodemask+0x1002/0x17f0 [] alloc_pages_current+0x103/0x2b0 [] sk_page_frag_refill+0x8f/0x160 [] tcp_sendmsg+0x560/0xee0 [] inet_sendmsg+0x67/0x100 [] __sock_sendmsg_nosec+0x6c/0x90 [] sock_sendmsg+0xc5/0xf0 [] __sys_sendmsg+0x136/0x430 [] sys_sendmsg+0x88/0x110 [] system_call_fastpath+0x16/0x1b Out of Memory: Kill process 2856 (bash) score 9999 or sacrifice child Signed-off-by: Eric Dumazet Acked-by: David Rientjes Acked-by: "Eric W. Biederman" Signed-off-by: David S. Miller diff --git a/net/core/sock.c b/net/core/sock.c index 0c127dc..5b6a943 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1775,7 +1775,9 @@ struct sk_buff *sock_alloc_send_pskb(struct sock *sk, unsigned long header_len, while (order) { if (npages >= 1 << order) { page = alloc_pages(sk->sk_allocation | - __GFP_COMP | __GFP_NOWARN, + __GFP_COMP | + __GFP_NOWARN | + __GFP_NORETRY, order); if (page) goto fill_page; @@ -1845,7 +1847,7 @@ bool skb_page_frag_refill(unsigned int sz, struct page_frag *pfrag, gfp_t prio) gfp_t gfp = prio; if (order) - gfp |= __GFP_COMP | __GFP_NOWARN; + gfp |= __GFP_COMP | __GFP_NOWARN | __GFP_NORETRY; pfrag->page = alloc_pages(gfp, order); if (likely(pfrag->page)) { pfrag->offset = 0; -- cgit v0.10.2 From dbe173079ab58a444e12dbebe96f5aec1e0bed1a Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Thu, 6 Feb 2014 15:00:52 -0800 Subject: bridge: fix netconsole setup over bridge Commit 93d8bf9fb8f3 ("bridge: cleanup netpoll code") introduced a check in br_netpoll_enable(), but this check is incorrect for br_netpoll_setup(). This patch moves the code after the check into __br_netpoll_enable() and calls it in br_netpoll_setup(). For br_add_if(), the check is still needed. Fixes: 93d8bf9fb8f3 ("bridge: cleanup netpoll code") Cc: Toshiaki Makita Cc: Stephen Hemminger Cc: David S. Miller Signed-off-by: Cong Wang Signed-off-by: Cong Wang Acked-by: Toshiaki Makita Tested-by: Toshiaki Makita Signed-off-by: David S. Miller diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index e4401a5..d9a9b0f 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -226,6 +226,33 @@ static void br_netpoll_cleanup(struct net_device *dev) br_netpoll_disable(p); } +static int __br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp) +{ + struct netpoll *np; + int err; + + np = kzalloc(sizeof(*p->np), gfp); + if (!np) + return -ENOMEM; + + err = __netpoll_setup(np, p->dev, gfp); + if (err) { + kfree(np); + return err; + } + + p->np = np; + return err; +} + +int br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp) +{ + if (!p->br->dev->npinfo) + return 0; + + return __br_netpoll_enable(p, gfp); +} + static int br_netpoll_setup(struct net_device *dev, struct netpoll_info *ni, gfp_t gfp) { @@ -236,7 +263,7 @@ static int br_netpoll_setup(struct net_device *dev, struct netpoll_info *ni, list_for_each_entry(p, &br->port_list, list) { if (!p->dev) continue; - err = br_netpoll_enable(p, gfp); + err = __br_netpoll_enable(p, gfp); if (err) goto fail; } @@ -249,28 +276,6 @@ fail: goto out; } -int br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp) -{ - struct netpoll *np; - int err; - - if (!p->br->dev->npinfo) - return 0; - - np = kzalloc(sizeof(*p->np), gfp); - if (!np) - return -ENOMEM; - - err = __netpoll_setup(np, p->dev, gfp); - if (err) { - kfree(np); - return err; - } - - p->np = np; - return err; -} - void br_netpoll_disable(struct net_bridge_port *p) { struct netpoll *np = p->np; -- cgit v0.10.2 From 4a5ab4e224288403b0b4b6b8c4d339323150c312 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 6 Feb 2014 15:57:10 -0800 Subject: tcp: remove 1ms offset in srtt computation TCP pacing depends on an accurate srtt estimation. Current srtt estimation is using jiffie resolution, and has an artificial offset of at least 1 ms, which can produce slowdowns when FQ/pacing is used, especially in DC world, where typical rtt is below 1 ms. We are planning a switch to usec resolution for linux-3.15, but in the meantime, this patch removes the 1 ms offset. All we need is to have tp->srtt minimal value of 1 to differentiate the case of srtt being initialized or not, not 8. The problematic behavior was observed on a 40Gbit testbed, where 32 concurrent netperf were reaching 12Gbps of aggregate speed, instead of line speed. This patch also has the effect of reporting more accurate srtt and send rates to iproute2 ss command as in : $ ss -i dst cca2 Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port tcp ESTAB 0 0 10.244.129.1:56984 10.244.129.2:12865 cubic wscale:6,6 rto:200 rtt:0.25/0.25 ato:40 mss:1448 cwnd:10 send 463.4Mbps rcv_rtt:1 rcv_space:29200 tcp ESTAB 0 390960 10.244.129.1:60247 10.244.129.2:50204 cubic wscale:6,6 rto:200 rtt:0.875/0.75 mss:1448 cwnd:73 ssthresh:51 send 966.4Mbps unacked:73 retrans:0/121 rcv_space:29200 Reported-by: Vytautas Valancius Signed-off-by: Eric Dumazet Cc: Yuchung Cheng Cc: Neal Cardwell Acked-by: Neal Cardwell Signed-off-by: David S. Miller diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 65cf90e..227cba7 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -671,6 +671,7 @@ static void tcp_rtt_estimator(struct sock *sk, const __u32 mrtt) { struct tcp_sock *tp = tcp_sk(sk); long m = mrtt; /* RTT */ + u32 srtt = tp->srtt; /* The following amusing code comes from Jacobson's * article in SIGCOMM '88. Note that rtt and mdev @@ -688,11 +689,9 @@ static void tcp_rtt_estimator(struct sock *sk, const __u32 mrtt) * does not matter how to _calculate_ it. Seems, it was trap * that VJ failed to avoid. 8) */ - if (m == 0) - m = 1; - if (tp->srtt != 0) { - m -= (tp->srtt >> 3); /* m is now error in rtt est */ - tp->srtt += m; /* rtt = 7/8 rtt + 1/8 new */ + if (srtt != 0) { + m -= (srtt >> 3); /* m is now error in rtt est */ + srtt += m; /* rtt = 7/8 rtt + 1/8 new */ if (m < 0) { m = -m; /* m is now abs(error) */ m -= (tp->mdev >> 2); /* similar update on mdev */ @@ -723,11 +722,12 @@ static void tcp_rtt_estimator(struct sock *sk, const __u32 mrtt) } } else { /* no previous measure. */ - tp->srtt = m << 3; /* take the measured time to be rtt */ + srtt = m << 3; /* take the measured time to be rtt */ tp->mdev = m << 1; /* make sure rto = 3*rtt */ tp->mdev_max = tp->rttvar = max(tp->mdev, tcp_rto_min(sk)); tp->rtt_seq = tp->snd_nxt; } + tp->srtt = max(1U, srtt); } /* Set the sk_pacing_rate to allow proper sizing of TSO packets. @@ -746,8 +746,10 @@ static void tcp_update_pacing_rate(struct sock *sk) rate *= max(tp->snd_cwnd, tp->packets_out); - /* Correction for small srtt : minimum srtt being 8 (1 jiffy << 3), - * be conservative and assume srtt = 1 (125 us instead of 1.25 ms) + /* Correction for small srtt and scheduling constraints. + * For small rtt, consider noise is too high, and use + * the minimal value (srtt = 1 -> 125 us for HZ=1000) + * * We probably need usec resolution in the future. * Note: This also takes care of possible srtt=0 case, * when tcp_rtt_estimator() was not yet called. diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 03d26b8..10435b3 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -1977,7 +1977,7 @@ bool tcp_schedule_loss_probe(struct sock *sk) /* Schedule a loss probe in 2*RTT for SACK capable connections * in Open state, that are either limited by cwnd or application. */ - if (sysctl_tcp_early_retrans < 3 || !rtt || !tp->packets_out || + if (sysctl_tcp_early_retrans < 3 || !tp->srtt || !tp->packets_out || !tcp_is_sack(tp) || inet_csk(sk)->icsk_ca_state != TCP_CA_Open) return false; -- cgit v0.10.2 From 9e65dc371b5c8d7476c81353137efc13cc1bdabd Mon Sep 17 00:00:00 2001 From: Eli Cohen Date: Tue, 28 Jan 2014 14:52:47 +0200 Subject: IB/mlx5: Fix RC transport send queue overhead computation Fix the RC QPs send queue overhead computation to take into account two additional segments in the WQE which are needed for registration operations. Signed-off-by: Eli Cohen Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c index ae37fb9..492dc33 100644 --- a/drivers/infiniband/hw/mlx5/qp.c +++ b/drivers/infiniband/hw/mlx5/qp.c @@ -216,7 +216,9 @@ static int sq_overhead(enum ib_qp_type qp_type) case IB_QPT_UC: size += sizeof(struct mlx5_wqe_ctrl_seg) + - sizeof(struct mlx5_wqe_raddr_seg); + sizeof(struct mlx5_wqe_raddr_seg) + + sizeof(struct mlx5_wqe_umr_ctrl_seg) + + sizeof(struct mlx5_mkey_seg); break; case IB_QPT_UD: -- cgit v0.10.2 From 78c0f98cc9dd46824fa66f35f14ea24ba733d145 Mon Sep 17 00:00:00 2001 From: Eli Cohen Date: Thu, 30 Jan 2014 13:49:48 +0200 Subject: IB/mlx5: Fix binary compatibility with libmlx5 Commit c1be5232d21d ("Fix micro UAR allocator") broke binary compatibility between libmlx5 and mlx5_ib since it defines a different value to the number of micro UARs per page, leading to wrong calculation in libmlx5. This patch defines struct mlx5_ib_alloc_ucontext_req_v2 as an extension to struct mlx5_ib_alloc_ucontext_req. The extended size is determined in mlx5_ib_alloc_ucontext() and in case of old library we use uuarn 0 which works fine -- this is acheived due to create_user_qp() falling back from high to medium then to low class where low class will return 0. For new libraries we use the more sophisticated allocation algorithm. Signed-off-by: Eli Cohen Reviewed-by: Yann Droneaud Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c index 9660d09..f4ef4a2 100644 --- a/drivers/infiniband/hw/mlx5/main.c +++ b/drivers/infiniband/hw/mlx5/main.c @@ -536,24 +536,38 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev, struct ib_udata *udata) { struct mlx5_ib_dev *dev = to_mdev(ibdev); - struct mlx5_ib_alloc_ucontext_req req; + struct mlx5_ib_alloc_ucontext_req_v2 req; struct mlx5_ib_alloc_ucontext_resp resp; struct mlx5_ib_ucontext *context; struct mlx5_uuar_info *uuari; struct mlx5_uar *uars; int gross_uuars; int num_uars; + int ver; int uuarn; int err; int i; + int reqlen; if (!dev->ib_active) return ERR_PTR(-EAGAIN); - err = ib_copy_from_udata(&req, udata, sizeof(req)); + memset(&req, 0, sizeof(req)); + reqlen = udata->inlen - sizeof(struct ib_uverbs_cmd_hdr); + if (reqlen == sizeof(struct mlx5_ib_alloc_ucontext_req)) + ver = 0; + else if (reqlen == sizeof(struct mlx5_ib_alloc_ucontext_req_v2)) + ver = 2; + else + return ERR_PTR(-EINVAL); + + err = ib_copy_from_udata(&req, udata, reqlen); if (err) return ERR_PTR(err); + if (req.flags || req.reserved) + return ERR_PTR(-EINVAL); + if (req.total_num_uuars > MLX5_MAX_UUARS) return ERR_PTR(-ENOMEM); @@ -626,6 +640,7 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev, if (err) goto out_uars; + uuari->ver = ver; uuari->num_low_latency_uuars = req.num_low_latency_uuars; uuari->uars = uars; uuari->num_uars = num_uars; diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c index 492dc33..091576a 100644 --- a/drivers/infiniband/hw/mlx5/qp.c +++ b/drivers/infiniband/hw/mlx5/qp.c @@ -430,11 +430,17 @@ static int alloc_uuar(struct mlx5_uuar_info *uuari, break; case MLX5_IB_LATENCY_CLASS_MEDIUM: - uuarn = alloc_med_class_uuar(uuari); + if (uuari->ver < 2) + uuarn = -ENOMEM; + else + uuarn = alloc_med_class_uuar(uuari); break; case MLX5_IB_LATENCY_CLASS_HIGH: - uuarn = alloc_high_class_uuar(uuari); + if (uuari->ver < 2) + uuarn = -ENOMEM; + else + uuarn = alloc_high_class_uuar(uuari); break; case MLX5_IB_LATENCY_CLASS_FAST_PATH: diff --git a/drivers/infiniband/hw/mlx5/user.h b/drivers/infiniband/hw/mlx5/user.h index 32a2a5d..0f4f8e4 100644 --- a/drivers/infiniband/hw/mlx5/user.h +++ b/drivers/infiniband/hw/mlx5/user.h @@ -62,6 +62,13 @@ struct mlx5_ib_alloc_ucontext_req { __u32 num_low_latency_uuars; }; +struct mlx5_ib_alloc_ucontext_req_v2 { + __u32 total_num_uuars; + __u32 num_low_latency_uuars; + __u32 flags; + __u32 reserved; +}; + struct mlx5_ib_alloc_ucontext_resp { __u32 qp_tab_size; __u32 bf_reg_size; diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h index 554548c..32cb18c 100644 --- a/include/linux/mlx5/driver.h +++ b/include/linux/mlx5/driver.h @@ -227,6 +227,7 @@ struct mlx5_uuar_info { * protect uuar allocation data structs */ struct mutex lock; + u32 ver; }; struct mlx5_bf { -- cgit v0.10.2 From 1a4c3a3dc5fdeef2a7bdf4ac7d81df58c3c0a51e Mon Sep 17 00:00:00 2001 From: Eli Cohen Date: Thu, 6 Feb 2014 17:41:25 +0200 Subject: IB/mlx5: Don't set "block multicast loopback" capability Currently Connect-IB does not support blocking multicast loopback, so don't set IB_DEVICE_BLOCK_MULTICAST_LOOPBACK in the device caps. Reported by: Or Gerlitz Signed-off-by: Eli Cohen Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c index f4ef4a2..aa03e73 100644 --- a/drivers/infiniband/hw/mlx5/main.c +++ b/drivers/infiniband/hw/mlx5/main.c @@ -261,8 +261,7 @@ static int mlx5_ib_query_device(struct ib_device *ibdev, props->device_cap_flags = IB_DEVICE_CHANGE_PHY_PORT | IB_DEVICE_PORT_ACTIVE_EVENT | IB_DEVICE_SYS_IMAGE_GUID | - IB_DEVICE_RC_RNR_NAK_GEN | - IB_DEVICE_BLOCK_MULTICAST_LOOPBACK; + IB_DEVICE_RC_RNR_NAK_GEN; flags = dev->mdev.caps.flags; if (flags & MLX5_DEV_CAP_FLAG_BAD_PKEY_CNTR) props->device_cap_flags |= IB_DEVICE_BAD_PKEY_CNTR; diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c index 091576a..7dfe8a1 100644 --- a/drivers/infiniband/hw/mlx5/qp.c +++ b/drivers/infiniband/hw/mlx5/qp.c @@ -665,8 +665,8 @@ static int create_kernel_qp(struct mlx5_ib_dev *dev, int err; uuari = &dev->mdev.priv.uuari; - if (init_attr->create_flags & IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK) - qp->flags |= MLX5_IB_QP_BLOCK_MULTICAST_LOOPBACK; + if (init_attr->create_flags) + return -EINVAL; if (init_attr->qp_type == MLX5_IB_QPT_REG_UMR) lc = MLX5_IB_LATENCY_CLASS_FAST_PATH; -- cgit v0.10.2 From f8f1becfa4ac3231da55de68698cf7facf089646 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 6 Feb 2014 18:14:03 +0100 Subject: ALSA: hda - Fix leftover ifdef checks after modularization Since the commit [595fe1b702c3: ALSA: hda - Make CONFIG_SND_HDA_CODEC_* tristate], the kconfig variables for the generic parser and codec drivers can be "m" instead of boolean, but some codes are left unchanged to check only #ifdef CONFIG_SND_HDA_CODEC_XXX, which is no longer true for modules. This patch fixes them by replacing with IS_ENABLED() macros. Fixes: 595fe1b702c3 ('ALSA: hda - Make CONFIG_SND_HDA_CODEC_* tristate') Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=70161 Signed-off-by: Takashi Iwai diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index ec4536c..69acbf7 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -932,7 +932,7 @@ int snd_hda_bus_new(struct snd_card *card, } EXPORT_SYMBOL_GPL(snd_hda_bus_new); -#ifdef CONFIG_SND_HDA_GENERIC +#if IS_ENABLED(CONFIG_SND_HDA_GENERIC) #define is_generic_config(codec) \ (codec->modelname && !strcmp(codec->modelname, "generic")) #else @@ -1570,7 +1570,7 @@ int snd_hda_codec_update_widgets(struct hda_codec *codec) EXPORT_SYMBOL_GPL(snd_hda_codec_update_widgets); -#ifdef CONFIG_SND_HDA_CODEC_HDMI +#if IS_ENABLED(CONFIG_SND_HDA_CODEC_HDMI) /* if all audio out widgets are digital, let's assume the codec as a HDMI/DP */ static bool is_likely_hdmi_codec(struct hda_codec *codec) { @@ -1622,7 +1622,7 @@ int snd_hda_codec_configure(struct hda_codec *codec) unload_parser(codec); /* to be sure */ if (is_likely_hdmi_codec(codec)) patch = load_parser(codec, snd_hda_parse_hdmi_codec); -#ifdef CONFIG_SND_HDA_GENERIC +#if IS_ENABLED(CONFIG_SND_HDA_GENERIC) if (!patch) patch = load_parser(codec, snd_hda_parse_generic_codec); #endif diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index fa2879a..e354ab1 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -198,7 +198,7 @@ MODULE_DESCRIPTION("Intel HDA driver"); #endif #if defined(CONFIG_PM) && defined(CONFIG_VGA_SWITCHEROO) -#ifdef CONFIG_SND_HDA_CODEC_HDMI +#if IS_ENABLED(CONFIG_SND_HDA_CODEC_HDMI) #define SUPPORT_VGA_SWITCHEROO #endif #endif -- cgit v0.10.2 From 7fe307117db5bd7ec6efb93c563dcf44577b6d2b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 30 Jan 2014 17:59:02 +0100 Subject: ALSA: hda - Fix inconsistent Mic mute LED The current code for controlling mic mute LED in patch_sigmatel.c blindly assumes that there is a single capture switch. But, there can be multiple multiple ones, and each of them flips the state, ended up in an inconsistent state. For fixing this problem, this patch adds kcontrol to be passed to the hook function so that the callee can check which switch is being accessed. In stac_capture_led_hook(), the state is checked as a bitmask, and turns on the LED when all capture switches are off. Signed-off-by: Takashi Iwai diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 8321a97..d9a09bd 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c @@ -3269,7 +3269,7 @@ static int cap_put_caller(struct snd_kcontrol *kcontrol, mutex_unlock(&codec->control_mutex); snd_hda_codec_flush_cache(codec); /* flush the updates */ if (err >= 0 && spec->cap_sync_hook) - spec->cap_sync_hook(codec, ucontrol); + spec->cap_sync_hook(codec, kcontrol, ucontrol); return err; } @@ -3390,7 +3390,7 @@ static int cap_single_sw_put(struct snd_kcontrol *kcontrol, return ret; if (spec->cap_sync_hook) - spec->cap_sync_hook(codec, ucontrol); + spec->cap_sync_hook(codec, kcontrol, ucontrol); return ret; } @@ -3795,7 +3795,7 @@ static int mux_select(struct hda_codec *codec, unsigned int adc_idx, return 0; snd_hda_activate_path(codec, path, true, false); if (spec->cap_sync_hook) - spec->cap_sync_hook(codec, NULL); + spec->cap_sync_hook(codec, NULL, NULL); path_power_down_sync(codec, old_path); return 1; } @@ -5270,7 +5270,7 @@ static void init_input_src(struct hda_codec *codec) } if (spec->cap_sync_hook) - spec->cap_sync_hook(codec, NULL); + spec->cap_sync_hook(codec, NULL, NULL); } /* set right pin controls for digital I/O */ diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h index 07f7672..c908afb 100644 --- a/sound/pci/hda/hda_generic.h +++ b/sound/pci/hda/hda_generic.h @@ -274,6 +274,7 @@ struct hda_gen_spec { void (*init_hook)(struct hda_codec *codec); void (*automute_hook)(struct hda_codec *codec); void (*cap_sync_hook)(struct hda_codec *codec, + struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); /* PCM hooks */ diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 4e0ec14..bcf91be 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -3291,7 +3291,8 @@ static void cxt_update_headset_mode(struct hda_codec *codec) } static void cxt_update_headset_mode_hook(struct hda_codec *codec, - struct snd_ctl_elem_value *ucontrol) + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { cxt_update_headset_mode(codec); } diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index d9693ca..f363238 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -708,7 +708,8 @@ static void alc_inv_dmic_sync(struct hda_codec *codec, bool force) } static void alc_inv_dmic_hook(struct hda_codec *codec, - struct snd_ctl_elem_value *ucontrol) + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { alc_inv_dmic_sync(codec, false); } @@ -3218,7 +3219,8 @@ static void alc269_fixup_hp_gpio_mute_hook(void *private_data, int enabled) /* turn on/off mic-mute LED per capture hook */ static void alc269_fixup_hp_gpio_mic_mute_hook(struct hda_codec *codec, - struct snd_ctl_elem_value *ucontrol) + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { struct alc_spec *spec = codec->spec; unsigned int oldval = spec->gpio_led; @@ -3528,7 +3530,8 @@ static void alc_update_headset_mode(struct hda_codec *codec) } static void alc_update_headset_mode_hook(struct hda_codec *codec, - struct snd_ctl_elem_value *ucontrol) + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { alc_update_headset_mode(codec); } diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 6998cf2..7311bad 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -194,7 +194,7 @@ struct sigmatel_spec { int default_polarity; unsigned int mic_mute_led_gpio; /* capture mute LED GPIO */ - bool mic_mute_led_on; /* current mic mute state */ + unsigned int mic_enabled; /* current mic mute state (bitmask) */ /* stream */ unsigned int stream_delay; @@ -324,19 +324,26 @@ static void stac_gpio_set(struct hda_codec *codec, unsigned int mask, /* hook for controlling mic-mute LED GPIO */ static void stac_capture_led_hook(struct hda_codec *codec, - struct snd_ctl_elem_value *ucontrol) + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { struct sigmatel_spec *spec = codec->spec; - bool mute; + unsigned int mask; + bool cur_mute, prev_mute; - if (!ucontrol) + if (!kcontrol || !ucontrol) return; - mute = !(ucontrol->value.integer.value[0] || - ucontrol->value.integer.value[1]); - if (spec->mic_mute_led_on != mute) { - spec->mic_mute_led_on = mute; - if (mute) + mask = 1U << snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); + prev_mute = !spec->mic_enabled; + if (ucontrol->value.integer.value[0] || + ucontrol->value.integer.value[1]) + spec->mic_enabled |= mask; + else + spec->mic_enabled &= ~mask; + cur_mute = !spec->mic_enabled; + if (cur_mute != prev_mute) { + if (cur_mute) spec->gpio_data |= spec->mic_mute_led_gpio; else spec->gpio_data &= ~spec->mic_mute_led_gpio; @@ -4462,7 +4469,7 @@ static void stac_setup_gpio(struct hda_codec *codec) if (spec->mic_mute_led_gpio) { spec->gpio_mask |= spec->mic_mute_led_gpio; spec->gpio_dir |= spec->mic_mute_led_gpio; - spec->mic_mute_led_on = true; + spec->mic_enabled = 0; spec->gpio_data |= spec->mic_mute_led_gpio; spec->gen.cap_sync_hook = stac_capture_led_hook; diff --git a/sound/pci/hda/thinkpad_helper.c b/sound/pci/hda/thinkpad_helper.c index 5799fbc..8fe3b8c 100644 --- a/sound/pci/hda/thinkpad_helper.c +++ b/sound/pci/hda/thinkpad_helper.c @@ -39,6 +39,7 @@ static void update_tpacpi_mute_led(void *private_data, int enabled) } static void update_tpacpi_micmute_led(struct hda_codec *codec, + struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { if (!ucontrol || !led_set_func) -- cgit v0.10.2 From f47e5dc464251f661da9495fcbf003a0d22c1360 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Fri, 7 Feb 2014 11:00:16 +0100 Subject: ALSA: hda - Add a headset quirk for Dell XPS 13 This quirk is needed for the headset microphone to work. Alsa-info at http://www.alsa-project.org/db/?f=8c7dfe857ceff462ca2de133e67023c0f68de9cb Cc: stable@vger.kernel.org (3.10+) Reported-by: Po-Hsu Lin Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index f363238..1266f18 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -5109,6 +5109,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE), SND_PCI_QUIRK(0x1028, 0x05d8, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x05db, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1028, 0x060a, "Dell XPS 13", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x0623, "Dell", ALC668_FIXUP_AUTO_MUTE), SND_PCI_QUIRK(0x1028, 0x0624, "Dell", ALC668_FIXUP_AUTO_MUTE), SND_PCI_QUIRK(0x1028, 0x0625, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), -- cgit v0.10.2 From f88abaa0d0dc0d1f1a9ae21f8e822918e5aadfdf Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 7 Feb 2014 12:07:59 +0100 Subject: ALSA: hda - Fix mic capture on Sony VAIO Pro 11 The very same fixup is needed to make the mic on Sony VAIO Pro 11 working as well as VAIO Pro 13 model. Reported-and-tested-by: Hendrik-Jan Heins Cc: Signed-off-by: Takashi Iwai diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 1266f18..0ab0b9e 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4332,6 +4332,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC), SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC), SND_PCI_QUIRK(0x1043, 0x8516, "ASUS X101CH", ALC269_FIXUP_ASUS_X101), + SND_PCI_QUIRK(0x104d, 0x90b5, "Sony VAIO Pro 11", ALC286_FIXUP_SONY_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x104d, 0x90b6, "Sony VAIO Pro 13", ALC286_FIXUP_SONY_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIXUP_SONY_VAIO_GPIO2), SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ), -- cgit v0.10.2 From bd7fc645dabab423ef362186db2917f3919321d3 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Fri, 7 Feb 2014 12:53:07 +0100 Subject: netfilter: nf_tables: do not allow NFT_SET_ELEM_INTERVAL_END flag and data This combination is not allowed since end interval elements cannot contain data. Signed-off-by: Pablo Neira Ayuso Acked-by: Patrick McHardy diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 3a2e480..d0c790e3e 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -2741,6 +2741,9 @@ static int nft_add_set_elem(const struct nft_ctx *ctx, struct nft_set *set, if (nla[NFTA_SET_ELEM_DATA] == NULL && !(elem.flags & NFT_SET_ELEM_INTERVAL_END)) return -EINVAL; + if (nla[NFTA_SET_ELEM_DATA] != NULL && + elem.flags & NFT_SET_ELEM_INTERVAL_END) + return -EINVAL; } else { if (nla[NFTA_SET_ELEM_DATA] != NULL) return -EINVAL; -- cgit v0.10.2 From 2fb91ddbf8e1dcb207e1e2085473aeaeff975102 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 6 Feb 2014 16:15:39 +0100 Subject: netfilter: nft_rbtree: fix data handling of end interval elements This patch fixes several things which related to the handling of end interval elements: * Chain use underflow with intervals and map: If you add a rule using intervals+map that introduces a loop, the error path of the rbtree set decrements the chain refcount for each side of the interval, leading to a chain use counter underflow. * Don't copy the data part of the end interval element since, this area is uninitialized and this confuses the loop detection code. * Don't allocate room for the data part of end interval elements since this is unused. So, after this patch the idea is that end interval elements don't have a data part. Signed-off-by: Pablo Neira Ayuso Acked-by: Patrick McHardy diff --git a/net/netfilter/nft_rbtree.c b/net/netfilter/nft_rbtree.c index ca0c1b2..e21d69d 100644 --- a/net/netfilter/nft_rbtree.c +++ b/net/netfilter/nft_rbtree.c @@ -69,8 +69,10 @@ static void nft_rbtree_elem_destroy(const struct nft_set *set, struct nft_rbtree_elem *rbe) { nft_data_uninit(&rbe->key, NFT_DATA_VALUE); - if (set->flags & NFT_SET_MAP) + if (set->flags & NFT_SET_MAP && + !(rbe->flags & NFT_SET_ELEM_INTERVAL_END)) nft_data_uninit(rbe->data, set->dtype); + kfree(rbe); } @@ -108,7 +110,8 @@ static int nft_rbtree_insert(const struct nft_set *set, int err; size = sizeof(*rbe); - if (set->flags & NFT_SET_MAP) + if (set->flags & NFT_SET_MAP && + !(elem->flags & NFT_SET_ELEM_INTERVAL_END)) size += sizeof(rbe->data[0]); rbe = kzalloc(size, GFP_KERNEL); @@ -117,7 +120,8 @@ static int nft_rbtree_insert(const struct nft_set *set, rbe->flags = elem->flags; nft_data_copy(&rbe->key, &elem->key); - if (set->flags & NFT_SET_MAP) + if (set->flags & NFT_SET_MAP && + !(rbe->flags & NFT_SET_ELEM_INTERVAL_END)) nft_data_copy(rbe->data, &elem->data); err = __nft_rbtree_insert(set, rbe); @@ -153,7 +157,8 @@ static int nft_rbtree_get(const struct nft_set *set, struct nft_set_elem *elem) parent = parent->rb_right; else { elem->cookie = rbe; - if (set->flags & NFT_SET_MAP) + if (set->flags & NFT_SET_MAP && + !(rbe->flags & NFT_SET_ELEM_INTERVAL_END)) nft_data_copy(&elem->data, rbe->data); elem->flags = rbe->flags; return 0; @@ -177,7 +182,8 @@ static void nft_rbtree_walk(const struct nft_ctx *ctx, rbe = rb_entry(node, struct nft_rbtree_elem, node); nft_data_copy(&elem.key, &rbe->key); - if (set->flags & NFT_SET_MAP) + if (set->flags & NFT_SET_MAP && + !(rbe->flags & NFT_SET_ELEM_INTERVAL_END)) nft_data_copy(&elem.data, rbe->data); elem.flags = rbe->flags; -- cgit v0.10.2 From c2703b13a63da335053a2f3cb560bb806bdda0ae Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Thu, 6 Feb 2014 19:19:20 -0500 Subject: drm/msm: bigger synchronization hammer Because we use a list_head in the bo to track it's position in a submit, we need to serialize at a higher layer. Otherwise there are problems when multiple contexts are SUBMIT'ing in parallel cmdstreams referencing a shared bo. Signed-off-by: Rob Clark diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c index 5281d4b..5423e91 100644 --- a/drivers/gpu/drm/msm/msm_gem_submit.c +++ b/drivers/gpu/drm/msm/msm_gem_submit.c @@ -163,7 +163,7 @@ retry: /* if locking succeeded, pin bo: */ - ret = msm_gem_get_iova(&msm_obj->base, + ret = msm_gem_get_iova_locked(&msm_obj->base, submit->gpu->id, &iova); /* this would break the logic in the fail path.. there is no @@ -247,7 +247,7 @@ static int submit_reloc(struct msm_gem_submit *submit, struct msm_gem_object *ob /* For now, just map the entire thing. Eventually we probably * to do it page-by-page, w/ kmap() if not vmap()d.. */ - ptr = msm_gem_vaddr(&obj->base); + ptr = msm_gem_vaddr_locked(&obj->base); if (IS_ERR(ptr)) { ret = PTR_ERR(ptr); @@ -307,14 +307,12 @@ static void submit_cleanup(struct msm_gem_submit *submit, bool fail) { unsigned i; - mutex_lock(&submit->dev->struct_mutex); for (i = 0; i < submit->nr_bos; i++) { struct msm_gem_object *msm_obj = submit->bos[i].obj; submit_unlock_unpin_bo(submit, i); list_del_init(&msm_obj->submit_entry); drm_gem_object_unreference(&msm_obj->base); } - mutex_unlock(&submit->dev->struct_mutex); ww_acquire_fini(&submit->ticket); kfree(submit); @@ -342,6 +340,8 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, if (args->nr_cmds > MAX_CMDS) return -EINVAL; + mutex_lock(&dev->struct_mutex); + submit = submit_create(dev, gpu, args->nr_bos); if (!submit) { ret = -ENOMEM; @@ -410,5 +410,6 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, out: if (submit) submit_cleanup(submit, !!ret); + mutex_unlock(&dev->struct_mutex); return ret; } diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index 4ebce8b..0cfe3f4 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -298,8 +298,6 @@ int msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, struct msm_drm_private *priv = dev->dev_private; int i, ret; - mutex_lock(&dev->struct_mutex); - submit->fence = ++priv->next_fence; gpu->submitted_fence = submit->fence; @@ -331,7 +329,6 @@ int msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, msm_gem_move_to_active(&msm_obj->base, gpu, true, submit->fence); } hangcheck_timer_reset(gpu); - mutex_unlock(&dev->struct_mutex); return ret; } -- cgit v0.10.2 From 4e6b788c3f2388c519ab6ed7fe59f372c85d26e9 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 7 Feb 2014 16:33:20 +0100 Subject: drm/i915: Disable dp aux irq on g4x Apparently it's broken in the exact same way as the gmbus irq. For reference of the full story see commit c12aba5aa0e60b7947bc8b6ea25ef55c4acf81a4 Author: Jiri Kosina Date: Tue Mar 19 09:56:57 2013 +0100 drm/i915: stop using GMBUS IRQs on Gen4 chips The effect is that we have a storm of unclaimed interrupts on the legacy irq line. If that one is used by a different device then the kernel will complain and rather quickly kill the irq source. Which breaks any device trying to actually use the legacy irq line. This regression has been introduced commit 4aeebd7443e36b0a40032e518a9338f48bd27efc Author: Daniel Vetter Date: Thu Oct 31 09:53:36 2013 +0100 drm/i915: dp aux irq support for g4x/vlv Note that disabling MSI works around the issue, but we can't do that since apparently then the hw will miss interrupts. At least if relevant comments in i915_irq.c are accurate. v2: Cross-reference dp aux and gmbus gen4 comments. v3: Consolidate harder into i915_drv.h as suggested by Chris. Cc: Jani Nikula Cc: Jiri Kosina Cc: Chris Wilson Reported-and-tested-by: Jiri Kosina Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 9832205..c0cba20 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1831,6 +1831,14 @@ struct drm_i915_file_private { /* Early gen2 have a totally busted CS tlb and require pinned batches. */ #define HAS_BROKEN_CS_TLB(dev) (IS_I830(dev) || IS_845G(dev)) +/* + * dp aux and gmbus irq on gen4 seems to be able to generate legacy interrupts + * even when in MSI mode. This results in spurious interrupt warnings if the + * legacy irq no. is shared with another device. The kernel then disables that + * interrupt source and so prevents the other device from working properly. + */ +#define HAS_AUX_IRQ(dev) (INTEL_INFO(dev)->gen >= 5) +#define HAS_GMBUS_IRQ(dev) (INTEL_INFO(dev)->gen >= 5) /* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte * rows, which changed the alignment requirements and fence programming. diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index c00b6e3..2f517b8 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -404,7 +404,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, int i, ret, recv_bytes; uint32_t status; int try, precharge, clock = 0; - bool has_aux_irq = true; + bool has_aux_irq = HAS_AUX_IRQ(dev); uint32_t timeout; /* dp aux is extremely sensitive to irq latency, hence request the diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index b1dc33f..d33b61d 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c @@ -258,13 +258,6 @@ intel_gpio_setup(struct intel_gmbus *bus, u32 pin) algo->data = bus; } -/* - * gmbus on gen4 seems to be able to generate legacy interrupts even when in MSI - * mode. This results in spurious interrupt warnings if the legacy irq no. is - * shared with another device. The kernel then disables that interrupt source - * and so prevents the other device from working properly. - */ -#define HAS_GMBUS_IRQ(dev) (INTEL_INFO(dev)->gen >= 5) static int gmbus_wait_hw_status(struct drm_i915_private *dev_priv, u32 gmbus2_status, -- cgit v0.10.2 From 30c54df7cb9b15b222529a028390b9c9582dd65e Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Mon, 27 Jan 2014 22:27:23 +0200 Subject: mei: clear write cb from waiting list on reset Clear write callbacks sitting in write_waiting list on reset. Otherwise these callbacks are left dangling and cause memory leak. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Cc: stable Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index 1ee2b94..ccdacb5 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -942,8 +942,16 @@ void mei_cl_all_wakeup(struct mei_device *dev) void mei_cl_all_write_clear(struct mei_device *dev) { struct mei_cl_cb *cb, *next; + struct list_head *list; - list_for_each_entry_safe(cb, next, &dev->write_list.list, list) { + list = &dev->write_list.list; + list_for_each_entry_safe(cb, next, list, list) { + list_del(&cb->list); + mei_io_cb_free(cb); + } + + list = &dev->write_waiting_list.list; + list_for_each_entry_safe(cb, next, list, list) { list_del(&cb->list); mei_io_cb_free(cb); } -- cgit v0.10.2 From 5cb906c7035f03a3a44fecece9d3ff8fcc75d6e0 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Mon, 27 Jan 2014 22:27:24 +0200 Subject: mei: don't unset read cb ptr on reset Don't set read callback to NULL during reset as this leads to memory leak of both cb and its buffer. The memory is correctly freed during mei_release. The memory leak is detectable by kmemleak if application has open read call while system is going through suspend/resume. unreferenced object 0xecead780 (size 64): comm "AsyncTask #1", pid 1018, jiffies 4294949621 (age 152.440s) hex dump (first 32 bytes): 00 01 10 00 00 02 20 00 00 bf 30 f1 00 00 00 00 ...... ...0..... 00 00 00 00 00 00 00 00 36 01 00 00 00 70 da e2 ........6....p.. backtrace: [] kmemleak_alloc+0x3c/0xa0 [] kmem_cache_alloc_trace+0xc6/0x190 [] mei_io_cb_init+0x29/0x50 [] mei_cl_read_start+0x102/0x360 [] mei_read+0x103/0x4e0 [] vfs_read+0x89/0x160 [] SyS_read+0x4f/0x80 [] syscall_call+0x7/0xb [] 0xffffffff unreferenced object 0xe2da7000 (size 512): comm "AsyncTask #1", pid 1018, jiffies 4294949621 (age 152.440s) hex dump (first 32 bytes): 00 6c da e2 7c 00 00 00 00 00 00 00 c0 eb 0c 59 .l..|..........Y 1b 00 00 00 01 00 00 00 02 10 00 00 01 00 00 00 ................ backtrace: [] kmemleak_alloc+0x3c/0xa0 [] __kmalloc+0xe7/0x1d0 [] mei_io_cb_alloc_resp_buf+0x2e/0x60 [] mei_cl_read_start+0x12c/0x360 [] mei_read+0x103/0x4e0 [] vfs_read+0x89/0x160 [] SyS_read+0x4f/0x80 [] syscall_call+0x7/0xb [] 0xffffffff Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Cc: stable Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index ccdacb5..9b809cf 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -908,7 +908,6 @@ void mei_cl_all_disconnect(struct mei_device *dev) list_for_each_entry_safe(cl, next, &dev->file_list, link) { cl->state = MEI_FILE_DISCONNECTED; cl->mei_flow_ctrl_creds = 0; - cl->read_cb = NULL; cl->timer_count = 0; } } -- cgit v0.10.2 From f0342e66b397947ed8c3eef8c37b5ca2d5b1bb50 Mon Sep 17 00:00:00 2001 From: Martyn Welch Date: Fri, 7 Feb 2014 15:48:56 +0000 Subject: VME: Correct read/write alignment algorithm In order to ensure the correct width cycles on the VME bus, the VME bridge drivers implement an algorithm to utilise the largest possible width reads and writes whilst maintaining natural alignment constraints. The algorithm currently looks at the start address rather than the current read/write address when determining whether a 16-bit width cycle is required to get to 32-bit alignment. This results in incorrect alignment, Reported-by: Jim Strouth Tested-by: Jim Strouth Signed-off-by: Martyn Welch Cc: stable Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/vme/bridges/vme_ca91cx42.c b/drivers/vme/bridges/vme_ca91cx42.c index a06edbf..1b5d48c 100644 --- a/drivers/vme/bridges/vme_ca91cx42.c +++ b/drivers/vme/bridges/vme_ca91cx42.c @@ -884,7 +884,7 @@ static ssize_t ca91cx42_master_read(struct vme_master_resource *image, if (done == count) goto out; } - if ((uintptr_t)addr & 0x2) { + if ((uintptr_t)(addr + done) & 0x2) { if ((count - done) < 2) { *(u8 *)(buf + done) = ioread8(addr + done); done += 1; @@ -938,7 +938,7 @@ static ssize_t ca91cx42_master_write(struct vme_master_resource *image, if (done == count) goto out; } - if ((uintptr_t)addr & 0x2) { + if ((uintptr_t)(addr + done) & 0x2) { if ((count - done) < 2) { iowrite8(*(u8 *)(buf + done), addr + done); done += 1; diff --git a/drivers/vme/bridges/vme_tsi148.c b/drivers/vme/bridges/vme_tsi148.c index 16830d8..9911cd5 100644 --- a/drivers/vme/bridges/vme_tsi148.c +++ b/drivers/vme/bridges/vme_tsi148.c @@ -1289,7 +1289,7 @@ static ssize_t tsi148_master_read(struct vme_master_resource *image, void *buf, if (done == count) goto out; } - if ((uintptr_t)addr & 0x2) { + if ((uintptr_t)(addr + done) & 0x2) { if ((count - done) < 2) { *(u8 *)(buf + done) = ioread8(addr + done); done += 1; @@ -1371,7 +1371,7 @@ static ssize_t tsi148_master_write(struct vme_master_resource *image, void *buf, if (done == count) goto out; } - if ((uintptr_t)addr & 0x2) { + if ((uintptr_t)(addr + done) & 0x2) { if ((count - done) < 2) { iowrite8(*(u8 *)(buf + done), addr + done); done += 1; -- cgit v0.10.2 From 821003ba4b9ffbf020a12177f0ea3d27826463c3 Mon Sep 17 00:00:00 2001 From: Jean-Jacques Hiblot Date: Wed, 15 Jan 2014 11:24:46 +0100 Subject: ARM: at91/dt: sam9263: fix compatibility string for the I2C Signed-off-by: Jean-Jacques Hiblot Signed-off-by: Nicolas Ferre diff --git a/arch/arm/boot/dts/at91sam9263.dtsi b/arch/arm/boot/dts/at91sam9263.dtsi index 0042f73..fece866 100644 --- a/arch/arm/boot/dts/at91sam9263.dtsi +++ b/arch/arm/boot/dts/at91sam9263.dtsi @@ -523,7 +523,7 @@ }; i2c0: i2c@fff88000 { - compatible = "atmel,at91sam9263-i2c"; + compatible = "atmel,at91sam9260-i2c"; reg = <0xfff88000 0x100>; interrupts = <13 IRQ_TYPE_LEVEL_HIGH 6>; #address-cells = <1>; -- cgit v0.10.2 From 5f877518775a681b516dde700b511641fb3e4f9b Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 16 Jan 2014 16:25:34 +0100 Subject: ARM: at91/dt: fix sama5d3 ohci hclk clock reference The hclk clock of the ohci node is referencing udphs_clk instead of uhphs_clk. Signed-off-by: Boris BREZILLON Signed-off-by: Nicolas Ferre diff --git a/arch/arm/boot/dts/sama5d3.dtsi b/arch/arm/boot/dts/sama5d3.dtsi index 52447c1..3d5faf8 100644 --- a/arch/arm/boot/dts/sama5d3.dtsi +++ b/arch/arm/boot/dts/sama5d3.dtsi @@ -1228,7 +1228,7 @@ compatible = "atmel,at91rm9200-ohci", "usb-ohci"; reg = <0x00600000 0x100000>; interrupts = <32 IRQ_TYPE_LEVEL_HIGH 2>; - clocks = <&usb>, <&uhphs_clk>, <&udphs_clk>, + clocks = <&usb>, <&uhphs_clk>, <&uhphs_clk>, <&uhpck>; clock-names = "usb_clk", "ohci_clk", "hclk", "uhpck"; status = "disabled"; -- cgit v0.10.2 From d7e67ee8b2ce27f4481d3cf2ac6ba8febcc3d888 Mon Sep 17 00:00:00 2001 From: Bo Shen Date: Tue, 14 Jan 2014 14:34:44 +0800 Subject: ARM: at91: enable USB host on at91sam9n12ek board Enable USB host on at91sam9n12ek board. Signed-off-by: Bo Shen Signed-off-by: Nicolas Ferre diff --git a/arch/arm/boot/dts/at91sam9n12ek.dts b/arch/arm/boot/dts/at91sam9n12ek.dts index e9487f6..924a6a6 100644 --- a/arch/arm/boot/dts/at91sam9n12ek.dts +++ b/arch/arm/boot/dts/at91sam9n12ek.dts @@ -124,6 +124,10 @@ nand-on-flash-bbt; status = "okay"; }; + + usb0: ohci@00500000 { + status = "okay"; + }; }; leds { -- cgit v0.10.2 From 425bb8d6eb8cf7b6aa0cddd3ee59a919b0b21a80 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Tue, 17 Dec 2013 10:36:17 +0100 Subject: mmc: atmel-mci: document clock properties Document the clock properties required by the atmel-mci driver. Signed-off-by: Boris BREZILLON Acked-by: Ludovic Desroches Signed-off-by: Nicolas Ferre diff --git a/Documentation/devicetree/bindings/mmc/atmel-hsmci.txt b/Documentation/devicetree/bindings/mmc/atmel-hsmci.txt index 0a85c70..07ad020 100644 --- a/Documentation/devicetree/bindings/mmc/atmel-hsmci.txt +++ b/Documentation/devicetree/bindings/mmc/atmel-hsmci.txt @@ -13,6 +13,9 @@ Required properties: - #address-cells: should be one. The cell is the slot id. - #size-cells: should be zero. - at least one slot node +- clock-names: tuple listing input clock names. + Required elements: "mci_clk" +- clocks: phandles to input clocks. The node contains child nodes for each slot that the platform uses @@ -24,6 +27,8 @@ mmc0: mmc@f0008000 { interrupts = <12 4>; #address-cells = <1>; #size-cells = <0>; + clock-names = "mci_clk"; + clocks = <&mci0_clk>; [ child node definitions...] }; -- cgit v0.10.2 From bdb90b6bb78ff51603ca85b2d353699238b54c8e Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Tue, 17 Dec 2013 12:01:34 +0100 Subject: spi/atmel: document clock properties Document the clock properties required by the spi-atmel driver. Signed-off-by: Boris BREZILLON Signed-off-by: Nicolas Ferre diff --git a/Documentation/devicetree/bindings/spi/spi_atmel.txt b/Documentation/devicetree/bindings/spi/spi_atmel.txt index 07e04cd..4f8184d 100644 --- a/Documentation/devicetree/bindings/spi/spi_atmel.txt +++ b/Documentation/devicetree/bindings/spi/spi_atmel.txt @@ -5,6 +5,9 @@ Required properties: - reg: Address and length of the register set for the device - interrupts: Should contain spi interrupt - cs-gpios: chipselects +- clock-names: tuple listing input clock names. + Required elements: "spi_clk" +- clocks: phandles to input clocks. Example: @@ -14,6 +17,8 @@ spi1: spi@fffcc000 { interrupts = <13 4 5>; #address-cells = <1>; #size-cells = <0>; + clocks = <&spi1_clk>; + clock-names = "spi_clk"; cs-gpios = <&pioB 3 0>; status = "okay"; -- cgit v0.10.2 From b7c2b6157079811586180d13c44a1095b57c2d47 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Tue, 4 Feb 2014 15:05:55 +0100 Subject: ARM: at91: add Atmel's SAMA5D3 Xplained board Add DT file for new SAMA5D3 Xplained board. This board is based on Atmel's SAMA5D36 Cortex-A5 SoC. Signed-off-by: Nicolas Ferre diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index b9d6a8b..6d1e43d 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -38,6 +38,7 @@ dtb-$(CONFIG_ARCH_AT91) += at91sam9g35ek.dtb dtb-$(CONFIG_ARCH_AT91) += at91sam9x25ek.dtb dtb-$(CONFIG_ARCH_AT91) += at91sam9x35ek.dtb # sama5d3 +dtb-$(CONFIG_ARCH_AT91) += at91-sama5d3_xplained.dtb dtb-$(CONFIG_ARCH_AT91) += sama5d31ek.dtb dtb-$(CONFIG_ARCH_AT91) += sama5d33ek.dtb dtb-$(CONFIG_ARCH_AT91) += sama5d34ek.dtb diff --git a/arch/arm/boot/dts/at91-sama5d3_xplained.dts b/arch/arm/boot/dts/at91-sama5d3_xplained.dts new file mode 100644 index 0000000..ce13755 --- /dev/null +++ b/arch/arm/boot/dts/at91-sama5d3_xplained.dts @@ -0,0 +1,229 @@ +/* + * at91-sama5d3_xplained.dts - Device Tree file for the SAMA5D3 Xplained board + * + * Copyright (C) 2014 Atmel, + * 2014 Nicolas Ferre + * + * Licensed under GPLv2 or later. + */ +/dts-v1/; +#include "sama5d36.dtsi" + +/ { + model = "SAMA5D3 Xplained"; + compatible = "atmel,sama5d3-xplained", "atmel,sama5d3", "atmel,sama5"; + + chosen { + bootargs = "console=ttyS0,115200"; + }; + + memory { + reg = <0x20000000 0x10000000>; + }; + + ahb { + apb { + mmc0: mmc@f0000000 { + pinctrl-0 = <&pinctrl_mmc0_clk_cmd_dat0 &pinctrl_mmc0_dat1_3 &pinctrl_mmc0_dat4_7 &pinctrl_mmc0_cd>; + status = "okay"; + slot@0 { + reg = <0>; + bus-width = <8>; + cd-gpios = <&pioE 0 GPIO_ACTIVE_LOW>; + }; + }; + + spi0: spi@f0004000 { + cs-gpios = <&pioD 13 0>; + status = "okay"; + }; + + can0: can@f000c000 { + status = "okay"; + }; + + i2c0: i2c@f0014000 { + status = "okay"; + }; + + i2c1: i2c@f0018000 { + status = "okay"; + }; + + macb0: ethernet@f0028000 { + phy-mode = "rgmii"; + status = "okay"; + }; + + usart0: serial@f001c000 { + status = "okay"; + }; + + usart1: serial@f0020000 { + pinctrl-0 = <&pinctrl_usart1 &pinctrl_usart1_rts_cts>; + status = "okay"; + }; + + uart0: serial@f0024000 { + status = "okay"; + }; + + mmc1: mmc@f8000000 { + pinctrl-0 = <&pinctrl_mmc1_clk_cmd_dat0 &pinctrl_mmc1_dat1_3 &pinctrl_mmc1_cd>; + status = "okay"; + slot@0 { + reg = <0>; + bus-width = <4>; + cd-gpios = <&pioE 1 GPIO_ACTIVE_HIGH>; + }; + }; + + spi1: spi@f8008000 { + cs-gpios = <&pioC 25 0>, <0>, <0>, <&pioD 16 0>; + status = "okay"; + }; + + adc0: adc@f8018000 { + pinctrl-0 = < + &pinctrl_adc0_adtrg + &pinctrl_adc0_ad0 + &pinctrl_adc0_ad1 + &pinctrl_adc0_ad2 + &pinctrl_adc0_ad3 + &pinctrl_adc0_ad4 + &pinctrl_adc0_ad5 + &pinctrl_adc0_ad6 + &pinctrl_adc0_ad7 + &pinctrl_adc0_ad8 + &pinctrl_adc0_ad9 + >; + status = "okay"; + }; + + i2c2: i2c@f801c000 { + dmas = <0>, <0>; /* Do not use DMA for i2c2 */ + status = "okay"; + }; + + macb1: ethernet@f802c000 { + phy-mode = "rmii"; + status = "okay"; + }; + + dbgu: serial@ffffee00 { + status = "okay"; + }; + + pinctrl@fffff200 { + board { + pinctrl_mmc0_cd: mmc0_cd { + atmel,pins = + ; + }; + + pinctrl_mmc1_cd: mmc1_cd { + atmel,pins = + ; + }; + + pinctrl_usba_vbus: usba_vbus { + atmel,pins = + ; /* PE9, conflicts with A9 */ + }; + }; + }; + + pmc: pmc@fffffc00 { + main: mainck { + clock-frequency = <12000000>; + }; + }; + }; + + nand0: nand@60000000 { + nand-bus-width = <8>; + nand-ecc-mode = "hw"; + atmel,has-pmecc; + atmel,pmecc-cap = <4>; + atmel,pmecc-sector-size = <512>; + nand-on-flash-bbt; + status = "okay"; + + at91bootstrap@0 { + label = "at91bootstrap"; + reg = <0x0 0x40000>; + }; + + bootloader@40000 { + label = "bootloader"; + reg = <0x40000 0x80000>; + }; + + bootloaderenv@c0000 { + label = "bootloader env"; + reg = <0xc0000 0xc0000>; + }; + + dtb@180000 { + label = "device tree"; + reg = <0x180000 0x80000>; + }; + + kernel@200000 { + label = "kernel"; + reg = <0x200000 0x600000>; + }; + + rootfs@800000 { + label = "rootfs"; + reg = <0x800000 0x0f800000>; + }; + }; + + usb0: gadget@00500000 { + atmel,vbus-gpio = <&pioE 9 GPIO_ACTIVE_HIGH>; /* PE9, conflicts with A9 */ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usba_vbus>; + status = "okay"; + }; + + usb1: ohci@00600000 { + num-ports = <3>; + atmel,vbus-gpio = <0 + &pioE 3 GPIO_ACTIVE_LOW + &pioE 4 GPIO_ACTIVE_LOW + >; + status = "okay"; + }; + + usb2: ehci@00700000 { + status = "okay"; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + + bp3 { + label = "PB_USER"; + gpios = <&pioE 29 GPIO_ACTIVE_LOW>; + linux,code = <0x104>; + gpio-key,wakeup; + }; + }; + + leds { + compatible = "gpio-leds"; + + d2 { + label = "d2"; + gpios = <&pioE 23 GPIO_ACTIVE_LOW>; /* PE23, conflicts with A23, CTS2 */ + linux,default-trigger = "heartbeat"; + }; + + d3 { + label = "d3"; + gpios = <&pioE 24 GPIO_ACTIVE_HIGH>; + }; + }; +}; -- cgit v0.10.2 From 62f9c8b40d2db915f89a6aa47395412fb29f1cfc Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Fri, 7 Feb 2014 14:45:01 +0100 Subject: netfilter: nf_tables: fix loop checking with end interval elements Fix access to uninitialized data for end interval elements. The element data part is uninitialized in interval end elements. Signed-off-by: Pablo Neira Ayuso diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index d0c790e3e..adce01e 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -2998,6 +2998,9 @@ static int nf_tables_loop_check_setelem(const struct nft_ctx *ctx, const struct nft_set_iter *iter, const struct nft_set_elem *elem) { + if (elem->flags & NFT_SET_ELEM_INTERVAL_END) + return 0; + switch (elem->data.verdict) { case NFT_JUMP: case NFT_GOTO: -- cgit v0.10.2 From e28bab4828354583bb66ac09021ca69b341a7db4 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Wed, 15 Jan 2014 17:12:58 -0800 Subject: Drivers: hv: vmbus: Specify the target CPU that should receive notification During the initial VMBUS connect phase, starting with WS2012 R2, we should specify the VPCU in the guest that should receive the notification. Fix this issue. This fix is required to properly connect to the host in the kexeced kernel. Signed-off-by: K. Y. Srinivasan Cc: [3.9+] Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c index af6edf9..855bbda 100644 --- a/drivers/hv/connection.c +++ b/drivers/hv/connection.c @@ -78,6 +78,8 @@ static int vmbus_negotiate_version(struct vmbus_channel_msginfo *msginfo, msg->interrupt_page = virt_to_phys(vmbus_connection.int_page); msg->monitor_page1 = virt_to_phys(vmbus_connection.monitor_pages[0]); msg->monitor_page2 = virt_to_phys(vmbus_connection.monitor_pages[1]); + if (version == VERSION_WIN8) + msg->target_vcpu = hv_context.vp_index[smp_processor_id()]; /* * Add to list before we send the request since we may diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index 15da677..344883d 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -875,7 +875,7 @@ struct vmbus_channel_relid_released { struct vmbus_channel_initiate_contact { struct vmbus_channel_message_header header; u32 vmbus_version_requested; - u32 padding2; + u32 target_vcpu; /* The VCPU the host should respond to */ u64 interrupt_page; u64 monitor_page1; u64 monitor_page2; -- cgit v0.10.2 From 269f979467cf49f2ea8132316c1f00f8c9678f7c Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 16 Jan 2014 11:59:58 -0800 Subject: Drivers: hv: vmbus: Don't timeout during the initial connection with host When the guest attempts to connect with the host when there may already be a connection with the host (as would be the case during the kdump/kexec path), it is difficult to guarantee timely response from the host. Starting with WS2012 R2, the host supports this ability to re-connect with the host (explicitly to support kexec). Prior to responding to the guest, the host needs to ensure that device states based on the previous connection to the host have been properly torn down. This may introduce unbounded delays. To deal with this issue, don't do a timed wait during the initial connect with the host. Signed-off-by: K. Y. Srinivasan Cc: Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c index 855bbda..f2d7bf9 100644 --- a/drivers/hv/connection.c +++ b/drivers/hv/connection.c @@ -67,7 +67,6 @@ static int vmbus_negotiate_version(struct vmbus_channel_msginfo *msginfo, int ret = 0; struct vmbus_channel_initiate_contact *msg; unsigned long flags; - int t; init_completion(&msginfo->waitevent); @@ -102,15 +101,7 @@ static int vmbus_negotiate_version(struct vmbus_channel_msginfo *msginfo, } /* Wait for the connection response */ - t = wait_for_completion_timeout(&msginfo->waitevent, 5*HZ); - if (t == 0) { - spin_lock_irqsave(&vmbus_connection.channelmsg_lock, - flags); - list_del(&msginfo->msglistentry); - spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, - flags); - return -ETIMEDOUT; - } + wait_for_completion(&msginfo->waitevent); spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); list_del(&msginfo->msglistentry); -- cgit v0.10.2 From f17083c3affccfe955b0a419056784096c18fea8 Mon Sep 17 00:00:00 2001 From: Adam Thomson Date: Thu, 6 Feb 2014 18:03:21 +0000 Subject: regulator: da9055: Remove use of regmap_irq_get_virq() Signed-off-by: Adam Thomson Signed-off-by: Mark Brown diff --git a/drivers/regulator/da9055-regulator.c b/drivers/regulator/da9055-regulator.c index 7f34020..b14ebda 100644 --- a/drivers/regulator/da9055-regulator.c +++ b/drivers/regulator/da9055-regulator.c @@ -576,7 +576,9 @@ static int da9055_regulator_probe(struct platform_device *pdev) /* Only LDO 5 and 6 has got the over current interrupt */ if (pdev->id == DA9055_ID_LDO5 || pdev->id == DA9055_ID_LDO6) { irq = platform_get_irq_byname(pdev, "REGULATOR"); - irq = regmap_irq_get_virq(da9055->irq_data, irq); + if (irq < 0) + return irq; + ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, da9055_ldo5_6_oc_irq, IRQF_TRIGGER_HIGH | -- cgit v0.10.2 From 5bbb2ae3d6f896f8d2082d1eceb6131c2420b7cf Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Tue, 4 Feb 2014 23:23:12 +0100 Subject: raw: test against runtime value of max_raw_minors bind_get() checks the device number it is called with. It uses MAX_RAW_MINORS for the upper bound. But MAX_RAW_MINORS is set at compile time while the actual number of raw devices can be set at runtime. This means the test can either be too strict or too lenient. And if the test ends up being too lenient bind_get() might try to access memory beyond what was allocated for "raw_devices". So check against the runtime value (max_raw_minors) in this function. Signed-off-by: Paul Bolle Acked-by: Jan Kara Cc: stable Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/char/raw.c b/drivers/char/raw.c index f3223aa..6e8d65e 100644 --- a/drivers/char/raw.c +++ b/drivers/char/raw.c @@ -190,7 +190,7 @@ static int bind_get(int number, dev_t *dev) struct raw_device_data *rawdev; struct block_device *bdev; - if (number <= 0 || number >= MAX_RAW_MINORS) + if (number <= 0 || number >= max_raw_minors) return -EINVAL; rawdev = &raw_devices[number]; -- cgit v0.10.2 From 7143479a6a4f853881b19999310ada53b616d2ca Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Tue, 4 Feb 2014 23:23:40 +0100 Subject: raw: set range for MAX_RAW_DEVS The Kconfig symbol MAX_RAW_DEVS is meant to be between 1 and 65536. But those boundaries are not enforced by its Kconfig entry. Note that MAX_RAW_DEVS is used to set MAX_RAW_MINORS in drivers/char/raw.c. If one would accidentally set MAX_RAW_DEVS to an invalid value, that invalid value will actually end up being used in raw_init(). So add an appropriate range to this Kconfig entry. Signed-off-by: Paul Bolle Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index fa3243d..1386749 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -499,6 +499,7 @@ config RAW_DRIVER config MAX_RAW_DEVS int "Maximum number of RAW devices to support (1-65536)" depends on RAW_DRIVER + range 1 65536 default "256" help The maximum number of RAW devices that are supported. -- cgit v0.10.2 From 4fedd0bf479558e50924c6d88f9197336742d20f Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Wed, 15 Jan 2014 16:35:43 -0500 Subject: drivers/tty/hvc: don't use module_init in non-modular hyp. console code The HVC_OPAL/RTAS/UDBG/XEN options are all bool, and hence their support is either present or absent. It will never be modular, so using module_init as an alias for __initcall is rather misleading. Fix this up now, so that we can relocate module_init from init.h into module.h in the future. If we don't do this, we'd have to add module.h to obviously non-modular code, and that would be a worse thing. Note that direct use of __initcall is discouraged, vs. one of the priority categorized subgroups. As __initcall gets mapped onto device_initcall, our use of device_initcall directly in this change means that the runtime impact is zero -- it will remain at level 6 in initcall ordering. Also the __exitcall functions have been outright deleted since they are only ever of interest to UML, and UML will never be using any of this code. Cc: Richard Weinberger Cc: Konrad Rzeszutek Wilk Cc: Boris Ostrovsky Signed-off-by: Paul Gortmaker Acked-by: David Vrabel Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/hvc/hvc_opal.c b/drivers/tty/hvc/hvc_opal.c index 6496872..b01659b 100644 --- a/drivers/tty/hvc/hvc_opal.c +++ b/drivers/tty/hvc/hvc_opal.c @@ -255,13 +255,7 @@ static int __init hvc_opal_init(void) /* Register as a vio device to receive callbacks */ return platform_driver_register(&hvc_opal_driver); } -module_init(hvc_opal_init); - -static void __exit hvc_opal_exit(void) -{ - platform_driver_unregister(&hvc_opal_driver); -} -module_exit(hvc_opal_exit); +device_initcall(hvc_opal_init); static void udbg_opal_putc(char c) { diff --git a/drivers/tty/hvc/hvc_rtas.c b/drivers/tty/hvc/hvc_rtas.c index 0069bb8..08c8792 100644 --- a/drivers/tty/hvc/hvc_rtas.c +++ b/drivers/tty/hvc/hvc_rtas.c @@ -102,17 +102,7 @@ static int __init hvc_rtas_init(void) return 0; } -module_init(hvc_rtas_init); - -/* This will tear down the tty portion of the driver */ -static void __exit hvc_rtas_exit(void) -{ - /* Really the fun isn't over until the worker thread breaks down and - * the tty cleans up */ - if (hvc_rtas_dev) - hvc_remove(hvc_rtas_dev); -} -module_exit(hvc_rtas_exit); +device_initcall(hvc_rtas_init); /* This will happen prior to module init. There is no tty at this time? */ static int __init hvc_rtas_console_init(void) diff --git a/drivers/tty/hvc/hvc_udbg.c b/drivers/tty/hvc/hvc_udbg.c index 7222827..9cf573d 100644 --- a/drivers/tty/hvc/hvc_udbg.c +++ b/drivers/tty/hvc/hvc_udbg.c @@ -80,14 +80,7 @@ static int __init hvc_udbg_init(void) return 0; } -module_init(hvc_udbg_init); - -static void __exit hvc_udbg_exit(void) -{ - if (hvc_udbg_dev) - hvc_remove(hvc_udbg_dev); -} -module_exit(hvc_udbg_exit); +device_initcall(hvc_udbg_init); static int __init hvc_udbg_console_init(void) { diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c index 636c9ba..2dc2831 100644 --- a/drivers/tty/hvc/hvc_xen.c +++ b/drivers/tty/hvc/hvc_xen.c @@ -561,18 +561,7 @@ static int __init xen_hvc_init(void) #endif return r; } - -static void __exit xen_hvc_fini(void) -{ - struct xencons_info *entry, *next; - - if (list_empty(&xenconsoles)) - return; - - list_for_each_entry_safe(entry, next, &xenconsoles, list) { - xen_console_remove(entry); - } -} +device_initcall(xen_hvc_init); static int xen_cons_init(void) { @@ -598,10 +587,6 @@ static int xen_cons_init(void) hvc_instantiate(HVC_COOKIE, 0, ops); return 0; } - - -module_init(xen_hvc_init); -module_exit(xen_hvc_fini); console_initcall(xen_cons_init); #ifdef CONFIG_EARLY_PRINTK -- cgit v0.10.2 From 3ac06b905655b3ef2fd2196bab36e4587e1e4e4f Mon Sep 17 00:00:00 2001 From: Lars Poeschel Date: Tue, 7 Jan 2014 13:34:37 +0100 Subject: tty: n_gsm: Fix for modems with brk in modem status control 3GPP TS 07.10 states in section 5.4.6.3.7: "The length byte contains the value 2 or 3 ... depending on the break signal." The break byte is optional and if it is sent, the length is 3. In fact the driver was not able to work with modems that send this break byte in their modem status control message. If the modem just sends the break byte if it is really set, then weird things might happen. The code for deconding the modem status to the internal linux presentation in gsm_process_modem has already a big comment about this 2 or 3 byte length thing and it is already able to decode the brk, but the code calling the gsm_process_modem function in gsm_control_modem does not encode it and hand it over the right way. This patch fixes this. Without this fix if the modem sends the brk byte in it's modem status control message the driver will hang when opening a muxed channel. Signed-off-by: Lars Poeschel Cc: stable Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index f34461c..2ebe47b 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -1090,6 +1090,7 @@ static void gsm_control_modem(struct gsm_mux *gsm, u8 *data, int clen) { unsigned int addr = 0; unsigned int modem = 0; + unsigned int brk = 0; struct gsm_dlci *dlci; int len = clen; u8 *dp = data; @@ -1116,6 +1117,16 @@ static void gsm_control_modem(struct gsm_mux *gsm, u8 *data, int clen) if (len == 0) return; } + len--; + if (len > 0) { + while (gsm_read_ea(&brk, *dp++) == 0) { + len--; + if (len == 0) + return; + } + modem <<= 7; + modem |= (brk & 0x7f); + } tty = tty_port_tty_get(&dlci->port); gsm_process_modem(tty, dlci, modem, clen); if (tty) { -- cgit v0.10.2 From d8a5dc3033af2fd6d16030d2ee4fbd073460fe54 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 7 Feb 2014 11:38:30 +0100 Subject: tty: Set correct tty name in 'active' sysfs attribute The 'active' sysfs attribute should refer to the currently active tty devices the console is running on, not the currently active console. The console structure doesn't refer to any device in sysfs, only the tty the console is running on has. So we need to print out the tty names in 'active', not the console names. This resolves an issue on s390 platforms in determining the correct console device to use. Cc: Lennart Poettering Cc: Kay Sievers Cc: Jiri Slaby Cc: David Herrmann Signed-off-by: Werner Fink Signed-off-by: Hannes Reinecke Cc: stable Signed-off-by: Greg Kroah-Hartman diff --git a/Documentation/ABI/testing/sysfs-tty b/Documentation/ABI/testing/sysfs-tty index ad22fb0..a2ccec3 100644 --- a/Documentation/ABI/testing/sysfs-tty +++ b/Documentation/ABI/testing/sysfs-tty @@ -3,7 +3,8 @@ Date: Nov 2010 Contact: Kay Sievers Description: Shows the list of currently configured - console devices, like 'tty1 ttyS0'. + tty devices used for the console, + 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 c74a00a..bd2715a 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -1267,16 +1267,17 @@ 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. + * buffer. Return the number of bytes written. * * Locking: None */ -static void tty_line_name(struct tty_driver *driver, int index, char *p) +static ssize_t tty_line_name(struct tty_driver *driver, int index, char *p) { if (driver->flags & TTY_DRIVER_UNNUMBERED_NODE) - strcpy(p, driver->name); + return sprintf(p, "%s", driver->name); else - sprintf(p, "%s%d", driver->name, index + driver->name_base); + return sprintf(p, "%s%d", driver->name, + index + driver->name_base); } /** @@ -3545,9 +3546,19 @@ static ssize_t show_cons_active(struct device *dev, if (i >= ARRAY_SIZE(cs)) break; } - while (i--) - count += sprintf(buf + count, "%s%d%c", - cs[i]->name, cs[i]->index, i ? ' ':'\n'); + 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'); + } console_unlock(); return count; -- cgit v0.10.2 From 6d8c00d58e9e484fdc41aaaf62e5d8364efe375a Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 9 Jan 2014 18:42:42 +0000 Subject: netfilter: nf_tables: unininline nft_trace_packet() It makes no sense to inline a rarely used function meant for debugging only that is called a total of five times in the main evaluation loop. Signed-off-by: Patrick McHardy Signed-off-by: Pablo Neira Ayuso diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c index 0d879fc..90998a6 100644 --- a/net/netfilter/nf_tables_core.c +++ b/net/netfilter/nf_tables_core.c @@ -103,9 +103,9 @@ static struct nf_loginfo trace_loginfo = { }, }; -static inline void nft_trace_packet(const struct nft_pktinfo *pkt, - const struct nft_chain *chain, - int rulenum, enum nft_trace type) +static void nft_trace_packet(const struct nft_pktinfo *pkt, + const struct nft_chain *chain, + int rulenum, enum nft_trace type) { struct net *net = dev_net(pkt->in ? pkt->in : pkt->out); -- cgit v0.10.2 From 10f6f9c38a422451989eb4e36a14788b1799b491 Mon Sep 17 00:00:00 2001 From: Chen Gang Date: Sat, 18 Jan 2014 17:04:06 +0800 Subject: drivers: staging: android: ion: ion_dummy_driver: include "linux/io.h" Need add "linux/io.h" to pass compiling under metag architecture with allmodconfig (which use the default 'virt_to_phys'), the related error: CC drivers/staging/android/ion/ion_dummy_driver.o drivers/staging/android/ion/ion_dummy_driver.c: In function 'ion_dummy_init': drivers/staging/android/ion/ion_dummy_driver.c:81: error: implicit declaration of function 'virt_to_phys' Signed-off-by: Chen Gang Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/android/ion/ion_dummy_driver.c b/drivers/staging/android/ion/ion_dummy_driver.c index 55b2002..3854df7 100644 --- a/drivers/staging/android/ion/ion_dummy_driver.c +++ b/drivers/staging/android/ion/ion_dummy_driver.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "ion.h" #include "ion_priv.h" -- cgit v0.10.2 From 18691f53bcaab1226f22b733189ec9da190bb7a2 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 22 Jan 2014 19:15:55 +0200 Subject: ion: dummy driver: use ARRAY_SIZE for nr of heaps use ARRAY_SIZE to count number of heaps in static array Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/android/ion/ion_dummy_driver.c b/drivers/staging/android/ion/ion_dummy_driver.c index 3854df7..f8a7a32 100644 --- a/drivers/staging/android/ion/ion_dummy_driver.c +++ b/drivers/staging/android/ion/ion_dummy_driver.c @@ -58,7 +58,7 @@ struct ion_platform_heap dummy_heaps[] = { }; struct ion_platform_data dummy_ion_pdata = { - .nr = 4, + .nr = ARRAY_SIZE(dummy_heaps), .heaps = dummy_heaps, }; -- cgit v0.10.2 From 102f1a2a496a76f16675ee4bf13e2a5e512c447e Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Tue, 21 Jan 2014 16:22:12 -0500 Subject: staging: don't use module_init in non-modular ion_dummy_driver.c The ION_DUMMY option is bool, and hence this code is either present or absent. It will never be modular, so using module_init as an alias for __initcall is rather misleading. Fix this up now, so that we can relocate module_init from init.h into module.h in the future. If we don't do this, we'd have to add module.h to obviously non-modular code, and that would be a worse thing. Note that direct use of __initcall is discouraged, vs. one of the priority categorized subgroups. As __initcall gets mapped onto device_initcall, our use of device_initcall directly in this change means that the runtime impact is zero -- it will remain at level 6 in initcall ordering. Cc: Colin Cross Cc: Jesse Barker Cc: Android Kernel Team Cc: John Stultz Cc: Greg Kroah-Hartman Signed-off-by: Paul Gortmaker Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/android/ion/ion_dummy_driver.c b/drivers/staging/android/ion/ion_dummy_driver.c index f8a7a32..df8228b 100644 --- a/drivers/staging/android/ion/ion_dummy_driver.c +++ b/drivers/staging/android/ion/ion_dummy_driver.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -129,6 +130,7 @@ err: } return err; } +device_initcall(ion_dummy_init); static void __exit ion_dummy_exit(void) { @@ -153,7 +155,4 @@ static void __exit ion_dummy_exit(void) return; } - -module_init(ion_dummy_init); -module_exit(ion_dummy_exit); - +__exitcall(ion_dummy_exit); -- cgit v0.10.2 From bbd9ae8a05e05a608ff9158cf3b95be7b857a6fa Mon Sep 17 00:00:00 2001 From: Greg Hackmann Date: Tue, 4 Feb 2014 16:08:34 -0800 Subject: staging: sw_sync: Add stubs for kernels without CONFIG_SW_SYNC Add stubs for kernels without CONFIG_SW_SYNC Cc: Colin Cross Cc: Android Kernel Team Signed-off-by: Greg Hackmann [jstultz: resolved minor conflict, tweaked commit message] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/android/sw_sync.h b/drivers/staging/android/sw_sync.h index 585040b..5aaf71d 100644 --- a/drivers/staging/android/sw_sync.h +++ b/drivers/staging/android/sw_sync.h @@ -35,10 +35,27 @@ struct sw_sync_pt { u32 value; }; +#if IS_ENABLED(CONFIG_SW_SYNC) struct sw_sync_timeline *sw_sync_timeline_create(const char *name); void sw_sync_timeline_inc(struct sw_sync_timeline *obj, u32 inc); struct sync_pt *sw_sync_pt_create(struct sw_sync_timeline *obj, u32 value); +#else +static inline struct sw_sync_timeline *sw_sync_timeline_create(const char *name) +{ + return NULL; +} + +static inline void sw_sync_timeline_inc(struct sw_sync_timeline *obj, u32 inc) +{ +} + +static inline struct sync_pt *sw_sync_pt_create(struct sw_sync_timeline *obj, + u32 value) +{ + return NULL; +} +#endif /* IS_ENABLED(CONFIG_SW_SYNC) */ #endif /* __KERNEL __ */ -- cgit v0.10.2 From 5cf045f54d31894ec59ee741e01fa258be2ba0fb Mon Sep 17 00:00:00 2001 From: Alistair Strachan Date: Tue, 4 Feb 2014 16:08:36 -0800 Subject: staging: sync: Fix a race condition between release_obj and print_obj Before this change, a timeline would only be removed from the timeline list *after* the sync driver had its release_obj() called. However, the driver's release_obj() may free resources needed by print_obj(). Although the timeline list is locked when print_obj() is called, it is not locked when release_obj() is called. If one CPU was in print_obj() when another was in release_obj(), the print_obj() may make unsafe accesses. It is not actually necessary to hold the timeline list lock when calling release_obj() if the call is made after the timeline is unlinked from the list, since there is no possibility another thread could be in -- or enter -- print_obj() for that timeline. This change moves the release_obj() call to after the timeline is unlinked, preventing the above race from occurring. Cc: Colin Cross Cc: Android Kernel Team Signed-off-by: Alistair Strachan [jstultz: minor commit subject tweak] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/android/sync.c b/drivers/staging/android/sync.c index 38e5d3b..b7fcaab 100644 --- a/drivers/staging/android/sync.c +++ b/drivers/staging/android/sync.c @@ -79,13 +79,13 @@ static void sync_timeline_free(struct kref *kref) container_of(kref, struct sync_timeline, kref); unsigned long flags; - if (obj->ops->release_obj) - obj->ops->release_obj(obj); - spin_lock_irqsave(&sync_timeline_list_lock, flags); list_del(&obj->sync_timeline_list); spin_unlock_irqrestore(&sync_timeline_list_lock, flags); + if (obj->ops->release_obj) + obj->ops->release_obj(obj); + kfree(obj); } -- cgit v0.10.2 From 077f6db9731673753ca41a5c3acbb5ead142658a Mon Sep 17 00:00:00 2001 From: Todd Poynor Date: Tue, 4 Feb 2014 16:08:37 -0800 Subject: staging: ashmem: Avoid deadlock between read and mmap calls Avoid holding ashmem_mutex across code that can page fault. Page faults grab the mmap_sem for the process, which are also held by mmap calls prior to calling ashmem_mmap, which locks ashmem_mutex. The reversed order of locking between the two can deadlock. The calls that can page fault are read() and the ASHMEM_SET_NAME and ASHMEM_GET_NAME ioctls. Move the code that accesses userspace pages outside the ashmem_mutex. Cc: Colin Cross Cc: Android Kernel Team Signed-off-by: Todd Poynor [jstultz: minor commit message tweaks] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/android/ashmem.c b/drivers/staging/android/ashmem.c index 23948f1..713a972 100644 --- a/drivers/staging/android/ashmem.c +++ b/drivers/staging/android/ashmem.c @@ -295,21 +295,29 @@ static ssize_t ashmem_read(struct file *file, char __user *buf, /* If size is not set, or set to 0, always return EOF. */ if (asma->size == 0) - goto out; + goto out_unlock; if (!asma->file) { ret = -EBADF; - goto out; + goto out_unlock; } - ret = asma->file->f_op->read(asma->file, buf, len, pos); - if (ret < 0) - goto out; + mutex_unlock(&ashmem_mutex); - /** Update backing file pos, since f_ops->read() doesn't */ - asma->file->f_pos = *pos; + /* + * asma and asma->file are used outside the lock here. We assume + * once asma->file is set it will never be changed, and will not + * be destroyed until all references to the file are dropped and + * ashmem_release is called. + */ + ret = asma->file->f_op->read(asma->file, buf, len, pos); + if (ret >= 0) { + /** Update backing file pos, since f_ops->read() doesn't */ + asma->file->f_pos = *pos; + } + return ret; -out: +out_unlock: mutex_unlock(&ashmem_mutex); return ret; } @@ -498,6 +506,7 @@ out: static int set_name(struct ashmem_area *asma, void __user *name) { + int len; int ret = 0; char local_name[ASHMEM_NAME_LEN]; @@ -510,21 +519,19 @@ static int set_name(struct ashmem_area *asma, void __user *name) * variable that does not need protection and later copy the local * variable to the structure member with lock held. */ - if (copy_from_user(local_name, name, ASHMEM_NAME_LEN)) - return -EFAULT; - + len = strncpy_from_user(local_name, name, ASHMEM_NAME_LEN); + if (len < 0) + return len; + if (len == ASHMEM_NAME_LEN) + local_name[ASHMEM_NAME_LEN - 1] = '\0'; mutex_lock(&ashmem_mutex); /* cannot change an existing mapping's name */ - if (unlikely(asma->file)) { + if (unlikely(asma->file)) ret = -EINVAL; - goto out; - } - memcpy(asma->name + ASHMEM_NAME_PREFIX_LEN, - local_name, ASHMEM_NAME_LEN); - asma->name[ASHMEM_FULL_NAME_LEN-1] = '\0'; -out: - mutex_unlock(&ashmem_mutex); + else + strcpy(asma->name + ASHMEM_NAME_PREFIX_LEN, local_name); + mutex_unlock(&ashmem_mutex); return ret; } -- cgit v0.10.2 From c9e8440eca61298ecccbb27f53036124a7a3c6c8 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Tue, 4 Feb 2014 16:08:38 -0800 Subject: staging: ion: Fix overflow and list bugs in system heap Fix a few bugs in ion_system_heap: Initialize the list node in the info block. Don't store size_remaining in a signed long, allocating >2GB could overflow, resulting in a call to sg_alloc_table with nents=0 which panics. alloc_largest_available will never return a block larger than size_remanining, so it can never go negative. Limit a single allocation to half of all memory. Prevents a large allocation from taking down the whole system. Cc: Colin Cross Cc: Android Kernel Team Signed-off-by: Colin Cross [jstultz: Minor commit subject tweak] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 7f07291..9849f39 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -124,6 +124,7 @@ static struct page_info *alloc_largest_available(struct ion_system_heap *heap, info->page = page; info->order = orders[i]; + INIT_LIST_HEAD(&info->list); return info; } kfree(info); @@ -145,12 +146,15 @@ static int ion_system_heap_allocate(struct ion_heap *heap, struct list_head pages; struct page_info *info, *tmp_info; int i = 0; - long size_remaining = PAGE_ALIGN(size); + unsigned long size_remaining = PAGE_ALIGN(size); unsigned int max_order = orders[0]; if (align > PAGE_SIZE) return -EINVAL; + if (size / PAGE_SIZE > totalram_pages / 2) + return -ENOMEM; + INIT_LIST_HEAD(&pages); while (size_remaining > 0) { info = alloc_largest_available(sys_heap, buffer, size_remaining, -- cgit v0.10.2 From 8666a87611fbd8597111c96e93a2f075664ee392 Mon Sep 17 00:00:00 2001 From: Laura Abbott Date: Tue, 4 Feb 2014 16:08:39 -0800 Subject: staging: ion: Fix ION_IOC_FREE compat ioctl The compat ioctl for ION_IOC_FREE currently passes allocation data instead of the free data. Correct this. Cc: Colin Cross Cc: Android Kernel Team Signed-off-by: Laura Abbott [jstultz: Folded in a small build fix] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/android/ion/compat_ion.c b/drivers/staging/android/ion/compat_ion.c index af6cd37..ee3a738 100644 --- a/drivers/staging/android/ion/compat_ion.c +++ b/drivers/staging/android/ion/compat_ion.c @@ -35,9 +35,14 @@ struct compat_ion_custom_data { compat_ulong_t arg; }; +struct compat_ion_handle_data { + compat_int_t handle; +}; + #define COMPAT_ION_IOC_ALLOC _IOWR(ION_IOC_MAGIC, 0, \ struct compat_ion_allocation_data) -#define COMPAT_ION_IOC_FREE _IOWR(ION_IOC_MAGIC, 1, struct ion_handle_data) +#define COMPAT_ION_IOC_FREE _IOWR(ION_IOC_MAGIC, 1, \ + struct compat_ion_handle_data) #define COMPAT_ION_IOC_CUSTOM _IOWR(ION_IOC_MAGIC, 6, \ struct compat_ion_custom_data) @@ -64,6 +69,19 @@ static int compat_get_ion_allocation_data( return err; } +static int compat_get_ion_handle_data( + struct compat_ion_handle_data __user *data32, + struct ion_handle_data __user *data) +{ + compat_int_t i; + int err; + + err = get_user(i, &data32->handle); + err |= put_user(i, &data->handle); + + return err; +} + static int compat_put_ion_allocation_data( struct compat_ion_allocation_data __user *data32, struct ion_allocation_data __user *data) @@ -132,8 +150,8 @@ long compat_ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) } case COMPAT_ION_IOC_FREE: { - struct compat_ion_allocation_data __user *data32; - struct ion_allocation_data __user *data; + struct compat_ion_handle_data __user *data32; + struct ion_handle_data __user *data; int err; data32 = compat_ptr(arg); @@ -141,7 +159,7 @@ long compat_ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (data == NULL) return -EFAULT; - err = compat_get_ion_allocation_data(data32, data); + err = compat_get_ion_handle_data(data32, data); if (err) return err; -- cgit v0.10.2 From a33b2fc5a9a131eb0a82846f55d7775b28cb2fcb Mon Sep 17 00:00:00 2001 From: John Stultz Date: Tue, 4 Feb 2014 16:08:40 -0800 Subject: staging: ion: Fix build warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add #include to fix the following warning seen with gcc 4.7.3: In file included from drivers/staging/android/ion/ion_heap.c:26:0: drivers/staging/android/ion/ion_priv.h:358:21: warning: ‘struct device’ declared inside parameter list [enabled by default] drivers/staging/android/ion/ion_priv.h:358:21: warning: its scope is only this definition or declaration, which is probably not what you want [enabled by default] Cc: Colin Cross Cc: Android Kernel Team Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h index d986739..fc2e4fc 100644 --- a/drivers/staging/android/ion/ion_priv.h +++ b/drivers/staging/android/ion/ion_priv.h @@ -17,6 +17,7 @@ #ifndef _ION_PRIV_H #define _ION_PRIV_H +#include #include #include #include -- cgit v0.10.2 From 1ebf5b72dc8bfbe5e7866ee1a2eb935fc7d050e6 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Fri, 17 Jan 2014 09:46:56 +0100 Subject: staging: lustre: 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. Signed-off-by: Marek Szyprowski Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h index d0d942c..dddccca1 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h @@ -120,7 +120,7 @@ do { \ do { \ LASSERT(!in_interrupt() || \ ((size) <= LIBCFS_VMALLOC_SIZE && \ - ((mask) & GFP_ATOMIC)) != 0); \ + ((mask) & __GFP_WAIT) == 0)); \ } while (0) #define LIBCFS_ALLOC_POST(ptr, size) \ -- cgit v0.10.2 From 52481e4b00f0f2922f2b0d3a3ee392677476c250 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Thu, 23 Jan 2014 23:45:04 -0500 Subject: staging/lustre: fix compile warning with is_vmalloc_addr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Recent commit 175f5475fb9c5800319da4e3c4204413d7280f5c introduced this compile warning (because vaddr is unsigned long), so add a cast: drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c: In function ‘kiblnd_kvaddr_to_page’: drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c:532:2: warning: passing argument 1 of ‘is_vmalloc_addr’ makes pointer from integer without a cast [enabled by default] if (is_vmalloc_addr(vaddr)) { ^ In file included from drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h:43:0, from drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c:41: include/linux/mm.h:336:59: note: expected ‘const void *’ but argument is of type ‘long unsigned int’ static inline int is_vmalloc_addr(const void *x) Signed-off-by: Oleg Drokin CC: Laura Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c index 9364863..6f58ead 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c @@ -529,7 +529,7 @@ kiblnd_kvaddr_to_page (unsigned long vaddr) { struct page *page; - if (is_vmalloc_addr(vaddr)) { + if (is_vmalloc_addr((void *)vaddr)) { page = vmalloc_to_page ((void *)vaddr); LASSERT (page != NULL); return page; -- cgit v0.10.2 From d979f3b0a1f0b5499ab85e68cdf02b56852918b6 Mon Sep 17 00:00:00 2001 From: Steve French Date: Sat, 1 Feb 2014 23:27:18 -0600 Subject: Add protocol specific operation for CIFS xattrs Changeset 666753c3ef8fc88b0ddd5be4865d0aa66428ac35 added protocol operations for get/setxattr to avoid calling cifs operations on smb2/smb3 mounts for xattr operations and this changeset adds the calls to cifs specific protocol operations for xattrs (in order to reenable cifs support for xattrs which was temporarily disabled by the previous changeset. We do not have SMB2/SMB3 worker function for setting xattrs yet so this only enables it for cifs. CCing stable since without these two small changsets (its small coreq 666753c3ef8fc88b0ddd5be4865d0aa66428ac35 is also needed) calling getfattr/setfattr on smb2/smb3 mounts causes problems. Signed-off-by: Steve French Reviewed-by: Shirish Pargaonkar CC: Stable diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 9cb9679..be58b8f 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -527,10 +527,15 @@ static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path, return PTR_ERR(tlink); tcon = tlink_tcon(tlink); - rc = CIFSSMBQAllEAs(xid, tcon, path, "SETFILEBITS", - ea_value, 4 /* size of buf */, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); + if (tcon->ses->server->ops->query_all_EAs == NULL) { + cifs_put_tlink(tlink); + return -EOPNOTSUPP; + } + + rc = tcon->ses->server->ops->query_all_EAs(xid, tcon, path, + "SETFILEBITS", ea_value, 4 /* size of buf */, + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); cifs_put_tlink(tlink); if (rc < 0) return (int)rc; diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c index 9ac5bfc..3e4ff79 100644 --- a/fs/cifs/smb1ops.c +++ b/fs/cifs/smb1ops.c @@ -1067,6 +1067,10 @@ struct smb_version_operations smb1_operations = { .query_mf_symlink = cifs_query_mf_symlink, .create_mf_symlink = cifs_create_mf_symlink, .is_read_op = cifs_is_read_op, +#ifdef CONFIG_CIFS_XATTR + .query_all_EAs = CIFSSMBQAllEAs, + .set_EA = CIFSSMBSetEA, +#endif /* CIFS_XATTR */ }; struct smb_version_values smb1_values = { -- cgit v0.10.2 From 83e3bc23ef9ce7c03b7b4e5d3d790246ea59db3e Mon Sep 17 00:00:00 2001 From: Steve French Date: Sun, 2 Feb 2014 23:31:47 -0600 Subject: retrieving CIFS ACLs when mounted with SMB2 fails dropping session The get/set ACL xattr support for CIFS ACLs attempts to send old cifs dialect protocol requests even when mounted with SMB2 or later dialects. Sending cifs requests on an smb2 session causes problems - the server drops the session due to the illegal request. This patch makes CIFS ACL operations protocol specific to fix that. Attempting to query/set CIFS ACLs for SMB2 will now return EOPNOTSUPP (until we add worker routines for sending query ACL requests via SMB2) instead of sending invalid (cifs) requests. A separate followon patch will be needed to fix cifs_acl_to_fattr (which takes a cifs specific u16 fid so can't be abstracted to work with SMB2 until that is changed) and will be needed to fix mount problems when "cifsacl" is specified on mount with e.g. vers=2.1 Signed-off-by: Steve French Reviewed-by: Shirish Pargaonkar CC: Stable diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index 8f9b4f7..c819b0b 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c @@ -1043,15 +1043,30 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode, __u32 secdesclen = 0; struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */ struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */ + struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); + struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); + struct cifs_tcon *tcon; + + if (IS_ERR(tlink)) + return PTR_ERR(tlink); + tcon = tlink_tcon(tlink); cifs_dbg(NOISY, "set ACL from mode for %s\n", path); /* Get the security descriptor */ - pntsd = get_cifs_acl(CIFS_SB(inode->i_sb), inode, path, &secdesclen); + + if (tcon->ses->server->ops->get_acl == NULL) { + cifs_put_tlink(tlink); + return -EOPNOTSUPP; + } + + pntsd = tcon->ses->server->ops->get_acl(cifs_sb, inode, path, + &secdesclen); if (IS_ERR(pntsd)) { rc = PTR_ERR(pntsd); cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc); - goto out; + cifs_put_tlink(tlink); + return rc; } /* @@ -1064,6 +1079,7 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode, pnntsd = kmalloc(secdesclen, GFP_KERNEL); if (!pnntsd) { kfree(pntsd); + cifs_put_tlink(tlink); return -ENOMEM; } @@ -1072,14 +1088,18 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode, cifs_dbg(NOISY, "build_sec_desc rc: %d\n", rc); + if (tcon->ses->server->ops->set_acl == NULL) + rc = -EOPNOTSUPP; + if (!rc) { /* Set the security descriptor */ - rc = set_cifs_acl(pnntsd, secdesclen, inode, path, aclflag); + rc = tcon->ses->server->ops->set_acl(pnntsd, secdesclen, inode, + path, aclflag); cifs_dbg(NOISY, "set_cifs_acl rc: %d\n", rc); } + cifs_put_tlink(tlink); kfree(pnntsd); kfree(pntsd); -out: return rc; } diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index a245d18..615e35a 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -395,6 +395,10 @@ struct smb_version_operations { int (*set_EA)(const unsigned int, struct cifs_tcon *, const char *, const char *, const void *, const __u16, const struct nls_table *, int); + struct cifs_ntsd * (*get_acl)(struct cifs_sb_info *, struct inode *, + const char *, u32 *); + int (*set_acl)(struct cifs_ntsd *, __u32, struct inode *, const char *, + int); }; struct smb_version_values { diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c index 3e4ff79..bfd66d8 100644 --- a/fs/cifs/smb1ops.c +++ b/fs/cifs/smb1ops.c @@ -1071,6 +1071,10 @@ struct smb_version_operations smb1_operations = { .query_all_EAs = CIFSSMBQAllEAs, .set_EA = CIFSSMBSetEA, #endif /* CIFS_XATTR */ +#ifdef CONFIG_CIFS_ACL + .get_acl = get_cifs_acl, + .set_acl = set_cifs_acl, +#endif /* CIFS_ACL */ }; struct smb_version_values smb1_values = { diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c index 95c43bb..5ac836a 100644 --- a/fs/cifs/xattr.c +++ b/fs/cifs/xattr.c @@ -176,8 +176,12 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, rc = -ENOMEM; } else { memcpy(pacl, ea_value, value_size); - rc = set_cifs_acl(pacl, value_size, - direntry->d_inode, full_path, CIFS_ACL_DACL); + if (pTcon->ses->server->ops->set_acl) + rc = pTcon->ses->server->ops->set_acl(pacl, + value_size, direntry->d_inode, + full_path, CIFS_ACL_DACL); + else + rc = -EOPNOTSUPP; if (rc == 0) /* force revalidate of the inode */ CIFS_I(direntry->d_inode)->time = 0; kfree(pacl); @@ -323,8 +327,11 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, u32 acllen; struct cifs_ntsd *pacl; - pacl = get_cifs_acl(cifs_sb, direntry->d_inode, - full_path, &acllen); + if (pTcon->ses->server->ops->get_acl == NULL) + goto get_ea_exit; /* rc already EOPNOTSUPP */ + + pacl = pTcon->ses->server->ops->get_acl(cifs_sb, + direntry->d_inode, full_path, &acllen); if (IS_ERR(pacl)) { rc = PTR_ERR(pacl); cifs_dbg(VFS, "%s: error %zd getting sec desc\n", -- cgit v0.10.2 From aadbacc7f2f0f359bd562cb95adde3da348fb643 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Thu, 23 Jan 2014 23:45:05 -0500 Subject: staging/lustre/lnet: Fix use after free in ksocknal_send Call to ksocknal_launch_packet might schedule a callback that might free the just sent message, and so subsequent access to it via lntmsg->msg_vmflush goes to freed memory. Instead we'll just remember if we are in the vmflush thread and only restore if we happened to set mempressure flag. Signed-off-by: Oleg Drokin Reviewed-on: http://review.whamcloud.com/8667 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4360 Reviewed-by: Liang Zhen Reviewed-by: Amir Shehata Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c index 68a4f52..b7b53b5 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c @@ -924,7 +924,7 @@ ksocknal_launch_packet (lnet_ni_t *ni, ksock_tx_t *tx, lnet_process_id_t id) int ksocknal_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg) { - int mpflag = 0; + int mpflag = 1; int type = lntmsg->msg_type; lnet_process_id_t target = lntmsg->msg_target; unsigned int payload_niov = lntmsg->msg_niov; @@ -993,8 +993,9 @@ ksocknal_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg) /* The first fragment will be set later in pro_pack */ rc = ksocknal_launch_packet(ni, tx, target); - if (lntmsg->msg_vmflush) + if (!mpflag) cfs_memory_pressure_restore(mpflag); + if (rc == 0) return (0); -- cgit v0.10.2 From 910827f17496e03d23577c580e2456604caa9f35 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Thu, 23 Jan 2014 23:45:06 -0500 Subject: lustre: Account for changelog_ext_rec in CR_MAXSIZE CR_MAXSIZE needs to account for an llog_changelog_rec that actually contains a changelog_ext_rec structure rather than a changelog_rec. With out doing so, a file size approaching the Linux kernel NAME_MAX length that is renamed to a size also close to, or at, NAME_MAX will exceed CR_MAXSIZE and trip an assertion. Signed-off-by: Christopher J. Morrone Reviewed-on: http://review.whamcloud.com/6993 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3587 Reviewed-by: Niu Yawei Reviewed-by: Lai Siyao Reviewed-by: Oleg Drokin Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h index 6b6c0240..7893d83 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h @@ -760,7 +760,8 @@ static inline void hsm_set_cl_error(int *flags, int error) *flags |= (error << CLF_HSM_ERR_L); } -#define CR_MAXSIZE cfs_size_round(2*NAME_MAX + 1 + sizeof(struct changelog_rec)) +#define CR_MAXSIZE cfs_size_round(2*NAME_MAX + 1 + \ + sizeof(struct changelog_ext_rec)) struct changelog_rec { __u16 cr_namelen; -- cgit v0.10.2 From 18e042f0c9cb14afa5540dc366eeefe67295d0b9 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Thu, 23 Jan 2014 23:45:07 -0500 Subject: lustre: Correct KUC code max changelog msg size The kernel to userspace communication routines (KUC) allocate and limit the maximum cs_buf size to CR_MAXSIZE. However this fails to account for the fact that the buffer is assumed to begin with a struct kuc_hdr. To allocate and account for that space, we introduce a new define, KUC_CHANGELOG_MSG_MAXSIZE. Signed-off-by: Christopher J. Morrone Reviewed-on: http://review.whamcloud.com/7406 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3587 Reviewed-by: Andreas Dilger Reviewed-by: jacques-Charles Lafoucriere Reviewed-by: Oleg Drokin Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_kernelcomm.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_kernelcomm.h index 596a15f..037ae8a 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_kernelcomm.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_kernelcomm.h @@ -61,6 +61,8 @@ struct kuc_hdr { __u16 kuc_msglen; /* Including header */ } __attribute__((aligned(sizeof(__u64)))); +#define KUC_CHANGELOG_MSG_MAXSIZE (sizeof(struct kuc_hdr)+CR_MAXSIZE) + #define KUC_MAGIC 0x191C /*Lustre9etLinC */ #define KUC_FL_BLOCK 0x01 /* Wait for send */ diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index d1ad91c3..8301392 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -1430,7 +1430,7 @@ static struct kuc_hdr *changelog_kuc_hdr(char *buf, int len, int flags) { struct kuc_hdr *lh = (struct kuc_hdr *)buf; - LASSERT(len <= CR_MAXSIZE); + LASSERT(len <= KUC_CHANGELOG_MSG_MAXSIZE); lh->kuc_magic = KUC_MAGIC; lh->kuc_transport = KUC_TRANSPORT_CHANGELOG; @@ -1503,7 +1503,7 @@ static int mdc_changelog_send_thread(void *csdata) CDEBUG(D_CHANGELOG, "changelog to fp=%p start "LPU64"\n", cs->cs_fp, cs->cs_startrec); - OBD_ALLOC(cs->cs_buf, CR_MAXSIZE); + OBD_ALLOC(cs->cs_buf, KUC_CHANGELOG_MSG_MAXSIZE); if (cs->cs_buf == NULL) GOTO(out, rc = -ENOMEM); @@ -1540,7 +1540,7 @@ out: if (ctxt) llog_ctxt_put(ctxt); if (cs->cs_buf) - OBD_FREE(cs->cs_buf, CR_MAXSIZE); + OBD_FREE(cs->cs_buf, KUC_CHANGELOG_MSG_MAXSIZE); OBD_FREE_PTR(cs); return rc; } -- cgit v0.10.2 From 1ea98e4c440eb497e1af1bce31cbba261b081a7b Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Thu, 23 Jan 2014 23:45:08 -0500 Subject: lustre: add myself to list of people to CC on lustre patches Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/TODO b/drivers/staging/lustre/TODO index 22742d6..0a2b6cb 100644 --- a/drivers/staging/lustre/TODO +++ b/drivers/staging/lustre/TODO @@ -9,5 +9,6 @@ * Other minor misc cleanups... Please send any patches to Greg Kroah-Hartman , Andreas Dilger - and Peng Tao . CCing -hpdd-discuss would be great too. +, Oleg Drokin and +Peng Tao . CCing hpdd-discuss +would be great too. -- cgit v0.10.2 From b91619c284e53fec09d502f29c1ad7ee4766e664 Mon Sep 17 00:00:00 2001 From: David Daney Date: Mon, 3 Feb 2014 19:39:01 +0200 Subject: staging: octeon-usb: Probe via device tree populated platform device. Extract clocking parameters from the device tree, and remove now dead code and types. Signed-off-by: David Daney Tested-by: Aaro Koskinen Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/octeon-usb/octeon-hcd.c b/drivers/staging/octeon-usb/octeon-hcd.c index 47e0a91..5a001d9 100644 --- a/drivers/staging/octeon-usb/octeon-hcd.c +++ b/drivers/staging/octeon-usb/octeon-hcd.c @@ -275,13 +275,6 @@ enum cvmx_usb_pipe_flags { */ #define MAX_TRANSFER_PACKETS ((1<<10)-1) -enum { - USB_CLOCK_TYPE_REF_12, - USB_CLOCK_TYPE_REF_24, - USB_CLOCK_TYPE_REF_48, - USB_CLOCK_TYPE_CRYSTAL_12, -}; - /** * Logical transactions may take numerous low level * transactions, especially when splits are concerned. This @@ -471,19 +464,6 @@ struct octeon_hcd { /* Returns the IO address to push/pop stuff data from the FIFOs */ #define USB_FIFO_ADDRESS(channel, usb_index) (CVMX_USBCX_GOTGCTL(usb_index) + ((channel)+1)*0x1000) -static int octeon_usb_get_clock_type(void) -{ - switch (cvmx_sysinfo_get()->board_type) { - case CVMX_BOARD_TYPE_BBGW_REF: - case CVMX_BOARD_TYPE_LANAI2_A: - case CVMX_BOARD_TYPE_LANAI2_U: - case CVMX_BOARD_TYPE_LANAI2_G: - case CVMX_BOARD_TYPE_UBNT_E100: - return USB_CLOCK_TYPE_CRYSTAL_12; - } - return USB_CLOCK_TYPE_REF_48; -} - /** * Read a USB 32bit CSR. It performs the necessary address swizzle * for 32bit CSRs and logs the value in a readable format if @@ -582,37 +562,6 @@ static inline int __cvmx_usb_get_data_pid(struct cvmx_usb_pipe *pipe) return 0; /* Data0 */ } - -/** - * Return the number of USB ports supported by this Octeon - * chip. If the chip doesn't support USB, or is not supported - * by this API, a zero will be returned. Most Octeon chips - * support one usb port, but some support two ports. - * cvmx_usb_initialize() must be called on independent - * struct cvmx_usb_state. - * - * Returns: Number of port, zero if usb isn't supported - */ -static int cvmx_usb_get_num_ports(void) -{ - int arch_ports = 0; - - if (OCTEON_IS_MODEL(OCTEON_CN56XX)) - arch_ports = 1; - else if (OCTEON_IS_MODEL(OCTEON_CN52XX)) - arch_ports = 2; - else if (OCTEON_IS_MODEL(OCTEON_CN50XX)) - arch_ports = 1; - else if (OCTEON_IS_MODEL(OCTEON_CN31XX)) - arch_ports = 1; - else if (OCTEON_IS_MODEL(OCTEON_CN30XX)) - arch_ports = 1; - else - arch_ports = 0; - - return arch_ports; -} - /** * Initialize a USB port for use. This must be called before any * other access to the Octeon USB port is made. The port starts @@ -628,41 +577,16 @@ static int cvmx_usb_get_num_ports(void) * Returns: 0 or a negative error code. */ static int cvmx_usb_initialize(struct cvmx_usb_state *usb, - int usb_port_number) + int usb_port_number, + enum cvmx_usb_initialize_flags flags) { union cvmx_usbnx_clk_ctl usbn_clk_ctl; union cvmx_usbnx_usbp_ctl_status usbn_usbp_ctl_status; - enum cvmx_usb_initialize_flags flags = 0; int i; /* At first allow 0-1 for the usb port number */ if ((usb_port_number < 0) || (usb_port_number > 1)) return -EINVAL; - /* For all chips except 52XX there is only one port */ - if (!OCTEON_IS_MODEL(OCTEON_CN52XX) && (usb_port_number > 0)) - return -EINVAL; - /* Try to determine clock type automatically */ - if (octeon_usb_get_clock_type() == USB_CLOCK_TYPE_CRYSTAL_12) { - /* Only 12 MHZ crystals are supported */ - flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_XI; - } else { - flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND; - - switch (octeon_usb_get_clock_type()) { - case USB_CLOCK_TYPE_REF_12: - flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_12MHZ; - break; - case USB_CLOCK_TYPE_REF_24: - flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_24MHZ; - break; - case USB_CLOCK_TYPE_REF_48: - flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_48MHZ; - break; - default: - return -EINVAL; - break; - } - } memset(usb, 0, sizeof(*usb)); usb->init_flags = flags; @@ -3431,7 +3355,6 @@ static int octeon_usb_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, return 0; } - static const struct hc_driver octeon_hc_driver = { .description = "Octeon USB", .product_desc = "Octeon Host Controller", @@ -3448,15 +3371,74 @@ static const struct hc_driver octeon_hc_driver = { .hub_control = octeon_usb_hub_control, }; - -static int octeon_usb_driver_probe(struct device *dev) +static int octeon_usb_probe(struct platform_device *pdev) { int status; - int usb_num = to_platform_device(dev)->id; - int irq = platform_get_irq(to_platform_device(dev), 0); + int initialize_flags; + int usb_num; + struct resource *res_mem; + struct device_node *usbn_node; + int irq = platform_get_irq(pdev, 0); + struct device *dev = &pdev->dev; struct octeon_hcd *priv; struct usb_hcd *hcd; unsigned long flags; + u32 clock_rate = 48000000; + bool is_crystal_clock = false; + const char *clock_type; + int i; + + if (dev->of_node == NULL) { + dev_err(dev, "Error: empty of_node\n"); + return -ENXIO; + } + usbn_node = dev->of_node->parent; + + i = of_property_read_u32(usbn_node, + "refclk-frequency", &clock_rate); + if (i) { + dev_err(dev, "No USBN \"refclk-frequency\"\n"); + return -ENXIO; + } + switch (clock_rate) { + case 12000000: + initialize_flags = CVMX_USB_INITIALIZE_FLAGS_CLOCK_12MHZ; + break; + case 24000000: + initialize_flags = CVMX_USB_INITIALIZE_FLAGS_CLOCK_24MHZ; + break; + case 48000000: + initialize_flags = CVMX_USB_INITIALIZE_FLAGS_CLOCK_48MHZ; + break; + default: + dev_err(dev, "Illebal USBN \"refclk-frequency\" %u\n", clock_rate); + return -ENXIO; + + } + + i = of_property_read_string(usbn_node, + "refclk-type", &clock_type); + + if (!i && strcmp("crystal", clock_type) == 0) + is_crystal_clock = true; + + if (is_crystal_clock) + initialize_flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_XI; + else + initialize_flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND; + + res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res_mem == NULL) { + dev_err(dev, "found no memory resource\n"); + return -ENXIO; + } + usb_num = (res_mem->start >> 44) & 1; + + if (irq < 0) { + /* Defective device tree, but we know how to fix it. */ + irq_hw_number_t hwirq = usb_num ? (1 << 6) + 17 : 56; + irq = irq_create_mapping(NULL, hwirq); + } /* * Set the DMA mask to 64bits so we get buffers already translated for @@ -3465,6 +3447,26 @@ static int octeon_usb_driver_probe(struct device *dev) dev->coherent_dma_mask = ~0; dev->dma_mask = &dev->coherent_dma_mask; + /* + * Only cn52XX and cn56XX have DWC_OTG USB hardware and the + * IOB priority registers. Under heavy network load USB + * hardware can be starved by the IOB causing a crash. Give + * it a priority boost if it has been waiting more than 400 + * cycles to avoid this situation. + * + * Testing indicates that a cnt_val of 8192 is not sufficient, + * but no failures are seen with 4096. We choose a value of + * 400 to give a safety factor of 10. + */ + if (OCTEON_IS_MODEL(OCTEON_CN52XX) || OCTEON_IS_MODEL(OCTEON_CN56XX)) { + union cvmx_iob_n2c_l2c_pri_cnt pri_cnt; + + pri_cnt.u64 = 0; + pri_cnt.s.cnt_enb = 1; + pri_cnt.s.cnt_val = 400; + cvmx_write_csr(CVMX_IOB_N2C_L2C_PRI_CNT, pri_cnt.u64); + } + hcd = usb_create_hcd(&octeon_hc_driver, dev, dev_name(dev)); if (!hcd) { dev_dbg(dev, "Failed to allocate memory for HCD\n"); @@ -3478,7 +3480,7 @@ static int octeon_usb_driver_probe(struct device *dev) tasklet_init(&priv->dequeue_tasklet, octeon_usb_urb_dequeue_work, (unsigned long)priv); INIT_LIST_HEAD(&priv->dequeue_list); - status = cvmx_usb_initialize(&priv->usb, usb_num); + status = cvmx_usb_initialize(&priv->usb, usb_num, initialize_flags); if (status) { dev_dbg(dev, "USB initialization failed with %d\n", status); kfree(hcd); @@ -3492,7 +3494,7 @@ static int octeon_usb_driver_probe(struct device *dev) cvmx_usb_poll(&priv->usb); spin_unlock_irqrestore(&priv->lock, flags); - status = usb_add_hcd(hcd, irq, IRQF_SHARED); + status = usb_add_hcd(hcd, irq, 0); if (status) { dev_dbg(dev, "USB add HCD failed with %d\n", status); kfree(hcd); @@ -3500,14 +3502,15 @@ static int octeon_usb_driver_probe(struct device *dev) } device_wakeup_enable(hcd->self.controller); - dev_dbg(dev, "Registered HCD for port %d on irq %d\n", usb_num, irq); + dev_info(dev, "Registered HCD for port %d on irq %d\n", usb_num, irq); return 0; } -static int octeon_usb_driver_remove(struct device *dev) +static int octeon_usb_remove(struct platform_device *pdev) { int status; + struct device *dev = &pdev->dev; struct usb_hcd *hcd = dev_get_drvdata(dev); struct octeon_hcd *priv = hcd_to_octeon(hcd); unsigned long flags; @@ -3525,85 +3528,41 @@ static int octeon_usb_driver_remove(struct device *dev) return 0; } -static struct device_driver octeon_usb_driver = { - .name = "OcteonUSB", - .bus = &platform_bus_type, - .probe = octeon_usb_driver_probe, - .remove = octeon_usb_driver_remove, +static struct of_device_id octeon_usb_match[] = { + { + .compatible = "cavium,octeon-5750-usbc", + }, + {}, }; +static struct platform_driver octeon_usb_driver = { + .driver = { + .name = "OcteonUSB", + .owner = THIS_MODULE, + .of_match_table = octeon_usb_match, + }, + .probe = octeon_usb_probe, + .remove = octeon_usb_remove, +}; -#define MAX_USB_PORTS 10 -static struct platform_device *pdev_glob[MAX_USB_PORTS]; -static int octeon_usb_registered; -static int __init octeon_usb_module_init(void) +static int __init octeon_usb_driver_init(void) { - int num_devices = cvmx_usb_get_num_ports(); - int device; - - if (usb_disabled() || num_devices == 0) - return -ENODEV; - - if (driver_register(&octeon_usb_driver)) - return -ENOMEM; - - octeon_usb_registered = 1; - - /* - * Only cn52XX and cn56XX have DWC_OTG USB hardware and the - * IOB priority registers. Under heavy network load USB - * hardware can be starved by the IOB causing a crash. Give - * it a priority boost if it has been waiting more than 400 - * cycles to avoid this situation. - * - * Testing indicates that a cnt_val of 8192 is not sufficient, - * but no failures are seen with 4096. We choose a value of - * 400 to give a safety factor of 10. - */ - if (OCTEON_IS_MODEL(OCTEON_CN52XX) || OCTEON_IS_MODEL(OCTEON_CN56XX)) { - union cvmx_iob_n2c_l2c_pri_cnt pri_cnt; - - pri_cnt.u64 = 0; - pri_cnt.s.cnt_enb = 1; - pri_cnt.s.cnt_val = 400; - cvmx_write_csr(CVMX_IOB_N2C_L2C_PRI_CNT, pri_cnt.u64); - } - - for (device = 0; device < num_devices; device++) { - struct resource irq_resource; - struct platform_device *pdev; - memset(&irq_resource, 0, sizeof(irq_resource)); - irq_resource.start = (device == 0) ? OCTEON_IRQ_USB0 : OCTEON_IRQ_USB1; - irq_resource.end = irq_resource.start; - irq_resource.flags = IORESOURCE_IRQ; - pdev = platform_device_register_simple((char *)octeon_usb_driver. name, device, &irq_resource, 1); - if (IS_ERR(pdev)) { - driver_unregister(&octeon_usb_driver); - octeon_usb_registered = 0; - return PTR_ERR(pdev); - } - if (device < MAX_USB_PORTS) - pdev_glob[device] = pdev; + if (usb_disabled()) + return 0; - } - return 0; + return platform_driver_register(&octeon_usb_driver); } +module_init(octeon_usb_driver_init); -static void __exit octeon_usb_module_cleanup(void) +static void __exit octeon_usb_driver_exit(void) { - int i; + if (usb_disabled()) + return; - for (i = 0; i < MAX_USB_PORTS; i++) - if (pdev_glob[i]) { - platform_device_unregister(pdev_glob[i]); - pdev_glob[i] = NULL; - } - if (octeon_usb_registered) - driver_unregister(&octeon_usb_driver); + platform_driver_unregister(&octeon_usb_driver); } +module_exit(octeon_usb_driver_exit); MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Cavium Networks "); -MODULE_DESCRIPTION("Cavium Networks Octeon USB Host driver."); -module_init(octeon_usb_module_init); -module_exit(octeon_usb_module_cleanup); +MODULE_AUTHOR("Cavium, Inc. "); +MODULE_DESCRIPTION("Cavium Inc. OCTEON USB Host driver."); -- cgit v0.10.2 From fdf2f40c6cb9649e3990bc11fe0b5c155adf555a Mon Sep 17 00:00:00 2001 From: Surendra Patil Date: Mon, 3 Feb 2014 21:53:53 -0800 Subject: staging: rtl8821ae: Fixed the size of array to macro as discussed by Linus MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Linus Torvalds writes: It causes an interesting warning for me: drivers/staging/rtl8821ae/rtl8821ae/dm.c: In function ‘rtl8821ae_dm_clear_txpower_tracking_state’: drivers/staging/rtl8821ae/rtl8821ae/dm.c:487:31: warning: iteration 2u invokes undefined behavior [-Waggressive-loop-optimizations] rtldm->bb_swing_idx_ofdm[p] = rtldm->default_ofdm_index; ^ drivers/staging/rtl8821ae/rtl8821ae/dm.c:485:2: note: containing loop for (p = RF90_PATH_A; p < MAX_RF_PATH; ++p) { ^ and gcc is entirely correct: that loop iterates from 0 to 3, and does this: rtldm->bb_swing_idx_ofdm[p] = rtldm->default_ofdm_index; but the bb_swing_idx_ofdm[] array only has two members. So the last two iterations will overwrite bb_swing_idx_ofdm_current and the first entry in bb_swing_idx_ofdm_base[]. Now, the bug does seem to be benign: bb_swing_idx_ofdm_current isn't actually ever *used* as far as I can tell, and the first entry of bb_swing_idx_ofdm_base[] will have been written with that same "rtldm->default_ofdm_index" value. But gcc is absolutely correct, and that driver needs fixing. I've pulled it and will let it be because it doesn't seem to be an issue in practice, but please fix it. The obvious fix would seem to change the size of "2" to be "MAX_RF_PATH", but I'll abstain from doing those kinds of changes in the merge when it doesn't seem to affect the build or functionality). Reported-By: Linus Torvalds Signed-off-by: Surendra Patil Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8821ae/wifi.h b/drivers/staging/rtl8821ae/wifi.h index cfe88a1..76bef93 100644 --- a/drivers/staging/rtl8821ae/wifi.h +++ b/drivers/staging/rtl8821ae/wifi.h @@ -1414,7 +1414,7 @@ struct rtl_dm { /*88e tx power tracking*/ - u8 bb_swing_idx_ofdm[2]; + u8 bb_swing_idx_ofdm[MAX_RF_PATH]; u8 bb_swing_idx_ofdm_current; u8 bb_swing_idx_ofdm_base[MAX_RF_PATH]; bool bb_swing_flag_Ofdm; -- cgit v0.10.2 From 8360fb0d9c21283e6fc12c43ce9ad81d1f9cffef Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Wed, 22 Jan 2014 09:38:14 -0700 Subject: staging/usbip: Fix vhci_hcd attach failure error message to be informative When attach fails due to unsupported and/or invalid bus speed, the message vhci_hcd prints out doesn't include any useful information as to what caused the failure. Change the message to be informative and use usb_speed_string() to get the right speed string from usb common. Signed-off-by: Shuah Khan Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/usbip/vhci_sysfs.c b/drivers/staging/usbip/vhci_sysfs.c index 9b51586..0141bc3 100644 --- a/drivers/staging/usbip/vhci_sysfs.c +++ b/drivers/staging/usbip/vhci_sysfs.c @@ -149,7 +149,8 @@ static int valid_args(__u32 rhport, enum usb_device_speed speed) case USB_SPEED_WIRELESS: break; default: - pr_err("speed %d\n", speed); + pr_err("Failed attach request for unsupported USB speed: %s\n", + usb_speed_string(speed)); return -EINVAL; } -- cgit v0.10.2 From 0010b79d56cb1d7717bf146ee59df5a625b0330b Mon Sep 17 00:00:00 2001 From: Salym Senyonga Date: Sat, 25 Jan 2014 12:54:39 +0300 Subject: Staging: ozwpan: Fix null dereference If net_dev is NULL memcpy() will Oops. Signed-off-by: Salym Senyonga Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/ozwpan/ozproto.c b/drivers/staging/ozwpan/ozproto.c index cb06036..5d965cf 100644 --- a/drivers/staging/ozwpan/ozproto.c +++ b/drivers/staging/ozwpan/ozproto.c @@ -668,8 +668,8 @@ void oz_binding_add(const char *net_dev) if (binding) { binding->ptype.type = __constant_htons(OZ_ETHERTYPE); binding->ptype.func = oz_pkt_recv; - memcpy(binding->name, net_dev, OZ_MAX_BINDING_LEN); if (net_dev && *net_dev) { + memcpy(binding->name, net_dev, OZ_MAX_BINDING_LEN); oz_dbg(ON, "Adding binding: %s\n", net_dev); binding->ptype.dev = dev_get_by_name(&init_net, net_dev); @@ -680,6 +680,7 @@ void oz_binding_add(const char *net_dev) } } else { oz_dbg(ON, "Binding to all netcards\n"); + memset(binding->name, 0, OZ_MAX_BINDING_LEN); binding->ptype.dev = NULL; } if (binding) { -- cgit v0.10.2 From ead00ddca0578aa9984e7e712024aead113e8253 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 7 Feb 2014 09:16:38 -0800 Subject: Revert "Staging: dgrp: Refactor the function dgrp_receive() in drrp_net_ops.c" This reverts commit b73db54750482cf3910046c82a84ce8c1684dfbe. Reported-by: Geert Uytterhoeven Reported-by: Chen Gang Cc: Rashika Kheria Cc: James Hogan Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/dgrp/dgrp_net_ops.c b/drivers/staging/dgrp/dgrp_net_ops.c index 1f61b89..33ac7fb 100644 --- a/drivers/staging/dgrp/dgrp_net_ops.c +++ b/drivers/staging/dgrp/dgrp_net_ops.c @@ -2232,177 +2232,6 @@ done: return rtn; } -/* - * Common Packet Handling code - */ - -static void handle_data_in_packet(struct nd_struct *nd, struct ch_struct *ch, - long dlen, long plen, int n1, u8 *dbuf) -{ - char *error; - long n; - long remain; - u8 *buf; - u8 *b; - - remain = nd->nd_remain; - nd->nd_tx_work = 1; - - /* - * Otherwise data should appear only when we are - * in the CS_READY state. - */ - - if (ch->ch_state < CS_READY) { - error = "Data received before RWIN established"; - nd->nd_remain = 0; - nd->nd_state = NS_SEND_ERROR; - nd->nd_error = error; - } - - /* - * Assure that the data received is within the - * allowable window. - */ - - n = (ch->ch_s_rwin - ch->ch_s_rin) & 0xffff; - - if (dlen > n) { - error = "Receive data overrun"; - nd->nd_remain = 0; - nd->nd_state = NS_SEND_ERROR; - nd->nd_error = error; - } - - /* - * If we received 3 or less characters, - * assume it is a human typing, and set RTIME - * to 10 milliseconds. - * - * If we receive 10 or more characters, - * assume its not a human typing, and set RTIME - * to 100 milliseconds. - */ - - if (ch->ch_edelay != DGRP_RTIME) { - if (ch->ch_rtime != ch->ch_edelay) { - ch->ch_rtime = ch->ch_edelay; - ch->ch_flag |= CH_PARAM; - } - } else if (dlen <= 3) { - if (ch->ch_rtime != 10) { - ch->ch_rtime = 10; - ch->ch_flag |= CH_PARAM; - } - } else { - if (ch->ch_rtime != DGRP_RTIME) { - ch->ch_rtime = DGRP_RTIME; - ch->ch_flag |= CH_PARAM; - } - } - - /* - * If a portion of the packet is outside the - * buffer, shorten the effective length of the - * data packet to be the amount of data received. - */ - - if (remain < plen) - dlen -= plen - remain; - - /* - * Detect if receive flush is now complete. - */ - - if ((ch->ch_flag & CH_RX_FLUSH) != 0 && - ((ch->ch_flush_seq - nd->nd_seq_out) & SEQ_MASK) >= - ((nd->nd_seq_in - nd->nd_seq_out) & SEQ_MASK)) { - ch->ch_flag &= ~CH_RX_FLUSH; - } - - /* - * If we are ready to receive, move the data into - * the receive buffer. - */ - - ch->ch_s_rin = (ch->ch_s_rin + dlen) & 0xffff; - - if (ch->ch_state == CS_READY && - (ch->ch_tun.un_open_count != 0) && - (ch->ch_tun.un_flag & UN_CLOSING) == 0 && - (ch->ch_cflag & CF_CREAD) != 0 && - (ch->ch_flag & (CH_BAUD0 | CH_RX_FLUSH)) == 0 && - (ch->ch_send & RR_RX_FLUSH) == 0) { - - if (ch->ch_rin + dlen >= RBUF_MAX) { - n = RBUF_MAX - ch->ch_rin; - - memcpy(ch->ch_rbuf + ch->ch_rin, dbuf, n); - - ch->ch_rin = 0; - dbuf += n; - dlen -= n; - } - - memcpy(ch->ch_rbuf + ch->ch_rin, dbuf, dlen); - - ch->ch_rin += dlen; - - - /* - * If we are not in fastcook mode, or - * if there is a fastcook thread - * waiting for data, send the data to - * the line discipline. - */ - - if ((ch->ch_flag & CH_FAST_READ) == 0 || - ch->ch_inwait != 0) { - dgrp_input(ch); - } - - /* - * If there is a read thread waiting - * in select, and we are in fastcook - * mode, wake him up. - */ - - if (waitqueue_active(&ch->ch_tun.un_tty->read_wait) && - (ch->ch_flag & CH_FAST_READ) != 0) - wake_up_interruptible(&ch->ch_tun.un_tty->read_wait); - - /* - * Wake any thread waiting in the - * fastcook loop. - */ - - if ((ch->ch_flag & CH_INPUT) != 0) { - ch->ch_flag &= ~CH_INPUT; - wake_up_interruptible(&ch->ch_flag_wait); - } - } - - /* - * Fabricate and insert a data packet header to - * preced the remaining data when it comes in. - */ - - if (remain < plen) { - dlen = plen - remain; - b = buf; - - b[0] = 0x90 + n1; - put_unaligned_be16(dlen, b + 1); - - remain = 3; - if (remain > 0 && b != buf) - memcpy(buf, b, remain); - - nd->nd_remain = remain; - return; - } -} - /** * dgrp_receive() -- decode data packets received from the remote PortServer. * @nd: pointer to a node structure @@ -2477,8 +2306,7 @@ static void dgrp_receive(struct nd_struct *nd) plen = dlen + 1; dbuf = b + 1; - handle_data_in_packet(nd, ch, dlen, plen, n1, dbuf); - break; + goto data; /* * Process 2-byte header data packet. @@ -2492,8 +2320,7 @@ static void dgrp_receive(struct nd_struct *nd) plen = dlen + 2; dbuf = b + 2; - handle_data_in_packet(nd, ch, dlen, plen, n1, dbuf); - break; + goto data; /* * Process 3-byte header data packet. @@ -2508,6 +2335,159 @@ static void dgrp_receive(struct nd_struct *nd) dbuf = b + 3; + /* + * Common packet handling code. + */ + +data: + nd->nd_tx_work = 1; + + /* + * Otherwise data should appear only when we are + * in the CS_READY state. + */ + + if (ch->ch_state < CS_READY) { + error = "Data received before RWIN established"; + goto prot_error; + } + + /* + * Assure that the data received is within the + * allowable window. + */ + + n = (ch->ch_s_rwin - ch->ch_s_rin) & 0xffff; + + if (dlen > n) { + error = "Receive data overrun"; + goto prot_error; + } + + /* + * If we received 3 or less characters, + * assume it is a human typing, and set RTIME + * to 10 milliseconds. + * + * If we receive 10 or more characters, + * assume its not a human typing, and set RTIME + * to 100 milliseconds. + */ + + if (ch->ch_edelay != DGRP_RTIME) { + if (ch->ch_rtime != ch->ch_edelay) { + ch->ch_rtime = ch->ch_edelay; + ch->ch_flag |= CH_PARAM; + } + } else if (dlen <= 3) { + if (ch->ch_rtime != 10) { + ch->ch_rtime = 10; + ch->ch_flag |= CH_PARAM; + } + } else { + if (ch->ch_rtime != DGRP_RTIME) { + ch->ch_rtime = DGRP_RTIME; + ch->ch_flag |= CH_PARAM; + } + } + + /* + * If a portion of the packet is outside the + * buffer, shorten the effective length of the + * data packet to be the amount of data received. + */ + + if (remain < plen) + dlen -= plen - remain; + + /* + * Detect if receive flush is now complete. + */ + + if ((ch->ch_flag & CH_RX_FLUSH) != 0 && + ((ch->ch_flush_seq - nd->nd_seq_out) & SEQ_MASK) >= + ((nd->nd_seq_in - nd->nd_seq_out) & SEQ_MASK)) { + ch->ch_flag &= ~CH_RX_FLUSH; + } + + /* + * If we are ready to receive, move the data into + * the receive buffer. + */ + + ch->ch_s_rin = (ch->ch_s_rin + dlen) & 0xffff; + + if (ch->ch_state == CS_READY && + (ch->ch_tun.un_open_count != 0) && + (ch->ch_tun.un_flag & UN_CLOSING) == 0 && + (ch->ch_cflag & CF_CREAD) != 0 && + (ch->ch_flag & (CH_BAUD0 | CH_RX_FLUSH)) == 0 && + (ch->ch_send & RR_RX_FLUSH) == 0) { + + if (ch->ch_rin + dlen >= RBUF_MAX) { + n = RBUF_MAX - ch->ch_rin; + + memcpy(ch->ch_rbuf + ch->ch_rin, dbuf, n); + + ch->ch_rin = 0; + dbuf += n; + dlen -= n; + } + + memcpy(ch->ch_rbuf + ch->ch_rin, dbuf, dlen); + + ch->ch_rin += dlen; + + + /* + * If we are not in fastcook mode, or + * if there is a fastcook thread + * waiting for data, send the data to + * the line discipline. + */ + + if ((ch->ch_flag & CH_FAST_READ) == 0 || + ch->ch_inwait != 0) { + dgrp_input(ch); + } + + /* + * If there is a read thread waiting + * in select, and we are in fastcook + * mode, wake him up. + */ + + if (waitqueue_active(&ch->ch_tun.un_tty->read_wait) && + (ch->ch_flag & CH_FAST_READ) != 0) + wake_up_interruptible(&ch->ch_tun.un_tty->read_wait); + + /* + * Wake any thread waiting in the + * fastcook loop. + */ + + if ((ch->ch_flag & CH_INPUT) != 0) { + ch->ch_flag &= ~CH_INPUT; + + wake_up_interruptible(&ch->ch_flag_wait); + } + } + + /* + * Fabricate and insert a data packet header to + * preced the remaining data when it comes in. + */ + + if (remain < plen) { + dlen = plen - remain; + b = buf; + + b[0] = 0x90 + n1; + put_unaligned_be16(dlen, b + 1); + + remain = 3; + goto done; + } break; /* -- cgit v0.10.2 From d3a874e899b073496d1fe89b6a2d1aa50870874d Mon Sep 17 00:00:00 2001 From: Alexey Khoroshilov Date: Thu, 6 Feb 2014 01:47:13 +0100 Subject: staging: gdm72xx: fix leaks at failure path in gdm_usb_probe() Error handling code in gdm_usb_probe() misses to deallocate tx_ and rx_structs and to do usb_put_dev(). Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/gdm72xx/gdm_usb.c b/drivers/staging/gdm72xx/gdm_usb.c index f8788bf..cdeffe7 100644 --- a/drivers/staging/gdm72xx/gdm_usb.c +++ b/drivers/staging/gdm72xx/gdm_usb.c @@ -635,11 +635,14 @@ static int gdm_usb_probe(struct usb_interface *intf, #endif /* CONFIG_WIMAX_GDM72XX_USB_PM */ ret = register_wimax_device(phy_dev, &intf->dev); + if (ret) + release_usb(udev); out: if (ret) { kfree(phy_dev); kfree(udev); + usb_put_dev(usbdev); } else { usb_set_intfdata(intf, phy_dev); } -- cgit v0.10.2 From 7a081ea20e043f243b6fb9d50448cbe757fbb860 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 6 Feb 2014 23:42:42 +0300 Subject: staging: r8188eu: memory corruption handling long ssids We should cap the SSID length at NDIS_802_11_LENGTH_SSID (32) characters to avoid memory corruption. If the SSID is too long then I have opted to ignore it instead of truncating it. We don't need to clear bssid->Ssid.Ssid[0] because this struct is allocated with rtw_zmalloc() Signed-off-by: Dan Carpenter Acked-by: Larry Finger Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c index 153ec61..96df62f 100644 --- a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c +++ b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c @@ -912,12 +912,12 @@ int rtw_check_bcn_info(struct adapter *Adapter, u8 *pframe, u32 packet_len) unsigned char *pbuf; u32 wpa_ielen = 0; u8 *pbssid = GetAddr3Ptr(pframe); - u32 hidden_ssid = 0; struct HT_info_element *pht_info = NULL; struct rtw_ieee80211_ht_cap *pht_cap = NULL; u32 bcn_channel; unsigned short ht_cap_info; unsigned char ht_info_infos_0; + int ssid_len; if (is_client_associated_to_ap(Adapter) == false) return true; @@ -999,21 +999,15 @@ int rtw_check_bcn_info(struct adapter *Adapter, u8 *pframe, u32 packet_len) } /* checking SSID */ + ssid_len = 0; p = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, _SSID_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_); - if (p == NULL) { - DBG_88E("%s marc: cannot find SSID for survey event\n", __func__); - hidden_ssid = true; - } else { - hidden_ssid = false; - } - - if ((NULL != p) && (false == hidden_ssid && (*(p + 1)))) { - memcpy(bssid->Ssid.Ssid, (p + 2), *(p + 1)); - bssid->Ssid.SsidLength = *(p + 1); - } else { - bssid->Ssid.SsidLength = 0; - bssid->Ssid.Ssid[0] = '\0'; + if (p) { + ssid_len = *(p + 1); + if (ssid_len > NDIS_802_11_LENGTH_SSID) + ssid_len = 0; } + memcpy(bssid->Ssid.Ssid, (p + 2), ssid_len); + bssid->Ssid.SsidLength = ssid_len; RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s bssid.Ssid.Ssid:%s bssid.Ssid.SsidLength:%d " "cur_network->network.Ssid.Ssid:%s len:%d\n", __func__, bssid->Ssid.Ssid, -- cgit v0.10.2 From 1e85c1ea1ff2a60659e790ef8ec76c7339445841 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 5 Feb 2014 14:59:53 -0700 Subject: staging: comedi: adv_pci1710: fix analog output readback value The last value written to a analog output channel is cached in the private data of this driver for readback. Currently, the wrong value is cached in the (*insn_write) functions. The current code stores the data[n] value for readback afer the loop has written all the values. At this time 'n' points past the end of the data array. Fix the functions by using a local variable to hold the data being written to the analog output channel. This variable is then used after the loop is complete to store the readback value. The current value is retrieved before the loop in case no values are actually written.. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Cc: stable Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index 593676c..d9ad2c0 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -494,6 +494,7 @@ static int pci171x_insn_write_ao(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { struct pci1710_private *devpriv = dev->private; + unsigned int val; int n, chan, range, ofs; chan = CR_CHAN(insn->chanspec); @@ -509,11 +510,14 @@ static int pci171x_insn_write_ao(struct comedi_device *dev, outw(devpriv->da_ranges, dev->iobase + PCI171x_DAREF); ofs = PCI171x_DA1; } + val = devpriv->ao_data[chan]; - for (n = 0; n < insn->n; n++) - outw(data[n], dev->iobase + ofs); + for (n = 0; n < insn->n; n++) { + val = data[n]; + outw(val, dev->iobase + ofs); + } - devpriv->ao_data[chan] = data[n]; + devpriv->ao_data[chan] = val; return n; @@ -679,6 +683,7 @@ static int pci1720_insn_write_ao(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { struct pci1710_private *devpriv = dev->private; + unsigned int val; int n, rangereg, chan; chan = CR_CHAN(insn->chanspec); @@ -688,13 +693,15 @@ static int pci1720_insn_write_ao(struct comedi_device *dev, outb(rangereg, dev->iobase + PCI1720_RANGE); devpriv->da_ranges = rangereg; } + val = devpriv->ao_data[chan]; for (n = 0; n < insn->n; n++) { - outw(data[n], dev->iobase + PCI1720_DA0 + (chan << 1)); + val = data[n]; + outw(val, dev->iobase + PCI1720_DA0 + (chan << 1)); outb(0, dev->iobase + PCI1720_SYNCOUT); /* update outputs */ } - devpriv->ao_data[chan] = data[n]; + devpriv->ao_data[chan] = val; return n; } -- cgit v0.10.2 From ac5b705b22642208764aa784ccc47f093d0212b5 Mon Sep 17 00:00:00 2001 From: Prakash Kamliya Date: Tue, 4 Feb 2014 16:08:35 -0800 Subject: staging: android: sync: Signal pt before sync_timeline object gets destroyed There is a race condition Assume we have *one* sync_fence object, with *one* sync_pt which belongs to *one* sync_timeline, given this condition, sync_timeline->kref will have two counts, one for sync_timeline (implicit) and another for sync_pt. Assume following is the situation on CPU Theead-1 : (Thread which calls sync_timeline_destroy()) -> (some function calls) -> sync_timeline_destory() -> sync_timeline_signal() (CPU is inside this function after putting reference to sync_timeline) At this time Thread-2 comes and does following Thread-2 : (fclose on fence fd) > sync_fence_release() -> because of fclose() on fence object -> sync_fence_free() -> sync_pt_free() -> kref_put(&pt->parent->kref, sync_timeline_free); -> sync_timeline_free() (CPU is inside this because this time kref will be zero after _put) Thread-2 will free sync_timeline object before Thread-1 has finished its work inside sync_timeline_signal. With this change we signals all sync_pt before putting reference to sync_timeline object. Cc: Colin Cross Cc: Android Kernel Team Signed-off-by: Prakash Kamliya [jstultz: minor commit subject tweak] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/android/sync.c b/drivers/staging/android/sync.c index b7fcaab..3d05f662 100644 --- a/drivers/staging/android/sync.c +++ b/drivers/staging/android/sync.c @@ -92,14 +92,14 @@ static void sync_timeline_free(struct kref *kref) void sync_timeline_destroy(struct sync_timeline *obj) { obj->destroyed = true; + smp_wmb(); /* - * If this is not the last reference, signal any children - * that their parent is going away. + * signal any children that their parent is going away. */ + sync_timeline_signal(obj); - if (!kref_put(&obj->kref, sync_timeline_free)) - sync_timeline_signal(obj); + kref_put(&obj->kref, sync_timeline_free); } EXPORT_SYMBOL(sync_timeline_destroy); -- cgit v0.10.2 From 8b9e418c013e8b671fc10108ab14243f0657bffd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Dufour=20-=20Idiap=20Research=20Institute?= Date: Fri, 24 Jan 2014 20:57:05 +0100 Subject: staging: lustre: fix quotactl permission denied (LU-4530) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The changes introduced in commit 4b1a25f06b30b203 ("fix build when CONFIG_UIDGID_STRICT_TYPE_CHECKS is on") got the UID check the wrong way around, leading to "Permission denied" when a regular user attempts to retrieve his quota (lfs quota -u ...) but allowing him to retrieve other users quota. Full details at: https://jira.hpdd.intel.com/browse/LU-4530 Cc: Peng Tao Cc: # 3.12.x Cc: # 3.13.x Signed-off-by: Cédric Dufour Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 22d0acc9..52b7731 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -1086,7 +1086,7 @@ static int quotactl_ioctl(struct ll_sb_info *sbi, struct if_quotactl *qctl) break; case Q_GETQUOTA: if (((type == USRQUOTA && - uid_eq(current_euid(), make_kuid(&init_user_ns, id))) || + !uid_eq(current_euid(), make_kuid(&init_user_ns, id))) || (type == GRPQUOTA && !in_egroup_p(make_kgid(&init_user_ns, id)))) && (!cfs_capable(CFS_CAP_SYS_ADMIN) || -- cgit v0.10.2 From 2ed22e3c3bec5b92b9aba4afdef0cc5e6d859a11 Mon Sep 17 00:00:00 2001 From: Matt Rushton Date: Tue, 4 Feb 2014 11:26:12 +0100 Subject: xen-blkback: fix memory leak when persistent grants are used MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently shrink_free_pagepool() is called before the pages used for persistent grants are released via free_persistent_gnts(). This results in a memory leak when a VBD that uses persistent grants is torn down. Cc: Konrad Rzeszutek Wilk Cc: "Roger Pau Monné" Cc: Ian Campbell Reviewed-by: David Vrabel Cc: linux-kernel@vger.kernel.org Cc: xen-devel@lists.xen.org Cc: Anthony Liguori Signed-off-by: Matt Rushton Signed-off-by: Matt Wilson Signed-off-by: Konrad Rzeszutek Wilk diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index 6620b73..30ef7b3 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -625,9 +625,6 @@ purge_gnt_list: print_stats(blkif); } - /* Since we are shutting down remove all pages from the buffer */ - shrink_free_pagepool(blkif, 0 /* All */); - /* Free all persistent grant pages */ if (!RB_EMPTY_ROOT(&blkif->persistent_gnts)) free_persistent_gnts(blkif, &blkif->persistent_gnts, @@ -636,6 +633,9 @@ purge_gnt_list: BUG_ON(!RB_EMPTY_ROOT(&blkif->persistent_gnts)); blkif->persistent_gnt_c = 0; + /* Since we are shutting down remove all pages from the buffer */ + shrink_free_pagepool(blkif, 0 /* All */); + if (log_stats) print_stats(blkif); -- cgit v0.10.2 From ef753411339eae46b9a3151906901f8bfd12b0f1 Mon Sep 17 00:00:00 2001 From: Roger Pau Monne Date: Tue, 4 Feb 2014 11:26:13 +0100 Subject: xen-blkback: fix memory leaks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I've at least identified two possible memory leaks in blkback, both related to the shutdown path of a VBD: - blkback doesn't wait for any pending purge work to finish before cleaning the list of free_pages. The purge work will call put_free_pages and thus we might end up with pages being added to the free_pages list after we have emptied it. Fix this by making sure there's no pending purge work before exiting xen_blkif_schedule, and moving the free_page cleanup code to xen_blkif_free. - blkback doesn't wait for pending requests to end before cleaning persistent grants and the list of free_pages. Again this can add pages to the free_pages list or persistent grants to the persistent_gnts red-black tree. Fixed by moving the persistent grants and free_pages cleanup code to xen_blkif_free. Also, add some checks in xen_blkif_free to make sure we are cleaning everything. Signed-off-by: Roger Pau Monné Cc: Konrad Rzeszutek Wilk Reviewed-by: David Vrabel Cc: Boris Ostrovsky Tested-by: Matt Rushton Reviewed-by: Matt Rushton Cc: Matt Wilson Cc: Ian Campbell Signed-off-by: Konrad Rzeszutek Wilk diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index 30ef7b3..dcfe49f 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -375,7 +375,7 @@ static void purge_persistent_gnt(struct xen_blkif *blkif) pr_debug(DRV_PFX "Going to purge %u persistent grants\n", num_clean); - INIT_LIST_HEAD(&blkif->persistent_purge_list); + BUG_ON(!list_empty(&blkif->persistent_purge_list)); root = &blkif->persistent_gnts; purge_list: foreach_grant_safe(persistent_gnt, n, root, node) { @@ -625,6 +625,23 @@ purge_gnt_list: print_stats(blkif); } + /* Drain pending purge work */ + flush_work(&blkif->persistent_purge_work); + + if (log_stats) + print_stats(blkif); + + blkif->xenblkd = NULL; + xen_blkif_put(blkif); + + return 0; +} + +/* + * Remove persistent grants and empty the pool of free pages + */ +void xen_blkbk_free_caches(struct xen_blkif *blkif) +{ /* Free all persistent grant pages */ if (!RB_EMPTY_ROOT(&blkif->persistent_gnts)) free_persistent_gnts(blkif, &blkif->persistent_gnts, @@ -635,14 +652,6 @@ purge_gnt_list: /* Since we are shutting down remove all pages from the buffer */ shrink_free_pagepool(blkif, 0 /* All */); - - if (log_stats) - print_stats(blkif); - - blkif->xenblkd = NULL; - xen_blkif_put(blkif); - - return 0; } /* diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h index 8d88075..f733d76 100644 --- a/drivers/block/xen-blkback/common.h +++ b/drivers/block/xen-blkback/common.h @@ -376,6 +376,7 @@ int xen_blkif_xenbus_init(void); irqreturn_t xen_blkif_be_int(int irq, void *dev_id); int xen_blkif_schedule(void *arg); int xen_blkif_purge_persistent(void *arg); +void xen_blkbk_free_caches(struct xen_blkif *blkif); int xen_blkbk_flush_diskcache(struct xenbus_transaction xbt, struct backend_info *be, int state); diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c index c2014a0..8afef67 100644 --- a/drivers/block/xen-blkback/xenbus.c +++ b/drivers/block/xen-blkback/xenbus.c @@ -125,6 +125,7 @@ static struct xen_blkif *xen_blkif_alloc(domid_t domid) blkif->persistent_gnts.rb_node = NULL; spin_lock_init(&blkif->free_pages_lock); INIT_LIST_HEAD(&blkif->free_pages); + INIT_LIST_HEAD(&blkif->persistent_purge_list); blkif->free_pages_num = 0; atomic_set(&blkif->persistent_gnt_in_use, 0); @@ -259,6 +260,17 @@ static void xen_blkif_free(struct xen_blkif *blkif) if (!atomic_dec_and_test(&blkif->refcnt)) BUG(); + /* Remove all persistent grants and the cache of ballooned pages. */ + xen_blkbk_free_caches(blkif); + + /* Make sure everything is drained before shutting down */ + BUG_ON(blkif->persistent_gnt_c != 0); + BUG_ON(atomic_read(&blkif->persistent_gnt_in_use) != 0); + BUG_ON(blkif->free_pages_num != 0); + BUG_ON(!list_empty(&blkif->persistent_purge_list)); + BUG_ON(!list_empty(&blkif->free_pages)); + BUG_ON(!RB_EMPTY_ROOT(&blkif->persistent_gnts)); + /* Check that there is no request in use */ list_for_each_entry_safe(req, n, &blkif->pending_free, free_list) { list_del(&req->free_list); -- cgit v0.10.2 From c05f3e3c85df1d89673e00cee7ece5ae4eb4c6ec Mon Sep 17 00:00:00 2001 From: Roger Pau Monne Date: Tue, 4 Feb 2014 11:26:14 +0100 Subject: xen-blkback: fix shutdown race MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce a new variable to keep track of the number of in-flight requests. We need to make sure that when xen_blkif_put is called the request has already been freed and we can safely free xen_blkif, which was not the case before. Signed-off-by: Roger Pau Monné Cc: Konrad Rzeszutek Wilk Cc: David Vrabel Reviewed-by: Boris Ostrovsky Tested-by: Matt Rushton Reviewed-by: Matt Rushton Cc: Matt Wilson Cc: Ian Campbell Signed-off-by: Konrad Rzeszutek Wilk diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index dcfe49f..394fa2e 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -943,9 +943,7 @@ static void xen_blk_drain_io(struct xen_blkif *blkif) { atomic_set(&blkif->drain, 1); do { - /* The initial value is one, and one refcnt taken at the - * start of the xen_blkif_schedule thread. */ - if (atomic_read(&blkif->refcnt) <= 2) + if (atomic_read(&blkif->inflight) == 0) break; wait_for_completion_interruptible_timeout( &blkif->drain_complete, HZ); @@ -985,17 +983,30 @@ static void __end_block_io_op(struct pending_req *pending_req, int error) * the proper response on the ring. */ if (atomic_dec_and_test(&pending_req->pendcnt)) { - xen_blkbk_unmap(pending_req->blkif, + struct xen_blkif *blkif = pending_req->blkif; + + xen_blkbk_unmap(blkif, pending_req->segments, pending_req->nr_pages); - make_response(pending_req->blkif, pending_req->id, + make_response(blkif, pending_req->id, pending_req->operation, pending_req->status); - xen_blkif_put(pending_req->blkif); - if (atomic_read(&pending_req->blkif->refcnt) <= 2) { - if (atomic_read(&pending_req->blkif->drain)) - complete(&pending_req->blkif->drain_complete); + free_req(blkif, pending_req); + /* + * Make sure the request is freed before releasing blkif, + * or there could be a race between free_req and the + * cleanup done in xen_blkif_free during shutdown. + * + * NB: The fact that we might try to wake up pending_free_wq + * before drain_complete (in case there's a drain going on) + * it's not a problem with our current implementation + * because we can assure there's no thread waiting on + * pending_free_wq if there's a drain going on, but it has + * to be taken into account if the current model is changed. + */ + if (atomic_dec_and_test(&blkif->inflight) && atomic_read(&blkif->drain)) { + complete(&blkif->drain_complete); } - free_req(pending_req->blkif, pending_req); + xen_blkif_put(blkif); } } @@ -1249,6 +1260,7 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif, * below (in "!bio") if we are handling a BLKIF_OP_DISCARD. */ xen_blkif_get(blkif); + atomic_inc(&blkif->inflight); for (i = 0; i < nseg; i++) { while ((bio == NULL) || diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h index f733d76..e40326a 100644 --- a/drivers/block/xen-blkback/common.h +++ b/drivers/block/xen-blkback/common.h @@ -278,6 +278,7 @@ struct xen_blkif { /* for barrier (drain) requests */ struct completion drain_complete; atomic_t drain; + atomic_t inflight; /* One thread per one blkif. */ struct task_struct *xenblkd; unsigned int waiting_reqs; diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c index 8afef67..84973c6 100644 --- a/drivers/block/xen-blkback/xenbus.c +++ b/drivers/block/xen-blkback/xenbus.c @@ -128,6 +128,7 @@ static struct xen_blkif *xen_blkif_alloc(domid_t domid) INIT_LIST_HEAD(&blkif->persistent_purge_list); blkif->free_pages_num = 0; atomic_set(&blkif->persistent_gnt_in_use, 0); + atomic_set(&blkif->inflight, 0); INIT_LIST_HEAD(&blkif->pending_free); -- cgit v0.10.2 From 80bfa2f6e2e81049fc6cd3bfaeedcb64db3a9ba6 Mon Sep 17 00:00:00 2001 From: Roger Pau Monne Date: Tue, 4 Feb 2014 11:26:15 +0100 Subject: xen-blkif: drop struct blkif_request_segment_aligned MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This was wrongly introduced in commit 402b27f9, the only difference between blkif_request_segment_aligned and blkif_request_segment is that the former has a named padding, while both share the same memory layout. Also correct a few minor glitches in the description, including for it to no longer assume PAGE_SIZE == 4096. Signed-off-by: Roger Pau Monné [Description fix by Jan Beulich] Signed-off-by: Jan Beulich Reported-by: Jan Beulich Cc: Konrad Rzeszutek Wilk Cc: David Vrabel Cc: Boris Ostrovsky Tested-by: Matt Rushton Cc: Matt Wilson Signed-off-by: Konrad Rzeszutek Wilk diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index 394fa2e..e612627 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -847,7 +847,7 @@ static int xen_blkbk_parse_indirect(struct blkif_request *req, struct grant_page **pages = pending_req->indirect_pages; struct xen_blkif *blkif = pending_req->blkif; int indirect_grefs, rc, n, nseg, i; - struct blkif_request_segment_aligned *segments = NULL; + struct blkif_request_segment *segments = NULL; nseg = pending_req->nr_pages; indirect_grefs = INDIRECT_PAGES(nseg); diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h index e40326a..9eb34e2 100644 --- a/drivers/block/xen-blkback/common.h +++ b/drivers/block/xen-blkback/common.h @@ -57,7 +57,7 @@ #define MAX_INDIRECT_SEGMENTS 256 #define SEGS_PER_INDIRECT_FRAME \ - (PAGE_SIZE/sizeof(struct blkif_request_segment_aligned)) + (PAGE_SIZE/sizeof(struct blkif_request_segment)) #define MAX_INDIRECT_PAGES \ ((MAX_INDIRECT_SEGMENTS + SEGS_PER_INDIRECT_FRAME - 1)/SEGS_PER_INDIRECT_FRAME) #define INDIRECT_PAGES(_segs) \ diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index c4a4c90..7d09dfc 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -162,7 +162,7 @@ static DEFINE_SPINLOCK(minor_lock); #define DEV_NAME "xvd" /* name in /dev */ #define SEGS_PER_INDIRECT_FRAME \ - (PAGE_SIZE/sizeof(struct blkif_request_segment_aligned)) + (PAGE_SIZE/sizeof(struct blkif_request_segment)) #define INDIRECT_GREFS(_segs) \ ((_segs + SEGS_PER_INDIRECT_FRAME - 1)/SEGS_PER_INDIRECT_FRAME) @@ -393,7 +393,7 @@ static int blkif_queue_request(struct request *req) unsigned long id; unsigned int fsect, lsect; int i, ref, n; - struct blkif_request_segment_aligned *segments = NULL; + struct blkif_request_segment *segments = NULL; /* * Used to store if we are able to queue the request by just using @@ -550,7 +550,7 @@ static int blkif_queue_request(struct request *req) } else { n = i % SEGS_PER_INDIRECT_FRAME; segments[n] = - (struct blkif_request_segment_aligned) { + (struct blkif_request_segment) { .gref = ref, .first_sect = fsect, .last_sect = lsect }; diff --git a/include/xen/interface/io/blkif.h b/include/xen/interface/io/blkif.h index ae665ac..32ec05a 100644 --- a/include/xen/interface/io/blkif.h +++ b/include/xen/interface/io/blkif.h @@ -113,13 +113,13 @@ typedef uint64_t blkif_sector_t; * it's less than the number provided by the backend. The indirect_grefs field * in blkif_request_indirect should be filled by the frontend with the * grant references of the pages that are holding the indirect segments. - * This pages are filled with an array of blkif_request_segment_aligned - * that hold the information about the segments. The number of indirect - * pages to use is determined by the maximum number of segments - * a indirect request contains. Every indirect page can contain a maximum - * of 512 segments (PAGE_SIZE/sizeof(blkif_request_segment_aligned)), - * so to calculate the number of indirect pages to use we have to do - * ceil(indirect_segments/512). + * These pages are filled with an array of blkif_request_segment that hold the + * information about the segments. The number of indirect pages to use is + * determined by the number of segments an indirect request contains. Every + * indirect page can contain a maximum of + * (PAGE_SIZE / sizeof(struct blkif_request_segment)) segments, so to + * calculate the number of indirect pages to use we have to do + * ceil(indirect_segments / (PAGE_SIZE / sizeof(struct blkif_request_segment))). * * If a backend does not recognize BLKIF_OP_INDIRECT, it should *not* * create the "feature-max-indirect-segments" node! @@ -135,13 +135,12 @@ typedef uint64_t blkif_sector_t; #define BLKIF_MAX_INDIRECT_PAGES_PER_REQUEST 8 -struct blkif_request_segment_aligned { - grant_ref_t gref; /* reference to I/O buffer frame */ - /* @first_sect: first sector in frame to transfer (inclusive). */ - /* @last_sect: last sector in frame to transfer (inclusive). */ - uint8_t first_sect, last_sect; - uint16_t _pad; /* padding to make it 8 bytes, so it's cache-aligned */ -} __attribute__((__packed__)); +struct blkif_request_segment { + grant_ref_t gref; /* reference to I/O buffer frame */ + /* @first_sect: first sector in frame to transfer (inclusive). */ + /* @last_sect: last sector in frame to transfer (inclusive). */ + uint8_t first_sect, last_sect; +}; struct blkif_request_rw { uint8_t nr_segments; /* number of segments */ @@ -151,12 +150,7 @@ struct blkif_request_rw { #endif uint64_t id; /* private guest value, echoed in resp */ blkif_sector_t sector_number;/* start sector idx on disk (r/w only) */ - struct blkif_request_segment { - grant_ref_t gref; /* reference to I/O buffer frame */ - /* @first_sect: first sector in frame to transfer (inclusive). */ - /* @last_sect: last sector in frame to transfer (inclusive). */ - uint8_t first_sect, last_sect; - } seg[BLKIF_MAX_SEGMENTS_PER_REQUEST]; + struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST]; } __attribute__((__packed__)); struct blkif_request_discard { -- cgit v0.10.2 From 3661371701e714f0cea4120f6a365340858fb4e4 Mon Sep 17 00:00:00 2001 From: David Vrabel Date: Tue, 4 Feb 2014 18:53:56 +0000 Subject: xen-blkfront: handle backend CLOSED without CLOSING Backend drivers shouldn't transistion to CLOSED unless the frontend is CLOSED. If a backend does transition to CLOSED too soon then the frontend may not see the CLOSING state and will not properly shutdown. So, treat an unexpected backend CLOSED state the same as CLOSING. Signed-off-by: David Vrabel Acked-by: Konrad Rzeszutek Wilk Cc: stable@vger.kernel.org Signed-off-by: Konrad Rzeszutek Wilk diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 7d09dfc..76e5c0b 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -1904,13 +1904,16 @@ static void blkback_changed(struct xenbus_device *dev, case XenbusStateReconfiguring: case XenbusStateReconfigured: case XenbusStateUnknown: - case XenbusStateClosed: break; case XenbusStateConnected: blkfront_connect(info); break; + case XenbusStateClosed: + if (dev->state == XenbusStateClosed) + break; + /* Missed the backend's Closing state -- fallthrough */ case XenbusStateClosing: blkfront_closing(info); break; -- cgit v0.10.2 From 72a0a36e2854a6eadb4cf2561858f613f9cd4639 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 7 Feb 2014 10:22:36 -0800 Subject: blk-mq: support at_head inserations for blk_execute_rq This is neede for proper SG_IO operation as well as various uses of blk_execute_rq from the SCSI midlayer. Signed-off-by: Christoph Hellwig Signed-off-by: Jens Axboe diff --git a/block/blk-exec.c b/block/blk-exec.c index bbfc072..c68613b 100644 --- a/block/blk-exec.c +++ b/block/blk-exec.c @@ -65,7 +65,7 @@ void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk, * be resued after dying flag is set */ if (q->mq_ops) { - blk_mq_insert_request(q, rq, true); + blk_mq_insert_request(q, rq, at_head, true); return; } diff --git a/block/blk-mq.c b/block/blk-mq.c index 9072d0a..c9306e3 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -714,13 +714,16 @@ static void blk_mq_work_fn(struct work_struct *work) } static void __blk_mq_insert_request(struct blk_mq_hw_ctx *hctx, - struct request *rq) + struct request *rq, bool at_head) { struct blk_mq_ctx *ctx = rq->mq_ctx; trace_block_rq_insert(hctx->queue, rq); - list_add_tail(&rq->queuelist, &ctx->rq_list); + if (at_head) + list_add(&rq->queuelist, &ctx->rq_list); + else + list_add_tail(&rq->queuelist, &ctx->rq_list); blk_mq_hctx_mark_pending(hctx, ctx); /* @@ -730,7 +733,7 @@ static void __blk_mq_insert_request(struct blk_mq_hw_ctx *hctx, } void blk_mq_insert_request(struct request_queue *q, struct request *rq, - bool run_queue) + bool at_head, bool run_queue) { struct blk_mq_hw_ctx *hctx; struct blk_mq_ctx *ctx, *current_ctx; @@ -749,7 +752,7 @@ void blk_mq_insert_request(struct request_queue *q, struct request *rq, rq->mq_ctx = ctx; } spin_lock(&ctx->lock); - __blk_mq_insert_request(hctx, rq); + __blk_mq_insert_request(hctx, rq, at_head); spin_unlock(&ctx->lock); blk_mq_put_ctx(current_ctx); @@ -781,7 +784,7 @@ void blk_mq_run_request(struct request *rq, bool run_queue, bool async) /* ctx->cpu might be offline */ spin_lock(&ctx->lock); - __blk_mq_insert_request(hctx, rq); + __blk_mq_insert_request(hctx, rq, false); spin_unlock(&ctx->lock); blk_mq_put_ctx(current_ctx); @@ -819,7 +822,7 @@ static void blk_mq_insert_requests(struct request_queue *q, rq = list_first_entry(list, struct request, queuelist); list_del_init(&rq->queuelist); rq->mq_ctx = ctx; - __blk_mq_insert_request(hctx, rq); + __blk_mq_insert_request(hctx, rq, false); } spin_unlock(&ctx->lock); @@ -971,7 +974,7 @@ static void blk_mq_make_request(struct request_queue *q, struct bio *bio) __blk_mq_free_request(hctx, ctx, rq); else { blk_mq_bio_to_request(rq, bio); - __blk_mq_insert_request(hctx, rq); + __blk_mq_insert_request(hctx, rq, false); } spin_unlock(&ctx->lock); diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h index 1e8f16f..b7638be 100644 --- a/include/linux/blk-mq.h +++ b/include/linux/blk-mq.h @@ -122,7 +122,8 @@ void blk_mq_init_commands(struct request_queue *, void (*init)(void *data, struc void blk_mq_flush_plug_list(struct blk_plug *plug, bool from_schedule); -void blk_mq_insert_request(struct request_queue *, struct request *, bool); +void blk_mq_insert_request(struct request_queue *, struct request *, + bool, bool); void blk_mq_run_queues(struct request_queue *q, bool async); void blk_mq_free_request(struct request *rq); bool blk_mq_can_queue(struct blk_mq_hw_ctx *); -- cgit v0.10.2 From 6f5ba581c0d3ba0a76fe138123c1c2817ffcbeb1 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 7 Feb 2014 10:22:37 -0800 Subject: blk-mq: divert __blk_put_request for MQ ops __blk_put_request needs to call into the blk-mq code just like blk_put_request. As we don't have the queue lock in this case both end up calling the same function. Signed-off-by: Christoph Hellwig Signed-off-by: Jens Axboe diff --git a/block/blk-core.c b/block/blk-core.c index c00e0bd..06636f3 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -1278,6 +1278,11 @@ void __blk_put_request(struct request_queue *q, struct request *req) if (unlikely(!q)) return; + if (q->mq_ops) { + blk_mq_free_request(req); + return; + } + blk_pm_put_request(req); elv_completed_request(q, req); -- cgit v0.10.2 From 4f7f418c4835d3ce1b66d00502df41f324d13ec0 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 7 Feb 2014 10:22:38 -0800 Subject: blk-mq: handle dma_drain_size Make blk-mq handle the dma_drain_size field the same way as the old request path. Signed-off-by: Christoph Hellwig Signed-off-by: Jens Axboe diff --git a/block/blk-mq.c b/block/blk-mq.c index c9306e3..a99bea4 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -582,6 +582,16 @@ static void __blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx) list_del_init(&rq->queuelist); blk_mq_start_request(rq); + if (q->dma_drain_size && blk_rq_bytes(rq)) { + /* + * make sure space for the drain appears we + * know we can do this because max_hw_segments + * has been adjusted to be one fewer than the + * device can handle + */ + rq->nr_phys_segments++; + } + /* * Last request in the series. Flag it as such, this * enables drivers to know when IO should be kicked off, -- cgit v0.10.2 From 1be036e9464032362def6b3c13f57bfceefe2dab Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 7 Feb 2014 10:22:39 -0800 Subject: blk-mq: initialize sg_reserved_size To behave the same way as the old request path. Signed-off-by: Christoph Hellwig Signed-off-by: Jens Axboe diff --git a/block/blk-mq.c b/block/blk-mq.c index a99bea4..f1e63c2 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -1387,6 +1387,8 @@ struct request_queue *blk_mq_init_queue(struct blk_mq_reg *reg, q->mq_ops = reg->ops; q->queue_flags |= QUEUE_FLAG_MQ_DEFAULT; + q->sg_reserved_size = INT_MAX; + blk_queue_make_request(q, blk_mq_make_request); blk_queue_rq_timed_out(q, reg->ops->timeout); if (reg->timeout) -- cgit v0.10.2 From 630127f36784e59e995c206c37825a36a34d346c Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 20 Jan 2014 13:30:01 +0300 Subject: staging: android: ion: dummy: fix an error code We should be returning -ENOMEM here instead of zero. Signed-off-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/android/ion/ion_dummy_driver.c b/drivers/staging/android/ion/ion_dummy_driver.c index df8228b..01cdc8a 100644 --- a/drivers/staging/android/ion/ion_dummy_driver.c +++ b/drivers/staging/android/ion/ion_dummy_driver.c @@ -71,7 +71,7 @@ static int __init ion_dummy_init(void) heaps = kzalloc(sizeof(struct ion_heap *) * dummy_ion_pdata.nr, GFP_KERNEL); if (!heaps) - return PTR_ERR(heaps); + return -ENOMEM; /* Allocate a dummy carveout heap */ -- cgit v0.10.2 From f1ffdfcc52744ed264041741020364cfbad9c0de Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 21 Jan 2014 17:06:34 +0000 Subject: staging: comedi: fix too early cleanup in comedi_auto_config() `comedi_auto_config()` is usually called from the probe routine of a low-level comedi driver to allocate and auto-configure a comedi device. Part of this involves calling the low-level driver's `auto_attach()` handler, and if that is successful, `comedi_device_postconfig()` tries to complete the configuration of the comedi device. If either of those fail, `comedi_device_detach()` is called to clean up, and `comedi_release_hardware_device()` is called to remove the dynamically allocated comedi device. Unfortunately, `comedi_device_detach()` clears the `hw_dev` member of the `struct comedi_device` (indirectly via `comedi_clear_hw_dev()`), and that stops `comedi_release_hardware_device()` finding the comedi device associated with the hardware device, so the comedi device won't be removed properly. Since `comedi_release_hardware_device()` also calls `comedi_device_detach()` (assuming it finds the comedi device associated with the hardware device), the fix is to remove the direct call to `comedi_device_detach()` from `comedi_auto_config()` and let the call to `comedi_release_hardware_device()` take care of it. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c index 2460803..5b15033 100644 --- a/drivers/staging/comedi/drivers.c +++ b/drivers/staging/comedi/drivers.c @@ -616,8 +616,6 @@ int comedi_auto_config(struct device *hardware_device, ret = driver->auto_attach(dev, context); if (ret >= 0) ret = comedi_device_postconfig(dev); - if (ret < 0) - comedi_device_detach(dev); mutex_unlock(&dev->mutex); if (ret < 0) { -- cgit v0.10.2 From 791771e4e0587652e193ac8920e14911045a1dc8 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 21 Jan 2014 17:39:05 +0000 Subject: staging: comedi: usbduxsigma: fix unaligned dereferences There are a couple of dereferences such as `*(uint32_t *)(devpriv->insn_buf + 1)` that are unaligned as `devpriv->insn_buf` is of type `uint8_t *`. This works on x86 architecture but may not be supported on other architectures. Call `get_unalign()` to perform the unaligned dereferences. Signed-off-by: Ian Abbott Cc: Bernd Porr Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c index 3beeb12..88c60b6 100644 --- a/drivers/staging/comedi/drivers/usbduxsigma.c +++ b/drivers/staging/comedi/drivers/usbduxsigma.c @@ -48,6 +48,7 @@ #include #include #include +#include #include "comedi_fc.h" #include "../comedidev.h" @@ -792,7 +793,8 @@ static int usbduxsigma_ai_insn_read(struct comedi_device *dev, } /* 32 bits big endian from the A/D converter */ - val = be32_to_cpu(*((uint32_t *)((devpriv->insn_buf) + 1))); + val = be32_to_cpu(get_unaligned((uint32_t + *)(devpriv->insn_buf + 1))); val &= 0x00ffffff; /* strip status byte */ val ^= 0x00800000; /* convert to unsigned */ @@ -1357,7 +1359,7 @@ static int usbduxsigma_getstatusinfo(struct comedi_device *dev, int chan) return ret; /* 32 bits big endian from the A/D converter */ - val = be32_to_cpu(*((uint32_t *)((devpriv->insn_buf)+1))); + val = be32_to_cpu(get_unaligned((uint32_t *)(devpriv->insn_buf + 1))); val &= 0x00ffffff; /* strip status byte */ val ^= 0x00800000; /* convert to unsigned */ -- cgit v0.10.2 From 54de9af9f0d7a91e898b6e02199be16dc26a4870 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 22 Jan 2014 17:20:03 +0300 Subject: gpu: ion: dereferencing an ERR_PTR We dereference "heap->task" before checking if it's an ERR_PTR. Fixes: ea313b5f88ed ('gpu: ion: Also shrink memory cached in the deferred free list') Signed-off-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index 296c74f..37e64d5 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -243,12 +243,12 @@ int ion_heap_init_deferred_free(struct ion_heap *heap) init_waitqueue_head(&heap->waitqueue); heap->task = kthread_run(ion_heap_deferred_free, heap, "%s", heap->name); - sched_setscheduler(heap->task, SCHED_IDLE, ¶m); if (IS_ERR(heap->task)) { pr_err("%s: creating thread for deferred free failed\n", __func__); return PTR_RET(heap->task); } + sched_setscheduler(heap->task, SCHED_IDLE, ¶m); return 0; } -- cgit v0.10.2 From 2a7470d9ffe506ff895f4a27dcf3840cb3ea097f Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Tue, 28 Jan 2014 21:16:46 +0100 Subject: usbip/userspace/libsrc/names.c: memory leak revised patch p is freed if NULL. p is leaked if second calloc fails. Signed-off-by: Heinrich Schuchardt Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/usbip/userspace/libsrc/names.c b/drivers/staging/usbip/userspace/libsrc/names.c index 3c8d28b..81ff852 100644 --- a/drivers/staging/usbip/userspace/libsrc/names.c +++ b/drivers/staging/usbip/userspace/libsrc/names.c @@ -169,14 +169,14 @@ static void *my_malloc(size_t size) struct pool *p; p = calloc(1, sizeof(struct pool)); - if (!p) { - free(p); + if (!p) return NULL; - } p->mem = calloc(1, size); - if (!p->mem) + if (!p->mem) { + free(p); return NULL; + } p->next = pool_head; pool_head = p; -- cgit v0.10.2 From 08951f10ae146d0c4114ac508310ad316b6f8798 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Sun, 2 Feb 2014 22:23:06 -0600 Subject: staging: r8188eu: Fix typo in USB_DEVICE list There is a typo in the device list that interchanges the vendor and product codes for one of the entries. This exchange was determined by noticing that the vendor code is 0x07b8 for Abocom at http://www.linux-usb.org/usb.ids. Signed-off-by: Larry Finger Cc: stable Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c index 0a341d6..a70dcef 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c @@ -53,7 +53,7 @@ static struct usb_device_id rtw_usb_id_tbl[] = { {USB_DEVICE(USB_VENDER_ID_REALTEK, 0x0179)}, /* 8188ETV */ /*=== Customer ID ===*/ /****** 8188EUS ********/ - {USB_DEVICE(0x8179, 0x07B8)}, /* Abocom - Abocom */ + {USB_DEVICE(0x07b8, 0x8179)}, /* Abocom - Abocom */ {USB_DEVICE(0x2001, 0x330F)}, /* DLink DWA-125 REV D1 */ {} /* Terminating entry */ }; -- cgit v0.10.2 From 893134b084e137b92476ec11ce90790b5f568bb9 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 4 Feb 2014 01:38:03 +0300 Subject: staging: r8188eu: array overflow in rtw_mp_ioctl_hdl() MAX_MP_IOCTL_SUBCODE (35) and mp_ioctl_hdl (32 elements) are no longer in sync. It leads to a bogus pointer dereference. Signed-off-by: Dan Carpenter Acked-by: Larry Finger Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c index dec9925..684bc81 100644 --- a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c @@ -2500,7 +2500,7 @@ static int rtw_mp_ioctl_hdl(struct net_device *dev, struct iw_request_info *info ("rtw_mp_ioctl_hdl: subcode [%d], len[%d], buffer_len[%d]\r\n", poidparam->subcode, poidparam->len, len)); - if (poidparam->subcode >= MAX_MP_IOCTL_SUBCODE) { + if (poidparam->subcode >= ARRAY_SIZE(mp_ioctl_hdl)) { RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("no matching drvext subcodes\r\n")); ret = -EINVAL; goto _rtw_mp_ioctl_hdl_exit; -- cgit v0.10.2 From e6ff3f4e6d258021fe041d7acf5d013c26bf387b Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 4 Feb 2014 01:38:35 +0300 Subject: staging: r8188eu: overflow in rtw_p2p_get_go_device_address() The go_devadd_str[] array is two characters too small to hold the address so we corrupt memory. I've changed the user space API slightly and I don't have a way to test if this breaks anything. In the original code we truncated away the last digit of the address and the NUL terminator so it was already a bit broken. Signed-off-by: Dan Carpenter Acked-by: Larry Finger Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c index 684bc81..4ad80ae 100644 --- a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c @@ -3164,9 +3164,7 @@ static int rtw_p2p_get_go_device_address(struct net_device *dev, u8 *p2pie; uint p2pielen = 0, attr_contentlen = 0; u8 attr_content[100] = {0x00}; - - u8 go_devadd_str[17 + 10] = {0x00}; - /* +10 is for the str "go_devadd =", we have to clear it at wrqu->data.pointer */ + u8 go_devadd_str[17 + 12] = {}; /* Commented by Albert 20121209 */ /* The input data is the GO's interface address which the application wants to know its device address. */ @@ -3223,12 +3221,12 @@ static int rtw_p2p_get_go_device_address(struct net_device *dev, spin_unlock_bh(&pmlmepriv->scanned_queue.lock); if (!blnMatch) - sprintf(go_devadd_str, "\n\ndev_add = NULL"); + snprintf(go_devadd_str, sizeof(go_devadd_str), "\n\ndev_add = NULL"); else - sprintf(go_devadd_str, "\n\ndev_add =%.2X:%.2X:%.2X:%.2X:%.2X:%.2X", + snprintf(go_devadd_str, sizeof(go_devadd_str), "\n\ndev_add =%.2X:%.2X:%.2X:%.2X:%.2X:%.2X", attr_content[0], attr_content[1], attr_content[2], attr_content[3], attr_content[4], attr_content[5]); - if (copy_to_user(wrqu->data.pointer, go_devadd_str, 10 + 17)) + if (copy_to_user(wrqu->data.pointer, go_devadd_str, sizeof(go_devadd_str))) return -EFAULT; return ret; } -- cgit v0.10.2 From ad3815a595fd7a5c5e4a24947a56eec29582a505 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Wed, 5 Feb 2014 11:56:43 +0000 Subject: xlr_net: Fix missing trivial allocation check Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/netlogic/xlr_net.c b/drivers/staging/netlogic/xlr_net.c index eedffed..d8ea254 100644 --- a/drivers/staging/netlogic/xlr_net.c +++ b/drivers/staging/netlogic/xlr_net.c @@ -892,6 +892,11 @@ static int xlr_setup_mdio(struct xlr_net_priv *priv, priv->mii_bus->write = xlr_mii_write; priv->mii_bus->parent = &pdev->dev; priv->mii_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL); + if (priv->mii_bus->irq == NULL) { + pr_err("irq alloc failed\n"); + mdiobus_free(priv->mii_bus); + return -ENOMEM; + } priv->mii_bus->irq[priv->phy_addr] = priv->ndev->irq; /* Scan only the enabled address */ -- cgit v0.10.2 From 6b89db36b3ab7c4b99027873e1de4be8d07387d4 Mon Sep 17 00:00:00 2001 From: Maurizio Lombardi Date: Wed, 5 Feb 2014 16:46:56 +0100 Subject: wlags49_h2: Fix overflow in wireless_set_essid() This patch prevents the wireless_set_essid() function from overwriting the last byte of the NetworkName buffer which must be NULL. Signed-off-by: Maurizio Lombardi Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/wlags49_h2/wl_wext.c b/drivers/staging/wlags49_h2/wl_wext.c index 4a1ddaf..187fc06 100644 --- a/drivers/staging/wlags49_h2/wl_wext.c +++ b/drivers/staging/wlags49_h2/wl_wext.c @@ -1061,7 +1061,7 @@ static int wireless_set_essid(struct net_device *dev, struct iw_request_info *in goto out; } - if (data->flags != 0 && data->length > HCF_MAX_NAME_LEN + 1) { + if (data->flags != 0 && data->length > HCF_MAX_NAME_LEN) { ret = -EINVAL; goto out; } -- cgit v0.10.2 From 03b56329f9bb5a1cb73d7dc659d529a9a9bf3acc Mon Sep 17 00:00:00 2001 From: Jan Moskyto Matejka Date: Fri, 7 Feb 2014 19:15:11 +0100 Subject: Modpost: fixed USB alias generation for ranges including 0x9 and 0xA Commit afe2dab4f6 ("USB: add hex/bcd detection to usb modalias generation") changed the routine that generates alias ranges. Before that change, only digits 0-9 were supported; the commit tried to fix the case when the range includes higher values than 0x9. Unfortunately, the commit didn't fix the case when the range includes both 0x9 and 0xA, meaning that the final range must look like [x-9A-y] where x <= 0x9 and y >= 0xA -- instead the [x-9A-x] range was produced. Modprobe doesn't complain as it sees no difference between no-match and bad-pattern results of fnmatch(). Fixing this simple bug to fix the aliases. Also changing the hardcoded beginning of the range to uppercase as all the other letters are also uppercase in the device version numbers. Fortunately, this affects only the dvb-usb-dib0700 module, AFAIK. Signed-off-by: Jan Moskyto Matejka Cc: stable Signed-off-by: Greg Kroah-Hartman diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index 2370863..25e5cb0 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -210,8 +210,8 @@ static void do_usb_entry(void *symval, range_lo < 0x9 ? "[%X-9" : "[%X", range_lo); sprintf(alias + strlen(alias), - range_hi > 0xA ? "a-%X]" : "%X]", - range_lo); + range_hi > 0xA ? "A-%X]" : "%X]", + range_hi); } } if (bcdDevice_initial_digits < (sizeof(bcdDevice_lo) * 2 - 1)) -- cgit v0.10.2 From 14ec77f352cb00ab8425ec2af03bd7e529eefe24 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Fri, 7 Feb 2014 13:45:39 -0700 Subject: blk-mq: Add bio_integrity setup to blk_mq_make_request This patch adds the missing bio_integrity_enabled() + bio_integrity_prep() setup into blk_mq_make_request() in order to use DIF protection with scsi-mq. Cc: Martin K. Petersen Signed-off-by: Nicholas Bellinger Signed-off-by: Jens Axboe diff --git a/block/blk-mq.c b/block/blk-mq.c index f1e63c2..cee9623 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -922,6 +922,11 @@ static void blk_mq_make_request(struct request_queue *q, struct bio *bio) blk_queue_bounce(q, &bio); + if (bio_integrity_enabled(bio) && bio_integrity_prep(bio)) { + bio_endio(bio, -EIO); + return; + } + if (use_plug && blk_attempt_plug_merge(q, bio, &request_count)) return; -- cgit v0.10.2 From 087787959ce851d7bbb19f10f6e9241b7f85a3ca Mon Sep 17 00:00:00 2001 From: "Martin K. Petersen" Date: Thu, 6 Feb 2014 15:14:13 -0500 Subject: block: Fix nr_vecs for inline integrity vectors Commit 9f060e2231ca changed the way we handle allocations for the integrity vectors. When the vectors are inline there is no associated slab and consequently bvec_nr_vecs() returns 0. Ensure that we check against BIP_INLINE_VECS in that case. Reported-by: David Milburn Tested-by: David Milburn Cc: stable@vger.kernel.org # v3.10+ Signed-off-by: Martin K. Petersen Signed-off-by: Jens Axboe diff --git a/fs/bio-integrity.c b/fs/bio-integrity.c index 0bad24d..bcb4a4d 100644 --- a/fs/bio-integrity.c +++ b/fs/bio-integrity.c @@ -114,6 +114,14 @@ void bio_integrity_free(struct bio *bio) } EXPORT_SYMBOL(bio_integrity_free); +static inline unsigned int bip_integrity_vecs(struct bio_integrity_payload *bip) +{ + if (bip->bip_slab == BIO_POOL_NONE) + return BIP_INLINE_VECS; + + return bvec_nr_vecs(bip->bip_slab); +} + /** * bio_integrity_add_page - Attach integrity metadata * @bio: bio to update @@ -129,7 +137,7 @@ int bio_integrity_add_page(struct bio *bio, struct page *page, struct bio_integrity_payload *bip = bio->bi_integrity; struct bio_vec *iv; - if (bip->bip_vcnt >= bvec_nr_vecs(bip->bip_slab)) { + if (bip->bip_vcnt >= bip_integrity_vecs(bip)) { printk(KERN_ERR "%s: bip_vec full\n", __func__); return 0; } -- cgit v0.10.2 From 5cb8850c9c4a7605f74f5c9c7ecadd0b02e87a25 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Fri, 7 Feb 2014 13:53:46 -0700 Subject: block: Explicitly handle discard/write same segments Immutable biovecs changed the way biovecs are interpreted - drivers no longer use bi_vcnt, they have to go by bi_iter.bi_size (to allow for using part of an existing segment without modifying it). This breaks with discards and write_same bios, since for those bi_size has nothing to do with segments in the biovec. So for now, we need a fairly gross hack - we fortunately know that there will never be more than one segment for the entire request, so we can special case discard/write_same. Signed-off-by: Kent Overstreet Tested-by: Hugh Dickins Signed-off-by: Jens Axboe diff --git a/block/blk-merge.c b/block/blk-merge.c index 8f8adaa..6c583f9 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -21,6 +21,16 @@ static unsigned int __blk_recalc_rq_segments(struct request_queue *q, if (!bio) return 0; + /* + * This should probably be returning 0, but blk_add_request_payload() + * (Christoph!!!!) + */ + if (bio->bi_rw & REQ_DISCARD) + return 1; + + if (bio->bi_rw & REQ_WRITE_SAME) + return 1; + fbio = bio; cluster = blk_queue_cluster(q); seg_size = 0; @@ -161,30 +171,60 @@ new_segment: *bvprv = *bvec; } -/* - * map a request to scatterlist, return number of sg entries setup. Caller - * must make sure sg can hold rq->nr_phys_segments entries - */ -int blk_rq_map_sg(struct request_queue *q, struct request *rq, - struct scatterlist *sglist) +static int __blk_bios_map_sg(struct request_queue *q, struct bio *bio, + struct scatterlist *sglist, + struct scatterlist **sg) { struct bio_vec bvec, bvprv = { NULL }; - struct req_iterator iter; - struct scatterlist *sg; + struct bvec_iter iter; int nsegs, cluster; nsegs = 0; cluster = blk_queue_cluster(q); - /* - * for each bio in rq - */ - sg = NULL; - rq_for_each_segment(bvec, rq, iter) { - __blk_segment_map_sg(q, &bvec, sglist, &bvprv, &sg, - &nsegs, &cluster); - } /* segments in rq */ + if (bio->bi_rw & REQ_DISCARD) { + /* + * This is a hack - drivers should be neither modifying the + * biovec, nor relying on bi_vcnt - but because of + * blk_add_request_payload(), a discard bio may or may not have + * a payload we need to set up here (thank you Christoph) and + * bi_vcnt is really the only way of telling if we need to. + */ + + if (bio->bi_vcnt) + goto single_segment; + + return 0; + } + + if (bio->bi_rw & REQ_WRITE_SAME) { +single_segment: + *sg = sglist; + bvec = bio_iovec(bio); + sg_set_page(*sg, bvec.bv_page, bvec.bv_len, bvec.bv_offset); + return 1; + } + + for_each_bio(bio) + bio_for_each_segment(bvec, bio, iter) + __blk_segment_map_sg(q, &bvec, sglist, &bvprv, sg, + &nsegs, &cluster); + return nsegs; +} + +/* + * map a request to scatterlist, return number of sg entries setup. Caller + * must make sure sg can hold rq->nr_phys_segments entries + */ +int blk_rq_map_sg(struct request_queue *q, struct request *rq, + struct scatterlist *sglist) +{ + struct scatterlist *sg = NULL; + int nsegs = 0; + + if (rq->bio) + nsegs = __blk_bios_map_sg(q, rq->bio, sglist, &sg); if (unlikely(rq->cmd_flags & REQ_COPY_USER) && (blk_rq_bytes(rq) & q->dma_pad_mask)) { @@ -230,20 +270,13 @@ EXPORT_SYMBOL(blk_rq_map_sg); int blk_bio_map_sg(struct request_queue *q, struct bio *bio, struct scatterlist *sglist) { - struct bio_vec bvec, bvprv = { NULL }; - struct scatterlist *sg; - int nsegs, cluster; - struct bvec_iter iter; - - nsegs = 0; - cluster = blk_queue_cluster(q); - - sg = NULL; - bio_for_each_segment(bvec, bio, iter) { - __blk_segment_map_sg(q, &bvec, sglist, &bvprv, &sg, - &nsegs, &cluster); - } /* segments in bio */ + struct scatterlist *sg = NULL; + int nsegs; + struct bio *next = bio->bi_next; + bio->bi_next = NULL; + nsegs = __blk_bios_map_sg(q, bio, sglist, &sg); + bio->bi_next = next; if (sg) sg_mark_end(sg); -- cgit v0.10.2 From d7790b928d42597b7da21a4e43080774903e3b5c Mon Sep 17 00:00:00 2001 From: Shlomo Pongratz Date: Thu, 6 Feb 2014 18:33:17 +0200 Subject: block/null_blk: Fix completion processing from LIFO to FIFO The completion queue is implemented using lockless list. The llist_add is adds the events to the list head which is a push operation. The processing of the completion elements is done by disconnecting all the pushed elements and iterating over the disconnected list. The problem is that the processing is done in reverse order w.r.t order of the insertion i.e. LIFO processing. By reversing the disconnected list which is done in linear time the desired FIFO processing is achieved. Signed-off-by: Shlomo Pongratz Signed-off-by: Jens Axboe diff --git a/drivers/block/null_blk.c b/drivers/block/null_blk.c index 3107282..cc801cd 100644 --- a/drivers/block/null_blk.c +++ b/drivers/block/null_blk.c @@ -195,6 +195,7 @@ static enum hrtimer_restart null_cmd_timer_expired(struct hrtimer *timer) cq = &per_cpu(completion_queues, smp_processor_id()); while ((entry = llist_del_all(&cq->list)) != NULL) { + entry = llist_reverse_order(entry); do { cmd = container_of(entry, struct nullb_cmd, ll_list); end_cmd(cmd); @@ -235,6 +236,7 @@ static void null_ipi_cmd_end_io(void *data) cq = &per_cpu(completion_queues, smp_processor_id()); entry = llist_del_all(&cq->list); + entry = llist_reverse_order(entry); while (entry) { next = entry->next; -- cgit v0.10.2 From 247bf557273dd775505fb9240d2d152f4f20d304 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Fri, 31 Jan 2014 11:26:25 -0800 Subject: xhci 1.0: Limit arbitrarily-aligned scatter gather. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit xHCI 1.0 hosts have a set of requirements on how to align transfer buffers on the endpoint rings called "TD fragment" rules. When the ax88179_178a driver added support for scatter gather in 3.12, with commit 804fad45411b48233b48003e33a78f290d227c8 "USBNET: ax88179_178a: enable tso if usb host supports sg dma", it broke the device under xHCI 1.0 hosts. Under certain network loads, the device would see an unexpected short packet from the host, which would cause the device to stop sending ethernet packets, even through USB packets would still be sent. Commit 35773dac5f86 "usb: xhci: Link TRB must not occur within a USB payload burst" attempted to fix this. It was a quick hack to partially implement the TD fragment rules. However, it caused regressions in the usb-storage layer and userspace USB drivers using libusb. The patches to attempt to fix this are too far reaching into the USB core, and we really need to implement the TD fragment rules correctly in the xHCI driver, instead of continuing to wallpaper over the issues. Disable arbitrarily-aligned scatter-gather in the xHCI driver for 1.0 hosts. Only the ax88179_178a driver checks the no_sg_constraint flag, so don't set it for 1.0 hosts. This should not impact usb-storage or usbfs behavior, since they pass down max packet sized aligned sg-list entries (512 for USB 2.0 and 1024 for USB 3.0). Signed-off-by: Sarah Sharp Tested-by: Mark Lord Cc: David Laight Cc: Bjørn Mork Cc: Freddy Xin Cc: Ming Lei Cc: stable@vger.kernel.org # 3.12 diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 3712359..86a2e83 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -4733,9 +4733,6 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) /* Limit the block layer scatter-gather lists to half a segment. */ hcd->self.sg_tablesize = TRBS_PER_SEGMENT / 2; - /* support to build packet from discontinuous buffers */ - hcd->self.no_sg_constraint = 1; - /* XHCI controllers don't stop the ep queue on short packets :| */ hcd->self.no_stop_on_short = 1; @@ -4760,6 +4757,14 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) /* xHCI private pointer was set in xhci_pci_probe for the second * registered roothub. */ + xhci = hcd_to_xhci(hcd); + /* + * Support arbitrarily aligned sg-list entries on hosts without + * TD fragment rules (which are currently unsupported). + */ + if (xhci->hci_version < 0x100) + hcd->self.no_sg_constraint = 1; + return 0; } @@ -4788,6 +4793,9 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) if (xhci->hci_version > 0x96) xhci->quirks |= XHCI_SPURIOUS_SUCCESS; + if (xhci->hci_version < 0x100) + hcd->self.no_sg_constraint = 1; + /* Make sure the HC is halted. */ retval = xhci_halt(xhci); if (retval) -- cgit v0.10.2 From 1386ff75797a187df324062fb4e929152392da88 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Fri, 31 Jan 2014 11:45:02 -0800 Subject: Revert "xhci: Set scatter-gather limit to avoid failed block writes." This reverts commit f2d9b991c549f159dc9ae81f77d8206c790cbfee. We are ripping out commit 35773dac5f862cb1c82ea151eba3e2f6de51ec3e "usb: xhci: Link TRB must not occur within a USB payload burst" because it's a hack that caused regressions in the usb-storage and userspace USB drivers that use usbfs and libusb. This commit attempted to fix the issues with that patch. Signed-off-by: Sarah Sharp Cc: stable@vger.kernel.org #3.12 diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 86a2e83..6fe577d 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -4730,8 +4730,8 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) struct device *dev = hcd->self.controller; int retval; - /* Limit the block layer scatter-gather lists to half a segment. */ - hcd->self.sg_tablesize = TRBS_PER_SEGMENT / 2; + /* Accept arbitrarily long scatter-gather lists */ + hcd->self.sg_tablesize = ~0; /* XHCI controllers don't stop the ep queue on short packets :| */ hcd->self.no_stop_on_short = 1; diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 9154fd6..58ed9d0 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1268,7 +1268,7 @@ union xhci_trb { * since the command ring is 64-byte aligned. * It must also be greater than 16. */ -#define TRBS_PER_SEGMENT 256 +#define TRBS_PER_SEGMENT 64 /* Allow two commands + a link TRB, along with any reserved command TRBs */ #define MAX_RSVD_CMD_TRBS (TRBS_PER_SEGMENT - 3) #define TRB_SEGMENT_SIZE (TRBS_PER_SEGMENT*16) -- cgit v0.10.2 From 9cf00d91708221ff2d8a11143315f7ebab8d5da8 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Fri, 31 Jan 2014 11:51:59 -0800 Subject: Revert "xhci: Avoid infinite loop when sg urb requires too many trbs" This reverts commit d6c9ea9069af684358efedcaf2f2f687f51c58ee. We are ripping out commit 35773dac5f862cb1c82ea151eba3e2f6de51ec3e "usb: xhci: Link TRB must not occur within a USB payload burst" because it's a hack that caused regressions in the usb-storage and userspace USB drivers that use usbfs and libusb. This commit attempted to fix the issues with that patch. Signed-off-by: Sarah Sharp Cc: stable@vger.kernel.org # 3.12 diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 909b32a..0272450 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -3002,7 +3002,7 @@ static int prepare_ring(struct xhci_hcd *xhci, struct xhci_ring *ep_ring, if (num_trbs >= TRBS_PER_SEGMENT) { xhci_err(xhci, "Too many fragments %d, max %d\n", num_trbs, TRBS_PER_SEGMENT - 1); - return -EINVAL; + return -ENOMEM; } nop_cmd = cpu_to_le32(TRB_TYPE(TRB_TR_NOOP) | -- cgit v0.10.2 From 3d4b81eda2211f32886e2978daf6f39885042fc4 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Fri, 31 Jan 2014 11:52:57 -0800 Subject: Revert "usb: xhci: Link TRB must not occur within a USB payload burst" This reverts commit 35773dac5f862cb1c82ea151eba3e2f6de51ec3e. It's a hack that caused regressions in the usb-storage and userspace USB drivers that use usbfs and libusb. Commit 70cabb7d992f "xhci 1.0: Limit arbitrarily-aligned scatter gather." should fix the issues seen with the ax88179_178a driver on xHCI 1.0 hosts, without causing regressions. Signed-off-by: Sarah Sharp Cc: stable@vger.kernel.org # 3.12 diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 0272450..0ed64eb 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -2967,58 +2967,8 @@ static int prepare_ring(struct xhci_hcd *xhci, struct xhci_ring *ep_ring, } while (1) { - if (room_on_ring(xhci, ep_ring, num_trbs)) { - union xhci_trb *trb = ep_ring->enqueue; - unsigned int usable = ep_ring->enq_seg->trbs + - TRBS_PER_SEGMENT - 1 - trb; - u32 nop_cmd; - - /* - * Section 4.11.7.1 TD Fragments states that a link - * TRB must only occur at the boundary between - * data bursts (eg 512 bytes for 480M). - * While it is possible to split a large fragment - * we don't know the size yet. - * Simplest solution is to fill the trb before the - * LINK with nop commands. - */ - if (num_trbs == 1 || num_trbs <= usable || usable == 0) - break; - - if (ep_ring->type != TYPE_BULK) - /* - * While isoc transfers might have a buffer that - * crosses a 64k boundary it is unlikely. - * Since we can't add NOPs without generating - * gaps in the traffic just hope it never - * happens at the end of the ring. - * This could be fixed by writing a LINK TRB - * instead of the first NOP - however the - * TRB_TYPE_LINK_LE32() calls would all need - * changing to check the ring length. - */ - break; - - if (num_trbs >= TRBS_PER_SEGMENT) { - xhci_err(xhci, "Too many fragments %d, max %d\n", - num_trbs, TRBS_PER_SEGMENT - 1); - return -ENOMEM; - } - - nop_cmd = cpu_to_le32(TRB_TYPE(TRB_TR_NOOP) | - ep_ring->cycle_state); - ep_ring->num_trbs_free -= usable; - do { - trb->generic.field[0] = 0; - trb->generic.field[1] = 0; - trb->generic.field[2] = 0; - trb->generic.field[3] = nop_cmd; - trb++; - } while (--usable); - ep_ring->enqueue = trb; - if (room_on_ring(xhci, ep_ring, num_trbs)) - break; - } + if (room_on_ring(xhci, ep_ring, num_trbs)) + break; if (ep_ring == xhci->cmd_ring) { xhci_err(xhci, "Do not support expand command ring\n"); diff --git a/include/linux/usb.h b/include/linux/usb.h index c716da1..7f6eb85 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -1265,8 +1265,6 @@ typedef void (*usb_complete_t)(struct urb *); * @sg: scatter gather buffer list, the buffer size of each element in * the list (except the last) must be divisible by the endpoint's * max packet size if no_sg_constraint isn't set in 'struct usb_bus' - * (FIXME: scatter-gather under xHCI is broken for periodic transfers. - * Do not use urb->sg for interrupt endpoints for now, only bulk.) * @num_mapped_sgs: (internal) number of mapped sg entries * @num_sgs: number of entries in the sg list * @transfer_buffer_length: How big is transfer_buffer. The transfer may -- cgit v0.10.2 From fa69c87232cd6dac4d7e33e376467724697c43b9 Mon Sep 17 00:00:00 2001 From: Fu Wei Date: Tue, 28 Jan 2014 20:36:44 +0800 Subject: Documentation:Chinese translation of Documentation/arm64/tagged-pointers.txt This is a Chinese translated version of Documentation/arm64/tagged-pointers.txt It is based on the modifications of Documentation/arm64/tagged-pointers.txt in submission: "d50240a5", "374ed9d1". Signed-off-by: Fu Wei Acked-by: Harry Wei Signed-off-by: Greg Kroah-Hartman diff --git a/Documentation/zh_CN/arm64/tagged-pointers.txt b/Documentation/zh_CN/arm64/tagged-pointers.txt new file mode 100644 index 0000000..2664d1b --- /dev/null +++ b/Documentation/zh_CN/arm64/tagged-pointers.txt @@ -0,0 +1,52 @@ +Chinese translated version of Documentation/arm64/tagged-pointers.txt + +If you have any comment or update to the content, please contact the +original document maintainer directly. However, if you have a problem +communicating in English you can also ask the Chinese maintainer for +help. Contact the Chinese maintainer if this translation is outdated +or if there is a problem with the translation. + +Maintainer: Will Deacon +Chinese maintainer: Fu Wei +--------------------------------------------------------------------- +Documentation/arm64/tagged-pointers.txt 的中文翻译 + +如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文 +交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻 +译存在问题,请联系中文版维护者。 + +英文版维护者: Will Deacon +中文版维护者: 傅炜 Fu Wei +中文版翻译者: 傅炜 Fu Wei +中文版校译者: 傅炜 Fu Wei + +以下为正文 +--------------------------------------------------------------------- + Linux 在 AArch64 中带标记的虚拟地址 + ================================= + +作者: Will Deacon +日期: 2013 年 06 月 12 日 + +本文档简述了在 AArch64 地址转换系统中提供的带标记的虚拟地址及其在 +AArch64 Linux 中的潜在用途。 + +内核提供的地址转换表配置使通过 TTBR0 完成的虚拟地址转换(即用户空间 +映射),其虚拟地址的最高 8 位(63:56)会被转换硬件所忽略。这种机制 +让这些位可供应用程序自由使用,其注意事项如下: + + (1) 内核要求所有传递到 EL1 的用户空间地址带有 0x00 标记。 + 这意味着任何携带用户空间虚拟地址的系统调用(syscall) + 参数 *必须* 在陷入内核前使它们的最高字节被清零。 + + (2) 非零标记在传递信号时不被保存。这意味着在应用程序中利用了 + 标记的信号处理函数无法依赖 siginfo_t 的用户空间虚拟 + 地址所携带的包含其内部域信息的标记。此规则的一个例外是 + 当信号是在调试观察点的异常处理程序中产生的,此时标记的 + 信息将被保存。 + + (3) 当使用带标记的指针时需特别留心,因为仅对两个虚拟地址 + 的高字节,C 编译器很可能无法判断它们是不同的。 + +此构架会阻止对带标记的 PC 指针的利用,因此在异常返回时,其高字节 +将被设置成一个为 “55” 的扩展符。 -- cgit v0.10.2 From b0ab8a9030b655e02c5532d1f78b9ba9d9ff4420 Mon Sep 17 00:00:00 2001 From: Fu Wei Date: Tue, 28 Jan 2014 20:28:29 +0800 Subject: Documentation:Update Documentation/zh_CN/arm64/booting.txt This is a update of Chinese documentation: Documentation/zh_CN/arm64/booting.txt It is based on the modifications of Documentation/arm64/booting.txt in submission: "4d5e0b15", "4370eec0", "4fcd6e14". Update maintainer's Email address. Signed-off-by: Fu Wei Acked-by: Harry Wei Signed-off-by: Greg Kroah-Hartman diff --git a/Documentation/zh_CN/arm64/booting.txt b/Documentation/zh_CN/arm64/booting.txt index 28fa325..6f6d956 100644 --- a/Documentation/zh_CN/arm64/booting.txt +++ b/Documentation/zh_CN/arm64/booting.txt @@ -7,7 +7,7 @@ help. Contact the Chinese maintainer if this translation is outdated or if there is a problem with the translation. Maintainer: Will Deacon -Chinese maintainer: Fu Wei +Chinese maintainer: Fu Wei --------------------------------------------------------------------- Documentation/arm64/booting.txt 的中文翻译 @@ -16,9 +16,9 @@ Documentation/arm64/booting.txt 的中文翻译 译存在问题,请联系中文版维护者。 英文版维护者: Will Deacon -中文版维护者: 傅炜 Fu Wei -中文版翻译者: 傅炜 Fu Wei -中文版校译者: 傅炜 Fu Wei +中文版维护者: 傅炜 Fu Wei +中文版翻译者: 傅炜 Fu Wei +中文版校译者: 傅炜 Fu Wei 以下为正文 --------------------------------------------------------------------- @@ -64,8 +64,8 @@ RAM,或可能使用对这个设备已知的 RAM 信息,还可能使用任何 必要性: 强制 -设备树数据块(dtb)大小必须不大于 2 MB,且位于从内核映像起始算起第一个 -512MB 内的 2MB 边界上。这使得内核可以通过初始页表中的单个节描述符来 +设备树数据块(dtb)必须 8 字节对齐,并位于从内核映像起始算起第一个 512MB +内,且不得跨越 2MB 对齐边界。这使得内核可以通过初始页表中的单个节描述符来 映射此数据块。 @@ -84,13 +84,23 @@ AArch64 内核当前没有提供自解压代码,因此如果使用了压缩内 必要性: 强制 -已解压的内核映像包含一个 32 字节的头,内容如下: +已解压的内核映像包含一个 64 字节的头,内容如下: - u32 magic = 0x14000008; /* 跳转到 stext, 小端 */ - u32 res0 = 0; /* 保留 */ + u32 code0; /* 可执行代码 */ + u32 code1; /* 可执行代码 */ u64 text_offset; /* 映像装载偏移 */ + u64 res0 = 0; /* 保留 */ u64 res1 = 0; /* 保留 */ u64 res2 = 0; /* 保留 */ + u64 res3 = 0; /* 保留 */ + u64 res4 = 0; /* 保留 */ + u32 magic = 0x644d5241; /* 魔数, 小端, "ARM\x64" */ + u32 res5 = 0; /* 保留 */ + + +映像头注释: + +- code0/code1 负责跳转到 stext. 映像必须位于系统 RAM 起始处的特定偏移(当前是 0x80000)。系统 RAM 的起始地址必须是以 2MB 对齐的。 @@ -118,9 +128,9 @@ AArch64 内核当前没有提供自解压代码,因此如果使用了压缩内 外部高速缓存(如果存在)必须配置并禁用。 - 架构计时器 - CNTFRQ 必须设定为计时器的频率。 - 如果在 EL1 模式下进入内核,则 CNTHCTL_EL2 中的 EL1PCTEN (bit 0) - 必须置位。 + CNTFRQ 必须设定为计时器的频率,且 CNTVOFF 必须设定为对所有 CPU + 都一致的值。如果在 EL1 模式下进入内核,则 CNTHCTL_EL2 中的 + EL1PCTEN (bit 0) 必须置位。 - 一致性 通过内核启动的所有 CPU 在内核入口地址上必须处于相同的一致性域中。 @@ -131,23 +141,40 @@ AArch64 内核当前没有提供自解压代码,因此如果使用了压缩内 在进入内核映像的异常级中,所有构架中可写的系统寄存器必须通过软件 在一个更高的异常级别下初始化,以防止在 未知 状态下运行。 +以上对于 CPU 模式、高速缓存、MMU、架构计时器、一致性、系统寄存器的 +必要条件描述适用于所有 CPU。所有 CPU 必须在同一异常级别跳入内核。 + 引导装载程序必须在每个 CPU 处于以下状态时跳入内核入口: - 主 CPU 必须直接跳入内核映像的第一条指令。通过此 CPU 传递的设备树 - 数据块必须在每个 CPU 节点中包含以下内容: - - 1、‘enable-method’属性。目前,此字段支持的值仅为字符串“spin-table”。 - - 2、‘cpu-release-addr’标识一个 64-bit、初始化为零的内存位置。 + 数据块必须在每个 CPU 节点中包含一个 ‘enable-method’ 属性,所 + 支持的 enable-method 请见下文。 引导装载程序必须生成这些设备树属性,并在跳入内核入口之前将其插入 数据块。 -- 任何辅助 CPU 必须在内存保留区(通过设备树中的 /memreserve/ 域传递 +- enable-method 为 “spin-table” 的 CPU 必须在它们的 CPU + 节点中包含一个 ‘cpu-release-addr’ 属性。这个属性标识了一个 + 64 位自然对齐且初始化为零的内存位置。 + + 这些 CPU 必须在内存保留区(通过设备树中的 /memreserve/ 域传递 给内核)中自旋于内核之外,轮询它们的 cpu-release-addr 位置(必须 包含在保留区中)。可通过插入 wfe 指令来降低忙循环开销,而主 CPU 将 发出 sev 指令。当对 cpu-release-addr 所指位置的读取操作返回非零值 - 时,CPU 必须直接跳入此值所指向的地址。 + 时,CPU 必须跳入此值所指向的地址。此值为一个单独的 64 位小端值, + 因此 CPU 须在跳转前将所读取的值转换为其本身的端模式。 + +- enable-method 为 “psci” 的 CPU 保持在内核外(比如,在 + memory 节点中描述为内核空间的内存区外,或在通过设备树 /memreserve/ + 域中描述为内核保留区的空间中)。内核将会发起在 ARM 文档(编号 + ARM DEN 0022A:用于 ARM 上的电源状态协调接口系统软件)中描述的 + CPU_ON 调用来将 CPU 带入内核。 + + *译者注:到文档翻译时,此文档已更新为 ARM DEN 0022B。 + + 设备树必须包含一个 ‘psci’ 节点,请参考以下文档: + Documentation/devicetree/bindings/arm/psci.txt + - 辅助 CPU 通用寄存器设置 x0 = 0 (保留,将来可能使用) -- cgit v0.10.2 From d0f2a808b2f0fa6e115cc6f6c84bb4f29aa8af49 Mon Sep 17 00:00:00 2001 From: Fu Wei Date: Tue, 28 Jan 2014 20:14:29 +0800 Subject: Documentation:Update Documentation/zh_CN/arm64/memory.txt This is a update of Chinese documentation:Documentation/zh_CN/arm64/memory.txt It is based on the modifications of Documentation/arm64/memory.txt in submission: "2475ff9d", "847264fb", "aa4a73a0", "e29a074b". Update maintainer's Email address. Signed-off-by: Fu Wei Acked-by: Harry Wei Signed-off-by: Greg Kroah-Hartman diff --git a/Documentation/zh_CN/arm64/memory.txt b/Documentation/zh_CN/arm64/memory.txt index a5f6283..a782704 100644 --- a/Documentation/zh_CN/arm64/memory.txt +++ b/Documentation/zh_CN/arm64/memory.txt @@ -7,7 +7,7 @@ help. Contact the Chinese maintainer if this translation is outdated or if there is a problem with the translation. Maintainer: Catalin Marinas -Chinese maintainer: Fu Wei +Chinese maintainer: Fu Wei --------------------------------------------------------------------- Documentation/arm64/memory.txt 的中文翻译 @@ -16,9 +16,9 @@ Documentation/arm64/memory.txt 的中文翻译 译存在问题,请联系中文版维护者。 英文版维护者: Catalin Marinas -中文版维护者: 傅炜 Fu Wei -中文版翻译者: 傅炜 Fu Wei -中文版校译者: 傅炜 Fu Wei +中文版维护者: 傅炜 Fu Wei +中文版翻译者: 傅炜 Fu Wei +中文版校译者: 傅炜 Fu Wei 以下为正文 --------------------------------------------------------------------- @@ -41,7 +41,7 @@ AArch64 Linux 使用页大小为 4KB 的 3 级转换表配置,对于用户和 TTBR1 中,且从不写入 TTBR0。 -AArch64 Linux 内存布局: +AArch64 Linux 在页大小为 4KB 时的内存布局: 起始地址 结束地址 大小 用途 ----------------------------------------------------------------------- @@ -55,15 +55,42 @@ ffffffbc00000000 ffffffbdffffffff 8GB vmemmap ffffffbe00000000 ffffffbffbbfffff ~8GB [防护页,未来用于 vmmemap] +ffffffbffbc00000 ffffffbffbdfffff 2MB earlyprintk 设备 + ffffffbffbe00000 ffffffbffbe0ffff 64KB PCI I/O 空间 -ffffffbbffff0000 ffffffbcffffffff ~2MB [防护页] +ffffffbffbe10000 ffffffbcffffffff ~2MB [防护页] ffffffbffc000000 ffffffbfffffffff 64MB 模块 ffffffc000000000 ffffffffffffffff 256GB 内核逻辑内存映射 +AArch64 Linux 在页大小为 64KB 时的内存布局: + +起始地址 结束地址 大小 用途 +----------------------------------------------------------------------- +0000000000000000 000003ffffffffff 4TB 用户空间 + +fffffc0000000000 fffffdfbfffeffff ~2TB vmalloc + +fffffdfbffff0000 fffffdfbffffffff 64KB [防护页] + +fffffdfc00000000 fffffdfdffffffff 8GB vmemmap + +fffffdfe00000000 fffffdfffbbfffff ~8GB [防护页,未来用于 vmmemap] + +fffffdfffbc00000 fffffdfffbdfffff 2MB earlyprintk 设备 + +fffffdfffbe00000 fffffdfffbe0ffff 64KB PCI I/O 空间 + +fffffdfffbe10000 fffffdfffbffffff ~2MB [防护页] + +fffffdfffc000000 fffffdffffffffff 64MB 模块 + +fffffe0000000000 ffffffffffffffff 2TB 内核逻辑内存映射 + + 4KB 页大小的转换表查找: +--------+--------+--------+--------+--------+--------+--------+--------+ @@ -91,3 +118,10 @@ ffffffc000000000 ffffffffffffffff 256GB 内核逻辑内存映射 | | +--------------------------> [41:29] L2 索引 (仅使用 38:29 ) | +-------------------------------> [47:42] L1 索引 (未使用) +-------------------------------------------------> [63] TTBR0/1 + +当使用 KVM 时, 管理程序(hypervisor)在 EL2 中通过相对内核虚拟地址的 +一个固定偏移来映射内核页(内核虚拟地址的高 24 位设为零): + +起始地址 结束地址 大小 用途 +----------------------------------------------------------------------- +0000004000000000 0000007fffffffff 256GB 在 HYP 中映射的内核对象 -- cgit v0.10.2 From d913c7439add288b50752186b306634df2ae21e7 Mon Sep 17 00:00:00 2001 From: Christian Engelmayer Date: Sat, 25 Jan 2014 22:47:44 +0100 Subject: misc: genwqe: Fix potential memory leak when pinning memory Fix a memory leak in the genwqe_pin_mem() error path as called by ioctl GENWQE_PIN_MEM. In case there is an error encountered when mapping memory, the already allocated dma_mapping struct needs to be freed correctly. Detected by Coverity: CID 1162606. Signed-off-by: Christian Engelmayer Acked-by: Frank Haverkamp Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/misc/genwqe/card_dev.c b/drivers/misc/genwqe/card_dev.c index 8f8a6b3..2c2c9cc 100644 --- a/drivers/misc/genwqe/card_dev.c +++ b/drivers/misc/genwqe/card_dev.c @@ -787,6 +787,7 @@ static int genwqe_pin_mem(struct genwqe_file *cfile, struct genwqe_mem *m) if (rc != 0) { dev_err(&pci_dev->dev, "[%s] genwqe_user_vmap rc=%d\n", __func__, rc); + kfree(dma_map); return rc; } -- cgit v0.10.2 From f0de8e04a7201a2000f3c6d09732c11e7f35d42d Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Sun, 2 Feb 2014 14:52:05 +0100 Subject: misc: eeprom: sunxi: Add new compatibles The Allwinner A10 compatibles were following a slightly different compatible patterns than the rest of the SoCs for historical reasons. Add compatibles matching the other pattern to the SID driver for consistency, and keep the older one for backward compatibility. Signed-off-by: Maxime Ripard Signed-off-by: Greg Kroah-Hartman diff --git a/Documentation/devicetree/bindings/misc/allwinner,sunxi-sid.txt b/Documentation/devicetree/bindings/misc/allwinner,sunxi-sid.txt index 68ba372..c10a61a 100644 --- a/Documentation/devicetree/bindings/misc/allwinner,sunxi-sid.txt +++ b/Documentation/devicetree/bindings/misc/allwinner,sunxi-sid.txt @@ -1,12 +1,13 @@ Allwinner sunxi-sid Required properties: -- compatible: "allwinner,sun4i-sid" or "allwinner,sun7i-a20-sid". +- compatible: "allwinner,sun4i-a10-sid" or "allwinner,sun7i-a20-sid" + (Deprecated: "allwinner,sun4i-sid"). - reg: Should contain registers location and length Example for sun4i: sid@01c23800 { - compatible = "allwinner,sun4i-sid"; + compatible = "allwinner,sun4i-a10-sid"; reg = <0x01c23800 0x10> }; diff --git a/drivers/misc/eeprom/sunxi_sid.c b/drivers/misc/eeprom/sunxi_sid.c index 9c34e57..e137e75 100644 --- a/drivers/misc/eeprom/sunxi_sid.c +++ b/drivers/misc/eeprom/sunxi_sid.c @@ -96,8 +96,11 @@ static int sunxi_sid_remove(struct platform_device *pdev) } static const struct of_device_id sunxi_sid_of_match[] = { - { .compatible = "allwinner,sun4i-sid", .data = (void *)16}, + { .compatible = "allwinner,sun4i-a10-sid", .data = (void *)16}, { .compatible = "allwinner,sun7i-a20-sid", .data = (void *)512}, + + /* Deprecated */ + { .compatible = "allwinner,sun4i-sid", .data = (void *)16}, {/* sentinel */}, }; MODULE_DEVICE_TABLE(of, sunxi_sid_of_match); -- cgit v0.10.2 From 01ab1167cd2d861d20195eda08505652c536df97 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Sun, 2 Feb 2014 14:52:06 +0100 Subject: ARM: sunxi: dt: Convert to the new SID compatibles Switch the device tree to the new compatibles introduced in the SID drivers to have a common pattern accross all Allwinner SoCs. Signed-off-by: Maxime Ripard Signed-off-by: Greg Kroah-Hartman diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi index 040bb0e..7b10f85 100644 --- a/arch/arm/boot/dts/sun4i-a10.dtsi +++ b/arch/arm/boot/dts/sun4i-a10.dtsi @@ -421,7 +421,7 @@ }; sid: eeprom@01c23800 { - compatible = "allwinner,sun4i-sid"; + compatible = "allwinner,sun4i-a10-sid"; reg = <0x01c23800 0x10>; }; diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi index ea16054..6d287a0 100644 --- a/arch/arm/boot/dts/sun5i-a10s.dtsi +++ b/arch/arm/boot/dts/sun5i-a10s.dtsi @@ -378,7 +378,7 @@ }; sid: eeprom@01c23800 { - compatible = "allwinner,sun4i-sid"; + compatible = "allwinner,sun4i-a10-sid"; reg = <0x01c23800 0x10>; }; diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi index 320335a..f49eb13 100644 --- a/arch/arm/boot/dts/sun5i-a13.dtsi +++ b/arch/arm/boot/dts/sun5i-a13.dtsi @@ -341,7 +341,7 @@ }; sid: eeprom@01c23800 { - compatible = "allwinner,sun4i-sid"; + compatible = "allwinner,sun4i-a10-sid"; reg = <0x01c23800 0x10>; }; -- cgit v0.10.2 From 3b1cc9b9622a022208ec95b1259b05bbdf712eb7 Mon Sep 17 00:00:00 2001 From: Sudeep Dutt Date: Mon, 3 Feb 2014 14:53:19 -0800 Subject: misc: mic: fix possible signed underflow (undefined behavior) in userspace API iovcnt is declared as a signed integer in both the userspace API and as a local variable in mic_virtio.c. The while() loop in mic_virtio.c iterates until the local variable iovcnt reaches the value 0. If userspace passes e.g. INT_MIN as iovcnt field, this loop then appears to depend on an undefined behavior (signed underflow) to complete. The fix is to use unsigned integers in both the userspace API and the local variable. This issue was reported @ https://lkml.org/lkml/2014/1/10/10 Reported-by: Mathieu Desnoyers Reviewed-by: Ashutosh Dixit Signed-off-by: Sudeep Dutt Cc: stable Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/misc/mic/host/mic_virtio.c b/drivers/misc/mic/host/mic_virtio.c index 752ff87..7e1ef0e 100644 --- a/drivers/misc/mic/host/mic_virtio.c +++ b/drivers/misc/mic/host/mic_virtio.c @@ -156,7 +156,8 @@ static int mic_vringh_copy(struct mic_vdev *mvdev, struct vringh_kiov *iov, static int _mic_virtio_copy(struct mic_vdev *mvdev, struct mic_copy_desc *copy) { - int ret = 0, iovcnt = copy->iovcnt; + int ret = 0; + u32 iovcnt = copy->iovcnt; struct iovec iov; struct iovec __user *u_iov = copy->iov; void __user *ubuf = NULL; diff --git a/include/uapi/linux/mic_ioctl.h b/include/uapi/linux/mic_ioctl.h index 7fabba5..feb0b4c 100644 --- a/include/uapi/linux/mic_ioctl.h +++ b/include/uapi/linux/mic_ioctl.h @@ -39,7 +39,7 @@ struct mic_copy_desc { #else struct iovec *iov; #endif - int iovcnt; + __u32 iovcnt; __u8 vr_idx; __u8 update_used; __u32 out_len; -- cgit v0.10.2 From 9e1ccb4a7700fcb3ddfe2767e0bbb6131f8ab54e Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 7 Feb 2014 20:09:27 +0000 Subject: drivers/base: fix devres handling for master device We weren't handling the devres issues for the master device failing a bind, or being unbound properly. Add a devres group to contain these, and release the resources at the appropriate points. Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/base/component.c b/drivers/base/component.c index c53efe6..c477899 100644 --- a/drivers/base/component.c +++ b/drivers/base/component.c @@ -133,9 +133,16 @@ static int try_to_bring_up_master(struct master *master, goto out; } + if (!devres_open_group(master->dev, NULL, GFP_KERNEL)) { + ret = -ENOMEM; + goto out; + } + /* Found all components */ ret = master->ops->bind(master->dev); if (ret < 0) { + devres_release_group(master->dev, NULL); + dev_info(master->dev, "master bind failed: %d\n", ret); master_remove_components(master); goto out; } @@ -166,6 +173,7 @@ static void take_down_master(struct master *master) { if (master->bound) { master->ops->unbind(master->dev); + devres_release_group(master->dev, NULL); master->bound = false; } -- cgit v0.10.2 From 26c8f0d601f5d4c0d9f4bc8c5151539aae5dc26a Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Fri, 7 Feb 2014 11:04:04 -0500 Subject: cifs: use a flexarray in cifs_writedata The cifs_writedata code uses a single element trailing array, which just adds unneeded complexity. Use a flexarray instead. Signed-off-by: Jeff Layton Reviewed-by: Pavel Shilovsky Signed-off-by: Steve French diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 615e35a..d6a031e 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -1068,7 +1068,7 @@ struct cifs_writedata { unsigned int pagesz; unsigned int tailsz; unsigned int nr_pages; - struct page *pages[1]; + struct page *pages[]; }; /* diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 4d881c3..0cd742c 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -1962,15 +1962,9 @@ cifs_writedata_alloc(unsigned int nr_pages, work_func_t complete) { struct cifs_writedata *wdata; - /* this would overflow */ - if (nr_pages == 0) { - cifs_dbg(VFS, "%s: called with nr_pages == 0!\n", __func__); - return NULL; - } - /* writedata + number of page pointers */ wdata = kzalloc(sizeof(*wdata) + - sizeof(struct page *) * (nr_pages - 1), GFP_NOFS); + sizeof(struct page *) * nr_pages, GFP_NOFS); if (wdata != NULL) { kref_init(&wdata->refcount); INIT_LIST_HEAD(&wdata->list); -- cgit v0.10.2 From 4a5c80d7b5615be8098f9d5da97d166afc318abc Mon Sep 17 00:00:00 2001 From: Steve French Date: Fri, 7 Feb 2014 20:45:12 -0600 Subject: [CIFS] clean up page array when uncached write send fails In the event that a send fails in an uncached write, or we end up needing to reissue it (-EAGAIN case), we'll kfree the wdata but the pages currently leak. Fix this by adding a new kref release routine for uncached writedata that releases the pages, and have the uncached codepaths use that. [original patch by Jeff modified to fix minor formatting problems] Signed-off-by: Jeff Layton Reviewed-by: Pavel Shilovsky Signed-off-by: Steve French diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index d6a031e..86dc28c 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -323,7 +323,8 @@ struct smb_version_operations { /* async read from the server */ int (*async_readv)(struct cifs_readdata *); /* async write to the server */ - int (*async_writev)(struct cifs_writedata *); + int (*async_writev)(struct cifs_writedata *, + void (*release)(struct kref *)); /* sync read from the server */ int (*sync_read)(const unsigned int, struct cifsFileInfo *, struct cifs_io_parms *, unsigned int *, char **, diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 79e6e9a..d00e09d 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -488,7 +488,8 @@ void cifs_readdata_release(struct kref *refcount); int cifs_async_readv(struct cifs_readdata *rdata); int cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid); -int cifs_async_writev(struct cifs_writedata *wdata); +int cifs_async_writev(struct cifs_writedata *wdata, + void (*release)(struct kref *kref)); void cifs_writev_complete(struct work_struct *work); struct cifs_writedata *cifs_writedata_alloc(unsigned int nr_pages, work_func_t complete); diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 0cd742c..f3264bd 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -1910,7 +1910,7 @@ cifs_writev_requeue(struct cifs_writedata *wdata) do { server = tlink_tcon(wdata->cfile->tlink)->ses->server; - rc = server->ops->async_writev(wdata); + rc = server->ops->async_writev(wdata, cifs_writedata_release); } while (rc == -EAGAIN); for (i = 0; i < wdata->nr_pages; i++) { @@ -2025,7 +2025,8 @@ cifs_writev_callback(struct mid_q_entry *mid) /* cifs_async_writev - send an async write, and set up mid to handle result */ int -cifs_async_writev(struct cifs_writedata *wdata) +cifs_async_writev(struct cifs_writedata *wdata, + void (*release)(struct kref *kref)) { int rc = -EACCES; WRITE_REQ *smb = NULL; @@ -2099,7 +2100,7 @@ cifs_async_writev(struct cifs_writedata *wdata) if (rc == 0) cifs_stats_inc(&tcon->stats.cifs_stats.num_writes); else - kref_put(&wdata->refcount, cifs_writedata_release); + kref_put(&wdata->refcount, release); async_writev_out: cifs_small_buf_release(smb); diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 853d6d1..a301edb 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -2043,7 +2043,8 @@ retry: } wdata->pid = wdata->cfile->pid; server = tlink_tcon(wdata->cfile->tlink)->ses->server; - rc = server->ops->async_writev(wdata); + rc = server->ops->async_writev(wdata, + cifs_writedata_release); } while (wbc->sync_mode == WB_SYNC_ALL && rc == -EAGAIN); for (i = 0; i < nr_pages; ++i) @@ -2331,9 +2332,20 @@ size_t get_numpages(const size_t wsize, const size_t len, size_t *cur_len) } static void -cifs_uncached_writev_complete(struct work_struct *work) +cifs_uncached_writedata_release(struct kref *refcount) { int i; + struct cifs_writedata *wdata = container_of(refcount, + struct cifs_writedata, refcount); + + for (i = 0; i < wdata->nr_pages; i++) + put_page(wdata->pages[i]); + cifs_writedata_release(refcount); +} + +static void +cifs_uncached_writev_complete(struct work_struct *work) +{ struct cifs_writedata *wdata = container_of(work, struct cifs_writedata, work); struct inode *inode = wdata->cfile->dentry->d_inode; @@ -2347,12 +2359,7 @@ cifs_uncached_writev_complete(struct work_struct *work) complete(&wdata->done); - if (wdata->result != -EAGAIN) { - for (i = 0; i < wdata->nr_pages; i++) - put_page(wdata->pages[i]); - } - - kref_put(&wdata->refcount, cifs_writedata_release); + kref_put(&wdata->refcount, cifs_uncached_writedata_release); } /* attempt to send write to server, retry on any -EAGAIN errors */ @@ -2370,7 +2377,8 @@ cifs_uncached_retry_writev(struct cifs_writedata *wdata) if (rc != 0) continue; } - rc = server->ops->async_writev(wdata); + rc = server->ops->async_writev(wdata, + cifs_uncached_writedata_release); } while (rc == -EAGAIN); return rc; @@ -2454,7 +2462,8 @@ cifs_iovec_write(struct file *file, const struct iovec *iov, wdata->tailsz = cur_len - ((nr_pages - 1) * PAGE_SIZE); rc = cifs_uncached_retry_writev(wdata); if (rc) { - kref_put(&wdata->refcount, cifs_writedata_release); + kref_put(&wdata->refcount, + cifs_uncached_writedata_release); break; } @@ -2496,7 +2505,7 @@ restart_loop: } } list_del_init(&wdata->list); - kref_put(&wdata->refcount, cifs_writedata_release); + kref_put(&wdata->refcount, cifs_uncached_writedata_release); } if (total_written > 0) diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 2013234..a3f7a9c 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -1890,7 +1890,8 @@ smb2_writev_callback(struct mid_q_entry *mid) /* smb2_async_writev - send an async write, and set up mid to handle result */ int -smb2_async_writev(struct cifs_writedata *wdata) +smb2_async_writev(struct cifs_writedata *wdata, + void (*release)(struct kref *kref)) { int rc = -EACCES; struct smb2_write_req *req = NULL; @@ -1938,7 +1939,7 @@ smb2_async_writev(struct cifs_writedata *wdata) smb2_writev_callback, wdata, 0); if (rc) { - kref_put(&wdata->refcount, cifs_writedata_release); + kref_put(&wdata->refcount, release); cifs_stats_fail_inc(tcon, SMB2_WRITE_HE); } diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h index 93adc64..0ce48db 100644 --- a/fs/cifs/smb2proto.h +++ b/fs/cifs/smb2proto.h @@ -123,7 +123,8 @@ extern int SMB2_get_srv_num(const unsigned int xid, struct cifs_tcon *tcon, extern int smb2_async_readv(struct cifs_readdata *rdata); extern int SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms, unsigned int *nbytes, char **buf, int *buf_type); -extern int smb2_async_writev(struct cifs_writedata *wdata); +extern int smb2_async_writev(struct cifs_writedata *wdata, + void (*release)(struct kref *kref)); extern int SMB2_write(const unsigned int xid, struct cifs_io_parms *io_parms, unsigned int *nbytes, struct kvec *iov, int n_vec); extern int SMB2_echo(struct TCP_Server_Info *server); -- cgit v0.10.2 From f25330f63edd8e2d02ca76ed43fc852d4d76bb12 Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Wed, 1 Oct 2014 21:59:00 +0100 Subject: iio:magnetometer:mag3110: Report busy in _read_raw() / write_raw() when buffer is enabled individual reads are not permitted concurrently with buffered reads Signed-off-by: Peter Meerwald Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/magnetometer/mag3110.c b/drivers/iio/magnetometer/mag3110.c index 4b65b6d..b88cb44 100644 --- a/drivers/iio/magnetometer/mag3110.c +++ b/drivers/iio/magnetometer/mag3110.c @@ -154,6 +154,9 @@ static int mag3110_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: + if (iio_buffer_enabled(indio_dev)) + return -EBUSY; + switch (chan->type) { case IIO_MAGN: /* in 0.1 uT / LSB */ ret = mag3110_read(data, buffer); @@ -199,6 +202,9 @@ static int mag3110_write_raw(struct iio_dev *indio_dev, struct mag3110_data *data = iio_priv(indio_dev); int rate; + if (iio_buffer_enabled(indio_dev)) + return -EBUSY; + switch (mask) { case IIO_CHAN_INFO_SAMP_FREQ: rate = mag3110_get_samp_freq_index(data, val, val2); -- cgit v0.10.2 From 71bd89454d4cd6a4d0304aa8c3304ed8b0a294dc Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Wed, 1 Oct 2014 21:59:00 +0100 Subject: iio:magnetometer:mag3110: Fix output of decimal digits in show_int_plus_micros() need to print leading zeros, hence "%d.%06d" Signed-off-by: Peter Meerwald Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/magnetometer/mag3110.c b/drivers/iio/magnetometer/mag3110.c index b88cb44..f66955f 100644 --- a/drivers/iio/magnetometer/mag3110.c +++ b/drivers/iio/magnetometer/mag3110.c @@ -106,7 +106,7 @@ static ssize_t mag3110_show_int_plus_micros(char *buf, while (n-- > 0) len += scnprintf(buf + len, PAGE_SIZE - len, - "%d.%d ", vals[n][0], vals[n][1]); + "%d.%06d ", vals[n][0], vals[n][1]); /* replace trailing space by newline */ buf[len - 1] = '\n'; -- cgit v0.10.2 From d4bf105bb65b61fd9036031a1854383381ef638f Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 13 Jan 2014 16:02:00 +0000 Subject: iio: mxs-lradc: fix buffer overflow Fixes: drivers/staging/iio/adc/mxs-lradc.c:1556 mxs_lradc_probe() error: buffer overflow 'iio->channels' 15 <= 15 The reported available scales for in_voltage15 were also wrong. The realbits lookup is not necessary as all the channels of the LRADC have the same resolution, use LRADC_RESOLUTION instead. Reported-by: Dan Carpenter Signed-off-by: Alexandre Belloni Signed-off-by: Jonathan Cameron diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c index df71669..aa86849 100644 --- a/drivers/staging/iio/adc/mxs-lradc.c +++ b/drivers/staging/iio/adc/mxs-lradc.c @@ -1613,7 +1613,7 @@ static int mxs_lradc_probe(struct platform_device *pdev) * of the array. */ scale_uv = ((u64)lradc->vref_mv[i] * 100000000) >> - (iio->channels[i].scan_type.realbits - s); + (LRADC_RESOLUTION - s); lradc->scale_avail[i][s].nano = do_div(scale_uv, 100000000) * 10; lradc->scale_avail[i][s].integer = scale_uv; -- cgit v0.10.2 From 5af473c17accce1094990d25c5381264433c5fa9 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 13 Jan 2014 16:02:00 +0000 Subject: iio: mxs-lradc: remove useless scale_available files in_voltage8_scale_available and in_voltage9_scale_available are exposed to userspace but useless as in_voltage8_raw and in_voltage9_raw are not available. Signed-off-by: Alexandre Belloni Signed-off-by: Jonathan Cameron diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c index aa86849..7fc66a6 100644 --- a/drivers/staging/iio/adc/mxs-lradc.c +++ b/drivers/staging/iio/adc/mxs-lradc.c @@ -1035,8 +1035,6 @@ SHOW_SCALE_AVAILABLE_ATTR(4); SHOW_SCALE_AVAILABLE_ATTR(5); SHOW_SCALE_AVAILABLE_ATTR(6); SHOW_SCALE_AVAILABLE_ATTR(7); -SHOW_SCALE_AVAILABLE_ATTR(8); -SHOW_SCALE_AVAILABLE_ATTR(9); SHOW_SCALE_AVAILABLE_ATTR(10); SHOW_SCALE_AVAILABLE_ATTR(11); SHOW_SCALE_AVAILABLE_ATTR(12); @@ -1053,8 +1051,6 @@ static struct attribute *mxs_lradc_attributes[] = { &iio_dev_attr_in_voltage5_scale_available.dev_attr.attr, &iio_dev_attr_in_voltage6_scale_available.dev_attr.attr, &iio_dev_attr_in_voltage7_scale_available.dev_attr.attr, - &iio_dev_attr_in_voltage8_scale_available.dev_attr.attr, - &iio_dev_attr_in_voltage9_scale_available.dev_attr.attr, &iio_dev_attr_in_voltage10_scale_available.dev_attr.attr, &iio_dev_attr_in_voltage11_scale_available.dev_attr.attr, &iio_dev_attr_in_voltage12_scale_available.dev_attr.attr, -- cgit v0.10.2 From d180371d412627a10dc31d675ef8bc777567df09 Mon Sep 17 00:00:00 2001 From: Hartmut Knaack Date: Sat, 2 Aug 2014 00:07:00 +0100 Subject: staging:iio:ad799x fix typo in ad799x_events[] This patch fixes a typo in ad799x_events[], which caused the error "Failed to register event set". Signed-off-by: Hartmut Knaack Cc: stable@vger.kernel.org Signed-off-by: Jonathan Cameron diff --git a/drivers/staging/iio/adc/ad799x_core.c b/drivers/staging/iio/adc/ad799x_core.c index 31a2be6..5708ffc 100644 --- a/drivers/staging/iio/adc/ad799x_core.c +++ b/drivers/staging/iio/adc/ad799x_core.c @@ -393,7 +393,7 @@ static const struct iio_event_spec ad799x_events[] = { }, { .type = IIO_EV_TYPE_THRESH, .dir = IIO_EV_DIR_FALLING, - .mask_separate = BIT(IIO_EV_INFO_VALUE), + .mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE), }, { .type = IIO_EV_TYPE_THRESH, -- cgit v0.10.2 From bef44abccb2677e8d16e50b75316d4fd1061be81 Mon Sep 17 00:00:00 2001 From: Beomho Seo Date: Wed, 2 Apr 2014 09:15:00 +0100 Subject: iio: ak8975: Fix calculation formula for convert micro tesla to gauss unit This effects the reported scale of the raw values, and thus userspace applications that use this value. One micro tesla equal 0.01 gauss. So I have fixed calculation formula And add RAW_TO_GAUSS macro. ASA is in the range of 0 to 255. If multiply 0.003, calculation result(in_magn_[*]_scale) is always 0. So multiply 3000 and return and IIO_VAL_INT_PLUS_MICRO. As a result, read_raw call back function return accurate scale value. Signed-off-by: Beomho Seo Cc: stable@vger.kernel.org Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c index ff284e5..0542354 100644 --- a/drivers/iio/magnetometer/ak8975.c +++ b/drivers/iio/magnetometer/ak8975.c @@ -85,6 +85,7 @@ #define AK8975_MAX_CONVERSION_TIMEOUT 500 #define AK8975_CONVERSION_DONE_POLL_TIME 10 #define AK8975_DATA_READY_TIMEOUT ((100*HZ)/1000) +#define RAW_TO_GAUSS(asa) ((((asa) + 128) * 3000) / 256) /* * Per-instance context data for the device. @@ -265,15 +266,15 @@ static int ak8975_setup(struct i2c_client *client) * * Since 1uT = 0.01 gauss, our final scale factor becomes: * - * Hadj = H * ((ASA + 128) / 256) * 3/10 * 100 - * Hadj = H * ((ASA + 128) * 30 / 256 + * Hadj = H * ((ASA + 128) / 256) * 3/10 * 1/100 + * Hadj = H * ((ASA + 128) * 0.003) / 256 * * Since ASA doesn't change, we cache the resultant scale factor into the * device context in ak8975_setup(). */ - data->raw_to_gauss[0] = ((data->asa[0] + 128) * 30) >> 8; - data->raw_to_gauss[1] = ((data->asa[1] + 128) * 30) >> 8; - data->raw_to_gauss[2] = ((data->asa[2] + 128) * 30) >> 8; + data->raw_to_gauss[0] = RAW_TO_GAUSS(data->asa[0]); + data->raw_to_gauss[1] = RAW_TO_GAUSS(data->asa[1]); + data->raw_to_gauss[2] = RAW_TO_GAUSS(data->asa[2]); return 0; } @@ -428,8 +429,9 @@ static int ak8975_read_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_RAW: return ak8975_read_axis(indio_dev, chan->address, val); case IIO_CHAN_INFO_SCALE: - *val = data->raw_to_gauss[chan->address]; - return IIO_VAL_INT; + *val = 0; + *val2 = data->raw_to_gauss[chan->address]; + return IIO_VAL_INT_PLUS_MICRO; } return -EINVAL; } -- cgit v0.10.2 From c76782d151dab7ecfdcdf9a01561c2d61d9b490f Mon Sep 17 00:00:00 2001 From: Marcus Folkesson Date: Fri, 24 Jan 2014 11:24:00 +0000 Subject: iio: adis16400: Set timestamp as the last element in chan_spec This is necessary since timestamp is calculated as the last element in iio_compute_scan_bytes(). Without this fix any userspace code reading the layout of the buffer via sysfs will incorrectly interpret the data leading some nasty corruption. Signed-off-by: Marcus Folkesson Acked-by: Lars-Peter Clausen Cc: stable@vger.kernel.org Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/imu/adis16400.h b/drivers/iio/imu/adis16400.h index 2f8f9d6..0916bf6 100644 --- a/drivers/iio/imu/adis16400.h +++ b/drivers/iio/imu/adis16400.h @@ -189,6 +189,7 @@ enum { ADIS16300_SCAN_INCLI_X, ADIS16300_SCAN_INCLI_Y, ADIS16400_SCAN_ADC, + ADIS16400_SCAN_TIMESTAMP, }; #ifdef CONFIG_IIO_BUFFER diff --git a/drivers/iio/imu/adis16400_core.c b/drivers/iio/imu/adis16400_core.c index 368660d..7c582f7 100644 --- a/drivers/iio/imu/adis16400_core.c +++ b/drivers/iio/imu/adis16400_core.c @@ -632,7 +632,7 @@ static const struct iio_chan_spec adis16400_channels[] = { ADIS16400_MAGN_CHAN(Z, ADIS16400_ZMAGN_OUT, 14), ADIS16400_TEMP_CHAN(ADIS16400_TEMP_OUT, 12), ADIS16400_AUX_ADC_CHAN(ADIS16400_AUX_ADC, 12), - IIO_CHAN_SOFT_TIMESTAMP(12) + IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP), }; static const struct iio_chan_spec adis16448_channels[] = { @@ -659,7 +659,7 @@ static const struct iio_chan_spec adis16448_channels[] = { }, }, ADIS16400_TEMP_CHAN(ADIS16448_TEMP_OUT, 12), - IIO_CHAN_SOFT_TIMESTAMP(11) + IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP), }; static const struct iio_chan_spec adis16350_channels[] = { @@ -677,7 +677,7 @@ static const struct iio_chan_spec adis16350_channels[] = { ADIS16400_MOD_TEMP_CHAN(X, ADIS16350_XTEMP_OUT, 12), ADIS16400_MOD_TEMP_CHAN(Y, ADIS16350_YTEMP_OUT, 12), ADIS16400_MOD_TEMP_CHAN(Z, ADIS16350_ZTEMP_OUT, 12), - IIO_CHAN_SOFT_TIMESTAMP(11) + IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP), }; static const struct iio_chan_spec adis16300_channels[] = { @@ -690,7 +690,7 @@ static const struct iio_chan_spec adis16300_channels[] = { ADIS16400_AUX_ADC_CHAN(ADIS16300_AUX_ADC, 12), ADIS16400_INCLI_CHAN(X, ADIS16300_PITCH_OUT, 13), ADIS16400_INCLI_CHAN(Y, ADIS16300_ROLL_OUT, 13), - IIO_CHAN_SOFT_TIMESTAMP(14) + IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP), }; static const struct iio_chan_spec adis16334_channels[] = { @@ -701,7 +701,7 @@ static const struct iio_chan_spec adis16334_channels[] = { ADIS16400_ACCEL_CHAN(Y, ADIS16400_YACCL_OUT, 14), ADIS16400_ACCEL_CHAN(Z, ADIS16400_ZACCL_OUT, 14), ADIS16400_TEMP_CHAN(ADIS16350_XTEMP_OUT, 12), - IIO_CHAN_SOFT_TIMESTAMP(8) + IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP), }; static struct attribute *adis16400_attributes[] = { -- cgit v0.10.2 From 5585215b6daabf898b4d40f33d1b8c1d41e85018 Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Wed, 1 Oct 2014 21:37:00 +0100 Subject: iio:accel:bma180: Use modifier instead of index in channel specification This driver was not complying with the ABI and the purpose of this patch is to bring it inline so that userspace will correctly identify the channels. Should use channel modifiers (X/Y/Z), not channel indices timestamp channel has scan index 3, not 4 Signed-off-by: Peter Meerwald Cc: Kravchenko Oleksandr Cc: Stable@vger.kernel.org Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/accel/bma180.c b/drivers/iio/accel/bma180.c index 3bec922..bfec313 100644 --- a/drivers/iio/accel/bma180.c +++ b/drivers/iio/accel/bma180.c @@ -447,14 +447,14 @@ static const struct iio_chan_spec_ext_info bma180_ext_info[] = { { }, }; -#define BMA180_CHANNEL(_index) { \ +#define BMA180_CHANNEL(_axis) { \ .type = IIO_ACCEL, \ - .indexed = 1, \ - .channel = (_index), \ + .modified = 1, \ + .channel2 = IIO_MOD_##_axis, \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ - .scan_index = (_index), \ + .scan_index = AXIS_##_axis, \ .scan_type = { \ .sign = 's', \ .realbits = 14, \ @@ -465,10 +465,10 @@ static const struct iio_chan_spec_ext_info bma180_ext_info[] = { } static const struct iio_chan_spec bma180_channels[] = { - BMA180_CHANNEL(AXIS_X), - BMA180_CHANNEL(AXIS_Y), - BMA180_CHANNEL(AXIS_Z), - IIO_CHAN_SOFT_TIMESTAMP(4), + BMA180_CHANNEL(X), + BMA180_CHANNEL(Y), + BMA180_CHANNEL(Z), + IIO_CHAN_SOFT_TIMESTAMP(3), }; static irqreturn_t bma180_trigger_handler(int irq, void *p) -- cgit v0.10.2 From 55b40d37311807a6bb2acdae0df904f54a0da3ae Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Mon, 27 Jan 2014 18:10:00 +0000 Subject: iio: max1363: Use devm_regulator_get_optional for optional regulator In kernel version 3.13, devm_regulator_get() may return no error if a regulator is undeclared. regulator_get_voltage() will return -EINVAL if this happens. This causes the driver to fail loading if the vref regulator is not declared. Since vref is optional, call devm_regulator_get_optional instead. Signed-off-by: Guenter Roeck Cc: Stable@vger.kernel.org Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/adc/max1363.c b/drivers/iio/adc/max1363.c index e283f2f..3602592 100644 --- a/drivers/iio/adc/max1363.c +++ b/drivers/iio/adc/max1363.c @@ -1560,7 +1560,7 @@ static int max1363_probe(struct i2c_client *client, st->client = client; st->vref_uv = st->chip_info->int_vref_mv * 1000; - vref = devm_regulator_get(&client->dev, "vref"); + vref = devm_regulator_get_optional(&client->dev, "vref"); if (!IS_ERR(vref)) { int vref_uv; -- cgit v0.10.2 From 569d6557ab957d6ae7e97a46ae669174be4189e6 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Tue, 4 Feb 2014 14:13:15 -0500 Subject: x86: Use preempt_disable_notrace() in cycles_2_ns() When debug preempt is enabled, preempt_disable() can be traced by function and function graph tracing. There's a place in the function graph tracer that calls trace_clock() which eventually calls cycles_2_ns() outside of the recursion protection. When cycles_2_ns() calls preempt_disable() it gets traced and the graph tracer will go into a recursive loop causing a crash or worse, a triple fault. Simple fix is to use preempt_disable_notrace() in cycles_2_ns, which makes sense because the preempt_disable() tracing may use that code too, and it tracing it, even with recursion protection is rather pointless. Signed-off-by: Steven Rostedt Acked-by: Thomas Gleixner Signed-off-by: Peter Zijlstra Cc: Linus Torvalds Link: http://lkml.kernel.org/r/20140204141315.2a968a72@gandalf.local.home Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index 19e5adb..acb3b60 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -209,7 +209,7 @@ static inline unsigned long long cycles_2_ns(unsigned long long cyc) * dance when its actually needed. */ - preempt_disable(); + preempt_disable_notrace(); data = this_cpu_read(cyc2ns.head); tail = this_cpu_read(cyc2ns.tail); @@ -229,7 +229,7 @@ static inline unsigned long long cycles_2_ns(unsigned long long cyc) if (!--data->__count) this_cpu_write(cyc2ns.tail, data); } - preempt_enable(); + preempt_enable_notrace(); return ns; } -- cgit v0.10.2 From 0668d3065128d39449c097e62dbdb5707820137d Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Thu, 2 Jan 2014 16:37:32 -0800 Subject: genirq: Add devm_request_any_context_irq() Some drivers use request_any_context_irq() but there isn't a devm_* function for it. Add one so that these drivers don't need to explicitly free the irq on driver detach. Signed-off-by: Stephen Boyd Cc: linux-arm-kernel@lists.infradead.org Cc: Dmitry Torokhov Link: http://lkml.kernel.org/r/1388709460-19222-3-git-send-email-sboyd@codeaurora.org Signed-off-by: Thomas Gleixner diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index 0053add..a2678d3 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h @@ -158,6 +158,11 @@ devm_request_irq(struct device *dev, unsigned int irq, irq_handler_t handler, devname, dev_id); } +extern int __must_check +devm_request_any_context_irq(struct device *dev, unsigned int irq, + irq_handler_t handler, unsigned long irqflags, + const char *devname, void *dev_id); + extern void devm_free_irq(struct device *dev, unsigned int irq, void *dev_id); /* diff --git a/kernel/irq/devres.c b/kernel/irq/devres.c index bd8e788..1ef0606 100644 --- a/kernel/irq/devres.c +++ b/kernel/irq/devres.c @@ -73,6 +73,51 @@ int devm_request_threaded_irq(struct device *dev, unsigned int irq, EXPORT_SYMBOL(devm_request_threaded_irq); /** + * devm_request_any_context_irq - allocate an interrupt line for a managed device + * @dev: device to request interrupt for + * @irq: Interrupt line to allocate + * @handler: Function to be called when the IRQ occurs + * @thread_fn: function to be called in a threaded interrupt context. NULL + * for devices which handle everything in @handler + * @irqflags: Interrupt type flags + * @devname: An ascii name for the claiming device + * @dev_id: A cookie passed back to the handler function + * + * Except for the extra @dev argument, this function takes the + * same arguments and performs the same function as + * request_any_context_irq(). IRQs requested with this function will be + * automatically freed on driver detach. + * + * If an IRQ allocated with this function needs to be freed + * separately, devm_free_irq() must be used. + */ +int devm_request_any_context_irq(struct device *dev, unsigned int irq, + irq_handler_t handler, unsigned long irqflags, + const char *devname, void *dev_id) +{ + struct irq_devres *dr; + int rc; + + dr = devres_alloc(devm_irq_release, sizeof(struct irq_devres), + GFP_KERNEL); + if (!dr) + return -ENOMEM; + + rc = request_any_context_irq(irq, handler, irqflags, devname, dev_id); + if (rc) { + devres_free(dr); + return rc; + } + + dr->irq = irq; + dr->dev_id = dev_id; + devres_add(dev, dr); + + return 0; +} +EXPORT_SYMBOL(devm_request_any_context_irq); + +/** * devm_free_irq - free an interrupt * @dev: device to free interrupt for * @irq: Interrupt line to free -- cgit v0.10.2 From 0b4ef8de090a60e04560ed69aa35f439b8d5145f Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Sun, 9 Feb 2014 18:22:53 +0530 Subject: fs: Mark function as static in fs/bio-integrity.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mark functions as static in bio-integrity.c because it is not used outside this file. This eliminates the following warnings in bio-integrity.c: fs/bio-integrity.c:224:5: warning: no previous prototype for ‘bio_integrity_tag’ [-Wmissing-prototypes] Signed-off-by: Rashika Kheria Reviewed-by: Josh Triplett Signed-off-by: Jens Axboe diff --git a/fs/bio-integrity.c b/fs/bio-integrity.c index bcb4a4d..0129b78 100644 --- a/fs/bio-integrity.c +++ b/fs/bio-integrity.c @@ -234,7 +234,8 @@ unsigned int bio_integrity_tag_size(struct bio *bio) } EXPORT_SYMBOL(bio_integrity_tag_size); -int bio_integrity_tag(struct bio *bio, void *tag_buf, unsigned int len, int set) +static int bio_integrity_tag(struct bio *bio, void *tag_buf, unsigned int len, + int set) { struct bio_integrity_payload *bip = bio->bi_integrity; struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev); -- cgit v0.10.2 From c4540a7d8c1e595560e53acedf88901daf15a2b5 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Sun, 9 Feb 2014 18:30:39 +0530 Subject: fs: Add prototype declaration to appropriate header file include/linux/bio.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add prototype declaration to header file include/linux/bio.h because it is used by more than one file. This eliminates the following warning in bio-integrity.c: fs/bio-integrity.c:214:14: warning: no previous prototype for ‘bio_integrity_tag_size’ [-Wmissing-prototypes] Signed-off-by: Rashika Kheria Reviewed-by: Josh Triplett Signed-off-by: Jens Axboe diff --git a/include/linux/bio.h b/include/linux/bio.h index 7065452..d6791bb 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -332,6 +332,7 @@ extern struct bio *bio_clone_fast(struct bio *, gfp_t, struct bio_set *); extern struct bio *bio_clone_bioset(struct bio *, gfp_t, struct bio_set *bs); extern struct bio_set *fs_bio_set; +unsigned int bio_integrity_tag_size(struct bio *bio); static inline struct bio *bio_alloc(gfp_t gfp_mask, unsigned int nr_iovecs) { -- cgit v0.10.2 From fd944bded5ce32247941ce54eb8f65646549886b Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Sun, 9 Feb 2014 19:57:33 +0530 Subject: net: Mark function as static in 9p/client.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mark function as static in net/9p/client.c because it is not used outside this file. This eliminates the following warning in net/9p/client.c: net/9p/client.c:207:18: warning: no previous prototype for ‘p9_fcall_alloc’ [-Wmissing-prototypes] Signed-off-by: Rashika Kheria Reviewed-by: Josh Triplett Signed-off-by: David S. Miller diff --git a/net/9p/client.c b/net/9p/client.c index a5e4d2d..9186550 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -204,7 +204,7 @@ free_and_return: return ret; } -struct p9_fcall *p9_fcall_alloc(int alloc_msize) +static struct p9_fcall *p9_fcall_alloc(int alloc_msize) { struct p9_fcall *fc; fc = kmalloc(sizeof(struct p9_fcall) + alloc_msize, GFP_NOFS); -- cgit v0.10.2 From 8203274e1541392e8a85d4bcbcda55d62fe62469 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Sun, 9 Feb 2014 19:59:04 +0530 Subject: net: Include appropriate header file in caif/caif_dev.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Include appropriate header file net/caif/caif_dev.h in caif/caif_dev.c because it has prototype declarations of function defined in caif/caif_dev.c. This eliminates the following file in caif/caif_dev.c: net/caif/caif_dev.c:303:6: warning: no previous prototype for ‘caif_enroll_dev’ [-Wmissing-prototypes] Signed-off-by: Rashika Kheria Reviewed-by: Josh Triplett Signed-off-by: David S. Miller diff --git a/net/caif/caif_dev.c b/net/caif/caif_dev.c index 4dca159..edbca46 100644 --- a/net/caif/caif_dev.c +++ b/net/caif/caif_dev.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include -- cgit v0.10.2 From 02fe72c9edc58d6b5d85c08327d7ef05cd3e97dc Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Sun, 9 Feb 2014 20:02:16 +0530 Subject: net: Include appropriate header file in caif/cfsrvl.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Include appropriate header file net/caif/caif_dev.h in caif/cfsrvl.c because it has prototype declaration of functions defined in caif/cfsrvl.c. This eliminates the following warning in caif/cfsrvl.c: net/caif/cfsrvl.c:198:6: warning: no previous prototype for ‘caif_free_client’ [-Wmissing-prototypes] net/caif/cfsrvl.c:208:6: warning: no previous prototype for ‘caif_client_register_refcnt’ [-Wmissing-prototypes] Signed-off-by: Rashika Kheria Reviewed-by: Josh Triplett Signed-off-by: David S. Miller diff --git a/net/caif/cfsrvl.c b/net/caif/cfsrvl.c index 353f793..a6e1154 100644 --- a/net/caif/cfsrvl.c +++ b/net/caif/cfsrvl.c @@ -15,6 +15,7 @@ #include #include #include +#include #define SRVL_CTRL_PKT_SIZE 1 #define SRVL_FLOW_OFF 0x81 -- cgit v0.10.2 From 0a59f3a9fd7e2801a445682465ea0522ea497183 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Sun, 9 Feb 2014 20:26:25 +0530 Subject: net: Mark functions as static in core/dev.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mark functions as static in core/dev.c because they are not used outside this file. This eliminates the following warning in core/dev.c: net/core/dev.c:2806:5: warning: no previous prototype for ‘__dev_queue_xmit’ [-Wmissing-prototypes] net/core/dev.c:4640:5: warning: no previous prototype for ‘netdev_adjacent_sysfs_add’ [-Wmissing-prototypes] net/core/dev.c:4650:6: warning: no previous prototype for ‘netdev_adjacent_sysfs_del’ [-Wmissing-prototypes] Signed-off-by: Rashika Kheria Reviewed-by: Josh Triplett Reviewed-by: Veaceslav Falico Signed-off-by: David S. Miller diff --git a/net/core/dev.c b/net/core/dev.c index 3721db7..4ad1b78 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2803,7 +2803,7 @@ EXPORT_SYMBOL(dev_loopback_xmit); * the BH enable code must have IRQs enabled so that it will not deadlock. * --BLG */ -int __dev_queue_xmit(struct sk_buff *skb, void *accel_priv) +static int __dev_queue_xmit(struct sk_buff *skb, void *accel_priv) { struct net_device *dev = skb->dev; struct netdev_queue *txq; @@ -4637,7 +4637,7 @@ struct net_device *netdev_master_upper_dev_get_rcu(struct net_device *dev) } EXPORT_SYMBOL(netdev_master_upper_dev_get_rcu); -int netdev_adjacent_sysfs_add(struct net_device *dev, +static int netdev_adjacent_sysfs_add(struct net_device *dev, struct net_device *adj_dev, struct list_head *dev_list) { @@ -4647,7 +4647,7 @@ int netdev_adjacent_sysfs_add(struct net_device *dev, return sysfs_create_link(&(dev->dev.kobj), &(adj_dev->dev.kobj), linkname); } -void netdev_adjacent_sysfs_del(struct net_device *dev, +static void netdev_adjacent_sysfs_del(struct net_device *dev, char *name, struct list_head *dev_list) { -- cgit v0.10.2 From f56b8bf6e445b22bb6207dbcf30b2c7f5ddfdf96 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Sun, 9 Feb 2014 22:20:09 +0530 Subject: net: Move prototype declaration to appropriate header file from decnet/af_decnet.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move prototype declaration of functions to header file include/net/dn_route.h from net/decnet/af_decnet.c because it is used by more than one file. This eliminates the following warning in net/decnet/dn_route.c: net/decnet/dn_route.c:629:5: warning: no previous prototype for ‘dn_route_rcv’ [-Wmissing-prototypes] Signed-off-by: Rashika Kheria Reviewed-by: Josh Triplett Signed-off-by: David S. Miller diff --git a/include/net/dn_route.h b/include/net/dn_route.h index b409ad6..55df993 100644 --- a/include/net/dn_route.h +++ b/include/net/dn_route.h @@ -20,6 +20,8 @@ int dn_route_output_sock(struct dst_entry __rcu **pprt, struct flowidn *, struct sock *sk, int flags); int dn_cache_dump(struct sk_buff *skb, struct netlink_callback *cb); void dn_rt_cache_flush(int delay); +int dn_route_rcv(struct sk_buff *skb, struct net_device *dev, + struct packet_type *pt, struct net_device *orig_dev); /* Masks for flags field */ #define DN_RT_F_PID 0x07 /* Mask for packet type */ diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c index 2954dcb..24d9193 100644 --- a/net/decnet/af_decnet.c +++ b/net/decnet/af_decnet.c @@ -2104,8 +2104,6 @@ static struct notifier_block dn_dev_notifier = { .notifier_call = dn_device_event, }; -extern int dn_route_rcv(struct sk_buff *, struct net_device *, struct packet_type *, struct net_device *); - static struct packet_type dn_dix_packet_type __read_mostly = { .type = cpu_to_be16(ETH_P_DNA_RT), .func = dn_route_rcv, -- cgit v0.10.2 From ab3301bd96c024ec9c2e1c35c90327dc5c8012a4 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Sun, 9 Feb 2014 22:22:53 +0530 Subject: net: Move prototype declaration to header file include/net/dn.h from net/decnet/af_decnet.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move prototype declaration of functions to header file include/net/dn.h from net/decnet/af_decnet.c because they are used by more than one file. This eliminates the following warning in net/decnet/af_decnet.c: net/decnet/sysctl_net_decnet.c:354:6: warning: no previous prototype for ‘dn_register_sysctl’ [-Wmissing-prototypes] net/decnet/sysctl_net_decnet.c:359:6: warning: no previous prototype for ‘dn_unregister_sysctl’ [-Wmissing-prototypes] Signed-off-by: Rashika Kheria Reviewed-by: Josh Triplett Signed-off-by: David S. Miller diff --git a/include/net/dn.h b/include/net/dn.h index ccc1558..913b73d 100644 --- a/include/net/dn.h +++ b/include/net/dn.h @@ -200,6 +200,8 @@ static inline void dn_sk_ports_copy(struct flowidn *fld, struct dn_scp *scp) } unsigned int dn_mss_from_pmtu(struct net_device *dev, int mtu); +void dn_register_sysctl(void); +void dn_unregister_sysctl(void); #define DN_MENUVER_ACC 0x01 #define DN_MENUVER_USR 0x02 diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c index 24d9193..4c04848 100644 --- a/net/decnet/af_decnet.c +++ b/net/decnet/af_decnet.c @@ -2351,9 +2351,6 @@ static const struct proto_ops dn_proto_ops = { .sendpage = sock_no_sendpage, }; -void dn_register_sysctl(void); -void dn_unregister_sysctl(void); - MODULE_DESCRIPTION("The Linux DECnet Network Protocol"); MODULE_AUTHOR("Linux DECnet Project Team"); MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 493cc5e5ba450356560cc12a8f71ff6a8574c91c Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Sun, 9 Feb 2014 22:24:33 +0530 Subject: net: Move prototype declaration to include/net/ipx.h from net/ipx/ipx_route.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move prototype definition of function to header file include/net/ipx.h from net/ipx/ipx_route.c because they are used by more than one file. This eliminates the following warning from net/ipx/af_ipx.c: net/ipx/af_ipx.c:193:23: warning: no previous prototype for ‘ipxitf_find_using_net’ [-Wmissing-prototypes] net/ipx/af_ipx.c:577:5: warning: no previous prototype for ‘ipxitf_send’ [-Wmissing-prototypes] net/ipx/af_ipx.c:1219:8: warning: no previous prototype for ‘ipx_cksum’ [-Wmissing-prototypes] Signed-off-by: Rashika Kheria Reviewed-by: Josh Triplett Signed-off-by: David S. Miller diff --git a/include/net/ipx.h b/include/net/ipx.h index 9e9e354..75466ac 100644 --- a/include/net/ipx.h +++ b/include/net/ipx.h @@ -140,6 +140,9 @@ static __inline__ void ipxitf_hold(struct ipx_interface *intrfc) } void ipxitf_down(struct ipx_interface *intrfc); +struct ipx_interface *ipxitf_find_using_net(__be32 net); +int ipxitf_send(struct ipx_interface *intrfc, struct sk_buff *skb, char *node); +__be16 ipx_cksum(struct ipxhdr *packet, int length); static __inline__ void ipxitf_put(struct ipx_interface *intrfc) { diff --git a/net/ipx/ipx_route.c b/net/ipx/ipx_route.c index 30f4519..c1f0318 100644 --- a/net/ipx/ipx_route.c +++ b/net/ipx/ipx_route.c @@ -20,15 +20,11 @@ DEFINE_RWLOCK(ipx_routes_lock); extern struct ipx_interface *ipx_internal_net; -extern __be16 ipx_cksum(struct ipxhdr *packet, int length); extern struct ipx_interface *ipxitf_find_using_net(__be32 net); extern int ipxitf_demux_socket(struct ipx_interface *intrfc, struct sk_buff *skb, int copy); extern int ipxitf_demux_socket(struct ipx_interface *intrfc, struct sk_buff *skb, int copy); -extern int ipxitf_send(struct ipx_interface *intrfc, struct sk_buff *skb, - char *node); -extern struct ipx_interface *ipxitf_find_using_net(__be32 net); struct ipx_route *ipxrtr_lookup(__be32 net) { -- cgit v0.10.2 From 578efbc19f468686ad7eb1e505bab56d04e92784 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Sun, 9 Feb 2014 22:26:32 +0530 Subject: net: Move prototype declaration to header file include/net/ipx.h from net/ipx/af_ipx.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move prototype declaration of functions to header file include/net/ipx.h from net/ipx/af_ipx.c because they are used by more than one file. This eliminates the following warning in net/ipx/ipx_route.c:33:19: warning: no previous prototype for ‘ipxrtr_lookup’ [-Wmissing-prototypes] net/ipx/ipx_route.c:52:5: warning: no previous prototype for ‘ipxrtr_add_route’ [-Wmissing-prototypes] net/ipx/ipx_route.c:94:6: warning: no previous prototype for ‘ipxrtr_del_routes’ [-Wmissing-prototypes] net/ipx/ipx_route.c:149:5: warning: no previous prototype for ‘ipxrtr_route_skb’ [-Wmissing-prototypes] net/ipx/ipx_route.c:171:5: warning: no previous prototype for ‘ipxrtr_route_packet’ [-Wmissing-prototypes] net/ipx/ipx_route.c:261:5: warning: no previous prototype for ‘ipxrtr_ioctl’ [-Wmissing-prototypes] Signed-off-by: Rashika Kheria Reviewed-by: Josh Triplett Signed-off-by: David S. Miller diff --git a/include/net/ipx.h b/include/net/ipx.h index 75466ac..0143180 100644 --- a/include/net/ipx.h +++ b/include/net/ipx.h @@ -143,6 +143,14 @@ void ipxitf_down(struct ipx_interface *intrfc); struct ipx_interface *ipxitf_find_using_net(__be32 net); int ipxitf_send(struct ipx_interface *intrfc, struct sk_buff *skb, char *node); __be16 ipx_cksum(struct ipxhdr *packet, int length); +int ipxrtr_add_route(__be32 network, struct ipx_interface *intrfc, + unsigned char *node); +void ipxrtr_del_routes(struct ipx_interface *intrfc); +int ipxrtr_route_packet(struct sock *sk, struct sockaddr_ipx *usipx, + struct iovec *iov, size_t len, int noblock); +int ipxrtr_route_skb(struct sk_buff *skb); +struct ipx_route *ipxrtr_lookup(__be32 net); +int ipxrtr_ioctl(unsigned int cmd, void __user *arg); static __inline__ void ipxitf_put(struct ipx_interface *intrfc) { diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c index 994e28b..e5a00a9 100644 --- a/net/ipx/af_ipx.c +++ b/net/ipx/af_ipx.c @@ -84,15 +84,6 @@ DEFINE_SPINLOCK(ipx_interfaces_lock); struct ipx_interface *ipx_primary_net; struct ipx_interface *ipx_internal_net; -extern int ipxrtr_add_route(__be32 network, struct ipx_interface *intrfc, - unsigned char *node); -extern void ipxrtr_del_routes(struct ipx_interface *intrfc); -extern int ipxrtr_route_packet(struct sock *sk, struct sockaddr_ipx *usipx, - struct iovec *iov, size_t len, int noblock); -extern int ipxrtr_route_skb(struct sk_buff *skb); -extern struct ipx_route *ipxrtr_lookup(__be32 net); -extern int ipxrtr_ioctl(unsigned int cmd, void __user *arg); - struct ipx_interface *ipx_interfaces_head(void) { struct ipx_interface *rc = NULL; -- cgit v0.10.2 From 7780d8ae4ae1960ef7c0570de0a1ecd7b60c8152 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Sun, 9 Feb 2014 22:27:41 +0530 Subject: net: Move prototype declaration to header file include/net/datalink.h from net/ipx/af_ipx.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move prototype declarations of function to header file include/net/datalink.h from net/ipx/af_ipx.c because they are used by more than one file. This eliminates the following warning in net/ipx/pe2.c: net/ipx/pe2.c:20:24: warning: no previous prototype for ‘make_EII_client’ [-Wmissing-prototypes] net/ipx/pe2.c:32:6: warning: no previous prototype for ‘destroy_EII_client’ [-Wmissing-prototypes] Signed-off-by: Rashika Kheria Reviewed-by: Josh Triplett Signed-off-by: David S. Miller diff --git a/include/net/datalink.h b/include/net/datalink.h index deb7ca7..93cb18f 100644 --- a/include/net/datalink.h +++ b/include/net/datalink.h @@ -15,4 +15,6 @@ struct datalink_proto { struct list_head node; }; +struct datalink_proto *make_EII_client(void); +void destroy_EII_client(struct datalink_proto *dl); #endif diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c index e5a00a9..224d058 100644 --- a/net/ipx/af_ipx.c +++ b/net/ipx/af_ipx.c @@ -52,6 +52,7 @@ #include #include #include +#include #include #include @@ -1977,9 +1978,6 @@ static struct notifier_block ipx_dev_notifier = { .notifier_call = ipxitf_device_event, }; -extern struct datalink_proto *make_EII_client(void); -extern void destroy_EII_client(struct datalink_proto *); - static const unsigned char ipx_8022_type = 0xE0; static const unsigned char ipx_snap_id[5] = { 0x0, 0x0, 0x0, 0x81, 0x37 }; static const char ipx_EII_err_msg[] __initconst = -- cgit v0.10.2 From 535d3ae9c808e6a5248f0524dbc7a9e997cf3288 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Sun, 9 Feb 2014 22:29:14 +0530 Subject: net: Move prototype declaration to header file include/net/net_namespace.h from net/ipx/af_ipx.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move prototype declaration of function to header file include/net/net_namespace.h from net/ipx/af_ipx.c because they are used by more than one file. This eliminates the following warning in net/ipx/sysctl_net_ipx.c: net/ipx/sysctl_net_ipx.c:33:6: warning: no previous prototype for ‘ipx_register_sysctl’ [-Wmissing-prototypes] net/ipx/sysctl_net_ipx.c:38:6: warning: no previous prototype for ‘ipx_unregister_sysctl’ [-Wmissing-prototypes] Signed-off-by: Rashika Kheria Signed-off-by: David S. Miller diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index da68c9a..991dcd9 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h @@ -162,6 +162,14 @@ extern struct list_head net_namespace_list; struct net *get_net_ns_by_pid(pid_t pid); struct net *get_net_ns_by_fd(int pid); +#ifdef CONFIG_SYSCTL +void ipx_register_sysctl(void); +void ipx_unregister_sysctl(void); +#else +#define ipx_register_sysctl() +#define ipx_unregister_sysctl() +#endif + #ifdef CONFIG_NET_NS void __put_net(struct net *net); diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c index 224d058..00b2a6d 100644 --- a/net/ipx/af_ipx.c +++ b/net/ipx/af_ipx.c @@ -54,17 +54,10 @@ #include #include #include +#include #include -#ifdef CONFIG_SYSCTL -extern void ipx_register_sysctl(void); -extern void ipx_unregister_sysctl(void); -#else -#define ipx_register_sysctl() -#define ipx_unregister_sysctl() -#endif - /* Configuration Variables */ static unsigned char ipxcfg_max_hops = 16; static char ipxcfg_auto_select_primary; -- cgit v0.10.2 From bd76ed36bac50b5402fd09c3fc2f368ef324ffe2 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Sun, 9 Feb 2014 22:31:42 +0530 Subject: net: Include appropriate header file in netfilter/nft_lookup.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Include appropriate header file net/netfilter/nf_tables_core.h in net/netfilter/nft_lookup.c because it has prototype declaration of functions defined in net/netfilter/nft_lookup.c. This eliminates the following warning in net/netfilter/nft_lookup.c: net/netfilter/nft_lookup.c:133:12: warning: no previous prototype for ‘nft_lookup_module_init’ [-Wmissing-prototypes] net/netfilter/nft_lookup.c:138:6: warning: no previous prototype for ‘nft_lookup_module_exit’ [-Wmissing-prototypes] Signed-off-by: Rashika Kheria Reviewed-by: Josh Triplett Signed-off-by: David S. Miller diff --git a/net/netfilter/nft_lookup.c b/net/netfilter/nft_lookup.c index 8a6116b..bb4ef4c 100644 --- a/net/netfilter/nft_lookup.c +++ b/net/netfilter/nft_lookup.c @@ -16,6 +16,7 @@ #include #include #include +#include struct nft_lookup { struct nft_set *set; -- cgit v0.10.2 From e1d83ee673eff5407255ba9e884312219f6832d7 Mon Sep 17 00:00:00 2001 From: Rashika Kheria Date: Sun, 9 Feb 2014 22:33:03 +0530 Subject: net: Mark functions as static in net/sunrpc/svc_xprt.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mark functions as static in net/sunrpc/svc_xprt.c because they are not used outside this file. This eliminates the following warning in net/sunrpc/svc_xprt.c: net/sunrpc/svc_xprt.c:574:5: warning: no previous prototype for ‘svc_alloc_arg’ [-Wmissing-prototypes] net/sunrpc/svc_xprt.c:615:18: warning: no previous prototype for ‘svc_get_next_xprt’ [-Wmissing-prototypes] net/sunrpc/svc_xprt.c:694:6: warning: no previous prototype for ‘svc_add_new_temp_xprt’ [-Wmissing-prototypes] Signed-off-by: Rashika Kheria Reviewed-by: Josh Triplett Signed-off-by: David S. Miller diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index 80a6640..06c6ff0 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c @@ -571,7 +571,7 @@ static void svc_check_conn_limits(struct svc_serv *serv) } } -int svc_alloc_arg(struct svc_rqst *rqstp) +static int svc_alloc_arg(struct svc_rqst *rqstp) { struct svc_serv *serv = rqstp->rq_server; struct xdr_buf *arg; @@ -612,7 +612,7 @@ int svc_alloc_arg(struct svc_rqst *rqstp) return 0; } -struct svc_xprt *svc_get_next_xprt(struct svc_rqst *rqstp, long timeout) +static struct svc_xprt *svc_get_next_xprt(struct svc_rqst *rqstp, long timeout) { struct svc_xprt *xprt; struct svc_pool *pool = rqstp->rq_pool; @@ -691,7 +691,7 @@ struct svc_xprt *svc_get_next_xprt(struct svc_rqst *rqstp, long timeout) return xprt; } -void svc_add_new_temp_xprt(struct svc_serv *serv, struct svc_xprt *newxpt) +static void svc_add_new_temp_xprt(struct svc_serv *serv, struct svc_xprt *newxpt) { spin_lock_bh(&serv->sv_lock); set_bit(XPT_TEMP, &newxpt->xpt_flags); -- cgit v0.10.2 From d94c1f92bbf2c42c5febd68bbea51fffeac90834 Mon Sep 17 00:00:00 2001 From: FX Le Bail Date: Fri, 7 Feb 2014 11:22:37 +0100 Subject: ipv6: icmp6_send: fix Oops when pinging a not set up IPv6 peer on a sit tunnel The patch 446fab59333dea91e54688f033dd8d788d0486fb ("ipv6: enable anycast addresses as source addresses in ICMPv6 error messages") causes an Oops when pinging a not set up IPv6 peer on a sit tunnel. The problem is that ipv6_anycast_destination() uses unconditionally skb_dst(skb), which is NULL in this case. The solution is to use instead the ipv6_chk_acast_addr_src() function. Here are the steps to reproduce it: modprobe sit ip link add sit1 type sit remote 10.16.0.121 local 10.16.0.249 ip l s sit1 up ip -6 a a dev sit1 2001:1234::123 remote 2001:1234::121 ping6 2001:1234::121 Reported-by: Nicolas Dichtel Tested-by: Nicolas Dichtel Signed-off-by: Francois-Xavier Le Bail Signed-off-by: David S. Miller diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index f81f596..f2610e1 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -414,7 +414,7 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info) addr_type = ipv6_addr_type(&hdr->daddr); if (ipv6_chk_addr(net, &hdr->daddr, skb->dev, 0) || - ipv6_anycast_destination(skb)) + ipv6_chk_acast_addr_src(net, skb->dev, &hdr->daddr)) saddr = &hdr->daddr; /* -- cgit v0.10.2 From 310f6fd0ca9de8c1fc6399af494855e15157aa35 Mon Sep 17 00:00:00 2001 From: Christian Engelmayer Date: Fri, 7 Feb 2014 22:58:38 +0100 Subject: 6lowpan: Remove unused pointer in lowpan_header_create() Commit 8df8c56a (6lowpan: Moving generic compression code into 6lowpan_iphc.c) left pointer 'hdr' unused - remove it. Detected by Coverity: CID 1164868. Signed-off-by: Christian Engelmayer Signed-off-by: David S. Miller diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c index 48b25c0..8bfb401 100644 --- a/net/ieee802154/6lowpan.c +++ b/net/ieee802154/6lowpan.c @@ -106,7 +106,6 @@ static int lowpan_header_create(struct sk_buff *skb, unsigned short type, const void *_daddr, const void *_saddr, unsigned int len) { - struct ipv6hdr *hdr; const u8 *saddr = _saddr; const u8 *daddr = _daddr; struct ieee802154_addr sa, da; @@ -117,8 +116,6 @@ static int lowpan_header_create(struct sk_buff *skb, if (type != ETH_P_IPV6) return 0; - hdr = ipv6_hdr(skb); - if (!saddr) saddr = dev->dev_addr; -- cgit v0.10.2 From a88f92b1283a485b6096b6fba3f84e266df026fc Mon Sep 17 00:00:00 2001 From: Christian Engelmayer Date: Sat, 8 Feb 2014 00:21:10 +0100 Subject: wan: dlci: Remove unused netdev_priv pointer Remove occurrences of unused pointer to network device private data in functions dlci_header() and dlci_receive(). Detected by Coverity: CID 139844, CID 139845. Signed-off-by: Christian Engelmayer Signed-off-by: David S. Miller diff --git a/drivers/net/wan/dlci.c b/drivers/net/wan/dlci.c index 0d1c759..19f7cb2 100644 --- a/drivers/net/wan/dlci.c +++ b/drivers/net/wan/dlci.c @@ -71,12 +71,9 @@ static int dlci_header(struct sk_buff *skb, struct net_device *dev, const void *saddr, unsigned len) { struct frhdr hdr; - struct dlci_local *dlp; unsigned int hlen; char *dest; - dlp = netdev_priv(dev); - hdr.control = FRAD_I_UI; switch (type) { @@ -107,11 +104,9 @@ static int dlci_header(struct sk_buff *skb, struct net_device *dev, static void dlci_receive(struct sk_buff *skb, struct net_device *dev) { - struct dlci_local *dlp; struct frhdr *hdr; int process, header; - dlp = netdev_priv(dev); if (!pskb_may_pull(skb, sizeof(*hdr))) { netdev_notice(dev, "invalid data no header\n"); dev->stats.rx_errors++; -- cgit v0.10.2 From 946c032e5a53992ea45e062ecb08670ba39b99e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBenczykowski?= Date: Fri, 7 Feb 2014 16:23:48 -0800 Subject: net: fix 'ip rule' iif/oif device rename MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ip rules with iif/oif references do not update: (detach/attach) across interface renames. Signed-off-by: Maciej Żenczykowski CC: Willem de Bruijn CC: Eric Dumazet CC: Chris Davis CC: Carlo Contavalli Google-Bug-Id: 12936021 Acked-by: Eric Dumazet Signed-off-by: David S. Miller diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c index f409e0b..185c341 100644 --- a/net/core/fib_rules.c +++ b/net/core/fib_rules.c @@ -745,6 +745,13 @@ static int fib_rules_event(struct notifier_block *this, unsigned long event, attach_rules(&ops->rules_list, dev); break; + case NETDEV_CHANGENAME: + list_for_each_entry(ops, &net->rules_ops, list) { + detach_rules(&ops->rules_list, dev); + attach_rules(&ops->rules_list, dev); + } + break; + case NETDEV_UNREGISTER: list_for_each_entry(ops, &net->rules_ops, list) detach_rules(&ops->rules_list, dev); -- cgit v0.10.2 From 4e6ecd442db707cd29cae1774dc951855d82df5e Mon Sep 17 00:00:00 2001 From: Christian Engelmayer Date: Sat, 8 Feb 2014 18:11:17 +0100 Subject: 3c59x: Remove unused pointer in vortex_eisa_cleanup() Remove unused network device private data pointer 'vp' in function vortex_eisa_cleanup(). Detected by Coverity: CID 139826. Signed-off-by: Christian Engelmayer Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/3com/3c59x.c b/drivers/net/ethernet/3com/3c59x.c index 0f4241c..238ccea 100644 --- a/drivers/net/ethernet/3com/3c59x.c +++ b/drivers/net/ethernet/3com/3c59x.c @@ -3294,7 +3294,6 @@ static int __init vortex_init(void) static void __exit vortex_eisa_cleanup(void) { - struct vortex_private *vp; void __iomem *ioaddr; #ifdef CONFIG_EISA @@ -3303,7 +3302,6 @@ static void __exit vortex_eisa_cleanup(void) #endif if (compaq_net_device) { - vp = netdev_priv(compaq_net_device); ioaddr = ioport_map(compaq_net_device->base_addr, VORTEX_TOTAL_SIZE); -- cgit v0.10.2 From 7653aabfbdc73c1567e29a9790701f5898ba1420 Mon Sep 17 00:00:00 2001 From: Raymond Wanyoike Date: Sun, 9 Feb 2014 00:01:02 +0300 Subject: net: qmi_wwan: add ZTE MF667 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver description files give these descriptions to the vendor specific ports on this modem: VID_19D2&PID_1270&MI_00: "ZTE MF667 Diagnostics Port" VID_19D2&PID_1270&MI_01: "ZTE MF667 AT Port" VID_19D2&PID_1270&MI_02: "ZTE MF667 ATExt2 Port" VID_19D2&PID_1270&MI_03: "ZTE MF667 ATExt Port" VID_19D2&PID_1270&MI_04: "ZTE MF667 USB Modem" VID_19D2&PID_1270&MI_05: "ZTE MF667 Network Adapter" Signed-off-by: Raymond Wanyoike Acked-by: Bjørn Mork Signed-off-by: David S. Miller diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index ef4a45a..ff5c871 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -712,6 +712,7 @@ static const struct usb_device_id products[] = { {QMI_FIXED_INTF(0x19d2, 0x1255, 3)}, {QMI_FIXED_INTF(0x19d2, 0x1255, 4)}, {QMI_FIXED_INTF(0x19d2, 0x1256, 4)}, + {QMI_FIXED_INTF(0x19d2, 0x1270, 5)}, /* ZTE MF667 */ {QMI_FIXED_INTF(0x19d2, 0x1401, 2)}, {QMI_FIXED_INTF(0x19d2, 0x1402, 2)}, /* ZTE MF60 */ {QMI_FIXED_INTF(0x19d2, 0x1424, 2)}, -- cgit v0.10.2 From 0fbb8297b5468eb7d269dc868b80df1fb166a4ab Mon Sep 17 00:00:00 2001 From: Christian Engelmayer Date: Sun, 9 Feb 2014 00:16:17 +0100 Subject: net: vxge: Remove unused device pointer Remove occurrences of unused struct __vxge_hw_device pointer in functions vxge_learn_mac() and vxge_rem_isr(). Detected by Coverity: CID 139839, CID 139842. Signed-off-by: Christian Engelmayer Reviewed-by: Jingoo Han Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/neterion/vxge/vxge-main.c b/drivers/net/ethernet/neterion/vxge/vxge-main.c index 1ded50ca..e46e869 100644 --- a/drivers/net/ethernet/neterion/vxge/vxge-main.c +++ b/drivers/net/ethernet/neterion/vxge/vxge-main.c @@ -726,9 +726,6 @@ static int vxge_learn_mac(struct vxgedev *vdev, u8 *mac_header) int vpath_idx = 0; enum vxge_hw_status status = VXGE_HW_OK; struct vxge_vpath *vpath = NULL; - struct __vxge_hw_device *hldev; - - hldev = pci_get_drvdata(vdev->pdev); mac_address = (u8 *)&mac_addr; memcpy(mac_address, mac_header, ETH_ALEN); @@ -2443,9 +2440,6 @@ static void vxge_rem_msix_isr(struct vxgedev *vdev) static void vxge_rem_isr(struct vxgedev *vdev) { - struct __vxge_hw_device *hldev; - hldev = pci_get_drvdata(vdev->pdev); - #ifdef CONFIG_PCI_MSI if (vdev->config.intr_type == MSI_X) { vxge_rem_msix_isr(vdev); -- cgit v0.10.2 From b10bd54c05a6c3c96549f4642d7de23c99b9853b Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Sun, 9 Feb 2014 23:30:32 +0100 Subject: tcp: correct code comment stating 3 min timeout for FIN_WAIT2, we only do 1 min As far as I can tell we have used a default of 60 seconds for FIN_WAIT2 timeout for ages (since 2.x times??). In any case, the timeout these days is 60 seconds, so the 3 min comment is wrong (and cost me a few minutes of my life when I was debugging a FIN_WAIT2 related problem in a userspace application and checked the kernel source for details). Signed-off-by: Jesper Juhl Signed-off-by: David S. Miller diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 4475b3b..9f3a2db 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2229,7 +2229,7 @@ adjudge_to_death: /* This is a (useful) BSD violating of the RFC. There is a * problem with TCP as specified in that the other end could * keep a socket open forever with no application left this end. - * We use a 3 minute timeout (about the same as BSD) then kill + * We use a 1 minute timeout (about the same as BSD) then kill * our end. If they send after that then tough - BUT: long enough * that we won't make the old 4*rto = almost no time - whoops * reset mistake. -- cgit v0.10.2 From ac1566ece497b2a37667cc5d4258edb0bf3b6836 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 30 Jan 2014 15:25:37 +0100 Subject: microblaze: Fix missing HZ macro Add missing param.h header because of HZ macro. It is causing compilation failure: In file included from include/linux/delay.h:14:0, from drivers/clk/qcom/reset.c:18: drivers/clk/qcom/reset.c: In function 'qcom_reset': arch/microblaze/include/asm/delay.h:39:35: error: 'HZ' undeclared (first use in this function) Signed-off-by: Michal Simek diff --git a/arch/microblaze/include/asm/delay.h b/arch/microblaze/include/asm/delay.h index 05b7d39..66fc24c 100644 --- a/arch/microblaze/include/asm/delay.h +++ b/arch/microblaze/include/asm/delay.h @@ -13,6 +13,8 @@ #ifndef _ASM_MICROBLAZE_DELAY_H #define _ASM_MICROBLAZE_DELAY_H +#include + extern inline void __delay(unsigned long loops) { asm volatile ("# __delay \n\t" \ -- cgit v0.10.2 From 4f3cbd79afd99cc5143b2beb126e7425af7f1ff9 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 30 Jan 2014 15:27:26 +0100 Subject: microblaze: Define readq and writeq IO helper function Some drivers check if readq/writeq functions are defined. If not internal driver functions are used which cause compilation failures. Signed-off-by: Michal Simek diff --git a/arch/microblaze/include/asm/io.h b/arch/microblaze/include/asm/io.h index a2cea72..3fbb7f1 100644 --- a/arch/microblaze/include/asm/io.h +++ b/arch/microblaze/include/asm/io.h @@ -89,6 +89,11 @@ static inline unsigned int readl(const volatile void __iomem *addr) { return le32_to_cpu(*(volatile unsigned int __force *)addr); } +#define readq readq +static inline u64 readq(const volatile void __iomem *addr) +{ + return le64_to_cpu(__raw_readq(addr)); +} static inline void writeb(unsigned char v, volatile void __iomem *addr) { *(volatile unsigned char __force *)addr = v; @@ -101,6 +106,7 @@ static inline void writel(unsigned int v, volatile void __iomem *addr) { *(volatile unsigned int __force *)addr = cpu_to_le32(v); } +#define writeq(b, addr) __raw_writeq(cpu_to_le64(b), addr) /* ioread and iowrite variants. thease are for now same as __raw_ * variants of accessors. we might check for endianess in the feature -- cgit v0.10.2 From a49f56eec54d864ba0fda838e4c8bf5c72f3eb08 Mon Sep 17 00:00:00 2001 From: "Edgar E. Iglesias" Date: Sat, 8 Feb 2014 02:31:31 +0000 Subject: microblaze: Fix a typo when disabling stack protection Correct a typo causing the stack protector to be left enabled. 0xFFFFFFF -> 0xFFFFFFFF Signed-off-by: Edgar E. Iglesias Tested-by: Guenter Roeck Signed-off-by: Michal Simek diff --git a/arch/microblaze/kernel/head.S b/arch/microblaze/kernel/head.S index b7fb043..17645b2 100644 --- a/arch/microblaze/kernel/head.S +++ b/arch/microblaze/kernel/head.S @@ -66,7 +66,7 @@ real_start: mts rmsr, r0 /* Disable stack protection from bootloader */ mts rslr, r0 - addi r8, r0, 0xFFFFFFF + addi r8, r0, 0xFFFFFFFF mts rshr, r8 /* * According to Xilinx, msrclr instruction behaves like 'mfs rX,rpc' -- cgit v0.10.2 From ef8e39b51f24c8ac907e1f1995910ee3083375e0 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 10 Feb 2014 11:43:41 +0100 Subject: ALSA: hda - Fix undefined symbol due to builtin/module mixup Even after the fix for leftover kconfig handling (commit f8f1becf), the current code still doesn't handle properly the builtin/module mixup case between the core snd-hda-codec and other codec drivers. For example, when CONFIG_SND_HDA_INTEL=y and CONFIG_SND_HDA_CODEC_HDMI=m, it'll end up with an unresolved symbol snd_hda_parse_hdmi_codec. This patch fixes the issue. Now codec->parser points to the parser object *only* when a module (either generic or HDMI parser) is loaded and bound. When a builtin symbol is used, codec->parser still points to NULL. This is the difference from the previous versions. Fixes: f8f1becfa4ac ('ALSA: hda - Fix leftover ifdef checks after modularization') Reported-by: Fengguang Wu Signed-off-by: Takashi Iwai diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 69acbf7..dafcf82 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -1339,23 +1339,15 @@ get_hda_cvt_setup(struct hda_codec *codec, hda_nid_t nid) /* * Dynamic symbol binding for the codec parsers */ -#ifdef MODULE -#define load_parser_sym(sym) ((int (*)(struct hda_codec *))symbol_request(sym)) -#define unload_parser_addr(addr) symbol_put_addr(addr) -#else -#define load_parser_sym(sym) (sym) -#define unload_parser_addr(addr) do {} while (0) -#endif #define load_parser(codec, sym) \ - ((codec)->parser = load_parser_sym(sym)) + ((codec)->parser = (int (*)(struct hda_codec *))symbol_request(sym)) static void unload_parser(struct hda_codec *codec) { - if (codec->parser) { - unload_parser_addr(codec->parser); - codec->parser = NULL; - } + if (codec->parser) + symbol_put_addr(codec->parser); + codec->parser = NULL; } /* @@ -1620,12 +1612,20 @@ int snd_hda_codec_configure(struct hda_codec *codec) patch = codec->preset->patch; if (!patch) { unload_parser(codec); /* to be sure */ - if (is_likely_hdmi_codec(codec)) + if (is_likely_hdmi_codec(codec)) { +#if IS_MODULE(CONFIG_SND_HDA_CODEC_HDMI) patch = load_parser(codec, snd_hda_parse_hdmi_codec); -#if IS_ENABLED(CONFIG_SND_HDA_GENERIC) - if (!patch) +#elif IS_BUILTIN(CONFIG_SND_HDA_CODEC_HDMI) + patch = snd_hda_parse_hdmi_codec; +#endif + } + if (!patch) { +#if IS_MODULE(CONFIG_SND_HDA_GENERIC) patch = load_parser(codec, snd_hda_parse_generic_codec); +#elif IS_BUILTIN(CONFIG_SND_HDA_GENERIC) + patch = snd_hda_parse_generic_codec; #endif + } if (!patch) { printk(KERN_ERR "hda-codec: No codec parser is available\n"); return -ENODEV; -- cgit v0.10.2 From 0a8e5c3d5f0f4929761e6a5bef5358f0ccd8810c Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 10 Feb 2014 13:44:20 +0100 Subject: ACPI / dock: Use acpi_device_enumerated() to check if dock is present After commit 202317a573b2 (ACPI / scan: Add acpi_device objects for all device nodes in the namespace) acpi_bus_get_device() will always return 0 for dock devices in dock_notify(), so the dock station docking code under ACPI_NOTIFY_DEVICE_CHECK will never be executed and docking will not work as a result of that. Fix the problem by making dock_notify() use acpi_device_enumerated() to check the presence of the device instead of checking the return value of acpi_bus_get_device(). Fixes: 202317a573b2 (ACPI / scan: Add acpi_device objects for all device nodes in the namespace) Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index c431c88..e9b3081 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -609,7 +609,7 @@ static int handle_eject_request(struct dock_station *ds, u32 event) static void dock_notify(struct dock_station *ds, u32 event) { acpi_handle handle = ds->handle; - struct acpi_device *ad; + struct acpi_device *adev = NULL; int surprise_removal = 0; /* @@ -632,7 +632,8 @@ static void dock_notify(struct dock_station *ds, u32 event) switch (event) { case ACPI_NOTIFY_BUS_CHECK: case ACPI_NOTIFY_DEVICE_CHECK: - if (!dock_in_progress(ds) && acpi_bus_get_device(handle, &ad)) { + acpi_bus_get_device(handle, &adev); + if (!dock_in_progress(ds) && !acpi_device_enumerated(adev)) { begin_dock(ds); dock(ds); if (!dock_present(ds)) { -- cgit v0.10.2 From 30a91cb4ef385fe1b260df204ef314d86fff2850 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 10 Feb 2014 03:24:38 -0800 Subject: blk-mq: rework I/O completions Rework I/O completions to work more like the old code path. blk_mq_end_io now stays out of the business of deferring completions to others CPUs and calling blk_mark_rq_complete. The latter is very important to allow completing requests that have timed out and thus are already marked completed, the former allows using the IPI callout even for driver specific completions instead of having to reimplement them. Signed-off-by: Christoph Hellwig Signed-off-by: Jens Axboe diff --git a/block/blk-mq.c b/block/blk-mq.c index cee9623..14c8f35 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -326,7 +326,7 @@ static void blk_mq_bio_endio(struct request *rq, struct bio *bio, int error) bio_endio(bio, error); } -void blk_mq_complete_request(struct request *rq, int error) +void blk_mq_end_io(struct request *rq, int error) { struct bio *bio = rq->bio; unsigned int bytes = 0; @@ -351,46 +351,53 @@ void blk_mq_complete_request(struct request *rq, int error) else blk_mq_free_request(rq); } +EXPORT_SYMBOL(blk_mq_end_io); -void __blk_mq_end_io(struct request *rq, int error) -{ - if (!blk_mark_rq_complete(rq)) - blk_mq_complete_request(rq, error); -} - -static void blk_mq_end_io_remote(void *data) +static void __blk_mq_complete_request_remote(void *data) { struct request *rq = data; - __blk_mq_end_io(rq, rq->errors); + rq->q->softirq_done_fn(rq); } -/* - * End IO on this request on a multiqueue enabled driver. We'll either do - * it directly inline, or punt to a local IPI handler on the matching - * remote CPU. - */ -void blk_mq_end_io(struct request *rq, int error) +void __blk_mq_complete_request(struct request *rq) { struct blk_mq_ctx *ctx = rq->mq_ctx; int cpu; - if (!ctx->ipi_redirect) - return __blk_mq_end_io(rq, error); + if (!ctx->ipi_redirect) { + rq->q->softirq_done_fn(rq); + return; + } cpu = get_cpu(); if (cpu != ctx->cpu && cpu_online(ctx->cpu)) { - rq->errors = error; - rq->csd.func = blk_mq_end_io_remote; + rq->csd.func = __blk_mq_complete_request_remote; rq->csd.info = rq; rq->csd.flags = 0; __smp_call_function_single(ctx->cpu, &rq->csd, 0); } else { - __blk_mq_end_io(rq, error); + rq->q->softirq_done_fn(rq); } put_cpu(); } -EXPORT_SYMBOL(blk_mq_end_io); + +/** + * blk_mq_complete_request - end I/O on a request + * @rq: the request being processed + * + * Description: + * Ends all I/O on a request. It does not handle partial completions. + * The actual completion happens out-of-order, through a IPI handler. + **/ +void blk_mq_complete_request(struct request *rq) +{ + if (unlikely(blk_should_fake_timeout(rq->q))) + return; + if (!blk_mark_rq_complete(rq)) + __blk_mq_complete_request(rq); +} +EXPORT_SYMBOL(blk_mq_complete_request); static void blk_mq_start_request(struct request *rq) { @@ -1399,6 +1406,9 @@ struct request_queue *blk_mq_init_queue(struct blk_mq_reg *reg, if (reg->timeout) blk_queue_rq_timeout(q, reg->timeout); + if (reg->ops->complete) + blk_queue_softirq_done(q, reg->ops->complete); + blk_mq_init_flush(q); blk_mq_init_cpu_queues(q, reg->nr_hw_queues); diff --git a/block/blk-mq.h b/block/blk-mq.h index 5c39179..f29b645 100644 --- a/block/blk-mq.h +++ b/block/blk-mq.h @@ -22,8 +22,7 @@ struct blk_mq_ctx { struct kobject kobj; }; -void __blk_mq_end_io(struct request *rq, int error); -void blk_mq_complete_request(struct request *rq, int error); +void __blk_mq_complete_request(struct request *rq); void blk_mq_run_request(struct request *rq, bool run_queue, bool async); void blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx, bool async); void blk_mq_init_flush(struct request_queue *q); diff --git a/block/blk-timeout.c b/block/blk-timeout.c index bba81c9..d96f706 100644 --- a/block/blk-timeout.c +++ b/block/blk-timeout.c @@ -91,7 +91,7 @@ static void blk_rq_timed_out(struct request *req) case BLK_EH_HANDLED: /* Can we use req->errors here? */ if (q->mq_ops) - blk_mq_complete_request(req, req->errors); + __blk_mq_complete_request(req); else __blk_complete_request(req); break; diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h index b7638be..468be242d 100644 --- a/include/linux/blk-mq.h +++ b/include/linux/blk-mq.h @@ -86,6 +86,8 @@ struct blk_mq_ops { */ rq_timed_out_fn *timeout; + softirq_done_fn *complete; + /* * Override for hctx allocations (should probably go) */ @@ -137,6 +139,8 @@ void blk_mq_free_single_hw_queue(struct blk_mq_hw_ctx *, unsigned int); void blk_mq_end_io(struct request *rq, int error); +void blk_mq_complete_request(struct request *rq); + void blk_mq_stop_hw_queue(struct blk_mq_hw_ctx *hctx); void blk_mq_start_hw_queue(struct blk_mq_hw_ctx *hctx); void blk_mq_stop_hw_queues(struct request_queue *q); -- cgit v0.10.2 From 5124c285797aa33d5fdb909fbe808a61bcc5eb9d Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 10 Feb 2014 03:24:39 -0800 Subject: virtio_blk: use blk_mq_complete_request Make sure to complete requests on the submitting CPU. Previously this was done in blk_mq_end_io, but the responsibility shifted to the drivers. Signed-off-by: Christoph Hellwig Signed-off-by: Jens Axboe diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 6a680d4..b1cb3f4 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -110,9 +110,9 @@ static int __virtblk_add_req(struct virtqueue *vq, return virtqueue_add_sgs(vq, sgs, num_out, num_in, vbr, GFP_ATOMIC); } -static inline void virtblk_request_done(struct virtblk_req *vbr) +static inline void virtblk_request_done(struct request *req) { - struct request *req = vbr->req; + struct virtblk_req *vbr = req->special; int error = virtblk_result(vbr); if (req->cmd_type == REQ_TYPE_BLOCK_PC) { @@ -138,7 +138,7 @@ static void virtblk_done(struct virtqueue *vq) do { virtqueue_disable_cb(vq); while ((vbr = virtqueue_get_buf(vblk->vq, &len)) != NULL) { - virtblk_request_done(vbr); + blk_mq_complete_request(vbr->req); req_done = true; } if (unlikely(virtqueue_is_broken(vq))) @@ -479,6 +479,7 @@ static struct blk_mq_ops virtio_mq_ops = { .map_queue = blk_mq_map_queue, .alloc_hctx = blk_mq_alloc_single_hw_queue, .free_hctx = blk_mq_free_single_hw_queue, + .complete = virtblk_request_done, }; static struct blk_mq_reg virtio_mq_reg = { -- cgit v0.10.2 From ce2c350b2cfe5b5ca5023a6b1ec4d21821d39add Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 10 Feb 2014 03:24:40 -0800 Subject: null_blk: use blk_complete_request and blk_mq_complete_request Use the block layer helpers for CPU-local completions instead of reimplementing them locally. Signed-off-by: Christoph Hellwig Signed-off-by: Jens Axboe diff --git a/drivers/block/null_blk.c b/drivers/block/null_blk.c index cc801cd..091b9ea 100644 --- a/drivers/block/null_blk.c +++ b/drivers/block/null_blk.c @@ -60,7 +60,9 @@ enum { NULL_IRQ_NONE = 0, NULL_IRQ_SOFTIRQ = 1, NULL_IRQ_TIMER = 2, +}; +enum { NULL_Q_BIO = 0, NULL_Q_RQ = 1, NULL_Q_MQ = 2, @@ -172,18 +174,20 @@ static struct nullb_cmd *alloc_cmd(struct nullb_queue *nq, int can_wait) static void end_cmd(struct nullb_cmd *cmd) { - if (cmd->rq) { - if (queue_mode == NULL_Q_MQ) - blk_mq_end_io(cmd->rq, 0); - else { - INIT_LIST_HEAD(&cmd->rq->queuelist); - blk_end_request_all(cmd->rq, 0); - } - } else if (cmd->bio) + switch (queue_mode) { + case NULL_Q_MQ: + blk_mq_end_io(cmd->rq, 0); + return; + case NULL_Q_RQ: + INIT_LIST_HEAD(&cmd->rq->queuelist); + blk_end_request_all(cmd->rq, 0); + break; + case NULL_Q_BIO: bio_endio(cmd->bio, 0); + break; + } - if (queue_mode != NULL_Q_MQ) - free_cmd(cmd); + free_cmd(cmd); } static enum hrtimer_restart null_cmd_timer_expired(struct hrtimer *timer) @@ -222,62 +226,31 @@ static void null_cmd_end_timer(struct nullb_cmd *cmd) static void null_softirq_done_fn(struct request *rq) { - blk_end_request_all(rq, 0); -} - -#ifdef CONFIG_SMP - -static void null_ipi_cmd_end_io(void *data) -{ - struct completion_queue *cq; - struct llist_node *entry, *next; - struct nullb_cmd *cmd; - - cq = &per_cpu(completion_queues, smp_processor_id()); - - entry = llist_del_all(&cq->list); - entry = llist_reverse_order(entry); - - while (entry) { - next = entry->next; - cmd = llist_entry(entry, struct nullb_cmd, ll_list); - end_cmd(cmd); - entry = next; - } -} - -static void null_cmd_end_ipi(struct nullb_cmd *cmd) -{ - struct call_single_data *data = &cmd->csd; - int cpu = get_cpu(); - struct completion_queue *cq = &per_cpu(completion_queues, cpu); - - cmd->ll_list.next = NULL; - - if (llist_add(&cmd->ll_list, &cq->list)) { - data->func = null_ipi_cmd_end_io; - data->flags = 0; - __smp_call_function_single(cpu, data, 0); - } - - put_cpu(); + end_cmd(rq->special); } -#endif /* CONFIG_SMP */ - static inline void null_handle_cmd(struct nullb_cmd *cmd) { /* Complete IO by inline, softirq or timer */ switch (irqmode) { - case NULL_IRQ_NONE: - end_cmd(cmd); - break; case NULL_IRQ_SOFTIRQ: -#ifdef CONFIG_SMP - null_cmd_end_ipi(cmd); -#else + switch (queue_mode) { + case NULL_Q_MQ: + blk_mq_complete_request(cmd->rq); + break; + case NULL_Q_RQ: + blk_complete_request(cmd->rq); + break; + case NULL_Q_BIO: + /* + * XXX: no proper submitting cpu information available. + */ + end_cmd(cmd); + break; + } + break; + case NULL_IRQ_NONE: end_cmd(cmd); -#endif break; case NULL_IRQ_TIMER: null_cmd_end_timer(cmd); @@ -413,6 +386,7 @@ static struct blk_mq_ops null_mq_ops = { .queue_rq = null_queue_rq, .map_queue = blk_mq_map_queue, .init_hctx = null_init_hctx, + .complete = null_softirq_done_fn, }; static struct blk_mq_reg null_mq_reg = { @@ -611,13 +585,6 @@ static int __init null_init(void) { unsigned int i; -#if !defined(CONFIG_SMP) - if (irqmode == NULL_IRQ_SOFTIRQ) { - pr_warn("null_blk: softirq completions not available.\n"); - pr_warn("null_blk: using direct completions.\n"); - irqmode = NULL_IRQ_NONE; - } -#endif if (bs > PAGE_SIZE) { pr_warn("null_blk: invalid block size\n"); pr_warn("null_blk: defaults block size to %lu\n", PAGE_SIZE); -- cgit v0.10.2 From 18741986a4b1dc4b1f171634c4191abc3b0fa023 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 10 Feb 2014 09:29:00 -0700 Subject: blk-mq: rework flush sequencing logic Witch to using a preallocated flush_rq for blk-mq similar to what's done with the old request path. This allows us to set up the request properly with a tag from the actually allowed range and ->rq_disk as needed by some drivers. To make life easier we also switch to dynamic allocation of ->flush_rq for the old path. This effectively reverts most of "blk-mq: fix for flush deadlock" and "blk-mq: Don't reserve a tag for flush request" Signed-off-by: Christoph Hellwig Signed-off-by: Jens Axboe diff --git a/block/blk-core.c b/block/blk-core.c index 06636f3..853f927 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -693,11 +693,20 @@ blk_init_queue_node(request_fn_proc *rfn, spinlock_t *lock, int node_id) if (!uninit_q) return NULL; + uninit_q->flush_rq = kzalloc(sizeof(struct request), GFP_KERNEL); + if (!uninit_q->flush_rq) + goto out_cleanup_queue; + q = blk_init_allocated_queue(uninit_q, rfn, lock); if (!q) - blk_cleanup_queue(uninit_q); - + goto out_free_flush_rq; return q; + +out_free_flush_rq: + kfree(uninit_q->flush_rq); +out_cleanup_queue: + blk_cleanup_queue(uninit_q); + return NULL; } EXPORT_SYMBOL(blk_init_queue_node); @@ -1127,7 +1136,7 @@ static struct request *blk_old_get_request(struct request_queue *q, int rw, struct request *blk_get_request(struct request_queue *q, int rw, gfp_t gfp_mask) { if (q->mq_ops) - return blk_mq_alloc_request(q, rw, gfp_mask, false); + return blk_mq_alloc_request(q, rw, gfp_mask); else return blk_old_get_request(q, rw, gfp_mask); } diff --git a/block/blk-flush.c b/block/blk-flush.c index 9143e85..66e2b69 100644 --- a/block/blk-flush.c +++ b/block/blk-flush.c @@ -130,20 +130,26 @@ static void blk_flush_restore_request(struct request *rq) blk_clear_rq_complete(rq); } -static void mq_flush_data_run(struct work_struct *work) +static void mq_flush_run(struct work_struct *work) { struct request *rq; - rq = container_of(work, struct request, mq_flush_data); + rq = container_of(work, struct request, mq_flush_work); memset(&rq->csd, 0, sizeof(rq->csd)); blk_mq_run_request(rq, true, false); } -static void blk_mq_flush_data_insert(struct request *rq) +static bool blk_flush_queue_rq(struct request *rq) { - INIT_WORK(&rq->mq_flush_data, mq_flush_data_run); - kblockd_schedule_work(rq->q, &rq->mq_flush_data); + if (rq->q->mq_ops) { + INIT_WORK(&rq->mq_flush_work, mq_flush_run); + kblockd_schedule_work(rq->q, &rq->mq_flush_work); + return false; + } else { + list_add_tail(&rq->queuelist, &rq->q->queue_head); + return true; + } } /** @@ -187,12 +193,7 @@ static bool blk_flush_complete_seq(struct request *rq, unsigned int seq, case REQ_FSEQ_DATA: list_move_tail(&rq->flush.list, &q->flush_data_in_flight); - if (q->mq_ops) - blk_mq_flush_data_insert(rq); - else { - list_add(&rq->queuelist, &q->queue_head); - queued = true; - } + queued = blk_flush_queue_rq(rq); break; case REQ_FSEQ_DONE: @@ -216,9 +217,6 @@ static bool blk_flush_complete_seq(struct request *rq, unsigned int seq, } kicked = blk_kick_flush(q); - /* blk_mq_run_flush will run queue */ - if (q->mq_ops) - return queued; return kicked | queued; } @@ -230,10 +228,9 @@ static void flush_end_io(struct request *flush_rq, int error) struct request *rq, *n; unsigned long flags = 0; - if (q->mq_ops) { - blk_mq_free_request(flush_rq); + if (q->mq_ops) spin_lock_irqsave(&q->mq_flush_lock, flags); - } + running = &q->flush_queue[q->flush_running_idx]; BUG_ON(q->flush_pending_idx == q->flush_running_idx); @@ -263,48 +260,14 @@ static void flush_end_io(struct request *flush_rq, int error) * kblockd. */ if (queued || q->flush_queue_delayed) { - if (!q->mq_ops) - blk_run_queue_async(q); - else - /* - * This can be optimized to only run queues with requests - * queued if necessary. - */ - blk_mq_run_queues(q, true); + WARN_ON(q->mq_ops); + blk_run_queue_async(q); } q->flush_queue_delayed = 0; if (q->mq_ops) spin_unlock_irqrestore(&q->mq_flush_lock, flags); } -static void mq_flush_work(struct work_struct *work) -{ - struct request_queue *q; - struct request *rq; - - q = container_of(work, struct request_queue, mq_flush_work); - - rq = blk_mq_alloc_request(q, WRITE_FLUSH|REQ_FLUSH_SEQ, - __GFP_WAIT|GFP_ATOMIC, false); - rq->cmd_type = REQ_TYPE_FS; - rq->end_io = flush_end_io; - - blk_mq_run_request(rq, true, false); -} - -/* - * We can't directly use q->flush_rq, because it doesn't have tag and is not in - * hctx->rqs[]. so we must allocate a new request, since we can't sleep here, - * so offload the work to workqueue. - * - * Note: we assume a flush request finished in any hardware queue will flush - * the whole disk cache. - */ -static void mq_run_flush(struct request_queue *q) -{ - kblockd_schedule_work(q, &q->mq_flush_work); -} - /** * blk_kick_flush - consider issuing flush request * @q: request_queue being kicked @@ -339,19 +302,31 @@ static bool blk_kick_flush(struct request_queue *q) * different from running_idx, which means flush is in flight. */ q->flush_pending_idx ^= 1; + if (q->mq_ops) { - mq_run_flush(q); - return true; + struct blk_mq_ctx *ctx = first_rq->mq_ctx; + struct blk_mq_hw_ctx *hctx = q->mq_ops->map_queue(q, ctx->cpu); + + blk_mq_rq_init(hctx, q->flush_rq); + q->flush_rq->mq_ctx = ctx; + + /* + * Reuse the tag value from the fist waiting request, + * with blk-mq the tag is generated during request + * allocation and drivers can rely on it being inside + * the range they asked for. + */ + q->flush_rq->tag = first_rq->tag; + } else { + blk_rq_init(q, q->flush_rq); } - blk_rq_init(q, &q->flush_rq); - q->flush_rq.cmd_type = REQ_TYPE_FS; - q->flush_rq.cmd_flags = WRITE_FLUSH | REQ_FLUSH_SEQ; - q->flush_rq.rq_disk = first_rq->rq_disk; - q->flush_rq.end_io = flush_end_io; + q->flush_rq->cmd_type = REQ_TYPE_FS; + q->flush_rq->cmd_flags = WRITE_FLUSH | REQ_FLUSH_SEQ; + q->flush_rq->rq_disk = first_rq->rq_disk; + q->flush_rq->end_io = flush_end_io; - list_add_tail(&q->flush_rq.queuelist, &q->queue_head); - return true; + return blk_flush_queue_rq(q->flush_rq); } static void flush_data_end_io(struct request *rq, int error) @@ -407,11 +382,8 @@ void blk_insert_flush(struct request *rq) /* * @policy now records what operations need to be done. Adjust * REQ_FLUSH and FUA for the driver. - * We keep REQ_FLUSH for mq to track flush requests. For !FUA, - * we never dispatch the request directly. */ - if (rq->cmd_flags & REQ_FUA) - rq->cmd_flags &= ~REQ_FLUSH; + rq->cmd_flags &= ~REQ_FLUSH; if (!(fflags & REQ_FUA)) rq->cmd_flags &= ~REQ_FUA; @@ -560,5 +532,4 @@ EXPORT_SYMBOL(blkdev_issue_flush); void blk_mq_init_flush(struct request_queue *q) { spin_lock_init(&q->mq_flush_lock); - INIT_WORK(&q->mq_flush_work, mq_flush_work); } diff --git a/block/blk-mq.c b/block/blk-mq.c index 14c8f35..a59b056 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -194,27 +194,9 @@ static void blk_mq_rq_ctx_init(struct request_queue *q, struct blk_mq_ctx *ctx, } static struct request *__blk_mq_alloc_request(struct blk_mq_hw_ctx *hctx, - gfp_t gfp, bool reserved, - int rw) + gfp_t gfp, bool reserved) { - struct request *req; - bool is_flush = false; - /* - * flush need allocate a request, leave at least one request for - * non-flush IO to avoid deadlock - */ - if ((rw & REQ_FLUSH) && !(rw & REQ_FLUSH_SEQ)) { - if (atomic_inc_return(&hctx->pending_flush) >= - hctx->queue_depth - hctx->reserved_tags - 1) { - atomic_dec(&hctx->pending_flush); - return NULL; - } - is_flush = true; - } - req = blk_mq_alloc_rq(hctx, gfp, reserved); - if (!req && is_flush) - atomic_dec(&hctx->pending_flush); - return req; + return blk_mq_alloc_rq(hctx, gfp, reserved); } static struct request *blk_mq_alloc_request_pinned(struct request_queue *q, @@ -227,7 +209,7 @@ static struct request *blk_mq_alloc_request_pinned(struct request_queue *q, struct blk_mq_ctx *ctx = blk_mq_get_ctx(q); struct blk_mq_hw_ctx *hctx = q->mq_ops->map_queue(q, ctx->cpu); - rq = __blk_mq_alloc_request(hctx, gfp & ~__GFP_WAIT, reserved, rw); + rq = __blk_mq_alloc_request(hctx, gfp & ~__GFP_WAIT, reserved); if (rq) { blk_mq_rq_ctx_init(q, ctx, rq, rw); break; @@ -244,15 +226,14 @@ static struct request *blk_mq_alloc_request_pinned(struct request_queue *q, return rq; } -struct request *blk_mq_alloc_request(struct request_queue *q, int rw, - gfp_t gfp, bool reserved) +struct request *blk_mq_alloc_request(struct request_queue *q, int rw, gfp_t gfp) { struct request *rq; if (blk_mq_queue_enter(q)) return NULL; - rq = blk_mq_alloc_request_pinned(q, rw, gfp, reserved); + rq = blk_mq_alloc_request_pinned(q, rw, gfp, false); if (rq) blk_mq_put_ctx(rq->mq_ctx); return rq; @@ -276,7 +257,7 @@ EXPORT_SYMBOL(blk_mq_alloc_reserved_request); /* * Re-init and set pdu, if we have it */ -static void blk_mq_rq_init(struct blk_mq_hw_ctx *hctx, struct request *rq) +void blk_mq_rq_init(struct blk_mq_hw_ctx *hctx, struct request *rq) { blk_rq_init(hctx->queue, rq); @@ -290,9 +271,6 @@ static void __blk_mq_free_request(struct blk_mq_hw_ctx *hctx, const int tag = rq->tag; struct request_queue *q = rq->q; - if ((rq->cmd_flags & REQ_FLUSH) && !(rq->cmd_flags & REQ_FLUSH_SEQ)) - atomic_dec(&hctx->pending_flush); - blk_mq_rq_init(hctx, rq); blk_mq_put_tag(hctx->tags, tag); @@ -946,14 +924,14 @@ static void blk_mq_make_request(struct request_queue *q, struct bio *bio) hctx = q->mq_ops->map_queue(q, ctx->cpu); trace_block_getrq(q, bio, rw); - rq = __blk_mq_alloc_request(hctx, GFP_ATOMIC, false, bio->bi_rw); + rq = __blk_mq_alloc_request(hctx, GFP_ATOMIC, false); if (likely(rq)) - blk_mq_rq_ctx_init(q, ctx, rq, bio->bi_rw); + blk_mq_rq_ctx_init(q, ctx, rq, rw); else { blk_mq_put_ctx(ctx); trace_block_sleeprq(q, bio, rw); - rq = blk_mq_alloc_request_pinned(q, bio->bi_rw, - __GFP_WAIT|GFP_ATOMIC, false); + rq = blk_mq_alloc_request_pinned(q, rw, __GFP_WAIT|GFP_ATOMIC, + false); ctx = rq->mq_ctx; hctx = q->mq_ops->map_queue(q, ctx->cpu); } @@ -1230,9 +1208,7 @@ static int blk_mq_init_hw_queues(struct request_queue *q, hctx->queue_num = i; hctx->flags = reg->flags; hctx->queue_depth = reg->queue_depth; - hctx->reserved_tags = reg->reserved_tags; hctx->cmd_size = reg->cmd_size; - atomic_set(&hctx->pending_flush, 0); blk_mq_init_cpu_notifier(&hctx->cpu_notifier, blk_mq_hctx_notify, hctx); @@ -1412,9 +1388,14 @@ struct request_queue *blk_mq_init_queue(struct blk_mq_reg *reg, blk_mq_init_flush(q); blk_mq_init_cpu_queues(q, reg->nr_hw_queues); - if (blk_mq_init_hw_queues(q, reg, driver_data)) + q->flush_rq = kzalloc(round_up(sizeof(struct request) + reg->cmd_size, + cache_line_size()), GFP_KERNEL); + if (!q->flush_rq) goto err_hw; + if (blk_mq_init_hw_queues(q, reg, driver_data)) + goto err_flush_rq; + blk_mq_map_swqueue(q); mutex_lock(&all_q_mutex); @@ -1422,6 +1403,9 @@ struct request_queue *blk_mq_init_queue(struct blk_mq_reg *reg, mutex_unlock(&all_q_mutex); return q; + +err_flush_rq: + kfree(q->flush_rq); err_hw: kfree(q->mq_map); err_map: diff --git a/block/blk-mq.h b/block/blk-mq.h index f29b645..ed0035c 100644 --- a/block/blk-mq.h +++ b/block/blk-mq.h @@ -28,6 +28,7 @@ void blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx, bool async); void blk_mq_init_flush(struct request_queue *q); void blk_mq_drain_queue(struct request_queue *q); void blk_mq_free_queue(struct request_queue *q); +void blk_mq_rq_init(struct blk_mq_hw_ctx *hctx, struct request *rq); /* * CPU hotplug helpers diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c index 8095c4a..7500f87 100644 --- a/block/blk-sysfs.c +++ b/block/blk-sysfs.c @@ -549,6 +549,8 @@ static void blk_release_queue(struct kobject *kobj) if (q->mq_ops) blk_mq_free_queue(q); + kfree(q->flush_rq); + blk_trace_shutdown(q); bdi_destroy(&q->backing_dev_info); diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h index 468be242d..18ba8a6 100644 --- a/include/linux/blk-mq.h +++ b/include/linux/blk-mq.h @@ -36,15 +36,12 @@ struct blk_mq_hw_ctx { struct list_head page_list; struct blk_mq_tags *tags; - atomic_t pending_flush; - unsigned long queued; unsigned long run; #define BLK_MQ_MAX_DISPATCH_ORDER 10 unsigned long dispatched[BLK_MQ_MAX_DISPATCH_ORDER]; unsigned int queue_depth; - unsigned int reserved_tags; unsigned int numa_node; unsigned int cmd_size; /* per-request extra data */ @@ -129,7 +126,7 @@ void blk_mq_insert_request(struct request_queue *, struct request *, void blk_mq_run_queues(struct request_queue *q, bool async); void blk_mq_free_request(struct request *rq); bool blk_mq_can_queue(struct blk_mq_hw_ctx *); -struct request *blk_mq_alloc_request(struct request_queue *q, int rw, gfp_t gfp, bool reserved); +struct request *blk_mq_alloc_request(struct request_queue *q, int rw, gfp_t gfp); struct request *blk_mq_alloc_reserved_request(struct request_queue *q, int rw, gfp_t gfp); struct request *blk_mq_rq_from_tag(struct request_queue *q, unsigned int tag); diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 0375654..b2d25ec 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -101,7 +101,7 @@ struct request { }; union { struct call_single_data csd; - struct work_struct mq_flush_data; + struct work_struct mq_flush_work; }; struct request_queue *q; @@ -451,13 +451,8 @@ struct request_queue { unsigned long flush_pending_since; struct list_head flush_queue[2]; struct list_head flush_data_in_flight; - union { - struct request flush_rq; - struct { - spinlock_t mq_flush_lock; - struct work_struct mq_flush_work; - }; - }; + struct request *flush_rq; + spinlock_t mq_flush_lock; struct mutex sysfs_lock; -- cgit v0.10.2 From 11c94444074f40b479a05f6657d935204e992f2e Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Mon, 10 Feb 2014 10:39:18 -0700 Subject: block: Fix type mismatch in ssize_t_blk_mq_tag_sysfs_show cppcheck detected following format string mismatch. [blk-mq-tag.c:201]: (warning) %u in format string (no. 1) requires 'unsigned int' but the argument type is 'int'. Change "cpu" from int to unsigned int, because the cpu never become minus value. Signed-off-by: Masanari Iida Signed-off-by: Jens Axboe diff --git a/block/blk-mq-tag.c b/block/blk-mq-tag.c index d64a02f..4025050 100644 --- a/block/blk-mq-tag.c +++ b/block/blk-mq-tag.c @@ -182,7 +182,7 @@ void blk_mq_free_tags(struct blk_mq_tags *tags) ssize_t blk_mq_tag_sysfs_show(struct blk_mq_tags *tags, char *page) { char *orig_page = page; - int cpu; + unsigned int cpu; if (!tags) return 0; -- cgit v0.10.2 From 29ffa48fa64fcdfc71d80593c8ae79248bc27677 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 4 Feb 2014 13:30:05 +0100 Subject: ARM: pxa: fix compilation problem on AM300EPD board MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This board fails compilation like this: arch/arm/mach-pxa/am300epd.c: In function ‘am300_cleanup’: arch/arm/mach-pxa/am300epd.c:179:2: error: implicit declaration of function ‘PXA_GPIO_TO_IRQ’ [-Werror=implicit-function-declaration] free_irq(PXA_GPIO_TO_IRQ(RDY_GPIO_PIN), par); This was caused by commit 88f718e3fa4d67f3a8dbe79a2f97d722323e4051 "ARM: pxa: delete the custom GPIO header" This is because it was previously getting the macro PXA_GPIO_TO_IRQ implicitly from which in turn implicitly included which in turn included . Add the missing include so that the board compiles again. Reported-by: Arnd Bergmann Signed-off-by: Linus Walleij Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-pxa/am300epd.c b/arch/arm/mach-pxa/am300epd.c index c9f309a..8b90c4f 100644 --- a/arch/arm/mach-pxa/am300epd.c +++ b/arch/arm/mach-pxa/am300epd.c @@ -30,6 +30,7 @@ #include #include +#include #include #include "generic.h" -- cgit v0.10.2 From 9705e74671f0e4f994d86b00cecf441917c64a66 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 4 Feb 2014 13:53:07 +0100 Subject: ARM: pxa: fix various compilation problems MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Due to commit 88f718e3fa4d67f3a8dbe79a2f97d722323e4051 "ARM: pxa: delete the custom GPIO header" some drivers fail compilation, for example like this: In file included from sound/soc/pxa/spitz.c:28:0: sound/soc/pxa/spitz.c: In function ‘spitz_ext_control’: arch/arm/mach-pxa/include/mach/spitz.h:111:30: error: ‘PXA_NR_BUILTIN_GPIO’ undeclared (first use in this function) #define SPITZ_SCP_GPIO_BASE (PXA_NR_BUILTIN_GPIO) (etc.) This is caused by implicit inclusion of from various board-specific headers under in the PXA platform. So we take a sweep over these, and for every such header that uses PXA_NR_BUILTIN_GPIO or PXA_GPIO_TO_IRQ() we explicitly #include "irqs.h" so that we satisfy the dependency in the board include file alone. Reported-by: Arnd Bergmann Signed-off-by: Linus Walleij Cc: stable@vger.kernel.org # v3.13+ Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-pxa/include/mach/balloon3.h b/arch/arm/mach-pxa/include/mach/balloon3.h index 954641e..1b08259 100644 --- a/arch/arm/mach-pxa/include/mach/balloon3.h +++ b/arch/arm/mach-pxa/include/mach/balloon3.h @@ -14,6 +14,8 @@ #ifndef ASM_ARCH_BALLOON3_H #define ASM_ARCH_BALLOON3_H +#include "irqs.h" /* PXA_NR_BUILTIN_GPIO */ + enum balloon3_features { BALLOON3_FEATURE_OHCI, BALLOON3_FEATURE_MMC, diff --git a/arch/arm/mach-pxa/include/mach/corgi.h b/arch/arm/mach-pxa/include/mach/corgi.h index f3c3493..c030d95 100644 --- a/arch/arm/mach-pxa/include/mach/corgi.h +++ b/arch/arm/mach-pxa/include/mach/corgi.h @@ -13,6 +13,7 @@ #ifndef __ASM_ARCH_CORGI_H #define __ASM_ARCH_CORGI_H 1 +#include "irqs.h" /* PXA_NR_BUILTIN_GPIO */ /* * Corgi (Non Standard) GPIO Definitions diff --git a/arch/arm/mach-pxa/include/mach/csb726.h b/arch/arm/mach-pxa/include/mach/csb726.h index 2628e7b..00cfbbb 100644 --- a/arch/arm/mach-pxa/include/mach/csb726.h +++ b/arch/arm/mach-pxa/include/mach/csb726.h @@ -11,6 +11,8 @@ #ifndef CSB726_H #define CSB726_H +#include "irqs.h" /* PXA_GPIO_TO_IRQ */ + #define CSB726_GPIO_IRQ_LAN 52 #define CSB726_GPIO_IRQ_SM501 53 #define CSB726_GPIO_MMC_DETECT 100 diff --git a/arch/arm/mach-pxa/include/mach/gumstix.h b/arch/arm/mach-pxa/include/mach/gumstix.h index dba14b6..f7df27b 100644 --- a/arch/arm/mach-pxa/include/mach/gumstix.h +++ b/arch/arm/mach-pxa/include/mach/gumstix.h @@ -6,6 +6,7 @@ * published by the Free Software Foundation. */ +#include "irqs.h" /* PXA_GPIO_TO_IRQ */ /* BTRESET - Reset line to Bluetooth module, active low signal. */ #define GPIO_GUMSTIX_BTRESET 7 diff --git a/arch/arm/mach-pxa/include/mach/idp.h b/arch/arm/mach-pxa/include/mach/idp.h index 22a96f8..7e63f46 100644 --- a/arch/arm/mach-pxa/include/mach/idp.h +++ b/arch/arm/mach-pxa/include/mach/idp.h @@ -23,6 +23,7 @@ * IDP hardware. */ +#include "irqs.h" /* PXA_GPIO_TO_IRQ */ #define IDP_FLASH_PHYS (PXA_CS0_PHYS) #define IDP_ALT_FLASH_PHYS (PXA_CS1_PHYS) diff --git a/arch/arm/mach-pxa/include/mach/palmld.h b/arch/arm/mach-pxa/include/mach/palmld.h index 2c447133..b184f29 100644 --- a/arch/arm/mach-pxa/include/mach/palmld.h +++ b/arch/arm/mach-pxa/include/mach/palmld.h @@ -13,6 +13,8 @@ #ifndef _INCLUDE_PALMLD_H_ #define _INCLUDE_PALMLD_H_ +#include "irqs.h" /* PXA_GPIO_TO_IRQ */ + /** HERE ARE GPIOs **/ /* GPIOs */ diff --git a/arch/arm/mach-pxa/include/mach/palmt5.h b/arch/arm/mach-pxa/include/mach/palmt5.h index 0bd4f03..e342c59 100644 --- a/arch/arm/mach-pxa/include/mach/palmt5.h +++ b/arch/arm/mach-pxa/include/mach/palmt5.h @@ -15,6 +15,8 @@ #ifndef _INCLUDE_PALMT5_H_ #define _INCLUDE_PALMT5_H_ +#include "irqs.h" /* PXA_GPIO_TO_IRQ */ + /** HERE ARE GPIOs **/ /* GPIOs */ diff --git a/arch/arm/mach-pxa/include/mach/palmtc.h b/arch/arm/mach-pxa/include/mach/palmtc.h index c383a21..81c727b 100644 --- a/arch/arm/mach-pxa/include/mach/palmtc.h +++ b/arch/arm/mach-pxa/include/mach/palmtc.h @@ -16,6 +16,8 @@ #ifndef _INCLUDE_PALMTC_H_ #define _INCLUDE_PALMTC_H_ +#include "irqs.h" /* PXA_GPIO_TO_IRQ */ + /** HERE ARE GPIOs **/ /* GPIOs */ diff --git a/arch/arm/mach-pxa/include/mach/palmtx.h b/arch/arm/mach-pxa/include/mach/palmtx.h index f2e5303..92bc1f0 100644 --- a/arch/arm/mach-pxa/include/mach/palmtx.h +++ b/arch/arm/mach-pxa/include/mach/palmtx.h @@ -16,6 +16,8 @@ #ifndef _INCLUDE_PALMTX_H_ #define _INCLUDE_PALMTX_H_ +#include "irqs.h" /* PXA_GPIO_TO_IRQ */ + /** HERE ARE GPIOs **/ /* GPIOs */ diff --git a/arch/arm/mach-pxa/include/mach/pcm027.h b/arch/arm/mach-pxa/include/mach/pcm027.h index 6bf28de..86ebd7b 100644 --- a/arch/arm/mach-pxa/include/mach/pcm027.h +++ b/arch/arm/mach-pxa/include/mach/pcm027.h @@ -23,6 +23,8 @@ * Definitions of CPU card resources only */ +#include "irqs.h" /* PXA_GPIO_TO_IRQ */ + /* phyCORE-PXA270 (PCM027) Interrupts */ #define PCM027_IRQ(x) (IRQ_BOARD_START + (x)) #define PCM027_BTDET_IRQ PCM027_IRQ(0) diff --git a/arch/arm/mach-pxa/include/mach/pcm990_baseboard.h b/arch/arm/mach-pxa/include/mach/pcm990_baseboard.h index 0260aaa..7e544c1 100644 --- a/arch/arm/mach-pxa/include/mach/pcm990_baseboard.h +++ b/arch/arm/mach-pxa/include/mach/pcm990_baseboard.h @@ -20,6 +20,7 @@ */ #include +#include "irqs.h" /* PXA_GPIO_TO_IRQ */ /* * definitions relevant only when the PCM-990 diff --git a/arch/arm/mach-pxa/include/mach/poodle.h b/arch/arm/mach-pxa/include/mach/poodle.h index f32ff75..b56b193 100644 --- a/arch/arm/mach-pxa/include/mach/poodle.h +++ b/arch/arm/mach-pxa/include/mach/poodle.h @@ -15,6 +15,8 @@ #ifndef __ASM_ARCH_POODLE_H #define __ASM_ARCH_POODLE_H 1 +#include "irqs.h" /* PXA_GPIO_TO_IRQ */ + /* * GPIOs */ diff --git a/arch/arm/mach-pxa/include/mach/spitz.h b/arch/arm/mach-pxa/include/mach/spitz.h index 0bfe650..25c9f62 100644 --- a/arch/arm/mach-pxa/include/mach/spitz.h +++ b/arch/arm/mach-pxa/include/mach/spitz.h @@ -15,8 +15,8 @@ #define __ASM_ARCH_SPITZ_H 1 #endif +#include "irqs.h" /* PXA_NR_BUILTIN_GPIO, PXA_GPIO_TO_IRQ */ #include -#include /* Spitz/Akita GPIOs */ diff --git a/arch/arm/mach-pxa/include/mach/tosa.h b/arch/arm/mach-pxa/include/mach/tosa.h index 2bb0e86..0497d95 100644 --- a/arch/arm/mach-pxa/include/mach/tosa.h +++ b/arch/arm/mach-pxa/include/mach/tosa.h @@ -13,6 +13,8 @@ #ifndef _ASM_ARCH_TOSA_H_ #define _ASM_ARCH_TOSA_H_ 1 +#include "irqs.h" /* PXA_NR_BUILTIN_GPIO */ + /* TOSA Chip selects */ #define TOSA_LCDC_PHYS PXA_CS4_PHYS /* Internel Scoop */ diff --git a/arch/arm/mach-pxa/include/mach/trizeps4.h b/arch/arm/mach-pxa/include/mach/trizeps4.h index d2ca010..ae3ca01 100644 --- a/arch/arm/mach-pxa/include/mach/trizeps4.h +++ b/arch/arm/mach-pxa/include/mach/trizeps4.h @@ -10,6 +10,8 @@ #ifndef _TRIPEPS4_H_ #define _TRIPEPS4_H_ +#include "irqs.h" /* PXA_GPIO_TO_IRQ */ + /* physical memory regions */ #define TRIZEPS4_FLASH_PHYS (PXA_CS0_PHYS) /* Flash region */ #define TRIZEPS4_DISK_PHYS (PXA_CS1_PHYS) /* Disk On Chip region */ -- cgit v0.10.2 From e7c57ecd6019cc6392223605aed18cce257c3eff Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Wed, 29 Jan 2014 17:10:04 +0100 Subject: ARM: imx6: Initialize low-power mode early again Since commit 9e8147bb5ec5d1dda2141da70f96b98985a306cb "ARM: imx6q: move low-power code out of clock driver" the kernel fails to boot on i.MX6Q/D if preemption is enabled (CONFIG_PREEMPT=y). The kernel just hangs before the console comes up. The above commit moved the initalization of the low-power mode setting (enabling clocked WAIT states), which was introduced in commit 83ae20981ae924c37d02a42c829155fc3851260c "ARM: imx: correct low-power mode setting", from imx6q_clks_init to imx6q_pm_init. Now it is called much later, after all cores are enabled. This patch moves the low-power mode initialization back to imx6q_clks_init again (and to imx6sl_clks_init). Signed-off-by: Philipp Zabel Signed-off-by: Shawn Guo Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c index af2e582..4d677f4 100644 --- a/arch/arm/mach-imx/clk-imx6q.c +++ b/arch/arm/mach-imx/clk-imx6q.c @@ -482,6 +482,9 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) if (IS_ENABLED(CONFIG_PCI_IMX6)) clk_set_parent(clk[lvds1_sel], clk[sata_ref]); + /* Set initial power mode */ + imx6q_set_lpm(WAIT_CLOCKED); + np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpt"); base = of_iomap(np, 0); WARN_ON(!base); diff --git a/arch/arm/mach-imx/clk-imx6sl.c b/arch/arm/mach-imx/clk-imx6sl.c index 3781a18..4c86f30 100644 --- a/arch/arm/mach-imx/clk-imx6sl.c +++ b/arch/arm/mach-imx/clk-imx6sl.c @@ -266,6 +266,9 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node) /* Audio-related clocks configuration */ clk_set_parent(clks[IMX6SL_CLK_SPDIF0_SEL], clks[IMX6SL_CLK_PLL3_PFD3]); + /* Set initial power mode */ + imx6q_set_lpm(WAIT_CLOCKED); + np = of_find_compatible_node(NULL, NULL, "fsl,imx6sl-gpt"); base = of_iomap(np, 0); WARN_ON(!base); diff --git a/arch/arm/mach-imx/pm-imx6q.c b/arch/arm/mach-imx/pm-imx6q.c index 9d47adc..7a9b985 100644 --- a/arch/arm/mach-imx/pm-imx6q.c +++ b/arch/arm/mach-imx/pm-imx6q.c @@ -236,8 +236,6 @@ void __init imx6q_pm_init(void) regmap_update_bits(gpr, IOMUXC_GPR1, IMX6Q_GPR1_GINT, IMX6Q_GPR1_GINT); - /* Set initial power mode */ - imx6q_set_lpm(WAIT_CLOCKED); suspend_set_ops(&imx6q_pm_ops); } -- cgit v0.10.2 From 5db1dabc562b27c356376fbb527a746dcf7c9572 Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Thu, 6 Feb 2014 09:29:31 -0600 Subject: ARM: multi_v7_defconfig: Select CONFIG_SOC_DRA7XX Select CONFIG_SOC_DRA7XX so that we can boot dra7-evm. DRA7 family are A15 based processors that supports LPAE and an evolutionary update to the OMAP5 generation of processors. Signed-off-by: Nishanth Menon Signed-off-by: Kevin Hilman diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 845bc74..ee69829 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -29,6 +29,7 @@ CONFIG_ARCH_OMAP3=y CONFIG_ARCH_OMAP4=y CONFIG_SOC_OMAP5=y CONFIG_SOC_AM33XX=y +CONFIG_SOC_DRA7XX=y CONFIG_SOC_AM43XX=y CONFIG_ARCH_ROCKCHIP=y CONFIG_ARCH_SOCFPGA=y -- cgit v0.10.2 From 46f5b96085b03f9e71a0134de77efc6a1f9d84c3 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 31 Jan 2014 12:55:06 +0100 Subject: ARM: zynq: Reserve not DMAable space in front of the kernel Reserve space from 0x0 - __pa(swapper_pg_dir), if kernel is loaded from 0, which is not DMAable. It is causing problem with MMC driver and others which want to add dma buffers to this space. Signed-off-by: Michal Simek Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c index 1db2a5ca..8c09a83 100644 --- a/arch/arm/mach-zynq/common.c +++ b/arch/arm/mach-zynq/common.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -41,6 +42,18 @@ void __iomem *zynq_scu_base; +/** + * zynq_memory_init - Initialize special memory + * + * We need to stop things allocating the low memory as DMA can't work in + * the 1st 512K of memory. + */ +static void __init zynq_memory_init(void) +{ + if (!__pa(PAGE_OFFSET)) + memblock_reserve(__pa(PAGE_OFFSET), __pa(swapper_pg_dir)); +} + static struct platform_device zynq_cpuidle_device = { .name = "cpuidle-zynq", }; @@ -117,5 +130,6 @@ DT_MACHINE_START(XILINX_EP107, "Xilinx Zynq Platform") .init_machine = zynq_init_machine, .init_time = zynq_timer_init, .dt_compat = zynq_dt_match, + .reserve = zynq_memory_init, .restart = zynq_system_reset, MACHINE_END -- cgit v0.10.2 From a5642ab4744bc8c5a8c7ce7c6e30c01bd6bbc691 Mon Sep 17 00:00:00 2001 From: Toshiaki Makita Date: Fri, 7 Feb 2014 16:48:18 +0900 Subject: bridge: Fix the way to find old local fdb entries in br_fdb_changeaddr br_fdb_changeaddr() assumes that there is at most one local entry per port per vlan. It used to be true, but since commit 36fd2b63e3b4 ("bridge: allow creating/deleting fdb entries via netlink"), it has not been so. Therefore, the function might fail to search a correct previous address to be deleted and delete an arbitrary local entry if user has added local entries manually. Example of problematic case: ip link set eth0 address ee:ff:12:34:56:78 brctl addif br0 eth0 bridge fdb add 12:34:56:78:90:ab dev eth0 master ip link set eth0 address aa:bb:cc:dd:ee:ff Then, the address 12:34:56:78:90:ab might be deleted instead of ee:ff:12:34:56:78, the original mac address of eth0. Address this issue by introducing a new flag, added_by_user, to struct net_bridge_fdb_entry. Note that br_fdb_delete_by_port() has to set added_by_user to 0 in cases like: ip link set eth0 address 12:34:56:78:90:ab ip link set eth1 address aa:bb:cc:dd:ee:ff brctl addif br0 eth0 bridge fdb add aa:bb:cc:dd:ee:ff dev eth0 master brctl addif br0 eth1 brctl delif br0 eth0 In this case, kernel should delete the user-added entry aa:bb:cc:dd:ee:ff, but it also should have been added by "brctl addif br0 eth1" originally, so we don't delete it and treat it a new kernel-created entry. Signed-off-by: Toshiaki Makita Signed-off-by: David S. Miller diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index c5f5a4a..ce54119 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c @@ -104,7 +104,7 @@ void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr) struct net_bridge_fdb_entry *f; f = hlist_entry(h, struct net_bridge_fdb_entry, hlist); - if (f->dst == p && f->is_local) { + if (f->dst == p && f->is_local && !f->added_by_user) { /* maybe another port has same hw addr? */ struct net_bridge_port *op; u16 vid = f->vlan_id; @@ -247,6 +247,7 @@ void br_fdb_delete_by_port(struct net_bridge *br, ether_addr_equal(op->dev->dev_addr, f->addr.addr)) { f->dst = op; + f->added_by_user = 0; goto skip_delete; } } @@ -397,6 +398,7 @@ static struct net_bridge_fdb_entry *fdb_create(struct hlist_head *head, fdb->vlan_id = vid; fdb->is_local = 0; fdb->is_static = 0; + fdb->added_by_user = 0; fdb->updated = fdb->used = jiffies; hlist_add_head_rcu(&fdb->hlist, head); } @@ -447,7 +449,7 @@ int br_fdb_insert(struct net_bridge *br, struct net_bridge_port *source, } void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source, - const unsigned char *addr, u16 vid) + const unsigned char *addr, u16 vid, bool added_by_user) { struct hlist_head *head = &br->hash[br_mac_hash(addr, vid)]; struct net_bridge_fdb_entry *fdb; @@ -473,13 +475,18 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source, /* fastpath: update of existing entry */ fdb->dst = source; fdb->updated = jiffies; + if (unlikely(added_by_user)) + fdb->added_by_user = 1; } } else { spin_lock(&br->hash_lock); if (likely(!fdb_find(head, addr, vid))) { fdb = fdb_create(head, source, addr, vid); - if (fdb) + if (fdb) { + if (unlikely(added_by_user)) + fdb->added_by_user = 1; fdb_notify(br, fdb, RTM_NEWNEIGH); + } } /* else we lose race and someone else inserts * it first, don't bother updating @@ -647,6 +654,7 @@ static int fdb_add_entry(struct net_bridge_port *source, const __u8 *addr, modified = true; } + fdb->added_by_user = 1; fdb->used = jiffies; if (modified) { @@ -664,7 +672,7 @@ static int __br_fdb_add(struct ndmsg *ndm, struct net_bridge_port *p, if (ndm->ndm_flags & NTF_USE) { rcu_read_lock(); - br_fdb_update(p->br, p, addr, vid); + br_fdb_update(p->br, p, addr, vid, true); rcu_read_unlock(); } else { spin_lock_bh(&p->br->hash_lock); diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index bf8dc7d..28d5446 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c @@ -77,7 +77,7 @@ int br_handle_frame_finish(struct sk_buff *skb) /* insert into forwarding database after filtering to avoid spoofing */ br = p->br; if (p->flags & BR_LEARNING) - br_fdb_update(br, p, eth_hdr(skb)->h_source, vid); + br_fdb_update(br, p, eth_hdr(skb)->h_source, vid, false); if (!is_broadcast_ether_addr(dest) && is_multicast_ether_addr(dest) && br_multicast_rcv(br, p, skb, vid)) @@ -148,7 +148,7 @@ static int br_handle_local_finish(struct sk_buff *skb) br_vlan_get_tag(skb, &vid); if (p->flags & BR_LEARNING) - br_fdb_update(p->br, p, eth_hdr(skb)->h_source, vid); + br_fdb_update(p->br, p, eth_hdr(skb)->h_source, vid, false); return 0; /* process further */ } diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index fcd1233..939a59e 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -104,6 +104,7 @@ struct net_bridge_fdb_entry mac_addr addr; unsigned char is_local; unsigned char is_static; + unsigned char added_by_user; __u16 vlan_id; }; @@ -383,7 +384,7 @@ int br_fdb_fillbuf(struct net_bridge *br, void *buf, unsigned long count, int br_fdb_insert(struct net_bridge *br, struct net_bridge_port *source, const unsigned char *addr, u16 vid); void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source, - const unsigned char *addr, u16 vid); + const unsigned char *addr, u16 vid, bool added_by_user); int fdb_delete_by_addr(struct net_bridge *br, const u8 *addr, u16 vid); int br_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[], -- cgit v0.10.2 From 2836882fe07718fe3263745b1aa07284ec71871c Mon Sep 17 00:00:00 2001 From: Toshiaki Makita Date: Fri, 7 Feb 2014 16:48:19 +0900 Subject: bridge: Fix the way to insert new local fdb entries in br_fdb_changeaddr Since commit bc9a25d21ef8 ("bridge: Add vlan support for local fdb entries"), br_fdb_changeaddr() has inserted a new local fdb entry only if it can find old one. But if we have two ports where they have the same address or user has deleted a local entry, there will be no entry for one of the ports. Example of problematic case: ip link set eth0 address aa:bb:cc:dd:ee:ff ip link set eth1 address aa:bb:cc:dd:ee:ff brctl addif br0 eth0 brctl addif br0 eth1 # eth1 will not have a local entry due to dup. ip link set eth1 address 12:34:56:78:90:ab Then, the new entry for the address 12:34:56:78:90:ab will not be created, and the bridge device will not be able to communicate. Insert new entries regardless of whether we can find old entries or not. Signed-off-by: Toshiaki Makita Acked-by: Vlad Yasevich Signed-off-by: David S. Miller diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index ce54119..96ab1d1 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c @@ -92,8 +92,10 @@ static void fdb_delete(struct net_bridge *br, struct net_bridge_fdb_entry *f) void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr) { struct net_bridge *br = p->br; - bool no_vlan = (nbp_get_vlan_info(p) == NULL) ? true : false; + struct net_port_vlans *pv = nbp_get_vlan_info(p); + bool no_vlan = !pv; int i; + u16 vid; spin_lock_bh(&br->hash_lock); @@ -114,28 +116,37 @@ void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr) f->addr.addr) && nbp_vlan_find(op, vid)) { f->dst = op; - goto insert; + goto skip_delete; } } /* delete old one */ fdb_delete(br, f); -insert: - /* insert new address, may fail if invalid - * address or dup. - */ - fdb_insert(br, p, newaddr, vid); - +skip_delete: /* if this port has no vlan information * configured, we can safely be done at * this point. */ if (no_vlan) - goto done; + goto insert; } } } +insert: + /* insert new address, may fail if invalid address or dup. */ + fdb_insert(br, p, newaddr, 0); + + if (no_vlan) + goto done; + + /* Now add entries for every VLAN configured on the port. + * This function runs under RTNL so the bitmap will not change + * from under us. + */ + for_each_set_bit(vid, pv->vlan_bitmap, VLAN_N_VID) + fdb_insert(br, p, newaddr, vid); + done: spin_unlock_bh(&br->hash_lock); } -- cgit v0.10.2 From a3ebb7efe7033d903d86c9d664f07a9cc21747b3 Mon Sep 17 00:00:00 2001 From: Toshiaki Makita Date: Fri, 7 Feb 2014 16:48:20 +0900 Subject: bridge: Fix the way to find old local fdb entries in br_fdb_change_mac_address We have been always failed to delete the old entry at br_fdb_change_mac_address() because br_set_mac_address() updates dev->dev_addr before calling br_fdb_change_mac_address() and br_fdb_change_mac_address() uses dev->dev_addr to find the old entry. That update of dev_addr is completely unnecessary because the same work is done in br_stp_change_bridge_id() which is called right away after calling br_fdb_change_mac_address(). Signed-off-by: Toshiaki Makita Acked-by: Vlad Yasevich Signed-off-by: David S. Miller diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index d9a9b0f..6f5cbd1 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -187,8 +187,8 @@ static int br_set_mac_address(struct net_device *dev, void *p) spin_lock_bh(&br->lock); if (!ether_addr_equal(dev->dev_addr, addr->sa_data)) { - memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); br_fdb_change_mac_address(br, addr->sa_data); + /* Mac address will be changed in br_stp_change_bridge_id(). */ br_stp_change_bridge_id(br, addr->sa_data); } spin_unlock_bh(&br->lock); -- cgit v0.10.2 From a4b816d8ba1c1917842dc3de97cbf8ef116e043e Mon Sep 17 00:00:00 2001 From: Toshiaki Makita Date: Fri, 7 Feb 2014 16:48:21 +0900 Subject: bridge: Change local fdb entries whenever mac address of bridge device changes Vlan code may need fdb change when changing mac address of bridge device even if it is caused by the mac address changing of a bridge port. Example configuration: ip link set eth0 address 12:34:56:78:90:ab ip link set eth1 address aa:bb:cc:dd:ee:ff brctl addif br0 eth0 brctl addif br0 eth1 # br0 will have mac address 12:34:56:78:90:ab bridge vlan add dev br0 vid 10 self bridge vlan add dev eth0 vid 10 We will have fdb entry such that f->dst == NULL, f->vlan_id == 10 and f->addr == 12:34:56:78:90:ab at this time. Next, change the mac address of eth0 to greater value. ip link set eth0 address ee:ff:12:34:56:78 Then, mac address of br0 will be recalculated and set to aa:bb:cc:dd:ee:ff. However, an entry aa:bb:cc:dd:ee:ff will not be created and we will be not able to communicate using br0 on vlan 10. Address this issue by deleting and adding local entries whenever changing the mac address of the bridge device. If there already exists an entry that has the same address, for example, in case that br_fdb_changeaddr() has already inserted it, br_fdb_change_mac_address() will simply fail to insert it and no duplicated entry will be made, as it was. This approach also needs br_add_if() to call br_fdb_insert() before br_stp_recalculate_bridge_id() so that we don't create an entry whose dst == NULL in this function to preserve previous behavior. Note that this is a slight change in behavior where the bridge device can receive the traffic to the new address before calling br_stp_recalculate_bridge_id() in br_add_if(). However, it is not a problem because we have already the address on the new port and such a way to insert new one before recalculating bridge id is taken in br_device_event() as well. Signed-off-by: Toshiaki Makita Acked-by: Vlad Yasevich Signed-off-by: David S. Miller diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 6f5cbd1..63f0455 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -187,7 +187,6 @@ static int br_set_mac_address(struct net_device *dev, void *p) spin_lock_bh(&br->lock); if (!ether_addr_equal(dev->dev_addr, addr->sa_data)) { - br_fdb_change_mac_address(br, addr->sa_data); /* Mac address will be changed in br_stp_change_bridge_id(). */ br_stp_change_bridge_id(br, addr->sa_data); } diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index cffe1d6..54d207d 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -389,6 +389,9 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) if (br->dev->needed_headroom < dev->needed_headroom) br->dev->needed_headroom = dev->needed_headroom; + if (br_fdb_insert(br, p, dev->dev_addr, 0)) + netdev_err(dev, "failed insert local address bridge forwarding table\n"); + spin_lock_bh(&br->lock); changed_addr = br_stp_recalculate_bridge_id(br); @@ -404,9 +407,6 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) dev_set_mtu(br->dev, br_min_mtu(br)); - if (br_fdb_insert(br, p, dev->dev_addr, 0)) - netdev_err(dev, "failed insert local address bridge forwarding table\n"); - kobject_uevent(&p->kobj, KOBJ_ADD); return 0; diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c index 656a6f3..189ba1e 100644 --- a/net/bridge/br_stp_if.c +++ b/net/bridge/br_stp_if.c @@ -194,6 +194,8 @@ void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *addr) wasroot = br_is_root_bridge(br); + br_fdb_change_mac_address(br, addr); + memcpy(oldaddr, br->bridge_id.addr, ETH_ALEN); memcpy(br->bridge_id.addr, addr, ETH_ALEN); memcpy(br->dev->dev_addr, addr, ETH_ALEN); -- cgit v0.10.2 From 2b292fb4a57dc233e298a84196d33be0bc3828e4 Mon Sep 17 00:00:00 2001 From: Toshiaki Makita Date: Fri, 7 Feb 2014 16:48:22 +0900 Subject: bridge: Fix the way to check if a local fdb entry can be deleted We should take into account the followings when deleting a local fdb entry. - nbp_vlan_find() can be used only when vid != 0 to check if an entry is deletable, because a fdb entry with vid 0 can exist at any time while nbp_vlan_find() always return false with vid 0. Example of problematic case: ip link set eth0 address 12:34:56:78:90:ab ip link set eth1 address 12:34:56:78:90:ab brctl addif br0 eth0 brctl addif br0 eth1 ip link set eth0 address aa:bb:cc:dd:ee:ff Then, the fdb entry 12:34:56:78:90:ab will be deleted even though the bridge port eth1 still has that address. - The port to which the bridge device is attached might needs a local entry if its mac address is set manually. Example of problematic case: ip link set eth0 address 12:34:56:78:90:ab brctl addif br0 eth0 ip link set br0 address 12:34:56:78:90:ab ip link set eth0 address aa:bb:cc:dd:ee:ff Then, the fdb still must have the entry 12:34:56:78:90:ab, but it will be deleted. We can use br->dev->addr_assign_type to check if the address is manually set or not, but I propose another approach. Since we delete and insert local entries whenever changing mac address of the bridge device, we can change dst of the entry to NULL regardless of addr_assign_type when deleting an entry associated with a certain port, and if it is found to be unnecessary later, then delete it. That is, if changing mac address of a port, the entry might be changed to its dst being NULL first, but is eventually deleted when recalculating and changing bridge id. This approach is especially useful when we want to share the code with deleting vlan in which the bridge device might want such an entry regardless of addr_assign_type, and makes things easy because we don't have to consider if mac address of the bridge device will be changed or not at the time we delete a local entry of a port, which means fdb code will not be bothered even if the bridge id calculating logic is changed in the future. Also, this change reduces inconsistent state, where frames whose dst is the mac address of the bridge, can't reach the bridge because of premature fdb entry deletion. This change reduces the possibility that the bridge device replies unreachable mac address to arp requests, which could occur during the short window between calling del_nbp() and br_stp_recalculate_bridge_id() in br_del_if(). This will effective after br_fdb_delete_by_port() starts to use the same code by following patch. Signed-off-by: Toshiaki Makita Acked-by: Vlad Yasevich Signed-off-by: David S. Miller diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index 96ab1d1..b4005f5 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c @@ -114,12 +114,20 @@ void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr) if (op != p && ether_addr_equal(op->dev->dev_addr, f->addr.addr) && - nbp_vlan_find(op, vid)) { + (!vid || nbp_vlan_find(op, vid))) { f->dst = op; goto skip_delete; } } + /* maybe bridge device has same hw addr? */ + if (ether_addr_equal(br->dev->dev_addr, + f->addr.addr) && + (!vid || br_vlan_find(br, vid))) { + f->dst = NULL; + goto skip_delete; + } + /* delete old one */ fdb_delete(br, f); skip_delete: diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 939a59e..f91e1d9 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -585,6 +585,7 @@ struct sk_buff *br_handle_vlan(struct net_bridge *br, int br_vlan_add(struct net_bridge *br, u16 vid, u16 flags); int br_vlan_delete(struct net_bridge *br, u16 vid); void br_vlan_flush(struct net_bridge *br); +bool br_vlan_find(struct net_bridge *br, u16 vid); int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val); int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags); int nbp_vlan_delete(struct net_bridge_port *port, u16 vid); @@ -666,6 +667,11 @@ static inline void br_vlan_flush(struct net_bridge *br) { } +static inline bool br_vlan_find(struct net_bridge *br, u16 vid) +{ + return false; +} + static inline int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags) { return -EOPNOTSUPP; diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c index 4ca4d0a..233ec1c 100644 --- a/net/bridge/br_vlan.c +++ b/net/bridge/br_vlan.c @@ -295,6 +295,25 @@ void br_vlan_flush(struct net_bridge *br) __vlan_flush(pv); } +bool br_vlan_find(struct net_bridge *br, u16 vid) +{ + struct net_port_vlans *pv; + bool found = false; + + rcu_read_lock(); + pv = rcu_dereference(br->vlan_info); + + if (!pv) + goto out; + + if (test_bit(vid, pv->vlan_bitmap)) + found = true; + +out: + rcu_read_unlock(); + return found; +} + int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val) { if (!rtnl_trylock()) -- cgit v0.10.2 From 960b589f86c74ce582922fcb996103271081f4de Mon Sep 17 00:00:00 2001 From: Toshiaki Makita Date: Fri, 7 Feb 2014 16:48:23 +0900 Subject: bridge: Properly check if local fdb entry can be deleted in br_fdb_change_mac_address br_fdb_change_mac_address() doesn't check if the local entry has the same address as any of bridge ports. Although I'm not sure when it is beneficial, current implementation allow the bridge device to receive any mac address of its ports. To preserve this behavior, we have to check if the mac address of the entry being deleted is identical to that of any port. As this check is almost the same as that in br_fdb_changeaddr(), create a common function fdb_delete_local() and call it from br_fdb_changeadddr() and br_fdb_change_mac_address(). Signed-off-by: Toshiaki Makita Acked-by: Vlad Yasevich Signed-off-by: David S. Miller diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index b4005f5..15bf13d 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c @@ -89,6 +89,34 @@ static void fdb_delete(struct net_bridge *br, struct net_bridge_fdb_entry *f) call_rcu(&f->rcu, fdb_rcu_free); } +/* Delete a local entry if no other port had the same address. */ +static void fdb_delete_local(struct net_bridge *br, + const struct net_bridge_port *p, + struct net_bridge_fdb_entry *f) +{ + const unsigned char *addr = f->addr.addr; + u16 vid = f->vlan_id; + struct net_bridge_port *op; + + /* Maybe another port has same hw addr? */ + list_for_each_entry(op, &br->port_list, list) { + if (op != p && ether_addr_equal(op->dev->dev_addr, addr) && + (!vid || nbp_vlan_find(op, vid))) { + f->dst = op; + return; + } + } + + /* Maybe bridge device has same hw addr? */ + if (p && ether_addr_equal(br->dev->dev_addr, addr) && + (!vid || br_vlan_find(br, vid))) { + f->dst = NULL; + return; + } + + fdb_delete(br, f); +} + void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr) { struct net_bridge *br = p->br; @@ -107,30 +135,9 @@ void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr) f = hlist_entry(h, struct net_bridge_fdb_entry, hlist); if (f->dst == p && f->is_local && !f->added_by_user) { - /* maybe another port has same hw addr? */ - struct net_bridge_port *op; - u16 vid = f->vlan_id; - list_for_each_entry(op, &br->port_list, list) { - if (op != p && - ether_addr_equal(op->dev->dev_addr, - f->addr.addr) && - (!vid || nbp_vlan_find(op, vid))) { - f->dst = op; - goto skip_delete; - } - } - - /* maybe bridge device has same hw addr? */ - if (ether_addr_equal(br->dev->dev_addr, - f->addr.addr) && - (!vid || br_vlan_find(br, vid))) { - f->dst = NULL; - goto skip_delete; - } - /* delete old one */ - fdb_delete(br, f); -skip_delete: + fdb_delete_local(br, p, f); + /* if this port has no vlan information * configured, we can safely be done at * this point. @@ -168,7 +175,7 @@ void br_fdb_change_mac_address(struct net_bridge *br, const u8 *newaddr) /* If old entry was unassociated with any port, then delete it. */ f = __br_fdb_get(br, br->dev->dev_addr, 0); if (f && f->is_local && !f->dst) - fdb_delete(br, f); + fdb_delete_local(br, NULL, f); fdb_insert(br, NULL, newaddr, 0); @@ -183,7 +190,7 @@ void br_fdb_change_mac_address(struct net_bridge *br, const u8 *newaddr) for_each_set_bit_from(vid, pv->vlan_bitmap, VLAN_N_VID) { f = __br_fdb_get(br, br->dev->dev_addr, vid); if (f && f->is_local && !f->dst) - fdb_delete(br, f); + fdb_delete_local(br, NULL, f); fdb_insert(br, NULL, newaddr, vid); } } -- cgit v0.10.2 From a778e6d1a51faaafa6a3a3cef9bee11c3bd47f9f Mon Sep 17 00:00:00 2001 From: Toshiaki Makita Date: Fri, 7 Feb 2014 16:48:24 +0900 Subject: bridge: Properly check if local fdb entry can be deleted in br_fdb_delete_by_port br_fdb_delete_by_port() doesn't care about vlan and mac address of the bridge device. As the check is almost the same as mac address changing, slightly modify fdb_delete_local() and use it. Note that we can always set added_by_user to 0 in fdb_delete_local() because - br_fdb_delete_by_port() calls fdb_delete_local() for local entries regardless of its added_by_user. In this case, we have to check if another port has the same address and vlan, and if found, we have to create the entry (by changing dst). This is kernel-added entry, not user-added. - br_fdb_changeaddr() doesn't call fdb_delete_local() for user-added entry. Signed-off-by: Toshiaki Makita Acked-by: Vlad Yasevich Signed-off-by: David S. Miller diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index 15bf13d..43e54d1 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c @@ -103,6 +103,7 @@ static void fdb_delete_local(struct net_bridge *br, if (op != p && ether_addr_equal(op->dev->dev_addr, addr) && (!vid || nbp_vlan_find(op, vid))) { f->dst = op; + f->added_by_user = 0; return; } } @@ -111,6 +112,7 @@ static void fdb_delete_local(struct net_bridge *br, if (p && ether_addr_equal(br->dev->dev_addr, addr) && (!vid || br_vlan_find(br, vid))) { f->dst = NULL; + f->added_by_user = 0; return; } @@ -261,26 +263,11 @@ void br_fdb_delete_by_port(struct net_bridge *br, if (f->is_static && !do_all) continue; - /* - * if multiple ports all have the same device address - * then when one port is deleted, assign - * the local entry to other port - */ - if (f->is_local) { - struct net_bridge_port *op; - list_for_each_entry(op, &br->port_list, list) { - if (op != p && - ether_addr_equal(op->dev->dev_addr, - f->addr.addr)) { - f->dst = op; - f->added_by_user = 0; - goto skip_delete; - } - } - } - fdb_delete(br, f); - skip_delete: ; + if (f->is_local) + fdb_delete_local(br, p, f); + else + fdb_delete(br, f); } } spin_unlock_bh(&br->hash_lock); -- cgit v0.10.2 From 424bb9c97cc1992018950485ca7410779b8ea21d Mon Sep 17 00:00:00 2001 From: Toshiaki Makita Date: Fri, 7 Feb 2014 16:48:25 +0900 Subject: bridge: Properly check if local fdb entry can be deleted when deleting vlan Vlan codes unconditionally delete local fdb entries. We should consider the possibility that other ports have the same address and vlan. Example of problematic case: ip link set eth0 address 12:34:56:78:90:ab ip link set eth1 address aa:bb:cc:dd:ee:ff brctl addif br0 eth0 brctl addif br0 eth1 # br0 will have mac address 12:34:56:78:90:ab bridge vlan add dev eth0 vid 10 bridge vlan add dev eth1 vid 10 bridge vlan add dev br0 vid 10 self We will have fdb entry such that f->dst == eth0, f->vlan_id == 10 and f->addr == 12:34:56:78:90:ab at this time. Next, delete eth0 vlan 10. bridge vlan del dev eth0 vid 10 In this case, we still need the entry for br0, but it will be deleted. Note that br0 needs the entry even though its mac address is not set manually. To delete the entry with proper condition checking, fdb_delete_local() is suitable to use. Signed-off-by: Toshiaki Makita Acked-by: Vlad Yasevich Signed-off-by: David S. Miller diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index 43e54d1..0426dff 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c @@ -27,6 +27,9 @@ #include "br_private.h" static struct kmem_cache *br_fdb_cache __read_mostly; +static struct net_bridge_fdb_entry *fdb_find(struct hlist_head *head, + const unsigned char *addr, + __u16 vid); static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source, const unsigned char *addr, u16 vid); static void fdb_notify(struct net_bridge *br, @@ -119,6 +122,20 @@ static void fdb_delete_local(struct net_bridge *br, fdb_delete(br, f); } +void br_fdb_find_delete_local(struct net_bridge *br, + const struct net_bridge_port *p, + const unsigned char *addr, u16 vid) +{ + struct hlist_head *head = &br->hash[br_mac_hash(addr, vid)]; + struct net_bridge_fdb_entry *f; + + spin_lock_bh(&br->hash_lock); + f = fdb_find(head, addr, vid); + if (f && f->is_local && !f->added_by_user && f->dst == p) + fdb_delete_local(br, p, f); + spin_unlock_bh(&br->hash_lock); +} + void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr) { struct net_bridge *br = p->br; @@ -770,8 +787,7 @@ out: return err; } -int fdb_delete_by_addr(struct net_bridge *br, const u8 *addr, - u16 vlan) +static int fdb_delete_by_addr(struct net_bridge *br, const u8 *addr, u16 vlan) { struct hlist_head *head = &br->hash[br_mac_hash(addr, vlan)]; struct net_bridge_fdb_entry *fdb; diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index f91e1d9..3ba11bc 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -371,6 +371,9 @@ static inline void br_netpoll_disable(struct net_bridge_port *p) int br_fdb_init(void); void br_fdb_fini(void); void br_fdb_flush(struct net_bridge *br); +void br_fdb_find_delete_local(struct net_bridge *br, + const struct net_bridge_port *p, + const unsigned char *addr, u16 vid); void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr); void br_fdb_change_mac_address(struct net_bridge *br, const u8 *newaddr); void br_fdb_cleanup(unsigned long arg); @@ -385,7 +388,6 @@ int br_fdb_insert(struct net_bridge *br, struct net_bridge_port *source, const unsigned char *addr, u16 vid); void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source, const unsigned char *addr, u16 vid, bool added_by_user); -int fdb_delete_by_addr(struct net_bridge *br, const u8 *addr, u16 vid); int br_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[], struct net_device *dev, const unsigned char *addr); diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c index 233ec1c..8249ca76 100644 --- a/net/bridge/br_vlan.c +++ b/net/bridge/br_vlan.c @@ -275,9 +275,7 @@ int br_vlan_delete(struct net_bridge *br, u16 vid) if (!pv) return -EINVAL; - spin_lock_bh(&br->hash_lock); - fdb_delete_by_addr(br, br->dev->dev_addr, vid); - spin_unlock_bh(&br->hash_lock); + br_fdb_find_delete_local(br, NULL, br->dev->dev_addr, vid); __vlan_del(pv, vid); return 0; @@ -378,9 +376,7 @@ int nbp_vlan_delete(struct net_bridge_port *port, u16 vid) if (!pv) return -EINVAL; - spin_lock_bh(&port->br->hash_lock); - fdb_delete_by_addr(port->br, port->dev->dev_addr, vid); - spin_unlock_bh(&port->br->hash_lock); + br_fdb_find_delete_local(port->br, port, port->dev->dev_addr, vid); return __vlan_del(pv, vid); } -- cgit v0.10.2 From ac4c8868837a7c70ebb3eaf2298324a3b61b214e Mon Sep 17 00:00:00 2001 From: Toshiaki Makita Date: Fri, 7 Feb 2014 16:48:26 +0900 Subject: bridge: Prevent possible race condition in br_fdb_change_mac_address br_fdb_change_mac_address() calls fdb_insert()/fdb_delete() without br->hash_lock. These hash list updates are racy with br_fdb_update()/br_fdb_cleanup(). Signed-off-by: Toshiaki Makita Acked-by: Vlad Yasevich Signed-off-by: David S. Miller diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index 0426dff..9203d5a 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c @@ -191,6 +191,8 @@ void br_fdb_change_mac_address(struct net_bridge *br, const u8 *newaddr) struct net_port_vlans *pv; u16 vid = 0; + spin_lock_bh(&br->hash_lock); + /* If old entry was unassociated with any port, then delete it. */ f = __br_fdb_get(br, br->dev->dev_addr, 0); if (f && f->is_local && !f->dst) @@ -204,7 +206,7 @@ void br_fdb_change_mac_address(struct net_bridge *br, const u8 *newaddr) */ pv = br_get_vlan_info(br); if (!pv) - return; + goto out; for_each_set_bit_from(vid, pv->vlan_bitmap, VLAN_N_VID) { f = __br_fdb_get(br, br->dev->dev_addr, vid); @@ -212,6 +214,8 @@ void br_fdb_change_mac_address(struct net_bridge *br, const u8 *newaddr) fdb_delete_local(br, NULL, f); fdb_insert(br, NULL, newaddr, vid); } +out: + spin_unlock_bh(&br->hash_lock); } void br_fdb_cleanup(unsigned long _data) -- cgit v0.10.2 From bf06200e732de613a1277984bf34d1a21c2de03d Mon Sep 17 00:00:00 2001 From: John Ogness Date: Sun, 9 Feb 2014 18:40:11 -0800 Subject: tcp: tsq: fix nonagle handling Commit 46d3ceabd8d9 ("tcp: TCP Small Queues") introduced a possible regression for applications using TCP_NODELAY. If TCP session is throttled because of tsq, we should consult tp->nonagle when TX completion is done and allow us to send additional segment, especially if this segment is not a full MSS. Otherwise this segment is sent after an RTO. [edumazet] : Cooked the changelog, added another fix about testing sk_wmem_alloc twice because TX completion can happen right before setting TSQ_THROTTLED bit. This problem is particularly visible with recent auto corking, but might also be triggered with low tcp_limit_output_bytes values or NIC drivers delaying TX completion by hundred of usec, and very low rtt. Thomas Glanzmann for example reported an iscsi regression, caused by tcp auto corking making this bug quite visible. Fixes: 46d3ceabd8d9 ("tcp: TCP Small Queues") Signed-off-by: John Ogness Signed-off-by: Eric Dumazet Reported-by: Thomas Glanzmann Signed-off-by: David S. Miller diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 10435b3..3be1672 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -698,7 +698,8 @@ static void tcp_tsq_handler(struct sock *sk) if ((1 << sk->sk_state) & (TCPF_ESTABLISHED | TCPF_FIN_WAIT1 | TCPF_CLOSING | TCPF_CLOSE_WAIT | TCPF_LAST_ACK)) - tcp_write_xmit(sk, tcp_current_mss(sk), 0, 0, GFP_ATOMIC); + tcp_write_xmit(sk, tcp_current_mss(sk), tcp_sk(sk)->nonagle, + 0, GFP_ATOMIC); } /* * One tasklet per cpu tries to send more skbs. @@ -1904,7 +1905,15 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle, if (atomic_read(&sk->sk_wmem_alloc) > limit) { set_bit(TSQ_THROTTLED, &tp->tsq_flags); - break; + /* It is possible TX completion already happened + * before we set TSQ_THROTTLED, so we must + * test again the condition. + * We abuse smp_mb__after_clear_bit() because + * there is no smp_mb__after_set_bit() yet + */ + smp_mb__after_clear_bit(); + if (atomic_read(&sk->sk_wmem_alloc) > limit) + break; } limit = mss_now; -- cgit v0.10.2 From 49d3d6c37a322117b1eeb410a49165bb3d0441f7 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 10 Feb 2014 14:25:30 -0800 Subject: drivers/misc/sgi-gru/grukdump.c: unlocking should be conditional in gru_dump_context() I was reviewing this and noticed that unlocking should be conditional on the error path. I've changed it to unlock and return directly since we only do it once and it seems unlikely to change in the near future. Signed-off-by: Dan Carpenter Acked-by: Dimitri Sivanich Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/misc/sgi-gru/grukdump.c b/drivers/misc/sgi-gru/grukdump.c index 9b2062d..2bef3f7 100644 --- a/drivers/misc/sgi-gru/grukdump.c +++ b/drivers/misc/sgi-gru/grukdump.c @@ -139,8 +139,11 @@ static int gru_dump_context(struct gru_state *gru, int ctxnum, ubuf += sizeof(hdr); ubufcch = ubuf; - if (gru_user_copy_handle(&ubuf, cch)) - goto fail; + if (gru_user_copy_handle(&ubuf, cch)) { + if (cch_locked) + unlock_cch_handle(cch); + return -EFAULT; + } if (cch_locked) ubufcch->delresp = 0; bytes = sizeof(hdr) + GRU_CACHE_LINE_BYTES; @@ -179,10 +182,6 @@ static int gru_dump_context(struct gru_state *gru, int ctxnum, ret = -EFAULT; return ret ? ret : bytes; - -fail: - unlock_cch_handle(cch); - return -EFAULT; } int gru_dump_chiplet_request(unsigned long arg) -- cgit v0.10.2 From ec83b616a71d76cc062371339472ed66ba405824 Mon Sep 17 00:00:00 2001 From: Richard Genoud Date: Mon, 10 Feb 2014 14:25:31 -0800 Subject: get_maintainer: fix detection of git repository Since git v1.7.7, the .git directory can be a file when, for example, the kernel is a submodule of another git super project. So, the check "-d .git" is not working anymore in this case. Using a more generic check like "-e .git" corrects this behaviour. Signed-off-by: Richard Genoud Cc: Andy Whitcroft Cc: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl index 9c3986f..4198788 100755 --- a/scripts/get_maintainer.pl +++ b/scripts/get_maintainer.pl @@ -95,7 +95,7 @@ my %VCS_cmds; my %VCS_cmds_git = ( "execute_cmd" => \&git_execute_cmd, - "available" => '(which("git") ne "") && (-d ".git")', + "available" => '(which("git") ne "") && (-e ".git")', "find_signers_cmd" => "git log --no-color --follow --since=\$email_git_since " . '--numstat --no-merges ' . -- cgit v0.10.2 From 3645e3283b90524ed9a6b33b68c93ee29d1bfeb9 Mon Sep 17 00:00:00 2001 From: Richard Genoud Date: Mon, 10 Feb 2014 14:25:32 -0800 Subject: checkpatch: fix detection of git repository Since git v1.7.7, the .git directory can be a file when, for example, the kernel is a submodule of another git super project. So, the check "-d .git" is not working anymore in this case. Using a more generic check like "-e .git" corrects this behaviour. Signed-off-by: Richard Genoud Cc: Andy Whitcroft Cc: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 0ea2a1e..464dcef 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -471,7 +471,7 @@ sub seed_camelcase_includes { $camelcase_seeded = 1; - if (-d ".git") { + if (-e ".git") { my $git_last_include_commit = `git log --no-merges --pretty=format:"%h%n" -1 -- include`; chomp $git_last_include_commit; $camelcase_cache = ".checkpatch-camelcase.git.$git_last_include_commit"; @@ -499,7 +499,7 @@ sub seed_camelcase_includes { return; } - if (-d ".git") { + if (-e ".git") { $files = `git ls-files "include/*.h"`; @include_files = split('\n', $files); } -- cgit v0.10.2 From 3cf8ca1c250d3c3d8bf61f20bd71acd1876bf777 Mon Sep 17 00:00:00 2001 From: Henrik Austad Date: Mon, 10 Feb 2014 14:25:33 -0800 Subject: Documentation/: update 00-INDEX files Some of the 00-INDEX files are somewhat outdated and some folders does not contain 00-INDEX at all. Only outdated (with the notably exception of spi) indexes are touched here, the 169 folders without 00-INDEX has not been touched. New 00-INDEX - spi/* was added in a series of commits dating back to 2006 Added files (missing in (*/)00-INDEX) - dmatest.txt was added by commit 851b7e16a07d ("dmatest: run test via debugfs") - this_cpu_ops.txt was added by commit a1b2a555d637 ("percpu: add documentation on this_cpu operations") - ww-mutex-design.txt was added by commit 040a0a371005 ("mutex: Add support for wound/wait style locks") - bcache.txt was added by commit cafe56359144 ("bcache: A block layer cache") - kernel-per-CPU-kthreads.txt was added by commit 49717cb40410 ("kthread: Document ways of reducing OS jitter due to per-CPU kthreads") - phy.txt was added by commit ff764963479a ("drivers: phy: add generic PHY framework") - block/null_blk was added by commit 12f8f4fc0314 ("null_blk: documentation") - module-signing.txt was added by commit 3cafea307642 ("Add Documentation/module-signing.txt file") - assoc_array.txt was added by commit 3cb989501c26 ("Add a generic associative array implementation.") - arm/IXP4xx was part of the initial repo - arm/cluster-pm-race-avoidance.txt was added by commit 7fe31d28e839 ("ARM: mcpm: introduce helpers for platform coherency exit/setup") - arm/firmware.txt was added by commit 7366b92a77fc ("ARM: Add interface for registering and calling firmware-specific operations") - arm/kernel_mode_neon.txt was added by commit 2afd0a05241d ("ARM: 7825/1: document the use of NEON in kernel mode") - arm/tcm.txt was added by commit bc581770cfdd ("ARM: 5580/2: ARM TCM (Tightly-Coupled Memory) support v3") - arm/vlocks.txt was added by commit 9762f12d3e05 ("ARM: mcpm: Add baremetal voting mutexes") - blackfin/gptimers-example.c, Makefile was added by commit 4b60779d5ea7 ("Blackfin: add an example showing how to use the gptimers API") - devicetree/usage-model.txt was added by commit 31134efc681a ("dt: Linux DT usage model documentation") - fb/api.txt was added by commit fb21c2f42879 ("fbdev: Add FOURCC-based format configuration API") - fb/sm501.txt was added by commit e6a049807105 ("video, sm501: add edid and commandline support") - fb/udlfb.txt was added by commit 96f8d864afd6 ("fbdev: move udlfb out of staging.") - filesystems/Makefile was added by commit 1e0051ae48a2 ("Documentation/fs/: split txt and source files") - filesystems/nfs/nfsd-admin-interfaces.txt was added by commit 8a4c6e19cfed ("nfsd: document kernel interfaces for nfsd configuration") - ide/warm-plug-howto.txt was added by commit f74c91413ec6 ("ide: add warm-plug support for IDE devices (take 2)") - laptops/Makefile was added by commit d49129accc21 ("Documentation/laptop/: split txt and source files") - leds/leds-blinkm.txt was added by commit b54cf35a7f65 ("LEDS: add BlinkM RGB LED driver, documentation and update MAINTAINERS") - leds/ledtrig-oneshot.txt was added by commit 5e417281cde2 ("leds: add oneshot trigger") - leds/ledtrig-transient.txt was added by commit 44e1e9f8e705 ("leds: add new transient trigger for one shot timer activation") - m68k/README.buddha was part of the initial repo - networking/LICENSE.(qla3xxx|qlcnic|qlge) was added by commits 40839129f779, c4e84bde1d59, 5a4faa873782 - networking/Makefile was added by commit 3794f3e812ef ("docsrc: build Documentation/ sources") - networking/i40evf.txt was added by commit 105bf2fe6b32 ("i40evf: add driver to kernel build system") - networking/ipsec.txt was added by commit b3c6efbc36e2 ("xfrm: Add file to document IPsec corner case") - networking/mac80211-auth-assoc-deauth.txt was added by commit 3cd7920a2be8 ("mac80211: add auth/assoc/deauth flow diagram") - networking/netlink_mmap.txt was added by commit 5683264c3981 ("netlink: add documentation for memory mapped I/O") - networking/nf_conntrack-sysctl.txt was added by commit c9f9e0e1597f ("netfilter: doc: add nf_conntrack sysctl api documentation") lan) - networking/team.txt was added by commit 3d249d4ca7d0 ("net: introduce ethernet teaming device") - networking/vxlan.txt was added by commit d342894c5d2f ("vxlan: virtual extensible lan") - power/runtime_pm.txt was added by commit 5e928f77a09a ("PM: Introduce core framework for run-time PM of I/O devices (rev. 17)") - power/charger-manager.txt was added by commit 3bb3dbbd56ea ("power_supply: Add initial Charger-Manager driver") - RCU/lockdep-splat.txt was added by commit d7bd2d68aa2e ("rcu: Document interpretation of RCU-lockdep splats") - s390/kvm.txt was added by 5ecee4b (KVM: s390: API documentation) - s390/qeth.txt was added by commit b4d72c08b358 ("qeth: bridgeport support - basic control") - scheduler/sched-bwc.txt was added by commit 88ebc08ea9f7 ("sched: Add documentation for bandwidth control") - scsi/advansys.txt was added by commit 4bd6d7f35661 ("[SCSI] advansys: Move documentation to Documentation/scsi") - scsi/bfa.txt was added by commit 1ec90174bdb4 ("[SCSI] bfa: add readme file") - scsi/bnx2fc.txt was added by commit 12b8fc10eaf4 ("[SCSI] bnx2fc: Add driver documentation") - scsi/cxgb3i.txt was added by commit c3673464ebc0 ("[SCSI] cxgb3i: Add cxgb3i iSCSI driver.") - scsi/hpsa.txt was added by commit 992ebcf14f3c ("[SCSI] hpsa: Add hpsa.txt to Documentation/scsi") - scsi/link_power_management_policy.txt was added by commit ca77329fb713 ("[libata] Link power management infrastructure") - scsi/osd.txt was added by commit 78e0c621deca ("[SCSI] osd: Documentation for OSD library") - scsi/scsi-parameter.txt was created/moved by commit 163475fb111c ("Documentation: move SCSI parameters to their own text file") - serial/driver was part of the initial repo - serial/n_gsm.txt was added by commit 323e84122ec6 ("n_gsm: add a documentation") - timers/Makefile was added by commit 3794f3e812ef ("docsrc: build Documentation/ sources") - virt/kvm/s390.txt was added by commit d9101fca3d57 ("KVM: s390: diagnose call documentation") - vm/split_page_table_lock was added by commit 49076ec2ccaf ("mm: dynamically allocate page->ptl if it cannot be embedded to struct page") - w1/slaves/w1_ds28e04 was added by commit fbf7f7b4e2ae ("w1: Add 1-wire slave device driver for DS28E04-100") - w1/masters/omap-hdq was added by commit e0a29382c6f5 ("hdq: documentation for OMAP HDQ") - x86/early-microcode.txt was added by commit 0d91ea86a895 ("x86, doc: Documentation for early microcode loading") - x86/earlyprintk.txt was added by commit a1aade478862 ("x86/doc: mini-howto for using earlyprintk=dbgp") - x86/entry_64.txt was added by commit 8b4777a4b50c ("x86-64: Document some of entry_64.S") - x86/pat.txt was added by commit d27554d874c7 ("x86: PAT documentation") Moved files - arm/kernel_user_helpers.txt was moved out of arch/arm/kernel by commit 37b8304642c7 ("ARM: kuser: move interface documentation out of the source code") - efi-stub.txt was moved out of x86/ and down into Documentation/ in commit 4172fe2f8a47 ("EFI stub documentation updates") - laptops/hpfall.c was moved out of hwmon/ and into laptops/ in commit efcfed9bad88 ("Move hp_accel to drivers/platform/x86") - commit 5616c23ad9cd ("x86: doc: move x86-generic documentation from Doc/x86/i386"): * x86/usb-legacy-support.txt * x86/boot.txt * x86/zero_page.txt - power/video_extension.txt was moved to acpi in commit 70e66e4df191 ("ACPI / video: move video_extension.txt to Documentation/acpi") Removed files (left in 00-INDEX) - memory.txt was removed by commit 00ea8990aadf ("memory.txt: remove stray information") - gpio.txt was moved to gpio/ in commit fd8e198cfcaa ("Documentation: gpiolib: document new interface") - networking/DLINK.txt was removed by commit 168e06ae26dd ("drivers/net: delete old parallel port de600/de620 drivers") - serial/hayes-esp.txt was removed by commit f53a2ade0bb9 ("tty: esp: remove broken driver") - s390/TAPE was removed by commit 9e280f669308 ("[S390] remove tape block docu") - vm/locking was removed by commit 57ea8171d2bc ("mm: documentation: remove hopelessly out-of-date locking doc") - laptops/acer-wmi.txt was remvoed by commit 020036678e81 ("acer-wmi: Delete out-of-date documentation") Typos/misc issues - rpc-server-gss.txt was added as knfsd-rpcgss.txt in commit 030d794bf498 ("SUNRPC: Use gssproxy upcall for server RPCGSS authentication.") - commit b88cf73d9278 ("net: add missing entries to Documentation/networking/00-INDEX") * generic-hdlc.txt was added as generic_hdlc.txt * spider_net.txt was added as spider-net.txt - w1/master/mxc-w1 was added as mxc_w1 by commit a5fd9139f74c ("w1: add 1-wire master driver for i.MX27 / i.MX31") - s390/zfcpdump.txt was added as zfcpdump by commit 6920c12a407e ("[S390] Add Documentation/s390/00-INDEX.") Signed-off-by: Henrik Austad Reviewed-by: Paul E. McKenney [rcu bits] Acked-by: Rob Landley Cc: Jiri Kosina Cc: Thomas Gleixner Cc: Rob Herring Cc: David S. Miller Cc: Mark Brown Cc: "H. Peter Anvin" Cc: Ingo Molnar Cc: Gleb Natapov Cc: Linus Torvalds Cc: Len Brown Cc: James Bottomley Cc: Jean-Christophe Plagniol-Villard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX index 38f8444..07de7e1 100644 --- a/Documentation/00-INDEX +++ b/Documentation/00-INDEX @@ -29,6 +29,8 @@ DMA-ISA-LPC.txt - How to do DMA with ISA (and LPC) devices. DMA-attributes.txt - listing of the various possible attributes a DMA region can have +dmatest.txt + - how to compile, configure and use the dmatest system. DocBook/ - directory with DocBook templates etc. for kernel documentation. EDID/ @@ -77,6 +79,8 @@ arm/ - directory with info about Linux on the ARM architecture. arm64/ - directory with info about Linux on the 64 bit ARM architecture. +assoc_array.txt + - generic associative array intro. atomic_ops.txt - semantics and behavior of atomic and bitmask operations. auxdisplay/ @@ -87,6 +91,8 @@ bad_memory.txt - how to use kernel parameters to exclude bad RAM regions. basic_profiling.txt - basic instructions for those who wants to profile Linux kernel. +bcache.txt + - Block-layer cache on fast SSDs to improve slow (raid) I/O performance. binfmt_misc.txt - info on the kernel support for extra binary formats. blackfin/ @@ -171,6 +177,8 @@ early-userspace/ - info about initramfs, klibc, and userspace early during boot. edac.txt - information on EDAC - Error Detection And Correction +efi-stub.txt + - How to use the EFI boot stub to bypass GRUB or elilo on EFI systems. eisa.txt - info on EISA bus support. email-clients.txt @@ -195,8 +203,8 @@ futex-requeue-pi.txt - info on requeueing of tasks from a non-PI futex to a PI futex gcov.txt - use of GCC's coverage testing tool "gcov" with the Linux kernel -gpio.txt - - overview of GPIO (General Purpose Input/Output) access conventions. +gpio/ + - gpio related documentation hid/ - directory with information on human interface devices highuid.txt @@ -255,6 +263,8 @@ kernel-docs.txt - listing of various WWW + books that document kernel internals. kernel-parameters.txt - summary listing of command line / boot prompt args for the kernel. +kernel-per-CPU-kthreads.txt + - List of all per-CPU kthreads and how they introduce jitter. kmemcheck.txt - info on dynamic checker that detects uses of uninitialized memory. kmemleak.txt @@ -299,8 +309,6 @@ memory-devices/ - directory with info on parts like the Texas Instruments EMIF driver memory-hotplug.txt - Hotpluggable memory support, how to use and current status. -memory.txt - - info on typical Linux memory problems. metag/ - directory with info about Linux on Meta architecture. mips/ @@ -311,6 +319,8 @@ mmc/ - directory with info about the MMC subsystem mn10300/ - directory with info about the mn10300 architecture port +module-signing.txt + - Kernel module signing for increased security when loading modules. mtd/ - directory with info about memory technology devices (flash) mono.txt @@ -343,6 +353,8 @@ pcmcia/ - info on the Linux PCMCIA driver. percpu-rw-semaphore.txt - RCU based read-write semaphore optimized for locking for reading +phy.txt + - Description of the generic PHY framework. pi-futex.txt - documentation on lightweight priority inheritance futexes. pinctrl.txt @@ -431,6 +443,8 @@ sysrq.txt - info on the magic SysRq key. target/ - directory with info on generating TCM v4 fabric .ko modules +this_cpu_ops.txt + - List rationale behind and the way to use this_cpu operations. thermal/ - directory with information on managing thermal issues (CPU/temp) trace/ @@ -469,6 +483,8 @@ wimax/ - directory with info about Intel Wireless Wimax Connections workqueue.txt - information on the Concurrency Managed Workqueue implementation +ww-mutex-design.txt + - Intro to Mutex wait/would deadlock handling.s x86/x86_64/ - directory with info on Linux support for AMD x86-64 (Hammer) machines. xtensa/ diff --git a/Documentation/RCU/00-INDEX b/Documentation/RCU/00-INDEX index 1d7a885..fa57139 100644 --- a/Documentation/RCU/00-INDEX +++ b/Documentation/RCU/00-INDEX @@ -8,6 +8,8 @@ listRCU.txt - Using RCU to Protect Read-Mostly Linked Lists lockdep.txt - RCU and lockdep checking +lockdep-splat.txt + - RCU Lockdep splats explained. NMI-RCU.txt - Using RCU to Protect Dynamic NMI Handlers rcubarrier.txt diff --git a/Documentation/arm/00-INDEX b/Documentation/arm/00-INDEX index 36420e1..a94090c 100644 --- a/Documentation/arm/00-INDEX +++ b/Documentation/arm/00-INDEX @@ -4,6 +4,8 @@ Booting - requirements for booting Interrupts - ARM Interrupt subsystem documentation +IXP4xx + - Intel IXP4xx Network processor. msm - MSM specific documentation Netwinder @@ -24,8 +26,16 @@ SPEAr - ST SPEAr platform Linux Overview VFP/ - Release notes for Linux Kernel Vector Floating Point support code +cluster-pm-race-avoidance.txt + - Algorithm for CPU and Cluster setup/teardown empeg/ - Ltd's Empeg MP3 Car Audio Player +firmware.txt + - Secure firmware registration and calling. +kernel_mode_neon.txt + - How to use NEON instructions in kernel mode +kernel_user_helpers.txt + - Helper functions in kernel space made available for userspace. mem_alignment - alignment abort handler documentation memory.txt @@ -34,3 +44,7 @@ nwfpe/ - NWFPE floating point emulator documentation swp_emulation - SWP/SWPB emulation handler/logging description +tcm.txt + - ARM Tightly Coupled Memory +vlocks.txt + - Voting locks, low-level mechanism relying on memory system atomic writes. diff --git a/Documentation/blackfin/00-INDEX b/Documentation/blackfin/00-INDEX index 2df0365..c54fcdd 100644 --- a/Documentation/blackfin/00-INDEX +++ b/Documentation/blackfin/00-INDEX @@ -1,8 +1,10 @@ 00-INDEX - This file - +Makefile + - Makefile for gptimers example file. bfin-gpio-notes.txt - Notes in developing/using bfin-gpio driver. - bfin-spi-notes.txt - Notes for using bfin spi bus driver. +gptimers-example.c + - gptimers example diff --git a/Documentation/block/00-INDEX b/Documentation/block/00-INDEX index 929d990..e840b47 100644 --- a/Documentation/block/00-INDEX +++ b/Documentation/block/00-INDEX @@ -14,6 +14,8 @@ deadline-iosched.txt - Deadline IO scheduler tunables ioprio.txt - Block io priorities (in CFQ scheduler) +null_blk.txt + - Null block for block-layer benchmarking. queue-sysfs.txt - Queue's sysfs entries request.txt diff --git a/Documentation/devicetree/00-INDEX b/Documentation/devicetree/00-INDEX index b78f691..8c4102c 100644 --- a/Documentation/devicetree/00-INDEX +++ b/Documentation/devicetree/00-INDEX @@ -8,3 +8,5 @@ https://lists.ozlabs.org/listinfo/devicetree-discuss - this file booting-without-of.txt - Booting Linux without Open Firmware, describes history and format of device trees. +usage-model.txt + - How Linux uses DT and what DT aims to solve. \ No newline at end of file diff --git a/Documentation/fb/00-INDEX b/Documentation/fb/00-INDEX index 30a7054..fe85e7c 100644 --- a/Documentation/fb/00-INDEX +++ b/Documentation/fb/00-INDEX @@ -5,6 +5,8 @@ please mail me. 00-INDEX - this file. +api.txt + - The frame buffer API between applications and buffer devices. arkfb.txt - info on the fbdev driver for ARK Logic chips. aty128fb.txt @@ -51,12 +53,16 @@ sh7760fb.txt - info on the SH7760/SH7763 integrated LCDC Framebuffer driver. sisfb.txt - info on the framebuffer device driver for various SiS chips. +sm501.txt + - info on the framebuffer device driver for sm501 videoframebuffer. sstfb.txt - info on the frame buffer driver for 3dfx' Voodoo Graphics boards. tgafb.txt - info on the TGA (DECChip 21030) frame buffer driver. tridentfb.txt info on the framebuffer driver for some Trident chip based cards. +udlfb.txt + - Driver for DisplayLink USB 2.0 chips. uvesafb.txt - info on the userspace VESA (VBE2+ compliant) frame buffer device. vesafb.txt diff --git a/Documentation/filesystems/00-INDEX b/Documentation/filesystems/00-INDEX index 632211c..ac28149 100644 --- a/Documentation/filesystems/00-INDEX +++ b/Documentation/filesystems/00-INDEX @@ -2,6 +2,8 @@ - this file (info on some of the filesystems supported by linux). Locking - info on locking rules as they pertain to Linux VFS. +Makefile + - Makefile for building the filsystems-part of DocBook. 9p.txt - 9p (v9fs) is an implementation of the Plan 9 remote fs protocol. adfs.txt diff --git a/Documentation/filesystems/nfs/00-INDEX b/Documentation/filesystems/nfs/00-INDEX index 66eb6c8..53f3b59 100644 --- a/Documentation/filesystems/nfs/00-INDEX +++ b/Documentation/filesystems/nfs/00-INDEX @@ -12,6 +12,8 @@ nfs41-server.txt - info on the Linux server implementation of NFSv4 minor version 1. nfs-rdma.txt - how to install and setup the Linux NFS/RDMA client and server software +nfsd-admin-interfaces.txt + - Administrative interfaces for nfsd. nfsroot.txt - short guide on setting up a diskless box with NFS root filesystem. pnfs.txt @@ -20,5 +22,5 @@ rpc-cache.txt - introduction to the caching mechanisms in the sunrpc layer. idmapper.txt - information for configuring request-keys to be used by idmapper -knfsd-rpcgss.txt +rpc-server-gss.txt - Information on GSS authentication support in the NFS Server diff --git a/Documentation/ide/00-INDEX b/Documentation/ide/00-INDEX index d6b7788..22f98ca 100644 --- a/Documentation/ide/00-INDEX +++ b/Documentation/ide/00-INDEX @@ -10,3 +10,5 @@ ide-tape.txt - info on the IDE ATAPI streaming tape driver ide.txt - important info for users of ATA devices (IDE/EIDE disks and CD-ROMS). +warm-plug-howto.txt + - using sysfs to remove and add IDE devices. \ No newline at end of file diff --git a/Documentation/laptops/00-INDEX b/Documentation/laptops/00-INDEX index fa68853..d13b9a9 100644 --- a/Documentation/laptops/00-INDEX +++ b/Documentation/laptops/00-INDEX @@ -1,13 +1,15 @@ 00-INDEX - This file -acer-wmi.txt - - information on the Acer Laptop WMI Extras driver. +Makefile + - Makefile for building dslm example program. asus-laptop.txt - information on the Asus Laptop Extras driver. disk-shock-protection.txt - information on hard disk shock protection. dslm.c - Simple Disk Sleep Monitor program +hpfall.c + - (HP) laptop accelerometer program for disk protection. laptop-mode.txt - how to conserve battery power using laptop-mode. sony-laptop.txt diff --git a/Documentation/leds/00-INDEX b/Documentation/leds/00-INDEX index 1ecd159..b4ef1f3 100644 --- a/Documentation/leds/00-INDEX +++ b/Documentation/leds/00-INDEX @@ -1,3 +1,7 @@ +00-INDEX + - This file +leds-blinkm.txt + - Driver for BlinkM LED-devices. leds-class.txt - documents LED handling under Linux. leds-lp3944.txt @@ -12,3 +16,7 @@ leds-lp55xx.txt - description about lp55xx common driver. leds-lm3556.txt - notes on how to use the leds-lm3556 driver. +ledtrig-oneshot.txt + - One-shot LED trigger for both sporadic and dense events. +ledtrig-transient.txt + - LED Transient Trigger, one shot timer activation. diff --git a/Documentation/m68k/00-INDEX b/Documentation/m68k/00-INDEX index a014e9f..2be8c6b 100644 --- a/Documentation/m68k/00-INDEX +++ b/Documentation/m68k/00-INDEX @@ -1,5 +1,7 @@ 00-INDEX - this file +README.buddha + - Amiga Buddha and Catweasel IDE Driver kernel-options.txt - command line options for Linux/m68k diff --git a/Documentation/networking/00-INDEX b/Documentation/networking/00-INDEX index f11580f..557b6ef 100644 --- a/Documentation/networking/00-INDEX +++ b/Documentation/networking/00-INDEX @@ -6,8 +6,14 @@ - information on the 3Com Etherlink III Series Ethernet cards. 6pack.txt - info on the 6pack protocol, an alternative to KISS for AX.25 -DLINK.txt - - info on the D-Link DE-600/DE-620 parallel port pocket adapters +LICENSE.qla3xxx + - GPLv2 for QLogic Linux Networking HBA Driver +LICENSE.qlge + - GPLv2 for QLogic Linux qlge NIC Driver +LICENSE.qlcnic + - GPLv2 for QLogic Linux qlcnic NIC Driver +Makefile + - Makefile for docsrc. PLIP.txt - PLIP: The Parallel Line Internet Protocol device driver README.ipw2100 @@ -17,7 +23,7 @@ README.ipw2200 README.sb1000 - info on General Instrument/NextLevel SURFboard1000 cable modem. alias.txt - - info on using alias network devices + - info on using alias network devices. arcnet-hardware.txt - tons of info on ARCnet, hubs, jumper settings for ARCnet cards, etc. arcnet.txt @@ -80,7 +86,7 @@ framerelay.txt - info on using Frame Relay/Data Link Connection Identifier (DLCI). gen_stats.txt - Generic networking statistics for netlink users. -generic_hdlc.txt +generic-hdlc.txt - The generic High Level Data Link Control (HDLC) layer. generic_netlink.txt - info on Generic Netlink @@ -88,6 +94,8 @@ gianfar.txt - Gianfar Ethernet Driver. i40e.txt - README for the Intel Ethernet Controller XL710 Driver (i40e). +i40evf.txt + - Short note on the Driver for the Intel(R) XL710 X710 Virtual Function ieee802154.txt - Linux IEEE 802.15.4 implementation, API and drivers igb.txt @@ -102,6 +110,8 @@ ipddp.txt - AppleTalk-IP Decapsulation and AppleTalk-IP Encapsulation iphase.txt - Interphase PCI ATM (i)Chip IA Linux driver info. +ipsec.txt + - Note on not compressing IPSec payload and resulting failed policy check. ipv6.txt - Options to the ipv6 kernel module. ipvs-sysctl.txt @@ -120,6 +130,8 @@ lapb-module.txt - programming information of the LAPB module. ltpc.txt - the Apple or Farallon LocalTalk PC card driver +mac80211-auth-assoc-deauth.txt + - authentication and association / deauth-disassoc with max80211 mac80211-injection.txt - HOWTO use packet injection with mac80211 multiqueue.txt @@ -134,6 +146,10 @@ netdevices.txt - info on network device driver functions exported to the kernel. netif-msg.txt - Design of the network interface message level setting (NETIF_MSG_*). +netlink_mmap.txt + - memory mapped I/O with netlink +nf_conntrack-sysctl.txt + - list of netfilter-sysctl knobs. nfc.txt - The Linux Near Field Communication (NFS) subsystem. openvswitch.txt @@ -176,7 +192,7 @@ skfp.txt - SysKonnect FDDI (SK-5xxx, Compaq Netelligent) driver info. smc9.txt - the driver for SMC's 9000 series of Ethernet cards -spider-net.txt +spider_net.txt - README for the Spidernet Driver (as found in PS3 / Cell BE). stmmac.txt - README for the STMicro Synopsys Ethernet driver. @@ -188,6 +204,8 @@ tcp.txt - short blurb on how TCP output takes place. tcp-thin.txt - kernel tuning options for low rate 'thin' TCP streams. +team.txt + - pointer to information for ethernet teaming devices. tlan.txt - ThunderLAN (Compaq Netelligent 10/100, Olicom OC-2xxx) driver info. tproxy.txt @@ -200,6 +218,8 @@ vortex.txt - info on using 3Com Vortex (3c590, 3c592, 3c595, 3c597) Ethernet cards. vxge.txt - README for the Neterion X3100 PCIe Server Adapter. +vxlan.txt + - Virtual extensible LAN overview x25.txt - general info on X.25 development. x25-iface.txt diff --git a/Documentation/power/00-INDEX b/Documentation/power/00-INDEX index a4d682f..ad04cc8 100644 --- a/Documentation/power/00-INDEX +++ b/Documentation/power/00-INDEX @@ -4,6 +4,8 @@ apm-acpi.txt - basic info about the APM and ACPI support. basic-pm-debugging.txt - Debugging suspend and resume +charger-manager.txt + - Battery charger management. devices.txt - How drivers interact with system-wide power management drivers-testing.txt @@ -22,6 +24,8 @@ pm_qos_interface.txt - info on Linux PM Quality of Service interface power_supply_class.txt - Tells userspace about battery, UPS, AC or DC power supply properties +runtime_pm.txt + - Power management framework for I/O devices. s2ram.txt - How to get suspend to ram working (and debug it when it isn't) states.txt @@ -38,7 +42,5 @@ tricks.txt - How to trick software suspend (to disk) into working when it isn't userland-swsusp.txt - Experimental implementation of software suspend in userspace -video_extension.txt - - ACPI video extensions video.txt - Video issues during resume from suspend diff --git a/Documentation/s390/00-INDEX b/Documentation/s390/00-INDEX index 3a2b963..10c874e 100644 --- a/Documentation/s390/00-INDEX +++ b/Documentation/s390/00-INDEX @@ -16,11 +16,13 @@ Debugging390.txt - hints for debugging on s390 systems. driver-model.txt - information on s390 devices and the driver model. +kvm.txt + - ioctl calls to /dev/kvm on s390. monreader.txt - information on accessing the z/VM monitor stream from Linux. +qeth.txt + - HiperSockets Bridge Port Support. s390dbf.txt - information on using the s390 debug feature. -TAPE - - information on the driver for channel-attached tapes. -zfcpdump +zfcpdump.txt - information on the s390 SCSI dump tool. diff --git a/Documentation/scheduler/00-INDEX b/Documentation/scheduler/00-INDEX index 46702e4..eccf7ad 100644 --- a/Documentation/scheduler/00-INDEX +++ b/Documentation/scheduler/00-INDEX @@ -2,6 +2,8 @@ - this file. sched-arch.txt - CPU Scheduler implementation hints for architecture specific code. +sched-bwc.txt + - CFS bandwidth control overview. sched-design-CFS.txt - goals, design and implementation of the Completely Fair Scheduler. sched-domains.txt diff --git a/Documentation/scsi/00-INDEX b/Documentation/scsi/00-INDEX index 2044be5..c4b978a 100644 --- a/Documentation/scsi/00-INDEX +++ b/Documentation/scsi/00-INDEX @@ -36,6 +36,8 @@ NinjaSCSI.txt - info on WorkBiT NinjaSCSI-32/32Bi driver aacraid.txt - Driver supporting Adaptec RAID controllers +advansys.txt + - List of Advansys Host Adapters aha152x.txt - info on driver for Adaptec AHA152x based adapters aic79xx.txt @@ -44,6 +46,12 @@ aic7xxx.txt - info on driver for Adaptec controllers arcmsr_spec.txt - ARECA FIRMWARE SPEC (for IOP331 adapter) +bfa.txt + - Brocade FC/FCOE adapter driver. +bnx2fc.txt + - FCoE hardware offload for Broadcom network interfaces. +cxgb3i.txt + - Chelsio iSCSI Linux Driver dc395x.txt - README file for the dc395x SCSI driver dpti.txt @@ -52,18 +60,24 @@ dtc3x80.txt - info on driver for DTC 2x80 based adapters g_NCR5380.txt - info on driver for NCR5380 and NCR53c400 based adapters +hpsa.txt + - HP Smart Array Controller SCSI driver. hptiop.txt - HIGHPOINT ROCKETRAID 3xxx RAID DRIVER in2000.txt - info on in2000 driver libsas.txt - Serial Attached SCSI management layer. +link_power_management_policy.txt + - Link power management options. lpfc.txt - LPFC driver release notes megaraid.txt - Common Management Module, shared code handling ioctls for LSI drivers ncr53c8xx.txt - info on driver for NCR53c8xx based adapters +osd.txt + Object-Based Storage Device, command set introduction. osst.txt - info on driver for OnStream SC-x0 SCSI tape ppa.txt @@ -74,6 +88,8 @@ scsi-changer.txt - README for the SCSI media changer driver scsi-generic.txt - info on the sg driver for generic (non-disk/CD/tape) SCSI devices. +scsi-parameters.txt + - List of SCSI-parameters to pass to the kernel at module load-time. scsi.txt - short blurb on using SCSI support as a module. scsi_mid_low_api.txt diff --git a/Documentation/serial/00-INDEX b/Documentation/serial/00-INDEX index 1f1b22f..f9c6b5e 100644 --- a/Documentation/serial/00-INDEX +++ b/Documentation/serial/00-INDEX @@ -4,10 +4,12 @@ README.cycladesZ - info on Cyclades-Z firmware loading. digiepca.txt - info on Digi Intl. {PC,PCI,EISA}Xx and Xem series cards. -hayes-esp.txt - - info on using the Hayes ESP serial driver. +driver + - intro to the low level serial driver. moxa-smartio - file with info on installing/using Moxa multiport serial driver. +n_gsm.txt + - GSM 0710 tty multiplexer howto. riscom8.txt - notes on using the RISCom/8 multi-port serial driver. rocket.txt diff --git a/Documentation/spi/00-INDEX b/Documentation/spi/00-INDEX new file mode 100644 index 0000000..a128fa8 --- /dev/null +++ b/Documentation/spi/00-INDEX @@ -0,0 +1,22 @@ +00-INDEX + - this file. +Makefile + - Makefile for the example sourcefiles. +butterfly + - AVR Butterfly SPI driver overview and pin configuration. +ep93xx_spi + - Basic EP93xx SPI driver configuration. +pxa2xx + - PXA2xx SPI master controller build by spi_message fifo wq +spidev + - Intro to the userspace API for spi devices +spidev_fdx.c + - spidev example file +spi-lm70llp + - Connecting an LM70-LLP sensor to the kernel via the SPI subsys. +spi-sc18is602 + - NXP SC18IS602/603 I2C-bus to SPI bridge +spi-summary + - (Linux) SPI overview. If unsure about SPI or SPI in Linux, start here. +spidev_test.c + - SPI testing utility. diff --git a/Documentation/timers/00-INDEX b/Documentation/timers/00-INDEX index ef2ccbf..6d042dc 100644 --- a/Documentation/timers/00-INDEX +++ b/Documentation/timers/00-INDEX @@ -8,6 +8,8 @@ hpet_example.c - sample hpet timer test program hrtimers.txt - subsystem for high-resolution kernel timers +Makefile + - Build and link hpet_example NO_HZ.txt - Summary of the different methods for the scheduler clock-interrupts management. timers-howto.txt diff --git a/Documentation/virtual/kvm/00-INDEX b/Documentation/virtual/kvm/00-INDEX index 641ec92..fee9f2b 100644 --- a/Documentation/virtual/kvm/00-INDEX +++ b/Documentation/virtual/kvm/00-INDEX @@ -20,5 +20,7 @@ ppc-pv.txt - the paravirtualization interface on PowerPC. review-checklist.txt - review checklist for KVM patches. +s390-diag.txt + - Diagnose hypercall description (for IBM S/390) timekeeping.txt - timekeeping virtualization for x86-based architectures. diff --git a/Documentation/vm/00-INDEX b/Documentation/vm/00-INDEX index a39d066..081c497 100644 --- a/Documentation/vm/00-INDEX +++ b/Documentation/vm/00-INDEX @@ -16,8 +16,6 @@ hwpoison.txt - explains what hwpoison is ksm.txt - how to use the Kernel Samepage Merging feature. -locking - - info on how locking and synchronization is done in the Linux vm code. numa - information about NUMA specific code in the Linux vm. numa_memory_policy.txt @@ -32,6 +30,8 @@ slub.txt - a short users guide for SLUB. soft-dirty.txt - short explanation for soft-dirty PTEs +split_page_table_lock + - Separate per-table lock to improve scalability of the old page_table_lock. transhuge.txt - Transparent Hugepage Support, alternative way of using hugepages. unevictable-lru.txt diff --git a/Documentation/w1/masters/00-INDEX b/Documentation/w1/masters/00-INDEX index d63fa02..8330cf9 100644 --- a/Documentation/w1/masters/00-INDEX +++ b/Documentation/w1/masters/00-INDEX @@ -4,7 +4,9 @@ ds2482 - The Maxim/Dallas Semiconductor DS2482 provides 1-wire busses. ds2490 - The Maxim/Dallas Semiconductor DS2490 builds USB <-> W1 bridges. -mxc_w1 +mxc-w1 - W1 master controller driver found on Freescale MX2/MX3 SoCs +omap-hdq + - HDQ/1-wire module of TI OMAP 2430/3430. w1-gpio - GPIO 1-wire bus master driver. diff --git a/Documentation/w1/slaves/00-INDEX b/Documentation/w1/slaves/00-INDEX index 75613c9..6e18c70 100644 --- a/Documentation/w1/slaves/00-INDEX +++ b/Documentation/w1/slaves/00-INDEX @@ -4,3 +4,5 @@ w1_therm - The Maxim/Dallas Semiconductor ds18*20 temperature sensor. w1_ds2423 - The Maxim/Dallas Semiconductor ds2423 counter device. +w1_ds28e04 + - The Maxim/Dallas Semiconductor ds28e04 eeprom. diff --git a/Documentation/x86/00-INDEX b/Documentation/x86/00-INDEX index f37b46d..6922644 100644 --- a/Documentation/x86/00-INDEX +++ b/Documentation/x86/00-INDEX @@ -1,6 +1,20 @@ 00-INDEX - this file -mtrr.txt - - how to use x86 Memory Type Range Registers to increase performance +boot.txt + - List of boot protocol versions +early-microcode.txt + - How to load microcode from an initrd-CPIO archive early to fix CPU issues. +earlyprintk.txt + - Using earlyprintk with a USB2 debug port key. +entry_64.txt + - Describe (some of the) kernel entry points for x86. exception-tables.txt - why and how Linux kernel uses exception tables on x86 +mtrr.txt + - how to use x86 Memory Type Range Registers to increase performance +pat.txt + - Page Attribute Table intro and API +usb-legacy-support.txt + - how to fix/avoid quirks when using emulated PS/2 mouse/keyboard. +zero-page.txt + - layout of the first page of memory. -- cgit v0.10.2 From a3eb7fbb41eb8d6e22d491741b8c5d5aa6cb069a Mon Sep 17 00:00:00 2001 From: Alexey Khoroshilov Date: Mon, 10 Feb 2014 14:25:35 -0800 Subject: drivers/message/i2o/i2o_config.c: fix deadlock in compat_ioctl(I2OGETIOPS) i2o_cfg_compat_ioctl(I2OGETIOPS) locks i2o_cfg_mutex and then calls i2o_cfg_ioctl(I2OGETIOPS) that locks i2o_cfg_mutex as well. A deadlock is guaranteed. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c index a60c188..04bd3b6 100644 --- a/drivers/message/i2o/i2o_config.c +++ b/drivers/message/i2o/i2o_config.c @@ -754,19 +754,19 @@ static long i2o_cfg_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg) { int ret; - mutex_lock(&i2o_cfg_mutex); switch (cmd) { case I2OGETIOPS: ret = i2o_cfg_ioctl(file, cmd, arg); break; case I2OPASSTHRU32: + mutex_lock(&i2o_cfg_mutex); ret = i2o_cfg_passthru32(file, cmd, arg); + mutex_unlock(&i2o_cfg_mutex); break; default: ret = -ENOIOCTLCMD; break; } - mutex_unlock(&i2o_cfg_mutex); return ret; } -- cgit v0.10.2 From 38dfac843cb6d7be1874888839817404a15a6b3c Mon Sep 17 00:00:00 2001 From: Greg Pearson Date: Mon, 10 Feb 2014 14:25:36 -0800 Subject: vmcore: prevent PT_NOTE p_memsz overflow during header update Currently, update_note_header_size_elf64() and update_note_header_size_elf32() will add the size of a PT_NOTE entry to real_sz even if that causes real_sz to exceeds max_sz. This patch corrects the while loop logic in those routines to ensure that does not happen and prints a warning if a PT_NOTE entry is dropped. If zero PT_NOTE entries are found or this condition is encountered because the only entry was dropped, a warning is printed and an error is returned. One possible negative side effect of exceeding the max_sz limit is an allocation failure in merge_note_headers_elf64() or merge_note_headers_elf32() which would produce console output such as the following while booting the crash kernel. vmalloc: allocation failure: 14076997632 bytes swapper/0: page allocation failure: order:0, mode:0x80d2 CPU: 0 PID: 1 Comm: swapper/0 Not tainted 3.10.0-gbp1 #7 Call Trace: dump_stack+0x19/0x1b warn_alloc_failed+0xf0/0x160 __vmalloc_node_range+0x19e/0x250 vmalloc_user+0x4c/0x70 merge_note_headers_elf64.constprop.9+0x116/0x24a vmcore_init+0x2d4/0x76c do_one_initcall+0xe2/0x190 kernel_init_freeable+0x17c/0x207 kernel_init+0xe/0x180 ret_from_fork+0x7c/0xb0 Kdump: vmcore not initialized kdump: dump target is /dev/sda4 kdump: saving to /sysroot//var/crash/127.0.0.1-2014.01.28-13:58:52/ kdump: saving vmcore-dmesg.txt Cannot open /proc/vmcore: No such file or directory kdump: saving vmcore-dmesg.txt failed kdump: saving vmcore kdump: saving vmcore failed This type of failure has been seen on a four socket prototype system with certain memory configurations. Most PT_NOTE sections have a single entry similar to: n_namesz = 0x5 n_descsz = 0x150 n_type = 0x1 Occasionally, a second entry is encountered with very large n_namesz and n_descsz sizes: n_namesz = 0x80000008 n_descsz = 0x510ae163 n_type = 0x80000008 Not yet sure of the source of these extra entries, they seem bogus, but they shouldn't cause crash dump to fail. Signed-off-by: Greg Pearson Acked-by: Vivek Goyal Cc: HATAYAMA Daisuke Cc: Michael Holzheu Cc: "Eric W. Biederman" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c index 2ca7ba0..88d4585 100644 --- a/fs/proc/vmcore.c +++ b/fs/proc/vmcore.c @@ -468,17 +468,24 @@ static int __init update_note_header_size_elf64(const Elf64_Ehdr *ehdr_ptr) return rc; } nhdr_ptr = notes_section; - while (real_sz < max_sz) { - if (nhdr_ptr->n_namesz == 0) - break; + while (nhdr_ptr->n_namesz != 0) { sz = sizeof(Elf64_Nhdr) + ((nhdr_ptr->n_namesz + 3) & ~3) + ((nhdr_ptr->n_descsz + 3) & ~3); + if ((real_sz + sz) > max_sz) { + pr_warn("Warning: Exceeded p_memsz, dropping PT_NOTE entry n_namesz=0x%x, n_descsz=0x%x\n", + nhdr_ptr->n_namesz, nhdr_ptr->n_descsz); + break; + } real_sz += sz; nhdr_ptr = (Elf64_Nhdr*)((char*)nhdr_ptr + sz); } kfree(notes_section); phdr_ptr->p_memsz = real_sz; + if (real_sz == 0) { + pr_warn("Warning: Zero PT_NOTE entries found\n"); + return -EINVAL; + } } return 0; @@ -648,17 +655,24 @@ static int __init update_note_header_size_elf32(const Elf32_Ehdr *ehdr_ptr) return rc; } nhdr_ptr = notes_section; - while (real_sz < max_sz) { - if (nhdr_ptr->n_namesz == 0) - break; + while (nhdr_ptr->n_namesz != 0) { sz = sizeof(Elf32_Nhdr) + ((nhdr_ptr->n_namesz + 3) & ~3) + ((nhdr_ptr->n_descsz + 3) & ~3); + if ((real_sz + sz) > max_sz) { + pr_warn("Warning: Exceeded p_memsz, dropping PT_NOTE entry n_namesz=0x%x, n_descsz=0x%x\n", + nhdr_ptr->n_namesz, nhdr_ptr->n_descsz); + break; + } real_sz += sz; nhdr_ptr = (Elf32_Nhdr*)((char*)nhdr_ptr + sz); } kfree(notes_section); phdr_ptr->p_memsz = real_sz; + if (real_sz == 0) { + pr_warn("Warning: Zero PT_NOTE entries found\n"); + return -EINVAL; + } } return 0; -- cgit v0.10.2 From bd180b4e2b0d5b8f14978e295741e69e6a01d398 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 10 Feb 2014 14:25:38 -0800 Subject: drivers/md/bcache/extents.c: use %zi to format size_t drivers/md/bcache/extents.c: In function `btree_ptr_bad_expensive': drivers/md/bcache/extents.c:196: warning: format `%li' expects type `long int', but argument 4 has type `size_t' Signed-off-by: Geert Uytterhoeven Cc: Kent Overstreet Cc: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/md/bcache/extents.c b/drivers/md/bcache/extents.c index c3ead58..416d1a3 100644 --- a/drivers/md/bcache/extents.c +++ b/drivers/md/bcache/extents.c @@ -194,7 +194,7 @@ err: mutex_unlock(&b->c->bucket_lock); bch_extent_to_text(buf, sizeof(buf), k); btree_bug(b, -"inconsistent btree pointer %s: bucket %li pin %i prio %i gen %i last_gc %i mark %llu gc_gen %i", +"inconsistent btree pointer %s: bucket %zi pin %i prio %i gen %i last_gc %i mark %llu gc_gen %i", buf, PTR_BUCKET_NR(b->c, k, i), atomic_read(&g->pin), g->prio, g->gen, g->last_gc, GC_MARK(g), g->gc_gen); return true; -- cgit v0.10.2 From 255d0884f5635122adb23866b242b4ca112f4bc8 Mon Sep 17 00:00:00 2001 From: David Rientjes Date: Mon, 10 Feb 2014 14:25:39 -0800 Subject: mm/slub.c: list_lock may not be held in some circumstances Commit c65c1877bd68 ("slub: use lockdep_assert_held") incorrectly required that add_full() and remove_full() hold n->list_lock. The lock is only taken when kmem_cache_debug(s), since that's the only time it actually does anything. Require that the lock only be taken under such a condition. Reported-by: Larry Finger Tested-by: Larry Finger Tested-by: Paul E. McKenney Acked-by: Christoph Lameter Cc: Pekka Enberg Signed-off-by: David Rientjes Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/mm/slub.c b/mm/slub.c index 7e3e045..3d3a8a7 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -1004,21 +1004,19 @@ static inline void slab_free_hook(struct kmem_cache *s, void *x) static void add_full(struct kmem_cache *s, struct kmem_cache_node *n, struct page *page) { - lockdep_assert_held(&n->list_lock); - if (!(s->flags & SLAB_STORE_USER)) return; + lockdep_assert_held(&n->list_lock); list_add(&page->lru, &n->full); } static void remove_full(struct kmem_cache *s, struct kmem_cache_node *n, struct page *page) { - lockdep_assert_held(&n->list_lock); - if (!(s->flags & SLAB_STORE_USER)) return; + lockdep_assert_held(&n->list_lock); list_del(&page->lru); } -- cgit v0.10.2 From a9c8e4beeeb64c22b84c803747487857fe424b68 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Mon, 10 Feb 2014 14:25:40 -0800 Subject: xen: properly account for _PAGE_NUMA during xen pte translations Steven Noonan forwarded a users report where they had a problem starting vsftpd on a Xen paravirtualized guest, with this in dmesg: BUG: Bad page map in process vsftpd pte:8000000493b88165 pmd:e9cc01067 page:ffffea00124ee200 count:0 mapcount:-1 mapping: (null) index:0x0 page flags: 0x2ffc0000000014(referenced|dirty) addr:00007f97eea74000 vm_flags:00100071 anon_vma:ffff880e98f80380 mapping: (null) index:7f97eea74 CPU: 4 PID: 587 Comm: vsftpd Not tainted 3.12.7-1-ec2 #1 Call Trace: dump_stack+0x45/0x56 print_bad_pte+0x22e/0x250 unmap_single_vma+0x583/0x890 unmap_vmas+0x65/0x90 exit_mmap+0xc5/0x170 mmput+0x65/0x100 do_exit+0x393/0x9e0 do_group_exit+0xcc/0x140 SyS_exit_group+0x14/0x20 system_call_fastpath+0x1a/0x1f Disabling lock debugging due to kernel taint BUG: Bad rss-counter state mm:ffff880e9ca60580 idx:0 val:-1 BUG: Bad rss-counter state mm:ffff880e9ca60580 idx:1 val:1 The issue could not be reproduced under an HVM instance with the same kernel, so it appears to be exclusive to paravirtual Xen guests. He bisected the problem to commit 1667918b6483 ("mm: numa: clear numa hinting information on mprotect") that was also included in 3.12-stable. The problem was related to how xen translates ptes because it was not accounting for the _PAGE_NUMA bit. This patch splits pte_present to add a pteval_present helper for use by xen so both bare metal and xen use the same code when checking if a PTE is present. [mgorman@suse.de: wrote changelog, proposed minor modifications] [akpm@linux-foundation.org: fix typo in comment] Reported-by: Steven Noonan Tested-by: Steven Noonan Signed-off-by: Elena Ufimtseva Signed-off-by: Mel Gorman Reviewed-by: David Vrabel Acked-by: Konrad Rzeszutek Wilk Cc: [3.12+] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index bbc8b12..5ad38ad 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -445,10 +445,20 @@ static inline int pte_same(pte_t a, pte_t b) return a.pte == b.pte; } +static inline int pteval_present(pteval_t pteval) +{ + /* + * Yes Linus, _PAGE_PROTNONE == _PAGE_NUMA. Expressing it this + * way clearly states that the intent is that protnone and numa + * hinting ptes are considered present for the purposes of + * pagetable operations like zapping, protection changes, gup etc. + */ + return pteval & (_PAGE_PRESENT | _PAGE_PROTNONE | _PAGE_NUMA); +} + static inline int pte_present(pte_t a) { - return pte_flags(a) & (_PAGE_PRESENT | _PAGE_PROTNONE | - _PAGE_NUMA); + return pteval_present(pte_flags(a)); } #define pte_accessible pte_accessible diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 2423ef0..256282e 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -365,7 +365,7 @@ void xen_ptep_modify_prot_commit(struct mm_struct *mm, unsigned long addr, /* Assume pteval_t is equivalent to all the other *val_t types. */ static pteval_t pte_mfn_to_pfn(pteval_t val) { - if (val & _PAGE_PRESENT) { + if (pteval_present(val)) { unsigned long mfn = (val & PTE_PFN_MASK) >> PAGE_SHIFT; unsigned long pfn = mfn_to_pfn(mfn); @@ -381,7 +381,7 @@ static pteval_t pte_mfn_to_pfn(pteval_t val) static pteval_t pte_pfn_to_mfn(pteval_t val) { - if (val & _PAGE_PRESENT) { + if (pteval_present(val)) { unsigned long pfn = (val & PTE_PFN_MASK) >> PAGE_SHIFT; pteval_t flags = val & PTE_FLAGS_MASK; unsigned long mfn; -- cgit v0.10.2 From 96c7a2ff21501691587e1ae969b83cbec8b78e08 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Mon, 10 Feb 2014 14:25:41 -0800 Subject: fs/file.c:fdtable: avoid triggering OOMs from alloc_fdmem Recently due to a spike in connections per second memcached on 3 separate boxes triggered the OOM killer from accept. At the time the OOM killer was triggered there was 4GB out of 36GB free in zone 1. The problem was that alloc_fdtable was allocating an order 3 page (32KiB) to hold a bitmap, and there was sufficient fragmentation that the largest page available was 8KiB. I find the logic that PAGE_ALLOC_COSTLY_ORDER can't fail pretty dubious but I do agree that order 3 allocations are very likely to succeed. There are always pathologies where order > 0 allocations can fail when there are copious amounts of free memory available. Using the pigeon hole principle it is easy to show that it requires 1 page more than 50% of the pages being free to guarantee an order 1 (8KiB) allocation will succeed, 1 page more than 75% of the pages being free to guarantee an order 2 (16KiB) allocation will succeed and 1 page more than 87.5% of the pages being free to guarantee an order 3 allocate will succeed. A server churning memory with a lot of small requests and replies like memcached is a common case that if anything can will skew the odds against large pages being available. Therefore let's not give external applications a practical way to kill linux server applications, and specify __GFP_NORETRY to the kmalloc in alloc_fdmem. Unless I am misreading the code and by the time the code reaches should_alloc_retry in __alloc_pages_slowpath (where __GFP_NORETRY becomes signification). We have already tried everything reasonable to allocate a page and the only thing left to do is wait. So not waiting and falling back to vmalloc immediately seems like the reasonable thing to do even if there wasn't a chance of triggering the OOM killer. Signed-off-by: "Eric W. Biederman" Cc: Eric Dumazet Acked-by: David Rientjes Cc: Cong Wang Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/file.c b/fs/file.c index 771578b..db25c2b 100644 --- a/fs/file.c +++ b/fs/file.c @@ -34,7 +34,7 @@ static void *alloc_fdmem(size_t size) * vmalloc() if the allocation size will be considered "large" by the VM. */ if (size <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER)) { - void *data = kmalloc(size, GFP_KERNEL|__GFP_NOWARN); + void *data = kmalloc(size, GFP_KERNEL|__GFP_NOWARN|__GFP_NORETRY); if (data != NULL) return data; } -- cgit v0.10.2 From 79040cad3f8235937e229f1b9401ba36dd5ad69b Mon Sep 17 00:00:00 2001 From: Prarit Bhargava Date: Mon, 10 Feb 2014 14:25:43 -0800 Subject: drivers/edac/edac_mc_sysfs.c: poll timeout cannot be zero If you do echo 0 > /sys/module/edac_core/parameters/edac_mc_poll_msec the following stack trace is output because the edac module is not designed to poll with a timeout of zero. WARNING: CPU: 12 PID: 0 at lib/list_debug.c:33 __list_add+0xac/0xc0() list_add corruption. prev->next should be next (ffff8808291dd1b8), but was (null). (prev=ffff8808286fe3f8). Modules linked in: sg nfsv3 rpcsec_gss_krb5 nfsv4 dns_resolver nfs fscache cfg80211 rfkill x86_pkg_temp_thermal coretemp kvm_intel kvm ixgbe e1000e crct10dif_pclmul crc32_pclmul crc32c_intel ghash_clmulni_intel aesni_intel lrw gf128mul glue_helper ablk_helper cryptd iTCO_wdt ptp sb_edac iTCO_vendor_support pps_core mdio ipmi_devintf edac_core ioatdma microcode shpchp lpc_ich pcspkr i2c_i801 dca mfd_core ipmi_si wmi ipmi_msghandler nfsd auth_rpcgss nfs_acl lockd sunrpc xfs libcrc32c sd_mod sr_mod cdrom crc_t10dif crct10dif_common mgag200 syscopyarea sysfillrect sysimgblt isci i2c_algo_bit drm_kms_helper ttm drm libsas ahci libahci scsi_transport_sas libata i2c_core dm_mirror dm_region_hash dm_log dm_mod CPU: 12 PID: 0 Comm: swapper/12 Not tainted 3.13.0+ #1 Hardware name: Intel Corporation LH Pass ........../SVRBD-ROW_T, BIOS SE5C600.86B.01.08.0003.022620131521 02/26/2013 Call Trace: __list_add+0xac/0xc0 __internal_add_timer+0xab/0x130 internal_add_timer+0x17/0x40 mod_timer_pinned+0xca/0x170 intel_pstate_timer_func+0x28a/0x380 call_timer_fn+0x36/0x100 run_timer_softirq+0x1ff/0x2f0 __do_softirq+0xf5/0x2e0 irq_exit+0x10d/0x120 smp_apic_timer_interrupt+0x45/0x60 apic_timer_interrupt+0x6d/0x80 cpuidle_idle_call+0xb9/0x1f0 arch_cpu_idle+0xe/0x30 cpu_startup_entry+0x9e/0x240 start_secondary+0x1e4/0x290 kernel BUG at kernel/timer.c:1084! invalid opcode: 0000 [#1] SMP Modules linked in: sg nfsv3 rpcsec_gss_krb5 nfsv4 dns_resolver nfs fscache cfg80211 rfkill x86_pkg_temp_thermal coretemp kvm_intel kvm ixgbe e1000e crct10dif_pclmul crc32_pclmul crc32c_intel ghash_clmulni_intel aesni_intel lrw gf128mul glue_helper ablk_helper cryptd iTCO_wdt ptp sb_edac iTCO_vendor_support pps_core mdio ipmi_devintf edac_core ioatdma microcode shpchp lpc_ich pcspkr i2c_i801 dca mfd_core ipmi_si wmi ipmi_msghandler nfsd auth_rpcgss nfs_acl lockd sunrpc xfs libcrc32c sd_mod sr_mod cdrom crc_t10dif crct10dif_common mgag200 syscopyarea sysfillrect sysimgblt isci i2c_algo_bit drm_kms_helper ttm drm libsas ahci libahci scsi_transport_sas libata i2c_core dm_mirror dm_region_hash dm_log dm_mod CPU: 12 PID: 0 Comm: swapper/12 Tainted: G W 3.13.0+ #1 Hardware name: Intel Corporation LH Pass ........../SVRBD-ROW_T, BIOS SE5C600.86B.01.08.0003.022620131521 02/26/2013 Call Trace: run_timer_softirq+0x245/0x2f0 __do_softirq+0xf5/0x2e0 irq_exit+0x10d/0x120 smp_apic_timer_interrupt+0x45/0x60 apic_timer_interrupt+0x6d/0x80 cpuidle_idle_call+0xb9/0x1f0 arch_cpu_idle+0xe/0x30 cpu_startup_entry+0x9e/0x240 start_secondary+0x1e4/0x290 RIP cascade+0x93/0xa0 WARNING: CPU: 36 PID: 1154 at kernel/workqueue.c:1461 __queue_delayed_work+0xed/0x1a0() Modules linked in: sg nfsv3 rpcsec_gss_krb5 nfsv4 dns_resolver nfs fscache cfg80211 rfkill x86_pkg_temp_thermal coretemp kvm_intel kvm ixgbe e1000e crct10dif_pclmul crc32_pclmul crc32c_intel ghash_clmulni_intel aesni_intel lrw gf128mul glue_helper ablk_helper cryptd iTCO_wdt ptp sb_edac iTCO_vendor_support pps_core mdio ipmi_devintf edac_core ioatdma microcode shpchp lpc_ich pcspkr i2c_i801 dca mfd_core ipmi_si wmi ipmi_msghandler nfsd auth_rpcgss nfs_acl lockd sunrpc xfs libcrc32c sd_mod sr_mod cdrom crc_t10dif crct10dif_common mgag200 syscopyarea sysfillrect sysimgblt isci i2c_algo_bit drm_kms_helper ttm drm libsas ahci libahci scsi_transport_sas libata i2c_core dm_mirror dm_region_hash dm_log dm_mod CPU: 36 PID: 1154 Comm: kworker/u481:3 Tainted: G W 3.13.0+ #1 Hardware name: Intel Corporation LH Pass ........../SVRBD-ROW_T, BIOS SE5C600.86B.01.08.0003.022620131521 02/26/2013 Workqueue: edac-poller edac_mc_workq_function [edac_core] Call Trace: dump_stack+0x45/0x56 warn_slowpath_common+0x7d/0xa0 warn_slowpath_null+0x1a/0x20 __queue_delayed_work+0xed/0x1a0 queue_delayed_work_on+0x27/0x50 edac_mc_workq_function+0x72/0xa0 [edac_core] process_one_work+0x17b/0x460 worker_thread+0x11b/0x400 kthread+0xd2/0xf0 ret_from_fork+0x7c/0xb0 This patch adds a range check in the edac_mc_poll_msec code to check for 0. Signed-off-by: Prarit Bhargava Cc: Doug Thompson Cc: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index 51c0362..8ec1747 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c @@ -61,7 +61,7 @@ static int edac_set_poll_msec(const char *val, struct kernel_param *kp) ret = kstrtol(val, 0, &l); if (ret) return ret; - if ((int)l != l) + if (!l || ((int)l != l)) return -EINVAL; *((int *)kp->arg) = l; -- cgit v0.10.2 From a987c7ca7fc9225a587b1dc59d7d4ad2d9e2e08e Mon Sep 17 00:00:00 2001 From: Younger Liu Date: Mon, 10 Feb 2014 14:25:44 -0800 Subject: ocfs2: fix ocfs2_sync_file() if filesystem is readonly If filesystem is readonly, there is no need to flush drive's caches or force any uncommitted transactions. [akpm@linux-foundation.org: return -EROFS, not 0] Signed-off-by: Younger Liu Cc: Joel Becker Cc: Mark Fasheh Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index d77d71e..fcd9706 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -185,6 +185,9 @@ static int ocfs2_sync_file(struct file *file, loff_t start, loff_t end, file->f_path.dentry->d_name.name, (unsigned long long)datasync); + if (ocfs2_is_hard_readonly(osb) || ocfs2_is_soft_readonly(osb)) + return -EROFS; + err = filemap_write_and_wait_range(inode->i_mapping, start, end); if (err) return err; -- cgit v0.10.2 From 25fba9bebeb79447bbe08dc0e1f441caef9f5644 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 10 Feb 2014 14:25:45 -0800 Subject: gitignore: add all.config This is used by kbuild to load preset Kconfig options. We need to ignore it, otherwise git clean kills it. Signed-off-by: Borislav Petkov Cc: Michal Marek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/.gitignore b/.gitignore index 7e9932e..42fa0d5 100644 --- a/.gitignore +++ b/.gitignore @@ -92,3 +92,6 @@ extra_certificates signing_key.priv signing_key.x509 x509.genkey + +# Kconfig presets +all.config -- cgit v0.10.2 From 1e4dd9461fabfbc780cdfaf103cec790f3a53325 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Mon, 10 Feb 2014 14:25:46 -0800 Subject: slub: do not assert not having lock in removing freed partial Vladimir reported the following issue: Commit c65c1877bd68 ("slub: use lockdep_assert_held") requires remove_partial() to be called with n->list_lock held, but free_partial() called from kmem_cache_close() on cache destruction does not follow this rule, leading to a warning: WARNING: CPU: 0 PID: 2787 at mm/slub.c:1536 __kmem_cache_shutdown+0x1b2/0x1f0() Modules linked in: CPU: 0 PID: 2787 Comm: modprobe Tainted: G W 3.14.0-rc1-mm1+ #1 Hardware name: 0000000000000600 ffff88003ae1dde8 ffffffff816d9583 0000000000000600 0000000000000000 ffff88003ae1de28 ffffffff8107c107 0000000000000000 ffff880037ab2b00 ffff88007c240d30 ffffea0001ee5280 ffffea0001ee52a0 Call Trace: __kmem_cache_shutdown+0x1b2/0x1f0 kmem_cache_destroy+0x43/0xf0 xfs_destroy_zones+0x103/0x110 [xfs] exit_xfs_fs+0x38/0x4e4 [xfs] SyS_delete_module+0x19a/0x1f0 system_call_fastpath+0x16/0x1b His solution was to add a spinlock in order to quiet lockdep. Although there would be no contention to adding the lock, that lock also requires disabling of interrupts which will have a larger impact on the system. Instead of adding a spinlock to a location where it is not needed for lockdep, make a __remove_partial() function that does not test if the list_lock is held, as no one should have it due to it being freed. Also added a __add_partial() function that does not do the lock validation either, as it is not needed for the creation of the cache. Signed-off-by: Steven Rostedt Reported-by: Vladimir Davydov Suggested-by: David Rientjes Acked-by: David Rientjes Acked-by: Vladimir Davydov Acked-by: Christoph Lameter Cc: Pekka Enberg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/mm/slub.c b/mm/slub.c index 3d3a8a7..25f14ad 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -1518,11 +1518,9 @@ static void discard_slab(struct kmem_cache *s, struct page *page) /* * Management of partially allocated slabs. */ -static inline void add_partial(struct kmem_cache_node *n, - struct page *page, int tail) +static inline void +__add_partial(struct kmem_cache_node *n, struct page *page, int tail) { - lockdep_assert_held(&n->list_lock); - n->nr_partial++; if (tail == DEACTIVATE_TO_TAIL) list_add_tail(&page->lru, &n->partial); @@ -1530,15 +1528,27 @@ static inline void add_partial(struct kmem_cache_node *n, list_add(&page->lru, &n->partial); } -static inline void remove_partial(struct kmem_cache_node *n, - struct page *page) +static inline void add_partial(struct kmem_cache_node *n, + struct page *page, int tail) { lockdep_assert_held(&n->list_lock); + __add_partial(n, page, tail); +} +static inline void +__remove_partial(struct kmem_cache_node *n, struct page *page) +{ list_del(&page->lru); n->nr_partial--; } +static inline void remove_partial(struct kmem_cache_node *n, + struct page *page) +{ + lockdep_assert_held(&n->list_lock); + __remove_partial(n, page); +} + /* * Remove slab from the partial list, freeze it and * return the pointer to the freelist. @@ -2904,12 +2914,10 @@ static void early_kmem_cache_node_alloc(int node) inc_slabs_node(kmem_cache_node, node, page->objects); /* - * the lock is for lockdep's sake, not for any actual - * race protection + * No locks need to be taken here as it has just been + * initialized and there is no concurrent access. */ - spin_lock(&n->list_lock); - add_partial(n, page, DEACTIVATE_TO_HEAD); - spin_unlock(&n->list_lock); + __add_partial(n, page, DEACTIVATE_TO_HEAD); } static void free_kmem_cache_nodes(struct kmem_cache *s) @@ -3195,7 +3203,7 @@ static void free_partial(struct kmem_cache *s, struct kmem_cache_node *n) list_for_each_entry_safe(page, h, &n->partial, lru) { if (!page->inuse) { - remove_partial(n, page); + __remove_partial(n, page); discard_slab(s, page); } else { list_slab_objects(s, page, -- cgit v0.10.2 From a0b54adda3fe4b4cc6d28f2a9217cd35d1aa888c Mon Sep 17 00:00:00 2001 From: Rafael Aquini Date: Mon, 10 Feb 2014 14:25:48 -0800 Subject: mm: fix page leak at nfs_symlink() Changes in commit a0b8cab3b9b2 ("mm: remove lru parameter from __pagevec_lru_add and remove parts of pagevec API") have introduced a call to add_to_page_cache_lru() which causes a leak in nfs_symlink() as now the page gets an extra refcount that is not dropped. Jan Stancek observed and reported the leak effect while running test8 from Connectathon Testsuite. After several iterations over the test case, which creates several symlinks on a NFS mountpoint, the test system was quickly getting into an out-of-memory scenario. This patch fixes the page leak by dropping that extra refcount add_to_page_cache_lru() is grabbing. Signed-off-by: Jan Stancek Signed-off-by: Rafael Aquini Acked-by: Mel Gorman Acked-by: Rik van Riel Cc: Jeff Layton Cc: Trond Myklebust Cc: [3.11.x+] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index be38b57..4a48fe4 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -1846,6 +1846,11 @@ int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) GFP_KERNEL)) { SetPageUptodate(page); unlock_page(page); + /* + * add_to_page_cache_lru() grabs an extra page refcount. + * Drop it here to avoid leaking this page later. + */ + page_cache_release(page); } else __free_page(page); -- cgit v0.10.2 From fb37bb04d6c8d6c44e61d9da189dcfa6aa0f135e Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Mon, 10 Feb 2014 14:25:49 -0800 Subject: smp.h: fix x86+cpu.c sparse warnings about arch nonboot CPU calls Use what we already do for arch_disable_smp_support() to fix these: arch/x86/kernel/smpboot.c:1155:6: warning: symbol 'arch_enable_nonboot_cpus_begin' was not declared. Should it be static? arch/x86/kernel/smpboot.c:1160:6: warning: symbol 'arch_enable_nonboot_cpus_end' was not declared. Should it be static? kernel/cpu.c:512:13: warning: symbol 'arch_enable_nonboot_cpus_begin' was not declared. Should it be static? kernel/cpu.c:516:13: warning: symbol 'arch_enable_nonboot_cpus_end' was not declared. Should it be static? Signed-off-by: Paul Gortmaker Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/smp.h b/include/linux/smp.h index 3834f43..6ae004e 100644 --- a/include/linux/smp.h +++ b/include/linux/smp.h @@ -188,6 +188,9 @@ static inline void kick_all_cpus_sync(void) { } */ extern void arch_disable_smp_support(void); +extern void arch_enable_nonboot_cpus_begin(void); +extern void arch_enable_nonboot_cpus_end(void); + void smp_setup_processor_id(void); #endif /* __LINUX_SMP_H */ -- cgit v0.10.2 From 8d547ff4ac5927245e0833ac18528f939da0ee0e Mon Sep 17 00:00:00 2001 From: Naoya Horiguchi Date: Mon, 10 Feb 2014 14:25:50 -0800 Subject: mm/memory-failure.c: move refcount only in !MF_COUNT_INCREASED mce-test detected a test failure when injecting error to a thp tail page. This is because we take page refcount of the tail page in madvise_hwpoison() while the fix in commit a3e0f9e47d5e ("mm/memory-failure.c: transfer page count from head page to tail page after split thp") assumes that we always take refcount on the head page. When a real memory error happens we take refcount on the head page where memory_failure() is called without MF_COUNT_INCREASED set, so it seems to me that testing memory error on thp tail page using madvise makes little sense. This patch cancels moving refcount in !MF_COUNT_INCREASED for valid testing. [akpm@linux-foundation.org: s/&&/&/] Signed-off-by: Naoya Horiguchi Cc: Andi Kleen Cc: Wanpeng Li Cc: Chen Gong Cc: [3.9+: a3e0f9e47d5e] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/mm/memory-failure.c b/mm/memory-failure.c index 4f08a2d..2f2f34a 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -945,8 +945,10 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn, * to it. Similarly, page lock is shifted. */ if (hpage != p) { - put_page(hpage); - get_page(p); + if (!(flags & MF_COUNT_INCREASED)) { + put_page(hpage); + get_page(p); + } lock_page(p); unlock_page(hpage); *hpagep = p; -- cgit v0.10.2 From d62e74be1270c89fbaf7aada8218bfdf62d00a58 Mon Sep 17 00:00:00 2001 From: Younger Liu Date: Mon, 10 Feb 2014 14:25:51 -0800 Subject: ocfs2: fix issue that ocfs2_setattr() does not deal with new_i_size==i_size The issue scenario is as following: - Create a small file and fallocate a large disk space for a file with FALLOC_FL_KEEP_SIZE option. - ftruncate the file back to the original size again. but the disk free space is not changed back. This is a real bug that be fixed in this patch. In order to solve the issue above, we modified ocfs2_setattr(), if attr->ia_size != i_size_read(inode), It calls ocfs2_truncate_file(), and truncate disk space to attr->ia_size. Signed-off-by: Younger Liu Reviewed-by: Jie Liu Tested-by: Jie Liu Cc: Joel Becker Reviewed-by: Mark Fasheh Cc: Sunil Mushran Reviewed-by: Jensen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index aada580..e2edff3 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c @@ -7158,7 +7158,7 @@ int ocfs2_truncate_inline(struct inode *inode, struct buffer_head *di_bh, if (end > i_size_read(inode)) end = i_size_read(inode); - BUG_ON(start >= end); + BUG_ON(start > end); if (!(OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) || !(le16_to_cpu(di->i_dyn_features) & OCFS2_INLINE_DATA_FL) || diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index fcd9706..9148353 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -477,11 +477,6 @@ static int ocfs2_truncate_file(struct inode *inode, goto bail; } - /* lets handle the simple truncate cases before doing any more - * cluster locking. */ - if (new_i_size == le64_to_cpu(fe->i_size)) - goto bail; - down_write(&OCFS2_I(inode)->ip_alloc_sem); ocfs2_resv_discard(&osb->osb_la_resmap, @@ -1148,14 +1143,14 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr) goto bail_unlock_rw; } - if (size_change && attr->ia_size != i_size_read(inode)) { + if (size_change) { status = inode_newsize_ok(inode, attr->ia_size); if (status) goto bail_unlock; inode_dio_wait(inode); - if (i_size_read(inode) > attr->ia_size) { + if (i_size_read(inode) >= attr->ia_size) { if (ocfs2_should_order_data(inode)) { status = ocfs2_begin_ordered_truncate(inode, attr->ia_size); -- cgit v0.10.2 From c7d2cbc364b2a237b0ed1bdd7cbf8a24c8a89dfd Mon Sep 17 00:00:00 2001 From: Junxiao Bi Date: Mon, 10 Feb 2014 14:25:53 -0800 Subject: ocfs2: update inode size after zeroing the hole fs-writeback will release the dirty pages without page lock whose offset are over inode size, the release happens at block_write_full_page_endio(). If not update, dirty pages in file holes may be released before flushed to the disk, then file holes will contain some non-zero data, this will cause sparse file md5sum error. To reproduce the bug, find a big sparse file with many holes, like vm image file, its actual size should be bigger than available mem size to make writeback work more frequently, tar it with -S option, then keep untar it and check its md5sum again and again until you get a wrong md5sum. Signed-off-by: Junxiao Bi Cc: Younger Liu Reviewed-by: Mark Fasheh Cc: Joel Becker Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 9148353..8450262bc 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -716,7 +716,8 @@ leave: * While a write will already be ordering the data, a truncate will not. * Thus, we need to explicitly order the zeroed pages. */ -static handle_t *ocfs2_zero_start_ordered_transaction(struct inode *inode) +static handle_t *ocfs2_zero_start_ordered_transaction(struct inode *inode, + struct buffer_head *di_bh) { struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); handle_t *handle = NULL; @@ -733,7 +734,14 @@ static handle_t *ocfs2_zero_start_ordered_transaction(struct inode *inode) } ret = ocfs2_jbd2_file_inode(handle, inode); - if (ret < 0) + if (ret < 0) { + mlog_errno(ret); + goto out; + } + + ret = ocfs2_journal_access_di(handle, INODE_CACHE(inode), di_bh, + OCFS2_JOURNAL_ACCESS_WRITE); + if (ret) mlog_errno(ret); out: @@ -749,7 +757,7 @@ out: * to be too fragile to do exactly what we need without us having to * worry about recursive locking in ->write_begin() and ->write_end(). */ static int ocfs2_write_zero_page(struct inode *inode, u64 abs_from, - u64 abs_to) + u64 abs_to, struct buffer_head *di_bh) { struct address_space *mapping = inode->i_mapping; struct page *page; @@ -757,6 +765,7 @@ static int ocfs2_write_zero_page(struct inode *inode, u64 abs_from, handle_t *handle = NULL; int ret = 0; unsigned zero_from, zero_to, block_start, block_end; + struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data; BUG_ON(abs_from >= abs_to); BUG_ON(abs_to > (((u64)index + 1) << PAGE_CACHE_SHIFT)); @@ -799,7 +808,8 @@ static int ocfs2_write_zero_page(struct inode *inode, u64 abs_from, } if (!handle) { - handle = ocfs2_zero_start_ordered_transaction(inode); + handle = ocfs2_zero_start_ordered_transaction(inode, + di_bh); if (IS_ERR(handle)) { ret = PTR_ERR(handle); handle = NULL; @@ -816,8 +826,22 @@ static int ocfs2_write_zero_page(struct inode *inode, u64 abs_from, ret = 0; } - if (handle) + if (handle) { + /* + * fs-writeback will release the dirty pages without page lock + * whose offset are over inode size, the release happens at + * block_write_full_page_endio(). + */ + i_size_write(inode, abs_to); + inode->i_blocks = ocfs2_inode_sector_count(inode); + di->i_size = cpu_to_le64((u64)i_size_read(inode)); + inode->i_mtime = inode->i_ctime = CURRENT_TIME; + di->i_mtime = di->i_ctime = cpu_to_le64(inode->i_mtime.tv_sec); + di->i_ctime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec); + di->i_mtime_nsec = di->i_ctime_nsec; + ocfs2_journal_dirty(handle, di_bh); ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle); + } out_unlock: unlock_page(page); @@ -913,7 +937,7 @@ out: * has made sure that the entire range needs zeroing. */ static int ocfs2_zero_extend_range(struct inode *inode, u64 range_start, - u64 range_end) + u64 range_end, struct buffer_head *di_bh) { int rc = 0; u64 next_pos; @@ -929,7 +953,7 @@ static int ocfs2_zero_extend_range(struct inode *inode, u64 range_start, next_pos = (zero_pos & PAGE_CACHE_MASK) + PAGE_CACHE_SIZE; if (next_pos > range_end) next_pos = range_end; - rc = ocfs2_write_zero_page(inode, zero_pos, next_pos); + rc = ocfs2_write_zero_page(inode, zero_pos, next_pos, di_bh); if (rc < 0) { mlog_errno(rc); break; @@ -975,7 +999,7 @@ int ocfs2_zero_extend(struct inode *inode, struct buffer_head *di_bh, range_end = zero_to_size; ret = ocfs2_zero_extend_range(inode, range_start, - range_end); + range_end, di_bh); if (ret) { mlog_errno(ret); break; -- cgit v0.10.2 From 0e048316ff577e12c748e2d0a2e4f0f7b006654d Mon Sep 17 00:00:00 2001 From: Xue jiufei Date: Mon, 10 Feb 2014 14:25:54 -0800 Subject: ocfs2: check existence of old dentry in ocfs2_link() System call linkat first calls user_path_at(), check the existence of old dentry, and then calls vfs_link()->ocfs2_link() to do the actual work. There may exist a race when Node A create a hard link for file while node B rm it. Node A Node B user_path_at() ->ocfs2_lookup(), find old dentry exist rm file, add inode say inodeA to orphan_dir call ocfs2_link(),create a hard link for inodeA. rm the link, add inodeA to orphan_dir again When orphan_scan work start, it calls ocfs2_queue_orphans() to do the main work. It first tranverses entrys in orphan_dir, linking all inodes in this orphan_dir to a list look like this: inodeA->inodeB->...->inodeA When tranvering this list, it will fall into loop, calling iput() again and again. And finally trigger BUG_ON(inode->i_state & I_CLEAR). Signed-off-by: joyce Reviewed-by: Mark Fasheh Cc: Joel Becker Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index f4d609b..3683643 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c @@ -664,6 +664,7 @@ static int ocfs2_link(struct dentry *old_dentry, struct ocfs2_super *osb = OCFS2_SB(dir->i_sb); struct ocfs2_dir_lookup_result lookup = { NULL, }; sigset_t oldset; + u64 old_de_ino; trace_ocfs2_link((unsigned long long)OCFS2_I(inode)->ip_blkno, old_dentry->d_name.len, old_dentry->d_name.name, @@ -686,6 +687,22 @@ static int ocfs2_link(struct dentry *old_dentry, goto out; } + err = ocfs2_lookup_ino_from_name(dir, old_dentry->d_name.name, + old_dentry->d_name.len, &old_de_ino); + if (err) { + err = -ENOENT; + goto out; + } + + /* + * Check whether another node removed the source inode while we + * were in the vfs. + */ + if (old_de_ino != OCFS2_I(inode)->ip_blkno) { + err = -ENOENT; + goto out; + } + err = ocfs2_check_dir_for_entry(dir, dentry->d_name.name, dentry->d_name.len); if (err) -- cgit v0.10.2 From 0215b4aa069b989c963d594cf0f1c705e21d8ca5 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Fri, 7 Feb 2014 14:50:58 -0500 Subject: powerpc: Fix build failure in sysdev/mpic.c for MPIC_WEIRD=y Commit 446f6d06fab0b49c61887ecbe8286d6aaa796637 ("powerpc/mpic: Properly set default triggers") breaks the mpc7447_hpc_defconfig as follows: CC arch/powerpc/sysdev/mpic.o arch/powerpc/sysdev/mpic.c: In function 'mpic_set_irq_type': arch/powerpc/sysdev/mpic.c:886:9: error: case label does not reduce to an integer constant arch/powerpc/sysdev/mpic.c:890:9: error: case label does not reduce to an integer constant arch/powerpc/sysdev/mpic.c:894:9: error: case label does not reduce to an integer constant arch/powerpc/sysdev/mpic.c:898:9: error: case label does not reduce to an integer constant Looking at the cpp output (gcc 4.7.3), I see: case mpic->hw_set[MPIC_IDX_VECPRI_SENSE_EDGE] | mpic->hw_set[MPIC_IDX_VECPRI_POLARITY_POSITIVE]: The pointer into an array appears because CONFIG_MPIC_WEIRD=y is set for this platform, thus enabling the following: ------------------- #ifdef CONFIG_MPIC_WEIRD static u32 mpic_infos[][MPIC_IDX_END] = { [0] = { /* Original OpenPIC compatible MPIC */ [...] #define MPIC_INFO(name) mpic->hw_set[MPIC_IDX_##name] #else /* CONFIG_MPIC_WEIRD */ #define MPIC_INFO(name) MPIC_##name #endif /* CONFIG_MPIC_WEIRD */ ------------------- Here we convert the case section to if/else if, and also add the equivalent of a default case to warn about unknown types. Boot tested on sbc8548, build tested on all defconfigs. Signed-off-by: Paul Gortmaker Signed-off-by: Benjamin Herrenschmidt diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 0e166ed..8209744 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c @@ -886,25 +886,25 @@ int mpic_set_irq_type(struct irq_data *d, unsigned int flow_type) /* Default: read HW settings */ if (flow_type == IRQ_TYPE_DEFAULT) { - switch(vold & (MPIC_INFO(VECPRI_POLARITY_MASK) | - MPIC_INFO(VECPRI_SENSE_MASK))) { - case MPIC_INFO(VECPRI_SENSE_EDGE) | - MPIC_INFO(VECPRI_POLARITY_POSITIVE): - flow_type = IRQ_TYPE_EDGE_RISING; - break; - case MPIC_INFO(VECPRI_SENSE_EDGE) | - MPIC_INFO(VECPRI_POLARITY_NEGATIVE): - flow_type = IRQ_TYPE_EDGE_FALLING; - break; - case MPIC_INFO(VECPRI_SENSE_LEVEL) | - MPIC_INFO(VECPRI_POLARITY_POSITIVE): - flow_type = IRQ_TYPE_LEVEL_HIGH; - break; - case MPIC_INFO(VECPRI_SENSE_LEVEL) | - MPIC_INFO(VECPRI_POLARITY_NEGATIVE): - flow_type = IRQ_TYPE_LEVEL_LOW; - break; - } + int vold_ps; + + vold_ps = vold & (MPIC_INFO(VECPRI_POLARITY_MASK) | + MPIC_INFO(VECPRI_SENSE_MASK)); + + if (vold_ps == (MPIC_INFO(VECPRI_SENSE_EDGE) | + MPIC_INFO(VECPRI_POLARITY_POSITIVE))) + flow_type = IRQ_TYPE_EDGE_RISING; + else if (vold_ps == (MPIC_INFO(VECPRI_SENSE_EDGE) | + MPIC_INFO(VECPRI_POLARITY_NEGATIVE))) + flow_type = IRQ_TYPE_EDGE_FALLING; + else if (vold_ps == (MPIC_INFO(VECPRI_SENSE_LEVEL) | + MPIC_INFO(VECPRI_POLARITY_POSITIVE))) + flow_type = IRQ_TYPE_LEVEL_HIGH; + else if (vold_ps == (MPIC_INFO(VECPRI_SENSE_LEVEL) | + MPIC_INFO(VECPRI_POLARITY_NEGATIVE))) + flow_type = IRQ_TYPE_LEVEL_LOW; + else + WARN_ONCE(1, "mpic: unknown IRQ type %d\n", vold); } /* Apply to irq desc */ -- cgit v0.10.2 From 8cc6b6cd8713457be80202fc4264f05d20bc5e1b Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo Date: Wed, 5 Feb 2014 16:20:45 -0200 Subject: powerpc/eeh: Drop taken reference to driver on eeh_rmv_device Commit f5c57710dd62dd06f176934a8b4b8accbf00f9f8 ("powerpc/eeh: Use partial hotplug for EEH unaware drivers") introduces eeh_rmv_device, which may grab a reference to a driver, but not release it. That prevents a driver from being removed after it has gone through EEH recovery. This patch drops the reference if it was taken. Signed-off-by: Thadeu Lima de Souza Cascardo Acked-by: Gavin Shan Signed-off-by: Benjamin Herrenschmidt diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c index 7bb30dc..fdc679d 100644 --- a/arch/powerpc/kernel/eeh_driver.c +++ b/arch/powerpc/kernel/eeh_driver.c @@ -362,9 +362,13 @@ static void *eeh_rmv_device(void *data, void *userdata) */ if (!dev || (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE)) return NULL; + driver = eeh_pcid_get(dev); - if (driver && driver->err_handler) - return NULL; + if (driver) { + eeh_pcid_put(dev); + if (driver->err_handler) + return NULL; + } /* Remove it from PCI subsystem */ pr_debug("EEH: Removing %s without EEH sensitive driver\n", -- cgit v0.10.2 From 3ec8b78fcc5aa7745026d8d85a4e9ab52c922765 Mon Sep 17 00:00:00 2001 From: Mahesh Salgaonkar Date: Fri, 31 Jan 2014 00:30:45 +0530 Subject: powerpc/pseries: Disable relocation on exception while going down during crash. Disable relocation on exception while going down even in kdump case. This is because we are about clear htab mappings while kexec-ing into kdump kernel and we may run into issues if we still have AIL ON. Signed-off-by: Mahesh Salgaonkar Signed-off-by: Benjamin Herrenschmidt diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 8e639d7..972df0ff 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -430,8 +430,7 @@ static void pSeries_machine_kexec(struct kimage *image) { long rc; - if (firmware_has_feature(FW_FEATURE_SET_MODE) && - (image->type != KEXEC_TYPE_CRASH)) { + if (firmware_has_feature(FW_FEATURE_SET_MODE)) { rc = pSeries_disable_reloc_on_exc(); if (rc != H_SUCCESS) pr_warning("Warning: Failed to disable relocation on " -- cgit v0.10.2 From 429d2e8342954d337abe370d957e78291032d867 Mon Sep 17 00:00:00 2001 From: Mahesh Salgaonkar Date: Fri, 31 Jan 2014 00:31:04 +0530 Subject: powerpc: Fix kdump hang issue on p8 with relocation on exception enabled. On p8 systems, with relocation on exception feature enabled we are seeing kdump kernel hang at interrupt vector 0xc*4400. The reason is, with this feature enabled, exception are raised with MMU (IR=DR=1) ON with the default offset of 0xc*4000. Since exception is raised in virtual mode it requires the vector region to be executable without which it fails to fetch and execute instruction at 0xc*4xxx. For default kernel since kernel is loaded at real 0, the htab mappings sets the entire kernel text region executable. But for relocatable kernel (e.g. kdump case) we only copy interrupt vectors down to real 0 and never marked that region as executable because in p7 and below we always get exception in real mode. This patch fixes this issue by marking htab mapping range as executable that overlaps with the interrupt vector region for relocatable kernel. Thanks to Ben who helped me to debug this issue and find the root cause. Signed-off-by: Mahesh Salgaonkar Signed-off-by: Benjamin Herrenschmidt diff --git a/arch/powerpc/include/asm/sections.h b/arch/powerpc/include/asm/sections.h index 4ee06fe..d0e784e 100644 --- a/arch/powerpc/include/asm/sections.h +++ b/arch/powerpc/include/asm/sections.h @@ -8,6 +8,7 @@ #ifdef __powerpc64__ +extern char __start_interrupts[]; extern char __end_interrupts[]; extern char __prom_init_toc_start[]; @@ -21,6 +22,17 @@ static inline int in_kernel_text(unsigned long addr) return 0; } +static inline int overlaps_interrupt_vector_text(unsigned long start, + unsigned long end) +{ + unsigned long real_start, real_end; + real_start = __start_interrupts - _stext; + real_end = __end_interrupts - _stext; + + return start < (unsigned long)__va(real_end) && + (unsigned long)__va(real_start) < end; +} + static inline int overlaps_kernel_text(unsigned long start, unsigned long end) { return start < (unsigned long)__init_end && diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index de68812..d766d6e 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c @@ -207,6 +207,20 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend, if (overlaps_kernel_text(vaddr, vaddr + step)) tprot &= ~HPTE_R_N; + /* + * If relocatable, check if it overlaps interrupt vectors that + * are copied down to real 0. For relocatable kernel + * (e.g. kdump case) we copy interrupt vectors down to real + * address 0. Mark that region as executable. This is + * because on p8 system with relocation on exception feature + * enabled, exceptions are raised with MMU (IR=DR=1) ON. Hence + * in order to execute the interrupt handlers in virtual + * mode the vector region need to be marked as executable. + */ + if ((PHYSICAL_START > MEMORY_START) && + overlaps_interrupt_vector_text(vaddr, vaddr + step)) + tprot &= ~HPTE_R_N; + hash = hpt_hash(vpn, shift, ssize); hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP); -- cgit v0.10.2 From 3b830c824a8b15bf032eafe09c48a09d2441f16d Mon Sep 17 00:00:00 2001 From: Laurent Dufour Date: Thu, 30 Jan 2014 16:58:42 +0100 Subject: powerpc/relocate fix relocate processing in LE mode Relocation's code is not working in little endian mode because the r_info field, which is a 64 bits value, should be read from the right offset. The current code is optimized to read the r_info field as a 32 bits value starting at the middle of the double word (offset 12). When running in LE mode, the read value is not correct since only the MSB is read. This patch removes this optimization which consist to deal with a 32 bits value instead of a 64 bits one. This way it works in big and little endian mode. Signed-off-by: Laurent Dufour Signed-off-by: Benjamin Herrenschmidt diff --git a/arch/powerpc/kernel/reloc_64.S b/arch/powerpc/kernel/reloc_64.S index b47a0e1..1482327 100644 --- a/arch/powerpc/kernel/reloc_64.S +++ b/arch/powerpc/kernel/reloc_64.S @@ -69,8 +69,8 @@ _GLOBAL(relocate) * R_PPC64_RELATIVE ones. */ mtctr r8 -5: lwz r0,12(9) /* ELF64_R_TYPE(reloc->r_info) */ - cmpwi r0,R_PPC64_RELATIVE +5: ld r0,8(9) /* ELF64_R_TYPE(reloc->r_info) */ + cmpdi r0,R_PPC64_RELATIVE bne 6f ld r6,0(r9) /* reloc->r_offset */ ld r0,16(r9) /* reloc->r_addend */ -- cgit v0.10.2 From 2fdd313f54eca8221125b7898e6a8393604b6fb6 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Fri, 24 Jan 2014 15:50:51 +1100 Subject: powerpc/perf: Add Power8 cache & TLB events Signed-off-by: Michael Ellerman Signed-off-by: Benjamin Herrenschmidt diff --git a/arch/powerpc/perf/power8-pmu.c b/arch/powerpc/perf/power8-pmu.c index a3f7abd..96cee20 100644 --- a/arch/powerpc/perf/power8-pmu.c +++ b/arch/powerpc/perf/power8-pmu.c @@ -25,6 +25,37 @@ #define PM_BRU_FIN 0x10068 #define PM_BR_MPRED_CMPL 0x400f6 +/* All L1 D cache load references counted at finish, gated by reject */ +#define PM_LD_REF_L1 0x100ee +/* Load Missed L1 */ +#define PM_LD_MISS_L1 0x3e054 +/* Store Missed L1 */ +#define PM_ST_MISS_L1 0x300f0 +/* L1 cache data prefetches */ +#define PM_L1_PREF 0x0d8b8 +/* Instruction fetches from L1 */ +#define PM_INST_FROM_L1 0x04080 +/* Demand iCache Miss */ +#define PM_L1_ICACHE_MISS 0x200fd +/* Instruction Demand sectors wriittent into IL1 */ +#define PM_L1_DEMAND_WRITE 0x0408c +/* Instruction prefetch written into IL1 */ +#define PM_IC_PREF_WRITE 0x0408e +/* The data cache was reloaded from local core's L3 due to a demand load */ +#define PM_DATA_FROM_L3 0x4c042 +/* Demand LD - L3 Miss (not L2 hit and not L3 hit) */ +#define PM_DATA_FROM_L3MISS 0x300fe +/* All successful D-side store dispatches for this thread */ +#define PM_L2_ST 0x17080 +/* All successful D-side store dispatches for this thread that were L2 Miss */ +#define PM_L2_ST_MISS 0x17082 +/* Total HW L3 prefetches(Load+store) */ +#define PM_L3_PREF_ALL 0x4e052 +/* Data PTEG reload */ +#define PM_DTLB_MISS 0x300fc +/* ITLB Reloaded */ +#define PM_ITLB_MISS 0x400fc + /* * Raw event encoding for POWER8: @@ -557,6 +588,8 @@ static int power8_generic_events[] = { [PERF_COUNT_HW_INSTRUCTIONS] = PM_INST_CMPL, [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = PM_BRU_FIN, [PERF_COUNT_HW_BRANCH_MISSES] = PM_BR_MPRED_CMPL, + [PERF_COUNT_HW_CACHE_REFERENCES] = PM_LD_REF_L1, + [PERF_COUNT_HW_CACHE_MISSES] = PM_LD_MISS_L1, }; static u64 power8_bhrb_filter_map(u64 branch_sample_type) @@ -596,6 +629,116 @@ static void power8_config_bhrb(u64 pmu_bhrb_filter) mtspr(SPRN_MMCRA, (mfspr(SPRN_MMCRA) | pmu_bhrb_filter)); } +#define C(x) PERF_COUNT_HW_CACHE_##x + +/* + * Table of generalized cache-related events. + * 0 means not supported, -1 means nonsensical, other values + * are event codes. + */ +static int power8_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = { + [ C(L1D) ] = { + [ C(OP_READ) ] = { + [ C(RESULT_ACCESS) ] = PM_LD_REF_L1, + [ C(RESULT_MISS) ] = PM_LD_MISS_L1, + }, + [ C(OP_WRITE) ] = { + [ C(RESULT_ACCESS) ] = 0, + [ C(RESULT_MISS) ] = PM_ST_MISS_L1, + }, + [ C(OP_PREFETCH) ] = { + [ C(RESULT_ACCESS) ] = PM_L1_PREF, + [ C(RESULT_MISS) ] = 0, + }, + }, + [ C(L1I) ] = { + [ C(OP_READ) ] = { + [ C(RESULT_ACCESS) ] = PM_INST_FROM_L1, + [ C(RESULT_MISS) ] = PM_L1_ICACHE_MISS, + }, + [ C(OP_WRITE) ] = { + [ C(RESULT_ACCESS) ] = PM_L1_DEMAND_WRITE, + [ C(RESULT_MISS) ] = -1, + }, + [ C(OP_PREFETCH) ] = { + [ C(RESULT_ACCESS) ] = PM_IC_PREF_WRITE, + [ C(RESULT_MISS) ] = 0, + }, + }, + [ C(LL) ] = { + [ C(OP_READ) ] = { + [ C(RESULT_ACCESS) ] = PM_DATA_FROM_L3, + [ C(RESULT_MISS) ] = PM_DATA_FROM_L3MISS, + }, + [ C(OP_WRITE) ] = { + [ C(RESULT_ACCESS) ] = PM_L2_ST, + [ C(RESULT_MISS) ] = PM_L2_ST_MISS, + }, + [ C(OP_PREFETCH) ] = { + [ C(RESULT_ACCESS) ] = PM_L3_PREF_ALL, + [ C(RESULT_MISS) ] = 0, + }, + }, + [ C(DTLB) ] = { + [ C(OP_READ) ] = { + [ C(RESULT_ACCESS) ] = 0, + [ C(RESULT_MISS) ] = PM_DTLB_MISS, + }, + [ C(OP_WRITE) ] = { + [ C(RESULT_ACCESS) ] = -1, + [ C(RESULT_MISS) ] = -1, + }, + [ C(OP_PREFETCH) ] = { + [ C(RESULT_ACCESS) ] = -1, + [ C(RESULT_MISS) ] = -1, + }, + }, + [ C(ITLB) ] = { + [ C(OP_READ) ] = { + [ C(RESULT_ACCESS) ] = 0, + [ C(RESULT_MISS) ] = PM_ITLB_MISS, + }, + [ C(OP_WRITE) ] = { + [ C(RESULT_ACCESS) ] = -1, + [ C(RESULT_MISS) ] = -1, + }, + [ C(OP_PREFETCH) ] = { + [ C(RESULT_ACCESS) ] = -1, + [ C(RESULT_MISS) ] = -1, + }, + }, + [ C(BPU) ] = { + [ C(OP_READ) ] = { + [ C(RESULT_ACCESS) ] = PM_BRU_FIN, + [ C(RESULT_MISS) ] = PM_BR_MPRED_CMPL, + }, + [ C(OP_WRITE) ] = { + [ C(RESULT_ACCESS) ] = -1, + [ C(RESULT_MISS) ] = -1, + }, + [ C(OP_PREFETCH) ] = { + [ C(RESULT_ACCESS) ] = -1, + [ C(RESULT_MISS) ] = -1, + }, + }, + [ C(NODE) ] = { + [ C(OP_READ) ] = { + [ C(RESULT_ACCESS) ] = -1, + [ C(RESULT_MISS) ] = -1, + }, + [ C(OP_WRITE) ] = { + [ C(RESULT_ACCESS) ] = -1, + [ C(RESULT_MISS) ] = -1, + }, + [ C(OP_PREFETCH) ] = { + [ C(RESULT_ACCESS) ] = -1, + [ C(RESULT_MISS) ] = -1, + }, + }, +}; + +#undef C + static struct power_pmu power8_pmu = { .name = "POWER8", .n_counter = 6, @@ -611,6 +754,7 @@ static struct power_pmu power8_pmu = { .flags = PPMU_HAS_SSLOT | PPMU_HAS_SIER | PPMU_BHRB | PPMU_EBB, .n_generic = ARRAY_SIZE(power8_generic_events), .generic_events = power8_generic_events, + .cache_events = &power8_cache_events, .attr_groups = power8_pmu_attr_groups, .bhrb_nr = 32, }; -- cgit v0.10.2 From 8d4887ee30695d6b092e96029ae974505c43bfb6 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 10 Dec 2013 14:02:49 +1100 Subject: powerpc/pseries: Select ARCH_RANDOM on pseries We have a driver for the ARCH_RANDOM hook in rng.c, so we should select ARCH_RANDOM on pseries. Without this the build breaks if you turn ARCH_RANDOM off. This hasn't broken the build because pseries_defconfig doesn't specify a value for PPC_POWERNV, which is default y, and selects ARCH_RANDOM. Signed-off-by: Michael Ellerman Signed-off-by: Benjamin Herrenschmidt diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig index 37300f6..80b1d57 100644 --- a/arch/powerpc/platforms/pseries/Kconfig +++ b/arch/powerpc/platforms/pseries/Kconfig @@ -20,6 +20,7 @@ config PPC_PSERIES select PPC_DOORBELL select HAVE_CONTEXT_TRACKING select HOTPLUG_CPU if SMP + select ARCH_RANDOM default y config PPC_SPLPAR -- cgit v0.10.2 From 0ba3e1011660042dd3ea08ae8dbdc173352f3d47 Mon Sep 17 00:00:00 2001 From: Nathan Fontenot Date: Wed, 29 Jan 2014 10:34:56 -0600 Subject: crypto/nx/nx-842: Fix handling of vmalloc addresses The powerpc specific nx-842 compression driver does not currently handle translating a vmalloc address to a physical address. The current driver uses __pa() for all addresses which does not properly handle vmalloc addresses and thus causes a failure since we do not pass a proper physical address to the hypervisor. This patch adds a routine to convert an address to a physical address by checking for vmalloc addresses and handling them properly. Signed-off-by: Nathan Fontenot --- drivers/crypto/nx/nx-842.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) Signed-off-by: Benjamin Herrenschmidt diff --git a/drivers/crypto/nx/nx-842.c b/drivers/crypto/nx/nx-842.c index 6c4c000..1e5481d 100644 --- a/drivers/crypto/nx/nx-842.c +++ b/drivers/crypto/nx/nx-842.c @@ -158,6 +158,15 @@ static inline unsigned long nx842_get_scatterlist_size( return sl->entry_nr * sizeof(struct nx842_slentry); } +static inline unsigned long nx842_get_pa(void *addr) +{ + if (is_vmalloc_addr(addr)) + return page_to_phys(vmalloc_to_page(addr)) + + offset_in_page(addr); + else + return __pa(addr); +} + static int nx842_build_scatterlist(unsigned long buf, int len, struct nx842_scatterlist *sl) { @@ -168,7 +177,7 @@ static int nx842_build_scatterlist(unsigned long buf, int len, entry = sl->entries; while (len) { - entry->ptr = __pa(buf); + entry->ptr = nx842_get_pa((void *)buf); nextpage = ALIGN(buf + 1, NX842_HW_PAGE_SIZE); if (nextpage < buf + len) { /* we aren't at the end yet */ @@ -370,8 +379,8 @@ int nx842_compress(const unsigned char *in, unsigned int inlen, op.flags = NX842_OP_COMPRESS; csbcpb = &workmem->csbcpb; memset(csbcpb, 0, sizeof(*csbcpb)); - op.csbcpb = __pa(csbcpb); - op.out = __pa(slout.entries); + op.csbcpb = nx842_get_pa(csbcpb); + op.out = nx842_get_pa(slout.entries); for (i = 0; i < hdr->blocks_nr; i++) { /* @@ -401,13 +410,13 @@ int nx842_compress(const unsigned char *in, unsigned int inlen, */ if (likely(max_sync_size == NX842_HW_PAGE_SIZE)) { /* Create direct DDE */ - op.in = __pa(inbuf); + op.in = nx842_get_pa((void *)inbuf); op.inlen = max_sync_size; } else { /* Create indirect DDE (scatterlist) */ nx842_build_scatterlist(inbuf, max_sync_size, &slin); - op.in = __pa(slin.entries); + op.in = nx842_get_pa(slin.entries); op.inlen = -nx842_get_scatterlist_size(&slin); } @@ -565,7 +574,7 @@ int nx842_decompress(const unsigned char *in, unsigned int inlen, op.flags = NX842_OP_DECOMPRESS; csbcpb = &workmem->csbcpb; memset(csbcpb, 0, sizeof(*csbcpb)); - op.csbcpb = __pa(csbcpb); + op.csbcpb = nx842_get_pa(csbcpb); /* * max_sync_size may have changed since compression, @@ -597,12 +606,12 @@ int nx842_decompress(const unsigned char *in, unsigned int inlen, if (likely((inbuf & NX842_HW_PAGE_MASK) == ((inbuf + hdr->sizes[i] - 1) & NX842_HW_PAGE_MASK))) { /* Create direct DDE */ - op.in = __pa(inbuf); + op.in = nx842_get_pa((void *)inbuf); op.inlen = hdr->sizes[i]; } else { /* Create indirect DDE (scatterlist) */ nx842_build_scatterlist(inbuf, hdr->sizes[i] , &slin); - op.in = __pa(slin.entries); + op.in = nx842_get_pa(slin.entries); op.inlen = -nx842_get_scatterlist_size(&slin); } @@ -613,12 +622,12 @@ int nx842_decompress(const unsigned char *in, unsigned int inlen, */ if (likely(max_sync_size == NX842_HW_PAGE_SIZE)) { /* Create direct DDE */ - op.out = __pa(outbuf); + op.out = nx842_get_pa((void *)outbuf); op.outlen = max_sync_size; } else { /* Create indirect DDE (scatterlist) */ nx842_build_scatterlist(outbuf, max_sync_size, &slout); - op.out = __pa(slout.entries); + op.out = nx842_get_pa(slout.entries); op.outlen = -nx842_get_scatterlist_size(&slout); } -- cgit v0.10.2 From b4d6c06c8de81517320a9964b0c26e096aeadd7b Mon Sep 17 00:00:00 2001 From: Anshuman Khandual Date: Wed, 18 Dec 2013 13:14:53 +1100 Subject: powerpc/perf: Configure BHRB filter before enabling PMU interrupts Right now the config_bhrb() PMU specific call happens after write_mmcr0(), which actually enables the PMU for event counting and interrupts. So there is a small window of time where the PMU and BHRB runs without the required HW branch filter (if any) enabled in BHRB. This can cause some of the branch samples to be collected through BHRB without any filter applied and hence affects the correctness of the results. This patch moves the BHRB config function call before enabling interrupts. Here are some data points captured via trace prints which depicts how we could get PMU interrupts with BHRB filter NOT enabled with a standard perf record command line (asking for branch record information as well). $ perf record -j any_call ls Before the patch:- ls-1962 [003] d... 2065.299590: .perf_event_interrupt: MMCRA: 40000000000 ls-1962 [003] d... 2065.299603: .perf_event_interrupt: MMCRA: 40000000000 ... All the PMU interrupts before this point did not have the requested HW branch filter enabled in the MMCRA. ls-1962 [003] d... 2065.299647: .perf_event_interrupt: MMCRA: 40040000000 ls-1962 [003] d... 2065.299662: .perf_event_interrupt: MMCRA: 40040000000 After the patch:- ls-1850 [008] d... 190.311828: .perf_event_interrupt: MMCRA: 40040000000 ls-1850 [008] d... 190.311848: .perf_event_interrupt: MMCRA: 40040000000 All the PMU interrupts have the requested HW BHRB branch filter enabled in MMCRA. Signed-off-by: Anshuman Khandual [mpe: Fixed up whitespace and cleaned up changelog] Signed-off-by: Michael Ellerman Signed-off-by: Benjamin Herrenschmidt diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c index 29b89e8..67cf220 100644 --- a/arch/powerpc/perf/core-book3s.c +++ b/arch/powerpc/perf/core-book3s.c @@ -1147,6 +1147,9 @@ static void power_pmu_enable(struct pmu *pmu) mmcr0 = ebb_switch_in(ebb, cpuhw->mmcr[0]); mb(); + if (cpuhw->bhrb_users) + ppmu->config_bhrb(cpuhw->bhrb_filter); + write_mmcr0(cpuhw, mmcr0); /* @@ -1158,8 +1161,6 @@ static void power_pmu_enable(struct pmu *pmu) } out: - if (cpuhw->bhrb_users) - ppmu->config_bhrb(cpuhw->bhrb_filter); local_irq_restore(flags); } -- cgit v0.10.2 From 730efb6193f8568354fd80849612291afa9fa81e Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Mon, 23 Dec 2013 23:46:04 +1100 Subject: powerpc/xmon: Don't loop forever in get_output_lock() If we enter with xmon_speaker != 0 we skip the first cmpxchg(), we also skip the while loop because xmon_speaker != last_speaker (0) - meaning we skip the second cmpxchg() also. Following that code path the compiler sees no memory barriers and so is within its rights to never reload xmon_speaker. The end result is we loop forever. This manifests as all cpus being in xmon ('c' command), but they refuse to take control when you switch to them ('c x' for cpu # x). I have seen this deadlock in practice and also checked the generated code to confirm this is what's happening. The simplest fix is just to always try the cmpxchg(). Signed-off-by: Michael Ellerman Signed-off-by: Benjamin Herrenschmidt diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index a90731b..598cdc7 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c @@ -309,12 +309,12 @@ static void get_output_lock(void) if (xmon_speaker == me) return; + for (;;) { - if (xmon_speaker == 0) { - last_speaker = cmpxchg(&xmon_speaker, 0, me); - if (last_speaker == 0) - return; - } + last_speaker = cmpxchg(&xmon_speaker, 0, me); + if (last_speaker == 0) + return; + timeout = 10000000; while (xmon_speaker == last_speaker) { if (--timeout > 0) -- cgit v0.10.2 From 1507589787529b0d8e2a9e66e0c6f113ecab5181 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Mon, 23 Dec 2013 23:46:05 +1100 Subject: powerpc/xmon: Fix timeout loop in get_output_lock() As far as I can tell, our 70s era timeout loop in get_output_lock() is generating no code. This leads to the hostile takeover happening more or less simultaneously on all cpus. The result is "interesting", some example output that is more readable than most: cpu 0x1: Vector: 100 (Scypsut e0mx bR:e setV)e catto xc0p:u[ c 00 c0:0 000t0o0V0erc0td:o5 rfc28050000]0c00 0 0 0 6t(pSrycsV1ppuot uxe 1m 2 0Rx21e3:0s0ce000c00000t00)00 60602oV2SerucSayt0y 0p 1sxs Fix it by using udelay() in the timeout loop. The wait time and check frequency are arbitrary, but seem to work OK. We already rely on udelay() working so this is not a new dependency. Signed-off-by: Michael Ellerman Signed-off-by: Benjamin Herrenschmidt diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index 598cdc7..d712b23 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c @@ -315,10 +315,17 @@ static void get_output_lock(void) if (last_speaker == 0) return; - timeout = 10000000; + /* + * Wait a full second for the lock, we might be on a slow + * console, but check every 100us. + */ + timeout = 10000; while (xmon_speaker == last_speaker) { - if (--timeout > 0) + if (--timeout > 0) { + udelay(100); continue; + } + /* hostile takeover */ prev = cmpxchg(&xmon_speaker, last_speaker, me); if (prev == last_speaker) -- cgit v0.10.2 From d2b496e5e1fa7a6796534e435440eb9d3ed184dd Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Mon, 23 Dec 2013 23:46:06 +1100 Subject: powerpc/xmon: Don't signal we've entered until we're finished printing Currently we set our cpu's bit in cpus_in_xmon, and then we take the output lock and print the exception information. This can race with the master cpu entering the command loop and printing the backtrace. The result is that the backtrace gets garbled with another cpu's exception print out. Fix it by delaying the set of cpus_in_xmon until we are finished printing. Signed-off-by: Michael Ellerman Signed-off-by: Benjamin Herrenschmidt diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index d712b23..b079098 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c @@ -404,7 +404,6 @@ static int xmon_core(struct pt_regs *regs, int fromipi) } xmon_fault_jmp[cpu] = recurse_jmp; - cpumask_set_cpu(cpu, &cpus_in_xmon); bp = NULL; if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) == (MSR_IR|MSR_64BIT)) @@ -426,6 +425,8 @@ static int xmon_core(struct pt_regs *regs, int fromipi) release_output_lock(); } + cpumask_set_cpu(cpu, &cpus_in_xmon); + waiting: secondary = 1; while (secondary && !xmon_gate) { -- cgit v0.10.2 From 04a341138da55daf47551308660a5fcc6b5b9077 Mon Sep 17 00:00:00 2001 From: Kevin Hao Date: Wed, 29 Jan 2014 18:24:54 +0800 Subject: powerpc/ppc32: Fix the bug in the init of non-base exception stack for UP We would allocate one specific exception stack for each kind of non-base exceptions for every CPU. For ppc32 the CPU hard ID is used as the subscript to get the specific exception stack for one CPU. But for an UP kernel, there is only one element in the each kind of exception stack array. We would get stuck if the CPU hard ID is not equal to '0'. So in this case we should use the subscript '0' no matter what the CPU hard ID is. Signed-off-by: Kevin Hao Signed-off-by: Benjamin Herrenschmidt diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 9729b23..1d0848b 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -559,8 +559,13 @@ void exc_lvl_ctx_init(void) #ifdef CONFIG_PPC64 cpu_nr = i; #else +#ifdef CONFIG_SMP cpu_nr = get_hard_smp_processor_id(i); +#else + cpu_nr = 0; #endif +#endif + memset((void *)critirq_ctx[cpu_nr], 0, THREAD_SIZE); tp = critirq_ctx[cpu_nr]; tp->cpu = cpu_nr; diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index 2b0da27..04cc4fc 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c @@ -247,7 +247,12 @@ static void __init exc_lvl_early_init(void) /* interrupt stacks must be in lowmem, we get that for free on ppc32 * as the memblock is limited to lowmem by MEMBLOCK_REAL_LIMIT */ for_each_possible_cpu(i) { +#ifdef CONFIG_SMP hw_cpu = get_hard_smp_processor_id(i); +#else + hw_cpu = 0; +#endif + critirq_ctx[hw_cpu] = (struct thread_info *) __va(memblock_alloc(THREAD_SIZE, THREAD_SIZE)); #ifdef CONFIG_BOOKE -- cgit v0.10.2 From ea961a828fe7250e954f086d74d9323c3d44c3e4 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Wed, 22 Jan 2014 08:40:28 +1100 Subject: powerpc: Fix endian issues in kexec and crash dump code We expose a number of OF properties in the kexec and crash dump code and these need to be big endian. Cc: stable@vger.kernel.org # v3.13 Signed-off-by: Anton Blanchard Signed-off-by: Benjamin Herrenschmidt diff --git a/arch/powerpc/kernel/machine_kexec.c b/arch/powerpc/kernel/machine_kexec.c index 75d4f73..015ae55 100644 --- a/arch/powerpc/kernel/machine_kexec.c +++ b/arch/powerpc/kernel/machine_kexec.c @@ -196,7 +196,9 @@ int overlaps_crashkernel(unsigned long start, unsigned long size) /* Values we need to export to the second kernel via the device tree. */ static phys_addr_t kernel_end; +static phys_addr_t crashk_base; static phys_addr_t crashk_size; +static unsigned long long mem_limit; static struct property kernel_end_prop = { .name = "linux,kernel-end", @@ -207,7 +209,7 @@ static struct property kernel_end_prop = { static struct property crashk_base_prop = { .name = "linux,crashkernel-base", .length = sizeof(phys_addr_t), - .value = &crashk_res.start, + .value = &crashk_base }; static struct property crashk_size_prop = { @@ -219,9 +221,11 @@ static struct property crashk_size_prop = { static struct property memory_limit_prop = { .name = "linux,memory-limit", .length = sizeof(unsigned long long), - .value = &memory_limit, + .value = &mem_limit, }; +#define cpu_to_be_ulong __PASTE(cpu_to_be, BITS_PER_LONG) + static void __init export_crashk_values(struct device_node *node) { struct property *prop; @@ -237,8 +241,9 @@ static void __init export_crashk_values(struct device_node *node) of_remove_property(node, prop); if (crashk_res.start != 0) { + crashk_base = cpu_to_be_ulong(crashk_res.start), of_add_property(node, &crashk_base_prop); - crashk_size = resource_size(&crashk_res); + crashk_size = cpu_to_be_ulong(resource_size(&crashk_res)); of_add_property(node, &crashk_size_prop); } @@ -246,6 +251,7 @@ static void __init export_crashk_values(struct device_node *node) * memory_limit is required by the kexec-tools to limit the * crash regions to the actual memory used. */ + mem_limit = cpu_to_be_ulong(memory_limit); of_update_property(node, &memory_limit_prop); } @@ -264,7 +270,7 @@ static int __init kexec_setup(void) of_remove_property(node, prop); /* information needed by userspace when using default_machine_kexec */ - kernel_end = __pa(_end); + kernel_end = cpu_to_be_ulong(__pa(_end)); of_add_property(node, &kernel_end_prop); export_crashk_values(node); diff --git a/arch/powerpc/kernel/machine_kexec_64.c b/arch/powerpc/kernel/machine_kexec_64.c index be4e6d6..59d229a 100644 --- a/arch/powerpc/kernel/machine_kexec_64.c +++ b/arch/powerpc/kernel/machine_kexec_64.c @@ -369,6 +369,7 @@ void default_machine_kexec(struct kimage *image) /* Values we need to export to the second kernel via the device tree. */ static unsigned long htab_base; +static unsigned long htab_size; static struct property htab_base_prop = { .name = "linux,htab-base", @@ -379,7 +380,7 @@ static struct property htab_base_prop = { static struct property htab_size_prop = { .name = "linux,htab-size", .length = sizeof(unsigned long), - .value = &htab_size_bytes, + .value = &htab_size, }; static int __init export_htab_values(void) @@ -403,8 +404,9 @@ static int __init export_htab_values(void) if (prop) of_remove_property(node, prop); - htab_base = __pa(htab_address); + htab_base = cpu_to_be64(__pa(htab_address)); of_add_property(node, &htab_base_prop); + htab_size = cpu_to_be64(htab_size_bytes); of_add_property(node, &htab_size_prop); of_node_put(node); -- cgit v0.10.2 From 19a38d8e0aa33b4f4d11d3b4baa902ad169daa80 Mon Sep 17 00:00:00 2001 From: Liu Junliang Date: Mon, 10 Feb 2014 14:31:42 +0800 Subject: USB2NET : SR9800 : One chip USB2.0 USB2NET SR9800 Device Driver Support Signed-off-by: Liu Junliang Signed-off-by: David S. Miller diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig index 6b638a0..409499f 100644 --- a/drivers/net/usb/Kconfig +++ b/drivers/net/usb/Kconfig @@ -292,6 +292,22 @@ config USB_NET_SR9700 This option adds support for CoreChip-sz SR9700 based USB 1.1 10/100 Ethernet adapters. +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. + + This driver makes the adapter appear as a normal Ethernet interface, + typically on eth0, if it is the only ethernet device, or perhaps on + eth1, if you have a PCI or ISA ethernet card installed. + + To compile this driver as a module, choose M here: the + module will be called sr9800. + config USB_NET_SMSC75XX tristate "SMSC LAN75XX based USB 2.0 gigabit ethernet devices" depends on USB_USBNET diff --git a/drivers/net/usb/Makefile b/drivers/net/usb/Makefile index b17b5e8..433f0a0 100644 --- a/drivers/net/usb/Makefile +++ b/drivers/net/usb/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o r815x.o obj-$(CONFIG_USB_NET_CDC_EEM) += cdc_eem.o obj-$(CONFIG_USB_NET_DM9601) += dm9601.o obj-$(CONFIG_USB_NET_SR9700) += sr9700.o +obj-$(CONFIG_USB_NET_SR9800) += sr9800.o obj-$(CONFIG_USB_NET_SMSC75XX) += smsc75xx.o obj-$(CONFIG_USB_NET_SMSC95XX) += smsc95xx.o obj-$(CONFIG_USB_NET_GL620A) += gl620a.o diff --git a/drivers/net/usb/sr9800.c b/drivers/net/usb/sr9800.c new file mode 100644 index 0000000..4175eb9 --- /dev/null +++ b/drivers/net/usb/sr9800.c @@ -0,0 +1,870 @@ +/* CoreChip-sz SR9800 one chip USB 2.0 Ethernet Devices + * + * Author : Liu Junliang + * + * Based on asix_common.c, asix_devices.c + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied.* + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sr9800.h" + +static int sr_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, + u16 size, void *data) +{ + int err; + + err = usbnet_read_cmd(dev, cmd, SR_REQ_RD_REG, value, index, + data, size); + if ((err != size) && (err >= 0)) + err = -EINVAL; + + return err; +} + +static int sr_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, + u16 size, void *data) +{ + int err; + + err = usbnet_write_cmd(dev, cmd, SR_REQ_WR_REG, value, index, + data, size); + if ((err != size) && (err >= 0)) + err = -EINVAL; + + return err; +} + +static void +sr_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index, + u16 size, void *data) +{ + usbnet_write_cmd_async(dev, cmd, SR_REQ_WR_REG, value, index, data, + size); +} + +static int sr_rx_fixup(struct usbnet *dev, struct sk_buff *skb) +{ + int offset = 0; + + while (offset + sizeof(u32) < skb->len) { + struct sk_buff *sr_skb; + u16 size; + u32 header = get_unaligned_le32(skb->data + offset); + + offset += sizeof(u32); + /* get the packet length */ + size = (u16) (header & 0x7ff); + if (size != ((~header >> 16) & 0x07ff)) { + netdev_err(dev->net, "%s : Bad Header Length\n", + __func__); + return 0; + } + + if ((size > dev->net->mtu + ETH_HLEN + VLAN_HLEN) || + (size + offset > skb->len)) { + netdev_err(dev->net, "%s : Bad RX Length %d\n", + __func__, size); + return 0; + } + sr_skb = netdev_alloc_skb_ip_align(dev->net, size); + if (!sr_skb) + return 0; + + skb_put(sr_skb, size); + memcpy(sr_skb->data, skb->data + offset, size); + usbnet_skb_return(dev, sr_skb); + + offset += (size + 1) & 0xfffe; + } + + if (skb->len != offset) { + netdev_err(dev->net, "%s : Bad SKB Length %d\n", __func__, + skb->len); + return 0; + } + + return 1; +} + +static struct sk_buff *sr_tx_fixup(struct usbnet *dev, struct sk_buff *skb, + gfp_t flags) +{ + int headroom = skb_headroom(skb); + int tailroom = skb_tailroom(skb); + u32 padbytes = 0xffff0000; + u32 packet_len; + int padlen; + + padlen = ((skb->len + 4) % (dev->maxpacket - 1)) ? 0 : 4; + + if ((!skb_cloned(skb)) && ((headroom + tailroom) >= (4 + padlen))) { + if ((headroom < 4) || (tailroom < padlen)) { + skb->data = memmove(skb->head + 4, skb->data, + skb->len); + skb_set_tail_pointer(skb, skb->len); + } + } else { + struct sk_buff *skb2; + skb2 = skb_copy_expand(skb, 4, padlen, flags); + dev_kfree_skb_any(skb); + skb = skb2; + if (!skb) + return NULL; + } + + skb_push(skb, 4); + packet_len = (((skb->len - 4) ^ 0x0000ffff) << 16) + (skb->len - 4); + cpu_to_le32s(&packet_len); + skb_copy_to_linear_data(skb, &packet_len, sizeof(packet_len)); + + if (padlen) { + cpu_to_le32s(&padbytes); + memcpy(skb_tail_pointer(skb), &padbytes, sizeof(padbytes)); + skb_put(skb, sizeof(padbytes)); + } + + return skb; +} + +static void sr_status(struct usbnet *dev, struct urb *urb) +{ + struct sr9800_int_data *event; + int link; + + if (urb->actual_length < 8) + return; + + event = urb->transfer_buffer; + link = event->link & 0x01; + if (netif_carrier_ok(dev->net) != link) { + usbnet_link_change(dev, link, 1); + netdev_dbg(dev->net, "Link Status is: %d\n", link); + } + + return; +} + +static inline int sr_set_sw_mii(struct usbnet *dev) +{ + int ret; + + ret = sr_write_cmd(dev, SR_CMD_SET_SW_MII, 0x0000, 0, 0, NULL); + if (ret < 0) + netdev_err(dev->net, "Failed to enable software MII access\n"); + return ret; +} + +static inline int sr_set_hw_mii(struct usbnet *dev) +{ + int ret; + + ret = sr_write_cmd(dev, SR_CMD_SET_HW_MII, 0x0000, 0, 0, NULL); + if (ret < 0) + netdev_err(dev->net, "Failed to enable hardware MII access\n"); + return ret; +} + +static inline int sr_get_phy_addr(struct usbnet *dev) +{ + u8 buf[2]; + int ret; + + ret = sr_read_cmd(dev, SR_CMD_READ_PHY_ID, 0, 0, 2, buf); + if (ret < 0) { + netdev_err(dev->net, "%s : Error reading PHYID register:%02x\n", + __func__, ret); + goto out; + } + netdev_dbg(dev->net, "%s : returning 0x%04x\n", __func__, + *((__le16 *)buf)); + + ret = buf[1]; + +out: + return ret; +} + +static int sr_sw_reset(struct usbnet *dev, u8 flags) +{ + int ret; + + ret = sr_write_cmd(dev, SR_CMD_SW_RESET, flags, 0, 0, NULL); + if (ret < 0) + netdev_err(dev->net, "Failed to send software reset:%02x\n", + ret); + + return ret; +} + +static u16 sr_read_rx_ctl(struct usbnet *dev) +{ + __le16 v; + int ret; + + ret = sr_read_cmd(dev, SR_CMD_READ_RX_CTL, 0, 0, 2, &v); + if (ret < 0) { + netdev_err(dev->net, "Error reading RX_CTL register:%02x\n", + ret); + goto out; + } + + ret = le16_to_cpu(v); +out: + return ret; +} + +static int sr_write_rx_ctl(struct usbnet *dev, u16 mode) +{ + int ret; + + netdev_dbg(dev->net, "%s : mode = 0x%04x\n", __func__, mode); + ret = sr_write_cmd(dev, SR_CMD_WRITE_RX_CTL, mode, 0, 0, NULL); + if (ret < 0) + netdev_err(dev->net, + "Failed to write RX_CTL mode to 0x%04x:%02x\n", + mode, ret); + + return ret; +} + +static u16 sr_read_medium_status(struct usbnet *dev) +{ + __le16 v; + int ret; + + ret = sr_read_cmd(dev, SR_CMD_READ_MEDIUM_STATUS, 0, 0, 2, &v); + if (ret < 0) { + netdev_err(dev->net, + "Error reading Medium Status register:%02x\n", ret); + return ret; /* TODO: callers not checking for error ret */ + } + + return le16_to_cpu(v); +} + +static int sr_write_medium_mode(struct usbnet *dev, u16 mode) +{ + int ret; + + netdev_dbg(dev->net, "%s : mode = 0x%04x\n", __func__, mode); + ret = sr_write_cmd(dev, SR_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL); + if (ret < 0) + netdev_err(dev->net, + "Failed to write Medium Mode mode to 0x%04x:%02x\n", + mode, ret); + return ret; +} + +static int sr_write_gpio(struct usbnet *dev, u16 value, int sleep) +{ + int ret; + + netdev_dbg(dev->net, "%s : value = 0x%04x\n", __func__, value); + ret = sr_write_cmd(dev, SR_CMD_WRITE_GPIOS, value, 0, 0, NULL); + if (ret < 0) + netdev_err(dev->net, "Failed to write GPIO value 0x%04x:%02x\n", + value, ret); + if (sleep) + msleep(sleep); + + return ret; +} + +/* SR9800 have a 16-bit RX_CTL value */ +static void sr_set_multicast(struct net_device *net) +{ + struct usbnet *dev = netdev_priv(net); + struct sr_data *data = (struct sr_data *)&dev->data; + u16 rx_ctl = SR_DEFAULT_RX_CTL; + + if (net->flags & IFF_PROMISC) { + rx_ctl |= SR_RX_CTL_PRO; + } else if (net->flags & IFF_ALLMULTI || + netdev_mc_count(net) > SR_MAX_MCAST) { + rx_ctl |= SR_RX_CTL_AMALL; + } else if (netdev_mc_empty(net)) { + /* just broadcast and directed */ + } else { + /* We use the 20 byte dev->data + * for our 8 byte filter buffer + * to avoid allocating memory that + * is tricky to free later + */ + struct netdev_hw_addr *ha; + u32 crc_bits; + + memset(data->multi_filter, 0, SR_MCAST_FILTER_SIZE); + + /* Build the multicast hash filter. */ + netdev_for_each_mc_addr(ha, net) { + crc_bits = ether_crc(ETH_ALEN, ha->addr) >> 26; + data->multi_filter[crc_bits >> 3] |= + 1 << (crc_bits & 7); + } + + sr_write_cmd_async(dev, SR_CMD_WRITE_MULTI_FILTER, 0, 0, + SR_MCAST_FILTER_SIZE, data->multi_filter); + + rx_ctl |= SR_RX_CTL_AM; + } + + sr_write_cmd_async(dev, SR_CMD_WRITE_RX_CTL, rx_ctl, 0, 0, NULL); +} + +static int sr_mdio_read(struct net_device *net, int phy_id, int loc) +{ + struct usbnet *dev = netdev_priv(net); + __le16 res; + + mutex_lock(&dev->phy_mutex); + sr_set_sw_mii(dev); + sr_read_cmd(dev, SR_CMD_READ_MII_REG, phy_id, (__u16)loc, 2, &res); + sr_set_hw_mii(dev); + mutex_unlock(&dev->phy_mutex); + + netdev_dbg(dev->net, + "%s : phy_id=0x%02x, loc=0x%02x, returns=0x%04x\n", __func__, + phy_id, loc, le16_to_cpu(res)); + + return le16_to_cpu(res); +} + +static void +sr_mdio_write(struct net_device *net, int phy_id, int loc, int val) +{ + struct usbnet *dev = netdev_priv(net); + __le16 res = cpu_to_le16(val); + + netdev_dbg(dev->net, + "%s : phy_id=0x%02x, loc=0x%02x, val=0x%04x\n", __func__, + phy_id, loc, val); + mutex_lock(&dev->phy_mutex); + sr_set_sw_mii(dev); + sr_write_cmd(dev, SR_CMD_WRITE_MII_REG, phy_id, (__u16)loc, 2, &res); + sr_set_hw_mii(dev); + mutex_unlock(&dev->phy_mutex); +} + +/* Get the PHY Identifier from the PHYSID1 & PHYSID2 MII registers */ +static u32 sr_get_phyid(struct usbnet *dev) +{ + int phy_reg; + u32 phy_id; + int i; + + /* Poll for the rare case the FW or phy isn't ready yet. */ + for (i = 0; i < 100; i++) { + phy_reg = sr_mdio_read(dev->net, dev->mii.phy_id, MII_PHYSID1); + if (phy_reg != 0 && phy_reg != 0xFFFF) + break; + mdelay(1); + } + + if (phy_reg <= 0 || phy_reg == 0xFFFF) + return 0; + + phy_id = (phy_reg & 0xffff) << 16; + + phy_reg = sr_mdio_read(dev->net, dev->mii.phy_id, MII_PHYSID2); + if (phy_reg < 0) + return 0; + + phy_id |= (phy_reg & 0xffff); + + return phy_id; +} + +static void +sr_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo) +{ + struct usbnet *dev = netdev_priv(net); + u8 opt; + + if (sr_read_cmd(dev, SR_CMD_READ_MONITOR_MODE, 0, 0, 1, &opt) < 0) { + wolinfo->supported = 0; + wolinfo->wolopts = 0; + return; + } + wolinfo->supported = WAKE_PHY | WAKE_MAGIC; + wolinfo->wolopts = 0; + if (opt & SR_MONITOR_LINK) + wolinfo->wolopts |= WAKE_PHY; + if (opt & SR_MONITOR_MAGIC) + wolinfo->wolopts |= WAKE_MAGIC; +} + +static int +sr_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo) +{ + struct usbnet *dev = netdev_priv(net); + u8 opt = 0; + + if (wolinfo->wolopts & WAKE_PHY) + opt |= SR_MONITOR_LINK; + if (wolinfo->wolopts & WAKE_MAGIC) + opt |= SR_MONITOR_MAGIC; + + if (sr_write_cmd(dev, SR_CMD_WRITE_MONITOR_MODE, + opt, 0, 0, NULL) < 0) + return -EINVAL; + + return 0; +} + +static int sr_get_eeprom_len(struct net_device *net) +{ + struct usbnet *dev = netdev_priv(net); + struct sr_data *data = (struct sr_data *)&dev->data; + + return data->eeprom_len; +} + +static int sr_get_eeprom(struct net_device *net, + struct ethtool_eeprom *eeprom, u8 *data) +{ + struct usbnet *dev = netdev_priv(net); + __le16 *ebuf = (__le16 *)data; + int ret; + int i; + + /* Crude hack to ensure that we don't overwrite memory + * if an odd length is supplied + */ + if (eeprom->len % 2) + return -EINVAL; + + eeprom->magic = SR_EEPROM_MAGIC; + + /* sr9800 returns 2 bytes from eeprom on read */ + for (i = 0; i < eeprom->len / 2; i++) { + ret = sr_read_cmd(dev, SR_CMD_READ_EEPROM, eeprom->offset + i, + 0, 2, &ebuf[i]); + if (ret < 0) + return -EINVAL; + } + return 0; +} + +static void sr_get_drvinfo(struct net_device *net, + struct ethtool_drvinfo *info) +{ + struct usbnet *dev = netdev_priv(net); + struct sr_data *data = (struct sr_data *)&dev->data; + + /* Inherit standard device info */ + usbnet_get_drvinfo(net, info); + strncpy(info->driver, DRIVER_NAME, sizeof(info->driver)); + strncpy(info->version, DRIVER_VERSION, sizeof(info->version)); + info->eedump_len = data->eeprom_len; +} + +static u32 sr_get_link(struct net_device *net) +{ + struct usbnet *dev = netdev_priv(net); + + return mii_link_ok(&dev->mii); +} + +static int sr_ioctl(struct net_device *net, struct ifreq *rq, int cmd) +{ + struct usbnet *dev = netdev_priv(net); + + return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL); +} + +static int sr_set_mac_address(struct net_device *net, void *p) +{ + struct usbnet *dev = netdev_priv(net); + struct sr_data *data = (struct sr_data *)&dev->data; + struct sockaddr *addr = p; + + if (netif_running(net)) + return -EBUSY; + if (!is_valid_ether_addr(addr->sa_data)) + return -EADDRNOTAVAIL; + + memcpy(net->dev_addr, addr->sa_data, ETH_ALEN); + + /* We use the 20 byte dev->data + * for our 6 byte mac buffer + * to avoid allocating memory that + * is tricky to free later + */ + memcpy(data->mac_addr, addr->sa_data, ETH_ALEN); + sr_write_cmd_async(dev, SR_CMD_WRITE_NODE_ID, 0, 0, ETH_ALEN, + data->mac_addr); + + return 0; +} + +static const struct ethtool_ops sr9800_ethtool_ops = { + .get_drvinfo = sr_get_drvinfo, + .get_link = sr_get_link, + .get_msglevel = usbnet_get_msglevel, + .set_msglevel = usbnet_set_msglevel, + .get_wol = sr_get_wol, + .set_wol = sr_set_wol, + .get_eeprom_len = sr_get_eeprom_len, + .get_eeprom = sr_get_eeprom, + .get_settings = usbnet_get_settings, + .set_settings = usbnet_set_settings, + .nway_reset = usbnet_nway_reset, +}; + +static int sr9800_link_reset(struct usbnet *dev) +{ + struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET }; + u16 mode; + + mii_check_media(&dev->mii, 1, 1); + mii_ethtool_gset(&dev->mii, &ecmd); + mode = SR9800_MEDIUM_DEFAULT; + + if (ethtool_cmd_speed(&ecmd) != SPEED_100) + mode &= ~SR_MEDIUM_PS; + + if (ecmd.duplex != DUPLEX_FULL) + mode &= ~SR_MEDIUM_FD; + + netdev_dbg(dev->net, "%s : speed: %u duplex: %d mode: 0x%04x\n", + __func__, ethtool_cmd_speed(&ecmd), ecmd.duplex, mode); + + sr_write_medium_mode(dev, mode); + + return 0; +} + + +static int sr9800_set_default_mode(struct usbnet *dev) +{ + u16 rx_ctl; + int ret; + + sr_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET); + sr_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE, + ADVERTISE_ALL | ADVERTISE_CSMA); + mii_nway_restart(&dev->mii); + + ret = sr_write_medium_mode(dev, SR9800_MEDIUM_DEFAULT); + if (ret < 0) + goto out; + + ret = sr_write_cmd(dev, SR_CMD_WRITE_IPG012, + SR9800_IPG0_DEFAULT | SR9800_IPG1_DEFAULT, + SR9800_IPG2_DEFAULT, 0, NULL); + if (ret < 0) { + netdev_dbg(dev->net, "Write IPG,IPG1,IPG2 failed: %d\n", ret); + goto out; + } + + /* Set RX_CTL to default values with 2k buffer, and enable cactus */ + ret = sr_write_rx_ctl(dev, SR_DEFAULT_RX_CTL); + if (ret < 0) + goto out; + + rx_ctl = sr_read_rx_ctl(dev); + netdev_dbg(dev->net, "RX_CTL is 0x%04x after all initializations\n", + rx_ctl); + + rx_ctl = sr_read_medium_status(dev); + netdev_dbg(dev->net, "Medium Status:0x%04x after all initializations\n", + rx_ctl); + + return 0; +out: + return ret; +} + +static int sr9800_reset(struct usbnet *dev) +{ + struct sr_data *data = (struct sr_data *)&dev->data; + int ret, embd_phy; + u16 rx_ctl; + + ret = sr_write_gpio(dev, + SR_GPIO_RSE | SR_GPIO_GPO_2 | SR_GPIO_GPO2EN, 5); + if (ret < 0) + goto out; + + embd_phy = ((sr_get_phy_addr(dev) & 0x1f) == 0x10 ? 1 : 0); + + ret = sr_write_cmd(dev, SR_CMD_SW_PHY_SELECT, embd_phy, 0, 0, NULL); + if (ret < 0) { + netdev_dbg(dev->net, "Select PHY #1 failed: %d\n", ret); + goto out; + } + + ret = sr_sw_reset(dev, SR_SWRESET_IPPD | SR_SWRESET_PRL); + if (ret < 0) + goto out; + + msleep(150); + + ret = sr_sw_reset(dev, SR_SWRESET_CLEAR); + if (ret < 0) + goto out; + + msleep(150); + + if (embd_phy) { + ret = sr_sw_reset(dev, SR_SWRESET_IPRL); + if (ret < 0) + goto out; + } else { + ret = sr_sw_reset(dev, SR_SWRESET_PRTE); + if (ret < 0) + goto out; + } + + msleep(150); + rx_ctl = sr_read_rx_ctl(dev); + netdev_dbg(dev->net, "RX_CTL is 0x%04x after software reset\n", rx_ctl); + ret = sr_write_rx_ctl(dev, 0x0000); + if (ret < 0) + goto out; + + rx_ctl = sr_read_rx_ctl(dev); + netdev_dbg(dev->net, "RX_CTL is 0x%04x setting to 0x0000\n", rx_ctl); + + ret = sr_sw_reset(dev, SR_SWRESET_PRL); + if (ret < 0) + goto out; + + msleep(150); + + ret = sr_sw_reset(dev, SR_SWRESET_IPRL | SR_SWRESET_PRL); + if (ret < 0) + goto out; + + msleep(150); + + ret = sr9800_set_default_mode(dev); + if (ret < 0) + goto out; + + /* Rewrite MAC address */ + memcpy(data->mac_addr, dev->net->dev_addr, ETH_ALEN); + ret = sr_write_cmd(dev, SR_CMD_WRITE_NODE_ID, 0, 0, ETH_ALEN, + data->mac_addr); + if (ret < 0) + goto out; + + return 0; + +out: + return ret; +} + +static const struct net_device_ops sr9800_netdev_ops = { + .ndo_open = usbnet_open, + .ndo_stop = usbnet_stop, + .ndo_start_xmit = usbnet_start_xmit, + .ndo_tx_timeout = usbnet_tx_timeout, + .ndo_change_mtu = usbnet_change_mtu, + .ndo_set_mac_address = sr_set_mac_address, + .ndo_validate_addr = eth_validate_addr, + .ndo_do_ioctl = sr_ioctl, + .ndo_set_rx_mode = sr_set_multicast, +}; + +static int sr9800_phy_powerup(struct usbnet *dev) +{ + int ret; + + /* set the embedded Ethernet PHY in power-down state */ + ret = sr_sw_reset(dev, SR_SWRESET_IPPD | SR_SWRESET_IPRL); + if (ret < 0) { + netdev_err(dev->net, "Failed to power down PHY : %d\n", ret); + return ret; + } + msleep(20); + + /* set the embedded Ethernet PHY in power-up state */ + ret = sr_sw_reset(dev, SR_SWRESET_IPRL); + if (ret < 0) { + netdev_err(dev->net, "Failed to reset PHY: %d\n", ret); + return ret; + } + msleep(600); + + /* set the embedded Ethernet PHY in reset state */ + ret = sr_sw_reset(dev, SR_SWRESET_CLEAR); + if (ret < 0) { + netdev_err(dev->net, "Failed to power up PHY: %d\n", ret); + return ret; + } + msleep(20); + + /* set the embedded Ethernet PHY in power-up state */ + ret = sr_sw_reset(dev, SR_SWRESET_IPRL); + if (ret < 0) { + netdev_err(dev->net, "Failed to reset PHY: %d\n", ret); + return ret; + } + + return 0; +} + +static int sr9800_bind(struct usbnet *dev, struct usb_interface *intf) +{ + struct sr_data *data = (struct sr_data *)&dev->data; + u16 led01_mux, led23_mux; + int ret, embd_phy; + u32 phyid; + u16 rx_ctl; + + data->eeprom_len = SR9800_EEPROM_LEN; + + usbnet_get_endpoints(dev, intf); + + /* LED Setting Rule : + * AABB:CCDD + * AA : MFA0(LED0) + * BB : MFA1(LED1) + * CC : MFA2(LED2), Reserved for SR9800 + * DD : MFA3(LED3), Reserved for SR9800 + */ + led01_mux = (SR_LED_MUX_LINK_ACTIVE << 8) | SR_LED_MUX_LINK; + led23_mux = (SR_LED_MUX_LINK_ACTIVE << 8) | SR_LED_MUX_TX_ACTIVE; + ret = sr_write_cmd(dev, SR_CMD_LED_MUX, led01_mux, led23_mux, 0, NULL); + if (ret < 0) { + netdev_err(dev->net, "set LINK LED failed : %d\n", ret); + goto out; + } + + /* Get the MAC address */ + ret = sr_read_cmd(dev, SR_CMD_READ_NODE_ID, 0, 0, ETH_ALEN, + dev->net->dev_addr); + if (ret < 0) { + netdev_dbg(dev->net, "Failed to read MAC address: %d\n", ret); + return ret; + } + netdev_dbg(dev->net, "mac addr : %pM\n", dev->net->dev_addr); + + /* Initialize MII structure */ + dev->mii.dev = dev->net; + dev->mii.mdio_read = sr_mdio_read; + dev->mii.mdio_write = sr_mdio_write; + dev->mii.phy_id_mask = 0x1f; + dev->mii.reg_num_mask = 0x1f; + dev->mii.phy_id = sr_get_phy_addr(dev); + + dev->net->netdev_ops = &sr9800_netdev_ops; + dev->net->ethtool_ops = &sr9800_ethtool_ops; + + embd_phy = ((dev->mii.phy_id & 0x1f) == 0x10 ? 1 : 0); + /* Reset the PHY to normal operation mode */ + ret = sr_write_cmd(dev, SR_CMD_SW_PHY_SELECT, embd_phy, 0, 0, NULL); + if (ret < 0) { + netdev_dbg(dev->net, "Select PHY #1 failed: %d\n", ret); + return ret; + } + + /* Init PHY routine */ + ret = sr9800_phy_powerup(dev); + if (ret < 0) + goto out; + + rx_ctl = sr_read_rx_ctl(dev); + netdev_dbg(dev->net, "RX_CTL is 0x%04x after software reset\n", rx_ctl); + ret = sr_write_rx_ctl(dev, 0x0000); + if (ret < 0) + goto out; + + rx_ctl = sr_read_rx_ctl(dev); + netdev_dbg(dev->net, "RX_CTL is 0x%04x setting to 0x0000\n", rx_ctl); + + /* Read PHYID register *AFTER* the PHY was reset properly */ + phyid = sr_get_phyid(dev); + netdev_dbg(dev->net, "PHYID=0x%08x\n", phyid); + + /* medium mode setting */ + ret = sr9800_set_default_mode(dev); + if (ret < 0) + goto out; + + if (dev->udev->speed == USB_SPEED_HIGH) { + ret = sr_write_cmd(dev, SR_CMD_BULKIN_SIZE, + SR9800_BULKIN_SIZE[SR9800_MAX_BULKIN_4K].byte_cnt, + SR9800_BULKIN_SIZE[SR9800_MAX_BULKIN_4K].threshold, + 0, NULL); + if (ret < 0) { + netdev_err(dev->net, "Reset RX_CTL failed: %d\n", ret); + goto out; + } + dev->rx_urb_size = + SR9800_BULKIN_SIZE[SR9800_MAX_BULKIN_4K].size; + } else { + ret = sr_write_cmd(dev, SR_CMD_BULKIN_SIZE, + SR9800_BULKIN_SIZE[SR9800_MAX_BULKIN_2K].byte_cnt, + SR9800_BULKIN_SIZE[SR9800_MAX_BULKIN_2K].threshold, + 0, NULL); + if (ret < 0) { + netdev_err(dev->net, "Reset RX_CTL failed: %d\n", ret); + goto out; + } + 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__, + dev->rx_urb_size); + return 0; + +out: + return ret; +} + +static const struct driver_info sr9800_driver_info = { + .description = "CoreChip SR9800 USB 2.0 Ethernet", + .bind = sr9800_bind, + .status = sr_status, + .link_reset = sr9800_link_reset, + .reset = sr9800_reset, + .flags = DRIVER_FLAG, + .rx_fixup = sr_rx_fixup, + .tx_fixup = sr_tx_fixup, +}; + +static const struct usb_device_id products[] = { + { + USB_DEVICE(0x0fe6, 0x9800), /* SR9800 Device */ + .driver_info = (unsigned long) &sr9800_driver_info, + }, + {}, /* END */ +}; + +MODULE_DEVICE_TABLE(usb, products); + +static struct usb_driver sr_driver = { + .name = DRIVER_NAME, + .id_table = products, + .probe = usbnet_probe, + .suspend = usbnet_suspend, + .resume = usbnet_resume, + .disconnect = usbnet_disconnect, + .supports_autosuspend = 1, +}; + +module_usb_driver(sr_driver); + +MODULE_AUTHOR("Liu Junliang + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +#ifndef _SR9800_H +#define _SR9800_H + +/* SR9800 spec. command table on Linux Platform */ + +/* command : Software Station Management Control Reg */ +#define SR_CMD_SET_SW_MII 0x06 +/* command : PHY Read Reg */ +#define SR_CMD_READ_MII_REG 0x07 +/* command : PHY Write Reg */ +#define SR_CMD_WRITE_MII_REG 0x08 +/* command : Hardware Station Management Control Reg */ +#define SR_CMD_SET_HW_MII 0x0a +/* command : SROM Read Reg */ +#define SR_CMD_READ_EEPROM 0x0b +/* command : SROM Write Reg */ +#define SR_CMD_WRITE_EEPROM 0x0c +/* command : SROM Write Enable Reg */ +#define SR_CMD_WRITE_ENABLE 0x0d +/* command : SROM Write Disable Reg */ +#define SR_CMD_WRITE_DISABLE 0x0e +/* command : RX Control Read Reg */ +#define SR_CMD_READ_RX_CTL 0x0f +#define SR_RX_CTL_PRO (1 << 0) +#define SR_RX_CTL_AMALL (1 << 1) +#define SR_RX_CTL_SEP (1 << 2) +#define SR_RX_CTL_AB (1 << 3) +#define SR_RX_CTL_AM (1 << 4) +#define SR_RX_CTL_AP (1 << 5) +#define SR_RX_CTL_ARP (1 << 6) +#define SR_RX_CTL_SO (1 << 7) +#define SR_RX_CTL_RH1M (1 << 8) +#define SR_RX_CTL_RH2M (1 << 9) +#define SR_RX_CTL_RH3M (1 << 10) +/* command : RX Control Write Reg */ +#define SR_CMD_WRITE_RX_CTL 0x10 +/* command : IPG0/IPG1/IPG2 Control Read Reg */ +#define SR_CMD_READ_IPG012 0x11 +/* command : IPG0/IPG1/IPG2 Control Write Reg */ +#define SR_CMD_WRITE_IPG012 0x12 +/* command : Node ID Read Reg */ +#define SR_CMD_READ_NODE_ID 0x13 +/* command : Node ID Write Reg */ +#define SR_CMD_WRITE_NODE_ID 0x14 +/* command : Multicast Filter Array Read Reg */ +#define SR_CMD_READ_MULTI_FILTER 0x15 +/* command : Multicast Filter Array Write Reg */ +#define SR_CMD_WRITE_MULTI_FILTER 0x16 +/* command : Eth/HomePNA PHY Address Reg */ +#define SR_CMD_READ_PHY_ID 0x19 +/* command : Medium Status Read Reg */ +#define SR_CMD_READ_MEDIUM_STATUS 0x1a +#define SR_MONITOR_LINK (1 << 1) +#define SR_MONITOR_MAGIC (1 << 2) +#define SR_MONITOR_HSFS (1 << 4) +/* command : Medium Status Write Reg */ +#define SR_CMD_WRITE_MEDIUM_MODE 0x1b +#define SR_MEDIUM_GM (1 << 0) +#define SR_MEDIUM_FD (1 << 1) +#define SR_MEDIUM_AC (1 << 2) +#define SR_MEDIUM_ENCK (1 << 3) +#define SR_MEDIUM_RFC (1 << 4) +#define SR_MEDIUM_TFC (1 << 5) +#define SR_MEDIUM_JFE (1 << 6) +#define SR_MEDIUM_PF (1 << 7) +#define SR_MEDIUM_RE (1 << 8) +#define SR_MEDIUM_PS (1 << 9) +#define SR_MEDIUM_RSV (1 << 10) +#define SR_MEDIUM_SBP (1 << 11) +#define SR_MEDIUM_SM (1 << 12) +/* command : Monitor Mode Status Read Reg */ +#define SR_CMD_READ_MONITOR_MODE 0x1c +/* command : Monitor Mode Status Write Reg */ +#define SR_CMD_WRITE_MONITOR_MODE 0x1d +/* command : GPIO Status Read Reg */ +#define SR_CMD_READ_GPIOS 0x1e +#define SR_GPIO_GPO0EN (1 << 0) /* GPIO0 Output enable */ +#define SR_GPIO_GPO_0 (1 << 1) /* GPIO0 Output value */ +#define SR_GPIO_GPO1EN (1 << 2) /* GPIO1 Output enable */ +#define SR_GPIO_GPO_1 (1 << 3) /* GPIO1 Output value */ +#define SR_GPIO_GPO2EN (1 << 4) /* GPIO2 Output enable */ +#define SR_GPIO_GPO_2 (1 << 5) /* GPIO2 Output value */ +#define SR_GPIO_RESERVED (1 << 6) /* Reserved */ +#define SR_GPIO_RSE (1 << 7) /* Reload serial EEPROM */ +/* command : GPIO Status Write Reg */ +#define SR_CMD_WRITE_GPIOS 0x1f +/* command : Eth PHY Power and Reset Control Reg */ +#define SR_CMD_SW_RESET 0x20 +#define SR_SWRESET_CLEAR 0x00 +#define SR_SWRESET_RR (1 << 0) +#define SR_SWRESET_RT (1 << 1) +#define SR_SWRESET_PRTE (1 << 2) +#define SR_SWRESET_PRL (1 << 3) +#define SR_SWRESET_BZ (1 << 4) +#define SR_SWRESET_IPRL (1 << 5) +#define SR_SWRESET_IPPD (1 << 6) +/* command : Software Interface Selection Status Read Reg */ +#define SR_CMD_SW_PHY_STATUS 0x21 +/* command : Software Interface Selection Status Write Reg */ +#define SR_CMD_SW_PHY_SELECT 0x22 +/* command : BULK in Buffer Size Reg */ +#define SR_CMD_BULKIN_SIZE 0x2A +/* command : LED_MUX Control Reg */ +#define SR_CMD_LED_MUX 0x70 +#define SR_LED_MUX_TX_ACTIVE (1 << 0) +#define SR_LED_MUX_RX_ACTIVE (1 << 1) +#define SR_LED_MUX_COLLISION (1 << 2) +#define SR_LED_MUX_DUP_COL (1 << 3) +#define SR_LED_MUX_DUP (1 << 4) +#define SR_LED_MUX_SPEED (1 << 5) +#define SR_LED_MUX_LINK_ACTIVE (1 << 6) +#define SR_LED_MUX_LINK (1 << 7) + +/* Register Access Flags */ +#define SR_REQ_RD_REG (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE) +#define SR_REQ_WR_REG (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE) + +/* Multicast Filter Array size & Max Number */ +#define SR_MCAST_FILTER_SIZE 8 +#define SR_MAX_MCAST 64 + +/* IPG0/1/2 Default Value */ +#define SR9800_IPG0_DEFAULT 0x15 +#define SR9800_IPG1_DEFAULT 0x0c +#define SR9800_IPG2_DEFAULT 0x12 + +/* Medium Status Default Mode */ +#define SR9800_MEDIUM_DEFAULT \ + (SR_MEDIUM_FD | SR_MEDIUM_RFC | \ + SR_MEDIUM_TFC | SR_MEDIUM_PS | \ + SR_MEDIUM_AC | SR_MEDIUM_RE) + +/* RX Control Default Setting */ +#define SR_DEFAULT_RX_CTL \ + (SR_RX_CTL_SO | SR_RX_CTL_AB | SR_RX_CTL_RH1M) + +/* EEPROM Magic Number & EEPROM Size */ +#define SR_EEPROM_MAGIC 0xdeadbeef +#define SR9800_EEPROM_LEN 0xff + +/* SR9800 Driver Version and Driver Name */ +#define DRIVER_VERSION "11-Nov-2013" +#define DRIVER_NAME "CoreChips" +#define DRIVER_FLAG \ + (FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR | FLAG_MULTI_PACKET) + +/* SR9800 BULKIN Buffer Size */ +#define SR9800_MAX_BULKIN_2K 0 +#define SR9800_MAX_BULKIN_4K 1 +#define SR9800_MAX_BULKIN_6K 2 +#define SR9800_MAX_BULKIN_8K 3 +#define SR9800_MAX_BULKIN_16K 4 +#define SR9800_MAX_BULKIN_20K 5 +#define SR9800_MAX_BULKIN_24K 6 +#define SR9800_MAX_BULKIN_32K 7 + +struct {unsigned short size, byte_cnt, threshold; } SR9800_BULKIN_SIZE[] = { + /* 2k */ + {2048, 0x8000, 0x8001}, + /* 4k */ + {4096, 0x8100, 0x8147}, + /* 6k */ + {6144, 0x8200, 0x81EB}, + /* 8k */ + {8192, 0x8300, 0x83D7}, + /* 16 */ + {16384, 0x8400, 0x851E}, + /* 20k */ + {20480, 0x8500, 0x8666}, + /* 24k */ + {24576, 0x8600, 0x87AE}, + /* 32k */ + {32768, 0x8700, 0x8A3D}, +}; + +/* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */ +struct sr_data { + u8 multi_filter[SR_MCAST_FILTER_SIZE]; + u8 mac_addr[ETH_ALEN]; + u8 phymode; + u8 ledmode; + u8 eeprom_len; +}; + +struct sr9800_int_data { + __le16 res1; + u8 link; + __le16 res2; + u8 status; + __le16 res3; +} __packed; + +#endif /* _SR9800_H */ -- cgit v0.10.2 From 6b8790b5006b5ca3ee1c039c3c909833d7958716 Mon Sep 17 00:00:00 2001 From: dingtianhong Date: Mon, 10 Feb 2014 16:33:59 +0800 Subject: bonding: remove unwanted bond lock for enslave processing The bond enslave processing don't hold bond->lock anymore, so release an unlocked rw lock will cause warning message, remove the unwanted read_unlock(&bond->lock). Cc: Jay Vosburgh Cc: Veaceslav Falico Cc: Andy Gospodarek Signed-off-by: Ding Tianhong Acked-by: Veaceslav Falico Signed-off-by: David S. Miller diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 35f7e90..71ba18e 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1510,7 +1510,6 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) slave_dev->npinfo = bond->dev->npinfo; if (slave_dev->npinfo) { if (slave_enable_netpoll(new_slave)) { - read_unlock(&bond->lock); pr_info("Error, %s: master_dev is using netpoll, " "but new slave device does not support netpoll.\n", bond_dev->name); -- cgit v0.10.2 From b6f52ae2f0d32387bde2b89883e3b64d88b9bfe8 Mon Sep 17 00:00:00 2001 From: Richard Yao Date: Sat, 8 Feb 2014 19:32:01 -0500 Subject: 9p/trans_virtio.c: Fix broken zero-copy on vmalloc() buffers The 9p-virtio transport does zero copy on things larger than 1024 bytes in size. It accomplishes this by returning the physical addresses of pages to the virtio-pci device. At present, the translation is usually a bit shift. That approach produces an invalid page address when we read/write to vmalloc buffers, such as those used for Linux kernel modules. Any attempt to load a Linux kernel module from 9p-virtio produces the following stack. [] p9_virtio_zc_request+0x45e/0x510 [] p9_client_zc_rpc.constprop.16+0xfd/0x4f0 [] p9_client_read+0x15d/0x240 [] v9fs_fid_readn+0x50/0xa0 [] v9fs_file_readn+0x10/0x20 [] v9fs_file_read+0x37/0x70 [] vfs_read+0x9b/0x160 [] kernel_read+0x41/0x60 [] copy_module_from_fd.isra.34+0xfb/0x180 Subsequently, QEMU will die printing: qemu-system-x86_64: virtio: trying to map MMIO memory This patch enables 9p-virtio to correctly handle this case. This not only enables us to load Linux kernel modules off virtfs, but also enables ZFS file-based vdevs on virtfs to be used without killing QEMU. Special thanks to both Avi Kivity and Alexander Graf for their interpretation of QEMU backtraces. Without their guidence, tracking down this bug would have taken much longer. Also, special thanks to Linus Torvalds for his insightful explanation of why this should use is_vmalloc_addr() instead of is_vmalloc_or_module_addr(): https://lkml.org/lkml/2014/2/8/272 Signed-off-by: Richard Yao Signed-off-by: David S. Miller diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index cd1e1ed..ac2666c 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c @@ -340,7 +340,10 @@ static int p9_get_mapped_pages(struct virtio_chan *chan, int count = nr_pages; while (nr_pages) { s = rest_of_page(data); - pages[index++] = kmap_to_page(data); + if (is_vmalloc_addr(data)) + pages[index++] = vmalloc_to_page(data); + else + pages[index++] = kmap_to_page(data); data += s; nr_pages--; } -- cgit v0.10.2 From 3e5ccc29f71b5dfdfb81dac8c19372af83923b7f Mon Sep 17 00:00:00 2001 From: John Greene Date: Mon, 10 Feb 2014 14:34:04 -0500 Subject: alx: add missing stats_lock spinlock init Trivial fix for init time stack trace occuring in alx_get_stats64 upon start up. Should have been part of commit adding the spinlock: f1b6b106 alx: add alx_get_stats64 operation Signed-off-by: John Greene Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c index e92ffd6..2e45f6e 100644 --- a/drivers/net/ethernet/atheros/alx/main.c +++ b/drivers/net/ethernet/atheros/alx/main.c @@ -1292,6 +1292,7 @@ static int alx_probe(struct pci_dev *pdev, const struct pci_device_id *ent) alx = netdev_priv(netdev); spin_lock_init(&alx->hw.mdio_lock); spin_lock_init(&alx->irq_lock); + spin_lock_init(&alx->stats_lock); alx->dev = netdev; alx->hw.pdev = pdev; alx->msg_enable = NETIF_MSG_LINK | NETIF_MSG_HW | NETIF_MSG_IFUP | -- cgit v0.10.2 From 20e7c4e80dcd01dad5e6c8b32455228b8fe9c619 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 10 Feb 2014 11:42:35 -0800 Subject: 6lowpan: fix lockdep splats When a device ndo_start_xmit() calls again dev_queue_xmit(), lockdep can complain because dev_queue_xmit() is re-entered and the spinlocks protecting tx queues share a common lockdep class. Same issue was fixed for bonding/l2tp/ppp in commits 0daa2303028a6 ("[PATCH] bonding: lockdep annotation") 49ee49202b4ac ("bonding: set qdisc_tx_busylock to avoid LOCKDEP splat") 23d3b8bfb8eb2 ("net: qdisc busylock needs lockdep annotations ") 303c07db487be ("ppp: set qdisc_tx_busylock to avoid LOCKDEP splat ") Reported-by: Alexander Aring Signed-off-by: Eric Dumazet Tested-by: Alexander Aring Signed-off-by: David S. Miller diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c index 8bfb401..8edfea5 100644 --- a/net/ieee802154/6lowpan.c +++ b/net/ieee802154/6lowpan.c @@ -530,7 +530,27 @@ static struct header_ops lowpan_header_ops = { .create = lowpan_header_create, }; +static struct lock_class_key lowpan_tx_busylock; +static struct lock_class_key lowpan_netdev_xmit_lock_key; + +static void lowpan_set_lockdep_class_one(struct net_device *dev, + struct netdev_queue *txq, + void *_unused) +{ + lockdep_set_class(&txq->_xmit_lock, + &lowpan_netdev_xmit_lock_key); +} + + +static int lowpan_dev_init(struct net_device *dev) +{ + netdev_for_each_tx_queue(dev, lowpan_set_lockdep_class_one, NULL); + dev->qdisc_tx_busylock = &lowpan_tx_busylock; + return 0; +} + static const struct net_device_ops lowpan_netdev_ops = { + .ndo_init = lowpan_dev_init, .ndo_start_xmit = lowpan_xmit, .ndo_set_mac_address = lowpan_set_address, }; -- cgit v0.10.2 From cd15b048445d0a54f7147c35a86c5a16ef231554 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Tue, 11 Feb 2014 11:32:38 +1100 Subject: powerpc/powernv: Add iommu DMA bypass support for IODA2 This patch adds the support for to create a direct iommu "bypass" window on IODA2 bridges (such as Power8) allowing to bypass iommu page translation completely for 64-bit DMA capable devices, thus significantly improving DMA performances. Additionally, this adds a hook to the struct iommu_table so that the IOMMU API / VFIO can disable the bypass when external ownership is requested, since in that case, the device will be used by an environment such as userspace or a KVM guest which must not be allowed to bypass translations. Signed-off-by: Benjamin Herrenschmidt diff --git a/arch/powerpc/include/asm/dma-mapping.h b/arch/powerpc/include/asm/dma-mapping.h index e27e9ad..150866b 100644 --- a/arch/powerpc/include/asm/dma-mapping.h +++ b/arch/powerpc/include/asm/dma-mapping.h @@ -134,6 +134,7 @@ static inline int dma_supported(struct device *dev, u64 mask) } extern int dma_set_mask(struct device *dev, u64 dma_mask); +extern int __dma_set_mask(struct device *dev, u64 dma_mask); #define dma_alloc_coherent(d,s,h,f) dma_alloc_attrs(d,s,h,f,NULL) diff --git a/arch/powerpc/include/asm/iommu.h b/arch/powerpc/include/asm/iommu.h index f7a8036..42632c7 100644 --- a/arch/powerpc/include/asm/iommu.h +++ b/arch/powerpc/include/asm/iommu.h @@ -77,6 +77,7 @@ struct iommu_table { #ifdef CONFIG_IOMMU_API struct iommu_group *it_group; #endif + void (*set_bypass)(struct iommu_table *tbl, bool enable); }; /* Pure 2^n version of get_order */ diff --git a/arch/powerpc/kernel/dma.c b/arch/powerpc/kernel/dma.c index 8032b97..ee78f6e 100644 --- a/arch/powerpc/kernel/dma.c +++ b/arch/powerpc/kernel/dma.c @@ -191,12 +191,10 @@ EXPORT_SYMBOL(dma_direct_ops); #define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16) -int dma_set_mask(struct device *dev, u64 dma_mask) +int __dma_set_mask(struct device *dev, u64 dma_mask) { struct dma_map_ops *dma_ops = get_dma_ops(dev); - if (ppc_md.dma_set_mask) - return ppc_md.dma_set_mask(dev, dma_mask); if ((dma_ops != NULL) && (dma_ops->set_dma_mask != NULL)) return dma_ops->set_dma_mask(dev, dma_mask); if (!dev->dma_mask || !dma_supported(dev, dma_mask)) @@ -204,6 +202,12 @@ int dma_set_mask(struct device *dev, u64 dma_mask) *dev->dma_mask = dma_mask; return 0; } +int dma_set_mask(struct device *dev, u64 dma_mask) +{ + if (ppc_md.dma_set_mask) + return ppc_md.dma_set_mask(dev, dma_mask); + return __dma_set_mask(dev, dma_mask); +} EXPORT_SYMBOL(dma_set_mask); u64 dma_get_required_mask(struct device *dev) diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index d773dd4..88e3ec6 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c @@ -1088,6 +1088,14 @@ int iommu_take_ownership(struct iommu_table *tbl) memset(tbl->it_map, 0xff, sz); iommu_clear_tces_and_put_pages(tbl, tbl->it_offset, tbl->it_size); + /* + * Disable iommu bypass, otherwise the user can DMA to all of + * our physical memory via the bypass window instead of just + * the pages that has been explicitly mapped into the iommu + */ + if (tbl->set_bypass) + tbl->set_bypass(tbl, false); + return 0; } EXPORT_SYMBOL_GPL(iommu_take_ownership); @@ -1102,6 +1110,10 @@ void iommu_release_ownership(struct iommu_table *tbl) /* Restore bit#0 set by iommu_init_table() */ if (tbl->it_offset == 0) set_bit(0, tbl->it_map); + + /* The kernel owns the device now, we can restore the iommu bypass */ + if (tbl->set_bypass) + tbl->set_bypass(tbl, true); } EXPORT_SYMBOL_GPL(iommu_release_ownership); diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 7d6dcc6..3b2b4fb 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -460,9 +461,39 @@ static void pnv_pci_ioda_dma_dev_setup(struct pnv_phb *phb, struct pci_dev *pdev return; pe = &phb->ioda.pe_array[pdn->pe_number]; + WARN_ON(get_dma_ops(&pdev->dev) != &dma_iommu_ops); set_iommu_table_base_and_group(&pdev->dev, &pe->tce32_table); } +static int pnv_pci_ioda_dma_set_mask(struct pnv_phb *phb, + struct pci_dev *pdev, u64 dma_mask) +{ + struct pci_dn *pdn = pci_get_pdn(pdev); + struct pnv_ioda_pe *pe; + uint64_t top; + bool bypass = false; + + if (WARN_ON(!pdn || pdn->pe_number == IODA_INVALID_PE)) + return -ENODEV;; + + pe = &phb->ioda.pe_array[pdn->pe_number]; + if (pe->tce_bypass_enabled) { + top = pe->tce_bypass_base + memblock_end_of_DRAM() - 1; + bypass = (dma_mask >= top); + } + + if (bypass) { + dev_info(&pdev->dev, "Using 64-bit DMA iommu bypass\n"); + set_dma_ops(&pdev->dev, &dma_direct_ops); + set_dma_offset(&pdev->dev, pe->tce_bypass_base); + } else { + dev_info(&pdev->dev, "Using 32-bit DMA via iommu\n"); + set_dma_ops(&pdev->dev, &dma_iommu_ops); + set_iommu_table_base(&pdev->dev, &pe->tce32_table); + } + return 0; +} + static void pnv_ioda_setup_bus_dma(struct pnv_ioda_pe *pe, struct pci_bus *bus) { struct pci_dev *dev; @@ -657,6 +688,56 @@ static void pnv_pci_ioda_setup_dma_pe(struct pnv_phb *phb, __free_pages(tce_mem, get_order(TCE32_TABLE_SIZE * segs)); } +static void pnv_pci_ioda2_set_bypass(struct iommu_table *tbl, bool enable) +{ + struct pnv_ioda_pe *pe = container_of(tbl, struct pnv_ioda_pe, + tce32_table); + uint16_t window_id = (pe->pe_number << 1 ) + 1; + int64_t rc; + + pe_info(pe, "%sabling 64-bit DMA bypass\n", enable ? "En" : "Dis"); + if (enable) { + phys_addr_t top = memblock_end_of_DRAM(); + + top = roundup_pow_of_two(top); + rc = opal_pci_map_pe_dma_window_real(pe->phb->opal_id, + pe->pe_number, + window_id, + pe->tce_bypass_base, + top); + } else { + rc = opal_pci_map_pe_dma_window_real(pe->phb->opal_id, + pe->pe_number, + window_id, + pe->tce_bypass_base, + 0); + + /* + * We might want to reset the DMA ops of all devices on + * this PE. However in theory, that shouldn't be necessary + * as this is used for VFIO/KVM pass-through and the device + * hasn't yet been returned to its kernel driver + */ + } + if (rc) + pe_err(pe, "OPAL error %lld configuring bypass window\n", rc); + else + pe->tce_bypass_enabled = enable; +} + +static void pnv_pci_ioda2_setup_bypass_pe(struct pnv_phb *phb, + struct pnv_ioda_pe *pe) +{ + /* TVE #1 is selected by PCI address bit 59 */ + pe->tce_bypass_base = 1ull << 59; + + /* Install set_bypass callback for VFIO */ + pe->tce32_table.set_bypass = pnv_pci_ioda2_set_bypass; + + /* Enable bypass by default */ + pnv_pci_ioda2_set_bypass(&pe->tce32_table, true); +} + static void pnv_pci_ioda2_setup_dma_pe(struct pnv_phb *phb, struct pnv_ioda_pe *pe) { @@ -727,6 +808,8 @@ static void pnv_pci_ioda2_setup_dma_pe(struct pnv_phb *phb, else pnv_ioda_setup_bus_dma(pe, pe->pbus); + /* Also create a bypass window */ + pnv_pci_ioda2_setup_bypass_pe(phb, pe); return; fail: if (pe->tce32_seg >= 0) @@ -1286,6 +1369,7 @@ void __init pnv_pci_init_ioda_phb(struct device_node *np, /* Setup TCEs */ phb->dma_dev_setup = pnv_pci_ioda_dma_dev_setup; + phb->dma_set_mask = pnv_pci_ioda_dma_set_mask; /* Setup shutdown function for kexec */ phb->shutdown = pnv_pci_ioda_shutdown; diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c index b555ebc..95633d7 100644 --- a/arch/powerpc/platforms/powernv/pci.c +++ b/arch/powerpc/platforms/powernv/pci.c @@ -634,6 +634,16 @@ static void pnv_pci_dma_dev_setup(struct pci_dev *pdev) pnv_pci_dma_fallback_setup(hose, pdev); } +int pnv_pci_dma_set_mask(struct pci_dev *pdev, u64 dma_mask) +{ + struct pci_controller *hose = pci_bus_to_host(pdev->bus); + struct pnv_phb *phb = hose->private_data; + + if (phb && phb->dma_set_mask) + return phb->dma_set_mask(phb, pdev, dma_mask); + return __dma_set_mask(&pdev->dev, dma_mask); +} + void pnv_pci_shutdown(void) { struct pci_controller *hose; diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h index 13f1942..cde1694 100644 --- a/arch/powerpc/platforms/powernv/pci.h +++ b/arch/powerpc/platforms/powernv/pci.h @@ -54,7 +54,9 @@ struct pnv_ioda_pe { struct iommu_table tce32_table; phys_addr_t tce_inval_reg_phys; - /* XXX TODO: Add support for additional 64-bit iommus */ + /* 64-bit TCE bypass region */ + bool tce_bypass_enabled; + uint64_t tce_bypass_base; /* MSIs. MVE index is identical for for 32 and 64 bit MSI * and -1 if not supported. (It's actually identical to the @@ -113,6 +115,8 @@ struct pnv_phb { unsigned int hwirq, unsigned int virq, unsigned int is_64, struct msi_msg *msg); void (*dma_dev_setup)(struct pnv_phb *phb, struct pci_dev *pdev); + int (*dma_set_mask)(struct pnv_phb *phb, struct pci_dev *pdev, + u64 dma_mask); void (*fixup_phb)(struct pci_controller *hose); u32 (*bdfn_to_pe)(struct pnv_phb *phb, struct pci_bus *bus, u32 devfn); void (*shutdown)(struct pnv_phb *phb); diff --git a/arch/powerpc/platforms/powernv/powernv.h b/arch/powerpc/platforms/powernv/powernv.h index de6819b..0051e10 100644 --- a/arch/powerpc/platforms/powernv/powernv.h +++ b/arch/powerpc/platforms/powernv/powernv.h @@ -7,12 +7,20 @@ extern void pnv_smp_init(void); static inline void pnv_smp_init(void) { } #endif +struct pci_dev; + #ifdef CONFIG_PCI extern void pnv_pci_init(void); extern void pnv_pci_shutdown(void); +extern int pnv_pci_dma_set_mask(struct pci_dev *pdev, u64 dma_mask); #else static inline void pnv_pci_init(void) { } static inline void pnv_pci_shutdown(void) { } + +static inline int pnv_pci_dma_set_mask(struct pci_dev *pdev, u64 dma_mask) +{ + return -ENODEV; +} #endif extern void pnv_lpc_init(void); diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c index 21166f6..110f4fb 100644 --- a/arch/powerpc/platforms/powernv/setup.c +++ b/arch/powerpc/platforms/powernv/setup.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -141,6 +142,13 @@ static void pnv_progress(char *s, unsigned short hex) { } +static int pnv_dma_set_mask(struct device *dev, u64 dma_mask) +{ + if (dev_is_pci(dev)) + return pnv_pci_dma_set_mask(to_pci_dev(dev), dma_mask); + return __dma_set_mask(dev, dma_mask); +} + static void pnv_shutdown(void) { /* Let the PCI code clear up IODA tables */ @@ -238,6 +246,7 @@ define_machine(powernv) { .machine_shutdown = pnv_shutdown, .power_save = powernv_idle, .calibrate_decr = generic_calibrate_decr, + .dma_set_mask = pnv_dma_set_mask, #ifdef CONFIG_KEXEC .kexec_cpu_down = pnv_kexec_cpu_down, #endif -- cgit v0.10.2 From 2c45aada341121438affc4cb8d5b4cfaa2813d3d Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Mon, 10 Feb 2014 13:39:53 -0500 Subject: genirq: Add missing irq_to_desc export for CONFIG_SPARSE_IRQ=n In allmodconfig builds for sparc and any other arch which does not set CONFIG_SPARSE_IRQ, the following will be seen at modpost: CC [M] lib/cpu-notifier-error-inject.o CC [M] lib/pm-notifier-error-inject.o ERROR: "irq_to_desc" [drivers/gpio/gpio-mcp23s08.ko] undefined! make[2]: *** [__modpost] Error 1 This happens because commit 3911ff30f5 ("genirq: export handle_edge_irq() and irq_to_desc()") added one export for it, but there were actually two instances of it, in an if/else clause for CONFIG_SPARSE_IRQ. Add the second one. Signed-off-by: Paul Gortmaker Cc: Jiri Kosina Cc: stable@vger.kernel.org # 3.4+ Link: http://lkml.kernel.org/r/1392057610-11514-1-git-send-email-paul.gortmaker@windriver.com Signed-off-by: Thomas Gleixner diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c index 192a302..8ab8e93 100644 --- a/kernel/irq/irqdesc.c +++ b/kernel/irq/irqdesc.c @@ -274,6 +274,7 @@ struct irq_desc *irq_to_desc(unsigned int irq) { return (irq < NR_IRQS) ? irq_desc + irq : NULL; } +EXPORT_SYMBOL(irq_to_desc); static void free_desc(unsigned int irq) { -- cgit v0.10.2 From a2d213dd77da4710bcb75f8efe85a32e3db8b39b Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 7 Feb 2014 16:34:05 +0100 Subject: drm/i915: Fix intel_pipe_to_cpu_transcoder for UMS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We don't have all the drm_crtc&co hanging around in that case. This regression has been introduced in commit 391f75e2bf13f105d9e4a120736ccdd8e3bc638b Author: Ville Syrjälä Date: Wed Sep 25 19:55:26 2013 +0300 drm/i915: Fix pre-CTG vblank counter Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=69521 Cc: stable@vger.kernel.org (for 3.13 only) Cc: Ville Syrjälä Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 17d8fcb..9fec711 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -567,8 +567,7 @@ static u32 i915_get_vblank_counter(struct drm_device *dev, int pipe) vbl_start = mode->crtc_vblank_start * mode->crtc_htotal; } else { - enum transcoder cpu_transcoder = - intel_pipe_to_cpu_transcoder(dev_priv, pipe); + enum transcoder cpu_transcoder = (enum transcoder) pipe; u32 htotal; htotal = ((I915_READ(HTOTAL(cpu_transcoder)) >> 16) & 0x1fff) + 1; -- cgit v0.10.2 From 1d2cb9a54abc6e1d239f28f07661366d5662a94a Mon Sep 17 00:00:00 2001 From: Mika Kuoppala Date: Fri, 7 Feb 2014 17:40:50 +0200 Subject: drm/i915: Pair va_copy with va_end in i915_error_vprintf Each invocation of va_copy() must be matched by a corresponding invocation of va_end() in the same function. This regression has been introduced in commit e29bb4ebbf000ff9ac081d29784a3331618f012e Author: Chris Wilson Date: Fri Sep 20 10:20:59 2013 +0100 drm/i915: Use a temporary va_list for two-pass string handling Signed-off-by: Mika Kuoppala Reviewed-by: Chris Wilson Cc: stable@vger.kernel.org Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index d7fd2fd..990cf8f 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -146,7 +146,10 @@ static void i915_error_vprintf(struct drm_i915_error_state_buf *e, va_list tmp; va_copy(tmp, args); - if (!__i915_error_seek(e, vsnprintf(NULL, 0, f, tmp))) + len = vsnprintf(NULL, 0, f, tmp); + va_end(tmp); + + if (!__i915_error_seek(e, len)) return; } -- cgit v0.10.2 From eec77da2744b1265653ab99af91c3b26c49501e9 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Mon, 27 Jan 2014 11:29:53 +0200 Subject: OMAPDSS: DISPC: decimation rounding fix The driver uses DIV_ROUND_UP when calculating decimated width & height. For example, when decimating with 3, the width is calculated as: width = DIV_ROUND_UP(width, decim_x); This yields bad results for some values. For example, 800/3=266.666..., which is rounded to 267. When the input width is set to 267, and pixel increment is set to 3, this causes the dispc to read a line of 801 pixels, i.e. it reads a wrong pixel at the end of the line. Even more pressing, the above rounding causes a BUG() in pixinc(), as the value of 801 is used to calculate row increment, leading to a bad value being passed to pixinc(). This patch fixes the decimation by removing the DIV_ROUND_UP()s when calculating width and height for decimation. Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index bbeb8dd..77d6221 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -2160,8 +2160,8 @@ static int dispc_ovl_calc_scaling_24xx(unsigned long pclk, unsigned long lclk, *five_taps = false; do { - in_height = DIV_ROUND_UP(height, *decim_y); - in_width = DIV_ROUND_UP(width, *decim_x); + in_height = height / *decim_y; + in_width = width / *decim_x; *core_clk = dispc.feat->calc_core_clk(pclk, in_width, in_height, out_width, out_height, mem_to_mem); error = (in_width > maxsinglelinewidth || !*core_clk || @@ -2199,8 +2199,8 @@ static int dispc_ovl_calc_scaling_34xx(unsigned long pclk, unsigned long lclk, dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH); do { - in_height = DIV_ROUND_UP(height, *decim_y); - in_width = DIV_ROUND_UP(width, *decim_x); + in_height = height / *decim_y; + in_width = width / *decim_x; *five_taps = in_height > out_height; if (in_width > maxsinglelinewidth) @@ -2268,7 +2268,7 @@ static int dispc_ovl_calc_scaling_44xx(unsigned long pclk, unsigned long lclk, { u16 in_width, in_width_max; int decim_x_min = *decim_x; - u16 in_height = DIV_ROUND_UP(height, *decim_y); + u16 in_height = height / *decim_y; const int maxsinglelinewidth = dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH); const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE); @@ -2287,7 +2287,7 @@ static int dispc_ovl_calc_scaling_44xx(unsigned long pclk, unsigned long lclk, return -EINVAL; do { - in_width = DIV_ROUND_UP(width, *decim_x); + in_width = width / *decim_x; } while (*decim_x <= *x_predecim && in_width > maxsinglelinewidth && ++*decim_x); @@ -2466,8 +2466,8 @@ static int dispc_ovl_setup_common(enum omap_plane plane, if (r) return r; - in_width = DIV_ROUND_UP(in_width, x_predecim); - in_height = DIV_ROUND_UP(in_height, y_predecim); + in_width = in_width / x_predecim; + in_height = in_height / y_predecim; if (color_mode == OMAP_DSS_COLOR_YUV2 || color_mode == OMAP_DSS_COLOR_UYVY || -- cgit v0.10.2 From c56812fc855e29f44aeb5e166d2b512dab0a3e26 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 28 Jan 2014 08:50:47 +0200 Subject: OMAPDSS: fix fck field types 'fck' field in dpi and sdi clock calculation struct is 'unsigned long long', even though it should be 'unsigned long'. This hasn't caused any issues so far. Fix the field's type. Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c index 7411f26..23ef21f 100644 --- a/drivers/video/omap2/dss/dpi.c +++ b/drivers/video/omap2/dss/dpi.c @@ -117,7 +117,7 @@ struct dpi_clk_calc_ctx { /* outputs */ struct dsi_clock_info dsi_cinfo; - unsigned long long fck; + unsigned long fck; struct dispc_clock_info dispc_cinfo; }; diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c index efb9ee9..ba806c9 100644 --- a/drivers/video/omap2/dss/sdi.c +++ b/drivers/video/omap2/dss/sdi.c @@ -46,7 +46,7 @@ static struct { struct sdi_clk_calc_ctx { unsigned long pck_min, pck_max; - unsigned long long fck; + unsigned long fck; struct dispc_clock_info dispc_cinfo; }; -- cgit v0.10.2 From 97253eeeb792d61ed22d397cfa236bd0311e4caf Mon Sep 17 00:00:00 2001 From: David Vrabel Date: Wed, 5 Feb 2014 14:13:10 +0000 Subject: xen/events: bind all new interdomain events to VCPU0 Commit fc087e10734a4d3e40693fc099461ec1270b3fff (xen/events: remove unnecessary init_evtchn_cpu_bindings()) causes a regression. The kernel-side VCPU binding was not being correctly set for newly allocated or bound interdomain events. In ARM guests where 2-level events were used, this would result in no interdomain events being handled because the kernel-side VCPU masks would all be clear. x86 guests would work because the irq affinity was set during irq setup and this would set the correct kernel-side VCPU binding. Fix this by properly initializing the kernel-side VCPU binding in bind_evtchn_to_irq(). Reported-and-tested-by: Julien Grall Signed-off-by: David Vrabel Signed-off-by: Konrad Rzeszutek Wilk diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c index 4672e00..f4a9e33 100644 --- a/drivers/xen/events/events_base.c +++ b/drivers/xen/events/events_base.c @@ -862,6 +862,8 @@ int bind_evtchn_to_irq(unsigned int evtchn) irq = ret; goto out; } + /* New interdomain events are bound to VCPU 0. */ + bind_evtchn_to_cpu(evtchn, 0); } else { struct irq_info *info = info_for_irq(irq); WARN_ON(info == NULL || info->type != IRQT_EVTCHN); -- cgit v0.10.2 From 564eb714f5f09ac733c26860d5f0831f213fbdf1 Mon Sep 17 00:00:00 2001 From: David Vrabel Date: Mon, 10 Feb 2014 13:54:02 +0000 Subject: xen: install xen/gntdev.h and xen/gntalloc.h xen/gntdev.h and xen/gntalloc.h both provide userspace ABIs so they should be installed. CC: stable@vger.kernel.org Signed-off-by: David Vrabel Signed-off-by: Konrad Rzeszutek Wilk diff --git a/include/uapi/xen/Kbuild b/include/uapi/xen/Kbuild index 61257cb..5c45962 100644 --- a/include/uapi/xen/Kbuild +++ b/include/uapi/xen/Kbuild @@ -1,3 +1,5 @@ # UAPI Header export list header-y += evtchn.h +header-y += gntalloc.h +header-y += gntdev.h header-y += privcmd.h diff --git a/include/uapi/xen/gntalloc.h b/include/uapi/xen/gntalloc.h new file mode 100644 index 0000000..76bd580 --- /dev/null +++ b/include/uapi/xen/gntalloc.h @@ -0,0 +1,82 @@ +/****************************************************************************** + * gntalloc.h + * + * Interface to /dev/xen/gntalloc. + * + * Author: Daniel De Graaf + * + * This file is in the public domain. + */ + +#ifndef __LINUX_PUBLIC_GNTALLOC_H__ +#define __LINUX_PUBLIC_GNTALLOC_H__ + +/* + * Allocates a new page and creates a new grant reference. + */ +#define IOCTL_GNTALLOC_ALLOC_GREF \ +_IOC(_IOC_NONE, 'G', 5, sizeof(struct ioctl_gntalloc_alloc_gref)) +struct ioctl_gntalloc_alloc_gref { + /* IN parameters */ + /* The ID of the domain to be given access to the grants. */ + uint16_t domid; + /* Flags for this mapping */ + uint16_t flags; + /* Number of pages to map */ + uint32_t count; + /* OUT parameters */ + /* The offset to be used on a subsequent call to mmap(). */ + uint64_t index; + /* The grant references of the newly created grant, one per page */ + /* Variable size, depending on count */ + uint32_t gref_ids[1]; +}; + +#define GNTALLOC_FLAG_WRITABLE 1 + +/* + * Deallocates the grant reference, allowing the associated page to be freed if + * no other domains are using it. + */ +#define IOCTL_GNTALLOC_DEALLOC_GREF \ +_IOC(_IOC_NONE, 'G', 6, sizeof(struct ioctl_gntalloc_dealloc_gref)) +struct ioctl_gntalloc_dealloc_gref { + /* IN parameters */ + /* The offset returned in the map operation */ + uint64_t index; + /* Number of references to unmap */ + uint32_t count; +}; + +/* + * Sets up an unmap notification within the page, so that the other side can do + * cleanup if this side crashes. Required to implement cross-domain robust + * mutexes or close notification on communication channels. + * + * Each mapped page only supports one notification; multiple calls referring to + * the same page overwrite the previous notification. You must clear the + * notification prior to the IOCTL_GNTALLOC_DEALLOC_GREF if you do not want it + * to occur. + */ +#define IOCTL_GNTALLOC_SET_UNMAP_NOTIFY \ +_IOC(_IOC_NONE, 'G', 7, sizeof(struct ioctl_gntalloc_unmap_notify)) +struct ioctl_gntalloc_unmap_notify { + /* IN parameters */ + /* Offset in the file descriptor for a byte within the page (same as + * used in mmap). If using UNMAP_NOTIFY_CLEAR_BYTE, this is the byte to + * be cleared. Otherwise, it can be any byte in the page whose + * notification we are adjusting. + */ + uint64_t index; + /* Action(s) to take on unmap */ + uint32_t action; + /* Event channel to notify */ + uint32_t event_channel_port; +}; + +/* Clear (set to zero) the byte specified by index */ +#define UNMAP_NOTIFY_CLEAR_BYTE 0x1 +/* Send an interrupt on the indicated event channel */ +#define UNMAP_NOTIFY_SEND_EVENT 0x2 + +#endif /* __LINUX_PUBLIC_GNTALLOC_H__ */ diff --git a/include/uapi/xen/gntdev.h b/include/uapi/xen/gntdev.h new file mode 100644 index 0000000..5304bd3 --- /dev/null +++ b/include/uapi/xen/gntdev.h @@ -0,0 +1,150 @@ +/****************************************************************************** + * gntdev.h + * + * Interface to /dev/xen/gntdev. + * + * Copyright (c) 2007, D G Murray + * + * 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; or, when distributed + * separately from the Linux kernel or incorporated into other + * software packages, subject to the following license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this source file (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 + * AUTHORS OR COPYRIGHT HOLDERS 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. + */ + +#ifndef __LINUX_PUBLIC_GNTDEV_H__ +#define __LINUX_PUBLIC_GNTDEV_H__ + +struct ioctl_gntdev_grant_ref { + /* The domain ID of the grant to be mapped. */ + uint32_t domid; + /* The grant reference of the grant to be mapped. */ + uint32_t ref; +}; + +/* + * Inserts the grant references into the mapping table of an instance + * of gntdev. N.B. This does not perform the mapping, which is deferred + * until mmap() is called with @index as the offset. + */ +#define IOCTL_GNTDEV_MAP_GRANT_REF \ +_IOC(_IOC_NONE, 'G', 0, sizeof(struct ioctl_gntdev_map_grant_ref)) +struct ioctl_gntdev_map_grant_ref { + /* IN parameters */ + /* The number of grants to be mapped. */ + uint32_t count; + uint32_t pad; + /* OUT parameters */ + /* The offset to be used on a subsequent call to mmap(). */ + uint64_t index; + /* Variable IN parameter. */ + /* Array of grant references, of size @count. */ + struct ioctl_gntdev_grant_ref refs[1]; +}; + +/* + * Removes the grant references from the mapping table of an instance of + * of gntdev. N.B. munmap() must be called on the relevant virtual address(es) + * before this ioctl is called, or an error will result. + */ +#define IOCTL_GNTDEV_UNMAP_GRANT_REF \ +_IOC(_IOC_NONE, 'G', 1, sizeof(struct ioctl_gntdev_unmap_grant_ref)) +struct ioctl_gntdev_unmap_grant_ref { + /* IN parameters */ + /* The offset was returned by the corresponding map operation. */ + uint64_t index; + /* The number of pages to be unmapped. */ + uint32_t count; + uint32_t pad; +}; + +/* + * Returns the offset in the driver's address space that corresponds + * to @vaddr. This can be used to perform a munmap(), followed by an + * UNMAP_GRANT_REF ioctl, where no state about the offset is retained by + * the caller. The number of pages that were allocated at the same time as + * @vaddr is returned in @count. + * + * N.B. Where more than one page has been mapped into a contiguous range, the + * supplied @vaddr must correspond to the start of the range; otherwise + * an error will result. It is only possible to munmap() the entire + * contiguously-allocated range at once, and not any subrange thereof. + */ +#define IOCTL_GNTDEV_GET_OFFSET_FOR_VADDR \ +_IOC(_IOC_NONE, 'G', 2, sizeof(struct ioctl_gntdev_get_offset_for_vaddr)) +struct ioctl_gntdev_get_offset_for_vaddr { + /* IN parameters */ + /* The virtual address of the first mapped page in a range. */ + uint64_t vaddr; + /* OUT parameters */ + /* The offset that was used in the initial mmap() operation. */ + uint64_t offset; + /* The number of pages mapped in the VM area that begins at @vaddr. */ + uint32_t count; + uint32_t pad; +}; + +/* + * Sets the maximum number of grants that may mapped at once by this gntdev + * instance. + * + * N.B. This must be called before any other ioctl is performed on the device. + */ +#define IOCTL_GNTDEV_SET_MAX_GRANTS \ +_IOC(_IOC_NONE, 'G', 3, sizeof(struct ioctl_gntdev_set_max_grants)) +struct ioctl_gntdev_set_max_grants { + /* IN parameter */ + /* The maximum number of grants that may be mapped at once. */ + uint32_t count; +}; + +/* + * Sets up an unmap notification within the page, so that the other side can do + * cleanup if this side crashes. Required to implement cross-domain robust + * mutexes or close notification on communication channels. + * + * Each mapped page only supports one notification; multiple calls referring to + * the same page overwrite the previous notification. You must clear the + * notification prior to the IOCTL_GNTALLOC_DEALLOC_GREF if you do not want it + * to occur. + */ +#define IOCTL_GNTDEV_SET_UNMAP_NOTIFY \ +_IOC(_IOC_NONE, 'G', 7, sizeof(struct ioctl_gntdev_unmap_notify)) +struct ioctl_gntdev_unmap_notify { + /* IN parameters */ + /* Offset in the file descriptor for a byte within the page (same as + * used in mmap). If using UNMAP_NOTIFY_CLEAR_BYTE, this is the byte to + * be cleared. Otherwise, it can be any byte in the page whose + * notification we are adjusting. + */ + uint64_t index; + /* Action(s) to take on unmap */ + uint32_t action; + /* Event channel to notify */ + uint32_t event_channel_port; +}; + +/* Clear (set to zero) the byte specified by index */ +#define UNMAP_NOTIFY_CLEAR_BYTE 0x1 +/* Send an interrupt on the indicated event channel */ +#define UNMAP_NOTIFY_SEND_EVENT 0x2 + +#endif /* __LINUX_PUBLIC_GNTDEV_H__ */ diff --git a/include/xen/gntalloc.h b/include/xen/gntalloc.h deleted file mode 100644 index 76bd580..0000000 --- a/include/xen/gntalloc.h +++ /dev/null @@ -1,82 +0,0 @@ -/****************************************************************************** - * gntalloc.h - * - * Interface to /dev/xen/gntalloc. - * - * Author: Daniel De Graaf - * - * This file is in the public domain. - */ - -#ifndef __LINUX_PUBLIC_GNTALLOC_H__ -#define __LINUX_PUBLIC_GNTALLOC_H__ - -/* - * Allocates a new page and creates a new grant reference. - */ -#define IOCTL_GNTALLOC_ALLOC_GREF \ -_IOC(_IOC_NONE, 'G', 5, sizeof(struct ioctl_gntalloc_alloc_gref)) -struct ioctl_gntalloc_alloc_gref { - /* IN parameters */ - /* The ID of the domain to be given access to the grants. */ - uint16_t domid; - /* Flags for this mapping */ - uint16_t flags; - /* Number of pages to map */ - uint32_t count; - /* OUT parameters */ - /* The offset to be used on a subsequent call to mmap(). */ - uint64_t index; - /* The grant references of the newly created grant, one per page */ - /* Variable size, depending on count */ - uint32_t gref_ids[1]; -}; - -#define GNTALLOC_FLAG_WRITABLE 1 - -/* - * Deallocates the grant reference, allowing the associated page to be freed if - * no other domains are using it. - */ -#define IOCTL_GNTALLOC_DEALLOC_GREF \ -_IOC(_IOC_NONE, 'G', 6, sizeof(struct ioctl_gntalloc_dealloc_gref)) -struct ioctl_gntalloc_dealloc_gref { - /* IN parameters */ - /* The offset returned in the map operation */ - uint64_t index; - /* Number of references to unmap */ - uint32_t count; -}; - -/* - * Sets up an unmap notification within the page, so that the other side can do - * cleanup if this side crashes. Required to implement cross-domain robust - * mutexes or close notification on communication channels. - * - * Each mapped page only supports one notification; multiple calls referring to - * the same page overwrite the previous notification. You must clear the - * notification prior to the IOCTL_GNTALLOC_DEALLOC_GREF if you do not want it - * to occur. - */ -#define IOCTL_GNTALLOC_SET_UNMAP_NOTIFY \ -_IOC(_IOC_NONE, 'G', 7, sizeof(struct ioctl_gntalloc_unmap_notify)) -struct ioctl_gntalloc_unmap_notify { - /* IN parameters */ - /* Offset in the file descriptor for a byte within the page (same as - * used in mmap). If using UNMAP_NOTIFY_CLEAR_BYTE, this is the byte to - * be cleared. Otherwise, it can be any byte in the page whose - * notification we are adjusting. - */ - uint64_t index; - /* Action(s) to take on unmap */ - uint32_t action; - /* Event channel to notify */ - uint32_t event_channel_port; -}; - -/* Clear (set to zero) the byte specified by index */ -#define UNMAP_NOTIFY_CLEAR_BYTE 0x1 -/* Send an interrupt on the indicated event channel */ -#define UNMAP_NOTIFY_SEND_EVENT 0x2 - -#endif /* __LINUX_PUBLIC_GNTALLOC_H__ */ diff --git a/include/xen/gntdev.h b/include/xen/gntdev.h deleted file mode 100644 index 5304bd3..0000000 --- a/include/xen/gntdev.h +++ /dev/null @@ -1,150 +0,0 @@ -/****************************************************************************** - * gntdev.h - * - * Interface to /dev/xen/gntdev. - * - * Copyright (c) 2007, D G Murray - * - * 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; or, when distributed - * separately from the Linux kernel or incorporated into other - * software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (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 - * AUTHORS OR COPYRIGHT HOLDERS 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. - */ - -#ifndef __LINUX_PUBLIC_GNTDEV_H__ -#define __LINUX_PUBLIC_GNTDEV_H__ - -struct ioctl_gntdev_grant_ref { - /* The domain ID of the grant to be mapped. */ - uint32_t domid; - /* The grant reference of the grant to be mapped. */ - uint32_t ref; -}; - -/* - * Inserts the grant references into the mapping table of an instance - * of gntdev. N.B. This does not perform the mapping, which is deferred - * until mmap() is called with @index as the offset. - */ -#define IOCTL_GNTDEV_MAP_GRANT_REF \ -_IOC(_IOC_NONE, 'G', 0, sizeof(struct ioctl_gntdev_map_grant_ref)) -struct ioctl_gntdev_map_grant_ref { - /* IN parameters */ - /* The number of grants to be mapped. */ - uint32_t count; - uint32_t pad; - /* OUT parameters */ - /* The offset to be used on a subsequent call to mmap(). */ - uint64_t index; - /* Variable IN parameter. */ - /* Array of grant references, of size @count. */ - struct ioctl_gntdev_grant_ref refs[1]; -}; - -/* - * Removes the grant references from the mapping table of an instance of - * of gntdev. N.B. munmap() must be called on the relevant virtual address(es) - * before this ioctl is called, or an error will result. - */ -#define IOCTL_GNTDEV_UNMAP_GRANT_REF \ -_IOC(_IOC_NONE, 'G', 1, sizeof(struct ioctl_gntdev_unmap_grant_ref)) -struct ioctl_gntdev_unmap_grant_ref { - /* IN parameters */ - /* The offset was returned by the corresponding map operation. */ - uint64_t index; - /* The number of pages to be unmapped. */ - uint32_t count; - uint32_t pad; -}; - -/* - * Returns the offset in the driver's address space that corresponds - * to @vaddr. This can be used to perform a munmap(), followed by an - * UNMAP_GRANT_REF ioctl, where no state about the offset is retained by - * the caller. The number of pages that were allocated at the same time as - * @vaddr is returned in @count. - * - * N.B. Where more than one page has been mapped into a contiguous range, the - * supplied @vaddr must correspond to the start of the range; otherwise - * an error will result. It is only possible to munmap() the entire - * contiguously-allocated range at once, and not any subrange thereof. - */ -#define IOCTL_GNTDEV_GET_OFFSET_FOR_VADDR \ -_IOC(_IOC_NONE, 'G', 2, sizeof(struct ioctl_gntdev_get_offset_for_vaddr)) -struct ioctl_gntdev_get_offset_for_vaddr { - /* IN parameters */ - /* The virtual address of the first mapped page in a range. */ - uint64_t vaddr; - /* OUT parameters */ - /* The offset that was used in the initial mmap() operation. */ - uint64_t offset; - /* The number of pages mapped in the VM area that begins at @vaddr. */ - uint32_t count; - uint32_t pad; -}; - -/* - * Sets the maximum number of grants that may mapped at once by this gntdev - * instance. - * - * N.B. This must be called before any other ioctl is performed on the device. - */ -#define IOCTL_GNTDEV_SET_MAX_GRANTS \ -_IOC(_IOC_NONE, 'G', 3, sizeof(struct ioctl_gntdev_set_max_grants)) -struct ioctl_gntdev_set_max_grants { - /* IN parameter */ - /* The maximum number of grants that may be mapped at once. */ - uint32_t count; -}; - -/* - * Sets up an unmap notification within the page, so that the other side can do - * cleanup if this side crashes. Required to implement cross-domain robust - * mutexes or close notification on communication channels. - * - * Each mapped page only supports one notification; multiple calls referring to - * the same page overwrite the previous notification. You must clear the - * notification prior to the IOCTL_GNTALLOC_DEALLOC_GREF if you do not want it - * to occur. - */ -#define IOCTL_GNTDEV_SET_UNMAP_NOTIFY \ -_IOC(_IOC_NONE, 'G', 7, sizeof(struct ioctl_gntdev_unmap_notify)) -struct ioctl_gntdev_unmap_notify { - /* IN parameters */ - /* Offset in the file descriptor for a byte within the page (same as - * used in mmap). If using UNMAP_NOTIFY_CLEAR_BYTE, this is the byte to - * be cleared. Otherwise, it can be any byte in the page whose - * notification we are adjusting. - */ - uint64_t index; - /* Action(s) to take on unmap */ - uint32_t action; - /* Event channel to notify */ - uint32_t event_channel_port; -}; - -/* Clear (set to zero) the byte specified by index */ -#define UNMAP_NOTIFY_CLEAR_BYTE 0x1 -/* Send an interrupt on the indicated event channel */ -#define UNMAP_NOTIFY_SEND_EVENT 0x2 - -#endif /* __LINUX_PUBLIC_GNTDEV_H__ */ -- cgit v0.10.2 From d8320b2d2e7d1cda8216d496c7c685c5fdf74ff0 Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Sat, 8 Feb 2014 23:35:43 +0100 Subject: ia64/xen: Remove Xen support for ia64 even more Commit d52eefb47d4e ("ia64/xen: Remove Xen support for ia64") removed the Kconfig symbol XEN_XENCOMM. But it didn't remove the code depending on that symbol. Remove that code now. Signed-off-by: Paul Bolle Acked-by: David Vrabel Signed-off-by: Konrad Rzeszutek Wilk diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile index d75c811..45e00af 100644 --- a/drivers/xen/Makefile +++ b/drivers/xen/Makefile @@ -16,7 +16,6 @@ xen-pad-$(CONFIG_X86) += xen-acpi-pad.o dom0-$(CONFIG_X86) += pcpu.o obj-$(CONFIG_XEN_DOM0) += $(dom0-y) obj-$(CONFIG_BLOCK) += biomerge.o -obj-$(CONFIG_XEN_XENCOMM) += xencomm.o obj-$(CONFIG_XEN_BALLOON) += xen-balloon.o obj-$(CONFIG_XEN_SELFBALLOONING) += xen-selfballoon.o obj-$(CONFIG_XEN_DEV_EVTCHN) += xen-evtchn.o diff --git a/drivers/xen/xencomm.c b/drivers/xen/xencomm.c deleted file mode 100644 index 4793fc5..0000000 --- a/drivers/xen/xencomm.c +++ /dev/null @@ -1,219 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Copyright (C) IBM Corp. 2006 - * - * Authors: Hollis Blanchard - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include /* for xencomm_is_phys_contiguous() */ - -static int xencomm_init(struct xencomm_desc *desc, - void *buffer, unsigned long bytes) -{ - unsigned long recorded = 0; - int i = 0; - - while ((recorded < bytes) && (i < desc->nr_addrs)) { - unsigned long vaddr = (unsigned long)buffer + recorded; - unsigned long paddr; - int offset; - int chunksz; - - offset = vaddr % PAGE_SIZE; /* handle partial pages */ - chunksz = min(PAGE_SIZE - offset, bytes - recorded); - - paddr = xencomm_vtop(vaddr); - if (paddr == ~0UL) { - printk(KERN_DEBUG "%s: couldn't translate vaddr %lx\n", - __func__, vaddr); - return -EINVAL; - } - - desc->address[i++] = paddr; - recorded += chunksz; - } - - if (recorded < bytes) { - printk(KERN_DEBUG - "%s: could only translate %ld of %ld bytes\n", - __func__, recorded, bytes); - return -ENOSPC; - } - - /* mark remaining addresses invalid (just for safety) */ - while (i < desc->nr_addrs) - desc->address[i++] = XENCOMM_INVALID; - - desc->magic = XENCOMM_MAGIC; - - return 0; -} - -static struct xencomm_desc *xencomm_alloc(gfp_t gfp_mask, - void *buffer, unsigned long bytes) -{ - struct xencomm_desc *desc; - unsigned long buffer_ulong = (unsigned long)buffer; - unsigned long start = buffer_ulong & PAGE_MASK; - unsigned long end = (buffer_ulong + bytes) | ~PAGE_MASK; - unsigned long nr_addrs = (end - start + 1) >> PAGE_SHIFT; - unsigned long size = sizeof(*desc) + - sizeof(desc->address[0]) * nr_addrs; - - /* - * slab allocator returns at least sizeof(void*) aligned pointer. - * When sizeof(*desc) > sizeof(void*), struct xencomm_desc might - * cross page boundary. - */ - if (sizeof(*desc) > sizeof(void *)) { - unsigned long order = get_order(size); - desc = (struct xencomm_desc *)__get_free_pages(gfp_mask, - order); - if (desc == NULL) - return NULL; - - desc->nr_addrs = - ((PAGE_SIZE << order) - sizeof(struct xencomm_desc)) / - sizeof(*desc->address); - } else { - desc = kmalloc(size, gfp_mask); - if (desc == NULL) - return NULL; - - desc->nr_addrs = nr_addrs; - } - return desc; -} - -void xencomm_free(struct xencomm_handle *desc) -{ - if (desc && !((ulong)desc & XENCOMM_INLINE_FLAG)) { - struct xencomm_desc *desc__ = (struct xencomm_desc *)desc; - if (sizeof(*desc__) > sizeof(void *)) { - unsigned long size = sizeof(*desc__) + - sizeof(desc__->address[0]) * desc__->nr_addrs; - unsigned long order = get_order(size); - free_pages((unsigned long)__va(desc), order); - } else - kfree(__va(desc)); - } -} - -static int xencomm_create(void *buffer, unsigned long bytes, - struct xencomm_desc **ret, gfp_t gfp_mask) -{ - struct xencomm_desc *desc; - int rc; - - pr_debug("%s: %p[%ld]\n", __func__, buffer, bytes); - - if (bytes == 0) { - /* don't create a descriptor; Xen recognizes NULL. */ - BUG_ON(buffer != NULL); - *ret = NULL; - return 0; - } - - BUG_ON(buffer == NULL); /* 'bytes' is non-zero */ - - desc = xencomm_alloc(gfp_mask, buffer, bytes); - if (!desc) { - printk(KERN_DEBUG "%s failure\n", "xencomm_alloc"); - return -ENOMEM; - } - - rc = xencomm_init(desc, buffer, bytes); - if (rc) { - printk(KERN_DEBUG "%s failure: %d\n", "xencomm_init", rc); - xencomm_free((struct xencomm_handle *)__pa(desc)); - return rc; - } - - *ret = desc; - return 0; -} - -static struct xencomm_handle *xencomm_create_inline(void *ptr) -{ - unsigned long paddr; - - BUG_ON(!xencomm_is_phys_contiguous((unsigned long)ptr)); - - paddr = (unsigned long)xencomm_pa(ptr); - BUG_ON(paddr & XENCOMM_INLINE_FLAG); - return (struct xencomm_handle *)(paddr | XENCOMM_INLINE_FLAG); -} - -/* "mini" routine, for stack-based communications: */ -static int xencomm_create_mini(void *buffer, - unsigned long bytes, struct xencomm_mini *xc_desc, - struct xencomm_desc **ret) -{ - int rc = 0; - struct xencomm_desc *desc; - BUG_ON(((unsigned long)xc_desc) % sizeof(*xc_desc) != 0); - - desc = (void *)xc_desc; - - desc->nr_addrs = XENCOMM_MINI_ADDRS; - - rc = xencomm_init(desc, buffer, bytes); - if (!rc) - *ret = desc; - - return rc; -} - -struct xencomm_handle *xencomm_map(void *ptr, unsigned long bytes) -{ - int rc; - struct xencomm_desc *desc; - - if (xencomm_is_phys_contiguous((unsigned long)ptr)) - return xencomm_create_inline(ptr); - - rc = xencomm_create(ptr, bytes, &desc, GFP_KERNEL); - - if (rc || desc == NULL) - return NULL; - - return xencomm_pa(desc); -} - -struct xencomm_handle *__xencomm_map_no_alloc(void *ptr, unsigned long bytes, - struct xencomm_mini *xc_desc) -{ - int rc; - struct xencomm_desc *desc = NULL; - - if (xencomm_is_phys_contiguous((unsigned long)ptr)) - return xencomm_create_inline(ptr); - - rc = xencomm_create_mini(ptr, bytes, xc_desc, - &desc); - - if (rc) - return NULL; - - return xencomm_pa(desc); -} diff --git a/include/xen/interface/xencomm.h b/include/xen/interface/xencomm.h deleted file mode 100644 index ac45e07..0000000 --- a/include/xen/interface/xencomm.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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 - * AUTHORS OR COPYRIGHT HOLDERS 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. - * - * Copyright (C) IBM Corp. 2006 - */ - -#ifndef _XEN_XENCOMM_H_ -#define _XEN_XENCOMM_H_ - -/* A xencomm descriptor is a scatter/gather list containing physical - * addresses corresponding to a virtually contiguous memory area. The - * hypervisor translates these physical addresses to machine addresses to copy - * to and from the virtually contiguous area. - */ - -#define XENCOMM_MAGIC 0x58434F4D /* 'XCOM' */ -#define XENCOMM_INVALID (~0UL) - -struct xencomm_desc { - uint32_t magic; - uint32_t nr_addrs; /* the number of entries in address[] */ - uint64_t address[0]; -}; - -#endif /* _XEN_XENCOMM_H_ */ diff --git a/include/xen/xencomm.h b/include/xen/xencomm.h deleted file mode 100644 index e43b039..0000000 --- a/include/xen/xencomm.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Copyright (C) IBM Corp. 2006 - * - * Authors: Hollis Blanchard - * Jerone Young - */ - -#ifndef _LINUX_XENCOMM_H_ -#define _LINUX_XENCOMM_H_ - -#include - -#define XENCOMM_MINI_ADDRS 3 -struct xencomm_mini { - struct xencomm_desc _desc; - uint64_t address[XENCOMM_MINI_ADDRS]; -}; - -/* To avoid additionnal virt to phys conversion, an opaque structure is - presented. */ -struct xencomm_handle; - -extern void xencomm_free(struct xencomm_handle *desc); -extern struct xencomm_handle *xencomm_map(void *ptr, unsigned long bytes); -extern struct xencomm_handle *__xencomm_map_no_alloc(void *ptr, - unsigned long bytes, struct xencomm_mini *xc_area); - -#if 0 -#define XENCOMM_MINI_ALIGNED(xc_desc, n) \ - struct xencomm_mini xc_desc ## _base[(n)] \ - __attribute__((__aligned__(sizeof(struct xencomm_mini)))); \ - struct xencomm_mini *xc_desc = &xc_desc ## _base[0]; -#else -/* - * gcc bug workaround: - * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=16660 - * gcc doesn't handle properly stack variable with - * __attribute__((__align__(sizeof(struct xencomm_mini)))) - */ -#define XENCOMM_MINI_ALIGNED(xc_desc, n) \ - unsigned char xc_desc ## _base[((n) + 1 ) * \ - sizeof(struct xencomm_mini)]; \ - struct xencomm_mini *xc_desc = (struct xencomm_mini *) \ - ((unsigned long)xc_desc ## _base + \ - (sizeof(struct xencomm_mini) - \ - ((unsigned long)xc_desc ## _base) % \ - sizeof(struct xencomm_mini))); -#endif -#define xencomm_map_no_alloc(ptr, bytes) \ - ({ XENCOMM_MINI_ALIGNED(xc_desc, 1); \ - __xencomm_map_no_alloc(ptr, bytes, xc_desc); }) - -/* provided by architecture code: */ -extern unsigned long xencomm_vtop(unsigned long vaddr); - -static inline void *xencomm_pa(void *ptr) -{ - return (void *)xencomm_vtop((unsigned long)ptr); -} - -#define xen_guest_handle(hnd) ((hnd).p) - -#endif /* _LINUX_XENCOMM_H_ */ -- cgit v0.10.2 From 8423ae3d7a3cfe084865262cfaeba1359d405182 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Mon, 10 Feb 2014 17:45:50 -0800 Subject: block: Fix cloning of discard/write same bios Immutable biovecs changed the way bio segments are treated in such a way that bio_for_each_segment() cannot now do what we want for discard/write same bios, since bi_size means something completely different for them. Fortunately discard and write same bios never have more than a single biovec, so bio_for_each_segment() is unnecessary and not terribly meaningful for them, but we still have to special case them in a few places. Signed-off-by: Kent Overstreet Tested-by: Richard W.M. Jones Signed-off-by: Jens Axboe diff --git a/fs/bio.c b/fs/bio.c index 75c49a3..8754e7b 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -611,7 +611,6 @@ EXPORT_SYMBOL(bio_clone_fast); struct bio *bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask, struct bio_set *bs) { - unsigned nr_iovecs = 0; struct bvec_iter iter; struct bio_vec bv; struct bio *bio; @@ -638,10 +637,7 @@ struct bio *bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask, * __bio_clone_fast() anyways. */ - bio_for_each_segment(bv, bio_src, iter) - nr_iovecs++; - - bio = bio_alloc_bioset(gfp_mask, nr_iovecs, bs); + bio = bio_alloc_bioset(gfp_mask, bio_segments(bio_src), bs); if (!bio) return NULL; @@ -650,9 +646,18 @@ struct bio *bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask, bio->bi_iter.bi_sector = bio_src->bi_iter.bi_sector; bio->bi_iter.bi_size = bio_src->bi_iter.bi_size; + if (bio->bi_rw & REQ_DISCARD) + goto integrity_clone; + + if (bio->bi_rw & REQ_WRITE_SAME) { + bio->bi_io_vec[bio->bi_vcnt++] = bio_src->bi_io_vec[0]; + goto integrity_clone; + } + bio_for_each_segment(bv, bio_src, iter) bio->bi_io_vec[bio->bi_vcnt++] = bv; +integrity_clone: if (bio_integrity(bio_src)) { int ret; diff --git a/include/linux/bio.h b/include/linux/bio.h index d6791bb..5a4d39b 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -250,6 +250,17 @@ static inline unsigned bio_segments(struct bio *bio) struct bio_vec bv; struct bvec_iter iter; + /* + * We special case discard/write same, because they interpret bi_size + * differently: + */ + + if (bio->bi_rw & REQ_DISCARD) + return 1; + + if (bio->bi_rw & REQ_WRITE_SAME) + return 1; + bio_for_each_segment(bv, bio, iter) segs++; -- cgit v0.10.2 From 1e93b8c274268038c93763dca65a73b42a081e10 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 11 Feb 2014 08:27:13 -0800 Subject: blk-mq: dont assume rq->errors is set when returning an error from ->queue_rq rq->errors never has been part of the communication protocol between drivers and the block stack and most drivers will not have initialized it. Return -EIO to upper layers when the driver returns BLK_MQ_RQ_QUEUE_ERROR unconditionally. If a driver want to return a different error it can easily do so by returning success after calling blk_mq_end_io itself. Signed-off-by: Christoph Hellwig Signed-off-by: Jens Axboe diff --git a/block/blk-mq.c b/block/blk-mq.c index a59b056..0480710 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -605,8 +605,8 @@ static void __blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx) break; default: pr_err("blk-mq: bad return on queue: %d\n", ret); - rq->errors = -EIO; case BLK_MQ_RQ_QUEUE_ERROR: + rq->errors = -EIO; blk_mq_end_io(rq, rq->errors); break; } -- cgit v0.10.2 From 49f5baa5109897b8cee491e8a7c4d74052b6bc1e Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 11 Feb 2014 08:27:14 -0800 Subject: blk-mq: pair blk_mq_start_request / blk_mq_requeue_request Make sure we have a proper pairing between starting and requeueing requests. Move the dma drain and REQ_END setup into blk_mq_start_request, and make sure blk_mq_requeue_request properly undoes them, giving us a pair of function to prepare and unprepare a request without leaving side effects. Together this ensures we always clean up properly after BLK_MQ_RQ_QUEUE_BUSY returns from ->queue_rq. Signed-off-by: Christoph Hellwig Signed-off-by: Jens Axboe diff --git a/block/blk-mq.c b/block/blk-mq.c index 0480710..1fa9dd1 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -377,7 +377,7 @@ void blk_mq_complete_request(struct request *rq) } EXPORT_SYMBOL(blk_mq_complete_request); -static void blk_mq_start_request(struct request *rq) +static void blk_mq_start_request(struct request *rq, bool last) { struct request_queue *q = rq->q; @@ -390,6 +390,25 @@ static void blk_mq_start_request(struct request *rq) */ rq->deadline = jiffies + q->rq_timeout; set_bit(REQ_ATOM_STARTED, &rq->atomic_flags); + + if (q->dma_drain_size && blk_rq_bytes(rq)) { + /* + * Make sure space for the drain appears. We know we can do + * this because max_hw_segments has been adjusted to be one + * fewer than the device can handle. + */ + rq->nr_phys_segments++; + } + + /* + * Flag the last request in the series so that drivers know when IO + * should be kicked off, if they don't do it on a per-request basis. + * + * Note: the flag isn't the only condition drivers should do kick off. + * If drive is busy, the last request might not have the bit set. + */ + if (last) + rq->cmd_flags |= REQ_END; } static void blk_mq_requeue_request(struct request *rq) @@ -398,6 +417,11 @@ static void blk_mq_requeue_request(struct request *rq) trace_block_rq_requeue(q, rq); clear_bit(REQ_ATOM_STARTED, &rq->atomic_flags); + + rq->cmd_flags &= ~REQ_END; + + if (q->dma_drain_size && blk_rq_bytes(rq)) + rq->nr_phys_segments--; } struct blk_mq_timeout_data { @@ -565,29 +589,8 @@ static void __blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx) rq = list_first_entry(&rq_list, struct request, queuelist); list_del_init(&rq->queuelist); - blk_mq_start_request(rq); - if (q->dma_drain_size && blk_rq_bytes(rq)) { - /* - * make sure space for the drain appears we - * know we can do this because max_hw_segments - * has been adjusted to be one fewer than the - * device can handle - */ - rq->nr_phys_segments++; - } - - /* - * Last request in the series. Flag it as such, this - * enables drivers to know when IO should be kicked off, - * if they don't do it on a per-request basis. - * - * Note: the flag isn't the only condition drivers - * should do kick off. If drive is busy, the last - * request might not have the bit set. - */ - if (list_empty(&rq_list)) - rq->cmd_flags |= REQ_END; + blk_mq_start_request(rq, list_empty(&rq_list)); ret = q->mq_ops->queue_rq(hctx, rq); switch (ret) { -- cgit v0.10.2 From 8858d88a25142544843869f0cd3e6654aa7b4aec Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 11 Feb 2014 14:02:37 +0100 Subject: ARM: ux500: disable msp2 device tree node Commit 70b41abc151f9 "ARM: ux500: move MSP pin control to the device tree" accidentally activated MSP2, giving rise to a boot scroll scream as the kernel attempts to probe a driver for it and fails to obtain DMA channel 14. Fix this up by marking the node disabled again. Acked-by: Lee Jones Signed-off-by: Linus Walleij Signed-off-by: Kevin Hilman diff --git a/arch/arm/boot/dts/ste-href.dtsi b/arch/arm/boot/dts/ste-href.dtsi index 0c1e8d8..6cb9b68 100644 --- a/arch/arm/boot/dts/ste-href.dtsi +++ b/arch/arm/boot/dts/ste-href.dtsi @@ -188,7 +188,6 @@ msp2: msp@80117000 { pinctrl-names = "default"; pinctrl-0 = <&msp2_default_mode>; - status = "okay"; }; msp3: msp@80125000 { -- cgit v0.10.2 From d651aa1d68a2f0a7ee65697b04c6a92f8c0a12f2 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Red Hat)" Date: Tue, 11 Feb 2014 13:38:54 -0500 Subject: ring-buffer: Fix first commit on sub-buffer having non-zero delta Each sub-buffer (buffer page) has a full 64 bit timestamp. The events on that page use a 27 bit delta against that timestamp in order to save on bits written to the ring buffer. If the time between events is larger than what the 27 bits can hold, a "time extend" event is added to hold the entire 64 bit timestamp again and the events after that hold a delta from that timestamp. As a "time extend" is always paired with an event, it is logical to just allocate the event with the time extend, to make things a bit more efficient. Unfortunately, when the pairing code was written, it removed the "delta = 0" from the first commit on a page, causing the events on the page to be slightly skewed. Fixes: 69d1b839f7ee "ring-buffer: Bind time extend and data events together" Cc: stable@vger.kernel.org # 2.6.37+ Signed-off-by: Steven Rostedt diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 294b8a2..fc4da2d 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -2397,6 +2397,13 @@ __rb_reserve_next(struct ring_buffer_per_cpu *cpu_buffer, write &= RB_WRITE_MASK; tail = write - length; + /* + * If this is the first commit on the page, then it has the same + * timestamp as the page itself. + */ + if (!tail) + delta = 0; + /* See if we shot pass the end of this buffer page */ if (unlikely(write > BUF_PAGE_SIZE)) return rb_move_tail(cpu_buffer, length, tail, -- cgit v0.10.2 From 09bdc2d70dedd0fc0358da93bca664c7b11ff907 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Tue, 11 Feb 2014 11:29:05 -0500 Subject: nfsd4: fix acl buffer overrun 4ac7249ea5a0ceef9f8269f63f33cc873c3fac61 "nfsd: use get_acl and ->set_acl" forgets to set the size in the case get_acl() succeeds, so _posix_to_nfsv4_one() can then write past the end of its allocation. Symptoms were slab corruption warnings. Also, some minor cleanup while we're here. (Among other things, note that the first few lines guarantee that pacl is non-NULL.) Signed-off-by: J. Bruce Fields diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c index d3a5871..d190e33 100644 --- a/fs/nfsd/nfs4acl.c +++ b/fs/nfsd/nfs4acl.c @@ -151,17 +151,15 @@ nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry, pacl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL); if (IS_ERR(pacl)) return PTR_ERR(pacl); - /* allocate for worst case: one (deny, allow) pair each: */ - size += 2 * pacl->a_count; } + /* allocate for worst case: one (deny, allow) pair each: */ + size += 2 * pacl->a_count; if (S_ISDIR(inode->i_mode)) { flags = NFS4_ACL_DIR; dpacl = get_acl(inode, ACL_TYPE_DEFAULT); if (dpacl) size += 2 * dpacl->a_count; - } else { - dpacl = NULL; } *acl = nfs4_acl_new(size); @@ -170,8 +168,7 @@ nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry, goto out; } - if (pacl) - _posix_to_nfsv4_one(pacl, *acl, flags & ~NFS4_ACL_TYPE_DEFAULT); + _posix_to_nfsv4_one(pacl, *acl, flags & ~NFS4_ACL_TYPE_DEFAULT); if (dpacl) _posix_to_nfsv4_one(dpacl, *acl, flags | NFS4_ACL_TYPE_DEFAULT); -- cgit v0.10.2 From 3635c7e2d59f7861afa6fa5e87e2a58860ff514d Mon Sep 17 00:00:00 2001 From: Raymond Wanyoike Date: Sun, 9 Feb 2014 11:59:46 +0300 Subject: usb: option: blacklist ZTE MF667 net interface Interface #5 of 19d2:1270 is a net interface which has been submitted to the qmi_wwan driver so consequently remove it from the option driver. Signed-off-by: Raymond Wanyoike Cc: stable Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 5c86f57..216d20a 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -1362,7 +1362,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1267, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1268, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1269, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1270, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1270, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1271, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1272, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1273, 0xff, 0xff, 0xff) }, -- cgit v0.10.2 From ddf5eb564d97c94e114b45e84c89ce0e7024a9ac Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 11 Feb 2014 15:25:24 -0800 Subject: staging/rtl8821ae: fix build, depends on MAC80211 rtl8821ae uses ieee80211 interfaces so it should depend on MAC80211. Fixes these build errors: ERROR: "ieee80211_rx_irqsafe" [drivers/staging/rtl8821ae/rtl8821ae.ko] undefined! ERROR: "ieee80211_beacon_get_tim" [drivers/staging/rtl8821ae/rtl8821ae.ko] undefined! ERROR: "ieee80211_unregister_hw" [drivers/staging/rtl8821ae/rtl8821ae.ko] undefined! ERROR: "rate_control_send_low" [drivers/staging/rtl8821ae/rtl8821ae.ko] undefined! ERROR: "ieee80211_stop_queue" [drivers/staging/rtl8821ae/rtl8821ae.ko] undefined! ERROR: "ieee80211_rate_control_register" [drivers/staging/rtl8821ae/rtl8821ae.ko] undefined! ERROR: "wiphy_to_ieee80211_hw" [drivers/staging/rtl8821ae/rtl8821ae.ko] undefined! ERROR: "ieee80211_stop_tx_ba_cb_irqsafe" [drivers/staging/rtl8821ae/rtl8821ae.ko] undefined! ERROR: "ieee80211_tx_status_irqsafe" [drivers/staging/rtl8821ae/rtl8821ae.ko] undefined! ERROR: "ieee80211_find_sta" [drivers/staging/rtl8821ae/rtl8821ae.ko] undefined! ERROR: "ieee80211_wake_queue" [drivers/staging/rtl8821ae/rtl8821ae.ko] undefined! ERROR: "ieee80211_rate_control_unregister" [drivers/staging/rtl8821ae/rtl8821ae.ko] undefined! ERROR: "ieee80211_register_hw" [drivers/staging/rtl8821ae/rtl8821ae.ko] undefined! ERROR: "ieee80211_start_tx_ba_session" [drivers/staging/rtl8821ae/rtl8821ae.ko] undefined! ERROR: "ieee80211_alloc_hw" [drivers/staging/rtl8821ae/rtl8821ae.ko] undefined! ERROR: "ieee80211_free_hw" [drivers/staging/rtl8821ae/rtl8821ae.ko] undefined! ERROR: "ieee80211_connection_loss" [drivers/staging/rtl8821ae/rtl8821ae.ko] undefined! ERROR: "ieee80211_start_tx_ba_cb_irqsafe" [drivers/staging/rtl8821ae/rtl8821ae.ko] undefined! Signed-off-by: Randy Dunlap Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8821ae/Kconfig b/drivers/staging/rtl8821ae/Kconfig index 2aa5dac2..abccc9d 100644 --- a/drivers/staging/rtl8821ae/Kconfig +++ b/drivers/staging/rtl8821ae/Kconfig @@ -1,6 +1,6 @@ config R8821AE tristate "RealTek RTL8821AE Wireless LAN NIC driver" - depends on PCI && WLAN + depends on PCI && WLAN && MAC80211 depends on m select WIRELESS_EXT select WEXT_PRIV -- cgit v0.10.2 From 87fbb2ac6073a7039303517546a76074feb14c84 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Red Hat)" Date: Tue, 11 Feb 2014 20:19:44 -0500 Subject: ftrace/x86: Use breakpoints for converting function graph caller When the conversion was made to remove stop machine and use the breakpoint logic instead, the modification of the function graph caller is still done directly as though it was being done under stop machine. As it is not converted via stop machine anymore, there is a possibility that the code could be layed across cache lines and if another CPU is accessing that function graph call when it is being updated, it could cause a General Protection Fault. Convert the update of the function graph caller to use the breakpoint method as well. Cc: H. Peter Anvin Cc: stable@vger.kernel.org # 3.5+ Fixes: 08d636b6d4fb "ftrace/x86: Have arch x86_64 use breakpoints instead of stop machine" Signed-off-by: Steven Rostedt diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c index d4bdd25..e625319 100644 --- a/arch/x86/kernel/ftrace.c +++ b/arch/x86/kernel/ftrace.c @@ -77,8 +77,7 @@ within(unsigned long addr, unsigned long start, unsigned long end) return addr >= start && addr < end; } -static int -do_ftrace_mod_code(unsigned long ip, const void *new_code) +static unsigned long text_ip_addr(unsigned long ip) { /* * On x86_64, kernel text mappings are mapped read-only with @@ -91,7 +90,7 @@ do_ftrace_mod_code(unsigned long ip, const void *new_code) if (within(ip, (unsigned long)_text, (unsigned long)_etext)) ip = (unsigned long)__va(__pa_symbol(ip)); - return probe_kernel_write((void *)ip, new_code, MCOUNT_INSN_SIZE); + return ip; } static const unsigned char *ftrace_nop_replace(void) @@ -123,8 +122,10 @@ ftrace_modify_code_direct(unsigned long ip, unsigned const char *old_code, if (memcmp(replaced, old_code, MCOUNT_INSN_SIZE) != 0) return -EINVAL; + ip = text_ip_addr(ip); + /* replace the text with the new text */ - if (do_ftrace_mod_code(ip, new_code)) + if (probe_kernel_write((void *)ip, new_code, MCOUNT_INSN_SIZE)) return -EPERM; sync_core(); @@ -221,37 +222,51 @@ int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr, return -EINVAL; } -int ftrace_update_ftrace_func(ftrace_func_t func) +static unsigned long ftrace_update_func; + +static int update_ftrace_func(unsigned long ip, void *new) { - unsigned long ip = (unsigned long)(&ftrace_call); - unsigned char old[MCOUNT_INSN_SIZE], *new; + unsigned char old[MCOUNT_INSN_SIZE]; int ret; - memcpy(old, &ftrace_call, MCOUNT_INSN_SIZE); - new = ftrace_call_replace(ip, (unsigned long)func); + memcpy(old, (void *)ip, MCOUNT_INSN_SIZE); + + ftrace_update_func = ip; + /* Make sure the breakpoints see the ftrace_update_func update */ + smp_wmb(); /* See comment above by declaration of modifying_ftrace_code */ atomic_inc(&modifying_ftrace_code); ret = ftrace_modify_code(ip, old, new); + atomic_dec(&modifying_ftrace_code); + + return ret; +} + +int ftrace_update_ftrace_func(ftrace_func_t func) +{ + unsigned long ip = (unsigned long)(&ftrace_call); + unsigned char *new; + int ret; + + new = ftrace_call_replace(ip, (unsigned long)func); + ret = update_ftrace_func(ip, new); + /* Also update the regs callback function */ if (!ret) { ip = (unsigned long)(&ftrace_regs_call); - memcpy(old, &ftrace_regs_call, MCOUNT_INSN_SIZE); new = ftrace_call_replace(ip, (unsigned long)func); - ret = ftrace_modify_code(ip, old, new); + ret = update_ftrace_func(ip, new); } - atomic_dec(&modifying_ftrace_code); - return ret; } static int is_ftrace_caller(unsigned long ip) { - if (ip == (unsigned long)(&ftrace_call) || - ip == (unsigned long)(&ftrace_regs_call)) + if (ip == ftrace_update_func) return 1; return 0; @@ -677,45 +692,41 @@ int __init ftrace_dyn_arch_init(void *data) #ifdef CONFIG_DYNAMIC_FTRACE extern void ftrace_graph_call(void); -static int ftrace_mod_jmp(unsigned long ip, - int old_offset, int new_offset) +static unsigned char *ftrace_jmp_replace(unsigned long ip, unsigned long addr) { - unsigned char code[MCOUNT_INSN_SIZE]; + static union ftrace_code_union calc; - if (probe_kernel_read(code, (void *)ip, MCOUNT_INSN_SIZE)) - return -EFAULT; + /* Jmp not a call (ignore the .e8) */ + calc.e8 = 0xe9; + calc.offset = ftrace_calc_offset(ip + MCOUNT_INSN_SIZE, addr); - if (code[0] != 0xe9 || old_offset != *(int *)(&code[1])) - return -EINVAL; + /* + * ftrace external locks synchronize the access to the static variable. + */ + return calc.code; +} - *(int *)(&code[1]) = new_offset; +static int ftrace_mod_jmp(unsigned long ip, void *func) +{ + unsigned char *new; - if (do_ftrace_mod_code(ip, &code)) - return -EPERM; + new = ftrace_jmp_replace(ip, (unsigned long)func); - return 0; + return update_ftrace_func(ip, new); } int ftrace_enable_ftrace_graph_caller(void) { unsigned long ip = (unsigned long)(&ftrace_graph_call); - int old_offset, new_offset; - old_offset = (unsigned long)(&ftrace_stub) - (ip + MCOUNT_INSN_SIZE); - new_offset = (unsigned long)(&ftrace_graph_caller) - (ip + MCOUNT_INSN_SIZE); - - return ftrace_mod_jmp(ip, old_offset, new_offset); + return ftrace_mod_jmp(ip, &ftrace_graph_caller); } int ftrace_disable_ftrace_graph_caller(void) { unsigned long ip = (unsigned long)(&ftrace_graph_call); - int old_offset, new_offset; - - old_offset = (unsigned long)(&ftrace_graph_caller) - (ip + MCOUNT_INSN_SIZE); - new_offset = (unsigned long)(&ftrace_stub) - (ip + MCOUNT_INSN_SIZE); - return ftrace_mod_jmp(ip, old_offset, new_offset); + return ftrace_mod_jmp(ip, &ftrace_stub); } #endif /* !CONFIG_DYNAMIC_FTRACE */ -- cgit v0.10.2 From abb97b8c502a270d59c0c2e1ecea78ad752372ee Mon Sep 17 00:00:00 2001 From: Roger Pau Monne Date: Tue, 11 Feb 2014 20:34:03 -0700 Subject: xen-blkback: init persistent_purge_work work_struct MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Initialize persistent_purge_work work_struct on xen_blkif_alloc (and remove the previous initialization done in purge_persistent_gnt). This prevents flush_work from complaining even if purge_persistent_gnt has not been used. Signed-off-by: Roger Pau Monné Reviewed-by: David Vrabel Tested-by: Sander Eikelenboom Signed-off-by: Jens Axboe diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index 765fc73..64c60ed 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -299,7 +299,7 @@ static void free_persistent_gnts(struct xen_blkif *blkif, struct rb_root *root, BUG_ON(num != 0); } -static void unmap_purged_grants(struct work_struct *work) +void xen_blkbk_unmap_purged_grants(struct work_struct *work) { struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST]; struct page *pages[BLKIF_MAX_SEGMENTS_PER_REQUEST]; @@ -420,7 +420,6 @@ finished: blkif->vbd.overflow_max_grants = 0; /* We can defer this work */ - INIT_WORK(&blkif->persistent_purge_work, unmap_purged_grants); schedule_work(&blkif->persistent_purge_work); pr_debug(DRV_PFX "Purged %u/%u\n", (total - num_clean), total); return; diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h index 9eb34e2..be05277 100644 --- a/drivers/block/xen-blkback/common.h +++ b/drivers/block/xen-blkback/common.h @@ -385,6 +385,7 @@ int xen_blkbk_flush_diskcache(struct xenbus_transaction xbt, int xen_blkbk_barrier(struct xenbus_transaction xbt, struct backend_info *be, int state); struct xenbus_device *xen_blkbk_xenbus(struct backend_info *be); +void xen_blkbk_unmap_purged_grants(struct work_struct *work); static inline void blkif_get_x86_32_req(struct blkif_request *dst, struct blkif_x86_32_request *src) diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c index 84973c6..9a547e6 100644 --- a/drivers/block/xen-blkback/xenbus.c +++ b/drivers/block/xen-blkback/xenbus.c @@ -129,6 +129,7 @@ static struct xen_blkif *xen_blkif_alloc(domid_t domid) blkif->free_pages_num = 0; atomic_set(&blkif->persistent_gnt_in_use, 0); atomic_set(&blkif->inflight, 0); + INIT_WORK(&blkif->persistent_purge_work, xen_blkbk_unmap_purged_grants); INIT_LIST_HEAD(&blkif->pending_free); -- cgit v0.10.2 From 7282059489868e0ed1b0d79765730c6b233a8399 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Tue, 11 Feb 2014 12:42:37 +0200 Subject: ACPI / hotplug / PCI: Relax the checking of _STA return values The ACPI specification (ACPI 5.0A, Section 6.3.7) says: _STA may return bit 0 clear (not present) with bit 3 set (device is functional). This case is used to indicate a valid device for which no device driver should be loaded (for example, a bridge device.) Children of this device may be present and valid. OSPM should continue enumeration below a device whose _STA returns this bit combination. Evidently, some BIOSes follow that and return 0x0A from _STA, which causes problems to happen when they trigger bus check or device check notifications for those devices too. Namely, ACPIPHP thinks that they are gone and may drop them, for example, if such a notification is triggered during a resume from system suspend. To fix that, modify ACPICA to regard devies as present and functioning if _STA returns both the ACPI_STA_DEVICE_ENABLED and ACPI_STA_DEVICE_FUNCTIONING bits set for them. Reported-and-tested-by: Peter Wu Cc: 3.12+ # 3.12+ [rjw: Subject and changelog, minor code modifications] Signed-off-by: Rafael J. Wysocki diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index e2a783f..7c7a388 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -730,6 +730,17 @@ static unsigned int get_slot_status(struct acpiphp_slot *slot) return (unsigned int)sta; } +static inline bool device_status_valid(unsigned int sta) +{ + /* + * ACPI spec says that _STA may return bit 0 clear with bit 3 set + * if the device is valid but does not require a device driver to be + * loaded (Section 6.3.7 of ACPI 5.0A). + */ + unsigned int mask = ACPI_STA_DEVICE_ENABLED | ACPI_STA_DEVICE_FUNCTIONING; + return (sta & mask) == mask; +} + /** * trim_stale_devices - remove PCI devices that are not responding. * @dev: PCI device to start walking the hierarchy from. @@ -745,7 +756,7 @@ static void trim_stale_devices(struct pci_dev *dev) unsigned long long sta; status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); - alive = (ACPI_SUCCESS(status) && sta == ACPI_STA_ALL) + alive = (ACPI_SUCCESS(status) && device_status_valid(sta)) || acpiphp_no_hotplug(handle); } if (!alive) { @@ -792,7 +803,7 @@ static void acpiphp_check_bridge(struct acpiphp_bridge *bridge) mutex_lock(&slot->crit_sect); if (slot_no_hotplug(slot)) { ; /* do nothing */ - } else if (get_slot_status(slot) == ACPI_STA_ALL) { + } else if (device_status_valid(get_slot_status(slot))) { /* remove stale devices if any */ list_for_each_entry_safe_reverse(dev, tmp, &bus->devices, bus_list) -- cgit v0.10.2 From 0f6aa09e40c38d734f5d70762056116ca4a76126 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 12 Feb 2014 00:52:49 +0100 Subject: ACPI / container: Fix error code path in container_device_attach() To avoid leaking memory on errors from device_register(), do a put_device() on the device object in question in the error code path of container_device_attach(). Fixes: caa73ea158de (ACPI / hotplug / driver core: Handle containers in a special way) Signed-off-by: Rafael J. Wysocki Reviewed-by: Yasuaki Ishimatsu diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c index 0b6ae6e..368f9dd 100644 --- a/drivers/acpi/container.c +++ b/drivers/acpi/container.c @@ -79,9 +79,10 @@ static int container_device_attach(struct acpi_device *adev, ACPI_COMPANION_SET(dev, adev); dev->release = acpi_container_release; ret = device_register(dev); - if (ret) + if (ret) { + put_device(dev); return ret; - + } adev->driver_data = dev; return 1; } -- cgit v0.10.2 From c8123f8c9cb517403b51aa41c3c46ff5e10b2c17 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 12 Feb 2014 09:34:01 -0700 Subject: block: add cond_resched() to potentially long running ioctl discard loop When mkfs issues a full device discard and the device only supports discards of a smallish size, we can loop in blkdev_issue_discard() for a long time. If preempt isn't enabled, this can turn into a softlock situation and the kernel will start complaining. Add an explicit cond_resched() at the end of the loop to avoid that. Cc: stable@kernel.org Signed-off-by: Jens Axboe diff --git a/block/blk-lib.c b/block/blk-lib.c index 2da76c9..97a733c 100644 --- a/block/blk-lib.c +++ b/block/blk-lib.c @@ -119,6 +119,14 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector, atomic_inc(&bb.done); submit_bio(type, bio); + + /* + * We can loop for a long time in here, if someone does + * full device discards (like mkfs). Be nice and allow + * us to schedule out to avoid softlocking if preempt + * is disabled. + */ + cond_resched(); } blk_finish_plug(&plug); -- cgit v0.10.2 From 2078600b1f8fc68b02f6ebdda1759fb0c9f51afb Mon Sep 17 00:00:00 2001 From: Martin Kepplinger Date: Wed, 12 Feb 2014 17:09:23 +0100 Subject: ALSA: Revert "ALSA: hda/realtek - Avoid invalid COEFs for ALC271X" This reverts commit d3c56568f43807135f2c2a09582a69f809f0d8b7. The reverted commit breaks audio through headphone line out on the Acer TravelMate B113 (Type1Sku0) Notebook, my main work machine. I don't know much about it but this fixes my problem. Bisected and tested. Fixes: d3c56568f438 ('ALSA: hda/realtek - Avoid invalid COEFs for ALC271X') Cc: Tested-by: Martin Kepplinger Signed-off-by: Martin Kepplinger Signed-off-by: Takashi Iwai diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 0ab0b9e..a9a83b8 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4438,9 +4438,6 @@ static void alc269_fill_coef(struct hda_codec *codec) if (spec->codec_variant != ALC269_TYPE_ALC269VB) return; - /* ALC271X doesn't seem to support these COEFs (bko#52181) */ - if (!strcmp(codec->chip_name, "ALC271X")) - return; if ((alc_get_coef0(codec) & 0x00ff) < 0x015) { alc_write_coef_idx(codec, 0xf, 0x960b); -- cgit v0.10.2 From d07875bd0d1517185534b5f9eef469426ba42cb9 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 29 Dec 2013 23:47:37 +0100 Subject: RDMA/nes: Fix error return code Set the return variable to an error code as done elsewhere in the function. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // ( if@p1 (\(ret < 0\|ret != 0\)) { ... return ret; } | ret@p1 = 0 ) ... when != ret = e1 when != &ret *if(...) { ... when != ret = e2 when forall return ret; } // Signed-off-by: Julia Lawall Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/hw/nes/nes.c b/drivers/infiniband/hw/nes/nes.c index 4291410..353c7b0 100644 --- a/drivers/infiniband/hw/nes/nes.c +++ b/drivers/infiniband/hw/nes/nes.c @@ -675,8 +675,11 @@ static int nes_probe(struct pci_dev *pcidev, const struct pci_device_id *ent) INIT_DELAYED_WORK(&nesdev->work, nes_recheck_link_status); /* Initialize network devices */ - if ((netdev = nes_netdev_init(nesdev, mmio_regs)) == NULL) + netdev = nes_netdev_init(nesdev, mmio_regs); + if (netdev == NULL) { + ret = -ENOMEM; goto bail7; + } /* Register network device */ ret = register_netdev(netdev); -- cgit v0.10.2 From ab576627c8f97c08297d81537be17df161171923 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 29 Dec 2013 23:47:29 +0100 Subject: RDMA/amso1100: Fix error return code Set the return variable to an error code as done elsewhere in the function. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // ( if@p1 (\(ret < 0\|ret != 0\)) { ... return ret; } | ret@p1 = 0 ) ... when != ret = e1 when != &ret *if(...) { ... when != ret = e2 when forall return ret; } // Signed-off-by: Julia Lawall Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/hw/amso1100/c2.c b/drivers/infiniband/hw/amso1100/c2.c index d53cf51..00400c3 100644 --- a/drivers/infiniband/hw/amso1100/c2.c +++ b/drivers/infiniband/hw/amso1100/c2.c @@ -1082,6 +1082,7 @@ static int c2_probe(struct pci_dev *pcidev, const struct pci_device_id *ent) /* Initialize network device */ if ((netdev = c2_devinit(c2dev, mmio_regs)) == NULL) { + ret = -ENOMEM; iounmap(mmio_regs); goto bail4; } @@ -1151,7 +1152,8 @@ static int c2_probe(struct pci_dev *pcidev, const struct pci_device_id *ent) goto bail10; } - if (c2_register_device(c2dev)) + ret = c2_register_device(c2dev); + if (ret) goto bail10; return 0; diff --git a/drivers/infiniband/hw/amso1100/c2_rnic.c b/drivers/infiniband/hw/amso1100/c2_rnic.c index b7c9869..d2a6d96 100644 --- a/drivers/infiniband/hw/amso1100/c2_rnic.c +++ b/drivers/infiniband/hw/amso1100/c2_rnic.c @@ -576,7 +576,8 @@ int c2_rnic_init(struct c2_dev *c2dev) goto bail4; /* Initialize cached the adapter limits */ - if (c2_rnic_query(c2dev, &c2dev->props)) + err = c2_rnic_query(c2dev, &c2dev->props); + if (err) goto bail5; /* Initialize the PD pool */ -- cgit v0.10.2 From fc09149df6e20cfbb0bb86f10899607c321a31eb Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Thu, 30 Jan 2014 13:08:49 -0800 Subject: target: Fix free-after-use regression in PR unregister This patch addresses a >= v3.11 free-after-use regression in core_scsi3_emulate_pro_register() that was introduced in the following commit: commit bc118fe4c4a8cfa453491ba77c0a146a6d0e73e0 Author: Andy Grover Date: Thu May 16 10:41:04 2013 -0700 target: Further refactoring of core_scsi3_emulate_pro_register() To avoid the free-after-use, save an type value before hand, and only call core_scsi3_put_pr_reg() with a valid *pr_reg. Reported-by: Dan Carpenter Cc: Andy Grover Cc: #3.11+ Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index 2f5d779..3013287 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -2009,7 +2009,7 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key, struct t10_reservation *pr_tmpl = &dev->t10_pr; unsigned char isid_buf[PR_REG_ISID_LEN], *isid_ptr = NULL; sense_reason_t ret = TCM_NO_SENSE; - int pr_holder = 0; + int pr_holder = 0, type; if (!se_sess || !se_lun) { pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n"); @@ -2131,6 +2131,7 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key, ret = TCM_RESERVATION_CONFLICT; goto out; } + type = pr_reg->pr_res_type; spin_lock(&pr_tmpl->registration_lock); /* @@ -2161,6 +2162,7 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key, * Release the calling I_T Nexus registration now.. */ __core_scsi3_free_registration(cmd->se_dev, pr_reg, NULL, 1); + pr_reg = NULL; /* * From spc4r17, section 5.7.11.3 Unregistering @@ -2174,8 +2176,8 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key, * RESERVATIONS RELEASED. */ if (pr_holder && - (pr_reg->pr_res_type == PR_TYPE_WRITE_EXCLUSIVE_REGONLY || - pr_reg->pr_res_type == PR_TYPE_EXCLUSIVE_ACCESS_REGONLY)) { + (type == PR_TYPE_WRITE_EXCLUSIVE_REGONLY || + type == PR_TYPE_EXCLUSIVE_ACCESS_REGONLY)) { list_for_each_entry(pr_reg_p, &pr_tmpl->registration_list, pr_reg_list) { @@ -2194,7 +2196,8 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key, ret = core_scsi3_update_and_write_aptpl(dev, aptpl); out: - core_scsi3_put_pr_reg(pr_reg); + if (pr_reg) + core_scsi3_put_pr_reg(pr_reg); return ret; } -- cgit v0.10.2 From cdf55949c10aed90d081342264d99b2b0ed0bbf3 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Thu, 30 Jan 2014 14:05:16 -0800 Subject: target: Fix 32-bit + CONFIG_LBDAF=n link error w/ sector_div This patch changes core_alua_state_lba_dependent() to use do_div() instead sector_div() to avoid the following link error on 32-bit with CONFIG_LBDAF=n as reported by Jim: buildlog-1391099072.txt-drivers/built-in.o: In function `target_alua_state_check': buildlog-1391099072.txt-(.text+0x928d93): undefined reference to `__umoddi3' buildlog-1391099072.txt:make: *** [vmlinux] Error 1 -- buildlog-1391101753.txt- CC init/version.o buildlog-1391101753.txt- LD init/built-in.o buildlog-1391101753.txt-drivers/built-in.o: In function `core_alua_state_lba_dependent': buildlog-1391101753.txt-/home/jim/linux/drivers/target/target_core_alua.c:503: undefined reference to `__umoddi3' buildlog-1391101753.txt:make: *** [vmlinux] Error 1 Reported-by: Jim Davis Cc: Hannes Reinecke Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c index 12da9b38..c3d9df6 100644 --- a/drivers/target/target_core_alua.c +++ b/drivers/target/target_core_alua.c @@ -500,7 +500,7 @@ static inline int core_alua_state_lba_dependent( if (segment_mult) { u64 tmp = lba; - start_lba = sector_div(tmp, segment_size * segment_mult); + start_lba = do_div(tmp, segment_size * segment_mult); last_lba = first_lba + segment_size - 1; if (start_lba >= first_lba && -- cgit v0.10.2 From 2d15025a568ba8ab2bc6120fb13c62a9ca322f62 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Fri, 31 Jan 2014 13:11:36 -0800 Subject: qla2xxx: Remove last vestiges of qla_tgt_cmd.cmd_list The only place this struct member is touched is in one INIT_LIST_HEAD. Signed-off-by: Roland Dreier Signed-off-by: Nicholas Bellinger diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 9e80d61..2eb97d7 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -2595,8 +2595,6 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha, return -ENOMEM; } - INIT_LIST_HEAD(&cmd->cmd_list); - memcpy(&cmd->atio, atio, sizeof(*atio)); cmd->state = QLA_TGT_STATE_NEW; cmd->tgt = vha->vha_tgt.qla_tgt; diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h index 1d10eec..66e755c 100644 --- a/drivers/scsi/qla2xxx/qla_target.h +++ b/drivers/scsi/qla2xxx/qla_target.h @@ -855,7 +855,6 @@ struct qla_tgt_cmd { uint16_t loop_id; /* to save extra sess dereferences */ struct qla_tgt *tgt; /* to save extra sess dereferences */ struct scsi_qla_host *vha; - struct list_head cmd_list; struct atio_from_isp atio; }; -- cgit v0.10.2 From 6a16d7be932a9df1024836ccbb448de73afd3dd0 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 3 Feb 2014 00:35:03 -0800 Subject: target: Fix missing length check in spc_emulate_evpd_83() Commit fbfe858fea2a ("target_core_spc: Include target device descriptor in VPD page 83") added a new length variable, but (due to a cut and paste mistake?) just checks scsi_name_len against 256 twice. Fix this to check scsi_target_len for overflow too. Signed-off-by: Roland Dreier Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index 43c5ca98..3bebc71 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -440,8 +440,8 @@ check_scsi_name: padding = ((-scsi_target_len) & 3); if (padding) scsi_target_len += padding; - if (scsi_name_len > 256) - scsi_name_len = 256; + if (scsi_target_len > 256) + scsi_target_len = 256; buf[off-1] = scsi_target_len; off += scsi_target_len; -- cgit v0.10.2 From 752d86805b18e58c56c6f3c7004c2dffd4430c17 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Mon, 3 Feb 2014 12:55:42 -0800 Subject: iscsi-target: Fix SNACK Type 1 + BegRun=0 handling This patch fixes Status SNACK handling of BegRun=0 to allow for all unacknowledged respones to be resent, instead of always assuming that BegRun would be an explicit value less than the current ExpStatSN. Reported-by: santosh kulkarni Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/iscsi/iscsi_target_erl1.c b/drivers/target/iscsi/iscsi_target_erl1.c index e048d64..cda4d80 100644 --- a/drivers/target/iscsi/iscsi_target_erl1.c +++ b/drivers/target/iscsi/iscsi_target_erl1.c @@ -507,7 +507,9 @@ int iscsit_handle_status_snack( u32 last_statsn; int found_cmd; - if (conn->exp_statsn > begrun) { + if (!begrun) { + begrun = conn->exp_statsn; + } else if (conn->exp_statsn > begrun) { pr_err("Got Status SNACK Begrun: 0x%08x, RunLength:" " 0x%08x but already got ExpStatSN: 0x%08x on CID:" " %hu.\n", begrun, runlength, conn->exp_statsn, -- cgit v0.10.2 From a80e21b3b2d151d79bb9be42334ab10d40195324 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Mon, 3 Feb 2014 12:59:56 -0800 Subject: iser-target: Fix leak on failure in isert_conn_create_fastreg_pool This patch fixes a memory leak for fr_desc upon failure of isert_create_fr_desc() in isert_conn_create_fastreg_pool() code. As reported by Coverity 1166659: *** CID 1166659: Resource leak (RESOURCE_LEAK) /drivers/infiniband/ulp/isert/ib_isert.c: 470 in isert_conn_create_fastreg_pool() 464 isert_conn, isert_conn->conn_fr_pool_size); 465 466 return 0; 467 468 err: 469 isert_conn_free_fastreg_pool(isert_conn); >>> CID 1166659: Resource leak (RESOURCE_LEAK) >>> Variable "fr_desc" going out of scope leaks the storage it points to. 470 return ret; 471 } 472 473 static int 474 isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) 475 { Cc: Sagi Grimberg Signed-off-by: Nicholas Bellinger diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index 2b161be..d18d08a 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c @@ -453,6 +453,7 @@ isert_conn_create_fastreg_pool(struct isert_conn *isert_conn) if (ret) { pr_err("Failed to create fastreg descriptor err=%d\n", ret); + kfree(fr_desc); goto err; } -- cgit v0.10.2 From 3dca1471993f9b89f3184468f8bbab2b1e024451 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 3 Feb 2014 14:08:26 -0800 Subject: target: Simplify command completion by removing CMD_T_FAILED flag The CMD_T_FAILED flag is set used in one place to record the result of a trivial test, and it is only tested once, few lines later. We might as well make the code simpler and easier to read by directly doing the test of "success" where we want to use it. Signed-off-by: Roland Dreier Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index c50fd9f..24b4f65d 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -669,9 +669,6 @@ void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status) return; } - if (!success) - cmd->transport_state |= CMD_T_FAILED; - /* * Check for case where an explicit ABORT_TASK has been received * and transport_wait_for_tasks() will be waiting for completion.. @@ -681,7 +678,7 @@ void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status) spin_unlock_irqrestore(&cmd->t_state_lock, flags); complete(&cmd->t_transport_stop_comp); return; - } else if (cmd->transport_state & CMD_T_FAILED) { + } else if (!success) { INIT_WORK(&cmd->work, target_complete_failure_work); } else { INIT_WORK(&cmd->work, target_complete_ok_work); diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index c9c7912..1772fad 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -525,7 +525,6 @@ struct se_cmd { #define CMD_T_COMPLETE (1 << 2) #define CMD_T_SENT (1 << 4) #define CMD_T_STOP (1 << 5) -#define CMD_T_FAILED (1 << 6) #define CMD_T_DEV_ACTIVE (1 << 7) #define CMD_T_REQUEST_STOP (1 << 8) #define CMD_T_BUSY (1 << 9) -- cgit v0.10.2 From 9d8abf45944e4f1c18a04070fc3ed2f3ffcbbcb6 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Wed, 5 Feb 2014 11:22:05 +0900 Subject: IB/srpt: replace strict_strtoul() with kstrtoul() The usage of strict_strtoul() is not preferred, because strict_strtoul() is obsolete. Thus, kstrtoul() should be used. Signed-off-by: Jingoo Han Signed-off-by: Nicholas Bellinger diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c index 520a7e5..0e537d8 100644 --- a/drivers/infiniband/ulp/srpt/ib_srpt.c +++ b/drivers/infiniband/ulp/srpt/ib_srpt.c @@ -3666,9 +3666,9 @@ static ssize_t srpt_tpg_attrib_store_srp_max_rdma_size( unsigned long val; int ret; - ret = strict_strtoul(page, 0, &val); + ret = kstrtoul(page, 0, &val); if (ret < 0) { - pr_err("strict_strtoul() failed with ret: %d\n", ret); + pr_err("kstrtoul() failed with ret: %d\n", ret); return -EINVAL; } if (val > MAX_SRPT_RDMA_SIZE) { @@ -3706,9 +3706,9 @@ static ssize_t srpt_tpg_attrib_store_srp_max_rsp_size( unsigned long val; int ret; - ret = strict_strtoul(page, 0, &val); + ret = kstrtoul(page, 0, &val); if (ret < 0) { - pr_err("strict_strtoul() failed with ret: %d\n", ret); + pr_err("kstrtoul() failed with ret: %d\n", ret); return -EINVAL; } if (val > MAX_SRPT_RSP_SIZE) { @@ -3746,9 +3746,9 @@ static ssize_t srpt_tpg_attrib_store_srp_sq_size( unsigned long val; int ret; - ret = strict_strtoul(page, 0, &val); + ret = kstrtoul(page, 0, &val); if (ret < 0) { - pr_err("strict_strtoul() failed with ret: %d\n", ret); + pr_err("kstrtoul() failed with ret: %d\n", ret); return -EINVAL; } if (val > MAX_SRPT_SRQ_SIZE) { @@ -3793,7 +3793,7 @@ static ssize_t srpt_tpg_store_enable( unsigned long tmp; int ret; - ret = strict_strtoul(page, 0, &tmp); + ret = kstrtoul(page, 0, &tmp); if (ret < 0) { printk(KERN_ERR "Unable to extract srpt_tpg_store_enable\n"); return -EINVAL; -- cgit v0.10.2 From d6a65fdc8903e632aa7bf86ee0f61a73969371f6 Mon Sep 17 00:00:00 2001 From: Sagi Grimberg Date: Wed, 12 Feb 2014 11:40:25 +0200 Subject: Target/sbc: Fix protection copy routine Need to take into account that protection sg_list (copy-buffer) may consist of multiple entries. Changes from v0: - Changed commit description Signed-off-by: Sagi Grimberg Signed-off-by: Nicholas Bellinger diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index fa3cae3..a448944 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -1074,12 +1074,19 @@ sbc_dif_copy_prot(struct se_cmd *cmd, unsigned int sectors, bool read, struct scatterlist *psg; void *paddr, *addr; unsigned int i, len, left; + unsigned int offset = 0; left = sectors * dev->prot_length; for_each_sg(cmd->t_prot_sg, psg, cmd->t_prot_nents, i) { len = min(psg->length, left); + if (offset >= sg->length) { + sg = sg_next(sg); + offset = 0; + sg_off = sg->offset; + } + paddr = kmap_atomic(sg_page(psg)) + psg->offset; addr = kmap_atomic(sg_page(sg)) + sg_off; @@ -1089,6 +1096,7 @@ sbc_dif_copy_prot(struct se_cmd *cmd, unsigned int sectors, bool read, memcpy(addr, paddr, len); left -= len; + offset += len; kunmap_atomic(paddr); kunmap_atomic(addr); } -- cgit v0.10.2 From 31fd8f5b89f22a88940a9838dfd1564f3d440247 Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Mon, 3 Feb 2014 17:13:23 -0800 Subject: dma: mv_xor: Silence a bunch of LPAE-related warnings Enabling some of the mvebu platforms in the multiplatform config for ARM enabled these drivers, which also triggered a bunch of warnings when LPAE is enabled (thus making phys_addr_t 64-bit). Most changes are switching printk formats, but also a bit of changes to what used to be array-based pointer arithmetic that could just be done with the address types instead. The warnings were: drivers/dma/mv_xor.c: In function 'mv_xor_tx_submit': drivers/dma/mv_xor.c:500:3: warning: format '%x' expects argument of type 'unsigned int', but argument 4 has type 'dma_addr_t' [-Wformat] drivers/dma/mv_xor.c: In function 'mv_xor_alloc_chan_resources': drivers/dma/mv_xor.c:553:13: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast] drivers/dma/mv_xor.c:555:4: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] drivers/dma/mv_xor.c: In function 'mv_xor_prep_dma_memcpy': drivers/dma/mv_xor.c:584:2: warning: format '%x' expects argument of type 'unsigned int', but argument 5 has type 'dma_addr_t' [-Wformat] drivers/dma/mv_xor.c:584:2: warning: format '%x' expects argument of type 'unsigned int', but argument 6 has type 'dma_addr_t' [-Wformat] drivers/dma/mv_xor.c: In function 'mv_xor_prep_dma_xor': drivers/dma/mv_xor.c:628:2: warning: format '%u' expects argument of type 'unsigned int', but argument 7 has type 'dma_addr_t' [-Wformat] Acked-by: Vinod Koul Acked-by: Jason Cooper Signed-off-by: Olof Johansson diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c index 53fb0c8..766b68e 100644 --- a/drivers/dma/mv_xor.c +++ b/drivers/dma/mv_xor.c @@ -497,8 +497,8 @@ mv_xor_tx_submit(struct dma_async_tx_descriptor *tx) if (!mv_can_chain(grp_start)) goto submit_done; - dev_dbg(mv_chan_to_devp(mv_chan), "Append to last desc %x\n", - old_chain_tail->async_tx.phys); + dev_dbg(mv_chan_to_devp(mv_chan), "Append to last desc %pa\n", + &old_chain_tail->async_tx.phys); /* fix up the hardware chain */ mv_desc_set_next_desc(old_chain_tail, grp_start->async_tx.phys); @@ -527,7 +527,8 @@ submit_done: /* returns the number of allocated descriptors */ static int mv_xor_alloc_chan_resources(struct dma_chan *chan) { - char *hw_desc; + void *virt_desc; + dma_addr_t dma_desc; int idx; struct mv_xor_chan *mv_chan = to_mv_xor_chan(chan); struct mv_xor_desc_slot *slot = NULL; @@ -542,17 +543,16 @@ static int mv_xor_alloc_chan_resources(struct dma_chan *chan) " %d descriptor slots", idx); break; } - hw_desc = (char *) mv_chan->dma_desc_pool_virt; - slot->hw_desc = (void *) &hw_desc[idx * MV_XOR_SLOT_SIZE]; + virt_desc = mv_chan->dma_desc_pool_virt; + slot->hw_desc = virt_desc + idx * MV_XOR_SLOT_SIZE; dma_async_tx_descriptor_init(&slot->async_tx, chan); slot->async_tx.tx_submit = mv_xor_tx_submit; INIT_LIST_HEAD(&slot->chain_node); INIT_LIST_HEAD(&slot->slot_node); INIT_LIST_HEAD(&slot->tx_list); - hw_desc = (char *) mv_chan->dma_desc_pool; - slot->async_tx.phys = - (dma_addr_t) &hw_desc[idx * MV_XOR_SLOT_SIZE]; + dma_desc = mv_chan->dma_desc_pool; + slot->async_tx.phys = dma_desc + idx * MV_XOR_SLOT_SIZE; slot->idx = idx++; spin_lock_bh(&mv_chan->lock); @@ -582,8 +582,8 @@ mv_xor_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, int slot_cnt; dev_dbg(mv_chan_to_devp(mv_chan), - "%s dest: %x src %x len: %u flags: %ld\n", - __func__, dest, src, len, flags); + "%s dest: %pad src %pad len: %u flags: %ld\n", + __func__, &dest, &src, len, flags); if (unlikely(len < MV_XOR_MIN_BYTE_COUNT)) return NULL; @@ -626,8 +626,8 @@ mv_xor_prep_dma_xor(struct dma_chan *chan, dma_addr_t dest, dma_addr_t *src, BUG_ON(len > MV_XOR_MAX_BYTE_COUNT); dev_dbg(mv_chan_to_devp(mv_chan), - "%s src_cnt: %d len: dest %x %u flags: %ld\n", - __func__, src_cnt, len, dest, flags); + "%s src_cnt: %d len: %u dest %pad flags: %ld\n", + __func__, src_cnt, len, &dest, flags); spin_lock_bh(&mv_chan->lock); slot_cnt = mv_chan_xor_slot_count(len, src_cnt); -- cgit v0.10.2 From 709c078e176bd47227e89bb34de7c64b57aaaeab Mon Sep 17 00:00:00 2001 From: Dirk Brandewie Date: Wed, 12 Feb 2014 10:01:03 -0800 Subject: intel_pstate: Remove energy reporting from pstate_sample tracepoint Remove the reporting of energy since it does not provide any useful information about the state of the driver and will be a maintainance headache going forward since the RAPL energy units register is not architectural and subject to change between micro-architectures References: https://bugzilla.kernel.org/show_bug.cgi?id=69831 Fixes: b69880f9ccf7 (intel_pstate: Add trace point to report internal state.) Signed-off-by: Dirk Brandewie Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 79606f473..c788abf 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -51,8 +51,6 @@ static inline int32_t div_fp(int32_t x, int32_t y) return div_s64((int64_t)x << FRAC_BITS, (int64_t)y); } -static u64 energy_divisor; - struct sample { int32_t core_pct_busy; u64 aperf; @@ -630,12 +628,10 @@ static void intel_pstate_timer_func(unsigned long __data) { struct cpudata *cpu = (struct cpudata *) __data; struct sample *sample; - u64 energy; intel_pstate_sample(cpu); sample = &cpu->samples[cpu->sample_ptr]; - rdmsrl(MSR_PKG_ENERGY_STATUS, energy); intel_pstate_adjust_busy_pstate(cpu); @@ -644,7 +640,6 @@ static void intel_pstate_timer_func(unsigned long __data) cpu->pstate.current_pstate, sample->mperf, sample->aperf, - div64_u64(energy, energy_divisor), sample->freq); intel_pstate_set_sample_time(cpu); @@ -926,7 +921,6 @@ static int __init intel_pstate_init(void) int cpu, rc = 0; const struct x86_cpu_id *id; struct cpu_defaults *cpu_info; - u64 units; if (no_load) return -ENODEV; @@ -960,9 +954,6 @@ static int __init intel_pstate_init(void) if (rc) goto out; - rdmsrl(MSR_RAPL_POWER_UNIT, units); - energy_divisor = 1 << ((units >> 8) & 0x1f); /* bits{12:8} */ - intel_pstate_debug_expose_params(); intel_pstate_sysfs_expose_params(); diff --git a/include/trace/events/power.h b/include/trace/events/power.h index 9e9475c..e5bf9a7 100644 --- a/include/trace/events/power.h +++ b/include/trace/events/power.h @@ -42,7 +42,6 @@ TRACE_EVENT(pstate_sample, u32 state, u64 mperf, u64 aperf, - u32 energy, u32 freq ), @@ -51,7 +50,6 @@ TRACE_EVENT(pstate_sample, state, mperf, aperf, - energy, freq ), @@ -61,7 +59,6 @@ TRACE_EVENT(pstate_sample, __field(u32, state) __field(u64, mperf) __field(u64, aperf) - __field(u32, energy) __field(u32, freq) ), @@ -72,17 +69,15 @@ TRACE_EVENT(pstate_sample, __entry->state = state; __entry->mperf = mperf; __entry->aperf = aperf; - __entry->energy = energy; __entry->freq = freq; ), - TP_printk("core_busy=%lu scaled=%lu state=%lu mperf=%llu aperf=%llu energy=%lu freq=%lu ", + TP_printk("core_busy=%lu scaled=%lu state=%lu mperf=%llu aperf=%llu freq=%lu ", (unsigned long)__entry->core_busy, (unsigned long)__entry->scaled_busy, (unsigned long)__entry->state, (unsigned long long)__entry->mperf, (unsigned long long)__entry->aperf, - (unsigned long)__entry->energy, (unsigned long)__entry->freq ) -- cgit v0.10.2 From 171d0ba869675dac9acbbb9f1966c54359e5aac8 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Tue, 11 Feb 2014 11:42:32 +0000 Subject: MAINTAINERS / cpufreq: update Sudeep's email address Though my old email address continues to work as alias, updating to the new address as it's shorter, easier and more appropriate. Signed-off-by: Sudeep Holla Signed-off-by: Rafael J. Wysocki diff --git a/MAINTAINERS b/MAINTAINERS index b2cf5cf..956f069 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2367,7 +2367,7 @@ F: include/linux/cpufreq.h CPU FREQUENCY DRIVERS - ARM BIG LITTLE M: Viresh Kumar -M: Sudeep KarkadaNagesha +M: Sudeep Holla L: cpufreq@vger.kernel.org L: linux-pm@vger.kernel.org W: http://www.arm.com/products/processors/technologies/biglittleprocessing.php -- cgit v0.10.2 From 789b5e0315284463617e106baad360cb9e8db3ac Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Thu, 6 Feb 2014 03:42:45 +0530 Subject: md/raid5: Fix CPU hotplug callback registration Subsystems that want to register CPU hotplug callbacks, as well as perform initialization for the CPUs that are already online, often do it as shown below: get_online_cpus(); for_each_online_cpu(cpu) init_cpu(cpu); register_cpu_notifier(&foobar_cpu_notifier); put_online_cpus(); This is wrong, since it is prone to ABBA deadlocks involving the cpu_add_remove_lock and the cpu_hotplug.lock (when running concurrently with CPU hotplug operations). Interestingly, the raid5 code can actually prevent double initialization and hence can use the following simplified form of callback registration: register_cpu_notifier(&foobar_cpu_notifier); get_online_cpus(); for_each_online_cpu(cpu) init_cpu(cpu); put_online_cpus(); A hotplug operation that occurs between registering the notifier and calling get_online_cpus(), won't disrupt anything, because the code takes care to perform the memory allocations only once. So reorganize the code in raid5 this way to fix the deadlock with callback registration. Cc: linux-raid@vger.kernel.org Cc: stable@vger.kernel.org (v2.6.32+) Fixes: 36d1c6476be51101778882897b315bd928c8c7b5 Signed-off-by: Oleg Nesterov [Srivatsa: Fixed the unregister_cpu_notifier() deadlock, added the free_scratch_buffer() helper to condense code further and wrote the changelog.] Signed-off-by: Srivatsa S. Bhat Signed-off-by: NeilBrown diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index f1feade..16f5c21 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -5514,23 +5514,43 @@ raid5_size(struct mddev *mddev, sector_t sectors, int raid_disks) return sectors * (raid_disks - conf->max_degraded); } +static void free_scratch_buffer(struct r5conf *conf, struct raid5_percpu *percpu) +{ + safe_put_page(percpu->spare_page); + kfree(percpu->scribble); + percpu->spare_page = NULL; + percpu->scribble = NULL; +} + +static int alloc_scratch_buffer(struct r5conf *conf, struct raid5_percpu *percpu) +{ + if (conf->level == 6 && !percpu->spare_page) + percpu->spare_page = alloc_page(GFP_KERNEL); + if (!percpu->scribble) + percpu->scribble = kmalloc(conf->scribble_len, GFP_KERNEL); + + if (!percpu->scribble || (conf->level == 6 && !percpu->spare_page)) { + free_scratch_buffer(conf, percpu); + return -ENOMEM; + } + + return 0; +} + static void raid5_free_percpu(struct r5conf *conf) { - struct raid5_percpu *percpu; unsigned long cpu; if (!conf->percpu) return; - get_online_cpus(); - for_each_possible_cpu(cpu) { - percpu = per_cpu_ptr(conf->percpu, cpu); - safe_put_page(percpu->spare_page); - kfree(percpu->scribble); - } #ifdef CONFIG_HOTPLUG_CPU unregister_cpu_notifier(&conf->cpu_notify); #endif + + get_online_cpus(); + for_each_possible_cpu(cpu) + free_scratch_buffer(conf, per_cpu_ptr(conf->percpu, cpu)); put_online_cpus(); free_percpu(conf->percpu); @@ -5557,15 +5577,7 @@ static int raid456_cpu_notify(struct notifier_block *nfb, unsigned long action, switch (action) { case CPU_UP_PREPARE: case CPU_UP_PREPARE_FROZEN: - if (conf->level == 6 && !percpu->spare_page) - percpu->spare_page = alloc_page(GFP_KERNEL); - if (!percpu->scribble) - percpu->scribble = kmalloc(conf->scribble_len, GFP_KERNEL); - - if (!percpu->scribble || - (conf->level == 6 && !percpu->spare_page)) { - safe_put_page(percpu->spare_page); - kfree(percpu->scribble); + if (alloc_scratch_buffer(conf, percpu)) { pr_err("%s: failed memory allocation for cpu%ld\n", __func__, cpu); return notifier_from_errno(-ENOMEM); @@ -5573,10 +5585,7 @@ static int raid456_cpu_notify(struct notifier_block *nfb, unsigned long action, break; case CPU_DEAD: case CPU_DEAD_FROZEN: - safe_put_page(percpu->spare_page); - kfree(percpu->scribble); - percpu->spare_page = NULL; - percpu->scribble = NULL; + free_scratch_buffer(conf, per_cpu_ptr(conf->percpu, cpu)); break; default: break; @@ -5588,40 +5597,29 @@ static int raid456_cpu_notify(struct notifier_block *nfb, unsigned long action, static int raid5_alloc_percpu(struct r5conf *conf) { unsigned long cpu; - struct page *spare_page; - struct raid5_percpu __percpu *allcpus; - void *scribble; - int err; + int err = 0; - allcpus = alloc_percpu(struct raid5_percpu); - if (!allcpus) + conf->percpu = alloc_percpu(struct raid5_percpu); + if (!conf->percpu) return -ENOMEM; - conf->percpu = allcpus; + +#ifdef CONFIG_HOTPLUG_CPU + conf->cpu_notify.notifier_call = raid456_cpu_notify; + conf->cpu_notify.priority = 0; + err = register_cpu_notifier(&conf->cpu_notify); + if (err) + return err; +#endif get_online_cpus(); - err = 0; for_each_present_cpu(cpu) { - if (conf->level == 6) { - spare_page = alloc_page(GFP_KERNEL); - if (!spare_page) { - err = -ENOMEM; - break; - } - per_cpu_ptr(conf->percpu, cpu)->spare_page = spare_page; - } - scribble = kmalloc(conf->scribble_len, GFP_KERNEL); - if (!scribble) { - err = -ENOMEM; + err = alloc_scratch_buffer(conf, per_cpu_ptr(conf->percpu, cpu)); + if (err) { + pr_err("%s: failed memory allocation for cpu%ld\n", + __func__, cpu); break; } - per_cpu_ptr(conf->percpu, cpu)->scribble = scribble; } -#ifdef CONFIG_HOTPLUG_CPU - conf->cpu_notify.notifier_call = raid456_cpu_notify; - conf->cpu_notify.priority = 0; - if (err == 0) - err = register_cpu_notifier(&conf->cpu_notify); -#endif put_online_cpus(); return err; -- cgit v0.10.2 From a9f180345f5378ac87d80ed0bea55ba421d83859 Mon Sep 17 00:00:00 2001 From: Steven Noonan Date: Wed, 12 Feb 2014 23:01:07 -0800 Subject: compiler/gcc4: Make quirk for asm_volatile_goto() unconditional I started noticing problems with KVM guest destruction on Linux 3.12+, where guest memory wasn't being cleaned up. I bisected it down to the commit introducing the new 'asm goto'-based atomics, and found this quirk was later applied to those. Unfortunately, even with GCC 4.8.2 (which ostensibly fixed the known 'asm goto' bug) I am still getting some kind of miscompilation. If I enable the asm_volatile_goto quirk for my compiler, KVM guests are destroyed correctly and the memory is cleaned up. So make the quirk unconditional for now, until bug is found and fixed. Suggested-by: Linus Torvalds Signed-off-by: Steven Noonan Cc: Peter Zijlstra Cc: Steven Rostedt Cc: Jakub Jelinek Cc: Richard Henderson Cc: Andrew Morton Cc: Oleg Nesterov Cc: Link: http://lkml.kernel.org/r/1392274867-15236-1-git-send-email-steven@uplinklabs.net Link: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58670 Signed-off-by: Ingo Molnar diff --git a/include/linux/compiler-gcc4.h b/include/linux/compiler-gcc4.h index ded4299..2507fd2 100644 --- a/include/linux/compiler-gcc4.h +++ b/include/linux/compiler-gcc4.h @@ -75,11 +75,7 @@ * * (asm goto is automatically volatile - the naming reflects this.) */ -#if GCC_VERSION <= 40801 -# define asm_volatile_goto(x...) do { asm goto(x); asm (""); } while (0) -#else -# define asm_volatile_goto(x...) do { asm goto(x); } while (0) -#endif +#define asm_volatile_goto(x...) do { asm goto(x); asm (""); } while (0) #ifdef CONFIG_ARCH_USE_BUILTIN_BSWAP #if GCC_VERSION >= 40400 -- cgit v0.10.2 From 03bbd596ac04fef47ce93a730b8f086d797c3021 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Thu, 13 Feb 2014 07:34:30 -0800 Subject: x86, smap: Don't enable SMAP if CONFIG_X86_SMAP is disabled If SMAP support is not compiled into the kernel, don't enable SMAP in CR4 -- in fact, we should clear it, because the kernel doesn't contain the proper STAC/CLAC instructions for SMAP support. Found by Fengguang Wu's test system. Reported-by: Fengguang Wu Link: http://lkml.kernel.org/r/20140213124550.GA30497@localhost Signed-off-by: H. Peter Anvin Cc: # v3.7+ diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 24b6fd1..8e28bf2 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -284,8 +284,13 @@ static __always_inline void setup_smap(struct cpuinfo_x86 *c) raw_local_save_flags(eflags); BUG_ON(eflags & X86_EFLAGS_AC); - if (cpu_has(c, X86_FEATURE_SMAP)) + if (cpu_has(c, X86_FEATURE_SMAP)) { +#ifdef CONFIG_X86_SMAP set_in_cr4(X86_CR4_SMAP); +#else + clear_in_cr4(X86_CR4_SMAP); +#endif + } } /* -- cgit v0.10.2 From 4640c7ee9b8953237d05a61ea3ea93981d1bc961 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Thu, 13 Feb 2014 07:46:04 -0800 Subject: x86, smap: smap_violation() is bogus if CONFIG_X86_SMAP is off If CONFIG_X86_SMAP is disabled, smap_violation() tests for conditions which are incorrect (as the AC flag doesn't matter), causing spurious faults. The dynamic disabling of SMAP (nosmap on the command line) is fine because it disables X86_FEATURE_SMAP, therefore causing the static_cpu_has() to return false. Found by Fengguang Wu's test system. [ v3: move all predicates into smap_violation() ] [ v2: use IS_ENABLED() instead of #ifdef ] Reported-by: Fengguang Wu Link: http://lkml.kernel.org/r/20140213124550.GA30497@localhost Signed-off-by: H. Peter Anvin Cc: # v3.7+ diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 9d591c8..6dea040 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -1001,6 +1001,12 @@ static int fault_in_kernel_space(unsigned long address) static inline bool smap_violation(int error_code, struct pt_regs *regs) { + if (!IS_ENABLED(CONFIG_X86_SMAP)) + return false; + + if (!static_cpu_has(X86_FEATURE_SMAP)) + return false; + if (error_code & PF_USER) return false; @@ -1087,11 +1093,9 @@ __do_page_fault(struct pt_regs *regs, unsigned long error_code) if (unlikely(error_code & PF_RSVD)) pgtable_bad(regs, error_code, address); - if (static_cpu_has(X86_FEATURE_SMAP)) { - if (unlikely(smap_violation(error_code, regs))) { - bad_area_nosemaphore(regs, error_code, address); - return; - } + if (unlikely(smap_violation(error_code, regs))) { + bad_area_nosemaphore(regs, error_code, address); + return; } /* -- cgit v0.10.2 From 4196670be786d529ab7f6c18f5077141ce1b787e Mon Sep 17 00:00:00 2001 From: Matan Barak Date: Sun, 2 Feb 2014 17:06:47 +0200 Subject: IB/mlx4: Don't allocate range of steerable UD QPs for Ethernet-only device When the device has only Ethernet ports, don't try to allocate range of steerable UD QPs since they aren't needed. This fixes an issue where mlx4 VFs tried to allocate a range of UD steerable QPs, but failed to do so. Fixes: c1c98501121e ("IB/mlx4: Add support for steerable IB UD QPs") Signed-off-by: Matan Barak Signed-off-by: Or Gerlitz Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c index c2702f5..64ca408 100644 --- a/drivers/infiniband/hw/mlx4/main.c +++ b/drivers/infiniband/hw/mlx4/main.c @@ -1810,6 +1810,7 @@ static void *mlx4_ib_add(struct mlx4_dev *dev) int i, j; int err; struct mlx4_ib_iboe *iboe; + int ib_num_ports = 0; pr_info_once("%s", mlx4_ib_version); @@ -1985,10 +1986,14 @@ static void *mlx4_ib_add(struct mlx4_dev *dev) ibdev->counters[i] = -1; } + mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_IB) + ib_num_ports++; + spin_lock_init(&ibdev->sm_lock); mutex_init(&ibdev->cap_mask_mutex); - if (ibdev->steering_support == MLX4_STEERING_MODE_DEVICE_MANAGED) { + if (ibdev->steering_support == MLX4_STEERING_MODE_DEVICE_MANAGED && + ib_num_ports) { ibdev->steer_qpn_count = MLX4_IB_UC_MAX_NUM_QPS; err = mlx4_qp_reserve_range(dev, ibdev->steer_qpn_count, MLX4_IB_UC_STEER_QPN_ALIGN, -- cgit v0.10.2 From ce6acca65ee42c06ac54ec9ba918865d06cee29d Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Fri, 24 Jan 2014 18:09:41 +0100 Subject: serial: omap-serial: Move info message to probe function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently the info message about a missing wakeirq for uart is printed every time the serial driver's startup function is called. This happens multiple times and not just once. This can cause lots of extra messages at boot time, slowing things down. It is caused by commit 2a0b965cfb6e (serial: omap: Add support for optional wake-up) which was applied for v3.13-rc1. This patch moves the infomessage to the probe function to display it only once. Reported-by: Uwe Kleine-König Acked-by: Tony Lindgren Signed-off-by: Markus Pargmann Acked-by: Uwe Kleine-König Cc: stable # 3.13 Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index fa511eb..2051581 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -738,9 +738,6 @@ static int serial_omap_startup(struct uart_port *port) return retval; } disable_irq(up->wakeirq); - } else { - dev_info(up->port.dev, "no wakeirq for uart%d\n", - up->port.line); } dev_dbg(up->port.dev, "serial_omap_startup+%d\n", up->port.line); @@ -1687,6 +1684,9 @@ static int serial_omap_probe(struct platform_device *pdev) up->port.iotype = UPIO_MEM; up->port.irq = uartirq; up->wakeirq = wakeirq; + if (!up->wakeirq) + dev_info(up->port.dev, "no wakeirq for uart%d\n", + up->port.line); up->port.regshift = 2; up->port.fifosize = 64; -- cgit v0.10.2 From 13b949f03e642c5df36ebf5b4770d75f8c4a6b09 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Thu, 16 Jan 2014 14:55:57 +0200 Subject: serial: 8250_dw: fix compilation warning when !CONFIG_PM_SLEEP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CONFIG_PM will be set if either or both CONFIG_PM_SLEEP and CONFIG_PM_RUNTIME is set. Compiling the driver with !CONFIG_PM_SLEEP causes following compilation warnings: drivers/tty/serial/8250/8250_dw.c:404:12: warning: ‘dw8250_suspend’ defined but not used [-Wunused-function] drivers/tty/serial/8250/8250_dw.c:413:12: warning: ‘dw8250_resume’ defined but not used [-Wunused-function] Fix this by using CONFIG_PM_SLEEP instead. Signed-off-by: Mika Westerberg Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index faa64e6..ed31135 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -391,7 +391,7 @@ static int dw8250_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int dw8250_suspend(struct device *dev) { struct dw8250_data *data = dev_get_drvdata(dev); @@ -409,7 +409,7 @@ static int dw8250_resume(struct device *dev) return 0; } -#endif /* CONFIG_PM */ +#endif /* CONFIG_PM_SLEEP */ #ifdef CONFIG_PM_RUNTIME static int dw8250_runtime_suspend(struct device *dev) -- cgit v0.10.2 From a64c1a1c755674399da3689499b3f64c2a538120 Mon Sep 17 00:00:00 2001 From: Michael Grzeschik Date: Thu, 13 Feb 2014 10:52:03 +0100 Subject: serial: omap: fix rs485 probe on defered pinctrl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the gpio is not yet available we better also defer the probing in the rs485 case. Signed-off-by: Michael Grzeschik Signed-off-by: Uwe Kleine-König Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 2051581..77f0351 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -1601,8 +1601,11 @@ static int serial_omap_probe_rs485(struct uart_omap_port *up, flags & SER_RS485_RTS_AFTER_SEND); if (ret < 0) return ret; - } else + } else if (up->rts_gpio == -EPROBE_DEFER) { + return -EPROBE_DEFER; + } else { up->rts_gpio = -EINVAL; + } if (of_property_read_u32_array(np, "rs485-rts-delay", rs485_delay, 2) == 0) { -- cgit v0.10.2 From a5934804a834f525c9e6289935ceef65b952b101 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Tue, 11 Feb 2014 11:49:58 -0500 Subject: n_tty: Fix poll() when TIME_CHAR and MIN_CHAR == 0 Commit eafbe67f84761d787802e5113d895a316b6292fe, n_tty: Refactor input_available_p() by call site broke poll() when TIME_CHAR(tty) and MIN_CHAR(tty) are both 0. When TIME_CHAR and MIN_CHAR are both 0, input is available if the read_cnt is 1 (not 0). Reported-by: Eric Dumazet Tested-by: Eric Dumazet Reported-by: Stephane Eranian Tested-by: David Ahern Tested-by: Arnaldo Carvalho de Melo Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index cb8017a..2747a3b 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1896,7 +1896,7 @@ err: static inline int input_available_p(struct tty_struct *tty, int poll) { struct n_tty_data *ldata = tty->disc_data; - int amt = poll && !TIME_CHAR(tty) ? MIN_CHAR(tty) : 1; + int amt = poll && !TIME_CHAR(tty) && MIN_CHAR(tty) ? MIN_CHAR(tty) : 1; if (ldata->icanon && !L_EXTPROC(tty)) { if (ldata->canon_head != ldata->read_tail) -- cgit v0.10.2 From 333c085e4b0cd9df04b087d29f87969a4e26dfa9 Mon Sep 17 00:00:00 2001 From: Dmitry Eremin-Solenikov Date: Tue, 11 Feb 2014 14:18:13 +0400 Subject: serial: 8250_pci: unbreak last serial ports on NetMos 9865 cards Aparently 9865 uses standard BAR encoding scheme (unlike 99xx cards). Current pci_netmos_9900_setup() uses wrong BAR indices for the 9865 PCI device, function 2. Using standard BAR indices makes all 6 ports work for me. Thus disable the NetMos 9900 quirk for NetMos 9865 pci device. For the reference, here is the relevant part of lspci for my device: 02:07.0 Serial controller: MosChip Semiconductor Technology Ltd. PCI 9865 Multi-I/O Controller (prog-if 02 [16550]) Subsystem: Device a000:1000 Flags: bus master, medium devsel, latency 32, IRQ 17 I/O ports at ac00 [size=8] Memory at fcfff000 (32-bit, non-prefetchable) [size=4K] Memory at fcffe000 (32-bit, non-prefetchable) [size=4K] Capabilities: [48] Power Management version 2 Kernel driver in use: serial 02:07.1 Serial controller: MosChip Semiconductor Technology Ltd. PCI 9865 Multi-I/O Controller (prog-if 02 [16550]) Subsystem: Device a000:1000 Flags: bus master, medium devsel, latency 32, IRQ 18 I/O ports at a800 [size=8] Memory at fcffd000 (32-bit, non-prefetchable) [size=4K] Memory at fcffc000 (32-bit, non-prefetchable) [size=4K] Capabilities: [48] Power Management version 2 Kernel driver in use: serial 02:07.2 Communication controller: MosChip Semiconductor Technology Ltd. PCI 9865 Multi-I/O Controller Subsystem: Device a000:3004 Flags: bus master, medium devsel, latency 32, IRQ 19 I/O ports at a400 [size=8] I/O ports at a000 [size=8] I/O ports at 9c00 [size=8] I/O ports at 9800 [size=8] Memory at fcffb000 (32-bit, non-prefetchable) [size=4K] Capabilities: [48] Power Management version 2 Kernel driver in use: serial Signed-off-by: Dmitry Eremin-Solenikov Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 50228ee..0ff3e36 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -783,7 +783,8 @@ static int pci_netmos_9900_setup(struct serial_private *priv, { unsigned int bar; - if ((priv->dev->subsystem_device & 0xff00) == 0x3000) { + if ((priv->dev->device != PCI_DEVICE_ID_NETMOS_9865) && + (priv->dev->subsystem_device & 0xff00) == 0x3000) { /* netmos apparently orders BARs by datasheet layout, so serial * ports get BARs 0 and 3 (or 1 and 4 for memmapped) */ -- cgit v0.10.2 From fb78b811422cd2d8c8605949cc4cc13618347ad5 Mon Sep 17 00:00:00 2001 From: Qipan Li Date: Mon, 27 Jan 2014 14:23:39 +0800 Subject: serial: sirf: fix kernel panic caused by unpaired spinlock commit 8b9ade9f74f8a279 coming from Viresh Kumar "tty: serial: sirfsoc: drop uart_port->lock before calling tty_flip_buffer_push()" broke sirfsoc uart driver by knic: [ 5.129122] BUG: spinlock already unlocked on CPU#0, ip6tables/1331 [ 5.132554] lock: sirfsoc_uart_ports+0x4/0x8a0, .magic: dead4ead, .owner: /-1, .owner_cpu: -1 [ 5.141651] CPU: 0 PID: 1331 Comm: ip6tables Tainted: G W O 3.10.16 #3 [ 5.148866] [] (unwind_backtrace+0x0/0xe0) from [] (show_stack+0x10/0x14) [ 5.157362] [] (show_stack+0x10/0x14) from [] (do_raw_spin_unlock+0x40/0xc8) [ 5.166125] [] (do_raw_spin_unlock+0x40/0xc8) from [] (_raw_spin_unlock+0x8/0x40) [ 5.175322] [] (_raw_spin_unlock+0x8/0x40) from [] (sirfsoc_uart_pio_rx_chars+0xa4/0xc0) [ 5.185120] [] (sirfsoc_uart_pio_rx_chars+0xa4/0xc0) from [] (sirfsoc_rx_tmo_process_tl+0xdc/0x1e0) [ 5.195875] [] (sirfsoc_rx_tmo_process_tl+0xdc/0x1e0) from [] (tasklet_action+0x8c/0xec) [ 5.205673] [] (tasklet_action+0x8c/0xec) from [] (__do_softirq+0xec/0x1d4) [ 5.214347] [] (__do_softirq+0xec/0x1d4) from [] (do_softirq+0x48/0x54) [ 5.222674] [] (do_softirq+0x48/0x54) from [] (irq_exit+0x74/0xc0) [ 5.230573] [] (irq_exit+0x74/0xc0) from [] (handle_IRQ+0x6c/0x90) [ 5.238465] [] (handle_IRQ+0x6c/0x90) from [] (__irq_svc+0x40/0x70) [ 5.246446] [] (__irq_svc+0x40/0x70) from [] (mark_page_accessed+0xc/0x68) [ 5.255034] [] (mark_page_accessed+0xc/0x68) from [] (unmap_single_vma+0x3bc/0x550) [ 5.264402] [] (unmap_single_vma+0x3bc/0x550) from [] (unmap_vmas+0x44/0x54) [ 5.273164] [] (unmap_vmas+0x44/0x54) from [] (exit_mmap+0xc4/0x1e0) [ 5.281233] [] (exit_mmap+0xc4/0x1e0) from [] (mmput+0x3c/0xdc) [ 5.288868] [] (mmput+0x3c/0xdc) from [] (do_exit+0x30c/0x828) [ 5.296413] [] (do_exit+0x30c/0x828) from [] (do_group_exit+0x4c/0xb0) [ 5.304653] [] (do_group_exit+0x4c/0xb0) from [] (__wake_up_parent+0x0/0x18) Root cause: the commit dropped uart_port->lock before calling tty_flip_buffer_push(), but in sirfsoc-uart, sirfsoc_uart_pio_rx_chars() can be called by sirfsoc_rx_tmo_process_tl(). here uart_port->lock has not been taken yet. so that caused unpaired lock/unlock. Solution: This patch is doing a quick fix for that, it adds spin_lock/unlock(&port->lock) protect to sirfsoc_uart_pio_rx_chars() in sirfsoc_rx_tmo_process_tl() to keep spin_lock/unlock in pair. Signed-off-by: Qipan Li Signed-off-by: Barry Song Cc: stable # 3.12 Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/sirfsoc_uart.c b/drivers/tty/serial/sirfsoc_uart.c index 49a2ffd..b7bfe24 100644 --- a/drivers/tty/serial/sirfsoc_uart.c +++ b/drivers/tty/serial/sirfsoc_uart.c @@ -542,8 +542,10 @@ static void sirfsoc_rx_tmo_process_tl(unsigned long param) wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl, rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) | SIRFUART_IO_MODE); - sirfsoc_uart_pio_rx_chars(port, 4 - sirfport->rx_io_count); spin_unlock_irqrestore(&sirfport->rx_lock, flags); + spin_lock(&port->lock); + sirfsoc_uart_pio_rx_chars(port, 4 - sirfport->rx_io_count); + spin_unlock(&port->lock); if (sirfport->rx_io_count == 4) { spin_lock_irqsave(&sirfport->rx_lock, flags); sirfport->rx_io_count = 0; -- cgit v0.10.2 From e2613be5093d04e6589924d36a1e363eef3c87c7 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Tue, 11 Feb 2014 16:34:55 -0500 Subject: n_tty: Fix stale echo output When echoes cannot be flushed to output (usually because the tty has no more write room) and L_ECHO is subsequently turned off, then when L_ECHO is turned back on, stale echoes are output. Output completed echoes regardless of the L_ECHO setting: 1. before normal writes to that tty 2. if the tty was stopped by soft flow control and is being restarted Reported-by: Mikulas Patocka Cc: # 3.13.x Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 2747a3b..d15624c 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -817,8 +817,7 @@ static void process_echoes(struct tty_struct *tty) struct n_tty_data *ldata = tty->disc_data; size_t echoed; - if ((!L_ECHO(tty) && !L_ECHONL(tty)) || - ldata->echo_mark == ldata->echo_tail) + if (ldata->echo_mark == ldata->echo_tail) return; mutex_lock(&ldata->output_lock); @@ -1244,7 +1243,8 @@ n_tty_receive_signal_char(struct tty_struct *tty, int signal, unsigned char c) if (L_ECHO(tty)) { echo_char(c, tty); commit_echoes(tty); - } + } else + process_echoes(tty); isig(signal, tty); return; } @@ -1274,7 +1274,7 @@ n_tty_receive_char_special(struct tty_struct *tty, unsigned char c) if (I_IXON(tty)) { if (c == START_CHAR(tty)) { start_tty(tty); - commit_echoes(tty); + process_echoes(tty); return 0; } if (c == STOP_CHAR(tty)) { @@ -1820,8 +1820,10 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old) * Fix tty hang when I_IXON(tty) is cleared, but the tty * been stopped by STOP_CHAR(tty) before it. */ - if (!I_IXON(tty) && old && (old->c_iflag & IXON) && !tty->flow_stopped) + if (!I_IXON(tty) && old && (old->c_iflag & IXON) && !tty->flow_stopped) { start_tty(tty); + process_echoes(tty); + } /* The termios change make the tty ready for I/O */ if (waitqueue_active(&tty->write_wait)) -- cgit v0.10.2 From 45a7bd635930baa960b6817674c64bdfb8f39570 Mon Sep 17 00:00:00 2001 From: Joe Schultz Date: Tue, 11 Feb 2014 18:30:01 -0600 Subject: serial: 8250: Support XR17V35x fraction divisor The Exar XR17V35x family of UARTs have an additional fractional divisor register (DLD) which was not being used. Calculate and set this register for these devices to reduce their baud rate error. Signed-off-by: Joe Schultz Signed-off-by: Aaron Sierra Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index 61ecd70..69932b7 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -2433,6 +2433,24 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, serial_dl_write(up, quot); /* + * XR17V35x UARTs have an extra fractional divisor register (DLD) + * + * We need to recalculate all of the registers, because DLM and DLL + * are already rounded to a whole integer. + * + * When recalculating we use a 32x clock instead of a 16x clock to + * allow 1-bit for rounding in the fractional part. + */ + if (up->port.type == PORT_XR17V35X) { + unsigned int baud_x32 = (port->uartclk * 2) / baud; + u16 quot = baud_x32 / 32; + u8 quot_frac = DIV_ROUND_CLOSEST(baud_x32 % 32, 2); + + serial_dl_write(up, quot); + serial_port_out(port, 0x2, quot_frac & 0xf); + } + + /* * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR * is written without DLAB set, this mode will be disabled. */ -- cgit v0.10.2 From 0930b0950a8996aa88b0d2ba4bb2bab27cc36bc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= Date: Thu, 6 Feb 2014 21:01:23 +0100 Subject: vt: Fix secure clear screen MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit \E[3J console code (secure clear screen) needs to update_screen(vc) in order to write-through blanks into off-screen video memory. This has been removed accidentally in 3.6 by: commit 81732c3b2fede049a692e58a7ceabb6d18ffb18c Author: Jean-François Moine Date: Thu Sep 6 19:24:13 2012 +0200 tty vt: Fix line garbage in virtual console on command line edition Signed-off-by: Petr Písař Cc: stable # 3.6 Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 61b1137..23b5d32 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -1164,6 +1164,8 @@ static void csi_J(struct vc_data *vc, int vpar) scr_memsetw(vc->vc_screenbuf, vc->vc_video_erase_char, vc->vc_screenbuf_size >> 1); set_origin(vc); + if (CON_IS_VISIBLE(vc)) + update_screen(vc); /* fall through */ case 2: /* erase whole display */ count = vc->vc_cols * vc->vc_rows; -- cgit v0.10.2 From 2ec197db1a56c9269d75e965f14c344b58b2a4f6 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Fri, 7 Feb 2014 17:10:26 +1100 Subject: lockd: send correct lock when granting a delayed lock. If an NFS client attempts to get a lock (using NLM) and the lock is not available, the server will remember the request and when the lock becomes available it will send a GRANT request to the client to provide the lock. If the client already held an adjacent lock, the GRANT callback will report the union of the existing and new locks, which can confuse the client. This happens because __posix_lock_file (called by vfs_lock_file) updates the passed-in file_lock structure when adjacent or over-lapping locks are found. To avoid this problem we take a copy of the two fields that can be changed (fl_start and fl_end) before the call and restore them afterwards. An alternate would be to allocate a 'struct file_lock', initialise it, use locks_copy_lock() to take a copy, then locks_release_private() after the vfs_lock_file() call. But that is a lot more work. Reported-by: Olaf Kirch Signed-off-by: NeilBrown Cc: stable@vger.kernel.org Signed-off-by: J. Bruce Fields -- v1 had a couple of issues (large on-stack struct and didn't really work properly). This version is much better tested. Signed-off-by: J. Bruce Fields diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index e066a39..ab798a8 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c @@ -779,6 +779,7 @@ nlmsvc_grant_blocked(struct nlm_block *block) struct nlm_file *file = block->b_file; struct nlm_lock *lock = &block->b_call->a_args.lock; int error; + loff_t fl_start, fl_end; dprintk("lockd: grant blocked lock %p\n", block); @@ -796,9 +797,16 @@ nlmsvc_grant_blocked(struct nlm_block *block) } /* Try the lock operation again */ + /* vfs_lock_file() can mangle fl_start and fl_end, but we need + * them unchanged for the GRANT_MSG + */ lock->fl.fl_flags |= FL_SLEEP; + fl_start = lock->fl.fl_start; + fl_end = lock->fl.fl_end; error = vfs_lock_file(file->f_file, F_SETLK, &lock->fl, NULL); lock->fl.fl_flags &= ~FL_SLEEP; + lock->fl.fl_start = fl_start; + lock->fl.fl_end = fl_end; switch (error) { case 0: -- cgit v0.10.2 From dd5fd9b91a77b4c9c28b7ef9c181b1a875820d0a Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 11 Feb 2014 14:35:40 +0100 Subject: tick: Clear broadcast pending bit when switching to oneshot AMD systems which use the C1E workaround in the amd_e400_idle routine trigger the WARN_ON_ONCE in the broadcast code when onlining a CPU. The reason is that the idle routine of those AMD systems switches the cpu into forced broadcast mode early on before the newly brought up CPU can switch over to high resolution / NOHZ mode. The timer related CPU1 bringup looks like this: clockevent_register_device(local_apic); tick_setup(local_apic); ... idle() tick_broadcast_on_off(FORCE); tick_broadcast_oneshot_control(ENTER) cpumask_set(cpu, broadcast_oneshot_mask); halt(); Now the broadcast interrupt on CPU0 sets CPU1 in the broadcast_pending_mask and wakes CPU1. So CPU1 continues: local_apic_timer_interrupt() tick_handle_periodic(); softirq() tick_init_highres(); cpumask_clr(cpu, broadcast_oneshot_mask); tick_broadcast_oneshot_control(ENTER) WARN_ON(cpumask_test(cpu, broadcast_pending_mask); So while we remove CPU1 from the broadcast_oneshot_mask when we switch over to highres mode, we do not clear the pending bit, which then triggers the warning when we go back to idle. The reason why this is only visible on C1E affected AMD systems is that the other machines enter the deep sleep states via acpi_idle/intel_idle and exit the broadcast mode before executing the remote triggered local_apic_timer_interrupt. So the pending bit is already cleared when the switch over to highres mode is clearing the oneshot mask. The solution is simple: Clear the pending bit together with the mask bit when we switch over to highres mode. Stanislaw came up independently with the same patch by enforcing the C1E workaround and debugging the fallout. I picked mine, because mine has a changelog :) Reported-by: poma Debugged-by: Stanislaw Gruszka Signed-off-by: Thomas Gleixner Cc: Olaf Hering Cc: Dave Jones Cc: Justin M. Forbes Cc: Josh Boyer Link: http://lkml.kernel.org/r/alpine.DEB.2.02.1402111434180.21991@ionos.tec.linutronix.de Cc: stable@vger.kernel.org # 3.10+ Signed-off-by: Thomas Gleixner diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c index 43780ab..98977a5 100644 --- a/kernel/time/tick-broadcast.c +++ b/kernel/time/tick-broadcast.c @@ -756,6 +756,7 @@ out: static void tick_broadcast_clear_oneshot(int cpu) { cpumask_clear_cpu(cpu, tick_broadcast_oneshot_mask); + cpumask_clear_cpu(cpu, tick_broadcast_pending_mask); } static void tick_broadcast_init_next_event(struct cpumask *mask, -- cgit v0.10.2 From acc4fccf4eff5b29e545995b75de77e60ea44aae Mon Sep 17 00:00:00 2001 From: Moni Shoua Date: Wed, 5 Feb 2014 15:12:58 +0200 Subject: IB/mlx4: Make sure GID index 0 is always occupied Make sure that for Ethernet ports, the port GID table index 0 is always occupied with a default GID of the relevant IPv6 link-local adderss. This provides better user experience for legacy applications that don't use the RDMA CM and were working on index 0 prior to the IP addressing change. Also, as GIDs are generated from IP addresses of the network devices that are associated with the port, it's basically possible that the GID table will be empty if no IP address was assigned. This doesn't comply with the IB spec section 4.1.1 "GID usage and properties". Signed-off-by: Moni Shoua Signed-off-by: Or Gerlitz Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c index 64ca408..b99d0ec 100644 --- a/drivers/infiniband/hw/mlx4/main.c +++ b/drivers/infiniband/hw/mlx4/main.c @@ -1357,6 +1357,21 @@ static struct device_attribute *mlx4_class_attributes[] = { &dev_attr_board_id }; +static void mlx4_addrconf_ifid_eui48(u8 *eui, u16 vlan_id, + struct net_device *dev) +{ + memcpy(eui, dev->dev_addr, 3); + memcpy(eui + 5, dev->dev_addr + 3, 3); + if (vlan_id < 0x1000) { + eui[3] = vlan_id >> 8; + eui[4] = vlan_id & 0xff; + } else { + eui[3] = 0xff; + eui[4] = 0xfe; + } + eui[0] ^= 2; +} + static void update_gids_task(struct work_struct *work) { struct update_gid_work *gw = container_of(work, struct update_gid_work, work); @@ -1425,7 +1440,8 @@ free: } static int update_gid_table(struct mlx4_ib_dev *dev, int port, - union ib_gid *gid, int clear) + union ib_gid *gid, int clear, + int default_gid) { struct update_gid_work *work; int i; @@ -1434,26 +1450,31 @@ static int update_gid_table(struct mlx4_ib_dev *dev, int port, int found = -1; int max_gids; - max_gids = dev->dev->caps.gid_table_len[port]; - for (i = 0; i < max_gids; ++i) { - if (!memcmp(&dev->iboe.gid_table[port - 1][i], gid, - sizeof(*gid))) - found = i; - - if (clear) { - if (found >= 0) { - need_update = 1; - dev->iboe.gid_table[port - 1][found] = zgid; - break; - } - } else { - if (found >= 0) - break; - - if (free < 0 && - !memcmp(&dev->iboe.gid_table[port - 1][i], &zgid, + if (default_gid) { + free = 0; + } else { + max_gids = dev->dev->caps.gid_table_len[port]; + for (i = 1; i < max_gids; ++i) { + if (!memcmp(&dev->iboe.gid_table[port - 1][i], gid, sizeof(*gid))) - free = i; + found = i; + + if (clear) { + if (found >= 0) { + need_update = 1; + dev->iboe.gid_table[port - 1][found] = + zgid; + break; + } + } else { + if (found >= 0) + break; + + if (free < 0 && + !memcmp(&dev->iboe.gid_table[port - 1][i], + &zgid, sizeof(*gid))) + free = i; + } } } @@ -1478,6 +1499,13 @@ static int update_gid_table(struct mlx4_ib_dev *dev, int port, return 0; } +static void mlx4_make_default_gid(struct net_device *dev, union ib_gid *gid) +{ + gid->global.subnet_prefix = cpu_to_be64(0xfe80000000000000LL); + mlx4_addrconf_ifid_eui48(&gid->raw[8], 0xffff, dev); +} + + static int reset_gid_table(struct mlx4_ib_dev *dev) { struct update_gid_work *work; @@ -1502,6 +1530,12 @@ static int mlx4_ib_addr_event(int event, struct net_device *event_netdev, struct net_device *real_dev = rdma_vlan_dev_real_dev(event_netdev) ? rdma_vlan_dev_real_dev(event_netdev) : event_netdev; + union ib_gid default_gid; + + mlx4_make_default_gid(real_dev, &default_gid); + + if (!memcmp(gid, &default_gid, sizeof(*gid))) + return 0; if (event != NETDEV_DOWN && event != NETDEV_UP) return 0; @@ -1520,7 +1554,7 @@ static int mlx4_ib_addr_event(int event, struct net_device *event_netdev, (!netif_is_bond_master(real_dev) && (real_dev == iboe->netdevs[port - 1]))) update_gid_table(ibdev, port, gid, - event == NETDEV_DOWN); + event == NETDEV_DOWN, 0); spin_unlock(&iboe->lock); return 0; @@ -1607,7 +1641,7 @@ static void mlx4_ib_get_dev_addr(struct net_device *dev, /*ifa->ifa_address;*/ ipv6_addr_set_v4mapped(ifa->ifa_address, (struct in6_addr *)&gid); - update_gid_table(ibdev, port, &gid, 0); + update_gid_table(ibdev, port, &gid, 0, 0); } endfor_ifa(in_dev); in_dev_put(in_dev); @@ -1619,7 +1653,7 @@ static void mlx4_ib_get_dev_addr(struct net_device *dev, read_lock_bh(&in6_dev->lock); list_for_each_entry(ifp, &in6_dev->addr_list, if_list) { pgid = (union ib_gid *)&ifp->addr; - update_gid_table(ibdev, port, pgid, 0); + update_gid_table(ibdev, port, pgid, 0, 0); } read_unlock_bh(&in6_dev->lock); in6_dev_put(in6_dev); @@ -1627,6 +1661,14 @@ static void mlx4_ib_get_dev_addr(struct net_device *dev, #endif } +static void mlx4_ib_set_default_gid(struct mlx4_ib_dev *ibdev, + struct net_device *dev, u8 port) +{ + union ib_gid gid; + mlx4_make_default_gid(dev, &gid); + update_gid_table(ibdev, port, &gid, 0, 1); +} + static int mlx4_ib_init_gid_table(struct mlx4_ib_dev *ibdev) { struct net_device *dev; @@ -1660,7 +1702,9 @@ static void mlx4_ib_scan_netdevs(struct mlx4_ib_dev *ibdev) struct net_device *curr_master; iboe->netdevs[port - 1] = mlx4_get_protocol_dev(ibdev->dev, MLX4_PROT_ETH, port); - + if (iboe->netdevs[port - 1]) + mlx4_ib_set_default_gid(ibdev, + iboe->netdevs[port - 1], port); if (iboe->netdevs[port - 1] && netif_is_bond_slave(iboe->netdevs[port - 1])) { rtnl_lock(); -- cgit v0.10.2 From 4ce5a5744a2f5479e58c6788cbe3987b8071b62e Mon Sep 17 00:00:00 2001 From: Moni Shoua Date: Wed, 5 Feb 2014 15:12:59 +0200 Subject: IB/mlx4: Move rtnl locking to the right place On the one hand, the invocation of netdev_master_upper_dev_get() within mlx4_ib_scan_netdevs() must be done with rtnl lock held. On the other hand, it's wrong to call rtnl_lock() from within this function since it's also called by our netdev notifier callback. Therefore move the locking to mlx4_ib_add() so that both cases are covered. Signed-off-by: Moni Shoua Signed-off-by: Or Gerlitz Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c index b99d0ec..93f492f 100644 --- a/drivers/infiniband/hw/mlx4/main.c +++ b/drivers/infiniband/hw/mlx4/main.c @@ -1707,10 +1707,8 @@ static void mlx4_ib_scan_netdevs(struct mlx4_ib_dev *ibdev) iboe->netdevs[port - 1], port); if (iboe->netdevs[port - 1] && netif_is_bond_slave(iboe->netdevs[port - 1])) { - rtnl_lock(); iboe->masters[port - 1] = netdev_master_upper_dev_get( iboe->netdevs[port - 1]); - rtnl_unlock(); } curr_master = iboe->masters[port - 1]; @@ -2100,7 +2098,9 @@ static void *mlx4_ib_add(struct mlx4_dev *dev) } } #endif + rtnl_lock(); mlx4_ib_scan_netdevs(ibdev); + rtnl_unlock(); mlx4_ib_init_gid_table(ibdev); } -- cgit v0.10.2 From ddf8bd349115c2bc85a62e3d94018c9976ac72f7 Mon Sep 17 00:00:00 2001 From: Moni Shoua Date: Wed, 5 Feb 2014 15:13:00 +0200 Subject: IB/mlx4: Do IBoE locking earlier when initializing the GID table Updating the GID table under IBoE requires read/write from/to shared data structures. These data structures are protected with the device iboe lock. The flows that modify the GID table start from 1. Initializing the GID table 2. NETDEV events 3. INET or INET6 events This patch makes sure that the flow of initializing the GID table is consistent with the other two flows w.r.t on what step the lock is taken. Signed-off-by: Moni Shoua Signed-off-by: Or Gerlitz Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c index 93f492f..3bafd0b 100644 --- a/drivers/infiniband/hw/mlx4/main.c +++ b/drivers/infiniband/hw/mlx4/main.c @@ -1570,7 +1570,6 @@ static u8 mlx4_ib_get_dev_port(struct net_device *dev, rdma_vlan_dev_real_dev(dev) : dev; iboe = &ibdev->iboe; - spin_lock(&iboe->lock); for (port = 1; port <= MLX4_MAX_PORTS; ++port) if ((netif_is_bond_master(real_dev) && @@ -1579,8 +1578,6 @@ static u8 mlx4_ib_get_dev_port(struct net_device *dev, (real_dev == iboe->netdevs[port - 1]))) break; - spin_unlock(&iboe->lock); - if ((port == 0) || (port > MLX4_MAX_PORTS)) return 0; else @@ -1672,11 +1669,13 @@ static void mlx4_ib_set_default_gid(struct mlx4_ib_dev *ibdev, static int mlx4_ib_init_gid_table(struct mlx4_ib_dev *ibdev) { struct net_device *dev; + struct mlx4_ib_iboe *iboe = &ibdev->iboe; if (reset_gid_table(ibdev)) return -1; read_lock(&dev_base_lock); + spin_lock(&iboe->lock); for_each_netdev(&init_net, dev) { u8 port = mlx4_ib_get_dev_port(dev, ibdev); @@ -1684,6 +1683,7 @@ static int mlx4_ib_init_gid_table(struct mlx4_ib_dev *ibdev) mlx4_ib_get_dev_addr(dev, ibdev, port); } + spin_unlock(&iboe->lock); read_unlock(&dev_base_lock); return 0; -- cgit v0.10.2 From 5071456fe244e409adcda7226e5f0b5d1b879fd3 Mon Sep 17 00:00:00 2001 From: Moni Shoua Date: Wed, 5 Feb 2014 15:13:01 +0200 Subject: IB/mlx4: Do IBoE GID table resets per-port The IBoE code used to reset the GID table did it for all Ethernet ports of the device. Since the whole architecture of generating GIDs and responding to events is port-based, this is inefficient and can lead to wrong content in the GID table. Change the reset flow to be per-port. Signed-off-by: Moni Shoua Signed-off-by: Or Gerlitz Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c index 3bafd0b..8e10630 100644 --- a/drivers/infiniband/hw/mlx4/main.c +++ b/drivers/infiniband/hw/mlx4/main.c @@ -1408,7 +1408,6 @@ static void reset_gids_task(struct work_struct *work) struct mlx4_cmd_mailbox *mailbox; union ib_gid *gids; int err; - int i; struct mlx4_dev *dev = gw->dev->dev; mailbox = mlx4_alloc_cmd_mailbox(dev); @@ -1420,18 +1419,16 @@ static void reset_gids_task(struct work_struct *work) gids = mailbox->buf; memcpy(gids, gw->gids, sizeof(gw->gids)); - for (i = 1; i < gw->dev->num_ports + 1; i++) { - if (mlx4_ib_port_link_layer(&gw->dev->ib_dev, i) == - IB_LINK_LAYER_ETHERNET) { - err = mlx4_cmd(dev, mailbox->dma, - MLX4_SET_PORT_GID_TABLE << 8 | i, - 1, MLX4_CMD_SET_PORT, - MLX4_CMD_TIME_CLASS_B, - MLX4_CMD_WRAPPED); - if (err) - pr_warn(KERN_WARNING - "set port %d command failed\n", i); - } + if (mlx4_ib_port_link_layer(&gw->dev->ib_dev, gw->port) == + IB_LINK_LAYER_ETHERNET) { + err = mlx4_cmd(dev, mailbox->dma, + MLX4_SET_PORT_GID_TABLE << 8 | gw->port, + 1, MLX4_CMD_SET_PORT, + MLX4_CMD_TIME_CLASS_B, + MLX4_CMD_WRAPPED); + if (err) + pr_warn(KERN_WARNING + "set port %d command failed\n", gw->port); } mlx4_free_cmd_mailbox(dev, mailbox); @@ -1506,7 +1503,7 @@ static void mlx4_make_default_gid(struct net_device *dev, union ib_gid *gid) } -static int reset_gid_table(struct mlx4_ib_dev *dev) +static int reset_gid_table(struct mlx4_ib_dev *dev, u8 port) { struct update_gid_work *work; @@ -1514,10 +1511,12 @@ static int reset_gid_table(struct mlx4_ib_dev *dev) work = kzalloc(sizeof(*work), GFP_ATOMIC); if (!work) return -ENOMEM; - memset(dev->iboe.gid_table, 0, sizeof(dev->iboe.gid_table)); + + memset(dev->iboe.gid_table[port - 1], 0, sizeof(work->gids)); memset(work->gids, 0, sizeof(work->gids)); INIT_WORK(&work->work, reset_gids_task); work->dev = dev; + work->port = port; queue_work(wq, &work->work); return 0; } @@ -1670,9 +1669,11 @@ static int mlx4_ib_init_gid_table(struct mlx4_ib_dev *ibdev) { struct net_device *dev; struct mlx4_ib_iboe *iboe = &ibdev->iboe; + int i; - if (reset_gid_table(ibdev)) - return -1; + for (i = 1; i <= ibdev->num_ports; ++i) + if (reset_gid_table(ibdev, i)) + return -1; read_lock(&dev_base_lock); spin_lock(&iboe->lock); -- cgit v0.10.2 From ad4885d279b63c65347220236d07669a2f59634b Mon Sep 17 00:00:00 2001 From: Moni Shoua Date: Wed, 5 Feb 2014 15:13:02 +0200 Subject: IB/mlx4: Build the port IBoE GID table properly under bonding When scanning netdevices we need to check a few more conditions and cases to build the IBoE GID table properly. For example, under bonding we must make sure that when a port is down, the bond IP address isn't programmed as a GID, since doing so will cause failure with IB core flows that selects ports by GID. Signed-off-by: Moni Shoua Signed-off-by: Or Gerlitz Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c index 8e10630..fdb5c7c 100644 --- a/drivers/infiniband/hw/mlx4/main.c +++ b/drivers/infiniband/hw/mlx4/main.c @@ -1507,7 +1507,6 @@ static int reset_gid_table(struct mlx4_ib_dev *dev, u8 port) { struct update_gid_work *work; - work = kzalloc(sizeof(*work), GFP_ATOMIC); if (!work) return -ENOMEM; @@ -1699,25 +1698,57 @@ static void mlx4_ib_scan_netdevs(struct mlx4_ib_dev *ibdev) spin_lock(&iboe->lock); mlx4_foreach_ib_transport_port(port, ibdev->dev) { + enum ib_port_state port_state = IB_PORT_NOP; struct net_device *old_master = iboe->masters[port - 1]; + struct net_device *curr_netdev; struct net_device *curr_master; + iboe->netdevs[port - 1] = mlx4_get_protocol_dev(ibdev->dev, MLX4_PROT_ETH, port); if (iboe->netdevs[port - 1]) mlx4_ib_set_default_gid(ibdev, iboe->netdevs[port - 1], port); + curr_netdev = iboe->netdevs[port - 1]; + if (iboe->netdevs[port - 1] && netif_is_bond_slave(iboe->netdevs[port - 1])) { iboe->masters[port - 1] = netdev_master_upper_dev_get( iboe->netdevs[port - 1]); + } else { + iboe->masters[port - 1] = NULL; } curr_master = iboe->masters[port - 1]; + if (curr_netdev) { + port_state = (netif_running(curr_netdev) && netif_carrier_ok(curr_netdev)) ? + IB_PORT_ACTIVE : IB_PORT_DOWN; + mlx4_ib_set_default_gid(ibdev, curr_netdev, port); + } else { + reset_gid_table(ibdev, port); + } + /* if using bonding/team and a slave port is down, we don't the bond IP + * based gids in the table since flows that select port by gid may get + * the down port. + */ + if (curr_master && (port_state == IB_PORT_DOWN)) { + reset_gid_table(ibdev, port); + mlx4_ib_set_default_gid(ibdev, curr_netdev, port); + } /* if bonding is used it is possible that we add it to masters - only after IP address is assigned to the net bonding - interface */ - if (curr_master && (old_master != curr_master)) + * only after IP address is assigned to the net bonding + * interface. + */ + if (curr_master && (old_master != curr_master)) { + reset_gid_table(ibdev, port); + mlx4_ib_set_default_gid(ibdev, curr_netdev, port); mlx4_ib_get_dev_addr(curr_master, ibdev, port); + } + + if (!curr_master && (old_master != curr_master)) { + reset_gid_table(ibdev, port); + mlx4_ib_set_default_gid(ibdev, curr_netdev, port); + mlx4_ib_get_dev_addr(curr_netdev, ibdev, port); + } } spin_unlock(&iboe->lock); @@ -2099,6 +2130,8 @@ static void *mlx4_ib_add(struct mlx4_dev *dev) } } #endif + for (i = 1 ; i <= ibdev->num_ports ; ++i) + reset_gid_table(ibdev, i); rtnl_lock(); mlx4_ib_scan_netdevs(ibdev); rtnl_unlock(); -- cgit v0.10.2 From b4a26a27287a7f81933ba016aeed6c69dd155323 Mon Sep 17 00:00:00 2001 From: Moni Shoua Date: Sun, 9 Feb 2014 11:54:34 +0200 Subject: IB: Report using RoCE IP based gids in port caps For userspace RoCE UD QPs we need to know the GID format that the kernel uses, e.g when working over older kernels. For that end, add a new port capability IB_PORT_IP_BASED_GIDS and report it when query port is issued. Signed-off-by: Moni Shoua Signed-off-by: Matan Barak Signed-off-by: Or Gerlitz Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c index c2702f5..5d4088a 100644 --- a/drivers/infiniband/hw/mlx4/main.c +++ b/drivers/infiniband/hw/mlx4/main.c @@ -347,7 +347,7 @@ static int eth_link_query_port(struct ib_device *ibdev, u8 port, props->active_width = (((u8 *)mailbox->buf)[5] == 0x40) ? IB_WIDTH_4X : IB_WIDTH_1X; props->active_speed = IB_SPEED_QDR; - props->port_cap_flags = IB_PORT_CM_SUP; + props->port_cap_flags = IB_PORT_CM_SUP | IB_PORT_IP_BASED_GIDS; props->gid_tbl_len = mdev->dev->caps.gid_table_len[port]; props->max_msg_sz = mdev->dev->caps.max_msg_sz; props->pkey_tbl_len = 1; diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c index aa92f40..7890e7b 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c @@ -176,7 +176,7 @@ int ocrdma_query_port(struct ib_device *ibdev, props->port_cap_flags = IB_PORT_CM_SUP | IB_PORT_REINIT_SUP | - IB_PORT_DEVICE_MGMT_SUP | IB_PORT_VENDOR_CLASS_SUP; + IB_PORT_DEVICE_MGMT_SUP | IB_PORT_VENDOR_CLASS_SUP | IB_PORT_IP_BASED_GIDS; props->gid_tbl_len = OCRDMA_MAX_SGID; props->pkey_tbl_len = 1; props->bad_pkey_cntr = 0; diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h index 8d4a1c0..6793f32 100644 --- a/include/rdma/ib_verbs.h +++ b/include/rdma/ib_verbs.h @@ -226,7 +226,8 @@ enum ib_port_cap_flags { IB_PORT_CAP_MASK_NOTICE_SUP = 1 << 22, IB_PORT_BOOT_MGMT_SUP = 1 << 23, IB_PORT_LINK_LATENCY_SUP = 1 << 24, - IB_PORT_CLIENT_REG_SUP = 1 << 25 + IB_PORT_CLIENT_REG_SUP = 1 << 25, + IB_PORT_IP_BASED_GIDS = 1 << 26 }; enum ib_port_width { -- cgit v0.10.2 From 0f0132001fd239bb67c1f68436b95cc79de89736 Mon Sep 17 00:00:00 2001 From: Kumar Sanghvi Date: Thu, 6 Feb 2014 16:00:16 +0530 Subject: RDMA/cxgb4: Add missing neigh_release in LE-Workaround path Signed-off-by: Kumar Sanghvi Signed-off-by: Hariprasad Shenai Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c index 4512687..d286bde 100644 --- a/drivers/infiniband/hw/cxgb4/cm.c +++ b/drivers/infiniband/hw/cxgb4/cm.c @@ -3352,6 +3352,7 @@ static int rx_pkt(struct c4iw_dev *dev, struct sk_buff *skb) goto free_dst; } + neigh_release(neigh); step = dev->rdev.lldi.nrxq / dev->rdev.lldi.nchan; rss_qid = dev->rdev.lldi.rxq_ids[pi->port_id * step]; window = (__force u16) htons((__force u16)tcph->window); -- cgit v0.10.2 From 2f75e12c4457a9b3d042c0a0d748fa198dc2ffaf Mon Sep 17 00:00:00 2001 From: Mike Marciniszyn Date: Wed, 12 Feb 2014 11:54:15 -0500 Subject: IB/qib: Add missing serdes init sequence Research has shown that commit a77fcf895046 ("IB/qib: Use a single txselect module parameter for serdes tuning") missed a key serdes init sequence. This patch add that sequence. Cc: Reviewed-by: Dennis Dalessandro Signed-off-by: Mike Marciniszyn Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c index 5bfc02f..d1bd213 100644 --- a/drivers/infiniband/hw/qib/qib_iba7322.c +++ b/drivers/infiniband/hw/qib/qib_iba7322.c @@ -2395,6 +2395,11 @@ static int qib_7322_bringup_serdes(struct qib_pportdata *ppd) qib_write_kreg_port(ppd, krp_ibcctrl_a, ppd->cpspec->ibcctrl_a); qib_write_kreg(dd, kr_scratch, 0ULL); + /* ensure previous Tx parameters are not still forced */ + qib_write_kreg_port(ppd, krp_tx_deemph_override, + SYM_MASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0, + reset_tx_deemphasis_override)); + if (qib_compat_ddr_negotiate) { ppd->cpspec->ibdeltainprog = 1; ppd->cpspec->ibsymsnap = read_7322_creg32_port(ppd, -- cgit v0.10.2 From d3d89c468ceebbcf9423d1a3d66c5bf91f569570 Mon Sep 17 00:00:00 2001 From: Doug Anderson Date: Thu, 13 Feb 2014 14:39:34 -0800 Subject: hwmon: (ntc_thermistor) Avoid math overflow The ntc thermistor code was doing math whose temporary result might have overflowed 32-bits. We need some casts in there to make it safe. In one example I found: - pullup_uV: 1800000 - result of iio_read_channel_raw: 3226 - 1800000 * 3226 => 0x15a1cbc80 Signed-off-by: Doug Anderson Cc: stable@vger.kernel.org # 3.10+ Signed-off-by: Guenter Roeck diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c index 8c23203..8a17f01 100644 --- a/drivers/hwmon/ntc_thermistor.c +++ b/drivers/hwmon/ntc_thermistor.c @@ -145,7 +145,7 @@ struct ntc_data { static int ntc_adc_iio_read(struct ntc_thermistor_platform_data *pdata) { struct iio_channel *channel = pdata->chan; - unsigned int result; + s64 result; int val, ret; ret = iio_read_channel_raw(channel, &val); @@ -155,10 +155,10 @@ static int ntc_adc_iio_read(struct ntc_thermistor_platform_data *pdata) } /* unit: mV */ - result = pdata->pullup_uv * val; + result = pdata->pullup_uv * (s64) val; result >>= 12; - return result; + return (int)result; } static const struct of_device_id ntc_match[] = { -- cgit v0.10.2 From 6ecde51dd7894ffe2f959cca1fea3ea2b9ee2394 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Thu, 13 Feb 2014 20:45:17 -0800 Subject: mlx5: Add include of because of kzalloc()/kfree() use On some architectures (for example, arm), we don't end up indirectly pulling in the declaration of kzalloc() and kfree(), and so building anything that includes breaks. Fix this by adding an explicit include to get the declaration. Reported-by: kbuild test robot Signed-off-by: Roland Dreier diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h index 32cb18c..130bc8d 100644 --- a/include/linux/mlx5/driver.h +++ b/include/linux/mlx5/driver.h @@ -38,8 +38,10 @@ #include #include #include +#include #include #include + #include #include -- cgit v0.10.2 From 0861565f501ce3fcea9394d4b98c02b1f6de6b9e Mon Sep 17 00:00:00 2001 From: Eli Cohen Date: Fri, 14 Feb 2014 10:29:49 +1100 Subject: IB/mlx5: Remove dependency on X86 Remove Kconfig dependency of mlx5_ib/mlx5_core on X86, since there is no such dependency in reality. Signed-off-by: Eli Cohen Signed-off-by: Michael Neuling Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/hw/mlx5/Kconfig b/drivers/infiniband/hw/mlx5/Kconfig index 8e6aebf..10df386 100644 --- a/drivers/infiniband/hw/mlx5/Kconfig +++ b/drivers/infiniband/hw/mlx5/Kconfig @@ -1,6 +1,6 @@ config MLX5_INFINIBAND tristate "Mellanox Connect-IB HCA support" - depends on NETDEVICES && ETHERNET && PCI && X86 + depends on NETDEVICES && ETHERNET && PCI select NET_VENDOR_MELLANOX select MLX5_CORE ---help--- diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Kconfig b/drivers/net/ethernet/mellanox/mlx5/core/Kconfig index 157fe8d..8ff57e8 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/Kconfig +++ b/drivers/net/ethernet/mellanox/mlx5/core/Kconfig @@ -4,5 +4,5 @@ config MLX5_CORE tristate - depends on PCI && X86 + depends on PCI default n -- cgit v0.10.2 From 31d6af29066bfaf30cf4f90e7cc0ab9409cee71f Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 12 Feb 2014 15:19:43 +0530 Subject: video: exynos: Fix S6E8AX0 LCD driver build error Enable S6E8AX0 LCD driver only if LCD_CLASS_DEVICE is a built-in driver. Else we get the following errors due to missing symbols: drivers/built-in.o: In function `s6e8ax0_probe': :(.text+0x51aec): undefined reference to `lcd_device_register' :(.text+0x51c44): undefined reference to `lcd_device_unregister' Signed-off-by: Sachin Kamat Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/exynos/Kconfig b/drivers/video/exynos/Kconfig index 1129d0e..75c8a8e 100644 --- a/drivers/video/exynos/Kconfig +++ b/drivers/video/exynos/Kconfig @@ -22,7 +22,8 @@ config EXYNOS_MIPI_DSI config EXYNOS_LCD_S6E8AX0 bool "S6E8AX0 MIPI AMOLED LCD Driver" - depends on (EXYNOS_MIPI_DSI && BACKLIGHT_CLASS_DEVICE && LCD_CLASS_DEVICE) + depends on EXYNOS_MIPI_DSI && BACKLIGHT_CLASS_DEVICE + depends on (LCD_CLASS_DEVICE = y) default n help If you have an S6E8AX0 MIPI AMOLED LCD Panel, say Y to enable its -- cgit v0.10.2 From b359bb0d9c5132abb6fec1ef555c48daf267de59 Mon Sep 17 00:00:00 2001 From: Denis Carikli Date: Wed, 22 Jan 2014 18:09:36 +0100 Subject: video: Kconfig: Allow more broad selection of the imxfb framebuffer driver. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Without that patch, a user can't select the imxfb driver when the i.MX25 and/or the i.MX27 device tree board are selected and that no boards that selects IMX_HAVE_PLATFORM_IMX_FB are compiled in. Cc: Eric Bénard Cc: Jean-Christophe Plagniol-Villard Cc: Sascha Hauer Cc: Tomi Valkeinen Cc: linux-arm-kernel@lists.infradead.org Cc: linux-fbdev@vger.kernel.org Signed-off-by: Denis Carikli Acked-by: Shawn Guo Acked-by: Jean-Christophe PLAGNIOL-VILLARD Acked-by: Sascha Hauer Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 22262a3..dade5b7 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -364,7 +364,7 @@ config FB_SA1100 config FB_IMX tristate "Freescale i.MX1/21/25/27 LCD support" - depends on FB && IMX_HAVE_PLATFORM_IMX_FB + depends on FB && ARCH_MXC select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT -- cgit v0.10.2 From c55d016f7a930dd1c995336017123b469a8c8f5a Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Fri, 14 Feb 2014 08:24:24 +0100 Subject: x86/efi: Fix 32-bit fallout We do not enable the new efi memmap on 32-bit and thus we need to run runtime_code_page_mkexec() unconditionally there. Fix that. Reported-and-tested-by: Lejun Zhu Signed-off-by: Borislav Petkov Signed-off-by: Matt Fleming diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h index 3b978c4..3d6b9f8 100644 --- a/arch/x86/include/asm/efi.h +++ b/arch/x86/include/asm/efi.h @@ -132,6 +132,8 @@ extern void __init efi_map_region_fixed(efi_memory_desc_t *md); extern void efi_sync_low_kernel_mappings(void); extern void efi_setup_page_tables(void); extern void __init old_map_region(efi_memory_desc_t *md); +extern void __init runtime_code_page_mkexec(void); +extern void __init efi_runtime_mkexec(void); struct efi_setup_data { u64 fw_vendor; diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index d62ec87..1a201ac 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -792,7 +792,7 @@ void __init efi_set_executable(efi_memory_desc_t *md, bool executable) set_memory_nx(addr, npages); } -static void __init runtime_code_page_mkexec(void) +void __init runtime_code_page_mkexec(void) { efi_memory_desc_t *md; void *p; @@ -1069,8 +1069,7 @@ void __init efi_enter_virtual_mode(void) efi.update_capsule = virt_efi_update_capsule; efi.query_capsule_caps = virt_efi_query_capsule_caps; - if (efi_enabled(EFI_OLD_MEMMAP) && (__supported_pte_mask & _PAGE_NX)) - runtime_code_page_mkexec(); + efi_runtime_mkexec(); kfree(new_memmap); diff --git a/arch/x86/platform/efi/efi_32.c b/arch/x86/platform/efi/efi_32.c index 249b183..0b74cdf 100644 --- a/arch/x86/platform/efi/efi_32.c +++ b/arch/x86/platform/efi/efi_32.c @@ -77,3 +77,9 @@ void efi_call_phys_epilog(void) local_irq_restore(efi_rt_eflags); } + +void __init efi_runtime_mkexec(void) +{ + if (__supported_pte_mask & _PAGE_NX) + runtime_code_page_mkexec(); +} diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c index 6284f15..0c2a234 100644 --- a/arch/x86/platform/efi/efi_64.c +++ b/arch/x86/platform/efi/efi_64.c @@ -233,3 +233,12 @@ void __init parse_efi_setup(u64 phys_addr, u32 data_len) { efi_setup = phys_addr + sizeof(struct setup_data); } + +void __init efi_runtime_mkexec(void) +{ + if (!efi_enabled(EFI_OLD_MEMMAP)) + return; + + if (__supported_pte_mask & _PAGE_NX) + runtime_code_page_mkexec(); +} -- cgit v0.10.2 From 9da21b1509d8aa7ab4846722817d16c72d656c91 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 3 Feb 2014 15:05:13 -0500 Subject: EDAC: Poll timeout cannot be zero, p2 Sanitize code even more to accept unsigned longs only and to not allow polling intervals below 1 second as this is unnecessary and doesn't make much sense anyway for polling errors. Signed-off-by: Borislav Petkov Link: http://lkml.kernel.org/r/1391457913-881-1-git-send-email-prarit@redhat.com Cc: Doug Thompson Cc: diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index e8c9ef0..aef5ec2 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -601,7 +601,7 @@ static void edac_mc_workq_teardown(struct mem_ctl_info *mci) * user space has updated our poll period value, need to * reset our workq delays */ -void edac_mc_reset_delay_period(int value) +void edac_mc_reset_delay_period(unsigned long value) { struct mem_ctl_info *mci; struct list_head *item; @@ -611,7 +611,7 @@ void edac_mc_reset_delay_period(int value) list_for_each(item, &mc_devices) { mci = list_entry(item, struct mem_ctl_info, link); - edac_mc_workq_setup(mci, (unsigned long) value); + edac_mc_workq_setup(mci, value); } mutex_unlock(&mem_ctls_mutex); diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index 8ec1747..b335c6a 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c @@ -52,18 +52,20 @@ int edac_mc_get_poll_msec(void) static int edac_set_poll_msec(const char *val, struct kernel_param *kp) { - long l; + unsigned long l; int ret; if (!val) return -EINVAL; - ret = kstrtol(val, 0, &l); + ret = kstrtoul(val, 0, &l); if (ret) return ret; - if (!l || ((int)l != l)) + + if (l < 1000) return -EINVAL; - *((int *)kp->arg) = l; + + *((unsigned long *)kp->arg) = l; /* notify edac_mc engine to reset the poll period */ edac_mc_reset_delay_period(l); diff --git a/drivers/edac/edac_module.h b/drivers/edac/edac_module.h index 3d139c6..f2118bf 100644 --- a/drivers/edac/edac_module.h +++ b/drivers/edac/edac_module.h @@ -52,7 +52,7 @@ extern void edac_device_workq_setup(struct edac_device_ctl_info *edac_dev, extern void edac_device_workq_teardown(struct edac_device_ctl_info *edac_dev); extern void edac_device_reset_delay_period(struct edac_device_ctl_info *edac_dev, unsigned long value); -extern void edac_mc_reset_delay_period(int value); +extern void edac_mc_reset_delay_period(unsigned long value); extern void *edac_align_ptr(void **p, unsigned size, int n_elems); -- cgit v0.10.2 From cb6ef42e516cb8948f15e4b70dc03af8020050a2 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Wed, 12 Feb 2014 18:15:00 +0100 Subject: EDAC: Correct workqueue setup path We're using edac_mc_workq_setup() both on the init path, when we load an edac driver and when we change the polling period (edac_mc_reset_delay_period) through /sys/.../edac_mc_poll_msec. On that second path we don't need to init the workqueue which has been initialized already. Thanks to Tejun for workqueue insights. Signed-off-by: Borislav Petkov Link: http://lkml.kernel.org/r/1391457913-881-1-git-send-email-prarit@redhat.com Cc: diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index aef5ec2..33edd67 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -559,7 +559,8 @@ static void edac_mc_workq_function(struct work_struct *work_req) * * called with the mem_ctls_mutex held */ -static void edac_mc_workq_setup(struct mem_ctl_info *mci, unsigned msec) +static void edac_mc_workq_setup(struct mem_ctl_info *mci, unsigned msec, + bool init) { edac_dbg(0, "\n"); @@ -567,7 +568,9 @@ static void edac_mc_workq_setup(struct mem_ctl_info *mci, unsigned msec) if (mci->op_state != OP_RUNNING_POLL) return; - INIT_DELAYED_WORK(&mci->work, edac_mc_workq_function); + if (init) + INIT_DELAYED_WORK(&mci->work, edac_mc_workq_function); + mod_delayed_work(edac_workqueue, &mci->work, msecs_to_jiffies(msec)); } @@ -611,7 +614,7 @@ void edac_mc_reset_delay_period(unsigned long value) list_for_each(item, &mc_devices) { mci = list_entry(item, struct mem_ctl_info, link); - edac_mc_workq_setup(mci, value); + edac_mc_workq_setup(mci, value, false); } mutex_unlock(&mem_ctls_mutex); @@ -782,7 +785,7 @@ int edac_mc_add_mc(struct mem_ctl_info *mci) /* This instance is NOW RUNNING */ mci->op_state = OP_RUNNING_POLL; - edac_mc_workq_setup(mci, edac_mc_get_poll_msec()); + edac_mc_workq_setup(mci, edac_mc_get_poll_msec(), true); } else { mci->op_state = OP_RUNNING_INTERRUPT; } -- cgit v0.10.2 From 09503379dc99535b1bbfa51aa1aeef340f5d82ec Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Thu, 13 Feb 2014 17:17:54 +0000 Subject: x86/efi: Check status field to validate BGRT header Madper reported seeing the following crash, BUG: unable to handle kernel paging request at ffffffffff340003 IP: [] efi_bgrt_init+0x9d/0x133 Call Trace: [] efi_late_init+0x9/0xb [] start_kernel+0x436/0x450 [] ? repair_env_string+0x5c/0x5c [] ? early_idt_handlers+0x120/0x120 [] x86_64_start_reservations+0x2a/0x2c [] x86_64_start_kernel+0x13e/0x14d This is caused because the layout of the ACPI BGRT header on this system doesn't match the definition from the ACPI spec, and so we get a bogus physical address when dereferencing ->image_address in efi_bgrt_init(). Luckily the status field in the BGRT header clearly marks it as invalid, so we can check that field and skip BGRT initialisation. Reported-by: Madper Xie Suggested-by: Toshi Kani Cc: "Rafael J. Wysocki" Cc: Matthew Garrett Cc: Josh Triplett Signed-off-by: Matt Fleming diff --git a/arch/x86/platform/efi/efi-bgrt.c b/arch/x86/platform/efi/efi-bgrt.c index 4df9591..f15103d 100644 --- a/arch/x86/platform/efi/efi-bgrt.c +++ b/arch/x86/platform/efi/efi-bgrt.c @@ -42,7 +42,7 @@ void __init efi_bgrt_init(void) if (bgrt_tab->header.length < sizeof(*bgrt_tab)) return; - if (bgrt_tab->version != 1) + if (bgrt_tab->version != 1 || bgrt_tab->status != 1) return; if (bgrt_tab->image_type != 0 || !bgrt_tab->image_address) return; -- cgit v0.10.2 From 2a2f3e269c75edf916de5967079069aeb6a601cb Mon Sep 17 00:00:00 2001 From: Christoffer Dall Date: Sun, 2 Feb 2014 13:41:02 -0800 Subject: arm64: KVM: Add VGIC device control for arm64 This fixes the build breakage introduced by c07a0191ef2de1f9510f12d1f88e3b0b5cd8d66f and adds support for the device control API and save/restore of the VGIC state for ARMv8. The defines were simply missing from the arm64 header files and uaccess.h must be implicitly imported from somewhere else on arm. Signed-off-by: Christoffer Dall Signed-off-by: Paolo Bonzini diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h index 495ab6f..eaf54a3 100644 --- a/arch/arm64/include/uapi/asm/kvm.h +++ b/arch/arm64/include/uapi/asm/kvm.h @@ -148,6 +148,15 @@ struct kvm_arch_memory_slot { #define KVM_REG_ARM_TIMER_CNT ARM64_SYS_REG(3, 3, 14, 3, 2) #define KVM_REG_ARM_TIMER_CVAL ARM64_SYS_REG(3, 3, 14, 0, 2) +/* Device Control API: ARM VGIC */ +#define KVM_DEV_ARM_VGIC_GRP_ADDR 0 +#define KVM_DEV_ARM_VGIC_GRP_DIST_REGS 1 +#define KVM_DEV_ARM_VGIC_GRP_CPU_REGS 2 +#define KVM_DEV_ARM_VGIC_CPUID_SHIFT 32 +#define KVM_DEV_ARM_VGIC_CPUID_MASK (0xffULL << KVM_DEV_ARM_VGIC_CPUID_SHIFT) +#define KVM_DEV_ARM_VGIC_OFFSET_SHIFT 0 +#define KVM_DEV_ARM_VGIC_OFFSET_MASK (0xffffffffULL << KVM_DEV_ARM_VGIC_OFFSET_SHIFT) + /* KVM_IRQ_LINE irq field index values */ #define KVM_ARM_IRQ_TYPE_SHIFT 24 #define KVM_ARM_IRQ_TYPE_MASK 0xff diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c index be456ce..8ca405c 100644 --- a/virt/kvm/arm/vgic.c +++ b/virt/kvm/arm/vgic.c @@ -24,6 +24,7 @@ #include #include #include +#include #include -- cgit v0.10.2 From f809309a251a13bd97cc189c3fa428782aab9716 Mon Sep 17 00:00:00 2001 From: Upinder Malhi Date: Thu, 23 Jan 2014 22:38:04 +0000 Subject: IB/usnic: Fix smatch endianness error Error reported at http://marc.info/?l=linux-rdma&m=138995755801039&w=2 Fix short to int cast for big endian systems. Signed-off-by: Upinder Malhi Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c b/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c index 7ecc606..f8dfd76 100644 --- a/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c +++ b/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c @@ -629,6 +629,7 @@ static int qp_grp_id_from_flow(struct usnic_ib_qp_grp_flow *qp_flow, { enum usnic_transport_type trans_type = qp_flow->trans_type; int err; + uint16_t port_num = 0; switch (trans_type) { case USNIC_TRANSPORT_ROCE_CUSTOM: @@ -637,9 +638,15 @@ static int qp_grp_id_from_flow(struct usnic_ib_qp_grp_flow *qp_flow, case USNIC_TRANSPORT_IPV4_UDP: err = usnic_transport_sock_get_addr(qp_flow->udp.sock, NULL, NULL, - (uint16_t *) id); + &port_num); if (err) return err; + /* + * Copy port_num to stack first and then to *id, + * so that the short to int cast works for little + * and big endian systems. + */ + *id = port_num; break; default: usnic_err("Unsupported transport %u\n", trans_type); -- cgit v0.10.2 From 7d9eacf9457efc6b614665e1095336c11ad83f0d Mon Sep 17 00:00:00 2001 From: Roi Dayan Date: Tue, 4 Feb 2014 16:54:54 +0200 Subject: IB/iser: Avoid dereferencing iscsi_iser conn object when not bound to iser connection Fix a possible NULL pointer dereference in disconnection flow. This can happen if the target disconnected/rejected the connection request, e.g before the binding stage between iscsi connection to the transport connection. Signed-off-by: Alex Tabachnik Signed-off-by: Roi Dayan Signed-off-by: Or Gerlitz Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c index afe9567..ca37ede 100644 --- a/drivers/infiniband/ulp/iser/iser_verbs.c +++ b/drivers/infiniband/ulp/iser/iser_verbs.c @@ -652,9 +652,13 @@ static int iser_disconnected_handler(struct rdma_cm_id *cma_id) /* getting here when the state is UP means that the conn is being * * terminated asynchronously from the iSCSI layer's perspective. */ if (iser_conn_state_comp_exch(ib_conn, ISER_CONN_UP, - ISER_CONN_TERMINATING)) - iscsi_conn_failure(ib_conn->iser_conn->iscsi_conn, - ISCSI_ERR_CONN_FAILED); + ISER_CONN_TERMINATING)){ + if (ib_conn->iser_conn) + iscsi_conn_failure(ib_conn->iser_conn->iscsi_conn, + ISCSI_ERR_CONN_FAILED); + else + iser_err("iscsi_iser connection isn't bound\n"); + } /* Complete the termination process if no posts are pending */ if (ib_conn->post_recv_buf_count == 0 && -- cgit v0.10.2 From fd8b48b22a2b7cdf21f15b01cae379e6159a7eea Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 29 Jan 2014 16:18:51 +0300 Subject: IB/iser: Fix use after free in iser_snd_completion() We use "tx_desc" again after we free it. Signed-off-by: Dan Carpenter Acked-by: Or Gerlitz Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c b/drivers/infiniband/ulp/iser/iser_initiator.c index 5388226..334f34b 100644 --- a/drivers/infiniband/ulp/iser/iser_initiator.c +++ b/drivers/infiniband/ulp/iser/iser_initiator.c @@ -610,11 +610,12 @@ void iser_snd_completion(struct iser_tx_desc *tx_desc, ib_dma_unmap_single(device->ib_device, tx_desc->dma_addr, ISER_HEADERS_LEN, DMA_TO_DEVICE); kmem_cache_free(ig.desc_cache, tx_desc); + tx_desc = NULL; } atomic_dec(&ib_conn->post_send_buf_count); - if (tx_desc->type == ISCSI_TX_CONTROL) { + if (tx_desc && tx_desc->type == ISCSI_TX_CONTROL) { /* this arithmetic is legal by libiscsi dd_data allocation */ task = (void *) ((long)(void *)tx_desc - sizeof(struct iscsi_task)); -- cgit v0.10.2 From a61d93d92f5c9533898098abb5f187840900aeb5 Mon Sep 17 00:00:00 2001 From: Devesh Sharma Date: Mon, 10 Feb 2014 13:48:58 +0530 Subject: RDMA/ocrdma: Fix traffic class shift Use correct value for obtaining traffic class from device response for Query QP request. Signed-off-by: Devesh Sharma Reported-by: Dan Carpenter Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c index aa92f40..77e38ec 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c @@ -1416,7 +1416,7 @@ int ocrdma_query_qp(struct ib_qp *ibqp, OCRDMA_QP_PARAMS_HOP_LMT_MASK) >> OCRDMA_QP_PARAMS_HOP_LMT_SHIFT; qp_attr->ah_attr.grh.traffic_class = (params.tclass_sq_psn & - OCRDMA_QP_PARAMS_SQ_PSN_MASK) >> + OCRDMA_QP_PARAMS_TCLASS_MASK) >> OCRDMA_QP_PARAMS_TCLASS_SHIFT; qp_attr->ah_attr.ah_flags = IB_AH_GRH; -- cgit v0.10.2 From 09de3f1313a30d8a22e488c9a5b96a9560cae96d Mon Sep 17 00:00:00 2001 From: Devesh Sharma Date: Tue, 4 Feb 2014 12:10:48 +0530 Subject: RDMA/ocrdma: Fix load time panic during GID table init We should use rdma_vlan_dev_real_dev() instead of using vlan_dev_real_dev() when building the GID table for a vlan interface. Signed-off-by: Devesh Sharma Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_main.c b/drivers/infiniband/hw/ocrdma/ocrdma_main.c index 2ca86ca..1a8a945 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_main.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_main.c @@ -127,7 +127,7 @@ static int ocrdma_addr_event(unsigned long event, struct net_device *netdev, is_vlan = netdev->priv_flags & IFF_802_1Q_VLAN; if (is_vlan) - netdev = vlan_dev_real_dev(netdev); + netdev = rdma_vlan_dev_real_dev(netdev); rcu_read_lock(); list_for_each_entry_rcu(dev, &ocrdma_dev_list, entry) { -- cgit v0.10.2 From 8c442794b2e7e3e2c7c15cc7d3a1b550ce99ac88 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 14 Feb 2014 11:15:40 -0800 Subject: Revert "ARM: sunxi: dt: Convert to the new SID compatibles" This reverts commit 01ab1167cd2d861d20195eda08505652c536df97, it is incorrect, a future patch will fix this up properly. Cc: Maxime Ripard Signed-off-by: Greg Kroah-Hartman diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi index 7b10f85..040bb0e 100644 --- a/arch/arm/boot/dts/sun4i-a10.dtsi +++ b/arch/arm/boot/dts/sun4i-a10.dtsi @@ -421,7 +421,7 @@ }; sid: eeprom@01c23800 { - compatible = "allwinner,sun4i-a10-sid"; + compatible = "allwinner,sun4i-sid"; reg = <0x01c23800 0x10>; }; diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi index 6d287a0..ea16054 100644 --- a/arch/arm/boot/dts/sun5i-a10s.dtsi +++ b/arch/arm/boot/dts/sun5i-a10s.dtsi @@ -378,7 +378,7 @@ }; sid: eeprom@01c23800 { - compatible = "allwinner,sun4i-a10-sid"; + compatible = "allwinner,sun4i-sid"; reg = <0x01c23800 0x10>; }; diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi index f49eb13..320335a 100644 --- a/arch/arm/boot/dts/sun5i-a13.dtsi +++ b/arch/arm/boot/dts/sun5i-a13.dtsi @@ -341,7 +341,7 @@ }; sid: eeprom@01c23800 { - compatible = "allwinner,sun4i-a10-sid"; + compatible = "allwinner,sun4i-sid"; reg = <0x01c23800 0x10>; }; -- cgit v0.10.2 From bf7471038840547c9328291b4d9d91c55581dcb8 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 14 Feb 2014 11:16:08 -0800 Subject: Revert "misc: eeprom: sunxi: Add new compatibles" This reverts commit f0de8e04a7201a2000f3c6d09732c11e7f35d42d, it is incorrect, a future patch will fix this up properly. Cc: Maxime Ripard Signed-off-by: Greg Kroah-Hartman diff --git a/Documentation/devicetree/bindings/misc/allwinner,sunxi-sid.txt b/Documentation/devicetree/bindings/misc/allwinner,sunxi-sid.txt index c10a61a..68ba372 100644 --- a/Documentation/devicetree/bindings/misc/allwinner,sunxi-sid.txt +++ b/Documentation/devicetree/bindings/misc/allwinner,sunxi-sid.txt @@ -1,13 +1,12 @@ Allwinner sunxi-sid Required properties: -- compatible: "allwinner,sun4i-a10-sid" or "allwinner,sun7i-a20-sid" - (Deprecated: "allwinner,sun4i-sid"). +- compatible: "allwinner,sun4i-sid" or "allwinner,sun7i-a20-sid". - reg: Should contain registers location and length Example for sun4i: sid@01c23800 { - compatible = "allwinner,sun4i-a10-sid"; + compatible = "allwinner,sun4i-sid"; reg = <0x01c23800 0x10> }; diff --git a/drivers/misc/eeprom/sunxi_sid.c b/drivers/misc/eeprom/sunxi_sid.c index e137e75..9c34e57 100644 --- a/drivers/misc/eeprom/sunxi_sid.c +++ b/drivers/misc/eeprom/sunxi_sid.c @@ -96,11 +96,8 @@ static int sunxi_sid_remove(struct platform_device *pdev) } static const struct of_device_id sunxi_sid_of_match[] = { - { .compatible = "allwinner,sun4i-a10-sid", .data = (void *)16}, - { .compatible = "allwinner,sun7i-a20-sid", .data = (void *)512}, - - /* Deprecated */ { .compatible = "allwinner,sun4i-sid", .data = (void *)16}, + { .compatible = "allwinner,sun7i-a20-sid", .data = (void *)512}, {/* sentinel */}, }; MODULE_DEVICE_TABLE(of, sunxi_sid_of_match); -- cgit v0.10.2 From 4e8ca6ee3a5d0e0f4c0cb32e43dc3d69e79e5a76 Mon Sep 17 00:00:00 2001 From: Kevin Hao Date: Fri, 14 Feb 2014 13:22:45 +0800 Subject: Revert "OF: base: match each node compatible against all given matches first" This reverts commit 105353145eafb3ea919f5cdeb652a9d8f270228e. Stephen Chivers reported this is broken as we will get a match entry '.type = "serial"' instead of the '.compatible = "ns16550"' in the following scenario: serial0: serial@4500 { compatible = "fsl,ns16550", "ns16550"; } struct of_device_id of_platform_serial_table[] = { { .compatible = "ns8250", .data = (void *)PORT_8250, }, { .compatible = "ns16450", .data = (void *)PORT_16450, }, { .compatible = "ns16550a", .data = (void *)PORT_16550A, }, { .compatible = "ns16550", .data = (void *)PORT_16550, }, { .compatible = "ns16750", .data = (void *)PORT_16750, }, { .compatible = "ns16850", .data = (void *)PORT_16850, }, ... { .type = "serial", .data = (void *)PORT_UNKNOWN, }, { /* end of list */ }, }; So just revert this patch, we will use another implementation to find the best compatible match in a follow-on patch. Reported-by: Stephen N Chivers Cc: Sebastian Hesselbarth Signed-off-by: Kevin Hao Signed-off-by: Rob Herring diff --git a/drivers/of/base.c b/drivers/of/base.c index ff85450..ba195fb 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -734,42 +734,24 @@ static const struct of_device_id *__of_match_node(const struct of_device_id *matches, const struct device_node *node) { - const char *cp; - int cplen, l; - if (!matches) return NULL; - cp = __of_get_property(node, "compatible", &cplen); - do { - const struct of_device_id *m = matches; - - /* Check against matches with current compatible string */ - while (m->name[0] || m->type[0] || m->compatible[0]) { - int match = 1; - if (m->name[0]) - match &= node->name - && !strcmp(m->name, node->name); - if (m->type[0]) - match &= node->type - && !strcmp(m->type, node->type); - if (m->compatible[0]) - match &= cp - && !of_compat_cmp(m->compatible, cp, - strlen(m->compatible)); - if (match) - return m; - m++; - } - - /* Get node's next compatible string */ - if (cp) { - l = strlen(cp) + 1; - cp += l; - cplen -= l; - } - } while (cp && (cplen > 0)); - + 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++; + } return NULL; } @@ -778,10 +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. Matching order - * is to compare each of the node's compatibles with all given matches - * first. This implies node's compatible is sorted from specific to - * generic while matches can be in any order. + * 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 v0.10.2 From 11bcac89c0d73dea42f1cb8646b532035796a5d6 Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Fri, 14 Feb 2014 13:42:13 -0800 Subject: Revert "btrfs: add ioctl to export size of global metadata reservation" This reverts commit 01e219e8069516cdb98594d417b8bb8d906ed30d. David Sterba found a different way to provide these features without adding a new ioctl. We haven't released any progs with this ioctl yet, so I'm taking this out for now until we finalize things. Signed-off-by: Chris Mason Signed-off-by: David Sterba CC: Jeff Mahoney diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index ebdd866..9a90445 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -3559,20 +3559,6 @@ out: return ret; } -static long btrfs_ioctl_global_rsv(struct btrfs_root *root, void __user *arg) -{ - struct btrfs_block_rsv *block_rsv = &root->fs_info->global_block_rsv; - u64 reserved; - - spin_lock(&block_rsv->lock); - reserved = block_rsv->reserved; - spin_unlock(&block_rsv->lock); - - if (arg && copy_to_user(arg, &reserved, sizeof(reserved))) - return -EFAULT; - return 0; -} - /* * there are many ways the trans_start and trans_end ioctls can lead * to deadlocks. They should only be used by applications that @@ -4779,8 +4765,6 @@ long btrfs_ioctl(struct file *file, unsigned int return btrfs_ioctl_logical_to_ino(root, argp); case BTRFS_IOC_SPACE_INFO: return btrfs_ioctl_space_info(root, argp); - case BTRFS_IOC_GLOBAL_RSV: - return btrfs_ioctl_global_rsv(root, argp); case BTRFS_IOC_SYNC: { int ret; diff --git a/include/uapi/linux/btrfs.h b/include/uapi/linux/btrfs.h index 1b8a0f4..b4d6909 100644 --- a/include/uapi/linux/btrfs.h +++ b/include/uapi/linux/btrfs.h @@ -558,7 +558,6 @@ static inline char *btrfs_err_str(enum btrfs_err_code err_code) #define BTRFS_IOC_DEFAULT_SUBVOL _IOW(BTRFS_IOCTL_MAGIC, 19, __u64) #define BTRFS_IOC_SPACE_INFO _IOWR(BTRFS_IOCTL_MAGIC, 20, \ struct btrfs_ioctl_space_args) -#define BTRFS_IOC_GLOBAL_RSV _IOR(BTRFS_IOCTL_MAGIC, 20, __u64) #define BTRFS_IOC_START_SYNC _IOR(BTRFS_IOCTL_MAGIC, 24, __u64) #define BTRFS_IOC_WAIT_SYNC _IOW(BTRFS_IOCTL_MAGIC, 22, __u64) #define BTRFS_IOC_SNAP_CREATE_V2 _IOW(BTRFS_IOCTL_MAGIC, 23, \ -- cgit v0.10.2 From a9d2d4adb6a87e515912a7033b227acbd9c8835e Mon Sep 17 00:00:00 2001 From: Liu Bo Date: Sat, 8 Feb 2014 15:33:08 +0800 Subject: Btrfs: fix a lockdep warning when cleaning up aborted transaction Given now we have 2 spinlock for management of delayed refs, CONFIG_DEBUG_SPINLOCK=y helped me find this, [ 4723.413809] BUG: spinlock wrong CPU on CPU#1, btrfs-transacti/2258 [ 4723.414882] lock: 0xffff880048377670, .magic: dead4ead, .owner: btrfs-transacti/2258, .owner_cpu: 2 [ 4723.417146] CPU: 1 PID: 2258 Comm: btrfs-transacti Tainted: G W O 3.12.0+ #4 [ 4723.421321] Call Trace: [ 4723.421872] [] dump_stack+0x54/0x74 [ 4723.422753] [] spin_dump+0x8c/0x91 [ 4723.424979] [] spin_bug+0x21/0x26 [ 4723.425846] [] do_raw_spin_unlock+0x66/0x90 [ 4723.434424] [] _raw_spin_unlock+0x27/0x40 [ 4723.438747] [] btrfs_cleanup_one_transaction+0x35e/0x710 [btrfs] [ 4723.443321] [] btrfs_cleanup_transaction+0x104/0x570 [btrfs] [ 4723.444692] [] ? trace_hardirqs_on_caller+0xfd/0x1c0 [ 4723.450336] [] ? trace_hardirqs_on+0xd/0x10 [ 4723.451332] [] transaction_kthread+0x22e/0x270 [btrfs] [ 4723.452543] [] ? btrfs_cleanup_transaction+0x570/0x570 [btrfs] [ 4723.457833] [] kthread+0xea/0xf0 [ 4723.458990] [] ? kthread_create_on_node+0x140/0x140 [ 4723.460133] [] ret_from_fork+0x7c/0xb0 [ 4723.460865] [] ? kthread_create_on_node+0x140/0x140 [ 4723.496521] ------------[ cut here ]------------ ---------------------------------------------------------------------- The reason is that we get to call cond_resched_lock(&head_ref->lock) while still holding @delayed_refs->lock. So it's different with __btrfs_run_delayed_refs(), where we do drop-acquire dance before and after actually processing delayed refs. Here we don't drop the lock, others are not able to add new delayed refs to head_ref, so cond_resched_lock(&head_ref->lock) is not necessary here. Signed-off-by: Liu Bo Signed-off-by: Chris Mason diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 3903bd3..fcf3675 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -3842,7 +3842,6 @@ static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans, rb_erase(&ref->rb_node, &head->ref_root); atomic_dec(&delayed_refs->num_entries); btrfs_put_delayed_ref(ref); - cond_resched_lock(&head->lock); } if (head->must_insert_reserved) pin_bytes = true; -- cgit v0.10.2 From feb5f96589302b39a2b10fc210db7c47a73e4168 Mon Sep 17 00:00:00 2001 From: Mitch Harder Date: Thu, 13 Feb 2014 09:13:16 -0600 Subject: Btrfs: fix max_inline mount option Currently, the only mount option for max_inline that has any effect is max_inline=0. Any other value that is supplied to max_inline will be adjusted to a minimum of 4k. Since max_inline has an effective maximum of ~3900 bytes due to page size limitations, the current behaviour only has meaning for max_inline=0. This patch will allow the the max_inline mount option to accept non-zero values as indicated in the documentation. Signed-off-by: Mitch Harder Signed-off-by: Chris Mason diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 97cc241..e73c80e 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -566,7 +566,7 @@ int btrfs_parse_options(struct btrfs_root *root, char *options) kfree(num); if (info->max_inline) { - info->max_inline = max_t(u64, + info->max_inline = min_t(u64, info->max_inline, root->sectorsize); } -- cgit v0.10.2 From 3a0dfa6a12e4bb64a434426ecb17d4842092db5e Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Fri, 14 Feb 2014 13:43:48 -0500 Subject: Btrfs: unset DCACHE_DISCONNECTED when mounting default subvol A user was running into errors from an NFS export of a subvolume that had a default subvol set. When we mount a default subvol we will use d_obtain_alias() to find an existing dentry for the subvolume in the case that the root subvol has already been mounted, or a dummy one is allocated in the case that the root subvol has not already been mounted. This allows us to connect the dentry later on if we wander into the path. However if we don't ever wander into the path we will keep DCACHE_DISCONNECTED set for a long time, which angers NFS. It doesn't appear to cause any problems but it is annoying nonetheless, so simply unset DCACHE_DISCONNECTED in the get_default_root case and switch btrfs_lookup() to use d_materialise_unique() instead which will make everything play nicely together and reconnect stuff if we wander into the defaul subvol path from a different way. With this patch I'm no longer getting the NFS errors when exporting a volume that has been mounted with a default subvol set. Thanks, cc: bfields@fieldses.org cc: ebiederm@xmission.com Signed-off-by: Josef Bacik Acked-by: "Eric W. Biederman" Signed-off-by: Chris Mason diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 1af34d0..4ffb6d7 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -5150,7 +5150,7 @@ static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry, return ERR_CAST(inode); } - return d_splice_alias(inode, dentry); + return d_materialise_unique(dentry, inode); } unsigned char btrfs_filetype_table[] = { diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index e73c80e..d04db81 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -855,6 +855,7 @@ static struct dentry *get_default_root(struct super_block *sb, struct btrfs_path *path; struct btrfs_key location; struct inode *inode; + struct dentry *dentry; u64 dir_id; int new = 0; @@ -925,7 +926,13 @@ setup_root: return dget(sb->s_root); } - return d_obtain_alias(inode); + dentry = d_obtain_alias(inode); + if (!IS_ERR(dentry)) { + spin_lock(&dentry->d_lock); + dentry->d_flags &= ~DCACHE_DISCONNECTED; + spin_unlock(&dentry->d_lock); + } + return dentry; } static int btrfs_fill_super(struct super_block *sb, -- cgit v0.10.2 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 diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index e9b3081..5bfd769 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 v0.10.2 From 79970db213344b4a4034645db5ebfc31571f3fa3 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Thu, 13 Feb 2014 21:36:29 +0100 Subject: i2c: mv64xxx: refactor message start to ensure proper initialization Because the offload mechanism can fall back to a standard transfer, having two seperate initialization states is unfortunate. Let's just have one state which does things consistently. This fixes a bug where some preparation was missing when the fallback happened. And it makes the code much easier to follow. To implement this, we put the check if offload is possible at the top of the offload setup function. Signed-off-by: Wolfram Sang Tested-by: Gregory CLEMENT Cc: stable@vger.kernel.org # v3.12+ Fixes: 930ab3d403ae (i2c: mv64xxx: Add I2C Transaction Generator support) diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c index b8c5187..d52d849 100644 --- a/drivers/i2c/busses/i2c-mv64xxx.c +++ b/drivers/i2c/busses/i2c-mv64xxx.c @@ -97,7 +97,6 @@ enum { enum { MV64XXX_I2C_ACTION_INVALID, MV64XXX_I2C_ACTION_CONTINUE, - MV64XXX_I2C_ACTION_OFFLOAD_SEND_START, MV64XXX_I2C_ACTION_SEND_START, MV64XXX_I2C_ACTION_SEND_RESTART, MV64XXX_I2C_ACTION_OFFLOAD_RESTART, @@ -204,6 +203,9 @@ static int mv64xxx_i2c_offload_msg(struct mv64xxx_i2c_data *drv_data) unsigned long ctrl_reg; struct i2c_msg *msg = drv_data->msgs; + if (!drv_data->offload_enabled) + return -EOPNOTSUPP; + drv_data->msg = msg; drv_data->byte_posn = 0; drv_data->bytes_left = msg->len; @@ -433,8 +435,7 @@ mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data) drv_data->msgs++; drv_data->num_msgs--; - if (!(drv_data->offload_enabled && - mv64xxx_i2c_offload_msg(drv_data))) { + if (mv64xxx_i2c_offload_msg(drv_data) < 0) { drv_data->cntl_bits |= MV64XXX_I2C_REG_CONTROL_START; writel(drv_data->cntl_bits, drv_data->reg_base + drv_data->reg_offsets.control); @@ -458,15 +459,14 @@ mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data) drv_data->reg_base + drv_data->reg_offsets.control); break; - case MV64XXX_I2C_ACTION_OFFLOAD_SEND_START: - if (!mv64xxx_i2c_offload_msg(drv_data)) - break; - else - drv_data->action = MV64XXX_I2C_ACTION_SEND_START; - /* FALLTHRU */ case MV64XXX_I2C_ACTION_SEND_START: - writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_START, - drv_data->reg_base + drv_data->reg_offsets.control); + /* Can we offload this msg ? */ + if (mv64xxx_i2c_offload_msg(drv_data) < 0) { + /* No, switch to standard path */ + mv64xxx_i2c_prepare_for_io(drv_data, drv_data->msgs); + writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_START, + drv_data->reg_base + drv_data->reg_offsets.control); + } break; case MV64XXX_I2C_ACTION_SEND_ADDR_1: @@ -625,15 +625,10 @@ mv64xxx_i2c_execute_msg(struct mv64xxx_i2c_data *drv_data, struct i2c_msg *msg, unsigned long flags; spin_lock_irqsave(&drv_data->lock, flags); - if (drv_data->offload_enabled) { - drv_data->action = MV64XXX_I2C_ACTION_OFFLOAD_SEND_START; - drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_START_COND; - } else { - mv64xxx_i2c_prepare_for_io(drv_data, msg); - drv_data->action = MV64XXX_I2C_ACTION_SEND_START; - drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_START_COND; - } + drv_data->action = MV64XXX_I2C_ACTION_SEND_START; + drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_START_COND; + drv_data->send_stop = is_last; drv_data->block = 1; mv64xxx_i2c_do_action(drv_data); -- cgit v0.10.2 From f085381e6d08f4c8d6882825f31accd455c54d70 Mon Sep 17 00:00:00 2001 From: Anand Jain Date: Wed, 15 Jan 2014 17:22:28 +0800 Subject: btrfs: fix null pointer deference at btrfs_sysfs_add_one+0x105 bdev is null when disk has disappeared and mounted with the degrade option stack trace --------- btrfs_sysfs_add_one+0x105/0x1c0 [btrfs] open_ctree+0x15f3/0x1fe0 [btrfs] btrfs_mount+0x5db/0x790 [btrfs] ? alloc_pages_current+0xa4/0x160 mount_fs+0x34/0x1b0 vfs_kern_mount+0x62/0xf0 do_mount+0x22e/0xa80 ? __get_free_pages+0x9/0x40 ? copy_mount_options+0x31/0x170 SyS_mount+0x7e/0xc0 system_call_fastpath+0x16/0x1b --------- reproducer: ------- mkfs.btrfs -draid1 -mraid1 /dev/sdc /dev/sdd (detach a disk) devmgt detach /dev/sdc [1] mount -o degrade /dev/sdd /btrfs ------- [1] github.com/anajain/devmgt.git Signed-off-by: Anand Jain Tested-by: Hidetoshi Seto Signed-off-by: Chris Mason diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c index 782374d..865f4cf 100644 --- a/fs/btrfs/sysfs.c +++ b/fs/btrfs/sysfs.c @@ -578,8 +578,14 @@ static int add_device_membership(struct btrfs_fs_info *fs_info) return -ENOMEM; list_for_each_entry(dev, &fs_devices->devices, dev_list) { - struct hd_struct *disk = dev->bdev->bd_part; - struct kobject *disk_kobj = &part_to_dev(disk)->kobj; + struct hd_struct *disk; + struct kobject *disk_kobj; + + if (!dev->bdev) + continue; + + disk = dev->bdev->bd_part; + disk_kobj = &part_to_dev(disk)->kobj; error = sysfs_create_link(fs_info->device_dir_kobj, disk_kobj, disk_kobj->name); -- cgit v0.10.2 From 93de4ba86480a9e0d1062cb1d535fa97fb81af48 Mon Sep 17 00:00:00 2001 From: Filipe David Borba Manana Date: Sat, 15 Feb 2014 15:53:16 +0000 Subject: Btrfs: use right clone root offset for compressed extents For non compressed extents, iterate_extent_inodes() gives us offsets that take into account the data offset from the file extent items, while for compressed extents it doesn't. Therefore we have to adjust them before placing them in a send clone instruction. Not doing this adjustment leads to the receiving end requesting for a wrong a file range to the clone ioctl, which results in different file content from the one in the original send root. Issue reproducible with the following excerpt from the test I made for xfstests: _scratch_mkfs _scratch_mount "-o compress-force=lzo" $XFS_IO_PROG -f -c "truncate 118811" $SCRATCH_MNT/foo $XFS_IO_PROG -c "pwrite -S 0x0d -b 39987 92267 39987" $SCRATCH_MNT/foo $BTRFS_UTIL_PROG subvolume snapshot -r $SCRATCH_MNT $SCRATCH_MNT/mysnap1 $XFS_IO_PROG -c "pwrite -S 0x3e -b 80000 200000 80000" $SCRATCH_MNT/foo $BTRFS_UTIL_PROG filesystem sync $SCRATCH_MNT $XFS_IO_PROG -c "pwrite -S 0xdc -b 10000 250000 10000" $SCRATCH_MNT/foo $XFS_IO_PROG -c "pwrite -S 0xff -b 10000 300000 10000" $SCRATCH_MNT/foo # will be used for incremental send to be able to issue clone operations $BTRFS_UTIL_PROG subvolume snapshot -r $SCRATCH_MNT $SCRATCH_MNT/clones_snap $BTRFS_UTIL_PROG subvolume snapshot -r $SCRATCH_MNT $SCRATCH_MNT/mysnap2 $FSSUM_PROG -A -f -w $tmp/1.fssum $SCRATCH_MNT/mysnap1 $FSSUM_PROG -A -f -w $tmp/2.fssum -x $SCRATCH_MNT/mysnap2/mysnap1 \ -x $SCRATCH_MNT/mysnap2/clones_snap $SCRATCH_MNT/mysnap2 $FSSUM_PROG -A -f -w $tmp/clones.fssum $SCRATCH_MNT/clones_snap \ -x $SCRATCH_MNT/clones_snap/mysnap1 -x $SCRATCH_MNT/clones_snap/mysnap2 $BTRFS_UTIL_PROG send $SCRATCH_MNT/mysnap1 -f $tmp/1.snap $BTRFS_UTIL_PROG send $SCRATCH_MNT/clones_snap -f $tmp/clones.snap $BTRFS_UTIL_PROG send -p $SCRATCH_MNT/mysnap1 \ -c $SCRATCH_MNT/clones_snap $SCRATCH_MNT/mysnap2 -f $tmp/2.snap _scratch_unmount _scratch_mkfs _scratch_mount $BTRFS_UTIL_PROG receive $SCRATCH_MNT -f $tmp/1.snap $FSSUM_PROG -r $tmp/1.fssum $SCRATCH_MNT/mysnap1 2>> $seqres.full $BTRFS_UTIL_PROG receive $SCRATCH_MNT -f $tmp/clones.snap $FSSUM_PROG -r $tmp/clones.fssum $SCRATCH_MNT/clones_snap 2>> $seqres.full $BTRFS_UTIL_PROG receive $SCRATCH_MNT -f $tmp/2.snap $FSSUM_PROG -r $tmp/2.fssum $SCRATCH_MNT/mysnap2 2>> $seqres.full Signed-off-by: Filipe David Borba Manana Signed-off-by: Chris Mason diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index 9c8d1a3..9dde971 100644 --- a/fs/btrfs/send.c +++ b/fs/btrfs/send.c @@ -1332,6 +1332,16 @@ verbose_printk(KERN_DEBUG "btrfs: find_extent_clone: data_offset=%llu, " } if (cur_clone_root) { + if (compressed != BTRFS_COMPRESS_NONE) { + /* + * Offsets given by iterate_extent_inodes() are relative + * to the start of the extent, we need to add logical + * offset from the file extent item. + * (See why at backref.c:check_extent_in_eb()) + */ + cur_clone_root->offset += btrfs_file_extent_offset(eb, + fi); + } *found = cur_clone_root; ret = 0; } else { -- cgit v0.10.2 From aeca0fe62ac19217cb8158a0c5f6f74e3b8d304b Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 10 Feb 2014 11:03:55 +0100 Subject: Documentation: i2c: describe devicetree method for instantiating devices Signed-off-by: Wolfram Sang diff --git a/Documentation/i2c/instantiating-devices b/Documentation/i2c/instantiating-devices index c70e7a7..6df095a 100644 --- a/Documentation/i2c/instantiating-devices +++ b/Documentation/i2c/instantiating-devices @@ -8,8 +8,8 @@ reason, the kernel code must instantiate I2C devices explicitly. There are several ways to achieve this, depending on the context and requirements. -Method 1: Declare the I2C devices by bus number ------------------------------------------------ +Method 1a: Declare the I2C devices by bus number +------------------------------------------------ This method is appropriate when the I2C bus is a system bus as is the case for many embedded systems. On such systems, each I2C bus has a number @@ -51,6 +51,36 @@ The devices will be automatically unbound and destroyed when the I2C bus they sit on goes away (if ever.) +Method 1b: Declare the I2C devices via devicetree +------------------------------------------------- + +This method has the same implications as method 1a. The declaration of I2C +devices is here done via devicetree as subnodes of the master controller. + +Example: + + i2c1: i2c@400a0000 { + /* ... master properties skipped ... */ + clock-frequency = <100000>; + + flash@50 { + compatible = "atmel,24c256"; + reg = <0x50>; + }; + + pca9532: gpio@60 { + compatible = "nxp,pca9532"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x60>; + }; + }; + +Here, two devices are attached to the bus using a speed of 100kHz. For +additional properties which might be needed to set up the device, please refer +to its devicetree documentation in Documentation/devicetree/bindings/. + + Method 2: Instantiate the devices explicitly -------------------------------------------- -- cgit v0.10.2 From fde1e418ab2c4269035f7f576e678b6ad3117d7d Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sat, 15 Feb 2014 15:58:35 +0100 Subject: Documentation: i2c: mention ACPI method for instantiating devices Signed-off-by: Wolfram Sang Acked-by: Guenter Roeck diff --git a/Documentation/i2c/instantiating-devices b/Documentation/i2c/instantiating-devices index 6df095a..0d85ac19 100644 --- a/Documentation/i2c/instantiating-devices +++ b/Documentation/i2c/instantiating-devices @@ -81,6 +81,13 @@ additional properties which might be needed to set up the device, please refer to its devicetree documentation in Documentation/devicetree/bindings/. +Method 1c: Declare the I2C devices via ACPI +------------------------------------------- + +ACPI can also describe I2C devices. There is special documentation for this +which is currently located at Documentation/acpi/enumeration.txt. + + Method 2: Instantiate the devices explicitly -------------------------------------------- -- cgit v0.10.2 From 06b29e76a74b2373e6f8b5a7938b3630b9ae98b2 Mon Sep 17 00:00:00 2001 From: Kevin Hao Date: Fri, 14 Feb 2014 13:22:46 +0800 Subject: of: search the best compatible match first in __of_match_node() Currently, of_match_node compares each given match against all 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, this patch introduces a function to match each of the node's compatible strings against all given compatible matches without type and name first, before checking the next compatible string. This implies that node's compatibles are ordered from specific to generic while given matches can be in any order. If we fail to find such a match entry, then fall-back to the old method in order to keep compatibility. Cc: Sebastian Hesselbarth Signed-off-by: Kevin Hao Tested-by: Stephen Chivers Signed-off-by: Rob Herring diff --git a/drivers/of/base.c b/drivers/of/base.c index ba195fb..10b5110 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -730,13 +730,49 @@ 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]) @@ -760,7 +796,12 @@ 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. + * 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. */ const struct of_device_id *of_match_node(const struct of_device_id *matches, const struct device_node *node) -- cgit v0.10.2 From 6d0abeca3242a88cab8232e4acd7e2bf088f3bc2 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 16 Feb 2014 13:30:25 -0800 Subject: Linux 3.14-rc3 diff --git a/Makefile b/Makefile index 933e1de..893d6f0 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 3 PATCHLEVEL = 14 SUBLEVEL = 0 -EXTRAVERSION = -rc2 +EXTRAVERSION = -rc3 NAME = Shuffling Zombie Juror # *DOCUMENTATION* -- cgit v0.10.2 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 diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index 52d45ea..361b40c 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 v0.10.2 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 diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c index 4ef83df..83face3 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 v0.10.2