From 6a806a214af42ac951e2d85e64d1bf4463482e16 Mon Sep 17 00:00:00 2001 From: Sifan Naeem Date: Thu, 18 Jun 2015 13:50:54 +0100 Subject: spi: img-spfi: fix support for speeds up to 1/4th input clock Setting the Same Edge bit indicates to the spfi block to receive and transmit data on the same edge of the spfi clock, which in turn doubles the operating frequency of spfi. The maximum supported frequency is limited to 1/4th of the spfi input clock, but without this bit set the maximum would be 1/8th of the input clock. The current driver calculates the divisor with maximum speed at 1/4th of the input clock, this would fail if the requested frequency is higher than 1/8 of the input clock. Any requests for 1/8th of the input clock would still pass. Fixes: 8543d0e72d43 ("spi: img-spfi: Limit bit clock to 1/4th of input clock") Signed-off-by: Sifan Naeem Signed-off-by: Mark Brown Cc: --- drivers/spi/spi-img-spfi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/spi/spi-img-spfi.c b/drivers/spi/spi-img-spfi.c index 788e2b176a4f..acce90ac7371 100644 --- a/drivers/spi/spi-img-spfi.c +++ b/drivers/spi/spi-img-spfi.c @@ -40,6 +40,7 @@ #define SPFI_CONTROL_SOFT_RESET BIT(11) #define SPFI_CONTROL_SEND_DMA BIT(10) #define SPFI_CONTROL_GET_DMA BIT(9) +#define SPFI_CONTROL_SE BIT(8) #define SPFI_CONTROL_TMODE_SHIFT 5 #define SPFI_CONTROL_TMODE_MASK 0x7 #define SPFI_CONTROL_TMODE_SINGLE 0 @@ -491,6 +492,7 @@ static void img_spfi_config(struct spi_master *master, struct spi_device *spi, else if (xfer->tx_nbits == SPI_NBITS_QUAD && xfer->rx_nbits == SPI_NBITS_QUAD) val |= SPFI_CONTROL_TMODE_QUAD << SPFI_CONTROL_TMODE_SHIFT; + val |= SPFI_CONTROL_SE; spfi_writel(spfi, val, SPFI_CONTROL); } -- cgit v1.2.3 From 32c848e33ace75fce388cceff76223d12b46eaa3 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 24 Jun 2015 19:48:43 +0900 Subject: regulator: s2mps11: Fix GPIO suspend enable shift wrapping bug Status of enabling suspend mode for regulator was stored in bitmap-like long integer. However since adding support for S2MPU02 the number of regulators exceeded 32 so on devices with more than 32 regulators (S2MPU02 and S2MPS13) overflow happens when shifting the bit. This could lead to enabling suspend mode for completely different regulator than intended or to switching different regulator to other mode (e.g. from always enabled to controlled by PWRHOLD pin). Both cases could result in larger energy usage and issues when suspending to RAM. Fixes: 00e2573d2c10 ("regulator: s2mps11: Add support S2MPU02 regulator device") Reported-by: Dan Carpenter Signed-off-by: Krzysztof Kozlowski Signed-off-by: Mark Brown Cc: --- drivers/regulator/s2mps11.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index 326ffb553371..72fc3c32db49 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c @@ -34,6 +34,8 @@ #include #include +/* The highest number of possible regulators for supported devices. */ +#define S2MPS_REGULATOR_MAX S2MPS13_REGULATOR_MAX struct s2mps11_info { unsigned int rdev_num; int ramp_delay2; @@ -49,7 +51,7 @@ struct s2mps11_info { * One bit for each S2MPS13/S2MPS14/S2MPU02 regulator whether * the suspend mode was enabled. */ - unsigned long long s2mps14_suspend_state:50; + DECLARE_BITMAP(suspend_state, S2MPS_REGULATOR_MAX); /* Array of size rdev_num with GPIO-s for external sleep control */ int *ext_control_gpio; @@ -500,7 +502,7 @@ static int s2mps14_regulator_enable(struct regulator_dev *rdev) switch (s2mps11->dev_type) { case S2MPS13X: case S2MPS14X: - if (s2mps11->s2mps14_suspend_state & (1 << rdev_get_id(rdev))) + if (test_bit(rdev_get_id(rdev), s2mps11->suspend_state)) val = S2MPS14_ENABLE_SUSPEND; else if (gpio_is_valid(s2mps11->ext_control_gpio[rdev_get_id(rdev)])) val = S2MPS14_ENABLE_EXT_CONTROL; @@ -508,7 +510,7 @@ static int s2mps14_regulator_enable(struct regulator_dev *rdev) val = rdev->desc->enable_mask; break; case S2MPU02: - if (s2mps11->s2mps14_suspend_state & (1 << rdev_get_id(rdev))) + if (test_bit(rdev_get_id(rdev), s2mps11->suspend_state)) val = S2MPU02_ENABLE_SUSPEND; else val = rdev->desc->enable_mask; @@ -562,7 +564,7 @@ static int s2mps14_regulator_set_suspend_disable(struct regulator_dev *rdev) if (ret < 0) return ret; - s2mps11->s2mps14_suspend_state |= (1 << rdev_get_id(rdev)); + set_bit(rdev_get_id(rdev), s2mps11->suspend_state); /* * Don't enable suspend mode if regulator is already disabled because * this would effectively for a short time turn on the regulator after @@ -960,18 +962,22 @@ static int s2mps11_pmic_probe(struct platform_device *pdev) case S2MPS11X: s2mps11->rdev_num = ARRAY_SIZE(s2mps11_regulators); regulators = s2mps11_regulators; + BUILD_BUG_ON(S2MPS_REGULATOR_MAX < s2mps11->rdev_num); break; case S2MPS13X: s2mps11->rdev_num = ARRAY_SIZE(s2mps13_regulators); regulators = s2mps13_regulators; + BUILD_BUG_ON(S2MPS_REGULATOR_MAX < s2mps11->rdev_num); break; case S2MPS14X: s2mps11->rdev_num = ARRAY_SIZE(s2mps14_regulators); regulators = s2mps14_regulators; + BUILD_BUG_ON(S2MPS_REGULATOR_MAX < s2mps11->rdev_num); break; case S2MPU02: s2mps11->rdev_num = ARRAY_SIZE(s2mpu02_regulators); regulators = s2mpu02_regulators; + BUILD_BUG_ON(S2MPS_REGULATOR_MAX < s2mps11->rdev_num); break; default: dev_err(&pdev->dev, "Invalid device type: %u\n", -- cgit v1.2.3 From 923a8c1d8069104726bde55c37cec66324ccc328 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sun, 31 May 2015 21:44:22 +0300 Subject: iwlwifi: mvm: fix antenna selection when BT is active When BT is active, we want to avoid the shared antenna for management frame to make sure we don't disturb BT. There was a bug in that code because it chose the antenna BIT(ANT_A) where ANT_A is already a bitmap (0x1). This means that the antenna chosen in the end was ANT_B. While this is not optimal on devices with 2 antennas (it'd disturb BT), it is critical on single antenna devices like 3160 which couldn't connect at all when BT was active. This fixes: https://bugzilla.kernel.org/show_bug.cgi?id=97181 CC: [3.17+] Fixes: 34c8b24ff284 ("iwlwifi: mvm: BT Coex - avoid the shared antenna for management frames") Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/tx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c index 7ba7a118ff5c..89116864d2a0 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/iwlwifi/mvm/tx.c @@ -252,7 +252,7 @@ void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm, struct iwl_tx_cmd *tx_cmd, if (info->band == IEEE80211_BAND_2GHZ && !iwl_mvm_bt_coex_is_shared_ant_avail(mvm)) - rate_flags = BIT(mvm->cfg->non_shared_ant) << RATE_MCS_ANT_POS; + rate_flags = mvm->cfg->non_shared_ant << RATE_MCS_ANT_POS; else rate_flags = BIT(mvm->mgmt_last_antenna_idx) << RATE_MCS_ANT_POS; -- cgit v1.2.3 From 11828dbce6f769ed631919aa378b645b1af6bda6 Mon Sep 17 00:00:00 2001 From: Matti Gottlieb Date: Mon, 1 Jun 2015 15:15:11 +0300 Subject: iwlwifi: mvm: Avoid accessing Null pointer when setting igtk Sometimes when setting an igtk key the station maybe NULL. In the of case igtk the function will skip to the end, and try to print sta->addr, if sta is Null - we will access a Null pointer. Avoid accessing a Null pointer when setting a igtk key & the sta == NULL, and print a default MAC address instead. Signed-off-by: Matti Gottlieb Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/sta.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c index d68dc697a4a0..26f076e82149 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/iwlwifi/mvm/sta.c @@ -1401,6 +1401,7 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm, bool mcast = !(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE); u8 sta_id; int ret; + static const u8 __maybe_unused zero_addr[ETH_ALEN] = {0}; lockdep_assert_held(&mvm->mutex); @@ -1467,7 +1468,7 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm, end: IWL_DEBUG_WEP(mvm, "key: cipher=%x len=%d idx=%d sta=%pM ret=%d\n", keyconf->cipher, keyconf->keylen, keyconf->keyidx, - sta->addr, ret); + sta ? sta->addr : zero_addr, ret); return ret; } -- cgit v1.2.3 From 0fd72ff92d6bea32bba612744abbe6a0abd25e43 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 24 Jun 2015 17:27:43 +0300 Subject: HID: wacom: NULL dereferences on error in probe() We can't pass a NULL to input_unregister_device(). Fixes: 2a6cdbdd4cc0 ('HID: wacom: Introduce new 'touch_input' device') Signed-off-by: Dan Carpenter Reviewed-by: Jason Gerecke Signed-off-by: Jiri Kosina --- drivers/hid/wacom_sys.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index 4c0ffca97bef..44958d79d598 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -1271,11 +1271,13 @@ fail_leds: pad_input_dev = NULL; wacom_wac->pad_registered = false; fail_register_pad_input: - input_unregister_device(touch_input_dev); + if (touch_input_dev) + input_unregister_device(touch_input_dev); wacom_wac->touch_input = NULL; wacom_wac->touch_registered = false; fail_register_touch_input: - input_unregister_device(pen_input_dev); + if (pen_input_dev) + input_unregister_device(pen_input_dev); wacom_wac->pen_input = NULL; wacom_wac->pen_registered = false; fail_register_pen_input: -- cgit v1.2.3 From c5b2b809cee8db018ac68566fe2114c175d79b5b Mon Sep 17 00:00:00 2001 From: Reyad Attiyat Date: Sun, 28 Jun 2015 19:22:37 -0500 Subject: HID: microsoft: Add quirk for MS Surface Type/Touch cover The newer firmware on MS Surface 2 tablets causes the type and touch cover keyboards to timeout when waiting for reports. The quirk HID_QUIRK_NO_INIT_REPORTS allows them to function normally. Signed-off-by: Reyad Attiyat Signed-off-by: Jiri Kosina --- drivers/hid/usbhid/hid-quirks.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 53e7de7cb9e2..20f9a653444c 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -87,6 +87,9 @@ static const struct hid_blacklist { { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOUSE_C05A, HID_QUIRK_ALWAYS_POLL }, { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOUSE_C06A, HID_QUIRK_ALWAYS_POLL }, { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE_PRO_2, HID_QUIRK_NO_INIT_REPORTS }, + { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_2, HID_QUIRK_NO_INIT_REPORTS }, + { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TOUCH_COVER_2, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3_JP, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER, HID_QUIRK_NO_INIT_REPORTS }, -- cgit v1.2.3 From 8b0a9d42301e45d501d751074a6f767fded680b1 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 29 Jun 2015 11:16:25 +0200 Subject: virtio_net: document VIRTIO_NET_CTRL_GUEST_OFFLOADS Document VIRTIO_NET_CTRL_GUEST_OFFLOADS and the relevant feature bits. Will allow ethtool control of the offloads down the road. Reported-by: Yan Vugenfirer Signed-off-by: Michael S. Tsirkin --- include/uapi/linux/virtio_net.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/include/uapi/linux/virtio_net.h b/include/uapi/linux/virtio_net.h index 7bbee79ca293..ec32293a00db 100644 --- a/include/uapi/linux/virtio_net.h +++ b/include/uapi/linux/virtio_net.h @@ -34,6 +34,7 @@ /* The feature bitmap for virtio net */ #define VIRTIO_NET_F_CSUM 0 /* Host handles pkts w/ partial csum */ #define VIRTIO_NET_F_GUEST_CSUM 1 /* Guest handles pkts w/ partial csum */ +#define VIRTIO_NET_F_CTRL_GUEST_OFFLOADS 2 /* Dynamic offload configuration. */ #define VIRTIO_NET_F_MAC 5 /* Host has given MAC address. */ #define VIRTIO_NET_F_GUEST_TSO4 7 /* Guest can handle TSOv4 in. */ #define VIRTIO_NET_F_GUEST_TSO6 8 /* Guest can handle TSOv6 in. */ @@ -226,4 +227,19 @@ struct virtio_net_ctrl_mq { #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN 1 #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX 0x8000 +/* + * Control network offloads + * + * Reconfigures the network offloads that Guest can handle. + * + * Available with the VIRTIO_NET_F_CTRL_GUEST_OFFLOADS feature bit. + * + * Command data format matches the feature bit mask exactly. + * + * See VIRTIO_NET_F_GUEST_* for the list of offloads + * that can be enabled/disabled. + */ +#define VIRTIO_NET_CTRL_GUEST_OFFLOADS 5 +#define VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET 0 + #endif /* _LINUX_VIRTIO_NET_H */ -- cgit v1.2.3 From bcfeacab45e6d419c6bafc0e57ea4b1125e23231 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Tue, 16 Jun 2015 18:33:35 +0200 Subject: vhost: use binary search instead of linear in find_region() For default region layouts performance stays the same as linear search i.e. it takes around 210ns average for translate_desc() that inlines find_region(). But it scales better with larger amount of regions, 235ns BS vs 300ns LS with 55 memory regions and it will be about the same values when allowed number of slots is increased to 509 like it has been done in kvm. Signed-off-by: Igor Mammedov Signed-off-by: Michael S. Tsirkin --- drivers/vhost/vhost.c | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 9e8e004bb1c3..71bb46813031 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "vhost.h" @@ -663,6 +664,16 @@ int vhost_vq_access_ok(struct vhost_virtqueue *vq) } EXPORT_SYMBOL_GPL(vhost_vq_access_ok); +static int vhost_memory_reg_sort_cmp(const void *p1, const void *p2) +{ + const struct vhost_memory_region *r1 = p1, *r2 = p2; + if (r1->guest_phys_addr < r2->guest_phys_addr) + return 1; + if (r1->guest_phys_addr > r2->guest_phys_addr) + return -1; + return 0; +} + static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m) { struct vhost_memory mem, *newmem, *oldmem; @@ -682,9 +693,11 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m) memcpy(newmem, &mem, size); if (copy_from_user(newmem->regions, m->regions, mem.nregions * sizeof *m->regions)) { - kfree(newmem); + kvfree(newmem); return -EFAULT; } + sort(newmem->regions, newmem->nregions, sizeof(*newmem->regions), + vhost_memory_reg_sort_cmp, NULL); if (!memory_access_ok(d, newmem, 0)) { kfree(newmem); @@ -992,17 +1005,22 @@ EXPORT_SYMBOL_GPL(vhost_dev_ioctl); static const struct vhost_memory_region *find_region(struct vhost_memory *mem, __u64 addr, __u32 len) { - struct vhost_memory_region *reg; - int i; + const struct vhost_memory_region *reg; + int start = 0, end = mem->nregions; - /* linear search is not brilliant, but we really have on the order of 6 - * regions in practice */ - for (i = 0; i < mem->nregions; ++i) { - reg = mem->regions + i; - if (reg->guest_phys_addr <= addr && - reg->guest_phys_addr + reg->memory_size - 1 >= addr) - return reg; + while (start < end) { + int slot = start + (end - start) / 2; + reg = mem->regions + slot; + if (addr >= reg->guest_phys_addr) + end = slot; + else + start = slot + 1; } + + reg = mem->regions + start; + if (addr >= reg->guest_phys_addr && + reg->guest_phys_addr + reg->memory_size > addr) + return reg; return NULL; } -- cgit v1.2.3 From 159eeea4cbc142bd5fd396a84cc63345455586a6 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Thu, 25 Jun 2015 19:14:18 +0200 Subject: MAINTAINERS: mtd: docg3: add docg3 maintainer Add myself as maintainer of the NAND based MSystems DiskOnChip G3 driver. Signed-off-by: Robert Jarzmik Signed-off-by: Brian Norris --- MAINTAINERS | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 8133cefb6b6e..956732963740 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6824,6 +6824,12 @@ T: git git://linuxtv.org/anttip/media_tree.git S: Maintained F: drivers/media/usb/msi2500/ +MSYSTEMS DISKONCHIP G3 MTD DRIVER +M: Robert Jarzmik +L: linux-mtd@lists.infradead.org +S: Maintained +F: drivers/mtd/devices/docg3* + MT9M032 APTINA SENSOR DRIVER M: Laurent Pinchart L: linux-media@vger.kernel.org -- cgit v1.2.3 From 908a5544cd29ed60114ed60bded6dbe8cdd56326 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Tue, 30 Jun 2015 10:59:04 +1000 Subject: virtio scsi: fix unused variable warning drivers/scsi/virtio_scsi.c: In function 'virtscsi_probe': drivers/scsi/virtio_scsi.c:952:11: warning: unused variable 'host_prot' [-Wunused-variable] int err, host_prot; ^ Signed-off-by: Stephen Rothwell Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- drivers/scsi/virtio_scsi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c index f164f24a4a55..55441c7f3e83 100644 --- a/drivers/scsi/virtio_scsi.c +++ b/drivers/scsi/virtio_scsi.c @@ -944,7 +944,7 @@ static int virtscsi_probe(struct virtio_device *vdev) { struct Scsi_Host *shost; struct virtio_scsi *vscsi; - int err, host_prot; + int err; u32 sg_elems, num_targets; u32 cmd_per_lun; u32 num_queues; @@ -1003,6 +1003,8 @@ static int virtscsi_probe(struct virtio_device *vdev) shost->nr_hw_queues = num_queues; if (virtio_has_feature(vdev, VIRTIO_SCSI_F_T10_PI)) { + int host_prot; + host_prot = SHOST_DIF_TYPE1_PROTECTION | SHOST_DIF_TYPE2_PROTECTION | SHOST_DIF_TYPE3_PROTECTION | SHOST_DIX_TYPE1_PROTECTION | SHOST_DIX_TYPE2_PROTECTION | SHOST_DIX_TYPE3_PROTECTION; -- cgit v1.2.3 From d768f32aec8c0ebb8499ffca89cfed8f5f1a4432 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Thu, 2 Jul 2015 09:21:22 +0200 Subject: virtio: Fix typecast of pointer in vring_init() The virtio_ring.h header is used in userspace programs (ie. QEMU), too. Here we can not assume that sizeof(pointer) is the same as sizeof(long), e.g. when compiling for Windows, so the typecast in vring_init() should be done with (uintptr_t) instead of (unsigned long). Signed-off-by: Thomas Huth Signed-off-by: Michael S. Tsirkin --- include/uapi/linux/virtio_ring.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/uapi/linux/virtio_ring.h b/include/uapi/linux/virtio_ring.h index 915980ac68df..c07295969b7e 100644 --- a/include/uapi/linux/virtio_ring.h +++ b/include/uapi/linux/virtio_ring.h @@ -31,6 +31,9 @@ * SUCH DAMAGE. * * Copyright Rusty Russell IBM Corporation 2007. */ +#ifndef __KERNEL__ +#include +#endif #include #include @@ -143,7 +146,7 @@ static inline void vring_init(struct vring *vr, unsigned int num, void *p, vr->num = num; vr->desc = p; vr->avail = p + num*sizeof(struct vring_desc); - vr->used = (void *)(((unsigned long)&vr->avail->ring[num] + sizeof(__virtio16) + vr->used = (void *)(((uintptr_t)&vr->avail->ring[num] + sizeof(__virtio16) + align-1) & ~(align - 1)); } -- cgit v1.2.3 From 3121bb023e2db4f00ed6678898c09e35ed4b5301 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Thu, 2 Jul 2015 10:56:49 +0200 Subject: virtio: define virtio_pci_cfg_cap in header. We already have VIRTIO_PCI_CAP_PCI_CFG, let's define the structure that goes with it. Signed-off-by: Michael S. Tsirkin --- include/uapi/linux/virtio_pci.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/uapi/linux/virtio_pci.h b/include/uapi/linux/virtio_pci.h index 75301468359f..90007a1abcab 100644 --- a/include/uapi/linux/virtio_pci.h +++ b/include/uapi/linux/virtio_pci.h @@ -157,6 +157,12 @@ struct virtio_pci_common_cfg { __le32 queue_used_hi; /* read-write */ }; +/* Fields in VIRTIO_PCI_CAP_PCI_CFG: */ +struct virtio_pci_cfg_cap { + struct virtio_pci_cap cap; + __u8 pci_cfg_data[4]; /* Data for BAR access. */ +}; + /* Macro versions of offsets for the Old Timers! */ #define VIRTIO_PCI_CAP_VNDR 0 #define VIRTIO_PCI_CAP_NEXT 1 -- cgit v1.2.3 From f2dbda3b4fc2833f0a6240ac28b0e3a17f09893b Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Wed, 1 Jul 2015 17:15:37 +0200 Subject: MAINTAINERS: separate section for s390 virtio drivers The s390-specific virtio drivers have probably more to do with virtio than with kvm today; let's move them out into a separate section to reflect this and to be able to add relevant mailing lists. CC: Christian Borntraeger Signed-off-by: Cornelia Huck Signed-off-by: Michael S. Tsirkin --- MAINTAINERS | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index af802b357b6a..280a5681d5b2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5690,7 +5690,6 @@ S: Supported F: Documentation/s390/kvm.txt F: arch/s390/include/asm/kvm* F: arch/s390/kvm/ -F: drivers/s390/kvm/ KERNEL VIRTUAL MACHINE (KVM) FOR ARM M: Christoffer Dall @@ -10571,6 +10570,15 @@ F: drivers/block/virtio_blk.c F: include/linux/virtio_*.h F: include/uapi/linux/virtio_*.h +VIRTIO DRIVERS FOR S390 +M: Christian Borntraeger +M: Cornelia Huck +L: linux-s390@vger.kernel.org +L: virtualization@lists.linux-foundation.org +L: kvm@vger.kernel.org +S: Supported +F: drivers/s390/kvm/ + VIRTIO HOST (VHOST) M: "Michael S. Tsirkin" L: kvm@vger.kernel.org -- cgit v1.2.3 From 1b568d934eec1c5c99565c41f6c8ca66e9743e96 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Tue, 7 Jul 2015 11:41:01 +0200 Subject: virtio/s390: rename drivers/s390/kvm -> drivers/s390/virtio This more accurately reflects what these drivers actually do. Suggested-by: Paolo Bonzini Acked-by: Christian Borntraeger Signed-off-by: Cornelia Huck Signed-off-by: Michael S. Tsirkin --- MAINTAINERS | 2 +- drivers/s390/Makefile | 2 +- drivers/s390/kvm/Makefile | 9 - drivers/s390/kvm/kvm_virtio.c | 510 -------------- drivers/s390/kvm/virtio_ccw.c | 1380 -------------------------------------- drivers/s390/virtio/Makefile | 9 + drivers/s390/virtio/kvm_virtio.c | 510 ++++++++++++++ drivers/s390/virtio/virtio_ccw.c | 1380 ++++++++++++++++++++++++++++++++++++++ 8 files changed, 1901 insertions(+), 1901 deletions(-) delete mode 100644 drivers/s390/kvm/Makefile delete mode 100644 drivers/s390/kvm/kvm_virtio.c delete mode 100644 drivers/s390/kvm/virtio_ccw.c create mode 100644 drivers/s390/virtio/Makefile create mode 100644 drivers/s390/virtio/kvm_virtio.c create mode 100644 drivers/s390/virtio/virtio_ccw.c diff --git a/MAINTAINERS b/MAINTAINERS index 280a5681d5b2..fbef7d0a4dd5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10577,7 +10577,7 @@ L: linux-s390@vger.kernel.org L: virtualization@lists.linux-foundation.org L: kvm@vger.kernel.org S: Supported -F: drivers/s390/kvm/ +F: drivers/s390/virtio/ VIRTIO HOST (VHOST) M: "Michael S. Tsirkin" diff --git a/drivers/s390/Makefile b/drivers/s390/Makefile index 95bccfd3f169..e5225ad9c5b1 100644 --- a/drivers/s390/Makefile +++ b/drivers/s390/Makefile @@ -2,7 +2,7 @@ # Makefile for the S/390 specific device drivers # -obj-y += cio/ block/ char/ crypto/ net/ scsi/ kvm/ +obj-y += cio/ block/ char/ crypto/ net/ scsi/ virtio/ drivers-y += drivers/s390/built-in.o diff --git a/drivers/s390/kvm/Makefile b/drivers/s390/kvm/Makefile deleted file mode 100644 index 241891a57caf..000000000000 --- a/drivers/s390/kvm/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# Makefile for kvm guest drivers on s390 -# -# Copyright IBM Corp. 2008 -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License (version 2 only) -# as published by the Free Software Foundation. - -obj-$(CONFIG_S390_GUEST) += kvm_virtio.o virtio_ccw.o diff --git a/drivers/s390/kvm/kvm_virtio.c b/drivers/s390/kvm/kvm_virtio.c deleted file mode 100644 index dd65c8b4c7fe..000000000000 --- a/drivers/s390/kvm/kvm_virtio.c +++ /dev/null @@ -1,510 +0,0 @@ -/* - * virtio for kvm on s390 - * - * Copyright IBM Corp. 2008 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License (version 2 only) - * as published by the Free Software Foundation. - * - * Author(s): Christian Borntraeger - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define VIRTIO_SUBCODE_64 0x0D00 - -/* - * The pointer to our (page) of device descriptions. - */ -static void *kvm_devices; -static struct work_struct hotplug_work; - -struct kvm_device { - struct virtio_device vdev; - struct kvm_device_desc *desc; -}; - -#define to_kvmdev(vd) container_of(vd, struct kvm_device, vdev) - -/* - * memory layout: - * - kvm_device_descriptor - * struct kvm_device_desc - * - configuration - * struct kvm_vqconfig - * - feature bits - * - config space - */ -static struct kvm_vqconfig *kvm_vq_config(const struct kvm_device_desc *desc) -{ - return (struct kvm_vqconfig *)(desc + 1); -} - -static u8 *kvm_vq_features(const struct kvm_device_desc *desc) -{ - return (u8 *)(kvm_vq_config(desc) + desc->num_vq); -} - -static u8 *kvm_vq_configspace(const struct kvm_device_desc *desc) -{ - return kvm_vq_features(desc) + desc->feature_len * 2; -} - -/* - * The total size of the config page used by this device (incl. desc) - */ -static unsigned desc_size(const struct kvm_device_desc *desc) -{ - return sizeof(*desc) - + desc->num_vq * sizeof(struct kvm_vqconfig) - + desc->feature_len * 2 - + desc->config_len; -} - -/* This gets the device's feature bits. */ -static u64 kvm_get_features(struct virtio_device *vdev) -{ - unsigned int i; - u32 features = 0; - struct kvm_device_desc *desc = to_kvmdev(vdev)->desc; - u8 *in_features = kvm_vq_features(desc); - - for (i = 0; i < min(desc->feature_len * 8, 32); i++) - if (in_features[i / 8] & (1 << (i % 8))) - features |= (1 << i); - return features; -} - -static int kvm_finalize_features(struct virtio_device *vdev) -{ - unsigned int i, bits; - struct kvm_device_desc *desc = to_kvmdev(vdev)->desc; - /* Second half of bitmap is features we accept. */ - u8 *out_features = kvm_vq_features(desc) + desc->feature_len; - - /* Give virtio_ring a chance to accept features. */ - vring_transport_features(vdev); - - /* Make sure we don't have any features > 32 bits! */ - BUG_ON((u32)vdev->features != vdev->features); - - memset(out_features, 0, desc->feature_len); - bits = min_t(unsigned, desc->feature_len, sizeof(vdev->features)) * 8; - for (i = 0; i < bits; i++) { - if (__virtio_test_bit(vdev, i)) - out_features[i / 8] |= (1 << (i % 8)); - } - - return 0; -} - -/* - * Reading and writing elements in config space - */ -static void kvm_get(struct virtio_device *vdev, unsigned int offset, - void *buf, unsigned len) -{ - struct kvm_device_desc *desc = to_kvmdev(vdev)->desc; - - BUG_ON(offset + len > desc->config_len); - memcpy(buf, kvm_vq_configspace(desc) + offset, len); -} - -static void kvm_set(struct virtio_device *vdev, unsigned int offset, - const void *buf, unsigned len) -{ - struct kvm_device_desc *desc = to_kvmdev(vdev)->desc; - - BUG_ON(offset + len > desc->config_len); - memcpy(kvm_vq_configspace(desc) + offset, buf, len); -} - -/* - * The operations to get and set the status word just access - * the status field of the device descriptor. set_status will also - * make a hypercall to the host, to tell about status changes - */ -static u8 kvm_get_status(struct virtio_device *vdev) -{ - return to_kvmdev(vdev)->desc->status; -} - -static void kvm_set_status(struct virtio_device *vdev, u8 status) -{ - BUG_ON(!status); - to_kvmdev(vdev)->desc->status = status; - kvm_hypercall1(KVM_S390_VIRTIO_SET_STATUS, - (unsigned long) to_kvmdev(vdev)->desc); -} - -/* - * To reset the device, we use the KVM_VIRTIO_RESET hypercall, using the - * descriptor address. The Host will zero the status and all the - * features. - */ -static void kvm_reset(struct virtio_device *vdev) -{ - kvm_hypercall1(KVM_S390_VIRTIO_RESET, - (unsigned long) to_kvmdev(vdev)->desc); -} - -/* - * When the virtio_ring code wants to notify the Host, it calls us here and we - * make a hypercall. We hand the address of the virtqueue so the Host - * knows which virtqueue we're talking about. - */ -static bool kvm_notify(struct virtqueue *vq) -{ - long rc; - struct kvm_vqconfig *config = vq->priv; - - rc = kvm_hypercall1(KVM_S390_VIRTIO_NOTIFY, config->address); - if (rc < 0) - return false; - return true; -} - -/* - * This routine finds the first virtqueue described in the configuration of - * this device and sets it up. - */ -static struct virtqueue *kvm_find_vq(struct virtio_device *vdev, - unsigned index, - void (*callback)(struct virtqueue *vq), - const char *name) -{ - struct kvm_device *kdev = to_kvmdev(vdev); - struct kvm_vqconfig *config; - struct virtqueue *vq; - int err; - - if (index >= kdev->desc->num_vq) - return ERR_PTR(-ENOENT); - - if (!name) - return NULL; - - config = kvm_vq_config(kdev->desc)+index; - - err = vmem_add_mapping(config->address, - vring_size(config->num, - KVM_S390_VIRTIO_RING_ALIGN)); - if (err) - goto out; - - vq = vring_new_virtqueue(index, config->num, KVM_S390_VIRTIO_RING_ALIGN, - vdev, true, (void *) config->address, - kvm_notify, callback, name); - if (!vq) { - err = -ENOMEM; - goto unmap; - } - - /* - * register a callback token - * The host will sent this via the external interrupt parameter - */ - config->token = (u64) vq; - - vq->priv = config; - return vq; -unmap: - vmem_remove_mapping(config->address, - vring_size(config->num, - KVM_S390_VIRTIO_RING_ALIGN)); -out: - return ERR_PTR(err); -} - -static void kvm_del_vq(struct virtqueue *vq) -{ - struct kvm_vqconfig *config = vq->priv; - - vring_del_virtqueue(vq); - vmem_remove_mapping(config->address, - vring_size(config->num, - KVM_S390_VIRTIO_RING_ALIGN)); -} - -static void kvm_del_vqs(struct virtio_device *vdev) -{ - struct virtqueue *vq, *n; - - list_for_each_entry_safe(vq, n, &vdev->vqs, list) - kvm_del_vq(vq); -} - -static int kvm_find_vqs(struct virtio_device *vdev, unsigned nvqs, - struct virtqueue *vqs[], - vq_callback_t *callbacks[], - const char *names[]) -{ - struct kvm_device *kdev = to_kvmdev(vdev); - int i; - - /* We must have this many virtqueues. */ - if (nvqs > kdev->desc->num_vq) - return -ENOENT; - - for (i = 0; i < nvqs; ++i) { - vqs[i] = kvm_find_vq(vdev, i, callbacks[i], names[i]); - if (IS_ERR(vqs[i])) - goto error; - } - return 0; - -error: - kvm_del_vqs(vdev); - return PTR_ERR(vqs[i]); -} - -static const char *kvm_bus_name(struct virtio_device *vdev) -{ - return ""; -} - -/* - * The config ops structure as defined by virtio config - */ -static const struct virtio_config_ops kvm_vq_configspace_ops = { - .get_features = kvm_get_features, - .finalize_features = kvm_finalize_features, - .get = kvm_get, - .set = kvm_set, - .get_status = kvm_get_status, - .set_status = kvm_set_status, - .reset = kvm_reset, - .find_vqs = kvm_find_vqs, - .del_vqs = kvm_del_vqs, - .bus_name = kvm_bus_name, -}; - -/* - * The root device for the kvm virtio devices. - * This makes them appear as /sys/devices/kvm_s390/0,1,2 not /sys/devices/0,1,2. - */ -static struct device *kvm_root; - -/* - * adds a new device and register it with virtio - * appropriate drivers are loaded by the device model - */ -static void add_kvm_device(struct kvm_device_desc *d, unsigned int offset) -{ - struct kvm_device *kdev; - - kdev = kzalloc(sizeof(*kdev), GFP_KERNEL); - if (!kdev) { - printk(KERN_EMERG "Cannot allocate kvm dev %u type %u\n", - offset, d->type); - return; - } - - kdev->vdev.dev.parent = kvm_root; - kdev->vdev.id.device = d->type; - kdev->vdev.config = &kvm_vq_configspace_ops; - kdev->desc = d; - - if (register_virtio_device(&kdev->vdev) != 0) { - printk(KERN_ERR "Failed to register kvm device %u type %u\n", - offset, d->type); - kfree(kdev); - } -} - -/* - * scan_devices() simply iterates through the device page. - * The type 0 is reserved to mean "end of devices". - */ -static void scan_devices(void) -{ - unsigned int i; - struct kvm_device_desc *d; - - for (i = 0; i < PAGE_SIZE; i += desc_size(d)) { - d = kvm_devices + i; - - if (d->type == 0) - break; - - add_kvm_device(d, i); - } -} - -/* - * match for a kvm device with a specific desc pointer - */ -static int match_desc(struct device *dev, void *data) -{ - struct virtio_device *vdev = dev_to_virtio(dev); - struct kvm_device *kdev = to_kvmdev(vdev); - - return kdev->desc == data; -} - -/* - * hotplug_device tries to find changes in the device page. - */ -static void hotplug_devices(struct work_struct *dummy) -{ - unsigned int i; - struct kvm_device_desc *d; - struct device *dev; - - for (i = 0; i < PAGE_SIZE; i += desc_size(d)) { - d = kvm_devices + i; - - /* end of list */ - if (d->type == 0) - break; - - /* device already exists */ - dev = device_find_child(kvm_root, d, match_desc); - if (dev) { - /* XXX check for hotplug remove */ - put_device(dev); - continue; - } - - /* new device */ - printk(KERN_INFO "Adding new virtio device %p\n", d); - add_kvm_device(d, i); - } -} - -/* - * we emulate the request_irq behaviour on top of s390 extints - */ -static void kvm_extint_handler(struct ext_code ext_code, - unsigned int param32, unsigned long param64) -{ - struct virtqueue *vq; - u32 param; - - if ((ext_code.subcode & 0xff00) != VIRTIO_SUBCODE_64) - return; - inc_irq_stat(IRQEXT_VRT); - - /* The LSB might be overloaded, we have to mask it */ - vq = (struct virtqueue *)(param64 & ~1UL); - - /* We use ext_params to decide what this interrupt means */ - param = param32 & VIRTIO_PARAM_MASK; - - switch (param) { - case VIRTIO_PARAM_CONFIG_CHANGED: - virtio_config_changed(vq->vdev); - break; - case VIRTIO_PARAM_DEV_ADD: - schedule_work(&hotplug_work); - break; - case VIRTIO_PARAM_VRING_INTERRUPT: - default: - vring_interrupt(0, vq); - break; - } -} - -/* - * For s390-virtio, we expect a page above main storage containing - * the virtio configuration. Try to actually load from this area - * in order to figure out if the host provides this page. - */ -static int __init test_devices_support(unsigned long addr) -{ - int ret = -EIO; - - asm volatile( - "0: lura 0,%1\n" - "1: xgr %0,%0\n" - "2:\n" - EX_TABLE(0b,2b) - EX_TABLE(1b,2b) - : "+d" (ret) - : "a" (addr) - : "0", "cc"); - return ret; -} -/* - * Init function for virtio - * devices are in a single page above top of "normal" + standby mem - */ -static int __init kvm_devices_init(void) -{ - int rc; - unsigned long total_memory_size = sclp_get_rzm() * sclp_get_rnmax(); - - if (!MACHINE_IS_KVM) - return -ENODEV; - - if (test_devices_support(total_memory_size) < 0) - return -ENODEV; - - rc = vmem_add_mapping(total_memory_size, PAGE_SIZE); - if (rc) - return rc; - - kvm_devices = (void *) total_memory_size; - - kvm_root = root_device_register("kvm_s390"); - if (IS_ERR(kvm_root)) { - rc = PTR_ERR(kvm_root); - printk(KERN_ERR "Could not register kvm_s390 root device"); - vmem_remove_mapping(total_memory_size, PAGE_SIZE); - return rc; - } - - INIT_WORK(&hotplug_work, hotplug_devices); - - irq_subclass_register(IRQ_SUBCLASS_SERVICE_SIGNAL); - register_external_irq(EXT_IRQ_CP_SERVICE, kvm_extint_handler); - - scan_devices(); - return 0; -} - -/* code for early console output with virtio_console */ -static __init int early_put_chars(u32 vtermno, const char *buf, int count) -{ - char scratch[17]; - unsigned int len = count; - - if (len > sizeof(scratch) - 1) - len = sizeof(scratch) - 1; - scratch[len] = '\0'; - memcpy(scratch, buf, len); - kvm_hypercall1(KVM_S390_VIRTIO_NOTIFY, __pa(scratch)); - return len; -} - -static int __init s390_virtio_console_init(void) -{ - if (sclp_has_vt220() || sclp_has_linemode()) - return -ENODEV; - return virtio_cons_early_init(early_put_chars); -} -console_initcall(s390_virtio_console_init); - - -/* - * We do this after core stuff, but before the drivers. - */ -postcore_initcall(kvm_devices_init); diff --git a/drivers/s390/kvm/virtio_ccw.c b/drivers/s390/kvm/virtio_ccw.c deleted file mode 100644 index 6f1fa1773e76..000000000000 --- a/drivers/s390/kvm/virtio_ccw.c +++ /dev/null @@ -1,1380 +0,0 @@ -/* - * ccw based virtio transport - * - * Copyright IBM Corp. 2012, 2014 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License (version 2 only) - * as published by the Free Software Foundation. - * - * Author(s): Cornelia Huck - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * virtio related functions - */ - -struct vq_config_block { - __u16 index; - __u16 num; -} __packed; - -#define VIRTIO_CCW_CONFIG_SIZE 0x100 -/* same as PCI config space size, should be enough for all drivers */ - -struct virtio_ccw_device { - struct virtio_device vdev; - __u8 *status; - __u8 config[VIRTIO_CCW_CONFIG_SIZE]; - struct ccw_device *cdev; - __u32 curr_io; - int err; - unsigned int revision; /* Transport revision */ - wait_queue_head_t wait_q; - spinlock_t lock; - struct list_head virtqueues; - unsigned long indicators; - unsigned long indicators2; - struct vq_config_block *config_block; - bool is_thinint; - bool going_away; - bool device_lost; - void *airq_info; -}; - -struct vq_info_block_legacy { - __u64 queue; - __u32 align; - __u16 index; - __u16 num; -} __packed; - -struct vq_info_block { - __u64 desc; - __u32 res0; - __u16 index; - __u16 num; - __u64 avail; - __u64 used; -} __packed; - -struct virtio_feature_desc { - __u32 features; - __u8 index; -} __packed; - -struct virtio_thinint_area { - unsigned long summary_indicator; - unsigned long indicator; - u64 bit_nr; - u8 isc; -} __packed; - -struct virtio_rev_info { - __u16 revision; - __u16 length; - __u8 data[]; -}; - -/* the highest virtio-ccw revision we support */ -#define VIRTIO_CCW_REV_MAX 1 - -struct virtio_ccw_vq_info { - struct virtqueue *vq; - int num; - void *queue; - union { - struct vq_info_block s; - struct vq_info_block_legacy l; - } *info_block; - int bit_nr; - struct list_head node; - long cookie; -}; - -#define VIRTIO_AIRQ_ISC IO_SCH_ISC /* inherit from subchannel */ - -#define VIRTIO_IV_BITS (L1_CACHE_BYTES * 8) -#define MAX_AIRQ_AREAS 20 - -static int virtio_ccw_use_airq = 1; - -struct airq_info { - rwlock_t lock; - u8 summary_indicator; - struct airq_struct airq; - struct airq_iv *aiv; -}; -static struct airq_info *airq_areas[MAX_AIRQ_AREAS]; - -#define CCW_CMD_SET_VQ 0x13 -#define CCW_CMD_VDEV_RESET 0x33 -#define CCW_CMD_SET_IND 0x43 -#define CCW_CMD_SET_CONF_IND 0x53 -#define CCW_CMD_READ_FEAT 0x12 -#define CCW_CMD_WRITE_FEAT 0x11 -#define CCW_CMD_READ_CONF 0x22 -#define CCW_CMD_WRITE_CONF 0x21 -#define CCW_CMD_WRITE_STATUS 0x31 -#define CCW_CMD_READ_VQ_CONF 0x32 -#define CCW_CMD_SET_IND_ADAPTER 0x73 -#define CCW_CMD_SET_VIRTIO_REV 0x83 - -#define VIRTIO_CCW_DOING_SET_VQ 0x00010000 -#define VIRTIO_CCW_DOING_RESET 0x00040000 -#define VIRTIO_CCW_DOING_READ_FEAT 0x00080000 -#define VIRTIO_CCW_DOING_WRITE_FEAT 0x00100000 -#define VIRTIO_CCW_DOING_READ_CONFIG 0x00200000 -#define VIRTIO_CCW_DOING_WRITE_CONFIG 0x00400000 -#define VIRTIO_CCW_DOING_WRITE_STATUS 0x00800000 -#define VIRTIO_CCW_DOING_SET_IND 0x01000000 -#define VIRTIO_CCW_DOING_READ_VQ_CONF 0x02000000 -#define VIRTIO_CCW_DOING_SET_CONF_IND 0x04000000 -#define VIRTIO_CCW_DOING_SET_IND_ADAPTER 0x08000000 -#define VIRTIO_CCW_DOING_SET_VIRTIO_REV 0x10000000 -#define VIRTIO_CCW_INTPARM_MASK 0xffff0000 - -static struct virtio_ccw_device *to_vc_device(struct virtio_device *vdev) -{ - return container_of(vdev, struct virtio_ccw_device, vdev); -} - -static void drop_airq_indicator(struct virtqueue *vq, struct airq_info *info) -{ - unsigned long i, flags; - - write_lock_irqsave(&info->lock, flags); - for (i = 0; i < airq_iv_end(info->aiv); i++) { - if (vq == (void *)airq_iv_get_ptr(info->aiv, i)) { - airq_iv_free_bit(info->aiv, i); - airq_iv_set_ptr(info->aiv, i, 0); - break; - } - } - write_unlock_irqrestore(&info->lock, flags); -} - -static void virtio_airq_handler(struct airq_struct *airq) -{ - struct airq_info *info = container_of(airq, struct airq_info, airq); - unsigned long ai; - - inc_irq_stat(IRQIO_VAI); - read_lock(&info->lock); - /* Walk through indicators field, summary indicator active. */ - for (ai = 0;;) { - ai = airq_iv_scan(info->aiv, ai, airq_iv_end(info->aiv)); - if (ai == -1UL) - break; - vring_interrupt(0, (void *)airq_iv_get_ptr(info->aiv, ai)); - } - info->summary_indicator = 0; - smp_wmb(); - /* Walk through indicators field, summary indicator not active. */ - for (ai = 0;;) { - ai = airq_iv_scan(info->aiv, ai, airq_iv_end(info->aiv)); - if (ai == -1UL) - break; - vring_interrupt(0, (void *)airq_iv_get_ptr(info->aiv, ai)); - } - read_unlock(&info->lock); -} - -static struct airq_info *new_airq_info(void) -{ - struct airq_info *info; - int rc; - - info = kzalloc(sizeof(*info), GFP_KERNEL); - if (!info) - return NULL; - rwlock_init(&info->lock); - info->aiv = airq_iv_create(VIRTIO_IV_BITS, AIRQ_IV_ALLOC | AIRQ_IV_PTR); - if (!info->aiv) { - kfree(info); - return NULL; - } - info->airq.handler = virtio_airq_handler; - info->airq.lsi_ptr = &info->summary_indicator; - info->airq.lsi_mask = 0xff; - info->airq.isc = VIRTIO_AIRQ_ISC; - rc = register_adapter_interrupt(&info->airq); - if (rc) { - airq_iv_release(info->aiv); - kfree(info); - return NULL; - } - return info; -} - -static void destroy_airq_info(struct airq_info *info) -{ - if (!info) - return; - - unregister_adapter_interrupt(&info->airq); - airq_iv_release(info->aiv); - kfree(info); -} - -static unsigned long get_airq_indicator(struct virtqueue *vqs[], int nvqs, - u64 *first, void **airq_info) -{ - int i, j; - struct airq_info *info; - unsigned long indicator_addr = 0; - unsigned long bit, flags; - - for (i = 0; i < MAX_AIRQ_AREAS && !indicator_addr; i++) { - if (!airq_areas[i]) - airq_areas[i] = new_airq_info(); - info = airq_areas[i]; - if (!info) - return 0; - write_lock_irqsave(&info->lock, flags); - bit = airq_iv_alloc(info->aiv, nvqs); - if (bit == -1UL) { - /* Not enough vacancies. */ - write_unlock_irqrestore(&info->lock, flags); - continue; - } - *first = bit; - *airq_info = info; - indicator_addr = (unsigned long)info->aiv->vector; - for (j = 0; j < nvqs; j++) { - airq_iv_set_ptr(info->aiv, bit + j, - (unsigned long)vqs[j]); - } - write_unlock_irqrestore(&info->lock, flags); - } - return indicator_addr; -} - -static void virtio_ccw_drop_indicators(struct virtio_ccw_device *vcdev) -{ - struct virtio_ccw_vq_info *info; - - list_for_each_entry(info, &vcdev->virtqueues, node) - drop_airq_indicator(info->vq, vcdev->airq_info); -} - -static int doing_io(struct virtio_ccw_device *vcdev, __u32 flag) -{ - unsigned long flags; - __u32 ret; - - spin_lock_irqsave(get_ccwdev_lock(vcdev->cdev), flags); - if (vcdev->err) - ret = 0; - else - ret = vcdev->curr_io & flag; - spin_unlock_irqrestore(get_ccwdev_lock(vcdev->cdev), flags); - return ret; -} - -static int ccw_io_helper(struct virtio_ccw_device *vcdev, - struct ccw1 *ccw, __u32 intparm) -{ - int ret; - unsigned long flags; - int flag = intparm & VIRTIO_CCW_INTPARM_MASK; - - do { - spin_lock_irqsave(get_ccwdev_lock(vcdev->cdev), flags); - ret = ccw_device_start(vcdev->cdev, ccw, intparm, 0, 0); - if (!ret) { - if (!vcdev->curr_io) - vcdev->err = 0; - vcdev->curr_io |= flag; - } - spin_unlock_irqrestore(get_ccwdev_lock(vcdev->cdev), flags); - cpu_relax(); - } while (ret == -EBUSY); - wait_event(vcdev->wait_q, doing_io(vcdev, flag) == 0); - return ret ? ret : vcdev->err; -} - -static void virtio_ccw_drop_indicator(struct virtio_ccw_device *vcdev, - struct ccw1 *ccw) -{ - int ret; - unsigned long *indicatorp = NULL; - struct virtio_thinint_area *thinint_area = NULL; - struct airq_info *airq_info = vcdev->airq_info; - - if (vcdev->is_thinint) { - thinint_area = kzalloc(sizeof(*thinint_area), - GFP_DMA | GFP_KERNEL); - if (!thinint_area) - return; - thinint_area->summary_indicator = - (unsigned long) &airq_info->summary_indicator; - thinint_area->isc = VIRTIO_AIRQ_ISC; - ccw->cmd_code = CCW_CMD_SET_IND_ADAPTER; - ccw->count = sizeof(*thinint_area); - ccw->cda = (__u32)(unsigned long) thinint_area; - } else { - indicatorp = kmalloc(sizeof(&vcdev->indicators), - GFP_DMA | GFP_KERNEL); - if (!indicatorp) - return; - *indicatorp = 0; - ccw->cmd_code = CCW_CMD_SET_IND; - ccw->count = sizeof(vcdev->indicators); - ccw->cda = (__u32)(unsigned long) indicatorp; - } - /* Deregister indicators from host. */ - vcdev->indicators = 0; - ccw->flags = 0; - ret = ccw_io_helper(vcdev, ccw, - vcdev->is_thinint ? - VIRTIO_CCW_DOING_SET_IND_ADAPTER : - VIRTIO_CCW_DOING_SET_IND); - if (ret && (ret != -ENODEV)) - dev_info(&vcdev->cdev->dev, - "Failed to deregister indicators (%d)\n", ret); - else if (vcdev->is_thinint) - virtio_ccw_drop_indicators(vcdev); - kfree(indicatorp); - kfree(thinint_area); -} - -static inline long do_kvm_notify(struct subchannel_id schid, - unsigned long queue_index, - long cookie) -{ - register unsigned long __nr asm("1") = KVM_S390_VIRTIO_CCW_NOTIFY; - register struct subchannel_id __schid asm("2") = schid; - register unsigned long __index asm("3") = queue_index; - register long __rc asm("2"); - register long __cookie asm("4") = cookie; - - asm volatile ("diag 2,4,0x500\n" - : "=d" (__rc) : "d" (__nr), "d" (__schid), "d" (__index), - "d"(__cookie) - : "memory", "cc"); - return __rc; -} - -static bool virtio_ccw_kvm_notify(struct virtqueue *vq) -{ - struct virtio_ccw_vq_info *info = vq->priv; - struct virtio_ccw_device *vcdev; - struct subchannel_id schid; - - vcdev = to_vc_device(info->vq->vdev); - ccw_device_get_schid(vcdev->cdev, &schid); - info->cookie = do_kvm_notify(schid, vq->index, info->cookie); - if (info->cookie < 0) - return false; - return true; -} - -static int virtio_ccw_read_vq_conf(struct virtio_ccw_device *vcdev, - struct ccw1 *ccw, int index) -{ - vcdev->config_block->index = index; - ccw->cmd_code = CCW_CMD_READ_VQ_CONF; - ccw->flags = 0; - ccw->count = sizeof(struct vq_config_block); - ccw->cda = (__u32)(unsigned long)(vcdev->config_block); - ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_READ_VQ_CONF); - return vcdev->config_block->num; -} - -static void virtio_ccw_del_vq(struct virtqueue *vq, struct ccw1 *ccw) -{ - struct virtio_ccw_device *vcdev = to_vc_device(vq->vdev); - struct virtio_ccw_vq_info *info = vq->priv; - unsigned long flags; - unsigned long size; - int ret; - unsigned int index = vq->index; - - /* Remove from our list. */ - spin_lock_irqsave(&vcdev->lock, flags); - list_del(&info->node); - spin_unlock_irqrestore(&vcdev->lock, flags); - - /* Release from host. */ - if (vcdev->revision == 0) { - info->info_block->l.queue = 0; - info->info_block->l.align = 0; - info->info_block->l.index = index; - info->info_block->l.num = 0; - ccw->count = sizeof(info->info_block->l); - } else { - info->info_block->s.desc = 0; - info->info_block->s.index = index; - info->info_block->s.num = 0; - info->info_block->s.avail = 0; - info->info_block->s.used = 0; - ccw->count = sizeof(info->info_block->s); - } - ccw->cmd_code = CCW_CMD_SET_VQ; - ccw->flags = 0; - ccw->cda = (__u32)(unsigned long)(info->info_block); - ret = ccw_io_helper(vcdev, ccw, - VIRTIO_CCW_DOING_SET_VQ | index); - /* - * -ENODEV isn't considered an error: The device is gone anyway. - * This may happen on device detach. - */ - if (ret && (ret != -ENODEV)) - dev_warn(&vq->vdev->dev, "Error %d while deleting queue %d", - ret, index); - - vring_del_virtqueue(vq); - size = PAGE_ALIGN(vring_size(info->num, KVM_VIRTIO_CCW_RING_ALIGN)); - free_pages_exact(info->queue, size); - kfree(info->info_block); - kfree(info); -} - -static void virtio_ccw_del_vqs(struct virtio_device *vdev) -{ - struct virtqueue *vq, *n; - struct ccw1 *ccw; - struct virtio_ccw_device *vcdev = to_vc_device(vdev); - - ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL); - if (!ccw) - return; - - virtio_ccw_drop_indicator(vcdev, ccw); - - list_for_each_entry_safe(vq, n, &vdev->vqs, list) - virtio_ccw_del_vq(vq, ccw); - - kfree(ccw); -} - -static struct virtqueue *virtio_ccw_setup_vq(struct virtio_device *vdev, - int i, vq_callback_t *callback, - const char *name, - struct ccw1 *ccw) -{ - struct virtio_ccw_device *vcdev = to_vc_device(vdev); - int err; - struct virtqueue *vq = NULL; - struct virtio_ccw_vq_info *info; - unsigned long size = 0; /* silence the compiler */ - unsigned long flags; - - /* Allocate queue. */ - info = kzalloc(sizeof(struct virtio_ccw_vq_info), GFP_KERNEL); - if (!info) { - dev_warn(&vcdev->cdev->dev, "no info\n"); - err = -ENOMEM; - goto out_err; - } - info->info_block = kzalloc(sizeof(*info->info_block), - GFP_DMA | GFP_KERNEL); - if (!info->info_block) { - dev_warn(&vcdev->cdev->dev, "no info block\n"); - err = -ENOMEM; - goto out_err; - } - info->num = virtio_ccw_read_vq_conf(vcdev, ccw, i); - size = PAGE_ALIGN(vring_size(info->num, KVM_VIRTIO_CCW_RING_ALIGN)); - info->queue = alloc_pages_exact(size, GFP_KERNEL | __GFP_ZERO); - if (info->queue == NULL) { - dev_warn(&vcdev->cdev->dev, "no queue\n"); - err = -ENOMEM; - goto out_err; - } - - vq = vring_new_virtqueue(i, info->num, KVM_VIRTIO_CCW_RING_ALIGN, vdev, - true, info->queue, virtio_ccw_kvm_notify, - callback, name); - if (!vq) { - /* For now, we fail if we can't get the requested size. */ - dev_warn(&vcdev->cdev->dev, "no vq\n"); - err = -ENOMEM; - goto out_err; - } - - /* Register it with the host. */ - if (vcdev->revision == 0) { - info->info_block->l.queue = (__u64)info->queue; - info->info_block->l.align = KVM_VIRTIO_CCW_RING_ALIGN; - info->info_block->l.index = i; - info->info_block->l.num = info->num; - ccw->count = sizeof(info->info_block->l); - } else { - info->info_block->s.desc = (__u64)info->queue; - info->info_block->s.index = i; - info->info_block->s.num = info->num; - info->info_block->s.avail = (__u64)virtqueue_get_avail(vq); - info->info_block->s.used = (__u64)virtqueue_get_used(vq); - ccw->count = sizeof(info->info_block->s); - } - ccw->cmd_code = CCW_CMD_SET_VQ; - ccw->flags = 0; - ccw->cda = (__u32)(unsigned long)(info->info_block); - err = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_SET_VQ | i); - if (err) { - dev_warn(&vcdev->cdev->dev, "SET_VQ failed\n"); - goto out_err; - } - - info->vq = vq; - vq->priv = info; - - /* Save it to our list. */ - spin_lock_irqsave(&vcdev->lock, flags); - list_add(&info->node, &vcdev->virtqueues); - spin_unlock_irqrestore(&vcdev->lock, flags); - - return vq; - -out_err: - if (vq) - vring_del_virtqueue(vq); - if (info) { - if (info->queue) - free_pages_exact(info->queue, size); - kfree(info->info_block); - } - kfree(info); - return ERR_PTR(err); -} - -static int virtio_ccw_register_adapter_ind(struct virtio_ccw_device *vcdev, - struct virtqueue *vqs[], int nvqs, - struct ccw1 *ccw) -{ - int ret; - struct virtio_thinint_area *thinint_area = NULL; - struct airq_info *info; - - thinint_area = kzalloc(sizeof(*thinint_area), GFP_DMA | GFP_KERNEL); - if (!thinint_area) { - ret = -ENOMEM; - goto out; - } - /* Try to get an indicator. */ - thinint_area->indicator = get_airq_indicator(vqs, nvqs, - &thinint_area->bit_nr, - &vcdev->airq_info); - if (!thinint_area->indicator) { - ret = -ENOSPC; - goto out; - } - info = vcdev->airq_info; - thinint_area->summary_indicator = - (unsigned long) &info->summary_indicator; - thinint_area->isc = VIRTIO_AIRQ_ISC; - ccw->cmd_code = CCW_CMD_SET_IND_ADAPTER; - ccw->flags = CCW_FLAG_SLI; - ccw->count = sizeof(*thinint_area); - ccw->cda = (__u32)(unsigned long)thinint_area; - ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_SET_IND_ADAPTER); - if (ret) { - if (ret == -EOPNOTSUPP) { - /* - * The host does not support adapter interrupts - * for virtio-ccw, stop trying. - */ - virtio_ccw_use_airq = 0; - pr_info("Adapter interrupts unsupported on host\n"); - } else - dev_warn(&vcdev->cdev->dev, - "enabling adapter interrupts = %d\n", ret); - virtio_ccw_drop_indicators(vcdev); - } -out: - kfree(thinint_area); - return ret; -} - -static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs, - struct virtqueue *vqs[], - vq_callback_t *callbacks[], - const char *names[]) -{ - struct virtio_ccw_device *vcdev = to_vc_device(vdev); - unsigned long *indicatorp = NULL; - int ret, i; - struct ccw1 *ccw; - - ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL); - if (!ccw) - return -ENOMEM; - - for (i = 0; i < nvqs; ++i) { - vqs[i] = virtio_ccw_setup_vq(vdev, i, callbacks[i], names[i], - ccw); - if (IS_ERR(vqs[i])) { - ret = PTR_ERR(vqs[i]); - vqs[i] = NULL; - goto out; - } - } - ret = -ENOMEM; - /* We need a data area under 2G to communicate. */ - indicatorp = kmalloc(sizeof(&vcdev->indicators), GFP_DMA | GFP_KERNEL); - if (!indicatorp) - goto out; - *indicatorp = (unsigned long) &vcdev->indicators; - if (vcdev->is_thinint) { - ret = virtio_ccw_register_adapter_ind(vcdev, vqs, nvqs, ccw); - if (ret) - /* no error, just fall back to legacy interrupts */ - vcdev->is_thinint = 0; - } - if (!vcdev->is_thinint) { - /* Register queue indicators with host. */ - vcdev->indicators = 0; - ccw->cmd_code = CCW_CMD_SET_IND; - ccw->flags = 0; - ccw->count = sizeof(vcdev->indicators); - ccw->cda = (__u32)(unsigned long) indicatorp; - ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_SET_IND); - if (ret) - goto out; - } - /* Register indicators2 with host for config changes */ - *indicatorp = (unsigned long) &vcdev->indicators2; - vcdev->indicators2 = 0; - ccw->cmd_code = CCW_CMD_SET_CONF_IND; - ccw->flags = 0; - ccw->count = sizeof(vcdev->indicators2); - ccw->cda = (__u32)(unsigned long) indicatorp; - ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_SET_CONF_IND); - if (ret) - goto out; - - kfree(indicatorp); - kfree(ccw); - return 0; -out: - kfree(indicatorp); - kfree(ccw); - virtio_ccw_del_vqs(vdev); - return ret; -} - -static void virtio_ccw_reset(struct virtio_device *vdev) -{ - struct virtio_ccw_device *vcdev = to_vc_device(vdev); - struct ccw1 *ccw; - - ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL); - if (!ccw) - return; - - /* Zero status bits. */ - *vcdev->status = 0; - - /* Send a reset ccw on device. */ - ccw->cmd_code = CCW_CMD_VDEV_RESET; - ccw->flags = 0; - ccw->count = 0; - ccw->cda = 0; - ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_RESET); - kfree(ccw); -} - -static u64 virtio_ccw_get_features(struct virtio_device *vdev) -{ - struct virtio_ccw_device *vcdev = to_vc_device(vdev); - struct virtio_feature_desc *features; - int ret; - u64 rc; - struct ccw1 *ccw; - - ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL); - if (!ccw) - return 0; - - features = kzalloc(sizeof(*features), GFP_DMA | GFP_KERNEL); - if (!features) { - rc = 0; - goto out_free; - } - /* Read the feature bits from the host. */ - features->index = 0; - ccw->cmd_code = CCW_CMD_READ_FEAT; - ccw->flags = 0; - ccw->count = sizeof(*features); - ccw->cda = (__u32)(unsigned long)features; - ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_READ_FEAT); - if (ret) { - rc = 0; - goto out_free; - } - - rc = le32_to_cpu(features->features); - - if (vcdev->revision == 0) - goto out_free; - - /* Read second half of the feature bits from the host. */ - features->index = 1; - ccw->cmd_code = CCW_CMD_READ_FEAT; - ccw->flags = 0; - ccw->count = sizeof(*features); - ccw->cda = (__u32)(unsigned long)features; - ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_READ_FEAT); - if (ret == 0) - rc |= (u64)le32_to_cpu(features->features) << 32; - -out_free: - kfree(features); - kfree(ccw); - return rc; -} - -static int virtio_ccw_finalize_features(struct virtio_device *vdev) -{ - struct virtio_ccw_device *vcdev = to_vc_device(vdev); - struct virtio_feature_desc *features; - struct ccw1 *ccw; - int ret; - - if (vcdev->revision >= 1 && - !__virtio_test_bit(vdev, VIRTIO_F_VERSION_1)) { - dev_err(&vdev->dev, "virtio: device uses revision 1 " - "but does not have VIRTIO_F_VERSION_1\n"); - return -EINVAL; - } - - ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL); - if (!ccw) - return -ENOMEM; - - features = kzalloc(sizeof(*features), GFP_DMA | GFP_KERNEL); - if (!features) { - ret = -ENOMEM; - goto out_free; - } - /* Give virtio_ring a chance to accept features. */ - vring_transport_features(vdev); - - features->index = 0; - features->features = cpu_to_le32((u32)vdev->features); - /* Write the first half of the feature bits to the host. */ - ccw->cmd_code = CCW_CMD_WRITE_FEAT; - ccw->flags = 0; - ccw->count = sizeof(*features); - ccw->cda = (__u32)(unsigned long)features; - ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_WRITE_FEAT); - if (ret) - goto out_free; - - if (vcdev->revision == 0) - goto out_free; - - features->index = 1; - features->features = cpu_to_le32(vdev->features >> 32); - /* Write the second half of the feature bits to the host. */ - ccw->cmd_code = CCW_CMD_WRITE_FEAT; - ccw->flags = 0; - ccw->count = sizeof(*features); - ccw->cda = (__u32)(unsigned long)features; - ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_WRITE_FEAT); - -out_free: - kfree(features); - kfree(ccw); - - return ret; -} - -static void virtio_ccw_get_config(struct virtio_device *vdev, - unsigned int offset, void *buf, unsigned len) -{ - struct virtio_ccw_device *vcdev = to_vc_device(vdev); - int ret; - struct ccw1 *ccw; - void *config_area; - - ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL); - if (!ccw) - return; - - config_area = kzalloc(VIRTIO_CCW_CONFIG_SIZE, GFP_DMA | GFP_KERNEL); - if (!config_area) - goto out_free; - - /* Read the config area from the host. */ - ccw->cmd_code = CCW_CMD_READ_CONF; - ccw->flags = 0; - ccw->count = offset + len; - ccw->cda = (__u32)(unsigned long)config_area; - ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_READ_CONFIG); - if (ret) - goto out_free; - - memcpy(vcdev->config, config_area, sizeof(vcdev->config)); - memcpy(buf, &vcdev->config[offset], len); - -out_free: - kfree(config_area); - kfree(ccw); -} - -static void virtio_ccw_set_config(struct virtio_device *vdev, - unsigned int offset, const void *buf, - unsigned len) -{ - struct virtio_ccw_device *vcdev = to_vc_device(vdev); - struct ccw1 *ccw; - void *config_area; - - ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL); - if (!ccw) - return; - - config_area = kzalloc(VIRTIO_CCW_CONFIG_SIZE, GFP_DMA | GFP_KERNEL); - if (!config_area) - goto out_free; - - memcpy(&vcdev->config[offset], buf, len); - /* Write the config area to the host. */ - memcpy(config_area, vcdev->config, sizeof(vcdev->config)); - ccw->cmd_code = CCW_CMD_WRITE_CONF; - ccw->flags = 0; - ccw->count = offset + len; - ccw->cda = (__u32)(unsigned long)config_area; - ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_WRITE_CONFIG); - -out_free: - kfree(config_area); - kfree(ccw); -} - -static u8 virtio_ccw_get_status(struct virtio_device *vdev) -{ - struct virtio_ccw_device *vcdev = to_vc_device(vdev); - - return *vcdev->status; -} - -static void virtio_ccw_set_status(struct virtio_device *vdev, u8 status) -{ - struct virtio_ccw_device *vcdev = to_vc_device(vdev); - u8 old_status = *vcdev->status; - struct ccw1 *ccw; - int ret; - - ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL); - if (!ccw) - return; - - /* Write the status to the host. */ - *vcdev->status = status; - ccw->cmd_code = CCW_CMD_WRITE_STATUS; - ccw->flags = 0; - ccw->count = sizeof(status); - ccw->cda = (__u32)(unsigned long)vcdev->status; - ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_WRITE_STATUS); - /* Write failed? We assume status is unchanged. */ - if (ret) - *vcdev->status = old_status; - kfree(ccw); -} - -static struct virtio_config_ops virtio_ccw_config_ops = { - .get_features = virtio_ccw_get_features, - .finalize_features = virtio_ccw_finalize_features, - .get = virtio_ccw_get_config, - .set = virtio_ccw_set_config, - .get_status = virtio_ccw_get_status, - .set_status = virtio_ccw_set_status, - .reset = virtio_ccw_reset, - .find_vqs = virtio_ccw_find_vqs, - .del_vqs = virtio_ccw_del_vqs, -}; - - -/* - * ccw bus driver related functions - */ - -static void virtio_ccw_release_dev(struct device *_d) -{ - struct virtio_device *dev = container_of(_d, struct virtio_device, - dev); - struct virtio_ccw_device *vcdev = to_vc_device(dev); - - kfree(vcdev->status); - kfree(vcdev->config_block); - kfree(vcdev); -} - -static int irb_is_error(struct irb *irb) -{ - if (scsw_cstat(&irb->scsw) != 0) - return 1; - if (scsw_dstat(&irb->scsw) & ~(DEV_STAT_CHN_END | DEV_STAT_DEV_END)) - return 1; - if (scsw_cc(&irb->scsw) != 0) - return 1; - return 0; -} - -static struct virtqueue *virtio_ccw_vq_by_ind(struct virtio_ccw_device *vcdev, - int index) -{ - struct virtio_ccw_vq_info *info; - unsigned long flags; - struct virtqueue *vq; - - vq = NULL; - spin_lock_irqsave(&vcdev->lock, flags); - list_for_each_entry(info, &vcdev->virtqueues, node) { - if (info->vq->index == index) { - vq = info->vq; - break; - } - } - spin_unlock_irqrestore(&vcdev->lock, flags); - return vq; -} - -static void virtio_ccw_int_handler(struct ccw_device *cdev, - unsigned long intparm, - struct irb *irb) -{ - __u32 activity = intparm & VIRTIO_CCW_INTPARM_MASK; - struct virtio_ccw_device *vcdev = dev_get_drvdata(&cdev->dev); - int i; - struct virtqueue *vq; - - if (!vcdev) - return; - /* Check if it's a notification from the host. */ - if ((intparm == 0) && - (scsw_stctl(&irb->scsw) == - (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND))) { - /* OK */ - } - if (irb_is_error(irb)) { - /* Command reject? */ - if ((scsw_dstat(&irb->scsw) & DEV_STAT_UNIT_CHECK) && - (irb->ecw[0] & SNS0_CMD_REJECT)) - vcdev->err = -EOPNOTSUPP; - else - /* Map everything else to -EIO. */ - vcdev->err = -EIO; - } - if (vcdev->curr_io & activity) { - switch (activity) { - case VIRTIO_CCW_DOING_READ_FEAT: - case VIRTIO_CCW_DOING_WRITE_FEAT: - case VIRTIO_CCW_DOING_READ_CONFIG: - case VIRTIO_CCW_DOING_WRITE_CONFIG: - case VIRTIO_CCW_DOING_WRITE_STATUS: - case VIRTIO_CCW_DOING_SET_VQ: - case VIRTIO_CCW_DOING_SET_IND: - case VIRTIO_CCW_DOING_SET_CONF_IND: - case VIRTIO_CCW_DOING_RESET: - case VIRTIO_CCW_DOING_READ_VQ_CONF: - case VIRTIO_CCW_DOING_SET_IND_ADAPTER: - case VIRTIO_CCW_DOING_SET_VIRTIO_REV: - vcdev->curr_io &= ~activity; - wake_up(&vcdev->wait_q); - break; - default: - /* don't know what to do... */ - dev_warn(&cdev->dev, "Suspicious activity '%08x'\n", - activity); - WARN_ON(1); - break; - } - } - for_each_set_bit(i, &vcdev->indicators, - sizeof(vcdev->indicators) * BITS_PER_BYTE) { - /* The bit clear must happen before the vring kick. */ - clear_bit(i, &vcdev->indicators); - barrier(); - vq = virtio_ccw_vq_by_ind(vcdev, i); - vring_interrupt(0, vq); - } - if (test_bit(0, &vcdev->indicators2)) { - virtio_config_changed(&vcdev->vdev); - clear_bit(0, &vcdev->indicators2); - } -} - -/* - * We usually want to autoonline all devices, but give the admin - * a way to exempt devices from this. - */ -#define __DEV_WORDS ((__MAX_SUBCHANNEL + (8*sizeof(long) - 1)) / \ - (8*sizeof(long))) -static unsigned long devs_no_auto[__MAX_SSID + 1][__DEV_WORDS]; - -static char *no_auto = ""; - -module_param(no_auto, charp, 0444); -MODULE_PARM_DESC(no_auto, "list of ccw bus id ranges not to be auto-onlined"); - -static int virtio_ccw_check_autoonline(struct ccw_device *cdev) -{ - struct ccw_dev_id id; - - ccw_device_get_id(cdev, &id); - if (test_bit(id.devno, devs_no_auto[id.ssid])) - return 0; - return 1; -} - -static void virtio_ccw_auto_online(void *data, async_cookie_t cookie) -{ - struct ccw_device *cdev = data; - int ret; - - ret = ccw_device_set_online(cdev); - if (ret) - dev_warn(&cdev->dev, "Failed to set online: %d\n", ret); -} - -static int virtio_ccw_probe(struct ccw_device *cdev) -{ - cdev->handler = virtio_ccw_int_handler; - - if (virtio_ccw_check_autoonline(cdev)) - async_schedule(virtio_ccw_auto_online, cdev); - return 0; -} - -static struct virtio_ccw_device *virtio_grab_drvdata(struct ccw_device *cdev) -{ - unsigned long flags; - struct virtio_ccw_device *vcdev; - - spin_lock_irqsave(get_ccwdev_lock(cdev), flags); - vcdev = dev_get_drvdata(&cdev->dev); - if (!vcdev || vcdev->going_away) { - spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); - return NULL; - } - vcdev->going_away = true; - spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); - return vcdev; -} - -static void virtio_ccw_remove(struct ccw_device *cdev) -{ - unsigned long flags; - struct virtio_ccw_device *vcdev = virtio_grab_drvdata(cdev); - - if (vcdev && cdev->online) { - if (vcdev->device_lost) - virtio_break_device(&vcdev->vdev); - unregister_virtio_device(&vcdev->vdev); - spin_lock_irqsave(get_ccwdev_lock(cdev), flags); - dev_set_drvdata(&cdev->dev, NULL); - spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); - } - cdev->handler = NULL; -} - -static int virtio_ccw_offline(struct ccw_device *cdev) -{ - unsigned long flags; - struct virtio_ccw_device *vcdev = virtio_grab_drvdata(cdev); - - if (!vcdev) - return 0; - if (vcdev->device_lost) - virtio_break_device(&vcdev->vdev); - unregister_virtio_device(&vcdev->vdev); - spin_lock_irqsave(get_ccwdev_lock(cdev), flags); - dev_set_drvdata(&cdev->dev, NULL); - spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); - return 0; -} - -static int virtio_ccw_set_transport_rev(struct virtio_ccw_device *vcdev) -{ - struct virtio_rev_info *rev; - struct ccw1 *ccw; - int ret; - - ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL); - if (!ccw) - return -ENOMEM; - rev = kzalloc(sizeof(*rev), GFP_DMA | GFP_KERNEL); - if (!rev) { - kfree(ccw); - return -ENOMEM; - } - - /* Set transport revision */ - ccw->cmd_code = CCW_CMD_SET_VIRTIO_REV; - ccw->flags = 0; - ccw->count = sizeof(*rev); - ccw->cda = (__u32)(unsigned long)rev; - - vcdev->revision = VIRTIO_CCW_REV_MAX; - do { - rev->revision = vcdev->revision; - /* none of our supported revisions carry payload */ - rev->length = 0; - ret = ccw_io_helper(vcdev, ccw, - VIRTIO_CCW_DOING_SET_VIRTIO_REV); - if (ret == -EOPNOTSUPP) { - if (vcdev->revision == 0) - /* - * The host device does not support setting - * the revision: let's operate it in legacy - * mode. - */ - ret = 0; - else - vcdev->revision--; - } - } while (ret == -EOPNOTSUPP); - - kfree(ccw); - kfree(rev); - return ret; -} - -static int virtio_ccw_online(struct ccw_device *cdev) -{ - int ret; - struct virtio_ccw_device *vcdev; - unsigned long flags; - - vcdev = kzalloc(sizeof(*vcdev), GFP_KERNEL); - if (!vcdev) { - dev_warn(&cdev->dev, "Could not get memory for virtio\n"); - ret = -ENOMEM; - goto out_free; - } - vcdev->config_block = kzalloc(sizeof(*vcdev->config_block), - GFP_DMA | GFP_KERNEL); - if (!vcdev->config_block) { - ret = -ENOMEM; - goto out_free; - } - vcdev->status = kzalloc(sizeof(*vcdev->status), GFP_DMA | GFP_KERNEL); - if (!vcdev->status) { - ret = -ENOMEM; - goto out_free; - } - - vcdev->is_thinint = virtio_ccw_use_airq; /* at least try */ - - vcdev->vdev.dev.parent = &cdev->dev; - vcdev->vdev.dev.release = virtio_ccw_release_dev; - vcdev->vdev.config = &virtio_ccw_config_ops; - vcdev->cdev = cdev; - init_waitqueue_head(&vcdev->wait_q); - INIT_LIST_HEAD(&vcdev->virtqueues); - spin_lock_init(&vcdev->lock); - - spin_lock_irqsave(get_ccwdev_lock(cdev), flags); - dev_set_drvdata(&cdev->dev, vcdev); - spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); - vcdev->vdev.id.vendor = cdev->id.cu_type; - vcdev->vdev.id.device = cdev->id.cu_model; - - ret = virtio_ccw_set_transport_rev(vcdev); - if (ret) - goto out_free; - - ret = register_virtio_device(&vcdev->vdev); - if (ret) { - dev_warn(&cdev->dev, "Failed to register virtio device: %d\n", - ret); - goto out_put; - } - return 0; -out_put: - spin_lock_irqsave(get_ccwdev_lock(cdev), flags); - dev_set_drvdata(&cdev->dev, NULL); - spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); - put_device(&vcdev->vdev.dev); - return ret; -out_free: - if (vcdev) { - kfree(vcdev->status); - kfree(vcdev->config_block); - } - kfree(vcdev); - return ret; -} - -static int virtio_ccw_cio_notify(struct ccw_device *cdev, int event) -{ - int rc; - struct virtio_ccw_device *vcdev = dev_get_drvdata(&cdev->dev); - - /* - * Make sure vcdev is set - * i.e. set_offline/remove callback not already running - */ - if (!vcdev) - return NOTIFY_DONE; - - switch (event) { - case CIO_GONE: - vcdev->device_lost = true; - rc = NOTIFY_DONE; - break; - default: - rc = NOTIFY_DONE; - break; - } - return rc; -} - -static struct ccw_device_id virtio_ids[] = { - { CCW_DEVICE(0x3832, 0) }, - {}, -}; -MODULE_DEVICE_TABLE(ccw, virtio_ids); - -static struct ccw_driver virtio_ccw_driver = { - .driver = { - .owner = THIS_MODULE, - .name = "virtio_ccw", - }, - .ids = virtio_ids, - .probe = virtio_ccw_probe, - .remove = virtio_ccw_remove, - .set_offline = virtio_ccw_offline, - .set_online = virtio_ccw_online, - .notify = virtio_ccw_cio_notify, - .int_class = IRQIO_VIR, -}; - -static int __init pure_hex(char **cp, unsigned int *val, int min_digit, - int max_digit, int max_val) -{ - int diff; - - diff = 0; - *val = 0; - - while (diff <= max_digit) { - int value = hex_to_bin(**cp); - - if (value < 0) - break; - *val = *val * 16 + value; - (*cp)++; - diff++; - } - - if ((diff < min_digit) || (diff > max_digit) || (*val > max_val)) - return 1; - - return 0; -} - -static int __init parse_busid(char *str, unsigned int *cssid, - unsigned int *ssid, unsigned int *devno) -{ - char *str_work; - int rc, ret; - - rc = 1; - - if (*str == '\0') - goto out; - - str_work = str; - ret = pure_hex(&str_work, cssid, 1, 2, __MAX_CSSID); - if (ret || (str_work[0] != '.')) - goto out; - str_work++; - ret = pure_hex(&str_work, ssid, 1, 1, __MAX_SSID); - if (ret || (str_work[0] != '.')) - goto out; - str_work++; - ret = pure_hex(&str_work, devno, 4, 4, __MAX_SUBCHANNEL); - if (ret || (str_work[0] != '\0')) - goto out; - - rc = 0; -out: - return rc; -} - -static void __init no_auto_parse(void) -{ - unsigned int from_cssid, to_cssid, from_ssid, to_ssid, from, to; - char *parm, *str; - int rc; - - str = no_auto; - while ((parm = strsep(&str, ","))) { - rc = parse_busid(strsep(&parm, "-"), &from_cssid, - &from_ssid, &from); - if (rc) - continue; - if (parm != NULL) { - rc = parse_busid(parm, &to_cssid, - &to_ssid, &to); - if ((from_ssid > to_ssid) || - ((from_ssid == to_ssid) && (from > to))) - rc = -EINVAL; - } else { - to_cssid = from_cssid; - to_ssid = from_ssid; - to = from; - } - if (rc) - continue; - while ((from_ssid < to_ssid) || - ((from_ssid == to_ssid) && (from <= to))) { - set_bit(from, devs_no_auto[from_ssid]); - from++; - if (from > __MAX_SUBCHANNEL) { - from_ssid++; - from = 0; - } - } - } -} - -static int __init virtio_ccw_init(void) -{ - /* parse no_auto string before we do anything further */ - no_auto_parse(); - return ccw_driver_register(&virtio_ccw_driver); -} -module_init(virtio_ccw_init); - -static void __exit virtio_ccw_exit(void) -{ - int i; - - ccw_driver_unregister(&virtio_ccw_driver); - for (i = 0; i < MAX_AIRQ_AREAS; i++) - destroy_airq_info(airq_areas[i]); -} -module_exit(virtio_ccw_exit); diff --git a/drivers/s390/virtio/Makefile b/drivers/s390/virtio/Makefile new file mode 100644 index 000000000000..241891a57caf --- /dev/null +++ b/drivers/s390/virtio/Makefile @@ -0,0 +1,9 @@ +# Makefile for kvm guest drivers on s390 +# +# Copyright IBM Corp. 2008 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License (version 2 only) +# as published by the Free Software Foundation. + +obj-$(CONFIG_S390_GUEST) += kvm_virtio.o virtio_ccw.o diff --git a/drivers/s390/virtio/kvm_virtio.c b/drivers/s390/virtio/kvm_virtio.c new file mode 100644 index 000000000000..dd65c8b4c7fe --- /dev/null +++ b/drivers/s390/virtio/kvm_virtio.c @@ -0,0 +1,510 @@ +/* + * virtio for kvm on s390 + * + * Copyright IBM Corp. 2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (version 2 only) + * as published by the Free Software Foundation. + * + * Author(s): Christian Borntraeger + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define VIRTIO_SUBCODE_64 0x0D00 + +/* + * The pointer to our (page) of device descriptions. + */ +static void *kvm_devices; +static struct work_struct hotplug_work; + +struct kvm_device { + struct virtio_device vdev; + struct kvm_device_desc *desc; +}; + +#define to_kvmdev(vd) container_of(vd, struct kvm_device, vdev) + +/* + * memory layout: + * - kvm_device_descriptor + * struct kvm_device_desc + * - configuration + * struct kvm_vqconfig + * - feature bits + * - config space + */ +static struct kvm_vqconfig *kvm_vq_config(const struct kvm_device_desc *desc) +{ + return (struct kvm_vqconfig *)(desc + 1); +} + +static u8 *kvm_vq_features(const struct kvm_device_desc *desc) +{ + return (u8 *)(kvm_vq_config(desc) + desc->num_vq); +} + +static u8 *kvm_vq_configspace(const struct kvm_device_desc *desc) +{ + return kvm_vq_features(desc) + desc->feature_len * 2; +} + +/* + * The total size of the config page used by this device (incl. desc) + */ +static unsigned desc_size(const struct kvm_device_desc *desc) +{ + return sizeof(*desc) + + desc->num_vq * sizeof(struct kvm_vqconfig) + + desc->feature_len * 2 + + desc->config_len; +} + +/* This gets the device's feature bits. */ +static u64 kvm_get_features(struct virtio_device *vdev) +{ + unsigned int i; + u32 features = 0; + struct kvm_device_desc *desc = to_kvmdev(vdev)->desc; + u8 *in_features = kvm_vq_features(desc); + + for (i = 0; i < min(desc->feature_len * 8, 32); i++) + if (in_features[i / 8] & (1 << (i % 8))) + features |= (1 << i); + return features; +} + +static int kvm_finalize_features(struct virtio_device *vdev) +{ + unsigned int i, bits; + struct kvm_device_desc *desc = to_kvmdev(vdev)->desc; + /* Second half of bitmap is features we accept. */ + u8 *out_features = kvm_vq_features(desc) + desc->feature_len; + + /* Give virtio_ring a chance to accept features. */ + vring_transport_features(vdev); + + /* Make sure we don't have any features > 32 bits! */ + BUG_ON((u32)vdev->features != vdev->features); + + memset(out_features, 0, desc->feature_len); + bits = min_t(unsigned, desc->feature_len, sizeof(vdev->features)) * 8; + for (i = 0; i < bits; i++) { + if (__virtio_test_bit(vdev, i)) + out_features[i / 8] |= (1 << (i % 8)); + } + + return 0; +} + +/* + * Reading and writing elements in config space + */ +static void kvm_get(struct virtio_device *vdev, unsigned int offset, + void *buf, unsigned len) +{ + struct kvm_device_desc *desc = to_kvmdev(vdev)->desc; + + BUG_ON(offset + len > desc->config_len); + memcpy(buf, kvm_vq_configspace(desc) + offset, len); +} + +static void kvm_set(struct virtio_device *vdev, unsigned int offset, + const void *buf, unsigned len) +{ + struct kvm_device_desc *desc = to_kvmdev(vdev)->desc; + + BUG_ON(offset + len > desc->config_len); + memcpy(kvm_vq_configspace(desc) + offset, buf, len); +} + +/* + * The operations to get and set the status word just access + * the status field of the device descriptor. set_status will also + * make a hypercall to the host, to tell about status changes + */ +static u8 kvm_get_status(struct virtio_device *vdev) +{ + return to_kvmdev(vdev)->desc->status; +} + +static void kvm_set_status(struct virtio_device *vdev, u8 status) +{ + BUG_ON(!status); + to_kvmdev(vdev)->desc->status = status; + kvm_hypercall1(KVM_S390_VIRTIO_SET_STATUS, + (unsigned long) to_kvmdev(vdev)->desc); +} + +/* + * To reset the device, we use the KVM_VIRTIO_RESET hypercall, using the + * descriptor address. The Host will zero the status and all the + * features. + */ +static void kvm_reset(struct virtio_device *vdev) +{ + kvm_hypercall1(KVM_S390_VIRTIO_RESET, + (unsigned long) to_kvmdev(vdev)->desc); +} + +/* + * When the virtio_ring code wants to notify the Host, it calls us here and we + * make a hypercall. We hand the address of the virtqueue so the Host + * knows which virtqueue we're talking about. + */ +static bool kvm_notify(struct virtqueue *vq) +{ + long rc; + struct kvm_vqconfig *config = vq->priv; + + rc = kvm_hypercall1(KVM_S390_VIRTIO_NOTIFY, config->address); + if (rc < 0) + return false; + return true; +} + +/* + * This routine finds the first virtqueue described in the configuration of + * this device and sets it up. + */ +static struct virtqueue *kvm_find_vq(struct virtio_device *vdev, + unsigned index, + void (*callback)(struct virtqueue *vq), + const char *name) +{ + struct kvm_device *kdev = to_kvmdev(vdev); + struct kvm_vqconfig *config; + struct virtqueue *vq; + int err; + + if (index >= kdev->desc->num_vq) + return ERR_PTR(-ENOENT); + + if (!name) + return NULL; + + config = kvm_vq_config(kdev->desc)+index; + + err = vmem_add_mapping(config->address, + vring_size(config->num, + KVM_S390_VIRTIO_RING_ALIGN)); + if (err) + goto out; + + vq = vring_new_virtqueue(index, config->num, KVM_S390_VIRTIO_RING_ALIGN, + vdev, true, (void *) config->address, + kvm_notify, callback, name); + if (!vq) { + err = -ENOMEM; + goto unmap; + } + + /* + * register a callback token + * The host will sent this via the external interrupt parameter + */ + config->token = (u64) vq; + + vq->priv = config; + return vq; +unmap: + vmem_remove_mapping(config->address, + vring_size(config->num, + KVM_S390_VIRTIO_RING_ALIGN)); +out: + return ERR_PTR(err); +} + +static void kvm_del_vq(struct virtqueue *vq) +{ + struct kvm_vqconfig *config = vq->priv; + + vring_del_virtqueue(vq); + vmem_remove_mapping(config->address, + vring_size(config->num, + KVM_S390_VIRTIO_RING_ALIGN)); +} + +static void kvm_del_vqs(struct virtio_device *vdev) +{ + struct virtqueue *vq, *n; + + list_for_each_entry_safe(vq, n, &vdev->vqs, list) + kvm_del_vq(vq); +} + +static int kvm_find_vqs(struct virtio_device *vdev, unsigned nvqs, + struct virtqueue *vqs[], + vq_callback_t *callbacks[], + const char *names[]) +{ + struct kvm_device *kdev = to_kvmdev(vdev); + int i; + + /* We must have this many virtqueues. */ + if (nvqs > kdev->desc->num_vq) + return -ENOENT; + + for (i = 0; i < nvqs; ++i) { + vqs[i] = kvm_find_vq(vdev, i, callbacks[i], names[i]); + if (IS_ERR(vqs[i])) + goto error; + } + return 0; + +error: + kvm_del_vqs(vdev); + return PTR_ERR(vqs[i]); +} + +static const char *kvm_bus_name(struct virtio_device *vdev) +{ + return ""; +} + +/* + * The config ops structure as defined by virtio config + */ +static const struct virtio_config_ops kvm_vq_configspace_ops = { + .get_features = kvm_get_features, + .finalize_features = kvm_finalize_features, + .get = kvm_get, + .set = kvm_set, + .get_status = kvm_get_status, + .set_status = kvm_set_status, + .reset = kvm_reset, + .find_vqs = kvm_find_vqs, + .del_vqs = kvm_del_vqs, + .bus_name = kvm_bus_name, +}; + +/* + * The root device for the kvm virtio devices. + * This makes them appear as /sys/devices/kvm_s390/0,1,2 not /sys/devices/0,1,2. + */ +static struct device *kvm_root; + +/* + * adds a new device and register it with virtio + * appropriate drivers are loaded by the device model + */ +static void add_kvm_device(struct kvm_device_desc *d, unsigned int offset) +{ + struct kvm_device *kdev; + + kdev = kzalloc(sizeof(*kdev), GFP_KERNEL); + if (!kdev) { + printk(KERN_EMERG "Cannot allocate kvm dev %u type %u\n", + offset, d->type); + return; + } + + kdev->vdev.dev.parent = kvm_root; + kdev->vdev.id.device = d->type; + kdev->vdev.config = &kvm_vq_configspace_ops; + kdev->desc = d; + + if (register_virtio_device(&kdev->vdev) != 0) { + printk(KERN_ERR "Failed to register kvm device %u type %u\n", + offset, d->type); + kfree(kdev); + } +} + +/* + * scan_devices() simply iterates through the device page. + * The type 0 is reserved to mean "end of devices". + */ +static void scan_devices(void) +{ + unsigned int i; + struct kvm_device_desc *d; + + for (i = 0; i < PAGE_SIZE; i += desc_size(d)) { + d = kvm_devices + i; + + if (d->type == 0) + break; + + add_kvm_device(d, i); + } +} + +/* + * match for a kvm device with a specific desc pointer + */ +static int match_desc(struct device *dev, void *data) +{ + struct virtio_device *vdev = dev_to_virtio(dev); + struct kvm_device *kdev = to_kvmdev(vdev); + + return kdev->desc == data; +} + +/* + * hotplug_device tries to find changes in the device page. + */ +static void hotplug_devices(struct work_struct *dummy) +{ + unsigned int i; + struct kvm_device_desc *d; + struct device *dev; + + for (i = 0; i < PAGE_SIZE; i += desc_size(d)) { + d = kvm_devices + i; + + /* end of list */ + if (d->type == 0) + break; + + /* device already exists */ + dev = device_find_child(kvm_root, d, match_desc); + if (dev) { + /* XXX check for hotplug remove */ + put_device(dev); + continue; + } + + /* new device */ + printk(KERN_INFO "Adding new virtio device %p\n", d); + add_kvm_device(d, i); + } +} + +/* + * we emulate the request_irq behaviour on top of s390 extints + */ +static void kvm_extint_handler(struct ext_code ext_code, + unsigned int param32, unsigned long param64) +{ + struct virtqueue *vq; + u32 param; + + if ((ext_code.subcode & 0xff00) != VIRTIO_SUBCODE_64) + return; + inc_irq_stat(IRQEXT_VRT); + + /* The LSB might be overloaded, we have to mask it */ + vq = (struct virtqueue *)(param64 & ~1UL); + + /* We use ext_params to decide what this interrupt means */ + param = param32 & VIRTIO_PARAM_MASK; + + switch (param) { + case VIRTIO_PARAM_CONFIG_CHANGED: + virtio_config_changed(vq->vdev); + break; + case VIRTIO_PARAM_DEV_ADD: + schedule_work(&hotplug_work); + break; + case VIRTIO_PARAM_VRING_INTERRUPT: + default: + vring_interrupt(0, vq); + break; + } +} + +/* + * For s390-virtio, we expect a page above main storage containing + * the virtio configuration. Try to actually load from this area + * in order to figure out if the host provides this page. + */ +static int __init test_devices_support(unsigned long addr) +{ + int ret = -EIO; + + asm volatile( + "0: lura 0,%1\n" + "1: xgr %0,%0\n" + "2:\n" + EX_TABLE(0b,2b) + EX_TABLE(1b,2b) + : "+d" (ret) + : "a" (addr) + : "0", "cc"); + return ret; +} +/* + * Init function for virtio + * devices are in a single page above top of "normal" + standby mem + */ +static int __init kvm_devices_init(void) +{ + int rc; + unsigned long total_memory_size = sclp_get_rzm() * sclp_get_rnmax(); + + if (!MACHINE_IS_KVM) + return -ENODEV; + + if (test_devices_support(total_memory_size) < 0) + return -ENODEV; + + rc = vmem_add_mapping(total_memory_size, PAGE_SIZE); + if (rc) + return rc; + + kvm_devices = (void *) total_memory_size; + + kvm_root = root_device_register("kvm_s390"); + if (IS_ERR(kvm_root)) { + rc = PTR_ERR(kvm_root); + printk(KERN_ERR "Could not register kvm_s390 root device"); + vmem_remove_mapping(total_memory_size, PAGE_SIZE); + return rc; + } + + INIT_WORK(&hotplug_work, hotplug_devices); + + irq_subclass_register(IRQ_SUBCLASS_SERVICE_SIGNAL); + register_external_irq(EXT_IRQ_CP_SERVICE, kvm_extint_handler); + + scan_devices(); + return 0; +} + +/* code for early console output with virtio_console */ +static __init int early_put_chars(u32 vtermno, const char *buf, int count) +{ + char scratch[17]; + unsigned int len = count; + + if (len > sizeof(scratch) - 1) + len = sizeof(scratch) - 1; + scratch[len] = '\0'; + memcpy(scratch, buf, len); + kvm_hypercall1(KVM_S390_VIRTIO_NOTIFY, __pa(scratch)); + return len; +} + +static int __init s390_virtio_console_init(void) +{ + if (sclp_has_vt220() || sclp_has_linemode()) + return -ENODEV; + return virtio_cons_early_init(early_put_chars); +} +console_initcall(s390_virtio_console_init); + + +/* + * We do this after core stuff, but before the drivers. + */ +postcore_initcall(kvm_devices_init); diff --git a/drivers/s390/virtio/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c new file mode 100644 index 000000000000..6f1fa1773e76 --- /dev/null +++ b/drivers/s390/virtio/virtio_ccw.c @@ -0,0 +1,1380 @@ +/* + * ccw based virtio transport + * + * Copyright IBM Corp. 2012, 2014 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (version 2 only) + * as published by the Free Software Foundation. + * + * Author(s): Cornelia Huck + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * virtio related functions + */ + +struct vq_config_block { + __u16 index; + __u16 num; +} __packed; + +#define VIRTIO_CCW_CONFIG_SIZE 0x100 +/* same as PCI config space size, should be enough for all drivers */ + +struct virtio_ccw_device { + struct virtio_device vdev; + __u8 *status; + __u8 config[VIRTIO_CCW_CONFIG_SIZE]; + struct ccw_device *cdev; + __u32 curr_io; + int err; + unsigned int revision; /* Transport revision */ + wait_queue_head_t wait_q; + spinlock_t lock; + struct list_head virtqueues; + unsigned long indicators; + unsigned long indicators2; + struct vq_config_block *config_block; + bool is_thinint; + bool going_away; + bool device_lost; + void *airq_info; +}; + +struct vq_info_block_legacy { + __u64 queue; + __u32 align; + __u16 index; + __u16 num; +} __packed; + +struct vq_info_block { + __u64 desc; + __u32 res0; + __u16 index; + __u16 num; + __u64 avail; + __u64 used; +} __packed; + +struct virtio_feature_desc { + __u32 features; + __u8 index; +} __packed; + +struct virtio_thinint_area { + unsigned long summary_indicator; + unsigned long indicator; + u64 bit_nr; + u8 isc; +} __packed; + +struct virtio_rev_info { + __u16 revision; + __u16 length; + __u8 data[]; +}; + +/* the highest virtio-ccw revision we support */ +#define VIRTIO_CCW_REV_MAX 1 + +struct virtio_ccw_vq_info { + struct virtqueue *vq; + int num; + void *queue; + union { + struct vq_info_block s; + struct vq_info_block_legacy l; + } *info_block; + int bit_nr; + struct list_head node; + long cookie; +}; + +#define VIRTIO_AIRQ_ISC IO_SCH_ISC /* inherit from subchannel */ + +#define VIRTIO_IV_BITS (L1_CACHE_BYTES * 8) +#define MAX_AIRQ_AREAS 20 + +static int virtio_ccw_use_airq = 1; + +struct airq_info { + rwlock_t lock; + u8 summary_indicator; + struct airq_struct airq; + struct airq_iv *aiv; +}; +static struct airq_info *airq_areas[MAX_AIRQ_AREAS]; + +#define CCW_CMD_SET_VQ 0x13 +#define CCW_CMD_VDEV_RESET 0x33 +#define CCW_CMD_SET_IND 0x43 +#define CCW_CMD_SET_CONF_IND 0x53 +#define CCW_CMD_READ_FEAT 0x12 +#define CCW_CMD_WRITE_FEAT 0x11 +#define CCW_CMD_READ_CONF 0x22 +#define CCW_CMD_WRITE_CONF 0x21 +#define CCW_CMD_WRITE_STATUS 0x31 +#define CCW_CMD_READ_VQ_CONF 0x32 +#define CCW_CMD_SET_IND_ADAPTER 0x73 +#define CCW_CMD_SET_VIRTIO_REV 0x83 + +#define VIRTIO_CCW_DOING_SET_VQ 0x00010000 +#define VIRTIO_CCW_DOING_RESET 0x00040000 +#define VIRTIO_CCW_DOING_READ_FEAT 0x00080000 +#define VIRTIO_CCW_DOING_WRITE_FEAT 0x00100000 +#define VIRTIO_CCW_DOING_READ_CONFIG 0x00200000 +#define VIRTIO_CCW_DOING_WRITE_CONFIG 0x00400000 +#define VIRTIO_CCW_DOING_WRITE_STATUS 0x00800000 +#define VIRTIO_CCW_DOING_SET_IND 0x01000000 +#define VIRTIO_CCW_DOING_READ_VQ_CONF 0x02000000 +#define VIRTIO_CCW_DOING_SET_CONF_IND 0x04000000 +#define VIRTIO_CCW_DOING_SET_IND_ADAPTER 0x08000000 +#define VIRTIO_CCW_DOING_SET_VIRTIO_REV 0x10000000 +#define VIRTIO_CCW_INTPARM_MASK 0xffff0000 + +static struct virtio_ccw_device *to_vc_device(struct virtio_device *vdev) +{ + return container_of(vdev, struct virtio_ccw_device, vdev); +} + +static void drop_airq_indicator(struct virtqueue *vq, struct airq_info *info) +{ + unsigned long i, flags; + + write_lock_irqsave(&info->lock, flags); + for (i = 0; i < airq_iv_end(info->aiv); i++) { + if (vq == (void *)airq_iv_get_ptr(info->aiv, i)) { + airq_iv_free_bit(info->aiv, i); + airq_iv_set_ptr(info->aiv, i, 0); + break; + } + } + write_unlock_irqrestore(&info->lock, flags); +} + +static void virtio_airq_handler(struct airq_struct *airq) +{ + struct airq_info *info = container_of(airq, struct airq_info, airq); + unsigned long ai; + + inc_irq_stat(IRQIO_VAI); + read_lock(&info->lock); + /* Walk through indicators field, summary indicator active. */ + for (ai = 0;;) { + ai = airq_iv_scan(info->aiv, ai, airq_iv_end(info->aiv)); + if (ai == -1UL) + break; + vring_interrupt(0, (void *)airq_iv_get_ptr(info->aiv, ai)); + } + info->summary_indicator = 0; + smp_wmb(); + /* Walk through indicators field, summary indicator not active. */ + for (ai = 0;;) { + ai = airq_iv_scan(info->aiv, ai, airq_iv_end(info->aiv)); + if (ai == -1UL) + break; + vring_interrupt(0, (void *)airq_iv_get_ptr(info->aiv, ai)); + } + read_unlock(&info->lock); +} + +static struct airq_info *new_airq_info(void) +{ + struct airq_info *info; + int rc; + + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) + return NULL; + rwlock_init(&info->lock); + info->aiv = airq_iv_create(VIRTIO_IV_BITS, AIRQ_IV_ALLOC | AIRQ_IV_PTR); + if (!info->aiv) { + kfree(info); + return NULL; + } + info->airq.handler = virtio_airq_handler; + info->airq.lsi_ptr = &info->summary_indicator; + info->airq.lsi_mask = 0xff; + info->airq.isc = VIRTIO_AIRQ_ISC; + rc = register_adapter_interrupt(&info->airq); + if (rc) { + airq_iv_release(info->aiv); + kfree(info); + return NULL; + } + return info; +} + +static void destroy_airq_info(struct airq_info *info) +{ + if (!info) + return; + + unregister_adapter_interrupt(&info->airq); + airq_iv_release(info->aiv); + kfree(info); +} + +static unsigned long get_airq_indicator(struct virtqueue *vqs[], int nvqs, + u64 *first, void **airq_info) +{ + int i, j; + struct airq_info *info; + unsigned long indicator_addr = 0; + unsigned long bit, flags; + + for (i = 0; i < MAX_AIRQ_AREAS && !indicator_addr; i++) { + if (!airq_areas[i]) + airq_areas[i] = new_airq_info(); + info = airq_areas[i]; + if (!info) + return 0; + write_lock_irqsave(&info->lock, flags); + bit = airq_iv_alloc(info->aiv, nvqs); + if (bit == -1UL) { + /* Not enough vacancies. */ + write_unlock_irqrestore(&info->lock, flags); + continue; + } + *first = bit; + *airq_info = info; + indicator_addr = (unsigned long)info->aiv->vector; + for (j = 0; j < nvqs; j++) { + airq_iv_set_ptr(info->aiv, bit + j, + (unsigned long)vqs[j]); + } + write_unlock_irqrestore(&info->lock, flags); + } + return indicator_addr; +} + +static void virtio_ccw_drop_indicators(struct virtio_ccw_device *vcdev) +{ + struct virtio_ccw_vq_info *info; + + list_for_each_entry(info, &vcdev->virtqueues, node) + drop_airq_indicator(info->vq, vcdev->airq_info); +} + +static int doing_io(struct virtio_ccw_device *vcdev, __u32 flag) +{ + unsigned long flags; + __u32 ret; + + spin_lock_irqsave(get_ccwdev_lock(vcdev->cdev), flags); + if (vcdev->err) + ret = 0; + else + ret = vcdev->curr_io & flag; + spin_unlock_irqrestore(get_ccwdev_lock(vcdev->cdev), flags); + return ret; +} + +static int ccw_io_helper(struct virtio_ccw_device *vcdev, + struct ccw1 *ccw, __u32 intparm) +{ + int ret; + unsigned long flags; + int flag = intparm & VIRTIO_CCW_INTPARM_MASK; + + do { + spin_lock_irqsave(get_ccwdev_lock(vcdev->cdev), flags); + ret = ccw_device_start(vcdev->cdev, ccw, intparm, 0, 0); + if (!ret) { + if (!vcdev->curr_io) + vcdev->err = 0; + vcdev->curr_io |= flag; + } + spin_unlock_irqrestore(get_ccwdev_lock(vcdev->cdev), flags); + cpu_relax(); + } while (ret == -EBUSY); + wait_event(vcdev->wait_q, doing_io(vcdev, flag) == 0); + return ret ? ret : vcdev->err; +} + +static void virtio_ccw_drop_indicator(struct virtio_ccw_device *vcdev, + struct ccw1 *ccw) +{ + int ret; + unsigned long *indicatorp = NULL; + struct virtio_thinint_area *thinint_area = NULL; + struct airq_info *airq_info = vcdev->airq_info; + + if (vcdev->is_thinint) { + thinint_area = kzalloc(sizeof(*thinint_area), + GFP_DMA | GFP_KERNEL); + if (!thinint_area) + return; + thinint_area->summary_indicator = + (unsigned long) &airq_info->summary_indicator; + thinint_area->isc = VIRTIO_AIRQ_ISC; + ccw->cmd_code = CCW_CMD_SET_IND_ADAPTER; + ccw->count = sizeof(*thinint_area); + ccw->cda = (__u32)(unsigned long) thinint_area; + } else { + indicatorp = kmalloc(sizeof(&vcdev->indicators), + GFP_DMA | GFP_KERNEL); + if (!indicatorp) + return; + *indicatorp = 0; + ccw->cmd_code = CCW_CMD_SET_IND; + ccw->count = sizeof(vcdev->indicators); + ccw->cda = (__u32)(unsigned long) indicatorp; + } + /* Deregister indicators from host. */ + vcdev->indicators = 0; + ccw->flags = 0; + ret = ccw_io_helper(vcdev, ccw, + vcdev->is_thinint ? + VIRTIO_CCW_DOING_SET_IND_ADAPTER : + VIRTIO_CCW_DOING_SET_IND); + if (ret && (ret != -ENODEV)) + dev_info(&vcdev->cdev->dev, + "Failed to deregister indicators (%d)\n", ret); + else if (vcdev->is_thinint) + virtio_ccw_drop_indicators(vcdev); + kfree(indicatorp); + kfree(thinint_area); +} + +static inline long do_kvm_notify(struct subchannel_id schid, + unsigned long queue_index, + long cookie) +{ + register unsigned long __nr asm("1") = KVM_S390_VIRTIO_CCW_NOTIFY; + register struct subchannel_id __schid asm("2") = schid; + register unsigned long __index asm("3") = queue_index; + register long __rc asm("2"); + register long __cookie asm("4") = cookie; + + asm volatile ("diag 2,4,0x500\n" + : "=d" (__rc) : "d" (__nr), "d" (__schid), "d" (__index), + "d"(__cookie) + : "memory", "cc"); + return __rc; +} + +static bool virtio_ccw_kvm_notify(struct virtqueue *vq) +{ + struct virtio_ccw_vq_info *info = vq->priv; + struct virtio_ccw_device *vcdev; + struct subchannel_id schid; + + vcdev = to_vc_device(info->vq->vdev); + ccw_device_get_schid(vcdev->cdev, &schid); + info->cookie = do_kvm_notify(schid, vq->index, info->cookie); + if (info->cookie < 0) + return false; + return true; +} + +static int virtio_ccw_read_vq_conf(struct virtio_ccw_device *vcdev, + struct ccw1 *ccw, int index) +{ + vcdev->config_block->index = index; + ccw->cmd_code = CCW_CMD_READ_VQ_CONF; + ccw->flags = 0; + ccw->count = sizeof(struct vq_config_block); + ccw->cda = (__u32)(unsigned long)(vcdev->config_block); + ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_READ_VQ_CONF); + return vcdev->config_block->num; +} + +static void virtio_ccw_del_vq(struct virtqueue *vq, struct ccw1 *ccw) +{ + struct virtio_ccw_device *vcdev = to_vc_device(vq->vdev); + struct virtio_ccw_vq_info *info = vq->priv; + unsigned long flags; + unsigned long size; + int ret; + unsigned int index = vq->index; + + /* Remove from our list. */ + spin_lock_irqsave(&vcdev->lock, flags); + list_del(&info->node); + spin_unlock_irqrestore(&vcdev->lock, flags); + + /* Release from host. */ + if (vcdev->revision == 0) { + info->info_block->l.queue = 0; + info->info_block->l.align = 0; + info->info_block->l.index = index; + info->info_block->l.num = 0; + ccw->count = sizeof(info->info_block->l); + } else { + info->info_block->s.desc = 0; + info->info_block->s.index = index; + info->info_block->s.num = 0; + info->info_block->s.avail = 0; + info->info_block->s.used = 0; + ccw->count = sizeof(info->info_block->s); + } + ccw->cmd_code = CCW_CMD_SET_VQ; + ccw->flags = 0; + ccw->cda = (__u32)(unsigned long)(info->info_block); + ret = ccw_io_helper(vcdev, ccw, + VIRTIO_CCW_DOING_SET_VQ | index); + /* + * -ENODEV isn't considered an error: The device is gone anyway. + * This may happen on device detach. + */ + if (ret && (ret != -ENODEV)) + dev_warn(&vq->vdev->dev, "Error %d while deleting queue %d", + ret, index); + + vring_del_virtqueue(vq); + size = PAGE_ALIGN(vring_size(info->num, KVM_VIRTIO_CCW_RING_ALIGN)); + free_pages_exact(info->queue, size); + kfree(info->info_block); + kfree(info); +} + +static void virtio_ccw_del_vqs(struct virtio_device *vdev) +{ + struct virtqueue *vq, *n; + struct ccw1 *ccw; + struct virtio_ccw_device *vcdev = to_vc_device(vdev); + + ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL); + if (!ccw) + return; + + virtio_ccw_drop_indicator(vcdev, ccw); + + list_for_each_entry_safe(vq, n, &vdev->vqs, list) + virtio_ccw_del_vq(vq, ccw); + + kfree(ccw); +} + +static struct virtqueue *virtio_ccw_setup_vq(struct virtio_device *vdev, + int i, vq_callback_t *callback, + const char *name, + struct ccw1 *ccw) +{ + struct virtio_ccw_device *vcdev = to_vc_device(vdev); + int err; + struct virtqueue *vq = NULL; + struct virtio_ccw_vq_info *info; + unsigned long size = 0; /* silence the compiler */ + unsigned long flags; + + /* Allocate queue. */ + info = kzalloc(sizeof(struct virtio_ccw_vq_info), GFP_KERNEL); + if (!info) { + dev_warn(&vcdev->cdev->dev, "no info\n"); + err = -ENOMEM; + goto out_err; + } + info->info_block = kzalloc(sizeof(*info->info_block), + GFP_DMA | GFP_KERNEL); + if (!info->info_block) { + dev_warn(&vcdev->cdev->dev, "no info block\n"); + err = -ENOMEM; + goto out_err; + } + info->num = virtio_ccw_read_vq_conf(vcdev, ccw, i); + size = PAGE_ALIGN(vring_size(info->num, KVM_VIRTIO_CCW_RING_ALIGN)); + info->queue = alloc_pages_exact(size, GFP_KERNEL | __GFP_ZERO); + if (info->queue == NULL) { + dev_warn(&vcdev->cdev->dev, "no queue\n"); + err = -ENOMEM; + goto out_err; + } + + vq = vring_new_virtqueue(i, info->num, KVM_VIRTIO_CCW_RING_ALIGN, vdev, + true, info->queue, virtio_ccw_kvm_notify, + callback, name); + if (!vq) { + /* For now, we fail if we can't get the requested size. */ + dev_warn(&vcdev->cdev->dev, "no vq\n"); + err = -ENOMEM; + goto out_err; + } + + /* Register it with the host. */ + if (vcdev->revision == 0) { + info->info_block->l.queue = (__u64)info->queue; + info->info_block->l.align = KVM_VIRTIO_CCW_RING_ALIGN; + info->info_block->l.index = i; + info->info_block->l.num = info->num; + ccw->count = sizeof(info->info_block->l); + } else { + info->info_block->s.desc = (__u64)info->queue; + info->info_block->s.index = i; + info->info_block->s.num = info->num; + info->info_block->s.avail = (__u64)virtqueue_get_avail(vq); + info->info_block->s.used = (__u64)virtqueue_get_used(vq); + ccw->count = sizeof(info->info_block->s); + } + ccw->cmd_code = CCW_CMD_SET_VQ; + ccw->flags = 0; + ccw->cda = (__u32)(unsigned long)(info->info_block); + err = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_SET_VQ | i); + if (err) { + dev_warn(&vcdev->cdev->dev, "SET_VQ failed\n"); + goto out_err; + } + + info->vq = vq; + vq->priv = info; + + /* Save it to our list. */ + spin_lock_irqsave(&vcdev->lock, flags); + list_add(&info->node, &vcdev->virtqueues); + spin_unlock_irqrestore(&vcdev->lock, flags); + + return vq; + +out_err: + if (vq) + vring_del_virtqueue(vq); + if (info) { + if (info->queue) + free_pages_exact(info->queue, size); + kfree(info->info_block); + } + kfree(info); + return ERR_PTR(err); +} + +static int virtio_ccw_register_adapter_ind(struct virtio_ccw_device *vcdev, + struct virtqueue *vqs[], int nvqs, + struct ccw1 *ccw) +{ + int ret; + struct virtio_thinint_area *thinint_area = NULL; + struct airq_info *info; + + thinint_area = kzalloc(sizeof(*thinint_area), GFP_DMA | GFP_KERNEL); + if (!thinint_area) { + ret = -ENOMEM; + goto out; + } + /* Try to get an indicator. */ + thinint_area->indicator = get_airq_indicator(vqs, nvqs, + &thinint_area->bit_nr, + &vcdev->airq_info); + if (!thinint_area->indicator) { + ret = -ENOSPC; + goto out; + } + info = vcdev->airq_info; + thinint_area->summary_indicator = + (unsigned long) &info->summary_indicator; + thinint_area->isc = VIRTIO_AIRQ_ISC; + ccw->cmd_code = CCW_CMD_SET_IND_ADAPTER; + ccw->flags = CCW_FLAG_SLI; + ccw->count = sizeof(*thinint_area); + ccw->cda = (__u32)(unsigned long)thinint_area; + ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_SET_IND_ADAPTER); + if (ret) { + if (ret == -EOPNOTSUPP) { + /* + * The host does not support adapter interrupts + * for virtio-ccw, stop trying. + */ + virtio_ccw_use_airq = 0; + pr_info("Adapter interrupts unsupported on host\n"); + } else + dev_warn(&vcdev->cdev->dev, + "enabling adapter interrupts = %d\n", ret); + virtio_ccw_drop_indicators(vcdev); + } +out: + kfree(thinint_area); + return ret; +} + +static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs, + struct virtqueue *vqs[], + vq_callback_t *callbacks[], + const char *names[]) +{ + struct virtio_ccw_device *vcdev = to_vc_device(vdev); + unsigned long *indicatorp = NULL; + int ret, i; + struct ccw1 *ccw; + + ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL); + if (!ccw) + return -ENOMEM; + + for (i = 0; i < nvqs; ++i) { + vqs[i] = virtio_ccw_setup_vq(vdev, i, callbacks[i], names[i], + ccw); + if (IS_ERR(vqs[i])) { + ret = PTR_ERR(vqs[i]); + vqs[i] = NULL; + goto out; + } + } + ret = -ENOMEM; + /* We need a data area under 2G to communicate. */ + indicatorp = kmalloc(sizeof(&vcdev->indicators), GFP_DMA | GFP_KERNEL); + if (!indicatorp) + goto out; + *indicatorp = (unsigned long) &vcdev->indicators; + if (vcdev->is_thinint) { + ret = virtio_ccw_register_adapter_ind(vcdev, vqs, nvqs, ccw); + if (ret) + /* no error, just fall back to legacy interrupts */ + vcdev->is_thinint = 0; + } + if (!vcdev->is_thinint) { + /* Register queue indicators with host. */ + vcdev->indicators = 0; + ccw->cmd_code = CCW_CMD_SET_IND; + ccw->flags = 0; + ccw->count = sizeof(vcdev->indicators); + ccw->cda = (__u32)(unsigned long) indicatorp; + ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_SET_IND); + if (ret) + goto out; + } + /* Register indicators2 with host for config changes */ + *indicatorp = (unsigned long) &vcdev->indicators2; + vcdev->indicators2 = 0; + ccw->cmd_code = CCW_CMD_SET_CONF_IND; + ccw->flags = 0; + ccw->count = sizeof(vcdev->indicators2); + ccw->cda = (__u32)(unsigned long) indicatorp; + ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_SET_CONF_IND); + if (ret) + goto out; + + kfree(indicatorp); + kfree(ccw); + return 0; +out: + kfree(indicatorp); + kfree(ccw); + virtio_ccw_del_vqs(vdev); + return ret; +} + +static void virtio_ccw_reset(struct virtio_device *vdev) +{ + struct virtio_ccw_device *vcdev = to_vc_device(vdev); + struct ccw1 *ccw; + + ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL); + if (!ccw) + return; + + /* Zero status bits. */ + *vcdev->status = 0; + + /* Send a reset ccw on device. */ + ccw->cmd_code = CCW_CMD_VDEV_RESET; + ccw->flags = 0; + ccw->count = 0; + ccw->cda = 0; + ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_RESET); + kfree(ccw); +} + +static u64 virtio_ccw_get_features(struct virtio_device *vdev) +{ + struct virtio_ccw_device *vcdev = to_vc_device(vdev); + struct virtio_feature_desc *features; + int ret; + u64 rc; + struct ccw1 *ccw; + + ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL); + if (!ccw) + return 0; + + features = kzalloc(sizeof(*features), GFP_DMA | GFP_KERNEL); + if (!features) { + rc = 0; + goto out_free; + } + /* Read the feature bits from the host. */ + features->index = 0; + ccw->cmd_code = CCW_CMD_READ_FEAT; + ccw->flags = 0; + ccw->count = sizeof(*features); + ccw->cda = (__u32)(unsigned long)features; + ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_READ_FEAT); + if (ret) { + rc = 0; + goto out_free; + } + + rc = le32_to_cpu(features->features); + + if (vcdev->revision == 0) + goto out_free; + + /* Read second half of the feature bits from the host. */ + features->index = 1; + ccw->cmd_code = CCW_CMD_READ_FEAT; + ccw->flags = 0; + ccw->count = sizeof(*features); + ccw->cda = (__u32)(unsigned long)features; + ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_READ_FEAT); + if (ret == 0) + rc |= (u64)le32_to_cpu(features->features) << 32; + +out_free: + kfree(features); + kfree(ccw); + return rc; +} + +static int virtio_ccw_finalize_features(struct virtio_device *vdev) +{ + struct virtio_ccw_device *vcdev = to_vc_device(vdev); + struct virtio_feature_desc *features; + struct ccw1 *ccw; + int ret; + + if (vcdev->revision >= 1 && + !__virtio_test_bit(vdev, VIRTIO_F_VERSION_1)) { + dev_err(&vdev->dev, "virtio: device uses revision 1 " + "but does not have VIRTIO_F_VERSION_1\n"); + return -EINVAL; + } + + ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL); + if (!ccw) + return -ENOMEM; + + features = kzalloc(sizeof(*features), GFP_DMA | GFP_KERNEL); + if (!features) { + ret = -ENOMEM; + goto out_free; + } + /* Give virtio_ring a chance to accept features. */ + vring_transport_features(vdev); + + features->index = 0; + features->features = cpu_to_le32((u32)vdev->features); + /* Write the first half of the feature bits to the host. */ + ccw->cmd_code = CCW_CMD_WRITE_FEAT; + ccw->flags = 0; + ccw->count = sizeof(*features); + ccw->cda = (__u32)(unsigned long)features; + ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_WRITE_FEAT); + if (ret) + goto out_free; + + if (vcdev->revision == 0) + goto out_free; + + features->index = 1; + features->features = cpu_to_le32(vdev->features >> 32); + /* Write the second half of the feature bits to the host. */ + ccw->cmd_code = CCW_CMD_WRITE_FEAT; + ccw->flags = 0; + ccw->count = sizeof(*features); + ccw->cda = (__u32)(unsigned long)features; + ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_WRITE_FEAT); + +out_free: + kfree(features); + kfree(ccw); + + return ret; +} + +static void virtio_ccw_get_config(struct virtio_device *vdev, + unsigned int offset, void *buf, unsigned len) +{ + struct virtio_ccw_device *vcdev = to_vc_device(vdev); + int ret; + struct ccw1 *ccw; + void *config_area; + + ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL); + if (!ccw) + return; + + config_area = kzalloc(VIRTIO_CCW_CONFIG_SIZE, GFP_DMA | GFP_KERNEL); + if (!config_area) + goto out_free; + + /* Read the config area from the host. */ + ccw->cmd_code = CCW_CMD_READ_CONF; + ccw->flags = 0; + ccw->count = offset + len; + ccw->cda = (__u32)(unsigned long)config_area; + ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_READ_CONFIG); + if (ret) + goto out_free; + + memcpy(vcdev->config, config_area, sizeof(vcdev->config)); + memcpy(buf, &vcdev->config[offset], len); + +out_free: + kfree(config_area); + kfree(ccw); +} + +static void virtio_ccw_set_config(struct virtio_device *vdev, + unsigned int offset, const void *buf, + unsigned len) +{ + struct virtio_ccw_device *vcdev = to_vc_device(vdev); + struct ccw1 *ccw; + void *config_area; + + ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL); + if (!ccw) + return; + + config_area = kzalloc(VIRTIO_CCW_CONFIG_SIZE, GFP_DMA | GFP_KERNEL); + if (!config_area) + goto out_free; + + memcpy(&vcdev->config[offset], buf, len); + /* Write the config area to the host. */ + memcpy(config_area, vcdev->config, sizeof(vcdev->config)); + ccw->cmd_code = CCW_CMD_WRITE_CONF; + ccw->flags = 0; + ccw->count = offset + len; + ccw->cda = (__u32)(unsigned long)config_area; + ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_WRITE_CONFIG); + +out_free: + kfree(config_area); + kfree(ccw); +} + +static u8 virtio_ccw_get_status(struct virtio_device *vdev) +{ + struct virtio_ccw_device *vcdev = to_vc_device(vdev); + + return *vcdev->status; +} + +static void virtio_ccw_set_status(struct virtio_device *vdev, u8 status) +{ + struct virtio_ccw_device *vcdev = to_vc_device(vdev); + u8 old_status = *vcdev->status; + struct ccw1 *ccw; + int ret; + + ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL); + if (!ccw) + return; + + /* Write the status to the host. */ + *vcdev->status = status; + ccw->cmd_code = CCW_CMD_WRITE_STATUS; + ccw->flags = 0; + ccw->count = sizeof(status); + ccw->cda = (__u32)(unsigned long)vcdev->status; + ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_WRITE_STATUS); + /* Write failed? We assume status is unchanged. */ + if (ret) + *vcdev->status = old_status; + kfree(ccw); +} + +static struct virtio_config_ops virtio_ccw_config_ops = { + .get_features = virtio_ccw_get_features, + .finalize_features = virtio_ccw_finalize_features, + .get = virtio_ccw_get_config, + .set = virtio_ccw_set_config, + .get_status = virtio_ccw_get_status, + .set_status = virtio_ccw_set_status, + .reset = virtio_ccw_reset, + .find_vqs = virtio_ccw_find_vqs, + .del_vqs = virtio_ccw_del_vqs, +}; + + +/* + * ccw bus driver related functions + */ + +static void virtio_ccw_release_dev(struct device *_d) +{ + struct virtio_device *dev = container_of(_d, struct virtio_device, + dev); + struct virtio_ccw_device *vcdev = to_vc_device(dev); + + kfree(vcdev->status); + kfree(vcdev->config_block); + kfree(vcdev); +} + +static int irb_is_error(struct irb *irb) +{ + if (scsw_cstat(&irb->scsw) != 0) + return 1; + if (scsw_dstat(&irb->scsw) & ~(DEV_STAT_CHN_END | DEV_STAT_DEV_END)) + return 1; + if (scsw_cc(&irb->scsw) != 0) + return 1; + return 0; +} + +static struct virtqueue *virtio_ccw_vq_by_ind(struct virtio_ccw_device *vcdev, + int index) +{ + struct virtio_ccw_vq_info *info; + unsigned long flags; + struct virtqueue *vq; + + vq = NULL; + spin_lock_irqsave(&vcdev->lock, flags); + list_for_each_entry(info, &vcdev->virtqueues, node) { + if (info->vq->index == index) { + vq = info->vq; + break; + } + } + spin_unlock_irqrestore(&vcdev->lock, flags); + return vq; +} + +static void virtio_ccw_int_handler(struct ccw_device *cdev, + unsigned long intparm, + struct irb *irb) +{ + __u32 activity = intparm & VIRTIO_CCW_INTPARM_MASK; + struct virtio_ccw_device *vcdev = dev_get_drvdata(&cdev->dev); + int i; + struct virtqueue *vq; + + if (!vcdev) + return; + /* Check if it's a notification from the host. */ + if ((intparm == 0) && + (scsw_stctl(&irb->scsw) == + (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND))) { + /* OK */ + } + if (irb_is_error(irb)) { + /* Command reject? */ + if ((scsw_dstat(&irb->scsw) & DEV_STAT_UNIT_CHECK) && + (irb->ecw[0] & SNS0_CMD_REJECT)) + vcdev->err = -EOPNOTSUPP; + else + /* Map everything else to -EIO. */ + vcdev->err = -EIO; + } + if (vcdev->curr_io & activity) { + switch (activity) { + case VIRTIO_CCW_DOING_READ_FEAT: + case VIRTIO_CCW_DOING_WRITE_FEAT: + case VIRTIO_CCW_DOING_READ_CONFIG: + case VIRTIO_CCW_DOING_WRITE_CONFIG: + case VIRTIO_CCW_DOING_WRITE_STATUS: + case VIRTIO_CCW_DOING_SET_VQ: + case VIRTIO_CCW_DOING_SET_IND: + case VIRTIO_CCW_DOING_SET_CONF_IND: + case VIRTIO_CCW_DOING_RESET: + case VIRTIO_CCW_DOING_READ_VQ_CONF: + case VIRTIO_CCW_DOING_SET_IND_ADAPTER: + case VIRTIO_CCW_DOING_SET_VIRTIO_REV: + vcdev->curr_io &= ~activity; + wake_up(&vcdev->wait_q); + break; + default: + /* don't know what to do... */ + dev_warn(&cdev->dev, "Suspicious activity '%08x'\n", + activity); + WARN_ON(1); + break; + } + } + for_each_set_bit(i, &vcdev->indicators, + sizeof(vcdev->indicators) * BITS_PER_BYTE) { + /* The bit clear must happen before the vring kick. */ + clear_bit(i, &vcdev->indicators); + barrier(); + vq = virtio_ccw_vq_by_ind(vcdev, i); + vring_interrupt(0, vq); + } + if (test_bit(0, &vcdev->indicators2)) { + virtio_config_changed(&vcdev->vdev); + clear_bit(0, &vcdev->indicators2); + } +} + +/* + * We usually want to autoonline all devices, but give the admin + * a way to exempt devices from this. + */ +#define __DEV_WORDS ((__MAX_SUBCHANNEL + (8*sizeof(long) - 1)) / \ + (8*sizeof(long))) +static unsigned long devs_no_auto[__MAX_SSID + 1][__DEV_WORDS]; + +static char *no_auto = ""; + +module_param(no_auto, charp, 0444); +MODULE_PARM_DESC(no_auto, "list of ccw bus id ranges not to be auto-onlined"); + +static int virtio_ccw_check_autoonline(struct ccw_device *cdev) +{ + struct ccw_dev_id id; + + ccw_device_get_id(cdev, &id); + if (test_bit(id.devno, devs_no_auto[id.ssid])) + return 0; + return 1; +} + +static void virtio_ccw_auto_online(void *data, async_cookie_t cookie) +{ + struct ccw_device *cdev = data; + int ret; + + ret = ccw_device_set_online(cdev); + if (ret) + dev_warn(&cdev->dev, "Failed to set online: %d\n", ret); +} + +static int virtio_ccw_probe(struct ccw_device *cdev) +{ + cdev->handler = virtio_ccw_int_handler; + + if (virtio_ccw_check_autoonline(cdev)) + async_schedule(virtio_ccw_auto_online, cdev); + return 0; +} + +static struct virtio_ccw_device *virtio_grab_drvdata(struct ccw_device *cdev) +{ + unsigned long flags; + struct virtio_ccw_device *vcdev; + + spin_lock_irqsave(get_ccwdev_lock(cdev), flags); + vcdev = dev_get_drvdata(&cdev->dev); + if (!vcdev || vcdev->going_away) { + spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); + return NULL; + } + vcdev->going_away = true; + spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); + return vcdev; +} + +static void virtio_ccw_remove(struct ccw_device *cdev) +{ + unsigned long flags; + struct virtio_ccw_device *vcdev = virtio_grab_drvdata(cdev); + + if (vcdev && cdev->online) { + if (vcdev->device_lost) + virtio_break_device(&vcdev->vdev); + unregister_virtio_device(&vcdev->vdev); + spin_lock_irqsave(get_ccwdev_lock(cdev), flags); + dev_set_drvdata(&cdev->dev, NULL); + spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); + } + cdev->handler = NULL; +} + +static int virtio_ccw_offline(struct ccw_device *cdev) +{ + unsigned long flags; + struct virtio_ccw_device *vcdev = virtio_grab_drvdata(cdev); + + if (!vcdev) + return 0; + if (vcdev->device_lost) + virtio_break_device(&vcdev->vdev); + unregister_virtio_device(&vcdev->vdev); + spin_lock_irqsave(get_ccwdev_lock(cdev), flags); + dev_set_drvdata(&cdev->dev, NULL); + spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); + return 0; +} + +static int virtio_ccw_set_transport_rev(struct virtio_ccw_device *vcdev) +{ + struct virtio_rev_info *rev; + struct ccw1 *ccw; + int ret; + + ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL); + if (!ccw) + return -ENOMEM; + rev = kzalloc(sizeof(*rev), GFP_DMA | GFP_KERNEL); + if (!rev) { + kfree(ccw); + return -ENOMEM; + } + + /* Set transport revision */ + ccw->cmd_code = CCW_CMD_SET_VIRTIO_REV; + ccw->flags = 0; + ccw->count = sizeof(*rev); + ccw->cda = (__u32)(unsigned long)rev; + + vcdev->revision = VIRTIO_CCW_REV_MAX; + do { + rev->revision = vcdev->revision; + /* none of our supported revisions carry payload */ + rev->length = 0; + ret = ccw_io_helper(vcdev, ccw, + VIRTIO_CCW_DOING_SET_VIRTIO_REV); + if (ret == -EOPNOTSUPP) { + if (vcdev->revision == 0) + /* + * The host device does not support setting + * the revision: let's operate it in legacy + * mode. + */ + ret = 0; + else + vcdev->revision--; + } + } while (ret == -EOPNOTSUPP); + + kfree(ccw); + kfree(rev); + return ret; +} + +static int virtio_ccw_online(struct ccw_device *cdev) +{ + int ret; + struct virtio_ccw_device *vcdev; + unsigned long flags; + + vcdev = kzalloc(sizeof(*vcdev), GFP_KERNEL); + if (!vcdev) { + dev_warn(&cdev->dev, "Could not get memory for virtio\n"); + ret = -ENOMEM; + goto out_free; + } + vcdev->config_block = kzalloc(sizeof(*vcdev->config_block), + GFP_DMA | GFP_KERNEL); + if (!vcdev->config_block) { + ret = -ENOMEM; + goto out_free; + } + vcdev->status = kzalloc(sizeof(*vcdev->status), GFP_DMA | GFP_KERNEL); + if (!vcdev->status) { + ret = -ENOMEM; + goto out_free; + } + + vcdev->is_thinint = virtio_ccw_use_airq; /* at least try */ + + vcdev->vdev.dev.parent = &cdev->dev; + vcdev->vdev.dev.release = virtio_ccw_release_dev; + vcdev->vdev.config = &virtio_ccw_config_ops; + vcdev->cdev = cdev; + init_waitqueue_head(&vcdev->wait_q); + INIT_LIST_HEAD(&vcdev->virtqueues); + spin_lock_init(&vcdev->lock); + + spin_lock_irqsave(get_ccwdev_lock(cdev), flags); + dev_set_drvdata(&cdev->dev, vcdev); + spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); + vcdev->vdev.id.vendor = cdev->id.cu_type; + vcdev->vdev.id.device = cdev->id.cu_model; + + ret = virtio_ccw_set_transport_rev(vcdev); + if (ret) + goto out_free; + + ret = register_virtio_device(&vcdev->vdev); + if (ret) { + dev_warn(&cdev->dev, "Failed to register virtio device: %d\n", + ret); + goto out_put; + } + return 0; +out_put: + spin_lock_irqsave(get_ccwdev_lock(cdev), flags); + dev_set_drvdata(&cdev->dev, NULL); + spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); + put_device(&vcdev->vdev.dev); + return ret; +out_free: + if (vcdev) { + kfree(vcdev->status); + kfree(vcdev->config_block); + } + kfree(vcdev); + return ret; +} + +static int virtio_ccw_cio_notify(struct ccw_device *cdev, int event) +{ + int rc; + struct virtio_ccw_device *vcdev = dev_get_drvdata(&cdev->dev); + + /* + * Make sure vcdev is set + * i.e. set_offline/remove callback not already running + */ + if (!vcdev) + return NOTIFY_DONE; + + switch (event) { + case CIO_GONE: + vcdev->device_lost = true; + rc = NOTIFY_DONE; + break; + default: + rc = NOTIFY_DONE; + break; + } + return rc; +} + +static struct ccw_device_id virtio_ids[] = { + { CCW_DEVICE(0x3832, 0) }, + {}, +}; +MODULE_DEVICE_TABLE(ccw, virtio_ids); + +static struct ccw_driver virtio_ccw_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "virtio_ccw", + }, + .ids = virtio_ids, + .probe = virtio_ccw_probe, + .remove = virtio_ccw_remove, + .set_offline = virtio_ccw_offline, + .set_online = virtio_ccw_online, + .notify = virtio_ccw_cio_notify, + .int_class = IRQIO_VIR, +}; + +static int __init pure_hex(char **cp, unsigned int *val, int min_digit, + int max_digit, int max_val) +{ + int diff; + + diff = 0; + *val = 0; + + while (diff <= max_digit) { + int value = hex_to_bin(**cp); + + if (value < 0) + break; + *val = *val * 16 + value; + (*cp)++; + diff++; + } + + if ((diff < min_digit) || (diff > max_digit) || (*val > max_val)) + return 1; + + return 0; +} + +static int __init parse_busid(char *str, unsigned int *cssid, + unsigned int *ssid, unsigned int *devno) +{ + char *str_work; + int rc, ret; + + rc = 1; + + if (*str == '\0') + goto out; + + str_work = str; + ret = pure_hex(&str_work, cssid, 1, 2, __MAX_CSSID); + if (ret || (str_work[0] != '.')) + goto out; + str_work++; + ret = pure_hex(&str_work, ssid, 1, 1, __MAX_SSID); + if (ret || (str_work[0] != '.')) + goto out; + str_work++; + ret = pure_hex(&str_work, devno, 4, 4, __MAX_SUBCHANNEL); + if (ret || (str_work[0] != '\0')) + goto out; + + rc = 0; +out: + return rc; +} + +static void __init no_auto_parse(void) +{ + unsigned int from_cssid, to_cssid, from_ssid, to_ssid, from, to; + char *parm, *str; + int rc; + + str = no_auto; + while ((parm = strsep(&str, ","))) { + rc = parse_busid(strsep(&parm, "-"), &from_cssid, + &from_ssid, &from); + if (rc) + continue; + if (parm != NULL) { + rc = parse_busid(parm, &to_cssid, + &to_ssid, &to); + if ((from_ssid > to_ssid) || + ((from_ssid == to_ssid) && (from > to))) + rc = -EINVAL; + } else { + to_cssid = from_cssid; + to_ssid = from_ssid; + to = from; + } + if (rc) + continue; + while ((from_ssid < to_ssid) || + ((from_ssid == to_ssid) && (from <= to))) { + set_bit(from, devs_no_auto[from_ssid]); + from++; + if (from > __MAX_SUBCHANNEL) { + from_ssid++; + from = 0; + } + } + } +} + +static int __init virtio_ccw_init(void) +{ + /* parse no_auto string before we do anything further */ + no_auto_parse(); + return ccw_driver_register(&virtio_ccw_driver); +} +module_init(virtio_ccw_init); + +static void __exit virtio_ccw_exit(void) +{ + int i; + + ccw_driver_unregister(&virtio_ccw_driver); + for (i = 0; i < MAX_AIRQ_AREAS; i++) + destroy_airq_info(airq_areas[i]); +} +module_exit(virtio_ccw_exit); -- cgit v1.2.3 From 6fec919b61b66e7f92646a7bd6fada9850f5cedc Mon Sep 17 00:00:00 2001 From: Jiri Prchal Date: Thu, 25 Jun 2015 13:44:19 +0200 Subject: spi: spidev: add compatible value for LTC2488 Since spidev is no more allowed to use in DT and is really loudly warned about it I'd like to add this compatible value. (Geert Uytterhoeven wrote: "Add the compatible value for your device to the spidev_dt_ids[] array in drivers/spi/spidev.c.") Signed-off-by: Mark Brown --- drivers/spi/spidev.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index dd616ff0ffc5..c7de64171c45 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c @@ -693,6 +693,7 @@ static struct class *spidev_class; #ifdef CONFIG_OF static const struct of_device_id spidev_dt_ids[] = { { .compatible = "rohm,dh2228fv" }, + { .compatible = "lineartechnology,ltc2488" }, {}, }; MODULE_DEVICE_TABLE(of, spidev_dt_ids); -- cgit v1.2.3 From 2e1c75f4d3ecf127032f2511aba76927a8703c1d Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 26 Jun 2015 14:07:12 +0200 Subject: spi: SPI_ZYNQMP_GQSPI should depend on HAS_DMA If NO_DMA=y: ERROR: "dma_unmap_single" [drivers/spi/spi-zynqmp-gqspi.ko] undefined! ERROR: "dma_mapping_error" [drivers/spi/spi-zynqmp-gqspi.ko] undefined! ERROR: "dma_map_single" [drivers/spi/spi-zynqmp-gqspi.ko] undefined! Add a dependency on HAS_DMA to fix this. Signed-off-by: Geert Uytterhoeven Acked-by: Ranjit Waghmode Signed-off-by: Mark Brown --- drivers/spi/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 0cae1694014d..b0f30fb68914 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -612,7 +612,7 @@ config SPI_XTENSA_XTFPGA config SPI_ZYNQMP_GQSPI tristate "Xilinx ZynqMP GQSPI controller" - depends on SPI_MASTER + depends on SPI_MASTER && HAS_DMA help Enables Xilinx GQSPI controller driver for Zynq UltraScale+ MPSoC. -- cgit v1.2.3 From 127e10624232c5d605cad840d21af3b842541719 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 1 Jul 2015 18:31:42 +0530 Subject: regulator: max8973: Fix up control flag option for bias control The control flag for the bias control is MAX8973_CONTROL_BIAS_ENABLE rather than MAX8973_BIAS_ENABLE which is macro for the bits in register. Fix this typo. Signed-off-by: Laxman Dewangan Signed-off-by: Mark Brown --- drivers/regulator/max8973-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/max8973-regulator.c b/drivers/regulator/max8973-regulator.c index 6f2bdad8b4d8..e94ddcf97722 100644 --- a/drivers/regulator/max8973-regulator.c +++ b/drivers/regulator/max8973-regulator.c @@ -450,7 +450,7 @@ static struct max8973_regulator_platform_data *max8973_parse_dt( pdata->control_flags |= MAX8973_CONTROL_FREQ_SHIFT_9PER_ENABLE; if (of_property_read_bool(np, "maxim,enable-bias-control")) - pdata->control_flags |= MAX8973_BIAS_ENABLE; + pdata->control_flags |= MAX8973_CONTROL_BIAS_ENABLE; return pdata; } -- cgit v1.2.3 From 861a481c5ede75bf31bc118f1f7f6d1f420182b5 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 24 Jun 2015 17:31:33 +0300 Subject: spi: zynq: missing break statement There is a missing break statement here so selecting both only selects upper. Fixes: dfe11a11d523 ('spi: Add support for Zynq Ultrascale+ MPSoC GQSPI controller') Signed-off-by: Dan Carpenter Acked-by: Michal Simek Signed-off-by: Mark Brown --- drivers/spi/spi-zynqmp-gqspi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c index 87b20a511a6b..f23f36ebaf3d 100644 --- a/drivers/spi/spi-zynqmp-gqspi.c +++ b/drivers/spi/spi-zynqmp-gqspi.c @@ -214,6 +214,7 @@ static void zynqmp_gqspi_selectslave(struct zynqmp_qspi *instanceptr, case GQSPI_SELECT_FLASH_CS_BOTH: instanceptr->genfifocs = GQSPI_GENFIFO_CS_LOWER | GQSPI_GENFIFO_CS_UPPER; + break; case GQSPI_SELECT_FLASH_CS_UPPER: instanceptr->genfifocs = GQSPI_GENFIFO_CS_UPPER; break; -- cgit v1.2.3 From 5f867db63473f32cce1b868e281ebd42a41f8fad Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Fri, 26 Jun 2015 19:43:58 -0500 Subject: mtd: nand: Fix NAND_USE_BOUNCE_BUFFER flag conflict Commit 66507c7bc8895f0da6b ("mtd: nand: Add support to use nand_base poi databuf as bounce buffer") added a flag NAND_USE_BOUNCE_BUFFER using the same bit value as the existing NAND_BUSWIDTH_AUTO. Cc: Kamal Dasu Fixes: 66507c7bc8895f0da6b ("mtd: nand: Add support to use nand_base poi databuf as bounce buffer") Signed-off-by: Scott Wood Signed-off-by: Brian Norris --- include/linux/mtd/nand.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index f25e2bdd188c..272f42952f34 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -177,11 +177,6 @@ typedef enum { #define NAND_OWN_BUFFERS 0x00020000 /* Chip may not exist, so silence any errors in scan */ #define NAND_SCAN_SILENT_NODEV 0x00040000 -/* - * This option could be defined by controller drivers to protect against - * kmap'ed, vmalloc'ed highmem buffers being passed from upper layers - */ -#define NAND_USE_BOUNCE_BUFFER 0x00080000 /* * Autodetect nand buswidth with readid/onfi. * This suppose the driver will configure the hardware in 8 bits mode @@ -189,6 +184,11 @@ typedef enum { * before calling nand_scan_tail. */ #define NAND_BUSWIDTH_AUTO 0x00080000 +/* + * This option could be defined by controller drivers to protect against + * kmap'ed, vmalloc'ed highmem buffers being passed from upper layers + */ +#define NAND_USE_BOUNCE_BUFFER 0x00100000 /* Options set by nand scan */ /* Nand scan has allocated controller struct */ -- cgit v1.2.3 From 66337b7c67f6237720ba13f6d41b9d8dbcb59cda Mon Sep 17 00:00:00 2001 From: "Dreyfuss, Haim" Date: Thu, 4 Jun 2015 11:45:33 +0300 Subject: iwlwifi: pcie: Fix bug in NIC's PM registers access While cleanig the access to those hw-dependent registers, instead of using the product family type, wrong condition was added mistakenly and enabled 8000 family devices a forbidden access to HW registers, fix it. Fixes: 95411d0455cc ("iwlwifi: pcie: Control access to the NIC's PM registers via iwl_cfg") Signed-off-by: Dreyfuss, Haim Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/pcie/trans.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index 43ae658af6ec..608ba1e39a0f 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c @@ -182,7 +182,7 @@ static void iwl_trans_pcie_write_shr(struct iwl_trans *trans, u32 reg, u32 val) static void iwl_pcie_set_pwr(struct iwl_trans *trans, bool vaux) { - if (!trans->cfg->apmg_not_supported) + if (trans->cfg->apmg_not_supported) return; if (vaux && pci_pme_capable(to_pci_dev(trans->dev), PCI_D3cold)) -- cgit v1.2.3 From af3f2f740173f8b5c61dba46f900998c5984ccd9 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 4 Jun 2015 09:51:11 +0300 Subject: iwlwifi: pcie: don't panic if pcie transport alloc fails iwl_trans_pcie_alloc needs to return a non-zero value if it fails. Otherwise the iwl_drv_start will think that the allocation succeeded. Remove the duplication of err and ret variable and use ret which is the name we usually use in other places of the driver. Fixes: c278754a21e6 ("iwlwifi: mvm: support family 8000 B2/C steps") CC: [4.1] Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/pcie/trans.c | 44 +++++++++++++++---------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index 608ba1e39a0f..fe61d0aa5550 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c @@ -2459,7 +2459,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, struct iwl_trans_pcie *trans_pcie; struct iwl_trans *trans; u16 pci_cmd; - int err; + int ret; trans = iwl_trans_alloc(sizeof(struct iwl_trans_pcie), &pdev->dev, cfg, &trans_ops_pcie, 0); @@ -2474,8 +2474,8 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, spin_lock_init(&trans_pcie->ref_lock); init_waitqueue_head(&trans_pcie->ucode_write_waitq); - err = pci_enable_device(pdev); - if (err) + ret = pci_enable_device(pdev); + if (ret) goto out_no_pci; if (!cfg->base_params->pcie_l1_allowed) { @@ -2491,23 +2491,23 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, pci_set_master(pdev); - err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36)); - if (!err) - err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(36)); - if (err) { - err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); - if (!err) - err = pci_set_consistent_dma_mask(pdev, + ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(36)); + if (!ret) + ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(36)); + if (ret) { + ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + if (!ret) + ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); /* both attempts failed: */ - if (err) { + if (ret) { dev_err(&pdev->dev, "No suitable DMA available\n"); goto out_pci_disable_device; } } - err = pci_request_regions(pdev, DRV_NAME); - if (err) { + ret = pci_request_regions(pdev, DRV_NAME); + if (ret) { dev_err(&pdev->dev, "pci_request_regions failed\n"); goto out_pci_disable_device; } @@ -2515,7 +2515,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, trans_pcie->hw_base = pci_ioremap_bar(pdev, 0); if (!trans_pcie->hw_base) { dev_err(&pdev->dev, "pci_ioremap_bar failed\n"); - err = -ENODEV; + ret = -ENODEV; goto out_pci_release_regions; } @@ -2527,9 +2527,9 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, trans_pcie->pci_dev = pdev; iwl_disable_interrupts(trans); - err = pci_enable_msi(pdev); - if (err) { - dev_err(&pdev->dev, "pci_enable_msi failed(0X%x)\n", err); + ret = pci_enable_msi(pdev); + if (ret) { + dev_err(&pdev->dev, "pci_enable_msi failed(0X%x)\n", ret); /* enable rfkill interrupt: hw bug w/a */ pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd); if (pci_cmd & PCI_COMMAND_INTX_DISABLE) { @@ -2547,7 +2547,6 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, */ if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) { unsigned long flags; - int ret; trans->hw_rev = (trans->hw_rev & 0xfff0) | (CSR_HW_REV_STEP(trans->hw_rev << 2) << 2); @@ -2591,13 +2590,14 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, /* Initialize the wait queue for commands */ init_waitqueue_head(&trans_pcie->wait_command_queue); - if (iwl_pcie_alloc_ict(trans)) + ret = iwl_pcie_alloc_ict(trans); + if (ret) goto out_pci_disable_msi; - err = request_threaded_irq(pdev->irq, iwl_pcie_isr, + ret = request_threaded_irq(pdev->irq, iwl_pcie_isr, iwl_pcie_irq_handler, IRQF_SHARED, DRV_NAME, trans); - if (err) { + if (ret) { IWL_ERR(trans, "Error allocating IRQ %d\n", pdev->irq); goto out_free_ict; } @@ -2617,5 +2617,5 @@ out_pci_disable_device: pci_disable_device(pdev); out_no_pci: iwl_trans_free(trans); - return ERR_PTR(err); + return ERR_PTR(ret); } -- cgit v1.2.3 From 1cc1cc92c4c4891abc48a777fb9fbc69077d5673 Mon Sep 17 00:00:00 2001 From: Brent Adam Date: Fri, 19 Jun 2015 10:53:35 -0600 Subject: HID: multitouch: Fix fields from pen report ID being interpreted for multitouch Fields like HID_DG_CONTACTCOUNT are outside of the physical collection, but within the application collection and report ID. Make sure to catch those fields that are not part of the mt_report_id and return 0 so they can be processed with the pen. Otherwise, the wrong HID_DG_CONTACTCOUNT will be applied to cc_index and result in dereferencing a null pointer in mt_touch_report. Signed-off-by: Brent Adam Signed-off-by: Jiri Kosina --- drivers/hid/hid-multitouch.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 6a9b05b328a9..7c811252c1ce 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -778,9 +778,16 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, /* * some egalax touchscreens have "application == HID_DG_TOUCHSCREEN" * for the stylus. + * The check for mt_report_id ensures we don't process + * HID_DG_CONTACTCOUNT from the pen report as it is outside the physical + * collection, but within the report ID. */ if (field->physical == HID_DG_STYLUS) return 0; + else if ((field->physical == 0) && + (field->report->id != td->mt_report_id) && + (td->mt_report_id != -1)) + return 0; if (field->application == HID_DG_TOUCHSCREEN || field->application == HID_DG_TOUCHPAD) -- cgit v1.2.3 From 9633920e5ef65f81d30f2acd642d6d1c25cf7bc7 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Wed, 1 Jul 2015 13:01:00 -0700 Subject: HID: wacom: Enable pad device for older Bamboo Touch tablets Commit 862cf55 ("HID: wacom: Introduce a new WACOM_DEVICETYPE_PAD device_type") neglected to set the WACOM_DEVICETYPE_PAD flag for older two-finger Bamboo Touch tablets. Not only does this result in the pad device not appearing when such a tablet is plugged in, but also causes a segfault when 'wacom_bpt_touch' tries to send pad events. This patch adds the flag to resolve these issues. Signed-off-by: Jason Gerecke Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 232da89f4e88..0d244239e55d 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -2213,6 +2213,9 @@ void wacom_setup_device_quirks(struct wacom *wacom) features->x_max = 4096; features->y_max = 4096; } + else if (features->pktlen == WACOM_PKGLEN_BBTOUCH) { + features->device_type |= WACOM_DEVICETYPE_PAD; + } } /* -- cgit v1.2.3 From 6debce6f4e787a8eb4cec94e7afa85fb4f40db27 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 21 Jun 2015 14:20:25 +0800 Subject: HID: cp2112: fix to force single data-report reply Current implementation of cp2112_raw_event() only accepts one data report at a time. If last received data report is not fully handled yet, a new incoming data report will overwrite it. In such case we don't guaranteed to propagate the correct incoming data. The trivial fix implemented here forces a single report at a time by requesting in cp2112_read() no more than 61 byte of data, which is the payload size of a single data report. Cc: stable@vger.kernel.org Signed-off-by: Antonio Borneo Tested-by: Ellen Wang Signed-off-by: Jiri Kosina --- drivers/hid/hid-cp2112.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/hid/hid-cp2112.c b/drivers/hid/hid-cp2112.c index 3318de690e00..a2dbbbe0d8d7 100644 --- a/drivers/hid/hid-cp2112.c +++ b/drivers/hid/hid-cp2112.c @@ -356,6 +356,8 @@ static int cp2112_read(struct cp2112_device *dev, u8 *data, size_t size) struct cp2112_force_read_report report; int ret; + if (size > sizeof(dev->read_data)) + size = sizeof(dev->read_data); report.report = CP2112_DATA_READ_FORCE_SEND; report.length = cpu_to_be16(size); -- cgit v1.2.3 From 69146e7bfc38139a134c79a4ee6607c881891786 Mon Sep 17 00:00:00 2001 From: Zhen Lei Date: Fri, 26 Jun 2015 09:32:58 +0100 Subject: iommu/arm-smmu: Fix the index calculation of strtab The element size of cfg->strtab is just one DWORD, so we should use a multiply operation instead of a shift when calculating the level 1 index. Signed-off-by: Zhen Lei Signed-off-by: Will Deacon --- drivers/iommu/arm-smmu-v3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index 8e9ec81ce4bb..606852f18808 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -1064,7 +1064,7 @@ static int arm_smmu_init_l2_strtab(struct arm_smmu_device *smmu, u32 sid) return 0; size = 1 << (STRTAB_SPLIT + ilog2(STRTAB_STE_DWORDS) + 3); - strtab = &cfg->strtab[sid >> STRTAB_SPLIT << STRTAB_L1_DESC_DWORDS]; + strtab = &cfg->strtab[(sid >> STRTAB_SPLIT) * STRTAB_L1_DESC_DWORDS]; desc->span = STRTAB_SPLIT + 1; desc->l2ptr = dma_zalloc_coherent(smmu->dev, size, &desc->l2ptr_dma, -- cgit v1.2.3 From d2e88e7c081efb2c5a9e1adb2a065d373167af4b Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 30 Jun 2015 10:02:28 +0100 Subject: iommu/arm-smmu: Fix LOG2SIZE setting for 2-level stream tables STRTAB_BASE_CFG.LOG2SIZE should be set to log2(entries), where entries is the *total* number of entries in the stream table, not just the first level. This patch fixes the register setting, which was previously being set to the size of the l1 thanks to a multi-use "size" variable. Reported-by: Zhen Lei Tested-by: Zhen Lei Signed-off-by: Will Deacon --- drivers/iommu/arm-smmu-v3.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index 606852f18808..6b1ae4e09616 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -2020,21 +2020,23 @@ static int arm_smmu_init_strtab_2lvl(struct arm_smmu_device *smmu) { void *strtab; u64 reg; - u32 size; + u32 size, l1size; int ret; struct arm_smmu_strtab_cfg *cfg = &smmu->strtab_cfg; /* Calculate the L1 size, capped to the SIDSIZE */ size = STRTAB_L1_SZ_SHIFT - (ilog2(STRTAB_L1_DESC_DWORDS) + 3); size = min(size, smmu->sid_bits - STRTAB_SPLIT); - if (size + STRTAB_SPLIT < smmu->sid_bits) + cfg->num_l1_ents = 1 << size; + + size += STRTAB_SPLIT; + if (size < smmu->sid_bits) dev_warn(smmu->dev, "2-level strtab only covers %u/%u bits of SID\n", - size + STRTAB_SPLIT, smmu->sid_bits); + size, smmu->sid_bits); - cfg->num_l1_ents = 1 << size; - size = cfg->num_l1_ents * (STRTAB_L1_DESC_DWORDS << 3); - strtab = dma_zalloc_coherent(smmu->dev, size, &cfg->strtab_dma, + l1size = cfg->num_l1_ents * (STRTAB_L1_DESC_DWORDS << 3); + strtab = dma_zalloc_coherent(smmu->dev, l1size, &cfg->strtab_dma, GFP_KERNEL); if (!strtab) { dev_err(smmu->dev, @@ -2055,8 +2057,7 @@ static int arm_smmu_init_strtab_2lvl(struct arm_smmu_device *smmu) ret = arm_smmu_init_l1_strtab(smmu); if (ret) dma_free_coherent(smmu->dev, - cfg->num_l1_ents * - (STRTAB_L1_DESC_DWORDS << 3), + l1size, strtab, cfg->strtab_dma); return ret; -- cgit v1.2.3 From 5d58c6207c300340151931ad9c2cdea2d1685dc4 Mon Sep 17 00:00:00 2001 From: Zhen Lei Date: Fri, 26 Jun 2015 09:32:59 +0100 Subject: iommu/arm-smmu: Fix the values of ARM64_TCR_{I,O}RGN0_SHIFT The arm64 CPU architecture defines TCR[8:11] as holding the inner and outer memory attributes for TTBR0. This patch fixes the ARM SMMUv3 driver to pack these bits into the context descriptor, rather than picking up the TTBR1 attributes as it currently does. Signed-off-by: Zhen Lei Signed-off-by: Will Deacon --- drivers/iommu/arm-smmu-v3.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index 6b1ae4e09616..98e987a3ed3a 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -269,10 +269,10 @@ #define ARM64_TCR_TG0_SHIFT 14 #define ARM64_TCR_TG0_MASK 0x3UL #define CTXDESC_CD_0_TCR_IRGN0_SHIFT 8 -#define ARM64_TCR_IRGN0_SHIFT 24 +#define ARM64_TCR_IRGN0_SHIFT 8 #define ARM64_TCR_IRGN0_MASK 0x3UL #define CTXDESC_CD_0_TCR_ORGN0_SHIFT 10 -#define ARM64_TCR_ORGN0_SHIFT 26 +#define ARM64_TCR_ORGN0_SHIFT 10 #define ARM64_TCR_ORGN0_MASK 0x3UL #define CTXDESC_CD_0_TCR_SH0_SHIFT 12 #define ARM64_TCR_SH0_SHIFT 12 -- cgit v1.2.3 From e2f4c2330f08ba73d9a3c919a3d6ca33dce7d2c2 Mon Sep 17 00:00:00 2001 From: Zhen Lei Date: Tue, 7 Jul 2015 04:30:17 +0100 Subject: iommu/arm-smmu: Enlarge STRTAB_L1_SZ_SHIFT to support larger sidsize Because we will choose the minimum value between STRTAB_L1_SZ_SHIFT and IDR1.SIDSIZE, so enlarge STRTAB_L1_SZ_SHIFT will not impact the platforms whose IDR1.SIDSIZE is smaller than old STRTAB_L1_SZ_SHIFT value. Signed-off-by: Zhen Lei Signed-off-by: Will Deacon --- drivers/iommu/arm-smmu-v3.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index 98e987a3ed3a..29cba3280af7 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -199,9 +199,10 @@ * Stream table. * * Linear: Enough to cover 1 << IDR1.SIDSIZE entries - * 2lvl: 8k L1 entries, 256 lazy entries per table (each table covers a PCI bus) + * 2lvl: 128k L1 entries, + * 256 lazy entries per table (each table covers a PCI bus) */ -#define STRTAB_L1_SZ_SHIFT 16 +#define STRTAB_L1_SZ_SHIFT 20 #define STRTAB_SPLIT 8 #define STRTAB_L1_DESC_DWORDS 1 -- cgit v1.2.3 From 5e92946c39ca6abc65e34775a93cc1d1a819c0e3 Mon Sep 17 00:00:00 2001 From: Zhen Lei Date: Tue, 7 Jul 2015 04:30:18 +0100 Subject: iommu/arm-smmu: Skip the execution of CMD_PREFETCH_CONFIG Hisilicon SMMUv3 devices treat CMD_PREFETCH_CONFIG as a illegal command, execute it will trigger GERROR interrupt. Although the gerror code manage to turn the prefetch into a SYNC, and the system can continue to run normally, but it's ugly to print error information. Signed-off-by: Zhen Lei [will: extended binding documentation] Signed-off-by: Will Deacon --- .../devicetree/bindings/iommu/arm,smmu-v3.txt | 3 ++ drivers/iommu/arm-smmu-v3.c | 32 +++++++++++++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu-v3.txt b/Documentation/devicetree/bindings/iommu/arm,smmu-v3.txt index c03eec116872..3443e0f838df 100644 --- a/Documentation/devicetree/bindings/iommu/arm,smmu-v3.txt +++ b/Documentation/devicetree/bindings/iommu/arm,smmu-v3.txt @@ -35,3 +35,6 @@ the PCIe specification. NOTE: this only applies to the SMMU itself, not masters connected upstream of the SMMU. + +- hisilicon,broken-prefetch-cmd + : Avoid sending CMD_PREFETCH_* commands to the SMMU. diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index 29cba3280af7..da902baaa794 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -543,6 +543,9 @@ struct arm_smmu_device { #define ARM_SMMU_FEAT_HYP (1 << 12) u32 features; +#define ARM_SMMU_OPT_SKIP_PREFETCH (1 << 0) + u32 options; + struct arm_smmu_cmdq cmdq; struct arm_smmu_evtq evtq; struct arm_smmu_priq priq; @@ -603,11 +606,35 @@ struct arm_smmu_domain { static DEFINE_SPINLOCK(arm_smmu_devices_lock); static LIST_HEAD(arm_smmu_devices); +struct arm_smmu_option_prop { + u32 opt; + const char *prop; +}; + +static struct arm_smmu_option_prop arm_smmu_options[] = { + { ARM_SMMU_OPT_SKIP_PREFETCH, "hisilicon,broken-prefetch-cmd" }, + { 0, NULL}, +}; + static struct arm_smmu_domain *to_smmu_domain(struct iommu_domain *dom) { return container_of(dom, struct arm_smmu_domain, domain); } +static void parse_driver_options(struct arm_smmu_device *smmu) +{ + int i = 0; + + do { + if (of_property_read_bool(smmu->dev->of_node, + arm_smmu_options[i].prop)) { + smmu->options |= arm_smmu_options[i].opt; + dev_notice(smmu->dev, "option %s\n", + arm_smmu_options[i].prop); + } + } while (arm_smmu_options[++i].opt); +} + /* Low-level queue manipulation functions */ static bool queue_full(struct arm_smmu_queue *q) { @@ -1037,7 +1064,8 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_device *smmu, u32 sid, arm_smmu_sync_ste_for_sid(smmu, sid); /* It's likely that we'll want to use the new STE soon */ - arm_smmu_cmdq_issue_cmd(smmu, &prefetch_cmd); + if (!(smmu->options & ARM_SMMU_OPT_SKIP_PREFETCH)) + arm_smmu_cmdq_issue_cmd(smmu, &prefetch_cmd); } static void arm_smmu_init_bypass_stes(u64 *strtab, unsigned int nent) @@ -2575,6 +2603,8 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev) if (irq > 0) smmu->gerr_irq = irq; + parse_driver_options(smmu); + /* Probe the h/w */ ret = arm_smmu_device_probe(smmu); if (ret) -- cgit v1.2.3 From 70f19f5869c5accfd9f371c099f21c71516591b2 Mon Sep 17 00:00:00 2001 From: "Steven J. Magnani" Date: Tue, 7 Jul 2015 13:06:05 -0500 Subject: udf: Don't corrupt unalloc spacetable when writing it For a UDF filesystem configured with an Unallocated Space Table, a filesystem operation that triggers an update to the table results in on-disk corruption that prevents remounting: udf_read_tagged: tag version 0x0000 != 0x0002 || 0x0003, block 274 For example: 1. Create a filesystem $ mkudffs --media-type=hd --blocksize=512 --lvid=BUGTEST \ --vid=BUGTEST --fsid=BUGTEST --space=unalloctable \ /dev/mmcblk0 2. Mount it # mount /dev/mmcblk0 /mnt 3. Create a file $ echo "No corruption, please" > /mnt/new.file 4. Umount # umount /mnt 5. Attempt remount # mount /dev/mmcblk0 /mnt This appears to be a longstanding bug caused by zero-initialization of the Unallocated Space Entry block buffer and only partial repopulation of required fields before writing to disk. Commit 0adfb339fd64 ("udf: Fix unalloc space handling in udf_update_inode") addressed one such field, but several others are required. Signed-off-by: Steven J. Magnani Signed-off-by: Jan Kara --- fs/udf/inode.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/fs/udf/inode.c b/fs/udf/inode.c index 6afac3d561ac..8d0b3ade0ff0 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -1652,17 +1652,9 @@ static int udf_update_inode(struct inode *inode, int do_sync) iinfo->i_ext.i_data, inode->i_sb->s_blocksize - sizeof(struct unallocSpaceEntry)); use->descTag.tagIdent = cpu_to_le16(TAG_IDENT_USE); - use->descTag.tagLocation = - cpu_to_le32(iinfo->i_location.logicalBlockNum); - crclen = sizeof(struct unallocSpaceEntry) + - iinfo->i_lenAlloc - sizeof(struct tag); - use->descTag.descCRCLength = cpu_to_le16(crclen); - use->descTag.descCRC = cpu_to_le16(crc_itu_t(0, (char *)use + - sizeof(struct tag), - crclen)); - use->descTag.tagChecksum = udf_tag_checksum(&use->descTag); + crclen = sizeof(struct unallocSpaceEntry); - goto out; + goto finish; } if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_UID_FORGET)) @@ -1782,6 +1774,8 @@ static int udf_update_inode(struct inode *inode, int do_sync) efe->descTag.tagIdent = cpu_to_le16(TAG_IDENT_EFE); crclen = sizeof(struct extendedFileEntry); } + +finish: if (iinfo->i_strat4096) { fe->icbTag.strategyType = cpu_to_le16(4096); fe->icbTag.strategyParameter = cpu_to_le16(1); @@ -1791,7 +1785,9 @@ static int udf_update_inode(struct inode *inode, int do_sync) fe->icbTag.numEntries = cpu_to_le16(1); } - if (S_ISDIR(inode->i_mode)) + if (iinfo->i_use) + fe->icbTag.fileType = ICBTAG_FILE_TYPE_USE; + else if (S_ISDIR(inode->i_mode)) fe->icbTag.fileType = ICBTAG_FILE_TYPE_DIRECTORY; else if (S_ISREG(inode->i_mode)) fe->icbTag.fileType = ICBTAG_FILE_TYPE_REGULAR; @@ -1828,7 +1824,6 @@ static int udf_update_inode(struct inode *inode, int do_sync) crclen)); fe->descTag.tagChecksum = udf_tag_checksum(&fe->descTag); -out: set_buffer_uptodate(bh); unlock_buffer(bh); -- cgit v1.2.3 From 322dfa6402ec08da1ca182ac0061a1cf2c5c3101 Mon Sep 17 00:00:00 2001 From: Yi Zhang Date: Thu, 9 Jul 2015 18:11:31 +0530 Subject: regulator: 88pm800: fix LDO vsel_mask value As per datasheet, Except LDO2, all other LDO's use bit [3:0] for VOUT select. Current code uses wrong mask value of 0x1f, So this patch fixes it to use 0xf. Signed-off-by: Yi Zhang [vaibhav.hiremath@linaro.org: Updated changelog with more detailed description] Signed-off-by: Vaibhav Hiremath Signed-off-by: Mark Brown --- drivers/regulator/88pm800.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/88pm800.c b/drivers/regulator/88pm800.c index 832932bdc977..7fd4f511d78f 100644 --- a/drivers/regulator/88pm800.c +++ b/drivers/regulator/88pm800.c @@ -130,7 +130,7 @@ struct pm800_regulators { .owner = THIS_MODULE, \ .n_voltages = ARRAY_SIZE(ldo_volt_table), \ .vsel_reg = PM800_##vreg##_VOUT, \ - .vsel_mask = 0x1f, \ + .vsel_mask = 0xf, \ .enable_reg = PM800_##ereg, \ .enable_mask = 1 << (ebit), \ .volt_table = ldo_volt_table, \ -- cgit v1.2.3 From 7865598ec24ab4162d976d0bd75a9b2a2f58cd64 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 21 Jun 2015 19:47:46 +0200 Subject: ath9k_hw: fix device ID check for AR956x Because of the missing return, the macVersion value was being overwritten with an invalid register read Signed-off-by: Felix Fietkau Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/hw.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 5e15e8e10ed3..a31a6804dc34 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -279,6 +279,7 @@ static void ath9k_hw_read_revisions(struct ath_hw *ah) return; case AR9300_DEVID_QCA956X: ah->hw_version.macVersion = AR_SREV_VERSION_9561; + return; } val = REG_READ(ah, AR_SREV) & AR_SREV_ID; -- cgit v1.2.3 From f9e5554cd8ca1d1212ec922755b397a20f737923 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 4 Jun 2015 11:09:47 +0300 Subject: iwlwifi: pcie: prepare the device before accessing it For 8000 series, we need to access the device to know what firmware to load. Before we do so, we need to prepare the device otherwise we might not be able to access the hardware. Fixes: c278754a21e6 ("iwlwifi: mvm: support family 8000 B2/C steps") CC: [4.1] Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/pcie/trans.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index fe61d0aa5550..6203c4ad9bba 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c @@ -2551,6 +2551,12 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, trans->hw_rev = (trans->hw_rev & 0xfff0) | (CSR_HW_REV_STEP(trans->hw_rev << 2) << 2); + ret = iwl_pcie_prepare_card_hw(trans); + if (ret) { + IWL_WARN(trans, "Exit HW not ready\n"); + goto out_pci_disable_msi; + } + /* * in-order to recognize C step driver should read chip version * id located at the AUX bus MISC address space. -- cgit v1.2.3 From 00fd233ac491708d1f64b7176be73c84a18a54a2 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 26 Jun 2015 16:04:01 +0200 Subject: iwlwifi: mvm: check time-event vif to avoid bad deletion The time event is initialized relatively late in interface (mvmvif) initialization, so it's possible to fail before that happens. As a consequence, the driver will crash if it ever tries to delete this time event in case initialization was unsuccessful. Avoid this by using the time event's vif pointer to indicate validity. The vif pointer is != NULL whenever the id is != TE_MAX, except for this special error case where the vif pointer will have the correct property (as the whole memory is cleared on allocation) whereas the id is 0, causing a crash in trying to delete the time event from the list. Signed-off-by: Johannes Berg Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/time-event.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.c b/drivers/net/wireless/iwlwifi/mvm/time-event.c index d24b6a83e68c..e472729e5f14 100644 --- a/drivers/net/wireless/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/iwlwifi/mvm/time-event.c @@ -86,7 +86,7 @@ void iwl_mvm_te_clear_data(struct iwl_mvm *mvm, { lockdep_assert_held(&mvm->time_event_lock); - if (te_data->id == TE_MAX) + if (!te_data->vif) return; list_del(&te_data->list); -- cgit v1.2.3 From b8eee757077e2aced778cfad8c1d989e2deec584 Mon Sep 17 00:00:00 2001 From: Oren Givon Date: Mon, 22 Jun 2015 13:44:05 +0300 Subject: iwlwifi: edit the 3165 series and 8000 series PCI IDs Add new 3165 devices support. Add one new 8000 series device support. Remove support for 0x0000, 0xC030 and 0xD030 sub-system IDs in the 8000 series. Signed-off-by: Oren Givon Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/pcie/drv.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c index 2ed1e4d2774d..9f65c1cff1b1 100644 --- a/drivers/net/wireless/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/iwlwifi/pcie/drv.c @@ -368,12 +368,14 @@ static const struct pci_device_id iwl_hw_card_ids[] = { /* 3165 Series */ {IWL_PCI_DEVICE(0x3165, 0x4010, iwl3165_2ac_cfg)}, {IWL_PCI_DEVICE(0x3165, 0x4012, iwl3165_2ac_cfg)}, + {IWL_PCI_DEVICE(0x3166, 0x4212, iwl3165_2ac_cfg)}, {IWL_PCI_DEVICE(0x3165, 0x4410, iwl3165_2ac_cfg)}, {IWL_PCI_DEVICE(0x3165, 0x4510, iwl3165_2ac_cfg)}, {IWL_PCI_DEVICE(0x3165, 0x4110, iwl3165_2ac_cfg)}, {IWL_PCI_DEVICE(0x3166, 0x4310, iwl3165_2ac_cfg)}, {IWL_PCI_DEVICE(0x3166, 0x4210, iwl3165_2ac_cfg)}, {IWL_PCI_DEVICE(0x3165, 0x8010, iwl3165_2ac_cfg)}, + {IWL_PCI_DEVICE(0x3165, 0x8110, iwl3165_2ac_cfg)}, /* 7265 Series */ {IWL_PCI_DEVICE(0x095A, 0x5010, iwl7265_2ac_cfg)}, @@ -426,9 +428,8 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x24F4, 0x1130, iwl8260_2ac_cfg)}, {IWL_PCI_DEVICE(0x24F4, 0x1030, iwl8260_2ac_cfg)}, {IWL_PCI_DEVICE(0x24F3, 0xC010, iwl8260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x24F3, 0xC110, iwl8260_2ac_cfg)}, {IWL_PCI_DEVICE(0x24F3, 0xD010, iwl8260_2ac_cfg)}, - {IWL_PCI_DEVICE(0x24F4, 0xC030, iwl8260_2ac_cfg)}, - {IWL_PCI_DEVICE(0x24F4, 0xD030, iwl8260_2ac_cfg)}, {IWL_PCI_DEVICE(0x24F3, 0xC050, iwl8260_2ac_cfg)}, {IWL_PCI_DEVICE(0x24F3, 0xD050, iwl8260_2ac_cfg)}, {IWL_PCI_DEVICE(0x24F3, 0x8010, iwl8260_2ac_cfg)}, -- cgit v1.2.3 From 8465fe6ac5cc054a7969e78e56aea40cd7808540 Mon Sep 17 00:00:00 2001 From: Avraham Stern Date: Sun, 21 Jun 2015 12:06:13 +0300 Subject: iwlwifi: mvm: Add preemptive flag to scheulded scan Add preemptive flag to scheduled scan command flags. Without this flag, all scan requests after scheduled scan was started will be delayed until scheduled scan stops. As a result, P2P_FIND will be blocked while scheduled scan is active. This flag was omitted during refactoring. Signed-off-by: Avraham Stern Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h | 3 ++- drivers/net/wireless/iwlwifi/mvm/scan.c | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h index 5e4cbdb44c60..737774a01c74 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h @@ -660,7 +660,8 @@ struct iwl_scan_config { * iwl_umac_scan_flags *@IWL_UMAC_SCAN_FLAG_PREEMPTIVE: scan process triggered by this scan request * can be preempted by other scan requests with higher priority. - * The low priority scan is aborted. + * The low priority scan will be resumed when the higher proirity scan is + * completed. *@IWL_UMAC_SCAN_FLAG_START_NOTIF: notification will be sent to the driver * when scan starts. */ diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index 5de144968723..5000bfcded61 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c @@ -1109,6 +1109,9 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif, cmd->uid = cpu_to_le32(uid); cmd->general_flags = cpu_to_le32(iwl_mvm_scan_umac_flags(mvm, params)); + if (type == IWL_MVM_SCAN_SCHED) + cmd->flags = cpu_to_le32(IWL_UMAC_SCAN_FLAG_PREEMPTIVE); + if (iwl_mvm_scan_use_ebs(mvm, vif, n_iterations)) cmd->channel_flags = IWL_SCAN_CHANNEL_FLAG_EBS | IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE | -- cgit v1.2.3 From 255ba06533f09875973d6b400f9c5b88065938df Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sat, 11 Jul 2015 22:30:49 +0300 Subject: Revert "iwlwifi: pcie: New RBD allocation model" This reverts commit 5f17570354f91275b0a37a4da33d29a2ab57d32e. This patch introduced a high latency in buffer allocation under extreme load. This latency caused a firmwre crash. The same scenario works fine with this patch reverted. Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/iwl-fh.h | 6 + drivers/net/wireless/iwlwifi/pcie/internal.h | 51 +--- drivers/net/wireless/iwlwifi/pcie/rx.c | 414 ++++++--------------------- 3 files changed, 97 insertions(+), 374 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-fh.h b/drivers/net/wireless/iwlwifi/iwl-fh.h index d56064861a9c..d45dc021cda2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fh.h +++ b/drivers/net/wireless/iwlwifi/iwl-fh.h @@ -438,6 +438,12 @@ static inline unsigned int FH_MEM_CBBC_QUEUE(unsigned int chnl) #define RX_QUEUE_MASK 255 #define RX_QUEUE_SIZE_LOG 8 +/* + * RX related structures and functions + */ +#define RX_FREE_BUFFERS 64 +#define RX_LOW_WATERMARK 8 + /** * struct iwl_rb_status - reserve buffer status * host memory mapped FH registers diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h index 31f72a61cc3f..376b84e54ad7 100644 --- a/drivers/net/wireless/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/iwlwifi/pcie/internal.h @@ -44,15 +44,6 @@ #include "iwl-io.h" #include "iwl-op-mode.h" -/* - * RX related structures and functions - */ -#define RX_NUM_QUEUES 1 -#define RX_POST_REQ_ALLOC 2 -#define RX_CLAIM_REQ_ALLOC 8 -#define RX_POOL_SIZE ((RX_CLAIM_REQ_ALLOC - RX_POST_REQ_ALLOC) * RX_NUM_QUEUES) -#define RX_LOW_WATERMARK 8 - struct iwl_host_cmd; /*This file includes the declaration that are internal to the @@ -86,29 +77,29 @@ struct isr_statistics { * struct iwl_rxq - Rx queue * @bd: driver's pointer to buffer of receive buffer descriptors (rbd) * @bd_dma: bus address of buffer of receive buffer descriptors (rbd) + * @pool: + * @queue: * @read: Shared index to newest available Rx buffer * @write: Shared index to oldest written Rx packet * @free_count: Number of pre-allocated buffers in rx_free - * @used_count: Number of RBDs handled to allocator to use for allocation * @write_actual: - * @rx_free: list of RBDs with allocated RB ready for use - * @rx_used: list of RBDs with no RB attached + * @rx_free: list of free SKBs for use + * @rx_used: List of Rx buffers with no SKB * @need_update: flag to indicate we need to update read/write index * @rb_stts: driver's pointer to receive buffer status * @rb_stts_dma: bus address of receive buffer status * @lock: - * @pool: initial pool of iwl_rx_mem_buffer for the queue - * @queue: actual rx queue * * NOTE: rx_free and rx_used are used as a FIFO for iwl_rx_mem_buffers */ struct iwl_rxq { __le32 *bd; dma_addr_t bd_dma; + struct iwl_rx_mem_buffer pool[RX_QUEUE_SIZE + RX_FREE_BUFFERS]; + struct iwl_rx_mem_buffer *queue[RX_QUEUE_SIZE]; u32 read; u32 write; u32 free_count; - u32 used_count; u32 write_actual; struct list_head rx_free; struct list_head rx_used; @@ -116,32 +107,6 @@ struct iwl_rxq { struct iwl_rb_status *rb_stts; dma_addr_t rb_stts_dma; spinlock_t lock; - struct iwl_rx_mem_buffer pool[RX_QUEUE_SIZE]; - struct iwl_rx_mem_buffer *queue[RX_QUEUE_SIZE]; -}; - -/** - * struct iwl_rb_allocator - Rx allocator - * @pool: initial pool of allocator - * @req_pending: number of requests the allcator had not processed yet - * @req_ready: number of requests honored and ready for claiming - * @rbd_allocated: RBDs with pages allocated and ready to be handled to - * the queue. This is a list of &struct iwl_rx_mem_buffer - * @rbd_empty: RBDs with no page attached for allocator use. This is a list - * of &struct iwl_rx_mem_buffer - * @lock: protects the rbd_allocated and rbd_empty lists - * @alloc_wq: work queue for background calls - * @rx_alloc: work struct for background calls - */ -struct iwl_rb_allocator { - struct iwl_rx_mem_buffer pool[RX_POOL_SIZE]; - atomic_t req_pending; - atomic_t req_ready; - struct list_head rbd_allocated; - struct list_head rbd_empty; - spinlock_t lock; - struct workqueue_struct *alloc_wq; - struct work_struct rx_alloc; }; struct iwl_dma_ptr { @@ -285,7 +250,7 @@ iwl_pcie_get_scratchbuf_dma(struct iwl_txq *txq, int idx) /** * struct iwl_trans_pcie - PCIe transport specific data * @rxq: all the RX queue data - * @rba: allocator for RX replenishing + * @rx_replenish: work that will be called when buffers need to be allocated * @drv - pointer to iwl_drv * @trans: pointer to the generic transport area * @scd_base_addr: scheduler sram base address in SRAM @@ -308,7 +273,7 @@ iwl_pcie_get_scratchbuf_dma(struct iwl_txq *txq, int idx) */ struct iwl_trans_pcie { struct iwl_rxq rxq; - struct iwl_rb_allocator rba; + struct work_struct rx_replenish; struct iwl_trans *trans; struct iwl_drv *drv; diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c index a3fbaa0ef5e0..adad8d0fae7f 100644 --- a/drivers/net/wireless/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/iwlwifi/pcie/rx.c @@ -1,7 +1,7 @@ /****************************************************************************** * * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. - * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH + * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. @@ -74,29 +74,16 @@ * resets the Rx queue buffers with new memory. * * The management in the driver is as follows: - * + A list of pre-allocated RBDs is stored in iwl->rxq->rx_free. - * When the interrupt handler is called, the request is processed. - * The page is either stolen - transferred to the upper layer - * or reused - added immediately to the iwl->rxq->rx_free list. - * + When the page is stolen - the driver updates the matching queue's used - * count, detaches the RBD and transfers it to the queue used list. - * When there are two used RBDs - they are transferred to the allocator empty - * list. Work is then scheduled for the allocator to start allocating - * eight buffers. - * When there are another 6 used RBDs - they are transferred to the allocator - * empty list and the driver tries to claim the pre-allocated buffers and - * add them to iwl->rxq->rx_free. If it fails - it continues to claim them - * until ready. - * When there are 8+ buffers in the free list - either from allocation or from - * 8 reused unstolen pages - restock is called to update the FW and indexes. - * + In order to make sure the allocator always has RBDs to use for allocation - * the allocator has initial pool in the size of num_queues*(8-2) - the - * maximum missing RBDs per allocation request (request posted with 2 - * empty RBDs, there is no guarantee when the other 6 RBDs are supplied). - * The queues supplies the recycle of the rest of the RBDs. + * + A list of pre-allocated SKBs is stored in iwl->rxq->rx_free. When + * iwl->rxq->free_count drops to or below RX_LOW_WATERMARK, work is scheduled + * to replenish the iwl->rxq->rx_free. + * + In iwl_pcie_rx_replenish (scheduled) if 'processed' != 'read' then the + * iwl->rxq is replenished and the READ INDEX is updated (updating the + * 'processed' and 'read' driver indexes as well) * + A received packet is processed and handed to the kernel network stack, * detached from the iwl->rxq. The driver 'processed' index is updated. - * + If there are no allocated buffers in iwl->rxq->rx_free, + * + The Host/Firmware iwl->rxq is replenished at irq thread time from the + * rx_free list. If there are no allocated buffers in iwl->rxq->rx_free, * the READ INDEX is not incremented and iwl->status(RX_STALLED) is set. * If there were enough free buffers and RX_STALLED is set it is cleared. * @@ -105,32 +92,18 @@ * * iwl_rxq_alloc() Allocates rx_free * iwl_pcie_rx_replenish() Replenishes rx_free list from rx_used, and calls - * iwl_pcie_rxq_restock. - * Used only during initialization. + * iwl_pcie_rxq_restock * iwl_pcie_rxq_restock() Moves available buffers from rx_free into Rx * queue, updates firmware pointers, and updates - * the WRITE index. - * iwl_pcie_rx_allocator() Background work for allocating pages. + * the WRITE index. If insufficient rx_free buffers + * are available, schedules iwl_pcie_rx_replenish * * -- enable interrupts -- * ISR - iwl_rx() Detach iwl_rx_mem_buffers from pool up to the * READ INDEX, detaching the SKB from the pool. * Moves the packet buffer from queue to rx_used. - * Posts and claims requests to the allocator. * Calls iwl_pcie_rxq_restock to refill any empty * slots. - * - * RBD life-cycle: - * - * Init: - * rxq.pool -> rxq.rx_used -> rxq.rx_free -> rxq.queue - * - * Regular Receive interrupt: - * Page Stolen: - * rxq.queue -> rxq.rx_used -> allocator.rbd_empty -> - * allocator.rbd_allocated -> rxq.rx_free -> rxq.queue - * Page not Stolen: - * rxq.queue -> rxq.rx_free -> rxq.queue * ... * */ @@ -267,6 +240,10 @@ static void iwl_pcie_rxq_restock(struct iwl_trans *trans) rxq->free_count--; } spin_unlock(&rxq->lock); + /* If the pre-allocated buffer pool is dropping low, schedule to + * refill it */ + if (rxq->free_count <= RX_LOW_WATERMARK) + schedule_work(&trans_pcie->rx_replenish); /* If we've added more space for the firmware to place data, tell it. * Increment device's write pointer in multiples of 8. */ @@ -277,44 +254,6 @@ static void iwl_pcie_rxq_restock(struct iwl_trans *trans) } } -/* - * iwl_pcie_rx_alloc_page - allocates and returns a page. - * - */ -static struct page *iwl_pcie_rx_alloc_page(struct iwl_trans *trans) -{ - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rxq *rxq = &trans_pcie->rxq; - struct page *page; - gfp_t gfp_mask = GFP_KERNEL; - - if (rxq->free_count > RX_LOW_WATERMARK) - gfp_mask |= __GFP_NOWARN; - - if (trans_pcie->rx_page_order > 0) - gfp_mask |= __GFP_COMP; - - /* Alloc a new receive buffer */ - page = alloc_pages(gfp_mask, trans_pcie->rx_page_order); - if (!page) { - if (net_ratelimit()) - IWL_DEBUG_INFO(trans, "alloc_pages failed, order: %d\n", - trans_pcie->rx_page_order); - /* Issue an error if the hardware has consumed more than half - * of its free buffer list and we don't have enough - * pre-allocated buffers. -` */ - if (rxq->free_count <= RX_LOW_WATERMARK && - iwl_rxq_space(rxq) > (RX_QUEUE_SIZE / 2) && - net_ratelimit()) - IWL_CRIT(trans, - "Failed to alloc_pages with GFP_KERNEL. Only %u free buffers remaining.\n", - rxq->free_count); - return NULL; - } - return page; -} - /* * iwl_pcie_rxq_alloc_rbs - allocate a page for each used RBD * @@ -324,12 +263,13 @@ static struct page *iwl_pcie_rx_alloc_page(struct iwl_trans *trans) * iwl_pcie_rxq_restock. The latter function will update the HW to use the newly * allocated buffers. */ -static void iwl_pcie_rxq_alloc_rbs(struct iwl_trans *trans) +static void iwl_pcie_rxq_alloc_rbs(struct iwl_trans *trans, gfp_t priority) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_rxq *rxq = &trans_pcie->rxq; struct iwl_rx_mem_buffer *rxb; struct page *page; + gfp_t gfp_mask = priority; while (1) { spin_lock(&rxq->lock); @@ -339,10 +279,32 @@ static void iwl_pcie_rxq_alloc_rbs(struct iwl_trans *trans) } spin_unlock(&rxq->lock); + if (rxq->free_count > RX_LOW_WATERMARK) + gfp_mask |= __GFP_NOWARN; + + if (trans_pcie->rx_page_order > 0) + gfp_mask |= __GFP_COMP; + /* Alloc a new receive buffer */ - page = iwl_pcie_rx_alloc_page(trans); - if (!page) + page = alloc_pages(gfp_mask, trans_pcie->rx_page_order); + if (!page) { + if (net_ratelimit()) + IWL_DEBUG_INFO(trans, "alloc_pages failed, " + "order: %d\n", + trans_pcie->rx_page_order); + + if ((rxq->free_count <= RX_LOW_WATERMARK) && + net_ratelimit()) + IWL_CRIT(trans, "Failed to alloc_pages with %s." + "Only %u free buffers remaining.\n", + priority == GFP_ATOMIC ? + "GFP_ATOMIC" : "GFP_KERNEL", + rxq->free_count); + /* We don't reschedule replenish work here -- we will + * call the restock method and if it still needs + * more buffers it will schedule replenish */ return; + } spin_lock(&rxq->lock); @@ -393,7 +355,7 @@ static void iwl_pcie_rxq_free_rbs(struct iwl_trans *trans) lockdep_assert_held(&rxq->lock); - for (i = 0; i < RX_QUEUE_SIZE; i++) { + for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) { if (!rxq->pool[i].page) continue; dma_unmap_page(trans->dev, rxq->pool[i].page_dma, @@ -410,144 +372,32 @@ static void iwl_pcie_rxq_free_rbs(struct iwl_trans *trans) * When moving to rx_free an page is allocated for the slot. * * Also restock the Rx queue via iwl_pcie_rxq_restock. - * This is called only during initialization + * This is called as a scheduled work item (except for during initialization) */ -static void iwl_pcie_rx_replenish(struct iwl_trans *trans) +static void iwl_pcie_rx_replenish(struct iwl_trans *trans, gfp_t gfp) { - iwl_pcie_rxq_alloc_rbs(trans); + iwl_pcie_rxq_alloc_rbs(trans, gfp); iwl_pcie_rxq_restock(trans); } -/* - * iwl_pcie_rx_allocator - Allocates pages in the background for RX queues - * - * Allocates for each received request 8 pages - * Called as a scheduled work item. - */ -static void iwl_pcie_rx_allocator(struct iwl_trans *trans) -{ - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rb_allocator *rba = &trans_pcie->rba; - - while (atomic_read(&rba->req_pending)) { - int i; - struct list_head local_empty; - struct list_head local_allocated; - - INIT_LIST_HEAD(&local_allocated); - spin_lock(&rba->lock); - /* swap out the entire rba->rbd_empty to a local list */ - list_replace_init(&rba->rbd_empty, &local_empty); - spin_unlock(&rba->lock); - - for (i = 0; i < RX_CLAIM_REQ_ALLOC;) { - struct iwl_rx_mem_buffer *rxb; - struct page *page; - - /* List should never be empty - each reused RBD is - * returned to the list, and initial pool covers any - * possible gap between the time the page is allocated - * to the time the RBD is added. - */ - BUG_ON(list_empty(&local_empty)); - /* Get the first rxb from the rbd list */ - rxb = list_first_entry(&local_empty, - struct iwl_rx_mem_buffer, list); - BUG_ON(rxb->page); - - /* Alloc a new receive buffer */ - page = iwl_pcie_rx_alloc_page(trans); - if (!page) - continue; - rxb->page = page; - - /* Get physical address of the RB */ - rxb->page_dma = dma_map_page(trans->dev, page, 0, - PAGE_SIZE << trans_pcie->rx_page_order, - DMA_FROM_DEVICE); - if (dma_mapping_error(trans->dev, rxb->page_dma)) { - rxb->page = NULL; - __free_pages(page, trans_pcie->rx_page_order); - continue; - } - /* dma address must be no more than 36 bits */ - BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36)); - /* and also 256 byte aligned! */ - BUG_ON(rxb->page_dma & DMA_BIT_MASK(8)); - - /* move the allocated entry to the out list */ - list_move(&rxb->list, &local_allocated); - i++; - } - - spin_lock(&rba->lock); - /* add the allocated rbds to the allocator allocated list */ - list_splice_tail(&local_allocated, &rba->rbd_allocated); - /* add the unused rbds back to the allocator empty list */ - list_splice_tail(&local_empty, &rba->rbd_empty); - spin_unlock(&rba->lock); - - atomic_dec(&rba->req_pending); - atomic_inc(&rba->req_ready); - } -} - -/* - * iwl_pcie_rx_allocator_get - Returns the pre-allocated pages -.* -.* Called by queue when the queue posted allocation request and - * has freed 8 RBDs in order to restock itself. - */ -static int iwl_pcie_rx_allocator_get(struct iwl_trans *trans, - struct iwl_rx_mem_buffer - *out[RX_CLAIM_REQ_ALLOC]) -{ - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rb_allocator *rba = &trans_pcie->rba; - int i; - - if (atomic_dec_return(&rba->req_ready) < 0) { - atomic_inc(&rba->req_ready); - IWL_DEBUG_RX(trans, - "Allocation request not ready, pending requests = %d\n", - atomic_read(&rba->req_pending)); - return -ENOMEM; - } - - spin_lock(&rba->lock); - for (i = 0; i < RX_CLAIM_REQ_ALLOC; i++) { - /* Get next free Rx buffer, remove it from free list */ - out[i] = list_first_entry(&rba->rbd_allocated, - struct iwl_rx_mem_buffer, list); - list_del(&out[i]->list); - } - spin_unlock(&rba->lock); - - return 0; -} - -static void iwl_pcie_rx_allocator_work(struct work_struct *data) +static void iwl_pcie_rx_replenish_work(struct work_struct *data) { - struct iwl_rb_allocator *rba_p = - container_of(data, struct iwl_rb_allocator, rx_alloc); struct iwl_trans_pcie *trans_pcie = - container_of(rba_p, struct iwl_trans_pcie, rba); + container_of(data, struct iwl_trans_pcie, rx_replenish); - iwl_pcie_rx_allocator(trans_pcie->trans); + iwl_pcie_rx_replenish(trans_pcie->trans, GFP_KERNEL); } static int iwl_pcie_rx_alloc(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_rxq *rxq = &trans_pcie->rxq; - struct iwl_rb_allocator *rba = &trans_pcie->rba; struct device *dev = trans->dev; memset(&trans_pcie->rxq, 0, sizeof(trans_pcie->rxq)); spin_lock_init(&rxq->lock); - spin_lock_init(&rba->lock); if (WARN_ON(rxq->bd || rxq->rb_stts)) return -EINVAL; @@ -637,49 +487,15 @@ static void iwl_pcie_rx_init_rxb_lists(struct iwl_rxq *rxq) INIT_LIST_HEAD(&rxq->rx_free); INIT_LIST_HEAD(&rxq->rx_used); rxq->free_count = 0; - rxq->used_count = 0; - for (i = 0; i < RX_QUEUE_SIZE; i++) + for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) list_add(&rxq->pool[i].list, &rxq->rx_used); } -static void iwl_pcie_rx_init_rba(struct iwl_rb_allocator *rba) -{ - int i; - - lockdep_assert_held(&rba->lock); - - INIT_LIST_HEAD(&rba->rbd_allocated); - INIT_LIST_HEAD(&rba->rbd_empty); - - for (i = 0; i < RX_POOL_SIZE; i++) - list_add(&rba->pool[i].list, &rba->rbd_empty); -} - -static void iwl_pcie_rx_free_rba(struct iwl_trans *trans) -{ - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rb_allocator *rba = &trans_pcie->rba; - int i; - - lockdep_assert_held(&rba->lock); - - for (i = 0; i < RX_POOL_SIZE; i++) { - if (!rba->pool[i].page) - continue; - dma_unmap_page(trans->dev, rba->pool[i].page_dma, - PAGE_SIZE << trans_pcie->rx_page_order, - DMA_FROM_DEVICE); - __free_pages(rba->pool[i].page, trans_pcie->rx_page_order); - rba->pool[i].page = NULL; - } -} - int iwl_pcie_rx_init(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_rxq *rxq = &trans_pcie->rxq; - struct iwl_rb_allocator *rba = &trans_pcie->rba; int i, err; if (!rxq->bd) { @@ -687,21 +503,11 @@ int iwl_pcie_rx_init(struct iwl_trans *trans) if (err) return err; } - if (!rba->alloc_wq) - rba->alloc_wq = alloc_workqueue("rb_allocator", - WQ_HIGHPRI | WQ_UNBOUND, 1); - INIT_WORK(&rba->rx_alloc, iwl_pcie_rx_allocator_work); - - spin_lock(&rba->lock); - atomic_set(&rba->req_pending, 0); - atomic_set(&rba->req_ready, 0); - /* free all first - we might be reconfigured for a different size */ - iwl_pcie_rx_free_rba(trans); - iwl_pcie_rx_init_rba(rba); - spin_unlock(&rba->lock); spin_lock(&rxq->lock); + INIT_WORK(&trans_pcie->rx_replenish, iwl_pcie_rx_replenish_work); + /* free all first - we might be reconfigured for a different size */ iwl_pcie_rxq_free_rbs(trans); iwl_pcie_rx_init_rxb_lists(rxq); @@ -716,7 +522,7 @@ int iwl_pcie_rx_init(struct iwl_trans *trans) memset(rxq->rb_stts, 0, sizeof(*rxq->rb_stts)); spin_unlock(&rxq->lock); - iwl_pcie_rx_replenish(trans); + iwl_pcie_rx_replenish(trans, GFP_KERNEL); iwl_pcie_rx_hw_init(trans, rxq); @@ -731,7 +537,6 @@ void iwl_pcie_rx_free(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_rxq *rxq = &trans_pcie->rxq; - struct iwl_rb_allocator *rba = &trans_pcie->rba; /*if rxq->bd is NULL, it means that nothing has been allocated, * exit now */ @@ -740,15 +545,7 @@ void iwl_pcie_rx_free(struct iwl_trans *trans) return; } - cancel_work_sync(&rba->rx_alloc); - if (rba->alloc_wq) { - destroy_workqueue(rba->alloc_wq); - rba->alloc_wq = NULL; - } - - spin_lock(&rba->lock); - iwl_pcie_rx_free_rba(trans); - spin_unlock(&rba->lock); + cancel_work_sync(&trans_pcie->rx_replenish); spin_lock(&rxq->lock); iwl_pcie_rxq_free_rbs(trans); @@ -769,43 +566,6 @@ void iwl_pcie_rx_free(struct iwl_trans *trans) rxq->rb_stts = NULL; } -/* - * iwl_pcie_rx_reuse_rbd - Recycle used RBDs - * - * Called when a RBD can be reused. The RBD is transferred to the allocator. - * When there are 2 empty RBDs - a request for allocation is posted - */ -static void iwl_pcie_rx_reuse_rbd(struct iwl_trans *trans, - struct iwl_rx_mem_buffer *rxb, - struct iwl_rxq *rxq) -{ - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rb_allocator *rba = &trans_pcie->rba; - - /* Count the used RBDs */ - rxq->used_count++; - - /* Move the RBD to the used list, will be moved to allocator in batches - * before claiming or posting a request*/ - list_add_tail(&rxb->list, &rxq->rx_used); - - /* If we have RX_POST_REQ_ALLOC new released rx buffers - - * issue a request for allocator. Modulo RX_CLAIM_REQ_ALLOC is - * used for the case we failed to claim RX_CLAIM_REQ_ALLOC, - * after but we still need to post another request. - */ - if ((rxq->used_count % RX_CLAIM_REQ_ALLOC) == RX_POST_REQ_ALLOC) { - /* Move the 2 RBDs to the allocator ownership. - Allocator has another 6 from pool for the request completion*/ - spin_lock(&rba->lock); - list_splice_tail_init(&rxq->rx_used, &rba->rbd_empty); - spin_unlock(&rba->lock); - - atomic_inc(&rba->req_pending); - queue_work(rba->alloc_wq, &rba->rx_alloc); - } -} - static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans, struct iwl_rx_mem_buffer *rxb) { @@ -928,13 +688,13 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans, */ __free_pages(rxb->page, trans_pcie->rx_page_order); rxb->page = NULL; - iwl_pcie_rx_reuse_rbd(trans, rxb, rxq); + list_add_tail(&rxb->list, &rxq->rx_used); } else { list_add_tail(&rxb->list, &rxq->rx_free); rxq->free_count++; } } else - iwl_pcie_rx_reuse_rbd(trans, rxb, rxq); + list_add_tail(&rxb->list, &rxq->rx_used); } /* @@ -944,7 +704,10 @@ static void iwl_pcie_rx_handle(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_rxq *rxq = &trans_pcie->rxq; - u32 r, i, j; + u32 r, i; + u8 fill_rx = 0; + u32 count = 8; + int total_empty; restart: spin_lock(&rxq->lock); @@ -957,6 +720,14 @@ restart: if (i == r) IWL_DEBUG_RX(trans, "HW = SW = %d\n", r); + /* calculate total frames need to be restock after handling RX */ + total_empty = r - rxq->write_actual; + if (total_empty < 0) + total_empty += RX_QUEUE_SIZE; + + if (total_empty > (RX_QUEUE_SIZE / 2)) + fill_rx = 1; + while (i != r) { struct iwl_rx_mem_buffer *rxb; @@ -968,48 +739,29 @@ restart: iwl_pcie_rx_handle_rb(trans, rxb); i = (i + 1) & RX_QUEUE_MASK; - - /* If we have RX_CLAIM_REQ_ALLOC released rx buffers - - * try to claim the pre-allocated buffers from the allocator */ - if (rxq->used_count >= RX_CLAIM_REQ_ALLOC) { - struct iwl_rb_allocator *rba = &trans_pcie->rba; - struct iwl_rx_mem_buffer *out[RX_CLAIM_REQ_ALLOC]; - - /* Add the remaining 6 empty RBDs for allocator use */ - spin_lock(&rba->lock); - list_splice_tail_init(&rxq->rx_used, &rba->rbd_empty); - spin_unlock(&rba->lock); - - /* If not ready - continue, will try to reclaim later. - * No need to reschedule work - allocator exits only on - * success */ - if (!iwl_pcie_rx_allocator_get(trans, out)) { - /* If success - then RX_CLAIM_REQ_ALLOC - * buffers were retrieved and should be added - * to free list */ - rxq->used_count -= RX_CLAIM_REQ_ALLOC; - for (j = 0; j < RX_CLAIM_REQ_ALLOC; j++) { - list_add_tail(&out[j]->list, - &rxq->rx_free); - rxq->free_count++; - } + /* If there are a lot of unused frames, + * restock the Rx queue so ucode wont assert. */ + if (fill_rx) { + count++; + if (count >= 8) { + rxq->read = i; + spin_unlock(&rxq->lock); + iwl_pcie_rx_replenish(trans, GFP_ATOMIC); + count = 0; + goto restart; } } - /* handle restock for two cases: - * - we just pulled buffers from the allocator - * - we have 8+ unstolen pages accumulated */ - if (rxq->free_count >= RX_CLAIM_REQ_ALLOC) { - rxq->read = i; - spin_unlock(&rxq->lock); - iwl_pcie_rxq_restock(trans); - goto restart; - } } /* Backtrack one entry */ rxq->read = i; spin_unlock(&rxq->lock); + if (fill_rx) + iwl_pcie_rx_replenish(trans, GFP_ATOMIC); + else + iwl_pcie_rxq_restock(trans); + if (trans_pcie->napi.poll) napi_gro_flush(&trans_pcie->napi, false); } -- cgit v1.2.3 From be88a1ada9b97bb016196b7f4a1fc2fe2f798529 Mon Sep 17 00:00:00 2001 From: Liad Kaufman Date: Wed, 1 Jul 2015 17:28:34 +0300 Subject: iwlwifi: nvm: remove mac address byte swapping in 8000 family This fixes the byte order copying in the MAO (Mac Override Section) section from the PNVM, as the byte swapping is not required anymore in the 8000 family. Due to the byte swapping, the driver was reporting an incorrect MAC adddress. CC: [4.1] Signed-off-by: Liad Kaufman Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/iwl-nvm-parse.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c index 80fefe7d7b8c..3b8e85e51002 100644 --- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c @@ -540,13 +540,11 @@ static void iwl_set_hw_address_family_8000(struct device *dev, hw_addr = (const u8 *)(mac_override + MAC_ADDRESS_OVERRIDE_FAMILY_8000); - /* The byte order is little endian 16 bit, meaning 214365 */ - data->hw_addr[0] = hw_addr[1]; - data->hw_addr[1] = hw_addr[0]; - data->hw_addr[2] = hw_addr[3]; - data->hw_addr[3] = hw_addr[2]; - data->hw_addr[4] = hw_addr[5]; - data->hw_addr[5] = hw_addr[4]; + /* + * Store the MAC address from MAO section. + * No byte swapping is required in MAO section + */ + memcpy(data->hw_addr, hw_addr, ETH_ALEN); /* * Force the use of the OTP MAC address in case of reserved MAC -- cgit v1.2.3 From ea52bf8eda9832ad30e9f059c5ead8d44f882a53 Mon Sep 17 00:00:00 2001 From: Pierre Morel Date: Thu, 9 Jul 2015 14:58:26 +0200 Subject: 9p/trans_virtio: reset virtio device on remove On device shutdown/removal, virtio drivers need to trigger a reset on the device; if this is neglected, the virtio core will complain about non-zero device status. This patch resets the status when the 9p virtio driver is removed from the system by calling vdev->config->reset on the virtio_device to send a reset to the host virtio device. Signed-off-by: Pierre Morel Reviewed-by: Cornelia Huck Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- net/9p/trans_virtio.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index 9dd49ca67dbc..6e70ddb158b4 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c @@ -704,6 +704,7 @@ static void p9_virtio_remove(struct virtio_device *vdev) mutex_unlock(&virtio_9p_lock); + vdev->config->reset(vdev); vdev->config->del_vqs(vdev); sysfs_remove_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr); -- cgit v1.2.3 From 4de7255f7d2be5e51664c6ac6011ffd6e5463571 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Wed, 1 Jul 2015 11:07:09 +0200 Subject: vhost: extend memory regions allocation to vmalloc with large number of memory regions we could end up with high order allocations and kmalloc could fail if host is under memory pressure. Considering that memory regions array is used on hot path try harder to allocate using kmalloc and if it fails resort to vmalloc. It's still better than just failing vhost_set_memory() and causing guest crash due to it when a new memory hotplugged to guest. I'll still look at QEMU side solution to reduce amount of memory regions it feeds to vhost to make things even better, but it doesn't hurt for kernel to behave smarter and don't crash older QEMU's which could use large amount of memory regions. Signed-off-by: Igor Mammedov Signed-off-by: Michael S. Tsirkin --- drivers/vhost/vhost.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 71bb46813031..a4ac369f6adb 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -544,7 +545,7 @@ void vhost_dev_cleanup(struct vhost_dev *dev, bool locked) fput(dev->log_file); dev->log_file = NULL; /* No one will access memory at this point */ - kfree(dev->memory); + kvfree(dev->memory); dev->memory = NULL; WARN_ON(!list_empty(&dev->work_list)); if (dev->worker) { @@ -674,6 +675,18 @@ static int vhost_memory_reg_sort_cmp(const void *p1, const void *p2) return 0; } +static void *vhost_kvzalloc(unsigned long size) +{ + void *n = kzalloc(size, GFP_KERNEL | __GFP_NOWARN | __GFP_REPEAT); + + if (!n) { + n = vzalloc(size); + if (!n) + return ERR_PTR(-ENOMEM); + } + return n; +} + static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m) { struct vhost_memory mem, *newmem, *oldmem; @@ -686,7 +699,7 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m) return -EOPNOTSUPP; if (mem.nregions > VHOST_MEMORY_MAX_NREGIONS) return -E2BIG; - newmem = kmalloc(size + mem.nregions * sizeof *m->regions, GFP_KERNEL); + newmem = vhost_kvzalloc(size + mem.nregions * sizeof(*m->regions)); if (!newmem) return -ENOMEM; @@ -700,7 +713,7 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m) vhost_memory_reg_sort_cmp, NULL); if (!memory_access_ok(d, newmem, 0)) { - kfree(newmem); + kvfree(newmem); return -EFAULT; } oldmem = d->memory; @@ -712,7 +725,7 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m) d->vqs[i]->memory = newmem; mutex_unlock(&d->vqs[i]->mutex); } - kfree(oldmem); + kvfree(oldmem); return 0; } -- cgit v1.2.3 From c9ce42f72fd0ba180fd35539829e4139dca31494 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Thu, 2 Jul 2015 15:08:11 +0200 Subject: vhost: add max_mem_regions module parameter it became possible to use a bigger amount of memory slots, which is used by memory hotplug for registering hotplugged memory. However QEMU crashes if it's used with more than ~60 pc-dimm devices and vhost-net enabled since host kernel in module vhost-net refuses to accept more than 64 memory regions. Allow to tweak limit via max_mem_regions module paramemter with default value set to 64 slots. Signed-off-by: Igor Mammedov Signed-off-by: Michael S. Tsirkin --- drivers/vhost/vhost.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index a4ac369f6adb..a9fe859f43c8 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -30,8 +30,12 @@ #include "vhost.h" +static ushort max_mem_regions = 64; +module_param(max_mem_regions, ushort, 0444); +MODULE_PARM_DESC(max_mem_regions, + "Maximum number of memory regions in memory map. (default: 64)"); + enum { - VHOST_MEMORY_MAX_NREGIONS = 64, VHOST_MEMORY_F_LOG = 0x1, }; @@ -697,7 +701,7 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m) return -EFAULT; if (mem.padding) return -EOPNOTSUPP; - if (mem.nregions > VHOST_MEMORY_MAX_NREGIONS) + if (mem.nregions > max_mem_regions) return -E2BIG; newmem = vhost_kvzalloc(size + mem.nregions * sizeof(*m->regions)); if (!newmem) -- cgit v1.2.3 From 7bee8b08c428b63aa4a3765bb907602e36355378 Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Tue, 14 Jul 2015 16:25:30 -0400 Subject: Bluetooth: btbcm: allow btbcm_read_verbose_config to fail on Apple Commit 1c8ba6d013 moved around the setup code for broadcomm chips, and also added btbcm_read_verbose_config() to read extra information about the hardware. It's returning errors on some macbooks: Bluetooth: hci0: BCM: Read verbose config info failed (-16) Which makes us error out of the setup function. Since this probe isn't critical to operate the chip, this patch just changes things to carry on when it fails. Signed-off-by: Chris Mason Signed-off-by: Marcel Holtmann Cc: stable@vger.kernel.org # v4.1 --- drivers/bluetooth/btbcm.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/bluetooth/btbcm.c b/drivers/bluetooth/btbcm.c index 1e1a4323a71f..9ceb8ac68fdc 100644 --- a/drivers/bluetooth/btbcm.c +++ b/drivers/bluetooth/btbcm.c @@ -472,12 +472,11 @@ int btbcm_setup_apple(struct hci_dev *hdev) /* Read Verbose Config Version Info */ skb = btbcm_read_verbose_config(hdev); - if (IS_ERR(skb)) - return PTR_ERR(skb); - - BT_INFO("%s: BCM: chip id %u build %4.4u", hdev->name, skb->data[1], - get_unaligned_le16(skb->data + 5)); - kfree_skb(skb); + if (!IS_ERR(skb)) { + BT_INFO("%s: BCM: chip id %u build %4.4u", hdev->name, skb->data[1], + get_unaligned_le16(skb->data + 5)); + kfree_skb(skb); + } set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); -- cgit v1.2.3 From 945b47441d83d2392ac9f984e0267ad521f24268 Mon Sep 17 00:00:00 2001 From: Lior Amsalem Date: Tue, 30 Jun 2015 16:09:49 +0200 Subject: ata: pmp: add quirk for Marvell 4140 SATA PMP This commit adds the necessary quirk to make the Marvell 4140 SATA PMP work properly. This PMP doesn't like SRST on port number 4 (the host port) so this commit marks this port as not supporting SRST. Signed-off-by: Lior Amsalem Reviewed-by: Nadav Haklai Signed-off-by: Thomas Petazzoni Signed-off-by: Tejun Heo Cc: stable@vger.kernel.org --- drivers/ata/libata-pmp.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c index 7ccc084bf1df..85aa76116a30 100644 --- a/drivers/ata/libata-pmp.c +++ b/drivers/ata/libata-pmp.c @@ -460,6 +460,13 @@ static void sata_pmp_quirks(struct ata_port *ap) ATA_LFLAG_NO_SRST | ATA_LFLAG_ASSUME_ATA; } + } else if (vendor == 0x11ab && devid == 0x4140) { + /* Marvell 4140 quirks */ + ata_for_each_link(link, ap, EDGE) { + /* port 4 is for SEMB device and it doesn't like SRST */ + if (link->pmp == 4) + link->flags |= ATA_LFLAG_DISABLED; + } } } -- cgit v1.2.3 From 08c85d2a599d967ede38a847f5594447b6100642 Mon Sep 17 00:00:00 2001 From: Aleksei Mamlin Date: Wed, 1 Jul 2015 13:48:30 +0300 Subject: libata: add ATA_HORKAGE_BROKEN_FPDMA_AA quirk for HP 250GB SATA disk VB0250EAVER Enabling AA on HP 250GB SATA disk VB0250EAVER causes errors: [ 3.788362] ata3.00: failed to enable AA (error_mask=0x1) [ 3.789243] ata3.00: failed to enable AA (error_mask=0x1) Add the ATA_HORKAGE_BROKEN_FPDMA_AA for this specific harddisk. tj: Collected FPDMA_AA entries and updated comment. Signed-off-by: Aleksei Mamlin Signed-off-by: Tejun Heo Cc: stable@vger.kernel.org --- drivers/ata/libata-core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index e83fc3d0da9c..58a6db8f0833 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4174,9 +4174,10 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { { "ST3320[68]13AS", "SD1[5-9]", ATA_HORKAGE_NONCQ | ATA_HORKAGE_FIRMWARE_WARN }, - /* Seagate Momentus SpinPoint M8 seem to have FPMDA_AA issues */ + /* drives which fail FPDMA_AA activation (some may freeze afterwards) */ { "ST1000LM024 HN-M101MBB", "2AR10001", ATA_HORKAGE_BROKEN_FPDMA_AA }, { "ST1000LM024 HN-M101MBB", "2BA30001", ATA_HORKAGE_BROKEN_FPDMA_AA }, + { "VB0250EAVER", "HPG7", ATA_HORKAGE_BROKEN_FPDMA_AA }, /* Blacklist entries taken from Silicon Image 3124/3132 Windows driver .inf file - also several Linux problem reports */ -- cgit v1.2.3 From 50c2e4dd6749725338621fff456b26d3a592259f Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sun, 12 Jul 2015 01:20:55 +0300 Subject: net/xen-netback: off by one in BUG_ON() condition The > should be >=. I also added spaces around the '-' operations so the code is a little more consistent and matches the condition better. Fixes: f53c3fe8dad7 ('xen-netback: Introduce TX grant mapping') Signed-off-by: Dan Carpenter Signed-off-by: David S. Miller --- drivers/net/xen-netback/netback.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index 880d0d63e872..7d50711476fe 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -1566,13 +1566,13 @@ static inline void xenvif_tx_dealloc_action(struct xenvif_queue *queue) smp_rmb(); while (dc != dp) { - BUG_ON(gop - queue->tx_unmap_ops > MAX_PENDING_REQS); + BUG_ON(gop - queue->tx_unmap_ops >= MAX_PENDING_REQS); pending_idx = queue->dealloc_ring[pending_index(dc++)]; - pending_idx_release[gop-queue->tx_unmap_ops] = + pending_idx_release[gop - queue->tx_unmap_ops] = pending_idx; - queue->pages_to_unmap[gop-queue->tx_unmap_ops] = + queue->pages_to_unmap[gop - queue->tx_unmap_ops] = queue->mmap_pages[pending_idx]; gnttab_set_unmap_op(gop, idx_to_kaddr(queue, pending_idx), -- cgit v1.2.3 From 6ae3673debfbf2cfa1972b6d00b974d0e10ad3c6 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Sat, 11 Jul 2015 21:03:07 +0200 Subject: can: at91_can: don't touch skb after netif_receive_skb()/netif_rx() There is no guarantee that the skb is in the same state after calling net_receive_skb() or netif_rx(). It might be freed or reused. Not really harmful as its a read access, except you turn on the proper debugging options which catch a use after free. Signed-off-by: Marc Kleine-Budde --- drivers/net/can/at91_can.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c index f4e40aa4d2a2..945c0955a967 100644 --- a/drivers/net/can/at91_can.c +++ b/drivers/net/can/at91_can.c @@ -577,10 +577,10 @@ static void at91_rx_overflow_err(struct net_device *dev) cf->can_id |= CAN_ERR_CRTL; cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW; - netif_receive_skb(skb); stats->rx_packets++; stats->rx_bytes += cf->can_dlc; + netif_receive_skb(skb); } /** @@ -642,10 +642,10 @@ static void at91_read_msg(struct net_device *dev, unsigned int mb) } at91_read_mb(dev, mb, cf); - netif_receive_skb(skb); stats->rx_packets++; stats->rx_bytes += cf->can_dlc; + netif_receive_skb(skb); can_led_event(dev, CAN_LED_EVENT_RX); } @@ -802,10 +802,10 @@ static int at91_poll_err(struct net_device *dev, int quota, u32 reg_sr) return 0; at91_poll_err_frame(dev, cf, reg_sr); - netif_receive_skb(skb); dev->stats.rx_packets++; dev->stats.rx_bytes += cf->can_dlc; + netif_receive_skb(skb); return 1; } @@ -1067,10 +1067,10 @@ static void at91_irq_err(struct net_device *dev) return; at91_irq_err_state(dev, cf, new_state); - netif_rx(skb); dev->stats.rx_packets++; dev->stats.rx_bytes += cf->can_dlc; + netif_rx(skb); priv->can.state = new_state; } -- cgit v1.2.3 From a18ec1b6c72eb87fe00e8e09c3a3f3cfbec3435b Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Fri, 8 May 2015 11:30:29 +0200 Subject: can: flexcan: don't touch skb after netif_receive_skb() There is no guarantee that the skb is in the same state after calling net_receive_skb() or netif_rx(). It might be freed or reused. Not really harmful as its a read access, except you turn on the proper debugging options which catch a use after free. Signed-off-by: Marc Kleine-Budde --- drivers/net/can/flexcan.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 6201c5a1a884..b1e8d729851c 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -577,10 +577,10 @@ static int flexcan_poll_bus_err(struct net_device *dev, u32 reg_esr) return 0; do_bus_err(dev, cf, reg_esr); - netif_receive_skb(skb); dev->stats.rx_packets++; dev->stats.rx_bytes += cf->can_dlc; + netif_receive_skb(skb); return 1; } @@ -622,10 +622,9 @@ static int flexcan_poll_state(struct net_device *dev, u32 reg_esr) if (unlikely(new_state == CAN_STATE_BUS_OFF)) can_bus_off(dev); - netif_receive_skb(skb); - dev->stats.rx_packets++; dev->stats.rx_bytes += cf->can_dlc; + netif_receive_skb(skb); return 1; } @@ -670,10 +669,10 @@ static int flexcan_read_frame(struct net_device *dev) } flexcan_read_fifo(dev, cf); - netif_receive_skb(skb); stats->rx_packets++; stats->rx_bytes += cf->can_dlc; + netif_receive_skb(skb); can_led_event(dev, CAN_LED_EVENT_RX); -- cgit v1.2.3 From 20926d79244de4e9c698ae429fdc1e7e5832b081 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Sat, 11 Jul 2015 21:16:08 +0200 Subject: can: bfin_can: don't touch skb after netif_rx() There is no guarantee that the skb is in the same state after calling net_receive_skb() or netif_rx(). It might be freed or reused. Not really harmful as its a read access, except you turn on the proper debugging options which catch a use after free. Cc: Aaron Wu Signed-off-by: Marc Kleine-Budde --- drivers/net/can/bfin_can.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/net/can/bfin_can.c b/drivers/net/can/bfin_can.c index 27ad312e7abf..57dadd52b428 100644 --- a/drivers/net/can/bfin_can.c +++ b/drivers/net/can/bfin_can.c @@ -424,10 +424,9 @@ static void bfin_can_rx(struct net_device *dev, u16 isrc) cf->data[6 - i] = (6 - i) < cf->can_dlc ? (val >> 8) : 0; } - netif_rx(skb); - stats->rx_packets++; stats->rx_bytes += cf->can_dlc; + netif_rx(skb); } static int bfin_can_err(struct net_device *dev, u16 isrc, u16 status) @@ -508,10 +507,9 @@ static int bfin_can_err(struct net_device *dev, u16 isrc, u16 status) priv->can.state = state; - netif_rx(skb); - stats->rx_packets++; stats->rx_bytes += cf->can_dlc; + netif_rx(skb); return 0; } -- cgit v1.2.3 From 83537b6fd6c3752bcb578d2bd46312d1e2c4a73a Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Sat, 11 Jul 2015 21:16:08 +0200 Subject: can: grcan: don't touch skb after netif_rx() There is no guarantee that the skb is in the same state after calling net_receive_skb() or netif_rx(). It might be freed or reused. Not really harmful as its a read access, except you turn on the proper debugging options which catch a use after free. Cc: Andreas Larsson Signed-off-by: Marc Kleine-Budde --- drivers/net/can/grcan.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/can/grcan.c b/drivers/net/can/grcan.c index e3d7e22a4fa0..db9538d4b358 100644 --- a/drivers/net/can/grcan.c +++ b/drivers/net/can/grcan.c @@ -1216,11 +1216,12 @@ static int grcan_receive(struct net_device *dev, int budget) cf->data[i] = (u8)(slot[j] >> shift); } } - netif_receive_skb(skb); /* Update statistics and read pointer */ stats->rx_packets++; stats->rx_bytes += cf->can_dlc; + netif_receive_skb(skb); + rd = grcan_ring_add(rd, GRCAN_MSG_SIZE, dma->rx.size); } -- cgit v1.2.3 From a2e78cf7a3f562edca4230b188c8832b6214eccd Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Sat, 11 Jul 2015 21:16:08 +0200 Subject: can: slcan: don't touch skb after netif_rx_ni() There is no guarantee that the skb is in the same state after calling net_receive_skb() or netif_rx(). It might be freed or reused. Not really harmful as its a read access, except you turn on the proper debugging options which catch a use after free. Cc: Oliver Hartkopp Signed-off-by: Marc Kleine-Budde --- drivers/net/can/slcan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c index a23a7af8eb9a..9a3f15cb7ef4 100644 --- a/drivers/net/can/slcan.c +++ b/drivers/net/can/slcan.c @@ -218,10 +218,10 @@ static void slc_bump(struct slcan *sl) memcpy(skb_put(skb, sizeof(struct can_frame)), &cf, sizeof(struct can_frame)); - netif_rx_ni(skb); sl->dev->stats.rx_packets++; sl->dev->stats.rx_bytes += cf.can_dlc; + netif_rx_ni(skb); } /* parse tty input stream */ -- cgit v1.2.3 From 05c4456538e9551b8ac47762b21127bf9cf6cc8e Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Sat, 11 Jul 2015 21:16:08 +0200 Subject: can: ti_heccn: don't touch skb after netif_rx() There is no guarantee that the skb is in the same state after calling net_receive_skb() or netif_rx(). It might be freed or reused. Not really harmful as its a read access, except you turn on the proper debugging options which catch a use after free. Cc: Anant Gole Signed-off-by: Marc Kleine-Budde --- drivers/net/can/ti_hecc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c index e95a9e1a889f..cf345cbfe819 100644 --- a/drivers/net/can/ti_hecc.c +++ b/drivers/net/can/ti_hecc.c @@ -747,9 +747,9 @@ static int ti_hecc_error(struct net_device *ndev, int int_status, } } - netif_rx(skb); stats->rx_packets++; stats->rx_bytes += cf->can_dlc; + netif_rx(skb); return 0; } -- cgit v1.2.3 From ef934e89f5e68535c447789b74de42cf389e55de Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Sat, 11 Jul 2015 21:16:08 +0200 Subject: can: cc770: don't touch skb after netif_rx() There is no guarantee that the skb is in the same state after calling net_receive_skb() or netif_rx(). It might be freed or reused. Not really harmful as its a read access, except you turn on the proper debugging options which catch a use after free. Cc: Wolfgang Grandegger Signed-off-by: Marc Kleine-Budde --- drivers/net/can/cc770/cc770.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/can/cc770/cc770.c b/drivers/net/can/cc770/cc770.c index c11d44984036..70a8cbb29e75 100644 --- a/drivers/net/can/cc770/cc770.c +++ b/drivers/net/can/cc770/cc770.c @@ -504,10 +504,10 @@ static void cc770_rx(struct net_device *dev, unsigned int mo, u8 ctrl1) for (i = 0; i < cf->can_dlc; i++) cf->data[i] = cc770_read_reg(priv, msgobj[mo].data[i]); } - netif_rx(skb); stats->rx_packets++; stats->rx_bytes += cf->can_dlc; + netif_rx(skb); } static int cc770_err(struct net_device *dev, u8 status) @@ -584,10 +584,10 @@ static int cc770_err(struct net_device *dev, u8 status) } } - netif_rx(skb); stats->rx_packets++; stats->rx_bytes += cf->can_dlc; + netif_rx(skb); return 0; } -- cgit v1.2.3 From 889dd06e107d816fe63ff65e5dd3466949878439 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Sat, 11 Jul 2015 21:16:08 +0200 Subject: can: sja1000: don't touch skb after netif_rx() There is no guarantee that the skb is in the same state after calling net_receive_skb() or netif_rx(). It might be freed or reused. Not really harmful as its a read access, except you turn on the proper debugging options which catch a use after free. Cc: Wolfgang Grandegger Cc: Oliver Hartkopp Signed-off-by: Marc Kleine-Budde --- drivers/net/can/sja1000/sja1000.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c index 32bd7f451aa4..7b92e911a616 100644 --- a/drivers/net/can/sja1000/sja1000.c +++ b/drivers/net/can/sja1000/sja1000.c @@ -377,10 +377,9 @@ static void sja1000_rx(struct net_device *dev) /* release receive buffer */ sja1000_write_cmdreg(priv, CMD_RRB); - netif_rx(skb); - stats->rx_packets++; stats->rx_bytes += cf->can_dlc; + netif_rx(skb); can_led_event(dev, CAN_LED_EVENT_RX); } @@ -484,10 +483,9 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status) can_bus_off(dev); } - netif_rx(skb); - stats->rx_packets++; stats->rx_bytes += cf->can_dlc; + netif_rx(skb); return 0; } -- cgit v1.2.3 From 296decb6931fca0bbc0bfb26865837d52e287599 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Sat, 11 Jul 2015 21:16:08 +0200 Subject: can: esd_usb2: don't touch skb after netif_rx() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is no guarantee that the skb is in the same state after calling net_receive_skb() or netif_rx(). It might be freed or reused. Not really harmful as its a read access, except you turn on the proper debugging options which catch a use after free. Cc: Thomas Körper Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/esd_usb2.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/net/can/usb/esd_usb2.c b/drivers/net/can/usb/esd_usb2.c index 411c1af92c62..0e5a4493ba4f 100644 --- a/drivers/net/can/usb/esd_usb2.c +++ b/drivers/net/can/usb/esd_usb2.c @@ -301,13 +301,12 @@ static void esd_usb2_rx_event(struct esd_usb2_net_priv *priv, cf->data[7] = rxerr; } - netif_rx(skb); - priv->bec.txerr = txerr; priv->bec.rxerr = rxerr; stats->rx_packets++; stats->rx_bytes += cf->can_dlc; + netif_rx(skb); } } @@ -347,10 +346,9 @@ static void esd_usb2_rx_can_msg(struct esd_usb2_net_priv *priv, cf->data[i] = msg->msg.rx.data[i]; } - netif_rx(skb); - stats->rx_packets++; stats->rx_bytes += cf->can_dlc; + netif_rx(skb); } return; -- cgit v1.2.3 From 43c021e8d6844c4b0f5cc9eda10d232e7b87a456 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Sat, 11 Jul 2015 21:16:08 +0200 Subject: can: ems_usb: don't touch skb after netif_rx() There is no guarantee that the skb is in the same state after calling net_receive_skb() or netif_rx(). It might be freed or reused. Not really harmful as its a read access, except you turn on the proper debugging options which catch a use after free. Cc: Gerhard Uttenthaler Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/ems_usb.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c index 866bac0ae7e9..2d390384ef3b 100644 --- a/drivers/net/can/usb/ems_usb.c +++ b/drivers/net/can/usb/ems_usb.c @@ -324,10 +324,9 @@ static void ems_usb_rx_can_msg(struct ems_usb *dev, struct ems_cpc_msg *msg) cf->data[i] = msg->msg.can_msg.msg[i]; } - netif_rx(skb); - stats->rx_packets++; stats->rx_bytes += cf->can_dlc; + netif_rx(skb); } static void ems_usb_rx_err(struct ems_usb *dev, struct ems_cpc_msg *msg) @@ -400,10 +399,9 @@ static void ems_usb_rx_err(struct ems_usb *dev, struct ems_cpc_msg *msg) stats->rx_errors++; } - netif_rx(skb); - stats->rx_packets++; stats->rx_bytes += cf->can_dlc; + netif_rx(skb); } /* -- cgit v1.2.3 From 9b721a4cefcbdedadbe72b5ec405046c139cf8ad Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Sat, 11 Jul 2015 21:16:08 +0200 Subject: can: usb_8dev: don't touch skb after netif_rx() There is no guarantee that the skb is in the same state after calling net_receive_skb() or netif_rx(). It might be freed or reused. Not really harmful as its a read access, except you turn on the proper debugging options which catch a use after free. Cc: Bernd Krumboeck Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/usb_8dev.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/net/can/usb/usb_8dev.c b/drivers/net/can/usb/usb_8dev.c index dd52c7a4c80d..de95b1ccba3e 100644 --- a/drivers/net/can/usb/usb_8dev.c +++ b/drivers/net/can/usb/usb_8dev.c @@ -461,10 +461,9 @@ static void usb_8dev_rx_err_msg(struct usb_8dev_priv *priv, priv->bec.txerr = txerr; priv->bec.rxerr = rxerr; - netif_rx(skb); - stats->rx_packets++; stats->rx_bytes += cf->can_dlc; + netif_rx(skb); } /* Read data and status frames */ @@ -494,10 +493,9 @@ static void usb_8dev_rx_can_msg(struct usb_8dev_priv *priv, else memcpy(cf->data, msg->data, cf->can_dlc); - netif_rx(skb); - stats->rx_packets++; stats->rx_bytes += cf->can_dlc; + netif_rx(skb); can_led_event(priv->netdev, CAN_LED_EVENT_RX); } else { -- cgit v1.2.3 From 1c0ee046957648106b415df79038e4e62b144c19 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Sat, 11 Jul 2015 21:16:08 +0200 Subject: can: pcan_usb: don't touch skb after netif_rx() There is no guarantee that the skb is in the same state after calling net_receive_skb() or netif_rx(). It might be freed or reused. Not really harmful as its a read access, except you turn on the proper debugging options which catch a use after free. Cc: Stephane Grosjean Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/peak_usb/pcan_usb.c | 7 +++---- drivers/net/can/usb/peak_usb/pcan_usb_pro.c | 4 ++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/net/can/usb/peak_usb/pcan_usb.c b/drivers/net/can/usb/peak_usb/pcan_usb.c index 72427f21edff..6b94007ae052 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb.c @@ -526,9 +526,9 @@ static int pcan_usb_decode_error(struct pcan_usb_msg_context *mc, u8 n, hwts->hwtstamp = timeval_to_ktime(tv); } - netif_rx(skb); mc->netdev->stats.rx_packets++; mc->netdev->stats.rx_bytes += cf->can_dlc; + netif_rx(skb); return 0; } @@ -659,12 +659,11 @@ static int pcan_usb_decode_data(struct pcan_usb_msg_context *mc, u8 status_len) hwts = skb_hwtstamps(skb); hwts->hwtstamp = timeval_to_ktime(tv); - /* push the skb */ - netif_rx(skb); - /* update statistics */ mc->netdev->stats.rx_packets++; mc->netdev->stats.rx_bytes += cf->can_dlc; + /* push the skb */ + netif_rx(skb); return 0; diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c index dec51717635e..7d61b3279798 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c @@ -553,9 +553,9 @@ static int pcan_usb_pro_handle_canmsg(struct pcan_usb_pro_interface *usb_if, hwts = skb_hwtstamps(skb); hwts->hwtstamp = timeval_to_ktime(tv); - netif_rx(skb); netdev->stats.rx_packets++; netdev->stats.rx_bytes += can_frame->can_dlc; + netif_rx(skb); return 0; } @@ -670,9 +670,9 @@ static int pcan_usb_pro_handle_error(struct pcan_usb_pro_interface *usb_if, peak_usb_get_ts_tv(&usb_if->time_ref, le32_to_cpu(er->ts32), &tv); hwts = skb_hwtstamps(skb); hwts->hwtstamp = timeval_to_ktime(tv); - netif_rx(skb); netdev->stats.rx_packets++; netdev->stats.rx_bytes += can_frame->can_dlc; + netif_rx(skb); return 0; } -- cgit v1.2.3 From 9f7e25edb1575a6d2363dc003f9cc09d840657e2 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 14 Jul 2015 11:17:26 +0100 Subject: regulator: core: Handle full constraints systems when resolving supplies When resolving device supplies if we fail to look up the regulator we substitute in the dummy supply instead if the system has fully specified constraints. When resolving supplies for regulators we do not have the equivalent code and instead just directly use the regulator_dev_lookup() result causing spurious failures. This does not affect DT systems since we are able to detect missing mappings directly as part of regulator_dev_lookup() and so have appropriate handling in the DT specific code. Reported-by: Christian Hartmann Signed-off-by: Mark Brown --- drivers/regulator/core.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index c9f72019bd68..bb8528dfad8c 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1381,9 +1381,13 @@ static int regulator_resolve_supply(struct regulator_dev *rdev) } if (!r) { - dev_err(dev, "Failed to resolve %s-supply for %s\n", - rdev->supply_name, rdev->desc->name); - return -EPROBE_DEFER; + if (have_full_constraints()) { + r = dummy_regulator_rdev; + } else { + dev_err(dev, "Failed to resolve %s-supply for %s\n", + rdev->supply_name, rdev->desc->name); + return -EPROBE_DEFER; + } } /* Recursively resolve the supply of the supply */ -- cgit v1.2.3 From 4c62360d7562a20c996836d163259c87d9378120 Mon Sep 17 00:00:00 2001 From: "Luck, Tony" Date: Tue, 30 Jun 2015 15:57:51 -0700 Subject: efi: Handle memory error structures produced based on old versions of standard The memory error record structure includes as its first field a bitmask of which subsequent fields are valid. The allows new fields to be added to the structure while keeping compatibility with older software that parses these records. This mechanism was used between versions 2.2 and 2.3 to add four new fields, growing the size of the structure from 73 bytes to 80. But Linux just added all the new fields so this test: if (gdata->error_data_length >= sizeof(*mem_err)) cper_print_mem(newpfx, mem_err); else goto err_section_too_small; now make Linux complain about old format records being too short. Add a definition for the old format of the structure and use that for the minimum size check. Pass the actual size to cper_print_mem() so it can sanity check the validation_bits field to ensure that if a BIOS using the old format sets bits as if it were new, we won't access fields beyond the end of the structure. Signed-off-by: Tony Luck Cc: Signed-off-by: Matt Fleming --- drivers/firmware/efi/cper.c | 15 ++++++++++++--- include/linux/cper.h | 22 +++++++++++++++++++++- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c index 4fd9961d552e..d42537425438 100644 --- a/drivers/firmware/efi/cper.c +++ b/drivers/firmware/efi/cper.c @@ -305,10 +305,17 @@ const char *cper_mem_err_unpack(struct trace_seq *p, return ret; } -static void cper_print_mem(const char *pfx, const struct cper_sec_mem_err *mem) +static void cper_print_mem(const char *pfx, const struct cper_sec_mem_err *mem, + int len) { struct cper_mem_err_compact cmem; + /* Don't trust UEFI 2.1/2.2 structure with bad validation bits */ + if (len == sizeof(struct cper_sec_mem_err_old) && + (mem->validation_bits & ~(CPER_MEM_VALID_RANK_NUMBER - 1))) { + pr_err(FW_WARN "valid bits set for fields beyond structure\n"); + return; + } if (mem->validation_bits & CPER_MEM_VALID_ERROR_STATUS) printk("%s""error_status: 0x%016llx\n", pfx, mem->error_status); if (mem->validation_bits & CPER_MEM_VALID_PA) @@ -405,8 +412,10 @@ static void cper_estatus_print_section( } else if (!uuid_le_cmp(*sec_type, CPER_SEC_PLATFORM_MEM)) { struct cper_sec_mem_err *mem_err = (void *)(gdata + 1); printk("%s""section_type: memory error\n", newpfx); - if (gdata->error_data_length >= sizeof(*mem_err)) - cper_print_mem(newpfx, mem_err); + if (gdata->error_data_length >= + sizeof(struct cper_sec_mem_err_old)) + cper_print_mem(newpfx, mem_err, + gdata->error_data_length); else goto err_section_too_small; } else if (!uuid_le_cmp(*sec_type, CPER_SEC_PCIE)) { diff --git a/include/linux/cper.h b/include/linux/cper.h index 76abba4b238e..dcacb1a72e26 100644 --- a/include/linux/cper.h +++ b/include/linux/cper.h @@ -340,7 +340,27 @@ struct cper_ia_proc_ctx { __u64 mm_reg_addr; }; -/* Memory Error Section */ +/* Old Memory Error Section UEFI 2.1, 2.2 */ +struct cper_sec_mem_err_old { + __u64 validation_bits; + __u64 error_status; + __u64 physical_addr; + __u64 physical_addr_mask; + __u16 node; + __u16 card; + __u16 module; + __u16 bank; + __u16 device; + __u16 row; + __u16 column; + __u16 bit_pos; + __u64 requestor_id; + __u64 responder_id; + __u64 target_id; + __u8 error_type; +}; + +/* Memory Error Section UEFI >= 2.3 */ struct cper_sec_mem_err { __u64 validation_bits; __u64 error_status; -- cgit v1.2.3 From 0a0830feb2adce8c7234b8c166a32fe9e7616788 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Tue, 2 Jun 2015 12:10:40 +0300 Subject: phy: ti-pipe3: fix suspend Relying on PM-ops for shutting down PHY clocks was a bad idea since the users (e.g. PCIe/SATA) might not have been suspended by then. The main culprit for not shutting down the clocks was the stray pm_runtime_get() call in probe. Fix the whole thing in the right way by getting rid of that pm_runtime_get() call from probe and removing all PM-ops. It is the sole responsibility of the PHY user to properly turn OFF and de-initialize the PHY as part of its suspend routine. As PHY core serializes init/exit we don't need to use a spinlock in this driver. So get rid of it. Signed-off-by: Roger Quadros Signed-off-by: Sekhar Nori Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/phy-ti-pipe3.c | 172 +++++++++++---------------------------------- 1 file changed, 41 insertions(+), 131 deletions(-) diff --git a/drivers/phy/phy-ti-pipe3.c b/drivers/phy/phy-ti-pipe3.c index 53f295c1bab1..3510b81db3fa 100644 --- a/drivers/phy/phy-ti-pipe3.c +++ b/drivers/phy/phy-ti-pipe3.c @@ -28,7 +28,6 @@ #include #include #include -#include #define PLL_STATUS 0x00000004 #define PLL_GO 0x00000008 @@ -83,10 +82,6 @@ struct ti_pipe3 { struct clk *refclk; struct clk *div_clk; struct pipe3_dpll_map *dpll_map; - bool enabled; - spinlock_t lock; /* serialize clock enable/disable */ - /* the below flag is needed specifically for SATA */ - bool refclk_enabled; }; static struct pipe3_dpll_map dpll_map_usb[] = { @@ -137,6 +132,9 @@ static struct pipe3_dpll_params *ti_pipe3_get_dpll_params(struct ti_pipe3 *phy) return NULL; } +static int ti_pipe3_enable_clocks(struct ti_pipe3 *phy); +static void ti_pipe3_disable_clocks(struct ti_pipe3 *phy); + static int ti_pipe3_power_off(struct phy *x) { struct ti_pipe3 *phy = phy_get_drvdata(x); @@ -217,6 +215,7 @@ static int ti_pipe3_init(struct phy *x) u32 val; int ret = 0; + ti_pipe3_enable_clocks(phy); /* * Set pcie_pcs register to 0x96 for proper functioning of phy * as recommended in AM572x TRM SPRUHZ6, section 18.5.2.2, table @@ -250,33 +249,35 @@ static int ti_pipe3_exit(struct phy *x) u32 val; unsigned long timeout; - /* SATA DPLL can't be powered down due to Errata i783 and PCIe - * does not have internal DPLL - */ - if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-sata") || - of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-pcie")) + /* SATA DPLL can't be powered down due to Errata i783 */ + if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-sata")) return 0; - /* Put DPLL in IDLE mode */ - val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2); - val |= PLL_IDLE; - ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val); - - /* wait for LDO and Oscillator to power down */ - timeout = jiffies + msecs_to_jiffies(PLL_IDLE_TIME); - do { - cpu_relax(); - val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS); - if ((val & PLL_TICOPWDN) && (val & PLL_LDOPWDN)) - break; - } while (!time_after(jiffies, timeout)); + /* PCIe doesn't have internal DPLL */ + if (!of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-pcie")) { + /* Put DPLL in IDLE mode */ + val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2); + val |= PLL_IDLE; + ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val); - if (!(val & PLL_TICOPWDN) || !(val & PLL_LDOPWDN)) { - dev_err(phy->dev, "Failed to power down: PLL_STATUS 0x%x\n", - val); - return -EBUSY; + /* wait for LDO and Oscillator to power down */ + timeout = jiffies + msecs_to_jiffies(PLL_IDLE_TIME); + do { + cpu_relax(); + val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS); + if ((val & PLL_TICOPWDN) && (val & PLL_LDOPWDN)) + break; + } while (!time_after(jiffies, timeout)); + + if (!(val & PLL_TICOPWDN) || !(val & PLL_LDOPWDN)) { + dev_err(phy->dev, "Failed to power down: PLL_STATUS 0x%x\n", + val); + return -EBUSY; + } } + ti_pipe3_disable_clocks(phy); + return 0; } static struct phy_ops ops = { @@ -306,7 +307,6 @@ static int ti_pipe3_probe(struct platform_device *pdev) return -ENOMEM; phy->dev = &pdev->dev; - spin_lock_init(&phy->lock); if (!of_device_is_compatible(node, "ti,phy-pipe3-pcie")) { match = of_match_device(ti_pipe3_id_table, &pdev->dev); @@ -402,6 +402,10 @@ static int ti_pipe3_probe(struct platform_device *pdev) platform_set_drvdata(pdev, phy); pm_runtime_enable(phy->dev); + /* Prevent auto-disable of refclk for SATA PHY due to Errata i783 */ + if (of_device_is_compatible(node, "ti,phy-pipe3-sata")) + if (!IS_ERR(phy->refclk)) + clk_prepare_enable(phy->refclk); generic_phy = devm_phy_create(phy->dev, NULL, &ops); if (IS_ERR(generic_phy)) @@ -413,63 +417,33 @@ static int ti_pipe3_probe(struct platform_device *pdev) if (IS_ERR(phy_provider)) return PTR_ERR(phy_provider); - pm_runtime_get(&pdev->dev); - return 0; } static int ti_pipe3_remove(struct platform_device *pdev) { - if (!pm_runtime_suspended(&pdev->dev)) - pm_runtime_put(&pdev->dev); pm_runtime_disable(&pdev->dev); return 0; } -#ifdef CONFIG_PM -static int ti_pipe3_enable_refclk(struct ti_pipe3 *phy) +static int ti_pipe3_enable_clocks(struct ti_pipe3 *phy) { - if (!IS_ERR(phy->refclk) && !phy->refclk_enabled) { - int ret; + int ret = 0; + if (!IS_ERR(phy->refclk)) { ret = clk_prepare_enable(phy->refclk); if (ret) { dev_err(phy->dev, "Failed to enable refclk %d\n", ret); return ret; } - phy->refclk_enabled = true; } - return 0; -} - -static void ti_pipe3_disable_refclk(struct ti_pipe3 *phy) -{ - if (!IS_ERR(phy->refclk)) - clk_disable_unprepare(phy->refclk); - - phy->refclk_enabled = false; -} - -static int ti_pipe3_enable_clocks(struct ti_pipe3 *phy) -{ - int ret = 0; - unsigned long flags; - - spin_lock_irqsave(&phy->lock, flags); - if (phy->enabled) - goto err1; - - ret = ti_pipe3_enable_refclk(phy); - if (ret) - goto err1; - if (!IS_ERR(phy->wkupclk)) { ret = clk_prepare_enable(phy->wkupclk); if (ret) { dev_err(phy->dev, "Failed to enable wkupclk %d\n", ret); - goto err2; + goto disable_refclk; } } @@ -477,96 +451,33 @@ static int ti_pipe3_enable_clocks(struct ti_pipe3 *phy) ret = clk_prepare_enable(phy->div_clk); if (ret) { dev_err(phy->dev, "Failed to enable div_clk %d\n", ret); - goto err3; + goto disable_wkupclk; } } - phy->enabled = true; - spin_unlock_irqrestore(&phy->lock, flags); return 0; -err3: +disable_wkupclk: if (!IS_ERR(phy->wkupclk)) clk_disable_unprepare(phy->wkupclk); -err2: +disable_refclk: if (!IS_ERR(phy->refclk)) clk_disable_unprepare(phy->refclk); - ti_pipe3_disable_refclk(phy); -err1: - spin_unlock_irqrestore(&phy->lock, flags); return ret; } static void ti_pipe3_disable_clocks(struct ti_pipe3 *phy) { - unsigned long flags; - - spin_lock_irqsave(&phy->lock, flags); - if (!phy->enabled) { - spin_unlock_irqrestore(&phy->lock, flags); - return; - } - if (!IS_ERR(phy->wkupclk)) clk_disable_unprepare(phy->wkupclk); - /* Don't disable refclk for SATA PHY due to Errata i783 */ - if (!of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-sata")) - ti_pipe3_disable_refclk(phy); + if (!IS_ERR(phy->refclk)) + clk_disable_unprepare(phy->refclk); if (!IS_ERR(phy->div_clk)) clk_disable_unprepare(phy->div_clk); - phy->enabled = false; - spin_unlock_irqrestore(&phy->lock, flags); -} - -static int ti_pipe3_runtime_suspend(struct device *dev) -{ - struct ti_pipe3 *phy = dev_get_drvdata(dev); - - ti_pipe3_disable_clocks(phy); - return 0; } -static int ti_pipe3_runtime_resume(struct device *dev) -{ - struct ti_pipe3 *phy = dev_get_drvdata(dev); - int ret = 0; - - ret = ti_pipe3_enable_clocks(phy); - return ret; -} - -static int ti_pipe3_suspend(struct device *dev) -{ - struct ti_pipe3 *phy = dev_get_drvdata(dev); - - ti_pipe3_disable_clocks(phy); - return 0; -} - -static int ti_pipe3_resume(struct device *dev) -{ - struct ti_pipe3 *phy = dev_get_drvdata(dev); - int ret; - - ret = ti_pipe3_enable_clocks(phy); - if (ret) - return ret; - - pm_runtime_disable(dev); - pm_runtime_set_active(dev); - pm_runtime_enable(dev); - return 0; -} -#endif - -static const struct dev_pm_ops ti_pipe3_pm_ops = { - SET_RUNTIME_PM_OPS(ti_pipe3_runtime_suspend, - ti_pipe3_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(ti_pipe3_suspend, ti_pipe3_resume) -}; - static const struct of_device_id ti_pipe3_id_table[] = { { .compatible = "ti,phy-usb3", @@ -592,7 +503,6 @@ static struct platform_driver ti_pipe3_driver = { .remove = ti_pipe3_remove, .driver = { .name = "ti-pipe3", - .pm = &ti_pipe3_pm_ops, .of_match_table = ti_pipe3_id_table, }, }; -- cgit v1.2.3 From 1c4b1d1da3d88ec3871459683d0e64fedbce0b16 Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Mon, 29 Jun 2015 16:57:08 +0200 Subject: phy/pxa: add HAS_IOMEM dependency Fix this compile error: drivers/built-in.o: In function 'mv_usb2_phy_probe': phy-pxa-28nm-usb2.c:(.text+0x25ec): undefined reference to 'devm_ioremap_resource' drivers/built-in.o: In function 'mv_hsic_phy_probe': phy-pxa-28nm-hsic.c:(.text+0x3084): undefined reference to 'devm_ioremap_resource' Signed-off-by: Sebastian Ott Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index c0e6ede3e27d..6b8dd162f644 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -56,6 +56,7 @@ config PHY_EXYNOS_MIPI_VIDEO config PHY_PXA_28NM_HSIC tristate "Marvell USB HSIC 28nm PHY Driver" + depends on HAS_IOMEM select GENERIC_PHY help Enable this to support Marvell USB HSIC PHY driver for Marvell @@ -66,6 +67,7 @@ config PHY_PXA_28NM_HSIC config PHY_PXA_28NM_USB2 tristate "Marvell USB 2.0 28nm PHY Driver" + depends on HAS_IOMEM select GENERIC_PHY help Enable this to support Marvell USB 2.0 PHY driver for Marvell -- cgit v1.2.3 From 96696a9df935d15fd2e89603454c20a692ec232a Mon Sep 17 00:00:00 2001 From: Thomas Hebb Date: Thu, 2 Jul 2015 01:04:18 -0400 Subject: phy: berlin-usb: fix divider for BG2CD The marvell,berlin2cd-usb-phy compatible incorrectly sets the PLL divider to BG2's value instead of BG2CD/BG2Q's. Change it to the right value. Signed-off-by: Thomas Hebb Cc: stable@vger.kernel.org Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/phy-berlin-usb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/phy/phy-berlin-usb.c b/drivers/phy/phy-berlin-usb.c index c6fc95b53083..ab54f2864451 100644 --- a/drivers/phy/phy-berlin-usb.c +++ b/drivers/phy/phy-berlin-usb.c @@ -106,8 +106,8 @@ static const u32 phy_berlin_pll_dividers[] = { /* Berlin 2 */ CLK_REF_DIV(0xc) | FEEDBACK_CLK_DIV(0x54), - /* Berlin 2CD */ - CLK_REF_DIV(0x6) | FEEDBACK_CLK_DIV(0x55), + /* Berlin 2CD/Q */ + CLK_REF_DIV(0xc) | FEEDBACK_CLK_DIV(0x54), }; struct phy_berlin_usb_priv { -- cgit v1.2.3 From dcb54fcb3483862e993abdae99cec22fb3ae4099 Mon Sep 17 00:00:00 2001 From: Thomas Hebb Date: Thu, 2 Jul 2015 01:04:26 -0400 Subject: phy: berlin-usb: fix divider for BG2 The USB PLL divider set by the marvell,berlin2-usb-phy compatible is not correct for BG2. We couldn't change it before because BG2Q incorrectly used the same compatible string. Now that BG2Q's compatible is fixed, change BG2's divider to the correct value. Signed-off-by: Thomas Hebb Tested-by: Antoine Tenart Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/phy-berlin-usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/phy/phy-berlin-usb.c b/drivers/phy/phy-berlin-usb.c index ab54f2864451..335e06d66ed9 100644 --- a/drivers/phy/phy-berlin-usb.c +++ b/drivers/phy/phy-berlin-usb.c @@ -105,7 +105,7 @@ static const u32 phy_berlin_pll_dividers[] = { /* Berlin 2 */ - CLK_REF_DIV(0xc) | FEEDBACK_CLK_DIV(0x54), + CLK_REF_DIV(0x6) | FEEDBACK_CLK_DIV(0x55), /* Berlin 2CD/Q */ CLK_REF_DIV(0xc) | FEEDBACK_CLK_DIV(0x54), }; -- cgit v1.2.3 From 71d126fd28de2d4d9b7b2088dbccd7ca62fad6e0 Mon Sep 17 00:00:00 2001 From: Arne Fitzenreiter Date: Wed, 15 Jul 2015 13:54:36 +0200 Subject: libata: add ATA_HORKAGE_NOTRIM Some devices lose data on TRIM whether queued or not. This patch adds a horkage to disable TRIM. tj: Collapsed unnecessary if() nesting. Signed-off-by: Arne Fitzenreiter Signed-off-by: Tejun Heo Cc: stable@vger.kernel.org --- drivers/ata/libata-scsi.c | 3 ++- drivers/ata/libata-transport.c | 2 ++ include/linux/libata.h | 2 ++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 3131adcc1f87..641a61a59e89 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -2568,7 +2568,8 @@ static unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf) rbuf[14] = (lowest_aligned >> 8) & 0x3f; rbuf[15] = lowest_aligned; - if (ata_id_has_trim(args->id)) { + if (ata_id_has_trim(args->id) && + !(dev->horkage & ATA_HORKAGE_NOTRIM)) { rbuf[14] |= 0x80; /* LBPME */ if (ata_id_has_zero_after_trim(args->id) && diff --git a/drivers/ata/libata-transport.c b/drivers/ata/libata-transport.c index d6c37bcd416d..e2d94972962d 100644 --- a/drivers/ata/libata-transport.c +++ b/drivers/ata/libata-transport.c @@ -569,6 +569,8 @@ show_ata_dev_trim(struct device *dev, if (!ata_id_has_trim(ata_dev->id)) mode = "unsupported"; + else if (ata_dev->horkage & ATA_HORKAGE_NOTRIM) + mode = "forced_unsupported"; else if (ata_dev->horkage & ATA_HORKAGE_NO_NCQ_TRIM) mode = "forced_unqueued"; else if (ata_fpdma_dsm_supported(ata_dev)) diff --git a/include/linux/libata.h b/include/linux/libata.h index 36ce37bcc963..5c8bac6225a6 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -431,6 +431,8 @@ enum { ATA_HORKAGE_WD_BROKEN_LPM = (1 << 21), /* some WDs have broken LPM */ ATA_HORKAGE_ZERO_AFTER_TRIM = (1 << 22),/* guarantees zero after trim */ ATA_HORKAGE_NO_NCQ_LOG = (1 << 23), /* don't use NCQ for log read */ + ATA_HORKAGE_NOTRIM = (1 << 24), /* don't use TRIM */ + /* DMA mask for user DMA control: User visible values; DO NOT renumber */ -- cgit v1.2.3 From cda57b1b05cf7b8b99ab4b732bea0b05b6c015cc Mon Sep 17 00:00:00 2001 From: Arne Fitzenreiter Date: Wed, 15 Jul 2015 13:54:37 +0200 Subject: libata: force disable trim for SuperSSpeed S238 This device loses blocks, often the partition table area, on trim. Disable TRIM. http://pcengines.ch/msata16a.htm Signed-off-by: Arne Fitzenreiter Signed-off-by: Tejun Heo Cc: stable@vger.kernel.org --- drivers/ata/libata-core.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 58a6db8f0833..ed2b218ea64d 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4239,6 +4239,9 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { { "Samsung SSD 8*", NULL, ATA_HORKAGE_NO_NCQ_TRIM | ATA_HORKAGE_ZERO_AFTER_TRIM, }, + /* devices that don't properly handle TRIM commands */ + { "SuperSSpeed S238*", NULL, ATA_HORKAGE_NOTRIM, }, + /* * As defined, the DRAT (Deterministic Read After Trim) and RZAT * (Return Zero After Trim) flags in the ATA Command Set are -- cgit v1.2.3 From af34d637637eabaf49406eb35c948cd51ba262a6 Mon Sep 17 00:00:00 2001 From: David Milburn Date: Mon, 13 Jul 2015 11:48:23 -0500 Subject: libata: add ATA_HORKAGE_MAX_SEC_1024 to revert back to previous max_sectors limit Since no longer limiting max_sectors to BLK_DEF_MAX_SECTORS (commit 34b48db66e08), data corruption may occur on ST380013AS drive configured on 82801JI (ICH10 Family) SATA controller. This patch will allow the driver to limit max_sectors as before # cat /sys/block/sdb/queue/max_sectors_kb 512 I was able to double the max_sectors_kb value up to 16384 on linux-4.2.0-rc2 before seeing corruption, but seems safer to use previous limit. Without this patch max_sectors_kb will be 32767. tj: Minor comment update. Reported-by: Jeff Moyer Signed-off-by: David Milburn Signed-off-by: Tejun Heo Cc: stable@vger.kernel.org # v3.19 and later Fixes: 34b48db66e08 ("block: remove artifical max_hw_sectors cap") --- drivers/ata/libata-core.c | 10 ++++++++++ include/linux/ata.h | 1 + include/linux/libata.h | 2 +- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index ed2b218ea64d..68202a8a3a0b 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -2478,6 +2478,10 @@ int ata_dev_configure(struct ata_device *dev) dev->max_sectors = min_t(unsigned int, ATA_MAX_SECTORS_128, dev->max_sectors); + if (dev->horkage & ATA_HORKAGE_MAX_SEC_1024) + dev->max_sectors = min_t(unsigned int, ATA_MAX_SECTORS_1024, + dev->max_sectors); + if (dev->horkage & ATA_HORKAGE_MAX_SEC_LBA48) dev->max_sectors = ATA_MAX_SECTORS_LBA48; @@ -4146,6 +4150,12 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { { "Slimtype DVD A DS8A8SH", NULL, ATA_HORKAGE_MAX_SEC_LBA48 }, { "Slimtype DVD A DS8A9SH", NULL, ATA_HORKAGE_MAX_SEC_LBA48 }, + /* + * Causes silent data corruption with higher max sects. + * http://lkml.kernel.org/g/x49wpy40ysk.fsf@segfault.boston.devel.redhat.com + */ + { "ST380013AS", "3.20", ATA_HORKAGE_MAX_SEC_1024 }, + /* Devices we expect to fail diagnostics */ /* Devices where NCQ should be avoided */ diff --git a/include/linux/ata.h b/include/linux/ata.h index fed36418dd1c..6c78956aa470 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -45,6 +45,7 @@ enum { ATA_SECT_SIZE = 512, ATA_MAX_SECTORS_128 = 128, ATA_MAX_SECTORS = 256, + ATA_MAX_SECTORS_1024 = 1024, ATA_MAX_SECTORS_LBA48 = 65535,/* TODO: 65536? */ ATA_MAX_SECTORS_TAPE = 65535, diff --git a/include/linux/libata.h b/include/linux/libata.h index 5c8bac6225a6..c9cfbcdb8d14 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -432,7 +432,7 @@ enum { ATA_HORKAGE_ZERO_AFTER_TRIM = (1 << 22),/* guarantees zero after trim */ ATA_HORKAGE_NO_NCQ_LOG = (1 << 23), /* don't use NCQ for log read */ ATA_HORKAGE_NOTRIM = (1 << 24), /* don't use TRIM */ - + ATA_HORKAGE_MAX_SEC_1024 = (1 << 25), /* Limit max sects to 1024 */ /* DMA mask for user DMA control: User visible values; DO NOT renumber */ -- cgit v1.2.3 From d531be2ca2f27cca5f041b6a140504999144a617 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Wed, 8 Jul 2015 13:06:12 -0400 Subject: libata: increase the timeout when setting transfer mode I have a ST4000DM000 disk. If Linux is booted while the disk is spun down, the command that sets transfer mode causes the disk to spin up. The spin-up takes longer than the default 5s timeout, so the command fails and timeout is reported. Fix this by increasing the timeout to 15s, which is enough for the disk to spin up. Signed-off-by: Mikulas Patocka Cc: stable@vger.kernel.org Signed-off-by: Tejun Heo --- drivers/ata/libata-core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 68202a8a3a0b..12b176a10d57 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4515,7 +4515,8 @@ static unsigned int ata_dev_set_xfermode(struct ata_device *dev) else /* In the ancient relic department - skip all of this */ return 0; - err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0); + /* On some disks, this command causes spin-up, so we need longer timeout */ + err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 15000); DPRINTK("EXIT, err_mask=%x\n", err_mask); return err_mask; -- cgit v1.2.3 From 035d210f928ce083435b4fd351a26d126c02c927 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Mon, 13 Jul 2015 00:06:02 +0200 Subject: rtnetlink: reject non-IFLA_VF_PORT attributes inside IFLA_VF_PORTS Similarly as in commit 4f7d2cdfdde7 ("rtnetlink: verify IFLA_VF_INFO attributes before passing them to driver"), we have a double nesting of netlink attributes, i.e. IFLA_VF_PORTS only contains IFLA_VF_PORT that is nested itself. While IFLA_VF_PORTS is a verified attribute from ifla_policy[], we only check if the IFLA_VF_PORTS container has IFLA_VF_PORT attributes and then pass the attribute's content itself via nla_parse_nested(). It would be more correct to reject inner types other than IFLA_VF_PORT instead of continuing parsing and also similarly as in commit 4f7d2cdfdde7, to check for a minimum of NLA_HDRLEN. Signed-off-by: Daniel Borkmann Cc: Roopa Prabhu Cc: Scott Feldman Cc: Jason Gunthorpe Acked-by: Roopa Prabhu Signed-off-by: David S. Miller --- net/core/rtnetlink.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 9e433d58d265..dc004b1e1f85 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1804,10 +1804,13 @@ static int do_setlink(const struct sk_buff *skb, goto errout; nla_for_each_nested(attr, tb[IFLA_VF_PORTS], rem) { - if (nla_type(attr) != IFLA_VF_PORT) - continue; - err = nla_parse_nested(port, IFLA_PORT_MAX, - attr, ifla_port_policy); + if (nla_type(attr) != IFLA_VF_PORT || + nla_len(attr) < NLA_HDRLEN) { + err = -EINVAL; + goto errout; + } + err = nla_parse_nested(port, IFLA_PORT_MAX, attr, + ifla_port_policy); if (err < 0) goto errout; if (!port[IFLA_PORT_VF]) { -- cgit v1.2.3 From 738ac1ebb96d02e0d23bc320302a6ea94c612dec Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Mon, 13 Jul 2015 16:04:13 +0800 Subject: net: Clone skb before setting peeked flag Shared skbs must not be modified and this is crucial for broadcast and/or multicast paths where we use it as an optimisation to avoid unnecessary cloning. The function skb_recv_datagram breaks this rule by setting peeked without cloning the skb first. This causes funky races which leads to double-free. This patch fixes this by cloning the skb and replacing the skb in the list when setting skb->peeked. Fixes: a59322be07c9 ("[UDP]: Only increment counter on first peek/recv") Reported-by: Konstantin Khlebnikov Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/core/datagram.c | 41 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/net/core/datagram.c b/net/core/datagram.c index b80fb91bb3f7..4e9a3f690b7e 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c @@ -131,6 +131,35 @@ out_noerr: goto out; } +static int skb_set_peeked(struct sk_buff *skb) +{ + struct sk_buff *nskb; + + if (skb->peeked) + return 0; + + /* We have to unshare an skb before modifying it. */ + if (!skb_shared(skb)) + goto done; + + nskb = skb_clone(skb, GFP_ATOMIC); + if (!nskb) + return -ENOMEM; + + skb->prev->next = nskb; + skb->next->prev = nskb; + nskb->prev = skb->prev; + nskb->next = skb->next; + + consume_skb(skb); + skb = nskb; + +done: + skb->peeked = 1; + + return 0; +} + /** * __skb_recv_datagram - Receive a datagram skbuff * @sk: socket @@ -165,7 +194,9 @@ out_noerr: struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned int flags, int *peeked, int *off, int *err) { + struct sk_buff_head *queue = &sk->sk_receive_queue; struct sk_buff *skb, *last; + unsigned long cpu_flags; long timeo; /* * Caller is allowed not to check sk->sk_err before skb_recv_datagram() @@ -184,8 +215,6 @@ struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned int flags, * Look at current nfs client by the way... * However, this function was correct in any case. 8) */ - unsigned long cpu_flags; - struct sk_buff_head *queue = &sk->sk_receive_queue; int _off = *off; last = (struct sk_buff *)queue; @@ -199,7 +228,11 @@ struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned int flags, _off -= skb->len; continue; } - skb->peeked = 1; + + error = skb_set_peeked(skb); + if (error) + goto unlock_err; + atomic_inc(&skb->users); } else __skb_unlink(skb, queue); @@ -223,6 +256,8 @@ struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned int flags, return NULL; +unlock_err: + spin_unlock_irqrestore(&queue->lock, cpu_flags); no_packet: *err = error; return NULL; -- cgit v1.2.3 From da278622bf04f8ddb14519a2b8214e108ef26101 Mon Sep 17 00:00:00 2001 From: Richard Stearn Date: Mon, 13 Jul 2015 11:38:24 +0200 Subject: NET: AX.25: Stop heartbeat timer on disconnect. This may result in a kernel panic. The bug has always existed but somehow we've run out of luck now and it bites. Signed-off-by: Richard Stearn Cc: stable@vger.kernel.org # all branches Signed-off-by: Ralf Baechle Signed-off-by: David S. Miller --- net/ax25/ax25_subr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/ax25/ax25_subr.c b/net/ax25/ax25_subr.c index 1997538a5d23..3b78e8473a01 100644 --- a/net/ax25/ax25_subr.c +++ b/net/ax25/ax25_subr.c @@ -264,6 +264,7 @@ void ax25_disconnect(ax25_cb *ax25, int reason) { ax25_clear_queues(ax25); + ax25_stop_heartbeat(ax25); ax25_stop_t1timer(ax25); ax25_stop_t2timer(ax25); ax25_stop_t3timer(ax25); -- cgit v1.2.3 From c9805b9986ed88b7df1b14ea7d538d83f2149cf5 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 13 Jul 2015 08:13:52 -0300 Subject: Revert "net: fec: Ensure clocks are enabled while using mdio bus" This reverts commit 6c3e921b18edca290099adfddde8a50236bf2d80. commit 6c3e921b18ed ("net: fec: Ensure clocks are enabled while using mdio bus") prevents the kernel to boot on mx6 boards, so let's revert it. Reported-by: Tyler Baker Signed-off-by: Fabio Estevam Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fec_main.c | 88 +++++-------------------------- 1 file changed, 13 insertions(+), 75 deletions(-) diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 42e20e5385ac..1f89c59b4353 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include @@ -78,7 +77,6 @@ static void fec_enet_itr_coal_init(struct net_device *ndev); #define FEC_ENET_RAEM_V 0x8 #define FEC_ENET_RAFL_V 0x8 #define FEC_ENET_OPD_V 0xFFF0 -#define FEC_MDIO_PM_TIMEOUT 100 /* ms */ static struct platform_device_id fec_devtype[] = { { @@ -1769,13 +1767,7 @@ static void fec_enet_adjust_link(struct net_device *ndev) static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum) { struct fec_enet_private *fep = bus->priv; - struct device *dev = &fep->pdev->dev; unsigned long time_left; - int ret = 0; - - ret = pm_runtime_get_sync(dev); - if (IS_ERR_VALUE(ret)) - return ret; fep->mii_timeout = 0; init_completion(&fep->mdio_done); @@ -1791,30 +1783,18 @@ static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum) if (time_left == 0) { fep->mii_timeout = 1; netdev_err(fep->netdev, "MDIO read timeout\n"); - ret = -ETIMEDOUT; - goto out; + return -ETIMEDOUT; } - ret = FEC_MMFR_DATA(readl(fep->hwp + FEC_MII_DATA)); - -out: - pm_runtime_mark_last_busy(dev); - pm_runtime_put_autosuspend(dev); - - return ret; + /* return value */ + return FEC_MMFR_DATA(readl(fep->hwp + FEC_MII_DATA)); } static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value) { struct fec_enet_private *fep = bus->priv; - struct device *dev = &fep->pdev->dev; unsigned long time_left; - int ret = 0; - - ret = pm_runtime_get_sync(dev); - if (IS_ERR_VALUE(ret)) - return ret; fep->mii_timeout = 0; init_completion(&fep->mdio_done); @@ -1831,13 +1811,10 @@ static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum, if (time_left == 0) { fep->mii_timeout = 1; netdev_err(fep->netdev, "MDIO write timeout\n"); - ret = -ETIMEDOUT; + return -ETIMEDOUT; } - pm_runtime_mark_last_busy(dev); - pm_runtime_put_autosuspend(dev); - - return ret; + return 0; } static int fec_enet_clk_enable(struct net_device *ndev, bool enable) @@ -1849,6 +1826,9 @@ static int fec_enet_clk_enable(struct net_device *ndev, bool enable) ret = clk_prepare_enable(fep->clk_ahb); if (ret) return ret; + ret = clk_prepare_enable(fep->clk_ipg); + if (ret) + goto failed_clk_ipg; if (fep->clk_enet_out) { ret = clk_prepare_enable(fep->clk_enet_out); if (ret) @@ -1872,6 +1852,7 @@ static int fec_enet_clk_enable(struct net_device *ndev, bool enable) } } else { clk_disable_unprepare(fep->clk_ahb); + clk_disable_unprepare(fep->clk_ipg); if (fep->clk_enet_out) clk_disable_unprepare(fep->clk_enet_out); if (fep->clk_ptp) { @@ -1893,6 +1874,8 @@ failed_clk_ptp: if (fep->clk_enet_out) clk_disable_unprepare(fep->clk_enet_out); failed_clk_enet_out: + clk_disable_unprepare(fep->clk_ipg); +failed_clk_ipg: clk_disable_unprepare(fep->clk_ahb); return ret; @@ -2864,14 +2847,10 @@ fec_enet_open(struct net_device *ndev) struct fec_enet_private *fep = netdev_priv(ndev); int ret; - ret = pm_runtime_get_sync(&fep->pdev->dev); - if (IS_ERR_VALUE(ret)) - return ret; - pinctrl_pm_select_default_state(&fep->pdev->dev); ret = fec_enet_clk_enable(ndev, true); if (ret) - goto clk_enable; + return ret; /* I should reset the ring buffers here, but I don't yet know * a simple way to do that. @@ -2902,9 +2881,6 @@ err_enet_mii_probe: fec_enet_free_buffers(ndev); err_enet_alloc: fec_enet_clk_enable(ndev, false); -clk_enable: - pm_runtime_mark_last_busy(&fep->pdev->dev); - pm_runtime_put_autosuspend(&fep->pdev->dev); pinctrl_pm_select_sleep_state(&fep->pdev->dev); return ret; } @@ -2927,9 +2903,6 @@ fec_enet_close(struct net_device *ndev) fec_enet_clk_enable(ndev, false); pinctrl_pm_select_sleep_state(&fep->pdev->dev); - pm_runtime_mark_last_busy(&fep->pdev->dev); - pm_runtime_put_autosuspend(&fep->pdev->dev); - fec_enet_free_buffers(ndev); return 0; @@ -3415,10 +3388,6 @@ fec_probe(struct platform_device *pdev) if (ret) goto failed_clk; - ret = clk_prepare_enable(fep->clk_ipg); - if (ret) - goto failed_clk_ipg; - fep->reg_phy = devm_regulator_get(&pdev->dev, "phy"); if (!IS_ERR(fep->reg_phy)) { ret = regulator_enable(fep->reg_phy); @@ -3465,8 +3434,6 @@ fec_probe(struct platform_device *pdev) netif_carrier_off(ndev); fec_enet_clk_enable(ndev, false); pinctrl_pm_select_sleep_state(&pdev->dev); - pm_runtime_set_active(&pdev->dev); - pm_runtime_enable(&pdev->dev); ret = register_netdev(ndev); if (ret) @@ -3480,12 +3447,6 @@ fec_probe(struct platform_device *pdev) fep->rx_copybreak = COPYBREAK_DEFAULT; INIT_WORK(&fep->tx_timeout_work, fec_enet_timeout_work); - - pm_runtime_set_autosuspend_delay(&pdev->dev, FEC_MDIO_PM_TIMEOUT); - pm_runtime_use_autosuspend(&pdev->dev); - pm_runtime_mark_last_busy(&pdev->dev); - pm_runtime_put_autosuspend(&pdev->dev); - return 0; failed_register: @@ -3496,8 +3457,6 @@ failed_init: if (fep->reg_phy) regulator_disable(fep->reg_phy); failed_regulator: - clk_disable_unprepare(fep->clk_ipg); -failed_clk_ipg: fec_enet_clk_enable(ndev, false); failed_clk: failed_phy: @@ -3609,28 +3568,7 @@ failed_clk: return ret; } -static int __maybe_unused fec_runtime_suspend(struct device *dev) -{ - struct net_device *ndev = dev_get_drvdata(dev); - struct fec_enet_private *fep = netdev_priv(ndev); - - clk_disable_unprepare(fep->clk_ipg); - - return 0; -} - -static int __maybe_unused fec_runtime_resume(struct device *dev) -{ - struct net_device *ndev = dev_get_drvdata(dev); - struct fec_enet_private *fep = netdev_priv(ndev); - - return clk_prepare_enable(fep->clk_ipg); -} - -static const struct dev_pm_ops fec_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(fec_suspend, fec_resume) - SET_RUNTIME_PM_OPS(fec_runtime_suspend, fec_runtime_resume, NULL) -}; +static SIMPLE_DEV_PM_OPS(fec_pm_ops, fec_suspend, fec_resume); static struct platform_driver fec_driver = { .driver = { -- cgit v1.2.3 From 89c22d8c3b278212eef6a8cc66b570bc840a6f5a Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Mon, 13 Jul 2015 20:01:42 +0800 Subject: net: Fix skb csum races when peeking When we calculate the checksum on the recv path, we store the result in the skb as an optimisation in case we need the checksum again down the line. This is in fact bogus for the MSG_PEEK case as this is done without any locking. So multiple threads can peek and then store the result to the same skb, potentially resulting in bogus skb states. This patch fixes this by only storing the result if the skb is not shared. This preserves the optimisations for the few cases where it can be done safely due to locking or other reasons, e.g., SIOCINQ. Signed-off-by: Herbert Xu Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- net/core/datagram.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/net/core/datagram.c b/net/core/datagram.c index 4e9a3f690b7e..4967262b2707 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c @@ -657,7 +657,8 @@ __sum16 __skb_checksum_complete_head(struct sk_buff *skb, int len) !skb->csum_complete_sw) netdev_rx_csum_fault(skb->dev); } - skb->csum_valid = !sum; + if (!skb_shared(skb)) + skb->csum_valid = !sum; return sum; } EXPORT_SYMBOL(__skb_checksum_complete_head); @@ -677,11 +678,13 @@ __sum16 __skb_checksum_complete(struct sk_buff *skb) netdev_rx_csum_fault(skb->dev); } - /* Save full packet checksum */ - skb->csum = csum; - skb->ip_summed = CHECKSUM_COMPLETE; - skb->csum_complete_sw = 1; - skb->csum_valid = !sum; + if (!skb_shared(skb)) { + /* Save full packet checksum */ + skb->csum = csum; + skb->ip_summed = CHECKSUM_COMPLETE; + skb->csum_complete_sw = 1; + skb->csum_valid = !sum; + } return sum; } -- cgit v1.2.3 From bc8c20acaea154efc558f5f4122ed65d396f6156 Mon Sep 17 00:00:00 2001 From: Satish Ashok Date: Mon, 13 Jul 2015 05:28:37 -0700 Subject: bridge: multicast: treat igmpv3 report with INCLUDE and no sources as a leave A report with INCLUDE/Change_to_include and empty source list should be treated as a leave, specified by RFC 3376, section 3.1: "If the requested filter mode is INCLUDE *and* the requested source list is empty, then the entry corresponding to the requested interface and multicast address is deleted if present. If no such entry is present, the request is ignored." Signed-off-by: Satish Ashok Signed-off-by: Nikolay Aleksandrov Signed-off-by: David S. Miller --- net/bridge/br_multicast.c | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 742a6c27d7a2..79db489cdade 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -39,6 +39,16 @@ static void br_multicast_start_querier(struct net_bridge *br, struct bridge_mcast_own_query *query); static void br_multicast_add_router(struct net_bridge *br, struct net_bridge_port *port); +static void br_ip4_multicast_leave_group(struct net_bridge *br, + struct net_bridge_port *port, + __be32 group, + __u16 vid); +#if IS_ENABLED(CONFIG_IPV6) +static void br_ip6_multicast_leave_group(struct net_bridge *br, + struct net_bridge_port *port, + const struct in6_addr *group, + __u16 vid); +#endif unsigned int br_mdb_rehash_seq; static inline int br_ip_equal(const struct br_ip *a, const struct br_ip *b) @@ -1010,9 +1020,15 @@ static int br_ip4_multicast_igmp3_report(struct net_bridge *br, continue; } - err = br_ip4_multicast_add_group(br, port, group, vid); - if (err) - break; + if ((type == IGMPV3_CHANGE_TO_INCLUDE || + type == IGMPV3_MODE_IS_INCLUDE) && + ntohs(grec->grec_nsrcs) == 0) { + br_ip4_multicast_leave_group(br, port, group, vid); + } else { + err = br_ip4_multicast_add_group(br, port, group, vid); + if (err) + break; + } } return err; @@ -1071,10 +1087,17 @@ static int br_ip6_multicast_mld2_report(struct net_bridge *br, continue; } - err = br_ip6_multicast_add_group(br, port, &grec->grec_mca, - vid); - if (err) - break; + if ((grec->grec_type == MLD2_CHANGE_TO_INCLUDE || + grec->grec_type == MLD2_MODE_IS_INCLUDE) && + ntohs(*nsrcs) == 0) { + br_ip6_multicast_leave_group(br, port, &grec->grec_mca, + vid); + } else { + err = br_ip6_multicast_add_group(br, port, + &grec->grec_mca, vid); + if (!err) + break; + } } return err; -- cgit v1.2.3 From 5ebc784625ea68a9570d1f70557e7932988cd1b4 Mon Sep 17 00:00:00 2001 From: Nikolay Aleksandrov Date: Mon, 13 Jul 2015 06:36:19 -0700 Subject: bridge: mdb: fix double add notification Since the mdb add/del code was introduced there have been 2 br_mdb_notify calls when doing br_mdb_add() resulting in 2 notifications on each add. Example: Command: bridge mdb add dev br0 port eth1 grp 239.0.0.1 permanent Before patch: root@debian:~# bridge monitor all [MDB]dev br0 port eth1 grp 239.0.0.1 permanent [MDB]dev br0 port eth1 grp 239.0.0.1 permanent After patch: root@debian:~# bridge monitor all [MDB]dev br0 port eth1 grp 239.0.0.1 permanent Signed-off-by: Nikolay Aleksandrov Fixes: cfd567543590 ("bridge: add support of adding and deleting mdb entries") Signed-off-by: David S. Miller --- net/bridge/br_mdb.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c index c11cf2611db0..1198a3dbad95 100644 --- a/net/bridge/br_mdb.c +++ b/net/bridge/br_mdb.c @@ -351,7 +351,6 @@ static int br_mdb_add_group(struct net_bridge *br, struct net_bridge_port *port, if (state == MDB_TEMPORARY) mod_timer(&p->timer, now + br->multicast_membership_interval); - br_mdb_notify(br->dev, port, group, RTM_NEWMDB); return 0; } -- cgit v1.2.3 From f82b681a511f4d61069e9586a9cf97bdef371ef3 Mon Sep 17 00:00:00 2001 From: Yuchung Cheng Date: Mon, 13 Jul 2015 12:10:20 -0700 Subject: tcp: don't use F-RTO on non-recurring timeouts Currently F-RTO may repeatedly send new data packets on non-recurring timeouts in CA_Loss mode. This is a bug because F-RTO (RFC5682) should only be used on either new recovery or recurring timeouts. This exacerbates the recovery progress during frequent timeout & repair, because we prioritize sending new data packets instead of repairing the holes when the bandwidth is already scarce. Fix it by correcting the test of a new recovery episode. Signed-off-by: Yuchung Cheng Signed-off-by: Neal Cardwell Signed-off-by: David S. Miller --- net/ipv4/tcp_input.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 684f095d196e..728f5b3d3c64 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -1917,14 +1917,13 @@ void tcp_enter_loss(struct sock *sk) const struct inet_connection_sock *icsk = inet_csk(sk); struct tcp_sock *tp = tcp_sk(sk); struct sk_buff *skb; - bool new_recovery = false; + bool new_recovery = icsk->icsk_ca_state < TCP_CA_Recovery; bool is_reneg; /* is receiver reneging on SACKs? */ /* Reduce ssthresh if it has not yet been made inside this window. */ if (icsk->icsk_ca_state <= TCP_CA_Disorder || !after(tp->high_seq, tp->snd_una) || (icsk->icsk_ca_state == TCP_CA_Loss && !icsk->icsk_retransmits)) { - new_recovery = true; tp->prior_ssthresh = tcp_current_ssthresh(sk); tp->snd_ssthresh = icsk->icsk_ca_ops->ssthresh(sk); tcp_ca_event(sk, CA_EVENT_LOSS); -- cgit v1.2.3 From 052cbda41fdc243a8d40cce7ab3a6327b4b2887e Mon Sep 17 00:00:00 2001 From: WANG Cong Date: Mon, 13 Jul 2015 12:30:07 -0700 Subject: fq_codel: fix a use-after-free Fixes: 25331d6ce42b ("net: sched: implement qstat helper routines") Cc: John Fastabend Signed-off-by: Cong Wang Signed-off-by: Cong Wang Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- net/sched/sch_fq_codel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sched/sch_fq_codel.c b/net/sched/sch_fq_codel.c index d75993f89fac..06e7c845e24d 100644 --- a/net/sched/sch_fq_codel.c +++ b/net/sched/sch_fq_codel.c @@ -155,10 +155,10 @@ static unsigned int fq_codel_drop(struct Qdisc *sch) skb = dequeue_head(flow); len = qdisc_pkt_len(skb); q->backlogs[idx] -= len; - kfree_skb(skb); sch->q.qlen--; qdisc_qstats_drop(sch); qdisc_qstats_backlog_dec(sch, skb); + kfree_skb(skb); flow->dropped++; return idx; } -- cgit v1.2.3 From fd98e9419d8d622a4de91f76b306af6aa627aa9c Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Tue, 14 Jul 2015 00:37:13 +0200 Subject: isdn/gigaset: reset tty->receive_room when attaching ser_gigaset Commit 79901317ce80 ("n_tty: Don't flush buffer when closing ldisc"), first merged in kernel release 3.10, caused the following regression in the Gigaset M101 driver: Before that commit, when closing the N_TTY line discipline in preparation to switching to N_GIGASET_M101, receive_room would be reset to a non-zero value by the call to n_tty_flush_buffer() in n_tty's close method. With the removal of that call, receive_room might be left at zero, blocking data reception on the serial line. The present patch fixes that regression by setting receive_room to an appropriate value in the ldisc open method. Fixes: 79901317ce80 ("n_tty: Don't flush buffer when closing ldisc") Signed-off-by: Tilman Schmidt Signed-off-by: David S. Miller --- drivers/isdn/gigaset/ser-gigaset.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/isdn/gigaset/ser-gigaset.c b/drivers/isdn/gigaset/ser-gigaset.c index 8c91fd5eb6fd..3ac9c4194814 100644 --- a/drivers/isdn/gigaset/ser-gigaset.c +++ b/drivers/isdn/gigaset/ser-gigaset.c @@ -524,9 +524,18 @@ gigaset_tty_open(struct tty_struct *tty) cs->hw.ser->tty = tty; atomic_set(&cs->hw.ser->refcnt, 1); init_completion(&cs->hw.ser->dead_cmp); - tty->disc_data = cs; + /* Set the amount of data we're willing to receive per call + * from the hardware driver to half of the input buffer size + * to leave some reserve. + * Note: We don't do flow control towards the hardware driver. + * If more data is received than will fit into the input buffer, + * it will be dropped and an error will be logged. This should + * never happen as the device is slow and the buffer size ample. + */ + tty->receive_room = RBUFSIZE/2; + /* OK.. Initialization of the datastructures and the HW is done.. Now * startup system and notify the LL that we are ready to run */ -- cgit v1.2.3 From 62c13bad39211387afd4354e8e127a535d13e70d Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Tue, 14 Jul 2015 00:37:13 +0200 Subject: isdn/gigaset: drop unused ldisc methods The line discipline read and write methods are optional so the dummy methods in ser_gigaset are unnecessary and can be removed. Signed-off-by: Tilman Schmidt Signed-off-by: David S. Miller --- drivers/isdn/gigaset/ser-gigaset.c | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/drivers/isdn/gigaset/ser-gigaset.c b/drivers/isdn/gigaset/ser-gigaset.c index 3ac9c4194814..375be509e95f 100644 --- a/drivers/isdn/gigaset/ser-gigaset.c +++ b/drivers/isdn/gigaset/ser-gigaset.c @@ -606,28 +606,6 @@ static int gigaset_tty_hangup(struct tty_struct *tty) return 0; } -/* - * Read on the tty. - * Unused, received data goes only to the Gigaset driver. - */ -static ssize_t -gigaset_tty_read(struct tty_struct *tty, struct file *file, - unsigned char __user *buf, size_t count) -{ - return -EAGAIN; -} - -/* - * Write on the tty. - * Unused, transmit data comes only from the Gigaset driver. - */ -static ssize_t -gigaset_tty_write(struct tty_struct *tty, struct file *file, - const unsigned char *buf, size_t count) -{ - return -EAGAIN; -} - /* * Ioctl on the tty. * Called in process context only. @@ -761,8 +739,6 @@ static struct tty_ldisc_ops gigaset_ldisc = { .open = gigaset_tty_open, .close = gigaset_tty_close, .hangup = gigaset_tty_hangup, - .read = gigaset_tty_read, - .write = gigaset_tty_write, .ioctl = gigaset_tty_ioctl, .receive_buf = gigaset_tty_receive, .write_wakeup = gigaset_tty_wakeup, -- cgit v1.2.3 From 03645a11a570d52e70631838cb786eb4253eb463 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 14 Jul 2015 08:10:22 +0200 Subject: ipv6: lock socket in ip6_datagram_connect() ip6_datagram_connect() is doing a lot of socket changes without socket being locked. This looks wrong, at least for udp_lib_rehash() which could corrupt lists because of concurrent udp_sk(sk)->udp_portaddr_hash accesses. Signed-off-by: Eric Dumazet Acked-by: Herbert Xu Signed-off-by: David S. Miller --- include/net/ip.h | 1 + net/ipv4/datagram.c | 16 ++++++++++++---- net/ipv6/datagram.c | 20 +++++++++++++++----- 3 files changed, 28 insertions(+), 9 deletions(-) diff --git a/include/net/ip.h b/include/net/ip.h index 0750a186ea63..d5fe9f2ab699 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -161,6 +161,7 @@ static inline __u8 get_rtconn_flags(struct ipcm_cookie* ipc, struct sock* sk) } /* datagram.c */ +int __ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len); int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len); void ip4_datagram_release_cb(struct sock *sk); diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c index 90c0e8386116..574fad9cca05 100644 --- a/net/ipv4/datagram.c +++ b/net/ipv4/datagram.c @@ -20,7 +20,7 @@ #include #include -int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) +int __ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) { struct inet_sock *inet = inet_sk(sk); struct sockaddr_in *usin = (struct sockaddr_in *) uaddr; @@ -39,8 +39,6 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) sk_dst_reset(sk); - lock_sock(sk); - oif = sk->sk_bound_dev_if; saddr = inet->inet_saddr; if (ipv4_is_multicast(usin->sin_addr.s_addr)) { @@ -82,9 +80,19 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) sk_dst_set(sk, &rt->dst); err = 0; out: - release_sock(sk); return err; } +EXPORT_SYMBOL(__ip4_datagram_connect); + +int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) +{ + int res; + + lock_sock(sk); + res = __ip4_datagram_connect(sk, uaddr, addr_len); + release_sock(sk); + return res; +} EXPORT_SYMBOL(ip4_datagram_connect); /* Because UDP xmit path can manipulate sk_dst_cache without holding diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 62d908e64eeb..b10a88986a98 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c @@ -40,7 +40,7 @@ static bool ipv6_mapped_addr_any(const struct in6_addr *a) return ipv6_addr_v4mapped(a) && (a->s6_addr32[3] == 0); } -int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) +static int __ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) { struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr; struct inet_sock *inet = inet_sk(sk); @@ -56,7 +56,7 @@ int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) if (usin->sin6_family == AF_INET) { if (__ipv6_only_sock(sk)) return -EAFNOSUPPORT; - err = ip4_datagram_connect(sk, uaddr, addr_len); + err = __ip4_datagram_connect(sk, uaddr, addr_len); goto ipv4_connected; } @@ -98,9 +98,9 @@ int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) sin.sin_addr.s_addr = daddr->s6_addr32[3]; sin.sin_port = usin->sin6_port; - err = ip4_datagram_connect(sk, - (struct sockaddr *) &sin, - sizeof(sin)); + err = __ip4_datagram_connect(sk, + (struct sockaddr *) &sin, + sizeof(sin)); ipv4_connected: if (err) @@ -204,6 +204,16 @@ out: fl6_sock_release(flowlabel); return err; } + +int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) +{ + int res; + + lock_sock(sk); + res = __ip6_datagram_connect(sk, uaddr, addr_len); + release_sock(sk); + return res; +} EXPORT_SYMBOL_GPL(ip6_datagram_connect); int ip6_datagram_connect_v6_only(struct sock *sk, struct sockaddr *uaddr, -- cgit v1.2.3 From 515866f8185b92fb18a782408c53839f003c7669 Mon Sep 17 00:00:00 2001 From: Konstantin Khlebnikov Date: Tue, 14 Jul 2015 16:35:50 +0300 Subject: ipvlan: remove counters of ipv4 and ipv6 addresses They are unused after commit f631c44bbe15 ("ipvlan: Always set broadcast bit in multicast filter"). Signed-off-by: Konstantin Khlebnikov Signed-off-by: David S. Miller --- drivers/net/ipvlan/ipvlan.h | 2 -- drivers/net/ipvlan/ipvlan_main.c | 33 ++++++++++++--------------------- 2 files changed, 12 insertions(+), 23 deletions(-) diff --git a/drivers/net/ipvlan/ipvlan.h b/drivers/net/ipvlan/ipvlan.h index 953a97492fab..68e2549c28c6 100644 --- a/drivers/net/ipvlan/ipvlan.h +++ b/drivers/net/ipvlan/ipvlan.h @@ -67,8 +67,6 @@ struct ipvl_dev { struct ipvl_port *port; struct net_device *phy_dev; struct list_head addrs; - int ipv4cnt; - int ipv6cnt; struct ipvl_pcpu_stats __percpu *pcpu_stats; DECLARE_BITMAP(mac_filters, IPVLAN_MAC_FILTER_SIZE); netdev_features_t sfeatures; diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c index 1acc283160d9..048ecf0c76fb 100644 --- a/drivers/net/ipvlan/ipvlan_main.c +++ b/drivers/net/ipvlan/ipvlan_main.c @@ -153,10 +153,9 @@ static int ipvlan_open(struct net_device *dev) else dev->flags &= ~IFF_NOARP; - if (ipvlan->ipv6cnt > 0 || ipvlan->ipv4cnt > 0) { - list_for_each_entry(addr, &ipvlan->addrs, anode) - ipvlan_ht_addr_add(ipvlan, addr); - } + list_for_each_entry(addr, &ipvlan->addrs, anode) + ipvlan_ht_addr_add(ipvlan, addr); + return dev_uc_add(phy_dev, phy_dev->dev_addr); } @@ -171,10 +170,9 @@ static int ipvlan_stop(struct net_device *dev) dev_uc_del(phy_dev, phy_dev->dev_addr); - if (ipvlan->ipv6cnt > 0 || ipvlan->ipv4cnt > 0) { - list_for_each_entry(addr, &ipvlan->addrs, anode) - ipvlan_ht_addr_del(addr, !dev->dismantle); - } + list_for_each_entry(addr, &ipvlan->addrs, anode) + ipvlan_ht_addr_del(addr, !dev->dismantle); + return 0; } @@ -471,8 +469,6 @@ static int ipvlan_link_new(struct net *src_net, struct net_device *dev, ipvlan->port = port; ipvlan->sfeatures = IPVLAN_FEATURES; INIT_LIST_HEAD(&ipvlan->addrs); - ipvlan->ipv4cnt = 0; - ipvlan->ipv6cnt = 0; /* TODO Probably put random address here to be presented to the * world but keep using the physical-dev address for the outgoing @@ -508,12 +504,11 @@ static void ipvlan_link_delete(struct net_device *dev, struct list_head *head) struct ipvl_dev *ipvlan = netdev_priv(dev); struct ipvl_addr *addr, *next; - if (ipvlan->ipv6cnt > 0 || ipvlan->ipv4cnt > 0) { - list_for_each_entry_safe(addr, next, &ipvlan->addrs, anode) { - ipvlan_ht_addr_del(addr, !dev->dismantle); - list_del(&addr->anode); - } + list_for_each_entry_safe(addr, next, &ipvlan->addrs, anode) { + ipvlan_ht_addr_del(addr, !dev->dismantle); + list_del(&addr->anode); } + list_del_rcu(&ipvlan->pnode); unregister_netdevice_queue(dev, head); netdev_upper_dev_unlink(ipvlan->phy_dev, dev); @@ -627,7 +622,7 @@ static int ipvlan_add_addr6(struct ipvl_dev *ipvlan, struct in6_addr *ip6_addr) memcpy(&addr->ip6addr, ip6_addr, sizeof(struct in6_addr)); addr->atype = IPVL_IPV6; list_add_tail(&addr->anode, &ipvlan->addrs); - ipvlan->ipv6cnt++; + /* If the interface is not up, the address will be added to the hash * list by ipvlan_open. */ @@ -647,8 +642,6 @@ static void ipvlan_del_addr6(struct ipvl_dev *ipvlan, struct in6_addr *ip6_addr) ipvlan_ht_addr_del(addr, true); list_del(&addr->anode); - ipvlan->ipv6cnt--; - WARN_ON(ipvlan->ipv6cnt < 0); kfree_rcu(addr, rcu); return; @@ -699,7 +692,7 @@ static int ipvlan_add_addr4(struct ipvl_dev *ipvlan, struct in_addr *ip4_addr) memcpy(&addr->ip4addr, ip4_addr, sizeof(struct in_addr)); addr->atype = IPVL_IPV4; list_add_tail(&addr->anode, &ipvlan->addrs); - ipvlan->ipv4cnt++; + /* If the interface is not up, the address will be added to the hash * list by ipvlan_open. */ @@ -719,8 +712,6 @@ static void ipvlan_del_addr4(struct ipvl_dev *ipvlan, struct in_addr *ip4_addr) ipvlan_ht_addr_del(addr, true); list_del(&addr->anode); - ipvlan->ipv4cnt--; - WARN_ON(ipvlan->ipv4cnt < 0); kfree_rcu(addr, rcu); return; -- cgit v1.2.3 From 6a725497318545aae246232ed05a8df9cffb0a02 Mon Sep 17 00:00:00 2001 From: Konstantin Khlebnikov Date: Tue, 14 Jul 2015 16:35:51 +0300 Subject: ipvlan: plug memory leak in ipvlan_link_delete Add missing kfree_rcu(addr, rcu); Signed-off-by: Konstantin Khlebnikov Signed-off-by: David S. Miller --- drivers/net/ipvlan/ipvlan_main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c index 048ecf0c76fb..7d81e37c3f76 100644 --- a/drivers/net/ipvlan/ipvlan_main.c +++ b/drivers/net/ipvlan/ipvlan_main.c @@ -507,6 +507,7 @@ static void ipvlan_link_delete(struct net_device *dev, struct list_head *head) list_for_each_entry_safe(addr, next, &ipvlan->addrs, anode) { ipvlan_ht_addr_del(addr, !dev->dismantle); list_del(&addr->anode); + kfree_rcu(addr, rcu); } list_del_rcu(&ipvlan->pnode); -- cgit v1.2.3 From 6640e673c6f3dbaace085ca2686a8a343dc23a71 Mon Sep 17 00:00:00 2001 From: Konstantin Khlebnikov Date: Tue, 14 Jul 2015 16:35:53 +0300 Subject: ipvlan: unhash addresses without synchronize_rcu All structures used in traffic forwarding are rcu-protected: ipvl_addr, ipvl_dev and ipvl_port. Thus we can unhash addresses without synchronization. We'll anyway hash it back into the same bucket: in worst case lockless lookup will scan hash once again. Signed-off-by: Konstantin Khlebnikov Signed-off-by: David S. Miller --- drivers/net/ipvlan/ipvlan.h | 2 +- drivers/net/ipvlan/ipvlan_core.c | 4 +--- drivers/net/ipvlan/ipvlan_main.c | 8 ++++---- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/net/ipvlan/ipvlan.h b/drivers/net/ipvlan/ipvlan.h index 68e2549c28c6..40f9d7e4a0ea 100644 --- a/drivers/net/ipvlan/ipvlan.h +++ b/drivers/net/ipvlan/ipvlan.h @@ -122,5 +122,5 @@ struct ipvl_addr *ipvlan_find_addr(const struct ipvl_dev *ipvlan, bool ipvlan_addr_busy(struct ipvl_port *port, void *iaddr, bool is_v6); struct ipvl_addr *ipvlan_ht_addr_lookup(const struct ipvl_port *port, const void *iaddr, bool is_v6); -void ipvlan_ht_addr_del(struct ipvl_addr *addr, bool sync); +void ipvlan_ht_addr_del(struct ipvl_addr *addr); #endif /* __IPVLAN_H */ diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c index 8afbedad620d..8f8628a0adba 100644 --- a/drivers/net/ipvlan/ipvlan_core.c +++ b/drivers/net/ipvlan/ipvlan_core.c @@ -85,11 +85,9 @@ void ipvlan_ht_addr_add(struct ipvl_dev *ipvlan, struct ipvl_addr *addr) hlist_add_head_rcu(&addr->hlnode, &port->hlhead[hash]); } -void ipvlan_ht_addr_del(struct ipvl_addr *addr, bool sync) +void ipvlan_ht_addr_del(struct ipvl_addr *addr) { hlist_del_init_rcu(&addr->hlnode); - if (sync) - synchronize_rcu(); } struct ipvl_addr *ipvlan_find_addr(const struct ipvl_dev *ipvlan, diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c index 7d81e37c3f76..e995bc501ee6 100644 --- a/drivers/net/ipvlan/ipvlan_main.c +++ b/drivers/net/ipvlan/ipvlan_main.c @@ -171,7 +171,7 @@ static int ipvlan_stop(struct net_device *dev) dev_uc_del(phy_dev, phy_dev->dev_addr); list_for_each_entry(addr, &ipvlan->addrs, anode) - ipvlan_ht_addr_del(addr, !dev->dismantle); + ipvlan_ht_addr_del(addr); return 0; } @@ -505,7 +505,7 @@ static void ipvlan_link_delete(struct net_device *dev, struct list_head *head) struct ipvl_addr *addr, *next; list_for_each_entry_safe(addr, next, &ipvlan->addrs, anode) { - ipvlan_ht_addr_del(addr, !dev->dismantle); + ipvlan_ht_addr_del(addr); list_del(&addr->anode); kfree_rcu(addr, rcu); } @@ -641,7 +641,7 @@ static void ipvlan_del_addr6(struct ipvl_dev *ipvlan, struct in6_addr *ip6_addr) if (!addr) return; - ipvlan_ht_addr_del(addr, true); + ipvlan_ht_addr_del(addr); list_del(&addr->anode); kfree_rcu(addr, rcu); @@ -711,7 +711,7 @@ static void ipvlan_del_addr4(struct ipvl_dev *ipvlan, struct in_addr *ip4_addr) if (!addr) return; - ipvlan_ht_addr_del(addr, true); + ipvlan_ht_addr_del(addr); list_del(&addr->anode); kfree_rcu(addr, rcu); -- cgit v1.2.3 From 0fba37a3af03a7e74bf9e75473729adb98da49c3 Mon Sep 17 00:00:00 2001 From: WANG Cong Date: Tue, 14 Jul 2015 16:35:54 +0300 Subject: ipvlan: use rcu_deference_bh() in ipvlan_queue_xmit() In tx path rcu_read_lock_bh() is held, so we need rcu_deference_bh(). This fixes the following warning: =============================== [ INFO: suspicious RCU usage. ] 4.1.0-rc1+ #1007 Not tainted ------------------------------- drivers/net/ipvlan/ipvlan.h:106 suspicious rcu_dereference_check() usage! other info that might help us debug this: rcu_scheduler_active = 1, debug_locks = 0 1 lock held by dhclient/1076: #0: (rcu_read_lock_bh){......}, at: [] rcu_lock_acquire+0x0/0x26 stack backtrace: CPU: 2 PID: 1076 Comm: dhclient Not tainted 4.1.0-rc1+ #1007 Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011 0000000000000001 ffff8800d381bac8 ffffffff81a4154f 000000003c1a3c19 ffff8800d4d0a690 ffff8800d381baf8 ffffffff810b849f ffff880117d41148 ffff880117d40000 ffff880117d40068 0000000000000156 ffff8800d381bb18 Call Trace: [] dump_stack+0x4c/0x65 [] lockdep_rcu_suspicious+0x107/0x110 [] ipvlan_port_get_rcu+0x47/0x4e [] ipvlan_queue_xmit+0x35/0x450 [] ? rcu_read_unlock+0x3e/0x5f [] ? local_clock+0x19/0x22 [] ? __lock_is_held+0x39/0x52 [] ipvlan_start_xmit+0x1b/0x44 [] dev_hard_start_xmit+0x2ae/0x467 [] __dev_queue_xmit+0x50a/0x60c [] dev_queue_xmit_sk+0x13/0x15 [] dev_queue_xmit+0x10/0x12 [] packet_sendmsg+0xb6b/0xbdf [] ? mark_lock+0x2e/0x226 [] ? sched_clock_cpu+0x9e/0xb7 [] sock_sendmsg_nosec+0x12/0x1d [] sock_sendmsg+0x29/0x2e [] sock_write_iter+0x70/0x91 [] __vfs_write+0x7e/0xa7 [] vfs_write+0x92/0xe8 [] SyS_write+0x47/0x7e [] system_call_fastpath+0x12/0x6f Fixes: 2ad7bf363841 ("ipvlan: Initial check-in of the IPVLAN driver.") Cc: Mahesh Bandewar Signed-off-by: Cong Wang Acked-by: Mahesh Bandewar Acked-by: Konstantin Khlebnikov Signed-off-by: David S. Miller --- drivers/net/ipvlan/ipvlan.h | 5 +++++ drivers/net/ipvlan/ipvlan_core.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/net/ipvlan/ipvlan.h b/drivers/net/ipvlan/ipvlan.h index 40f9d7e4a0ea..9542b7bac61a 100644 --- a/drivers/net/ipvlan/ipvlan.h +++ b/drivers/net/ipvlan/ipvlan.h @@ -104,6 +104,11 @@ static inline struct ipvl_port *ipvlan_port_get_rcu(const struct net_device *d) return rcu_dereference(d->rx_handler_data); } +static inline struct ipvl_port *ipvlan_port_get_rcu_bh(const struct net_device *d) +{ + return rcu_dereference_bh(d->rx_handler_data); +} + static inline struct ipvl_port *ipvlan_port_get_rtnl(const struct net_device *d) { return rtnl_dereference(d->rx_handler_data); diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c index 8f8628a0adba..207f62e8de9a 100644 --- a/drivers/net/ipvlan/ipvlan_core.c +++ b/drivers/net/ipvlan/ipvlan_core.c @@ -529,7 +529,7 @@ static int ipvlan_xmit_mode_l2(struct sk_buff *skb, struct net_device *dev) int ipvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev) { struct ipvl_dev *ipvlan = netdev_priv(dev); - struct ipvl_port *port = ipvlan_port_get_rcu(ipvlan->phy_dev); + struct ipvl_port *port = ipvlan_port_get_rcu_bh(ipvlan->phy_dev); if (!port) goto out; -- cgit v1.2.3 From 23a5a49c83dd8a7201a42e96d24238bde3547c11 Mon Sep 17 00:00:00 2001 From: Konstantin Khlebnikov Date: Tue, 14 Jul 2015 16:35:55 +0300 Subject: ipvlan: ignore addresses from ipv6 autoconfiguration Inet6addr notifier is atomic and runs in bh context without RTNL when ipv6 receives router advertisement packet and performs autoconfiguration. Proper fix still in discussion. Let's at least plug the bug. v1: http://lkml.kernel.org/r/20150514135618.14062.1969.stgit@buzz v2: http://lkml.kernel.org/r/20150703125840.24121.91556.stgit@buzz Signed-off-by: Konstantin Khlebnikov Signed-off-by: David S. Miller --- drivers/net/ipvlan/ipvlan_main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c index e995bc501ee6..20b58bdecf75 100644 --- a/drivers/net/ipvlan/ipvlan_main.c +++ b/drivers/net/ipvlan/ipvlan_main.c @@ -655,6 +655,10 @@ static int ipvlan_addr6_event(struct notifier_block *unused, struct net_device *dev = (struct net_device *)if6->idev->dev; struct ipvl_dev *ipvlan = netdev_priv(dev); + /* FIXME IPv6 autoconf calls us from bh without RTNL */ + if (in_softirq()) + return NOTIFY_DONE; + if (!netif_is_ipvlan(dev)) return NOTIFY_DONE; -- cgit v1.2.3 From e8d092aafd9e68c04d7b468e95ff7a617998a796 Mon Sep 17 00:00:00 2001 From: WANG Cong Date: Tue, 14 Jul 2015 11:21:57 -0700 Subject: net_sched: fix a use-after-free in sfq Fixes: 25331d6ce42b ("net: sched: implement qstat helper routines") Cc: John Fastabend Signed-off-by: Cong Wang Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- net/sched/sch_sfq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index 7d1492663360..52f75a5473e1 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c @@ -306,10 +306,10 @@ drop: len = qdisc_pkt_len(skb); slot->backlog -= len; sfq_dec(q, x); - kfree_skb(skb); sch->q.qlen--; qdisc_qstats_drop(sch); qdisc_qstats_backlog_dec(sch, skb); + kfree_skb(skb); return len; } -- cgit v1.2.3 From c0afd9ce4d6a646fb6433536f95a418bb348fab1 Mon Sep 17 00:00:00 2001 From: WANG Cong Date: Tue, 14 Jul 2015 11:21:58 -0700 Subject: fq_codel: fix return value of fq_codel_drop() The ->drop() is supposed to return the number of bytes it dropped, however fq_codel_drop() returns the index of the flow where it drops a packet from. Fix this by introducing a helper to wrap fq_codel_drop(). Cc: Eric Dumazet Signed-off-by: Cong Wang Signed-off-by: Cong Wang Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- net/sched/sch_fq_codel.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/net/sched/sch_fq_codel.c b/net/sched/sch_fq_codel.c index 06e7c845e24d..21ca33c9f036 100644 --- a/net/sched/sch_fq_codel.c +++ b/net/sched/sch_fq_codel.c @@ -163,6 +163,15 @@ static unsigned int fq_codel_drop(struct Qdisc *sch) return idx; } +static unsigned int fq_codel_qdisc_drop(struct Qdisc *sch) +{ + unsigned int prev_backlog; + + prev_backlog = sch->qstats.backlog; + fq_codel_drop(sch); + return prev_backlog - sch->qstats.backlog; +} + static int fq_codel_enqueue(struct sk_buff *skb, struct Qdisc *sch) { struct fq_codel_sched_data *q = qdisc_priv(sch); @@ -604,7 +613,7 @@ static struct Qdisc_ops fq_codel_qdisc_ops __read_mostly = { .enqueue = fq_codel_enqueue, .dequeue = fq_codel_dequeue, .peek = qdisc_peek_dequeued, - .drop = fq_codel_drop, + .drop = fq_codel_qdisc_drop, .init = fq_codel_init, .reset = fq_codel_reset, .destroy = fq_codel_destroy, -- cgit v1.2.3 From ddf06c1e569a64a44c4c750ae45b2604f19e45f0 Mon Sep 17 00:00:00 2001 From: Alexei Starovoitov Date: Tue, 14 Jul 2015 12:15:19 -0700 Subject: tc: act_bpf: fix memory leak prog->bpf_ops is populated when act_bpf is used with classic BPF and prog->bpf_name is optionally used with extended BPF. Fix memory leak when act_bpf is released. Fixes: d23b8ad8ab23 ("tc: add BPF based action") Fixes: a8cb5f556b56 ("act_bpf: add initial eBPF support for actions") Acked-by: Daniel Borkmann Signed-off-by: Alexei Starovoitov Signed-off-by: David S. Miller --- net/sched/act_bpf.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/sched/act_bpf.c b/net/sched/act_bpf.c index 1d56903fd4c7..1df78289e248 100644 --- a/net/sched/act_bpf.c +++ b/net/sched/act_bpf.c @@ -339,6 +339,9 @@ static void tcf_bpf_cleanup(struct tc_action *act, int bind) bpf_prog_put(prog->filter); else bpf_prog_destroy(prog->filter); + + kfree(prog->bpf_ops); + kfree(prog->bpf_name); } static struct tc_action_ops act_bpf_ops __read_mostly = { -- cgit v1.2.3 From 25b401c1816ae64bcc5dcb1d39ab41812522a0ce Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Mon, 18 May 2015 18:33:27 +0200 Subject: can: mcp251x: fix resume when device is down If a valid power regulator or a dummy regulator is used (which happens to be the case when no regulator is specified), restart_work is queued no matter whether the device was running or not at suspend time. Since work queues get initialized in the ndo_open callback, resuming leads to a NULL pointer exception. Reverse exactly the steps executed at suspend time: - Enable the power regulator in any case - Enable the transceiver regulator if the device was running, even in case we have a power regulator - Queue restart_work only in case the device was running Fixes: bf66f3736a94 ("can: mcp251x: Move to threaded interrupts instead of workqueues.") Signed-off-by: Stefan Agner Cc: linux-stable Signed-off-by: Marc Kleine-Budde --- drivers/net/can/spi/mcp251x.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/net/can/spi/mcp251x.c b/drivers/net/can/spi/mcp251x.c index c1a95a34d62e..3b2f34e6ba9b 100644 --- a/drivers/net/can/spi/mcp251x.c +++ b/drivers/net/can/spi/mcp251x.c @@ -1222,17 +1222,16 @@ static int __maybe_unused mcp251x_can_resume(struct device *dev) struct spi_device *spi = to_spi_device(dev); struct mcp251x_priv *priv = spi_get_drvdata(spi); - if (priv->after_suspend & AFTER_SUSPEND_POWER) { + if (priv->after_suspend & AFTER_SUSPEND_POWER) mcp251x_power_enable(priv->power, 1); + + if (priv->after_suspend & AFTER_SUSPEND_UP) { + mcp251x_power_enable(priv->transceiver, 1); queue_work(priv->wq, &priv->restart_work); } else { - if (priv->after_suspend & AFTER_SUSPEND_UP) { - mcp251x_power_enable(priv->transceiver, 1); - queue_work(priv->wq, &priv->restart_work); - } else { - priv->after_suspend = 0; - } + priv->after_suspend = 0; } + priv->force_quit = 0; enable_irq(spi->irq); return 0; -- cgit v1.2.3 From 69da3f2ac528642acbd06ed14564ac1b9a918394 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Mon, 18 May 2015 18:33:28 +0200 Subject: can: mcp251x: get regulators optionally The regulators power and transceiver are optional. If those are not present, the pointer (or error pointer) is correctly handled by the driver, hence we can use devm_regulator_get_optional safely, which avoids regulators getting created. Signed-off-by: Stefan Agner Signed-off-by: Marc Kleine-Budde --- drivers/net/can/spi/mcp251x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/can/spi/mcp251x.c b/drivers/net/can/spi/mcp251x.c index 3b2f34e6ba9b..b7e83c212023 100644 --- a/drivers/net/can/spi/mcp251x.c +++ b/drivers/net/can/spi/mcp251x.c @@ -1086,8 +1086,8 @@ static int mcp251x_can_probe(struct spi_device *spi) if (ret) goto out_clk; - priv->power = devm_regulator_get(&spi->dev, "vdd"); - priv->transceiver = devm_regulator_get(&spi->dev, "xceiver"); + priv->power = devm_regulator_get_optional(&spi->dev, "vdd"); + priv->transceiver = devm_regulator_get_optional(&spi->dev, "xceiver"); if ((PTR_ERR(priv->power) == -EPROBE_DEFER) || (PTR_ERR(priv->transceiver) == -EPROBE_DEFER)) { ret = -EPROBE_DEFER; -- cgit v1.2.3 From 9051bd393cf25e76dfb45409792719a854661500 Mon Sep 17 00:00:00 2001 From: "Martin K. Petersen" Date: Wed, 15 Jul 2015 21:03:23 -0400 Subject: libata: Do not blacklist M510DC A new Micron drive was just announced, once again recycling the first part of the model string. Add an underscore to the M510/M550 pattern to avoid picking up the new DC drive. Signed-off-by: Martin K. Petersen Cc: Signed-off-by: Tejun Heo --- drivers/ata/libata-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 12b176a10d57..db5d9f79a247 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4240,7 +4240,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { ATA_HORKAGE_ZERO_AFTER_TRIM, }, { "Crucial_CT*M500*", NULL, ATA_HORKAGE_NO_NCQ_TRIM | ATA_HORKAGE_ZERO_AFTER_TRIM, }, - { "Micron_M5[15]0*", "MU01", ATA_HORKAGE_NO_NCQ_TRIM | + { "Micron_M5[15]0_*", "MU01", ATA_HORKAGE_NO_NCQ_TRIM | ATA_HORKAGE_ZERO_AFTER_TRIM, }, { "Crucial_CT*M550*", "MU01", ATA_HORKAGE_NO_NCQ_TRIM | ATA_HORKAGE_ZERO_AFTER_TRIM, }, -- cgit v1.2.3 From 7d01cd261c76f95913c81554a751968a1d282d3a Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Mon, 13 Jul 2015 09:54:42 -0700 Subject: Input: zforce - don't overwrite the stack If we get a corrupted packet with PAYLOAD_LENGTH > FRAME_MAXSIZE, we will silently overwrite the stack. Cc: stable@vger.kernel.org Signed-off-by: Oleksij Rempel Signed-off-by: Dirk Behme Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/zforce_ts.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/touchscreen/zforce_ts.c b/drivers/input/touchscreen/zforce_ts.c index f58a196521a9..80285c71786e 100644 --- a/drivers/input/touchscreen/zforce_ts.c +++ b/drivers/input/touchscreen/zforce_ts.c @@ -429,7 +429,7 @@ static int zforce_read_packet(struct zforce_ts *ts, u8 *buf) goto unlock; } - if (buf[PAYLOAD_LENGTH] == 0) { + if (buf[PAYLOAD_LENGTH] == 0 || buf[PAYLOAD_LENGTH] > FRAME_MAXSIZE) { dev_err(&client->dev, "invalid payload length: %d\n", buf[PAYLOAD_LENGTH]); ret = -EIO; -- cgit v1.2.3 From d98399e688f8c4f42f4270c2dfe1293f69247c5b Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 16 Jul 2015 10:38:15 -0700 Subject: Input: elantech - force resolution of 31 u/mm All Elantech touchpads pre-v4 with dynamic resolution queries have a fixed resolution of 800dpi -> 31.49 units/mm. Set this statically, so userspace does not have to guess. Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede Reviewed-by: David Herrmann Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/elantech.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index ce3d40004458..22b9ca901f4e 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -1167,7 +1167,7 @@ static int elantech_set_input_params(struct psmouse *psmouse) struct input_dev *dev = psmouse->dev; struct elantech_data *etd = psmouse->private; unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0, width = 0; - unsigned int x_res = 0, y_res = 0; + unsigned int x_res = 31, y_res = 31; if (elantech_set_range(psmouse, &x_min, &y_min, &x_max, &y_max, &width)) return -1; @@ -1232,8 +1232,6 @@ static int elantech_set_input_params(struct psmouse *psmouse) /* For X to recognize me as touchpad. */ input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0); input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0); - input_abs_set_res(dev, ABS_X, x_res); - input_abs_set_res(dev, ABS_Y, y_res); /* * range of pressure and width is the same as v2, * report ABS_PRESSURE, ABS_TOOL_WIDTH for compatibility. @@ -1246,8 +1244,6 @@ static int elantech_set_input_params(struct psmouse *psmouse) input_mt_init_slots(dev, ETP_MAX_FINGERS, 0); input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0); input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0); - input_abs_set_res(dev, ABS_MT_POSITION_X, x_res); - input_abs_set_res(dev, ABS_MT_POSITION_Y, y_res); input_set_abs_params(dev, ABS_MT_PRESSURE, ETP_PMIN_V2, ETP_PMAX_V2, 0, 0); /* @@ -1259,6 +1255,13 @@ static int elantech_set_input_params(struct psmouse *psmouse) break; } + input_abs_set_res(dev, ABS_X, x_res); + input_abs_set_res(dev, ABS_Y, y_res); + if (etd->hw_version > 1) { + input_abs_set_res(dev, ABS_MT_POSITION_X, x_res); + input_abs_set_res(dev, ABS_MT_POSITION_Y, y_res); + } + etd->y_max = y_max; etd->width = width; -- cgit v1.2.3 From e2c09ae7a74d94222187edbe8f5cf1fa9364efcd Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Wed, 15 Jul 2015 16:10:28 +0200 Subject: regulator: core: Increase refcount for regulator supply's module When a regulator is unregistered with regulator_unregister(), a call to regulator_put() is made for its input supply if there is one. This does a module_put() to decrement the refcount of the module that owns the supply but there isn't a corresponding try_module_get() in set_supply() to make the calls balanced. Signed-off-by: Javier Martinez Canillas Signed-off-by: Mark Brown --- drivers/regulator/core.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index c9f72019bd68..934fde4faebe 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1105,6 +1105,9 @@ static int set_supply(struct regulator_dev *rdev, rdev_info(rdev, "supplied by %s\n", rdev_get_name(supply_rdev)); + if (!try_module_get(supply_rdev->owner)) + return -ENODEV; + rdev->supply = create_regulator(supply_rdev, &rdev->dev, "SUPPLY"); if (rdev->supply == NULL) { err = -ENOMEM; -- cgit v1.2.3 From 36a1f1b6ddc6d1442424e29548e790633ca39c7b Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Wed, 15 Jul 2015 16:10:29 +0200 Subject: regulator: core: Fix memory leak in regulator_resolve_supply() The regulator_resolve_supply() function calls set_supply() which in turn calls create_regulator() to allocate a supply regulator. If an error occurs after set_supply() succeeded, the allocated regulator has to be freed before propagating the error code. Signed-off-by: Javier Martinez Canillas Signed-off-by: Mark Brown --- drivers/regulator/core.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 934fde4faebe..80a123e8d0c3 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -109,6 +109,7 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev, static struct regulator *create_regulator(struct regulator_dev *rdev, struct device *dev, const char *supply_name); +static void _regulator_put(struct regulator *regulator); static const char *rdev_get_name(struct regulator_dev *rdev) { @@ -1401,8 +1402,11 @@ static int regulator_resolve_supply(struct regulator_dev *rdev) /* Cascade always-on state to supply */ if (_regulator_is_enabled(rdev)) { ret = regulator_enable(rdev->supply); - if (ret < 0) + if (ret < 0) { + if (rdev->supply) + _regulator_put(rdev->supply); return ret; + } } return 0; -- cgit v1.2.3 From e2370f07cf703c0920c99bc24de3d152262738f0 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 15 Jul 2015 00:56:52 +0300 Subject: ravb: do not invalidate cache for RX buffer twice First, dma_sync_single_for_cpu() shouldn't have been called in the first place (it's a streaming DMA API), dma_unmap_single() should have been called instead. Second, dma_unmap_single() call after handing the buffer to napi_gro_receive() makes little sense. Moreover desc->dptr might not be valid at this point. Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/ravb_main.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c index fd9745714d90..0e5fde321630 100644 --- a/drivers/net/ethernet/renesas/ravb_main.c +++ b/drivers/net/ethernet/renesas/ravb_main.c @@ -543,10 +543,9 @@ static bool ravb_rx(struct net_device *ndev, int *quota, int q) skb = priv->rx_skb[q][entry]; priv->rx_skb[q][entry] = NULL; - dma_sync_single_for_cpu(&ndev->dev, - le32_to_cpu(desc->dptr), - ALIGN(PKT_BUF_SZ, 16), - DMA_FROM_DEVICE); + dma_unmap_single(&ndev->dev, le32_to_cpu(desc->dptr), + ALIGN(PKT_BUF_SZ, 16), + DMA_FROM_DEVICE); get_ts &= (q == RAVB_NC) ? RAVB_RXTSTAMP_TYPE_V2_L2_EVENT : ~RAVB_RXTSTAMP_TYPE_V2_L2_EVENT; @@ -584,9 +583,6 @@ static bool ravb_rx(struct net_device *ndev, int *quota, int q) if (!skb) break; /* Better luck next round. */ ravb_set_buffer_align(skb); - dma_unmap_single(&ndev->dev, le32_to_cpu(desc->dptr), - ALIGN(PKT_BUF_SZ, 16), - DMA_FROM_DEVICE); dma_addr = dma_map_single(&ndev->dev, skb->data, le16_to_cpu(desc->ds_cc), DMA_FROM_DEVICE); -- cgit v1.2.3 From 5cde07abcbc57b3430b044cb2cf028d97d7a7254 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 15 Jun 2015 13:54:29 +0900 Subject: pinctrl: samsung: Remove old unused defines Since 9a2c1c3b91aa ("pinctrl: samsung: Allow grouping multiple pinmux/pinconf nodes") the defines for GPIO group and function names are not used anywhere in the driver. Signed-off-by: Krzysztof Kozlowski Inspired-by: Dan Carpenter Signed-off-by: Linus Walleij --- drivers/pinctrl/samsung/pinctrl-samsung.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c index 3dd5a3b2ac62..c760bf43d116 100644 --- a/drivers/pinctrl/samsung/pinctrl-samsung.c +++ b/drivers/pinctrl/samsung/pinctrl-samsung.c @@ -33,11 +33,6 @@ #include "../core.h" #include "pinctrl-samsung.h" -#define GROUP_SUFFIX "-grp" -#define GSUFFIX_LEN sizeof(GROUP_SUFFIX) -#define FUNCTION_SUFFIX "-mux" -#define FSUFFIX_LEN sizeof(FUNCTION_SUFFIX) - /* list of all possible config options supported */ static struct pin_config { const char *property; -- cgit v1.2.3 From 4479004e6409087d1b4986881dc98c6c15dffb28 Mon Sep 17 00:00:00 2001 From: Tom Hughes Date: Mon, 29 Jun 2015 19:41:49 +0100 Subject: mac80211: clear subdir_stations when removing debugfs If we don't do this, and we then fail to recreate the debugfs directory during a mode change, then we will fail later trying to add stations to this now bogus directory: BUG: unable to handle kernel NULL pointer dereference at 0000006c IP: [] mutex_lock+0x12/0x30 Call Trace: [] start_creating+0x44/0xc0 [] debugfs_create_dir+0x13/0xf0 [] ieee80211_sta_debugfs_add+0x6e/0x490 [mac80211] Cc: stable@kernel.org Signed-off-by: Tom Hughes Signed-off-by: Johannes Berg --- net/mac80211/debugfs_netdev.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 29236e832e44..c09c0131bfa2 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c @@ -723,6 +723,7 @@ void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata) debugfs_remove_recursive(sdata->vif.debugfs_dir); sdata->vif.debugfs_dir = NULL; + sdata->debugfs.subdir_stations = NULL; } void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata) -- cgit v1.2.3 From e9de01907e3d1957591113daa3857c0bf01067ef Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Thu, 2 Jul 2015 09:59:56 +0200 Subject: mac80211: don't clear all tx flags when requeing When acting as AP and a PS-Poll frame is received associated station is marked as one in a Service Period. This state is kept until Tx status for released frame is reported. While a station is in Service Period PS-Poll frames are ignored. However if PS-Poll was received during A-MPDU teardown it was possible to have the to-be released frame re-queued back to pending queue. In such case the frame was stripped of 2 important flags: (a) IEEE80211_TX_CTL_NO_PS_BUFFER (b) IEEE80211_TX_STATUS_EOSP Stripping of (a) led to the frame that was to be released to be queued back to ps_tx_buf queue. If station remained to use only PS-Poll frames the re-queued frame (and new ones) was never actually transmitted because mac80211 would ignore subsequent PS-Poll frames due to station being in Service Period. There was nothing left to clear the Service Period bit (no xmit -> no tx status -> no SP end), i.e. the AP would have the station stuck in Service Period. Beacon TIM would repeatedly prompt station to poll for frames but it would get none. Once (a) is not stripped (b) becomes important because it's the main condition to clear the Service Period bit of the station when Tx status for the released frame is reported back. This problem was observed with ath9k acting as P2P GO in some testing scenarios but isn't limited to it. AP operation with mac80211 based Tx A-MPDU control combined with clients using PS-Poll frames is subject to this race. Signed-off-by: Michal Kazior Signed-off-by: Johannes Berg --- net/mac80211/tx.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 8410bb3bf5e8..b8233505bf9f 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1117,7 +1117,9 @@ static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx, queued = true; info->control.vif = &tx->sdata->vif; info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; - info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS; + info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS | + IEEE80211_TX_CTL_NO_PS_BUFFER | + IEEE80211_TX_STATUS_EOSP; __skb_queue_tail(&tid_tx->pending, skb); if (skb_queue_len(&tid_tx->pending) > STA_MAX_TX_BUFFER) purge_skb = __skb_dequeue(&tid_tx->pending); -- cgit v1.2.3 From 541b6ed7cee1ec7c8f525f51a0ff097776111aeb Mon Sep 17 00:00:00 2001 From: Chaitanya T K Date: Wed, 10 Jun 2015 19:12:31 +0530 Subject: mac80211: wowlan: enable powersave if suspend while ps-polling If for any reason we're in the middle of PS-polling or awake after TX due to dynamic powersave while going to suspend, go back to save power. This might cause a response frame to get lost, but since we can't really wait for it while going to suspend that's still better than not enabling powersave which would cause higher power usage during (and possibly even after) suspend. Note that this really only affects the very few drivers that use the powersave implementation in mac80211. Signed-off-by: Chaitanya T K [rewrite misleading commit log] Signed-off-by: Johannes Berg --- net/mac80211/pm.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 06b60980c62c..b676b9fa707b 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c @@ -76,6 +76,22 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) if (sdata->vif.type != NL80211_IFTYPE_STATION) continue; ieee80211_mgd_quiesce(sdata); + /* If suspended during TX in progress, and wowlan + * is enabled (connection will be active) there + * can be a race where the driver is put out + * of power-save due to TX and during suspend + * dynamic_ps_timer is cancelled and TX packet + * is flushed, leaving the driver in ACTIVE even + * after resuming until dynamic_ps_timer puts + * driver back in DOZE. + */ + if (sdata->u.mgd.associated && + sdata->u.mgd.powersave && + !(local->hw.conf.flags & IEEE80211_CONF_PS)) { + local->hw.conf.flags |= IEEE80211_CONF_PS; + ieee80211_hw_config(local, + IEEE80211_CONF_CHANGE_PS); + } } err = drv_suspend(local, wowlan); -- cgit v1.2.3 From d8d9008cfb919db48d95f96b05e81f84b3774318 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 8 Jul 2015 15:41:50 +0300 Subject: mac80211: shut down interfaces before destroying interface list If the hardware is unregistered while interfaces are up, mac80211 will unregister all interfaces, which in turns causes mac80211 to be called again to remove them all from the driver and eventually shut down the hardware. During this shutdown, however, it's currently already unsafe to iterate the list of interfaces atomically, as the list is manipulated in an unsafe manner. This puts an undue burden on the driver - it must stop all its activities before calling ieee80211_unregister_hw(), while in the normal stop path it can do all cleanup in the stop method. If, for example, it's using the iteration during RX for some reason, it would have to stop RX before unregistering to avoid crashes. Fix this problem by closing all interfaces before unregistering them. This will cause the driver stop to have completed before we manipulate the interface list, and after the driver is stopped *and* has called ieee80211_unregister_hw() it really musn't be iterating any more as the memory will be freed as well. Signed-off-by: Johannes Berg --- net/mac80211/iface.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index ed1edac14372..553ac6dd4867 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -1863,10 +1863,6 @@ void ieee80211_sdata_stop(struct ieee80211_sub_if_data *sdata) ieee80211_teardown_sdata(sdata); } -/* - * Remove all interfaces, may only be called at hardware unregistration - * time because it doesn't do RCU-safe list removals. - */ void ieee80211_remove_interfaces(struct ieee80211_local *local) { struct ieee80211_sub_if_data *sdata, *tmp; @@ -1875,14 +1871,21 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local) ASSERT_RTNL(); - /* - * Close all AP_VLAN interfaces first, as otherwise they - * might be closed while the AP interface they belong to - * is closed, causing unregister_netdevice_many() to crash. + /* Before destroying the interfaces, make sure they're all stopped so + * that the hardware is stopped. Otherwise, the driver might still be + * iterating the interfaces during the shutdown, e.g. from a worker + * or from RX processing or similar, and if it does so (using atomic + * iteration) while we're manipulating the list, the iteration will + * crash. + * + * After this, the hardware should be stopped and the driver should + * have stopped all of its activities, so that we can do RCU-unaware + * manipulations of the interface list below. */ - list_for_each_entry(sdata, &local->interfaces, list) - if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) - dev_close(sdata->dev); + cfg80211_shutdown_all_interfaces(local->hw.wiphy); + + WARN(local->open_count, "%s: open count remains %d\n", + wiphy_name(local->hw.wiphy), local->open_count); mutex_lock(&local->iflist_mtx); list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) { -- cgit v1.2.3 From 042ab5fc7a80b934032fcc673a125feb36645b33 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Thu, 9 Jul 2015 15:35:15 +0200 Subject: wireless: regulatory: reduce log level of CRDA related messages With a basic Linux userspace, the messages "Calling CRDA to update world regulatory domain" appears 10 times after boot every second or so, followed by a final "Exceeded CRDA call max attempts. Not calling CRDA". For those of us not having the corresponding userspace parts, having those messages repeatedly displayed at boot time is a bit annoying, so this commit reduces their log level to pr_debug(). Signed-off-by: Thomas Petazzoni Signed-off-by: Johannes Berg --- net/wireless/reg.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index d359e0610198..29134c81e73c 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -544,15 +544,15 @@ static int call_crda(const char *alpha2) reg_regdb_query(alpha2); if (reg_crda_timeouts > REG_MAX_CRDA_TIMEOUTS) { - pr_info("Exceeded CRDA call max attempts. Not calling CRDA\n"); + pr_debug("Exceeded CRDA call max attempts. Not calling CRDA\n"); return -EINVAL; } if (!is_world_regdom((char *) alpha2)) - pr_info("Calling CRDA for country: %c%c\n", + pr_debug("Calling CRDA for country: %c%c\n", alpha2[0], alpha2[1]); else - pr_info("Calling CRDA to update world regulatory domain\n"); + pr_debug("Calling CRDA to update world regulatory domain\n"); return kobject_uevent_env(®_pdev->dev.kobj, KOBJ_CHANGE, env); } -- cgit v1.2.3 From 2ea752cd2ce066c5d8c1807b5310ef329885cecb Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Tue, 14 Jul 2015 08:31:55 -0400 Subject: mac80211: correct aid location in peering frames According to 802.11-2012 8.5.16.3.2 AID comes directly after the capability bytes in mesh peering confirm frames. The existing code, however, was adding a 2 byte offset to this location, resulting in garbage data going out over the air. Remove the offset to fix it. Signed-off-by: Bob Copeland Signed-off-by: Johannes Berg --- net/mac80211/mesh_plink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 5438d13e2f00..f17127e754c9 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -306,7 +306,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, if (action == WLAN_SP_MESH_PEERING_CONFIRM) { /* AID */ pos = skb_put(skb, 2); - put_unaligned_le16(plid, pos + 2); + put_unaligned_le16(plid, pos); } if (ieee80211_add_srates_ie(sdata, skb, true, band) || ieee80211_add_ext_srates_ie(sdata, skb, true, band) || -- cgit v1.2.3 From b3e7de873df77c1fa0bc2cfaf3eaff757b80e773 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Tue, 14 Jul 2015 08:31:56 -0400 Subject: mac80211: add missing length check for confirm frames Although mesh_rx_plink_frame() already checks that frames have enough bytes for the action code plus another two bytes for capability/reason code, it doesn't take into account that confirm frames also have an additional two-byte aid. As a result, a corrupt frame could cause a subsequent subtraction to wrap around to ill effect. Add another check for this case. Signed-off-by: Bob Copeland Signed-off-by: Johannes Berg --- net/mac80211/mesh_plink.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index f17127e754c9..3b59099413fb 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -1122,6 +1122,9 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, WLAN_SP_MESH_PEERING_CONFIRM) { baseaddr += 4; baselen += 4; + + if (baselen > len) + return; } ieee802_11_parse_elems(baseaddr, len - baselen, true, &elems); mesh_process_plink_frame(sdata, mgmt, &elems); -- cgit v1.2.3 From 923b352f19d9ea971ae2536eab55f5fc9e95fedf Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Wed, 8 Jul 2015 15:41:44 +0300 Subject: cfg80211: use RTNL locked reg_can_beacon for IR-relaxation The RTNL is required to check for IR-relaxation conditions that allow more channels to beacon. Export an RTNL locked version of reg_can_beacon and use it where possible in AP/STA interface type flows, where IR-relaxation may be applicable. Fixes: 06f207fc5418 ("cfg80211: change GO_CONCURRENT to IR_CONCURRENT for STA") Signed-off-by: Arik Nemtsov Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- include/net/cfg80211.h | 17 +++++++++++++++++ net/mac80211/tdls.c | 6 +++--- net/wireless/chan.c | 45 ++++++++++++++++++++++++++++++++++----------- net/wireless/nl80211.c | 14 ++++++++------ net/wireless/reg.c | 2 +- net/wireless/trace.h | 11 +++++++---- 6 files changed, 70 insertions(+), 25 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index a741678f24a2..883fe1e7c5a1 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -4868,6 +4868,23 @@ bool cfg80211_reg_can_beacon(struct wiphy *wiphy, struct cfg80211_chan_def *chandef, enum nl80211_iftype iftype); +/** + * cfg80211_reg_can_beacon_relax - check if beaconing is allowed with relaxation + * @wiphy: the wiphy + * @chandef: the channel definition + * @iftype: interface type + * + * Return: %true if there is no secondary channel or the secondary channel(s) + * can be used for beaconing (i.e. is not a radar channel etc.). This version + * also checks if IR-relaxation conditions apply, to allow beaconing under + * more permissive conditions. + * + * Requires the RTNL to be held. + */ +bool cfg80211_reg_can_beacon_relax(struct wiphy *wiphy, + struct cfg80211_chan_def *chandef, + enum nl80211_iftype iftype); + /* * cfg80211_ch_switch_notify - update wdev channel and notify userspace * @dev: the device which switched channels diff --git a/net/mac80211/tdls.c b/net/mac80211/tdls.c index ad31b2dab4f5..8db6e2994bbc 100644 --- a/net/mac80211/tdls.c +++ b/net/mac80211/tdls.c @@ -60,6 +60,7 @@ ieee80211_tdls_add_subband(struct ieee80211_sub_if_data *sdata, struct ieee80211_channel *ch; struct cfg80211_chan_def chandef; int i, subband_start; + struct wiphy *wiphy = sdata->local->hw.wiphy; for (i = start; i <= end; i += spacing) { if (!ch_cnt) @@ -70,9 +71,8 @@ ieee80211_tdls_add_subband(struct ieee80211_sub_if_data *sdata, /* we will be active on the channel */ cfg80211_chandef_create(&chandef, ch, NL80211_CHAN_NO_HT); - if (cfg80211_reg_can_beacon(sdata->local->hw.wiphy, - &chandef, - sdata->wdev.iftype)) { + if (cfg80211_reg_can_beacon_relax(wiphy, &chandef, + sdata->wdev.iftype)) { ch_cnt++; /* * check if the next channel is also part of diff --git a/net/wireless/chan.c b/net/wireless/chan.c index 915b328b9ac5..59cabc9bce69 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c @@ -797,23 +797,18 @@ static bool cfg80211_ir_permissive_chan(struct wiphy *wiphy, return false; } -bool cfg80211_reg_can_beacon(struct wiphy *wiphy, - struct cfg80211_chan_def *chandef, - enum nl80211_iftype iftype) +static bool _cfg80211_reg_can_beacon(struct wiphy *wiphy, + struct cfg80211_chan_def *chandef, + enum nl80211_iftype iftype, + bool check_no_ir) { bool res; u32 prohibited_flags = IEEE80211_CHAN_DISABLED | IEEE80211_CHAN_RADAR; - trace_cfg80211_reg_can_beacon(wiphy, chandef, iftype); + trace_cfg80211_reg_can_beacon(wiphy, chandef, iftype, check_no_ir); - /* - * Under certain conditions suggested by some regulatory bodies a - * GO/STA can IR on channels marked with IEEE80211_NO_IR. Set this flag - * only if such relaxations are not enabled and the conditions are not - * met. - */ - if (!cfg80211_ir_permissive_chan(wiphy, iftype, chandef->chan)) + if (check_no_ir) prohibited_flags |= IEEE80211_CHAN_NO_IR; if (cfg80211_chandef_dfs_required(wiphy, chandef, iftype) > 0 && @@ -827,8 +822,36 @@ bool cfg80211_reg_can_beacon(struct wiphy *wiphy, trace_cfg80211_return_bool(res); return res; } + +bool cfg80211_reg_can_beacon(struct wiphy *wiphy, + struct cfg80211_chan_def *chandef, + enum nl80211_iftype iftype) +{ + return _cfg80211_reg_can_beacon(wiphy, chandef, iftype, true); +} EXPORT_SYMBOL(cfg80211_reg_can_beacon); +bool cfg80211_reg_can_beacon_relax(struct wiphy *wiphy, + struct cfg80211_chan_def *chandef, + enum nl80211_iftype iftype) +{ + bool check_no_ir; + + ASSERT_RTNL(); + + /* + * Under certain conditions suggested by some regulatory bodies a + * GO/STA can IR on channels marked with IEEE80211_NO_IR. Set this flag + * only if such relaxations are not enabled and the conditions are not + * met. + */ + check_no_ir = !cfg80211_ir_permissive_chan(wiphy, iftype, + chandef->chan); + + return _cfg80211_reg_can_beacon(wiphy, chandef, iftype, check_no_ir); +} +EXPORT_SYMBOL(cfg80211_reg_can_beacon_relax); + int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev, struct cfg80211_chan_def *chandef) { diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index c264effd00a6..76b41578a838 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -2003,7 +2003,8 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev, switch (iftype) { case NL80211_IFTYPE_AP: case NL80211_IFTYPE_P2P_GO: - if (!cfg80211_reg_can_beacon(&rdev->wiphy, &chandef, iftype)) { + if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &chandef, + iftype)) { result = -EINVAL; break; } @@ -3403,8 +3404,8 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) } else if (!nl80211_get_ap_channel(rdev, ¶ms)) return -EINVAL; - if (!cfg80211_reg_can_beacon(&rdev->wiphy, ¶ms.chandef, - wdev->iftype)) + if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, ¶ms.chandef, + wdev->iftype)) return -EINVAL; if (info->attrs[NL80211_ATTR_ACL_POLICY]) { @@ -6492,8 +6493,8 @@ skip_beacons: if (err) return err; - if (!cfg80211_reg_can_beacon(&rdev->wiphy, ¶ms.chandef, - wdev->iftype)) + if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, ¶ms.chandef, + wdev->iftype)) return -EINVAL; err = cfg80211_chandef_dfs_required(wdev->wiphy, @@ -10170,7 +10171,8 @@ static int nl80211_tdls_channel_switch(struct sk_buff *skb, return -EINVAL; /* we will be active on the TDLS link */ - if (!cfg80211_reg_can_beacon(&rdev->wiphy, &chandef, wdev->iftype)) + if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &chandef, + wdev->iftype)) return -EINVAL; /* don't allow switching to DFS channels */ diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 29134c81e73c..aa2d75482017 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -1589,7 +1589,7 @@ static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev) case NL80211_IFTYPE_AP: case NL80211_IFTYPE_P2P_GO: case NL80211_IFTYPE_ADHOC: - return cfg80211_reg_can_beacon(wiphy, &chandef, iftype); + return cfg80211_reg_can_beacon_relax(wiphy, &chandef, iftype); case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_P2P_CLIENT: return cfg80211_chandef_usable(wiphy, &chandef, diff --git a/net/wireless/trace.h b/net/wireless/trace.h index af3617c9879e..a808279a432a 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h @@ -2358,20 +2358,23 @@ TRACE_EVENT(cfg80211_cqm_rssi_notify, TRACE_EVENT(cfg80211_reg_can_beacon, TP_PROTO(struct wiphy *wiphy, struct cfg80211_chan_def *chandef, - enum nl80211_iftype iftype), - TP_ARGS(wiphy, chandef, iftype), + enum nl80211_iftype iftype, bool check_no_ir), + TP_ARGS(wiphy, chandef, iftype, check_no_ir), TP_STRUCT__entry( WIPHY_ENTRY CHAN_DEF_ENTRY __field(enum nl80211_iftype, iftype) + __field(bool, check_no_ir) ), TP_fast_assign( WIPHY_ASSIGN; CHAN_DEF_ASSIGN(chandef); __entry->iftype = iftype; + __entry->check_no_ir = check_no_ir; ), - TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT ", iftype=%d", - WIPHY_PR_ARG, CHAN_DEF_PR_ARG, __entry->iftype) + TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT ", iftype=%d check_no_ir=%s", + WIPHY_PR_ARG, CHAN_DEF_PR_ARG, __entry->iftype, + BOOL_TO_STR(__entry->check_no_ir)) ); TRACE_EVENT(cfg80211_chandef_dfs_required, -- cgit v1.2.3 From 67756e3191c90e7c0b94b8b2fb63de255b6cd337 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 17 Jul 2015 15:22:33 +0200 Subject: ALSA: pcm: Fix lockdep warning with nonatomic PCM ops With the nonatomic PCM ops, the system may spew lockdep warnings like: ============================================= [ INFO: possible recursive locking detected ] 4.2.0-rc1-jeejaval3 #12 Not tainted --------------------------------------------- aplay/4029 is trying to acquire lock: (snd_pcm_link_rwsem){.+.+.+}, at: [] snd_pcm_stream_lock+0x43/0x60 but task is already holding lock: (snd_pcm_link_rwsem){.+.+.+}, at: [] snd_pcm_action_nonatomic+0x29/0x80 other info that might help us debug this: Possible unsafe locking scenario: CPU0 ---- lock(snd_pcm_link_rwsem); lock(snd_pcm_link_rwsem); Although this is false-positive as the rwsem is taken always as read-only for these code paths, it's certainly annoying to see this at any occasion. A simple fix is to use down_read_nested() in snd_pcm_stream_lock() that can be called inside another lock. Reported-by: Vinod Koul Reported-by: Jeeja Kp Tested-by: Jeeja Kp Cc: Signed-off-by: Takashi Iwai --- sound/core/pcm_native.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index d126c03361ae..75888dd38a7f 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -85,7 +85,7 @@ static DECLARE_RWSEM(snd_pcm_link_rwsem); void snd_pcm_stream_lock(struct snd_pcm_substream *substream) { if (substream->pcm->nonatomic) { - down_read(&snd_pcm_link_rwsem); + down_read_nested(&snd_pcm_link_rwsem, SINGLE_DEPTH_NESTING); mutex_lock(&substream->self_group.mutex); } else { read_lock(&snd_pcm_link_rwlock); -- cgit v1.2.3 From d6726c8145290bef950ae2538ea6ae1d96a1944b Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Red Hat)" Date: Fri, 17 Jul 2015 14:03:26 -0400 Subject: tracing: Fix sample output of dynamic arrays He Kuang noticed that the trace event samples for arrays was broken: "The output result of trace_foo_bar event in traceevent samples is wrong. This problem can be reproduced as following: (Build kernel with SAMPLE_TRACE_EVENTS=m) $ insmod trace-events-sample.ko $ echo 1 > /sys/kernel/debug/tracing/events/sample-trace/foo_bar/enable $ cat /sys/kernel/debug/tracing/trace event-sample-980 [000] .... 43.649559: foo_bar: foo hello 21 0x15 BIT1|BIT3|0x10 {0x1,0x6f6f6e53,0xff007970,0xffffffff} Snoopy ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The array length is not right, should be {0x1}. (ffffffff,ffffffff) event-sample-980 [000] .... 44.653827: foo_bar: foo hello 22 0x16 BIT2|BIT3|0x10 {0x1,0x2,0x646e6147,0x666c61,0xffffffff,0xffffffff,0x750aeffe,0x7} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The array length is not right, should be {0x1,0x2}. Gandalf (ffffffff,ffffffff)" This was caused by an update to have __print_array()'s second parameter be the count of items in the array and not the size of the array. As there is already users of __print_array(), it can not change. But the sample code can and we can also improve on the documentation about __print_array() and __get_dynamic_array_len(). Link: http://lkml.kernel.org/r/1436839171-31527-2-git-send-email-hekuang@huawei.com Fixes: ac01ce1410fc2 ("tracing: Make ftrace_print_array_seq compute buf_len") Reported-by: He Kuang Signed-off-by: Steven Rostedt --- samples/trace_events/trace-events-sample.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/samples/trace_events/trace-events-sample.h b/samples/trace_events/trace-events-sample.h index 8965d1bb8811..125d6402f64f 100644 --- a/samples/trace_events/trace-events-sample.h +++ b/samples/trace_events/trace-events-sample.h @@ -168,7 +168,10 @@ * * For __dynamic_array(int, foo, bar) use __get_dynamic_array(foo) * Use __get_dynamic_array_len(foo) to get the length of the array - * saved. + * saved. Note, __get_dynamic_array_len() returns the total allocated + * length of the dynamic array; __print_array() expects the second + * parameter to be the number of elements. To get that, the array length + * needs to be divided by the element size. * * For __string(foo, bar) use __get_str(foo) * @@ -288,7 +291,7 @@ TRACE_EVENT(foo_bar, * This prints out the array that is defined by __array in a nice format. */ __print_array(__get_dynamic_array(list), - __get_dynamic_array_len(list), + __get_dynamic_array_len(list) / sizeof(int), sizeof(int)), __get_str(str), __get_bitmask(cpus)) ); -- cgit v1.2.3 From 25e5eaf19962bd48788371e4f516bdd89ce248bc Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Fri, 17 Jul 2015 20:33:21 +0200 Subject: ALSA: sparc: Add missing kfree in error path If 'of_ioremap' fails, then 'amd' should be freed, otherwise, there is a memory leak. Signed-off-by: Christophe JAILLET Signed-off-by: Takashi Iwai --- sound/sparc/amd7930.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/sparc/amd7930.c b/sound/sparc/amd7930.c index 1b1a89e80d13..784ceb85b2d9 100644 --- a/sound/sparc/amd7930.c +++ b/sound/sparc/amd7930.c @@ -956,6 +956,7 @@ static int snd_amd7930_create(struct snd_card *card, if (!amd->regs) { snd_printk(KERN_ERR "amd7930-%d: Unable to map chip registers.\n", dev); + kfree(amd); return -EIO; } -- cgit v1.2.3 From 88cc7b4eee1e7b9bca1a64dae5adaa044cf72312 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Mon, 1 Jun 2015 16:36:27 -0700 Subject: hid-sensor: Fix suspend/resume delay By default all the sensors are runtime suspended state (lowest power state). During Linux suspend process, all the run time suspended devices are resumed and then suspended. This caused all sensors to power up and introduced delay in suspend time, when we introduced runtime PM for HID sensors. The opposite process happens during resume process. To fix this, we do powerup process of the sensors only when the request is issued from user (raw or tiggerred). In this way when runtime, resume calls for powerup it will simply return as this will not match user requested state. Note this is a regression fix as the increase in suspend / resume times can be substantial (report of 8 seconds on Len's laptop!) Signed-off-by: Srinivas Pandruvada Tested-by: Len Brown Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/common/hid-sensors/hid-sensor-trigger.c | 11 ++++++++++- include/linux/hid-sensor-hub.h | 1 + 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c index 610fc98f88ef..595511022795 100644 --- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c +++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c @@ -36,6 +36,8 @@ static int _hid_sensor_power_state(struct hid_sensor_common *st, bool state) s32 poll_value = 0; if (state) { + if (!atomic_read(&st->user_requested_state)) + return 0; if (sensor_hub_device_open(st->hsdev)) return -EIO; @@ -52,8 +54,12 @@ static int _hid_sensor_power_state(struct hid_sensor_common *st, bool state) poll_value = hid_sensor_read_poll_value(st); } else { - if (!atomic_dec_and_test(&st->data_ready)) + int val; + + val = atomic_dec_if_positive(&st->data_ready); + if (val < 0) return 0; + sensor_hub_device_close(st->hsdev); state_val = hid_sensor_get_usage_index(st->hsdev, st->power_state.report_id, @@ -92,9 +98,11 @@ EXPORT_SYMBOL(hid_sensor_power_state); int hid_sensor_power_state(struct hid_sensor_common *st, bool state) { + #ifdef CONFIG_PM int ret; + atomic_set(&st->user_requested_state, state); if (state) ret = pm_runtime_get_sync(&st->pdev->dev); else { @@ -109,6 +117,7 @@ int hid_sensor_power_state(struct hid_sensor_common *st, bool state) return 0; #else + atomic_set(&st->user_requested_state, state); return _hid_sensor_power_state(st, state); #endif } diff --git a/include/linux/hid-sensor-hub.h b/include/linux/hid-sensor-hub.h index 0042bf330b99..c02b5ce6c5cd 100644 --- a/include/linux/hid-sensor-hub.h +++ b/include/linux/hid-sensor-hub.h @@ -230,6 +230,7 @@ struct hid_sensor_common { struct platform_device *pdev; unsigned usage_id; atomic_t data_ready; + atomic_t user_requested_state; struct iio_trigger *trigger; struct hid_sensor_hub_attribute_info poll; struct hid_sensor_hub_attribute_info report_state; -- cgit v1.2.3 From c11e28f959a6e700d19a952e078cb368c2e781a4 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Mon, 25 May 2015 22:36:58 +0200 Subject: iio: adc: rockchip_saradc: add missing MODULE_* data The module-data is currently missing. This includes the license-information which makes the driver taint the kernel and miss symbols when compiled as module. Fixes: 44d6f2ef94f9 ("iio: adc: add driver for Rockchip saradc") Signed-off-by: Heiko Stuebner Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/adc/rockchip_saradc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/iio/adc/rockchip_saradc.c b/drivers/iio/adc/rockchip_saradc.c index 8d4e019ea4ca..9c311c1e1ac7 100644 --- a/drivers/iio/adc/rockchip_saradc.c +++ b/drivers/iio/adc/rockchip_saradc.c @@ -349,3 +349,7 @@ static struct platform_driver rockchip_saradc_driver = { }; module_platform_driver(rockchip_saradc_driver); + +MODULE_AUTHOR("Heiko Stuebner "); +MODULE_DESCRIPTION("Rockchip SARADC driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From b220da654d268c79f420fbfac6a35eb420b9cc4b Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Sun, 24 May 2015 17:39:04 -0300 Subject: iio: twl4030-madc: Pass the IRQF_ONESHOT flag Since commit 1c6c69525b40 ("genirq: Reject bogus threaded irq requests") threaded IRQs without a primary handler need to be requested with IRQF_ONESHOT, otherwise the request will fail. So pass the IRQF_ONESHOT flag in this case. The semantic patch that makes this change is available in scripts/coccinelle/misc/irqf_oneshot.cocci. Signed-off-by: Fabio Estevam Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/adc/twl4030-madc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/iio/adc/twl4030-madc.c b/drivers/iio/adc/twl4030-madc.c index 06f4792240f0..ebe415f10640 100644 --- a/drivers/iio/adc/twl4030-madc.c +++ b/drivers/iio/adc/twl4030-madc.c @@ -833,7 +833,8 @@ static int twl4030_madc_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, twl4030_madc_threaded_irq_handler, - IRQF_TRIGGER_RISING, "twl4030_madc", madc); + IRQF_TRIGGER_RISING | IRQF_ONESHOT, + "twl4030_madc", madc); if (ret) { dev_err(&pdev->dev, "could not request irq\n"); goto err_i2c; -- cgit v1.2.3 From 2acbe15f8ae539809ef8169a65a8d859cf932530 Mon Sep 17 00:00:00 2001 From: Adriana Reus Date: Fri, 12 Jun 2015 18:10:23 +0300 Subject: iio: inv-mpu: Specify the expected format/precision for write channels The gyroscope needs IIO_VAL_INT_PLUS_NANO for the scale channel and unless specified write returns MICRO by default. This needs to be properly specified so that write operations into scale have the expected behaviour. Signed-off-by: Adriana Reus Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c index 17d4bb15be4d..65ce86837177 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c @@ -431,6 +431,23 @@ static int inv_mpu6050_write_gyro_scale(struct inv_mpu6050_state *st, int val) return -EINVAL; } +static int inv_write_raw_get_fmt(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, long mask) +{ + switch (mask) { + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_ANGL_VEL: + return IIO_VAL_INT_PLUS_NANO; + default: + return IIO_VAL_INT_PLUS_MICRO; + } + default: + return IIO_VAL_INT_PLUS_MICRO; + } + + return -EINVAL; +} static int inv_mpu6050_write_accel_scale(struct inv_mpu6050_state *st, int val) { int result, i; @@ -696,6 +713,7 @@ static const struct iio_info mpu_info = { .driver_module = THIS_MODULE, .read_raw = &inv_mpu6050_read_raw, .write_raw = &inv_mpu6050_write_raw, + .write_raw_get_fmt = &inv_write_raw_get_fmt, .attrs = &inv_attribute_group, .validate_trigger = inv_mpu6050_validate_trigger, }; -- cgit v1.2.3 From 63fc444967591c3849438aa0f21d5de96a928311 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Thu, 11 Jun 2015 18:49:33 +0300 Subject: iio: ABI: Clarify proximity output value Current description for proximity measurement is ambiguous. While the first part says that proximity is measured by observing reflectivity, the second part incorrectly infers that reported values should behave like a distance. This is because of AS3935 lightning sensor which uses the proximity API, while not being a true proximity sensor. Note this is marked for stable as it accompanies a fix in ABI usage to the sx9500 driver which would otherwise appear to be correct. Fixes: 614e8842ddf ("iio: ABI: add clarification for proximity") Signed-off-by: Daniel Baluta Cc: Signed-off-by: Jonathan Cameron --- Documentation/ABI/testing/sysfs-bus-iio | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index bbed111c31b4..70c9b1ac66db 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -1234,10 +1234,8 @@ Description: object is near the sensor, usually be observing reflectivity of infrared or ultrasound emitted. Often these sensors are unit less and as such conversion - to SI units is not possible. Where it is, the units should - be meters. If such a conversion is not possible, the reported - values should behave in the same way as a distance, i.e. lower - values indicate something is closer to the sensor. + to SI units is not possible. Higher proximity measurements + indicate closer objects, and vice versa. What: /sys/.../iio:deviceX/in_illuminance_input What: /sys/.../iio:deviceX/in_illuminance_raw -- cgit v1.2.3 From 86d24f04f9a0a7bad8e1719e5aa464eb5779e678 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Thu, 11 Jun 2015 18:49:34 +0300 Subject: iio: proximity: sx9500: Fix proximity value Because of the ABI confusion proximity value exposed by SX9500 was inverted. Signed-off-by: Daniel Baluta Reviewed-by: Vlad Dogaru Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/proximity/sx9500.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/proximity/sx9500.c b/drivers/iio/proximity/sx9500.c index 2042e375f835..01494cd6fa32 100644 --- a/drivers/iio/proximity/sx9500.c +++ b/drivers/iio/proximity/sx9500.c @@ -281,7 +281,7 @@ static int sx9500_read_prox_data(struct sx9500_data *data, if (ret < 0) return ret; - *val = 32767 - (s16)be16_to_cpu(regval); + *val = be16_to_cpu(regval); return IIO_VAL_INT; } -- cgit v1.2.3 From 09f4dcc9443c4731b6669066bd1bc4312ef17bcc Mon Sep 17 00:00:00 2001 From: JM Friedt Date: Fri, 19 Jun 2015 14:48:06 +0200 Subject: iio: DAC: ad5624r_spi: fix bit shift of output data value The value sent on the SPI bus is shifted by an erroneous number of bits. The shift value was already computed in the iio_chan_spec structure and hence subtracting this argument to 16 yields an erroneous data position in the SPI stream. Signed-off-by: JM Friedt Acked-by: Lars-Peter Clausen Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/dac/ad5624r_spi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/iio/dac/ad5624r_spi.c b/drivers/iio/dac/ad5624r_spi.c index 61bb9d4239ea..e98428df0d44 100644 --- a/drivers/iio/dac/ad5624r_spi.c +++ b/drivers/iio/dac/ad5624r_spi.c @@ -22,7 +22,7 @@ #include "ad5624r.h" static int ad5624r_spi_write(struct spi_device *spi, - u8 cmd, u8 addr, u16 val, u8 len) + u8 cmd, u8 addr, u16 val, u8 shift) { u32 data; u8 msg[3]; @@ -35,7 +35,7 @@ static int ad5624r_spi_write(struct spi_device *spi, * 14-, 12-bit input code followed by 0, 2, or 4 don't care bits, * for the AD5664R, AD5644R, and AD5624R, respectively. */ - data = (0 << 22) | (cmd << 19) | (addr << 16) | (val << (16 - len)); + data = (0 << 22) | (cmd << 19) | (addr << 16) | (val << shift); msg[0] = data >> 16; msg[1] = data >> 8; msg[2] = data; -- cgit v1.2.3 From 815983e9afcb21552e1b9d77e3755d394cbf5249 Mon Sep 17 00:00:00 2001 From: Jan Leupold Date: Wed, 17 Jun 2015 18:21:36 +0200 Subject: iio: adc: at91_adc: allow to use full range of startup time The DT-Property "atmel,adc-startup-time" is stored in an u8 for a microsecond value. When trying to increase the value of STARTUP in Register AT91_ADC_MR some higher values can't be reached. Change the type in function parameter and private structure field from u8 to u32. Signed-off-by: Jan Leupold [nicolas.ferre@atmel.com: change commit message, increase u16 to u32 for startup time] Signed-off-by: Nicolas Ferre Acked-by: Alexandre Belloni Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/adc/at91_adc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c index 8a0eb4a04fb5..7b40925dd4ff 100644 --- a/drivers/iio/adc/at91_adc.c +++ b/drivers/iio/adc/at91_adc.c @@ -182,7 +182,7 @@ struct at91_adc_caps { u8 ts_pen_detect_sensitivity; /* startup time calculate function */ - u32 (*calc_startup_ticks)(u8 startup_time, u32 adc_clk_khz); + u32 (*calc_startup_ticks)(u32 startup_time, u32 adc_clk_khz); u8 num_channels; struct at91_adc_reg_desc registers; @@ -201,7 +201,7 @@ struct at91_adc_state { u8 num_channels; void __iomem *reg_base; struct at91_adc_reg_desc *registers; - u8 startup_time; + u32 startup_time; u8 sample_hold_time; bool sleep_mode; struct iio_trigger **trig; @@ -779,7 +779,7 @@ ret: return ret; } -static u32 calc_startup_ticks_9260(u8 startup_time, u32 adc_clk_khz) +static u32 calc_startup_ticks_9260(u32 startup_time, u32 adc_clk_khz) { /* * Number of ticks needed to cover the startup time of the ADC @@ -790,7 +790,7 @@ static u32 calc_startup_ticks_9260(u8 startup_time, u32 adc_clk_khz) return round_up((startup_time * adc_clk_khz / 1000) - 1, 8) / 8; } -static u32 calc_startup_ticks_9x5(u8 startup_time, u32 adc_clk_khz) +static u32 calc_startup_ticks_9x5(u32 startup_time, u32 adc_clk_khz) { /* * For sama5d3x and at91sam9x5, the formula changes to: -- cgit v1.2.3 From bd7bd0cc3a60e082b17a4f64ce76831aa1c6dffe Mon Sep 17 00:00:00 2001 From: Hartmut Knaack Date: Thu, 18 Jun 2015 00:31:59 +0200 Subject: iio:light:cm3323: clear bitmask before set When setting the bits for integration time, the appropriate bitmask needs to be cleared first. Signed-off-by: Hartmut Knaack Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/light/cm3323.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/light/cm3323.c b/drivers/iio/light/cm3323.c index 869033e48a1f..a1d4905cc9d2 100644 --- a/drivers/iio/light/cm3323.c +++ b/drivers/iio/light/cm3323.c @@ -123,7 +123,7 @@ static int cm3323_set_it_bits(struct cm3323_data *data, int val, int val2) for (i = 0; i < ARRAY_SIZE(cm3323_int_time); i++) { if (val == cm3323_int_time[i].val && val2 == cm3323_int_time[i].val2) { - reg_conf = data->reg_conf; + reg_conf = data->reg_conf & ~CM3323_CONF_IT_MASK; reg_conf |= i << CM3323_CONF_IT_SHIFT; ret = i2c_smbus_write_word_data(data->client, -- cgit v1.2.3 From c13c9da6d86fa9cb6449deb6c71b18ffcf32ae53 Mon Sep 17 00:00:00 2001 From: Hartmut Knaack Date: Mon, 15 Jun 2015 23:48:24 +0200 Subject: iio:accel:bmc150-accel: fix counting direction In bmc150_accel_unregister_triggers() triggers should be unregistered in reverse order of registration. Trigger registration starts with number 0, counting up. In consequence, trigger number needs to be count down here. Signed-off-by: Hartmut Knaack Reviewed-by: Octavian Purdila Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/accel/bmc150-accel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/accel/bmc150-accel.c b/drivers/iio/accel/bmc150-accel.c index 4e70f51c2370..cc5a35750b50 100644 --- a/drivers/iio/accel/bmc150-accel.c +++ b/drivers/iio/accel/bmc150-accel.c @@ -1464,7 +1464,7 @@ static void bmc150_accel_unregister_triggers(struct bmc150_accel_data *data, { int i; - for (i = from; i >= 0; i++) { + for (i = from; i >= 0; i--) { if (data->triggers[i].indio_trig) { iio_trigger_unregister(data->triggers[i].indio_trig); data->triggers[i].indio_trig = NULL; -- cgit v1.2.3 From 40f34b0c75c2a633ba647afec41947d8dd3bc920 Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Sun, 14 Jun 2015 23:09:35 +0200 Subject: iio: light: tcs3414: Fix bug preventing to set integration time the millisecond values in tcs3414_times should be checked against val2, not val, which is always zero. Signed-off-by: Peter Meerwald Reported-by: Stephan Kleisinger Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/light/tcs3414.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/light/tcs3414.c b/drivers/iio/light/tcs3414.c index 71c2bde275aa..f8b1df018abe 100644 --- a/drivers/iio/light/tcs3414.c +++ b/drivers/iio/light/tcs3414.c @@ -185,7 +185,7 @@ static int tcs3414_write_raw(struct iio_dev *indio_dev, if (val != 0) return -EINVAL; for (i = 0; i < ARRAY_SIZE(tcs3414_times); i++) { - if (val == tcs3414_times[i] * 1000) { + if (val2 == tcs3414_times[i] * 1000) { data->timing &= ~TCS3414_INTEG_MASK; data->timing |= i; return i2c_smbus_write_byte_data( -- cgit v1.2.3 From 5646e856db1e3e2b260c6ba732524e5a886770d5 Mon Sep 17 00:00:00 2001 From: Hartmut Knaack Date: Sun, 21 Jun 2015 12:15:50 +0200 Subject: iio:adc:cc10001_adc: fix Kconfig dependency The Cosmic Circuits 10001 ADC driver depends on HAS_IOMEM, HAVE_CLK and REGULATOR together, not just any of these. Signed-off-by: Hartmut Knaack Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/adc/Kconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 7c5565891cb8..eb0cd897714a 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -153,8 +153,7 @@ config DA9150_GPADC config CC10001_ADC tristate "Cosmic Circuits 10001 ADC driver" - depends on HAVE_CLK || REGULATOR - depends on HAS_IOMEM + depends on HAS_IOMEM && HAVE_CLK && REGULATOR select IIO_BUFFER select IIO_TRIGGERED_BUFFER help -- cgit v1.2.3 From 0f16fc8bb38156c842f6976ddbdf4f266e893a1b Mon Sep 17 00:00:00 2001 From: Tiberiu Breana Date: Wed, 1 Jul 2015 15:32:00 +0300 Subject: iio: light: STK3310: un-invert proximity values In accordance with the recent proximity ABI changes, STK3310's proximity readings should be un-inversed in order to return low values for far-away objects and high values for close ones. As consequences of this change, iio event directions have been switched and maximum proximity sensor reference values have also been adjusted in accordance with the real readings. Signed-off-by: Tiberiu Breana Acked-by: Hartmut Knaack Signed-off-by: Jonathan Cameron --- drivers/iio/light/stk3310.c | 53 +++++++++++++++------------------------------ 1 file changed, 17 insertions(+), 36 deletions(-) diff --git a/drivers/iio/light/stk3310.c b/drivers/iio/light/stk3310.c index fee4297d7c8f..c1a218236be5 100644 --- a/drivers/iio/light/stk3310.c +++ b/drivers/iio/light/stk3310.c @@ -43,7 +43,6 @@ #define STK3311_CHIP_ID_VAL 0x1D #define STK3310_PSINT_EN 0x01 #define STK3310_PS_MAX_VAL 0xFFFF -#define STK3310_THRESH_MAX 0xFFFF #define STK3310_DRIVER_NAME "stk3310" #define STK3310_REGMAP_NAME "stk3310_regmap" @@ -84,15 +83,13 @@ static const struct reg_field stk3310_reg_field_flag_psint = REG_FIELD(STK3310_REG_FLAG, 4, 4); static const struct reg_field stk3310_reg_field_flag_nf = REG_FIELD(STK3310_REG_FLAG, 0, 0); -/* - * Maximum PS values with regard to scale. Used to export the 'inverse' - * PS value (high values for far objects, low values for near objects). - */ + +/* Estimate maximum proximity values with regard to measurement scale. */ static const int stk3310_ps_max[4] = { - STK3310_PS_MAX_VAL / 64, - STK3310_PS_MAX_VAL / 16, - STK3310_PS_MAX_VAL / 4, - STK3310_PS_MAX_VAL, + STK3310_PS_MAX_VAL / 640, + STK3310_PS_MAX_VAL / 160, + STK3310_PS_MAX_VAL / 40, + STK3310_PS_MAX_VAL / 10 }; static const int stk3310_scale_table[][2] = { @@ -128,14 +125,14 @@ static const struct iio_event_spec stk3310_events[] = { /* Proximity event */ { .type = IIO_EV_TYPE_THRESH, - .dir = IIO_EV_DIR_FALLING, + .dir = IIO_EV_DIR_RISING, .mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE), }, /* Out-of-proximity event */ { .type = IIO_EV_TYPE_THRESH, - .dir = IIO_EV_DIR_RISING, + .dir = IIO_EV_DIR_FALLING, .mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE), }, @@ -205,23 +202,16 @@ static int stk3310_read_event(struct iio_dev *indio_dev, u8 reg; u16 buf; int ret; - unsigned int index; struct stk3310_data *data = iio_priv(indio_dev); if (info != IIO_EV_INFO_VALUE) return -EINVAL; - /* - * Only proximity interrupts are implemented at the moment. - * Since we're inverting proximity values, the sensor's 'high' - * threshold will become our 'low' threshold, associated with - * 'near' events. Similarly, the sensor's 'low' threshold will - * be our 'high' threshold, associated with 'far' events. - */ + /* Only proximity interrupts are implemented at the moment. */ if (dir == IIO_EV_DIR_RISING) - reg = STK3310_REG_THDL_PS; - else if (dir == IIO_EV_DIR_FALLING) reg = STK3310_REG_THDH_PS; + else if (dir == IIO_EV_DIR_FALLING) + reg = STK3310_REG_THDL_PS; else return -EINVAL; @@ -232,8 +222,7 @@ static int stk3310_read_event(struct iio_dev *indio_dev, dev_err(&data->client->dev, "register read failed\n"); return ret; } - regmap_field_read(data->reg_ps_gain, &index); - *val = swab16(stk3310_ps_max[index] - buf); + *val = swab16(buf); return IIO_VAL_INT; } @@ -257,13 +246,13 @@ static int stk3310_write_event(struct iio_dev *indio_dev, return -EINVAL; if (dir == IIO_EV_DIR_RISING) - reg = STK3310_REG_THDL_PS; - else if (dir == IIO_EV_DIR_FALLING) reg = STK3310_REG_THDH_PS; + else if (dir == IIO_EV_DIR_FALLING) + reg = STK3310_REG_THDL_PS; else return -EINVAL; - buf = swab16(stk3310_ps_max[index] - val); + buf = swab16(val); ret = regmap_bulk_write(data->regmap, reg, &buf, 2); if (ret < 0) dev_err(&client->dev, "failed to set PS threshold!\n"); @@ -334,14 +323,6 @@ static int stk3310_read_raw(struct iio_dev *indio_dev, return ret; } *val = swab16(buf); - if (chan->type == IIO_PROXIMITY) { - /* - * Invert the proximity data so we return low values - * for close objects and high values for far ones. - */ - regmap_field_read(data->reg_ps_gain, &index); - *val = stk3310_ps_max[index] - *val; - } mutex_unlock(&data->lock); return IIO_VAL_INT; case IIO_CHAN_INFO_INT_TIME: @@ -581,8 +562,8 @@ static irqreturn_t stk3310_irq_event_handler(int irq, void *private) } event = IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, 1, IIO_EV_TYPE_THRESH, - (dir ? IIO_EV_DIR_RISING : - IIO_EV_DIR_FALLING)); + (dir ? IIO_EV_DIR_FALLING : + IIO_EV_DIR_RISING)); iio_push_event(indio_dev, event, data->timestamp); /* Reset the interrupt flag */ -- cgit v1.2.3 From 53c8eccb710fbe10ad5ad1e056486f953c4cba18 Mon Sep 17 00:00:00 2001 From: Hartmut Knaack Date: Sat, 4 Jul 2015 17:56:57 +0200 Subject: iio:light:stk3310: Fix REGMAP_I2C dependency The stk3310 driver makes use of regmap_i2c, so this dependency needs to be reflected in Kconfig. Signed-off-by: Hartmut Knaack Signed-off-by: Jonathan Cameron --- drivers/iio/light/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig index e6198b7c9cbf..df995a42d5f3 100644 --- a/drivers/iio/light/Kconfig +++ b/drivers/iio/light/Kconfig @@ -201,6 +201,7 @@ config LTR501 config STK3310 tristate "STK3310 ALS and proximity sensor" depends on I2C + select REGMAP_I2C help Say yes here to get support for the Sensortek STK3310 ambient light and proximity sensor. The STK3311 model is also supported by this -- cgit v1.2.3 From c99389ad3d80eeef0d0980a17e07f41822bda687 Mon Sep 17 00:00:00 2001 From: Teodora Baluta Date: Mon, 29 Jun 2015 15:44:50 +0300 Subject: iio: magnetometer: mmc35240: fix available sampling frequencies Fix the sampling frequencies according to the datasheet (page 8). The datasheet specifies the following available frequencies for continuous mode: 1.5 Hz, 13 Hz, 25 Hz, and 50 Hz. Also fix comments about the ODR to comply with datasheet. Signed-off-by: Teodora Baluta Signed-off-by: Jonathan Cameron --- drivers/iio/magnetometer/mmc35240.c | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/drivers/iio/magnetometer/mmc35240.c b/drivers/iio/magnetometer/mmc35240.c index 7a2ea71c659a..d927397a6ef7 100644 --- a/drivers/iio/magnetometer/mmc35240.c +++ b/drivers/iio/magnetometer/mmc35240.c @@ -84,10 +84,10 @@ #define MMC35240_OTP_START_ADDR 0x1B enum mmc35240_resolution { - MMC35240_16_BITS_SLOW = 0, /* 100 Hz */ - MMC35240_16_BITS_FAST, /* 200 Hz */ - MMC35240_14_BITS, /* 333 Hz */ - MMC35240_12_BITS, /* 666 Hz */ + MMC35240_16_BITS_SLOW = 0, /* 7.92 ms */ + MMC35240_16_BITS_FAST, /* 4.08 ms */ + MMC35240_14_BITS, /* 2.16 ms */ + MMC35240_12_BITS, /* 1.20 ms */ }; enum mmc35240_axis { @@ -100,22 +100,22 @@ static const struct { int sens[3]; /* sensitivity per X, Y, Z axis */ int nfo; /* null field output */ } mmc35240_props_table[] = { - /* 16 bits, 100Hz ODR */ + /* 16 bits, 125Hz ODR */ { {1024, 1024, 1024}, 32768, }, - /* 16 bits, 200Hz ODR */ + /* 16 bits, 250Hz ODR */ { {1024, 1024, 770}, 32768, }, - /* 14 bits, 333Hz ODR */ + /* 14 bits, 450Hz ODR */ { {256, 256, 193}, 8192, }, - /* 12 bits, 666Hz ODR */ + /* 12 bits, 800Hz ODR */ { {64, 64, 48}, 2048, @@ -133,9 +133,15 @@ struct mmc35240_data { int axis_scale[3]; }; -static const int mmc35240_samp_freq[] = {100, 200, 333, 666}; +static const struct { + int val; + int val2; +} mmc35240_samp_freq[] = { {1, 500000}, + {13, 0}, + {25, 0}, + {50, 0} }; -static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("100 200 333 666"); +static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("1.5 13 25 50"); #define MMC35240_CHANNEL(_axis) { \ .type = IIO_MAGN, \ @@ -168,7 +174,8 @@ static int mmc35240_get_samp_freq_index(struct mmc35240_data *data, int i; for (i = 0; i < ARRAY_SIZE(mmc35240_samp_freq); i++) - if (mmc35240_samp_freq[i] == val) + if (mmc35240_samp_freq[i].val == val && + mmc35240_samp_freq[i].val2 == val2) return i; return -EINVAL; } @@ -378,9 +385,9 @@ static int mmc35240_read_raw(struct iio_dev *indio_dev, if (i < 0 || i >= ARRAY_SIZE(mmc35240_samp_freq)) return -EINVAL; - *val = mmc35240_samp_freq[i]; - *val2 = 0; - return IIO_VAL_INT; + *val = mmc35240_samp_freq[i].val; + *val2 = mmc35240_samp_freq[i].val2; + return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; } -- cgit v1.2.3 From 498adaeb898c4eff190d598799bd9b0d607ce051 Mon Sep 17 00:00:00 2001 From: Vlad Dogaru Date: Tue, 30 Jun 2015 14:20:58 +0300 Subject: iio: sx9500: rework error handling of raw readings Fix error handling so that we can power the chip down even if a raw read fails. Reported-by: Hartmut Knaack Signed-off-by: Vlad Dogaru Acked-by: Hartmut Knaack Signed-off-by: Jonathan Cameron --- drivers/iio/proximity/sx9500.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/iio/proximity/sx9500.c b/drivers/iio/proximity/sx9500.c index 01494cd6fa32..21eaa167a784 100644 --- a/drivers/iio/proximity/sx9500.c +++ b/drivers/iio/proximity/sx9500.c @@ -329,20 +329,20 @@ static int sx9500_read_proximity(struct sx9500_data *data, else ret = sx9500_wait_for_sample(data); - if (ret < 0) - return ret; - mutex_lock(&data->mutex); - ret = sx9500_read_prox_data(data, chan, val); if (ret < 0) - goto out; + goto out_dec_data_rdy; - ret = sx9500_dec_chan_users(data, chan->channel); + ret = sx9500_read_prox_data(data, chan, val); if (ret < 0) - goto out; + goto out_dec_data_rdy; ret = sx9500_dec_data_rdy_users(data); + if (ret < 0) + goto out_dec_chan; + + ret = sx9500_dec_chan_users(data, chan->channel); if (ret < 0) goto out; @@ -350,6 +350,8 @@ static int sx9500_read_proximity(struct sx9500_data *data, goto out; +out_dec_data_rdy: + sx9500_dec_data_rdy_users(data); out_dec_chan: sx9500_dec_chan_users(data, chan->channel); out: -- cgit v1.2.3 From 0d1462de0b24fd09284411a3753f24a3d7c67577 Mon Sep 17 00:00:00 2001 From: Vlad Dogaru Date: Tue, 30 Jun 2015 14:20:59 +0300 Subject: iio: sx9500: fix bug in compensation code The initial compensation was mistakingly toggling an extra bit in the control register. Fix this and make sure it's less likely to happen by introducing an additional macro. Reported-by: Hartmut Knaack Signed-off-by: Vlad Dogaru Acked-by: Hartmut Knaack Signed-off-by: Jonathan Cameron --- drivers/iio/proximity/sx9500.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/iio/proximity/sx9500.c b/drivers/iio/proximity/sx9500.c index 21eaa167a784..d260509d6000 100644 --- a/drivers/iio/proximity/sx9500.c +++ b/drivers/iio/proximity/sx9500.c @@ -80,6 +80,7 @@ #define SX9500_COMPSTAT_MASK GENMASK(3, 0) #define SX9500_NUM_CHANNELS 4 +#define SX9500_CHAN_MASK GENMASK(SX9500_NUM_CHANNELS - 1, 0) struct sx9500_data { struct mutex mutex; @@ -802,8 +803,7 @@ static int sx9500_init_compensation(struct iio_dev *indio_dev) unsigned int val; ret = regmap_update_bits(data->regmap, SX9500_REG_PROX_CTRL0, - GENMASK(SX9500_NUM_CHANNELS, 0), - GENMASK(SX9500_NUM_CHANNELS, 0)); + SX9500_CHAN_MASK, SX9500_CHAN_MASK); if (ret < 0) return ret; @@ -823,7 +823,7 @@ static int sx9500_init_compensation(struct iio_dev *indio_dev) out: regmap_update_bits(data->regmap, SX9500_REG_PROX_CTRL0, - GENMASK(SX9500_NUM_CHANNELS, 0), 0); + SX9500_CHAN_MASK, 0); return ret; } -- cgit v1.2.3 From fe5adb917431aafe1324a2455634ed59147df807 Mon Sep 17 00:00:00 2001 From: Hartmut Knaack Date: Sun, 28 Jun 2015 12:31:53 +0200 Subject: iio:light:ltr501: fix variable in ltr501_init When filling data->als_contr, the register content read into status needs to be used, instead of the return status value of regmap_read. Fixes: 8592a7eefa540 ("iio: ltr501: Add support for ltr559 chip") Signed-off-by: Hartmut Knaack Acked-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- drivers/iio/light/ltr501.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c index 1ef7d3773ab9..b5a0e66b5f28 100644 --- a/drivers/iio/light/ltr501.c +++ b/drivers/iio/light/ltr501.c @@ -1302,7 +1302,7 @@ static int ltr501_init(struct ltr501_data *data) if (ret < 0) return ret; - data->als_contr = ret | data->chip_info->als_mode_active; + data->als_contr = status | data->chip_info->als_mode_active; ret = regmap_read(data->regmap, LTR501_PS_CONTR, &status); if (ret < 0) -- cgit v1.2.3 From c42b9e13f98239ec77acf7c4a20003e1cdd9bace Mon Sep 17 00:00:00 2001 From: Hartmut Knaack Date: Sun, 28 Jun 2015 12:31:52 +0200 Subject: iio:light:ltr501: fix regmap dependency The use of regmap in commit 2f2c96338afc requires REGMAP_I2C to be selected, in order to meet all dependencies. Fixes: 2f2c96338afc ("iio: ltr501: Add regmap support.") Signed-off-by: Hartmut Knaack Acked-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- drivers/iio/light/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig index df995a42d5f3..a5c59251ec0e 100644 --- a/drivers/iio/light/Kconfig +++ b/drivers/iio/light/Kconfig @@ -188,6 +188,7 @@ config SENSORS_LM3533 config LTR501 tristate "LTR-501ALS-01 light sensor" depends on I2C + select REGMAP_I2C select IIO_BUFFER select IIO_TRIGGERED_BUFFER help -- cgit v1.2.3 From 06b00f99ca8a0ec79f5d428dfb128abd14162c57 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 29 Jun 2015 09:14:33 +0200 Subject: iio: sx9500: Add missing init in sx9500_buffer_pre{en,dis}able() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/iio/proximity/sx9500.c: In function ‘sx9500_buffer_preenable’: drivers/iio/proximity/sx9500.c:682: warning: ‘ret’ may be used uninitialized in this function drivers/iio/proximity/sx9500.c: In function ‘sx9500_buffer_predisable’: drivers/iio/proximity/sx9500.c:706: warning: ‘ret’ may be used uninitialized in this function If active_scan_mask is empty, it will loop once more over all channels, doing nothing. Signed-off-by: Geert Uytterhoeven Reviewed-by: Vlad Dogaru Signed-off-by: Jonathan Cameron --- drivers/iio/proximity/sx9500.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/iio/proximity/sx9500.c b/drivers/iio/proximity/sx9500.c index d260509d6000..3d756bd8c703 100644 --- a/drivers/iio/proximity/sx9500.c +++ b/drivers/iio/proximity/sx9500.c @@ -682,7 +682,7 @@ out: static int sx9500_buffer_preenable(struct iio_dev *indio_dev) { struct sx9500_data *data = iio_priv(indio_dev); - int ret, i; + int ret = 0, i; mutex_lock(&data->mutex); @@ -706,7 +706,7 @@ static int sx9500_buffer_preenable(struct iio_dev *indio_dev) static int sx9500_buffer_predisable(struct iio_dev *indio_dev) { struct sx9500_data *data = iio_priv(indio_dev); - int ret, i; + int ret = 0, i; iio_triggered_buffer_predisable(indio_dev); -- cgit v1.2.3 From f451957dafe712ab2cd4b7ca8ba9197798115fbe Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Sun, 21 Jun 2015 23:50:21 +0200 Subject: iio: tmp006: Check channel info on write only SAMP_FREQ is writable Will lead to SAMP_FREQ being written by any attempt to write to the other exported attributes and hence a rather unexpected result! Signed-off-by: Peter Meerwald Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/temperature/tmp006.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/iio/temperature/tmp006.c b/drivers/iio/temperature/tmp006.c index fcc49f89b946..8f21f32f9739 100644 --- a/drivers/iio/temperature/tmp006.c +++ b/drivers/iio/temperature/tmp006.c @@ -132,6 +132,9 @@ static int tmp006_write_raw(struct iio_dev *indio_dev, struct tmp006_data *data = iio_priv(indio_dev); int i; + if (mask != IIO_CHAN_INFO_SAMP_FREQ) + return -EINVAL; + for (i = 0; i < ARRAY_SIZE(tmp006_freqs); i++) if ((val == tmp006_freqs[i][0]) && (val2 == tmp006_freqs[i][1])) { -- cgit v1.2.3 From 42e0bb4db0ee3727de8ec1e5e0eb5f2dd686be00 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Thu, 9 Jul 2015 17:01:24 +0100 Subject: staging: vt6655: check ieee80211_bss_conf bssid not NULL Sometimes bssid can go null on failed association. Signed-off-by: Malcolm Priestley Cc: # v3.19+ Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/device_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index ed040fbb7df8..b0c8e235b982 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -1418,7 +1418,7 @@ static void vnt_bss_info_changed(struct ieee80211_hw *hw, priv->current_aid = conf->aid; - if (changed & BSS_CHANGED_BSSID) { + if (changed & BSS_CHANGED_BSSID && conf->bssid) { unsigned long flags; spin_lock_irqsave(&priv->lock, flags); -- cgit v1.2.3 From 7eb7ee30559c9c88ca23fa3b95bd06629669d0a8 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Thu, 9 Jul 2015 17:03:57 +0100 Subject: staging: vt6656: check ieee80211_bss_conf bssid not NULL Sometimes bssid can go null on failed association. Signed-off-by: Malcolm Priestley Cc: # v3.17+ Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/main_usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index f97323f19acf..af572d718135 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -701,7 +701,7 @@ static void vnt_bss_info_changed(struct ieee80211_hw *hw, priv->current_aid = conf->aid; - if (changed & BSS_CHANGED_BSSID) + if (changed & BSS_CHANGED_BSSID && conf->bssid) vnt_mac_set_bssid_addr(priv, (u8 *)conf->bssid); -- cgit v1.2.3 From 2e187a028496ffde88c9441a5dbb4e2cd58abb98 Mon Sep 17 00:00:00 2001 From: Hartmut Knaack Date: Fri, 17 Jul 2015 10:52:24 +0200 Subject: iio:magnetometer:bmc150_magn: add regmap dependency bmc150_magn makes use of REGMAP_I2C, so select it to build always without errors. Fixes: c91746a2361d ("iio: magn: Add support for BMC150 magnetometer") Signed-off-by: Hartmut Knaack Signed-off-by: Jonathan Cameron --- drivers/iio/magnetometer/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/iio/magnetometer/Kconfig b/drivers/iio/magnetometer/Kconfig index dcadfc4f0661..efb9350b0d76 100644 --- a/drivers/iio/magnetometer/Kconfig +++ b/drivers/iio/magnetometer/Kconfig @@ -90,6 +90,7 @@ config IIO_ST_MAGN_SPI_3AXIS config BMC150_MAGN tristate "Bosch BMC150 Magnetometer Driver" depends on I2C + select REGMAP_I2C select IIO_BUFFER select IIO_TRIGGERED_BUFFER help -- cgit v1.2.3 From 6a14925ef22bf6e9e3f5209db50708210d5ee451 Mon Sep 17 00:00:00 2001 From: Hartmut Knaack Date: Fri, 17 Jul 2015 10:52:26 +0200 Subject: iio:magnetometer:bmc150_magn: output intended variable According to the debug/error string, the content of chip_id is supposed to be output, rather than the return value of the previous operation. Fixes: c91746a2361d ("iio: magn: Add support for BMC150 magnetometer") Signed-off-by: Hartmut Knaack Signed-off-by: Jonathan Cameron --- drivers/iio/magnetometer/bmc150_magn.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/iio/magnetometer/bmc150_magn.c b/drivers/iio/magnetometer/bmc150_magn.c index d4c178869991..1347a1f2e46f 100644 --- a/drivers/iio/magnetometer/bmc150_magn.c +++ b/drivers/iio/magnetometer/bmc150_magn.c @@ -706,11 +706,11 @@ static int bmc150_magn_init(struct bmc150_magn_data *data) goto err_poweroff; } if (chip_id != BMC150_MAGN_CHIP_ID_VAL) { - dev_err(&data->client->dev, "Invalid chip id 0x%x\n", ret); + dev_err(&data->client->dev, "Invalid chip id 0x%x\n", chip_id); ret = -ENODEV; goto err_poweroff; } - dev_dbg(&data->client->dev, "Chip id %x\n", ret); + dev_dbg(&data->client->dev, "Chip id %x\n", chip_id); preset = bmc150_magn_presets_table[BMC150_MAGN_DEFAULT_PRESET]; ret = bmc150_magn_set_odr(data, preset.odr); -- cgit v1.2.3 From 8b14821a5c45e3472082c60723ca54cf2fe9c2f3 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Tue, 14 Jul 2015 17:56:52 +0300 Subject: iio: magnetometer: mmc35240: Fix crash in pm suspend We must set i2c client private data at probe in order to correctly retrieve it in pm suspend/resume, preventing the following crash: [ 321.790582] PM: Syncing filesystems ... done. [ 322.364440] PM: Preparing system for mem sleep [ 322.400047] PM: Entering mem sleep [ 322.462178] BUG: unable to handle kernel NULL pointer dereference at 0000036c [ 322.469119] IP: [<80e0b3d2>] mmc35240_suspend+0x12/0x30 [ 322.474291] *pdpt = 000000002fd6f001 *pde = 0000000000000000 [ 322.479967] Oops: 0000 1 PREEMPT SMP [ 322.496516] task: a86d0df0 ti: a8766000 task.ti: a8766000 [ 322.570744] Call Trace: [ 322.573217] [<80c0d2d1>] pm_generic_suspend+0x21/0x30 [ 322.578284] [<80d042ab>] i2c_device_pm_suspend+0x1b/0x30 Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- drivers/iio/magnetometer/mmc35240.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/iio/magnetometer/mmc35240.c b/drivers/iio/magnetometer/mmc35240.c index d927397a6ef7..36a4b53e618b 100644 --- a/drivers/iio/magnetometer/mmc35240.c +++ b/drivers/iio/magnetometer/mmc35240.c @@ -503,6 +503,7 @@ static int mmc35240_probe(struct i2c_client *client, } data = iio_priv(indio_dev); + i2c_set_clientdata(client, indio_dev); data->client = client; data->regmap = regmap; data->res = MMC35240_16_BITS_SLOW; -- cgit v1.2.3 From 3ceaa2c207ccf6933affc8358c0a04beb93e9aa7 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Tue, 14 Jul 2015 17:56:53 +0300 Subject: iio: magnetometer: mmc35240: Fix SET/RESET mask This fixes setting the SET/RESET bit in the REG_CTRL0 register. Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- drivers/iio/magnetometer/mmc35240.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/iio/magnetometer/mmc35240.c b/drivers/iio/magnetometer/mmc35240.c index 36a4b53e618b..e9dfa0e26826 100644 --- a/drivers/iio/magnetometer/mmc35240.c +++ b/drivers/iio/magnetometer/mmc35240.c @@ -202,8 +202,8 @@ static int mmc35240_hw_set(struct mmc35240_data *data, bool set) coil_bit = MMC35240_CTRL0_RESET_BIT; return regmap_update_bits(data->regmap, MMC35240_REG_CTRL0, - MMC35240_CTRL0_REFILL_BIT, - coil_bit); + coil_bit, coil_bit); + } static int mmc35240_init(struct mmc35240_data *data) -- cgit v1.2.3 From 354c879dbd9393ac411049f968474f2bf6c2a495 Mon Sep 17 00:00:00 2001 From: Viorel Suman Date: Tue, 14 Jul 2015 17:56:54 +0300 Subject: iio: magnetometer: mmc35240: fix SET/RESET sequence The RESET operation invoked in the last instance will align in the natural way all 3 axis and the chip top view. Without this, north and south are swapped. Signed-off-by: Viorel Suman Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- drivers/iio/magnetometer/mmc35240.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/iio/magnetometer/mmc35240.c b/drivers/iio/magnetometer/mmc35240.c index e9dfa0e26826..706ebfd6297f 100644 --- a/drivers/iio/magnetometer/mmc35240.c +++ b/drivers/iio/magnetometer/mmc35240.c @@ -222,14 +222,15 @@ static int mmc35240_init(struct mmc35240_data *data) /* * make sure we restore sensor characteristics, by doing - * a RESET/SET sequence + * a SET/RESET sequence, the axis polarity being naturally + * aligned after RESET */ - ret = mmc35240_hw_set(data, false); + ret = mmc35240_hw_set(data, true); if (ret < 0) return ret; usleep_range(MMC53240_WAIT_SET_RESET, MMC53240_WAIT_SET_RESET + 1); - ret = mmc35240_hw_set(data, true); + ret = mmc35240_hw_set(data, false); if (ret < 0) return ret; -- cgit v1.2.3 From c68a67b7adeec240bd79780635dc0ce74d0cb61a Mon Sep 17 00:00:00 2001 From: Crt Mori Date: Sun, 5 Jul 2015 20:03:53 +0200 Subject: iio: mlx96014: Replace offset sign Changed the offset to negative as usual equation is: (raw + offset)*scale and in this case offset should be negative (as we deduct 273.15 Kelvin to get temperature in Celsius). Signed-off-by: Crt Mori Acked-by: Peter Meerwald Signed-off-by: Jonathan Cameron --- drivers/iio/temperature/mlx90614.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/temperature/mlx90614.c b/drivers/iio/temperature/mlx90614.c index cb2e8ad8bfdc..7a2b639eaa96 100644 --- a/drivers/iio/temperature/mlx90614.c +++ b/drivers/iio/temperature/mlx90614.c @@ -204,7 +204,7 @@ static int mlx90614_read_raw(struct iio_dev *indio_dev, *val = ret; return IIO_VAL_INT; case IIO_CHAN_INFO_OFFSET: - *val = 13657; + *val = -13657; *val2 = 500000; return IIO_VAL_INT_PLUS_MICRO; case IIO_CHAN_INFO_SCALE: -- cgit v1.2.3 From bf604a4c44a91cc2ceb60d4643a091b6b32cc999 Mon Sep 17 00:00:00 2001 From: Fugang Duan Date: Thu, 16 Jul 2015 14:49:09 +0800 Subject: iio: adc: vf610: fix the adc register read fail issue Read the register only when the adc register address is 4 byte aligned. (rather than the other way around). Signed-off-by: Haibo Chen Signed-off-by: Fugang Duan Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/adc/vf610_adc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/adc/vf610_adc.c b/drivers/iio/adc/vf610_adc.c index 480f335a0f9f..819632bf1fda 100644 --- a/drivers/iio/adc/vf610_adc.c +++ b/drivers/iio/adc/vf610_adc.c @@ -635,7 +635,7 @@ static int vf610_adc_reg_access(struct iio_dev *indio_dev, struct vf610_adc *info = iio_priv(indio_dev); if ((readval == NULL) || - (!(reg % 4) || (reg > VF610_REG_ADC_PCTL))) + ((reg % 4) || (reg > VF610_REG_ADC_PCTL))) return -EINVAL; *readval = readl(info->regs + reg); -- cgit v1.2.3 From 41be6a0d5aa3c4fcb472f3d44251683b085b00a3 Mon Sep 17 00:00:00 2001 From: Manfred Schlaegl Date: Fri, 10 Jul 2015 22:55:30 +0200 Subject: iio: mcp320x: Fix NULL pointer dereference On reading in_voltage_scale of we got an NULL pointer dereference Oops. The reason for this is, that mcp320x_read_raw tries to access chip_info->resolution from struct mcp320x, but chip_info is never set. chip_info was never set since the driver was added, but there was no acute problem, because it was not referenced. The acute problem exists since b12206e917ac34bec41b9ff93d37d8bd53a2b3bc iio: adc: mcp320x. Add support for more ADCs This patch fixes the issue by setting chip_info in mcp320x_probe. Signed-off-by: Manfred Schlaegl Reviewed-by: Michael Welling Signed-off-by: Jonathan Cameron --- drivers/iio/adc/mcp320x.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/iio/adc/mcp320x.c b/drivers/iio/adc/mcp320x.c index 8d9c9b9215dd..d819823f7257 100644 --- a/drivers/iio/adc/mcp320x.c +++ b/drivers/iio/adc/mcp320x.c @@ -299,6 +299,8 @@ static int mcp320x_probe(struct spi_device *spi) indio_dev->channels = chip_info->channels; indio_dev->num_channels = chip_info->num_channels; + adc->chip_info = chip_info; + adc->transfer[0].tx_buf = &adc->tx_buf; adc->transfer[0].len = sizeof(adc->tx_buf); adc->transfer[1].rx_buf = adc->rx_buf; -- cgit v1.2.3 From c5d0db0690ff0a963dc082e7645268c466bf9a84 Mon Sep 17 00:00:00 2001 From: Martin Kepplinger Date: Sun, 5 Jul 2015 19:50:18 +0200 Subject: iio: mma8452: use iio event type IIO_EV_TYPE_MAG IIO_EV_TYPE_THRESH in rising direction describes an event where the threshold is crossed in rising direction, positive or negative values being possible. This is not the case here. Since the threshold is no signed value and only the magnitude is compared, IIO_EV_TYPE_MAG is what describes the behaviour of these devices, see the sysfs-bus-iio ABI Documentation. Signed-off-by: Martin Kepplinger Signed-off-by: Christoph Muellner Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/accel/mma8452.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c index e8e2077c7244..13ea1ea23328 100644 --- a/drivers/iio/accel/mma8452.c +++ b/drivers/iio/accel/mma8452.c @@ -557,21 +557,21 @@ static void mma8452_transient_interrupt(struct iio_dev *indio_dev) if (src & MMA8452_TRANSIENT_SRC_XTRANSE) iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_X, - IIO_EV_TYPE_THRESH, + IIO_EV_TYPE_MAG, IIO_EV_DIR_RISING), ts); if (src & MMA8452_TRANSIENT_SRC_YTRANSE) iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_Y, - IIO_EV_TYPE_THRESH, + IIO_EV_TYPE_MAG, IIO_EV_DIR_RISING), ts); if (src & MMA8452_TRANSIENT_SRC_ZTRANSE) iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_Z, - IIO_EV_TYPE_THRESH, + IIO_EV_TYPE_MAG, IIO_EV_DIR_RISING), ts); } @@ -644,7 +644,7 @@ static int mma8452_reg_access_dbg(struct iio_dev *indio_dev, static const struct iio_event_spec mma8452_transient_event[] = { { - .type = IIO_EV_TYPE_THRESH, + .type = IIO_EV_TYPE_MAG, .dir = IIO_EV_DIR_RISING, .mask_separate = BIT(IIO_EV_INFO_ENABLE), .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) | -- cgit v1.2.3 From 037e966f2d63896129220112644f32962af6d115 Mon Sep 17 00:00:00 2001 From: Hartmut Knaack Date: Thu, 9 Jul 2015 23:51:29 +0200 Subject: iio:light:stk3310: move device register to end of probe iio_device_register should be the last operation during probe. Therefor move up interrupt setup code and while at it, change the check for invalid values of client->irq to be smaller than zero. Fixes: 3dd477acbdd1 ("iio: light: Add threshold interrupt support for STK3310") As the device_register makes the userspace interfaces of the device available it is possible for requests to come in before the probe sequence has finished. This can lead to unhandled interrupts and similar. Signed-off-by: Hartmut Knaack Reviewed-by: Tiberiu Breana Signed-off-by: Jonathan Cameron --- drivers/iio/light/stk3310.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/iio/light/stk3310.c b/drivers/iio/light/stk3310.c index c1a218236be5..e7e6e5a2b1f8 100644 --- a/drivers/iio/light/stk3310.c +++ b/drivers/iio/light/stk3310.c @@ -608,13 +608,7 @@ static int stk3310_probe(struct i2c_client *client, if (ret < 0) return ret; - ret = iio_device_register(indio_dev); - if (ret < 0) { - dev_err(&client->dev, "device_register failed\n"); - stk3310_set_state(data, STK3310_STATE_STANDBY); - } - - if (client->irq <= 0) + if (client->irq < 0) client->irq = stk3310_gpio_probe(client); if (client->irq >= 0) { @@ -629,6 +623,12 @@ static int stk3310_probe(struct i2c_client *client, client->irq); } + ret = iio_device_register(indio_dev); + if (ret < 0) { + dev_err(&client->dev, "device_register failed\n"); + stk3310_set_state(data, STK3310_STATE_STANDBY); + } + return ret; } -- cgit v1.2.3 From 423ad0c405d87868bd1ab19e8b503e6a41c86caf Mon Sep 17 00:00:00 2001 From: Hartmut Knaack Date: Thu, 9 Jul 2015 23:51:30 +0200 Subject: iio:light:stk3310: make endianness independent of host Data is stored in the device in be16 format. Make use of be16_to_cpu and cpu_to_be16 to have correct endianness on any host architecture. Signed-off-by: Hartmut Knaack Reviewed-by: Tiberiu Breana Signed-off-by: Jonathan Cameron --- drivers/iio/light/stk3310.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/iio/light/stk3310.c b/drivers/iio/light/stk3310.c index e7e6e5a2b1f8..11a027adc204 100644 --- a/drivers/iio/light/stk3310.c +++ b/drivers/iio/light/stk3310.c @@ -200,7 +200,7 @@ static int stk3310_read_event(struct iio_dev *indio_dev, int *val, int *val2) { u8 reg; - u16 buf; + __be16 buf; int ret; struct stk3310_data *data = iio_priv(indio_dev); @@ -222,7 +222,7 @@ static int stk3310_read_event(struct iio_dev *indio_dev, dev_err(&data->client->dev, "register read failed\n"); return ret; } - *val = swab16(buf); + *val = be16_to_cpu(buf); return IIO_VAL_INT; } @@ -235,7 +235,7 @@ static int stk3310_write_event(struct iio_dev *indio_dev, int val, int val2) { u8 reg; - u16 buf; + __be16 buf; int ret; unsigned int index; struct stk3310_data *data = iio_priv(indio_dev); @@ -252,7 +252,7 @@ static int stk3310_write_event(struct iio_dev *indio_dev, else return -EINVAL; - buf = swab16(val); + buf = cpu_to_be16(val); ret = regmap_bulk_write(data->regmap, reg, &buf, 2); if (ret < 0) dev_err(&client->dev, "failed to set PS threshold!\n"); @@ -301,7 +301,7 @@ static int stk3310_read_raw(struct iio_dev *indio_dev, int *val, int *val2, long mask) { u8 reg; - u16 buf; + __be16 buf; int ret; unsigned int index; struct stk3310_data *data = iio_priv(indio_dev); @@ -322,7 +322,7 @@ static int stk3310_read_raw(struct iio_dev *indio_dev, mutex_unlock(&data->lock); return ret; } - *val = swab16(buf); + *val = be16_to_cpu(buf); mutex_unlock(&data->lock); return IIO_VAL_INT; case IIO_CHAN_INFO_INT_TIME: -- cgit v1.2.3 From 0420694dddeb9e269a1ab2129a0119a5cea294a4 Mon Sep 17 00:00:00 2001 From: Mateusz Sylwestrzak Date: Sun, 19 Jul 2015 17:38:56 +0200 Subject: ALSA: hda - Add headset mic support for Acer Aspire V5-573G Acer Aspire V5 with the ALC282 codec is given the wrong value for the 0x19 PIN by the laptop's BIOS. Overriding it with the correct value adds support for the headset microphone which would not otherwise be visible in the system. The fix is based on commit 7819717b1134 with a similar quirk for Acer Aspire with the ALC269 codec. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=96201 Cc: Signed-off-by: Mateusz Sylwestrzak Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index d35cf506a7db..caba66b2311c 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -5061,7 +5061,7 @@ static const struct hda_fixup alc269_fixups[] = { { 0x14, 0x90170110 }, { 0x17, 0x40000008 }, { 0x18, 0x411111f0 }, - { 0x19, 0x411111f0 }, + { 0x19, 0x01a1913c }, { 0x1a, 0x411111f0 }, { 0x1b, 0x411111f0 }, { 0x1d, 0x40f89b2d }, -- cgit v1.2.3 From 033ea349a7cd1aa15357cd6575de35188fc85b9a Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Thu, 16 Jul 2015 10:39:24 +0200 Subject: ALSA: hda - Fix Skylake codec timeout When the controller is powered up but the HDMI codec is powered down on Skylake, the power well is turned off. When the codec is then powered up again, we need to poke the codec a little extra to make sure it wakes up. Otherwise we'll get sad "no response from codec" messages and broken audio. This also changes azx_runtime_resume to actually call snd_hdac_set_codec_wakeup for Skylake (before STATETS read). (Otherwise it would only have been called for Haswell and Broadwell, which both do not need it, so this probably was not the author's intention.) Signed-off-by: David Henningsson Reviewed-by: Libin Yang Signed-off-by: Takashi Iwai --- sound/hda/hdac_i915.c | 5 ++++- sound/pci/hda/hda_intel.c | 18 ++++++++++-------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/sound/hda/hdac_i915.c b/sound/hda/hdac_i915.c index 442500e06b7c..5676b849379d 100644 --- a/sound/hda/hdac_i915.c +++ b/sound/hda/hdac_i915.c @@ -56,8 +56,11 @@ int snd_hdac_display_power(struct hdac_bus *bus, bool enable) enable ? "enable" : "disable"); if (enable) { - if (!bus->i915_power_refcount++) + if (!bus->i915_power_refcount++) { acomp->ops->get_power(acomp->dev); + snd_hdac_set_codec_wakeup(bus, true); + snd_hdac_set_codec_wakeup(bus, false); + } } else { WARN_ON(!bus->i915_power_refcount); if (!--bus->i915_power_refcount) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index ca151b45eeef..996223706676 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -979,14 +979,16 @@ static int azx_runtime_resume(struct device *dev) if (!azx_has_pm_runtime(chip)) return 0; - if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL - && hda->need_i915_power) { - bus = azx_bus(chip); - snd_hdac_display_power(bus, true); - haswell_set_bclk(hda); - /* toggle codec wakeup bit for STATESTS read */ - snd_hdac_set_codec_wakeup(bus, true); - snd_hdac_set_codec_wakeup(bus, false); + if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) { + bus = azx_bus(chip); + if (hda->need_i915_power) { + snd_hdac_display_power(bus, true); + haswell_set_bclk(hda); + } else { + /* toggle codec wakeup bit for STATESTS read */ + snd_hdac_set_codec_wakeup(bus, true); + snd_hdac_set_codec_wakeup(bus, false); + } } /* Read STATESTS before controller reset */ -- cgit v1.2.3 From 27aa2e3a3c99d3319de12ada0d292e33f5831e60 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 8 Jul 2015 15:12:06 +0200 Subject: pinctrl: abx500: remove strict mode Commit a21763a0b1e5a5ab8310f581886d04beadc16616 "pinctrl: nomadik: activate strict mux mode" put all Nomadik pin controllers to strict mode. This was not good on the Snowball platform: the muxing of GPIOs to different pins is done with hogs in the DTS file, and then these GPIOs are used by offset, relying on hogs to mux the pins. Since that means the pin controller "owns" the pins and at the same time we have a GPIO user, this pin controller is by definition not strict. Signed-off-by: Linus Walleij --- drivers/pinctrl/nomadik/pinctrl-abx500.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/pinctrl/nomadik/pinctrl-abx500.c b/drivers/pinctrl/nomadik/pinctrl-abx500.c index 557d0f2a3031..97681fac082e 100644 --- a/drivers/pinctrl/nomadik/pinctrl-abx500.c +++ b/drivers/pinctrl/nomadik/pinctrl-abx500.c @@ -787,7 +787,6 @@ static const struct pinmux_ops abx500_pinmux_ops = { .set_mux = abx500_pmx_set, .gpio_request_enable = abx500_gpio_request_enable, .gpio_disable_free = abx500_gpio_disable_free, - .strict = true, }; static int abx500_get_groups_cnt(struct pinctrl_dev *pctldev) -- cgit v1.2.3 From 61bb3aef92a4d102382f399eafccd5c72be6fdf2 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Fri, 26 Jun 2015 01:40:56 +0300 Subject: sh-pfc: fix sparse GPIOs for R-Car SoCs The PFC driver causes the kernel to hang on the R-Car gen2 SoC based boards when the CPU_ALL_PORT() macro is fixed to reflect the reality, i.e. when the GPIO space becomes actually sparse. This happens because the _GP_GPIO() macro includes an indexed initializer which causes the "holes" (array entries filled with all 0s) between the groups of the existing GPIOs; and the driver can't cope with that. There seems to be no reason to use the indexed initializer, so we can remove the index specifier and so avoid the "holes". Signed-off-by: Sergei Shtylyov Acked-by: Laurent Pinchart Tested-by: Geert Uytterhoeven Signed-off-by: Linus Walleij --- drivers/pinctrl/sh-pfc/sh_pfc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/sh-pfc/sh_pfc.h b/drivers/pinctrl/sh-pfc/sh_pfc.h index c7508d5f6886..0874cfee6889 100644 --- a/drivers/pinctrl/sh-pfc/sh_pfc.h +++ b/drivers/pinctrl/sh-pfc/sh_pfc.h @@ -224,7 +224,7 @@ struct sh_pfc_soc_info { /* PINMUX_GPIO_GP_ALL - Expand to a list of sh_pfc_pin entries */ #define _GP_GPIO(bank, _pin, _name, sfx) \ - [(bank * 32) + _pin] = { \ + { \ .pin = (bank * 32) + _pin, \ .name = __stringify(_name), \ .enum_id = _name##_DATA, \ -- cgit v1.2.3 From c10372e615b8f790d30cbfcf59e43908ca42bf1a Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Mon, 6 Jul 2015 18:13:37 +0300 Subject: pinctrl: single: ensure pcs irq will not be forced threaded The PSC IRQ is requested using request_irq() API and as result it can be forced to be threaded IRQ in RT-Kernel if PCS_QUIRK_HAS_SHARED_IRQ is enabled for pinctrl domain. As result, following 'possible irq lock inversion dependency' report can be seen: ========================================================= [ INFO: possible irq lock inversion dependency detected ] 3.14.43-rt42-00360-g96ff499-dirty #24 Not tainted --------------------------------------------------------- irq/369-pinctrl/927 just changed the state of lock: (&pcs->lock){+.....}, at: [] pcs_irq_handle+0x48/0x9c but this lock was taken by another, HARDIRQ-safe lock in the past: (&irq_desc_lock_class){-.....} and interrupts could create inverse lock ordering between them. other info that might help us debug this: Possible interrupt unsafe locking scenario: CPU0 CPU1 ---- ---- lock(&pcs->lock); local_irq_disable(); lock(&irq_desc_lock_class); lock(&pcs->lock); lock(&irq_desc_lock_class); *** DEADLOCK *** no locks held by irq/369-pinctrl/927. the shortest dependencies between 2nd lock and 1st lock: -> (&irq_desc_lock_class){-.....} ops: 58724 { IN-HARDIRQ-W at: [] lock_acquire+0x9c/0x158 [] _raw_spin_lock+0x48/0x58 [] handle_fasteoi_irq+0x24/0x15c [] generic_handle_irq+0x3c/0x4c [] handle_IRQ+0x50/0xa0 [] gic_handle_irq+0x3c/0x6c [] __irq_svc+0x44/0x8c [] arch_cpu_idle+0x40/0x4c [] cpu_startup_entry+0x270/0x2e0 [] rest_init+0xd4/0xe4 [] start_kernel+0x3d0/0x3dc [<80008084>] 0x80008084 INITIAL USE at: [] lock_acquire+0x9c/0x158 [] _raw_spin_lock_irqsave+0x54/0x68 [] __irq_get_desc_lock+0x64/0xa4 [] irq_set_chip+0x30/0x78 [] irq_set_chip_and_handler_name+0x24/0x3c [] gic_irq_domain_map+0x48/0xb4 [] irq_domain_associate+0x84/0x1d4 [] irq_create_mapping+0x80/0x11c [] irq_create_of_mapping+0x80/0x120 [] irq_of_parse_and_map+0x34/0x3c [] omap_dm_timer_init_one+0x90/0x30c [] omap5_realtime_timer_init+0x8c/0x48c [] time_init+0x28/0x38 [] start_kernel+0x240/0x3dc [<80008084>] 0x80008084 } ... key at: [] irq_desc_lock_class+0x0/0x8 ... acquired at: [] _raw_spin_lock+0x48/0x58 [] pcs_irq_unmask+0x58/0xa0 [] irq_enable+0x38/0x48 [] irq_startup+0x78/0x7c [] __setup_irq+0x4a8/0x4f4 [] request_threaded_irq+0xb8/0x138 [] omap_8250_startup+0x4c/0x148 [] serial8250_startup+0x24/0x30 [] uart_startup.part.9+0x5c/0x1b4 [] uart_open+0xf4/0x16c [] tty_open+0x170/0x61c [] chrdev_open+0xbc/0x1b4 [] do_dentry_open+0x1e8/0x2bc [] finish_open+0x44/0x5c [] do_last.isra.47+0x710/0xca0 [] path_openat+0xc4/0x640 [] do_filp_open+0x3c/0x98 [] do_sys_open+0x114/0x1d8 [] SyS_open+0x28/0x2c [] kernel_init_freeable+0x168/0x1e4 [] kernel_init+0x1c/0xf8 [] ret_from_fork+0x14/0x20 -> (&pcs->lock){+.....} ops: 65 { HARDIRQ-ON-W at: [] lock_acquire+0x9c/0x158 [] _raw_spin_lock+0x48/0x58 [] pcs_irq_handle+0x48/0x9c [] pcs_irq_handler+0x1c/0x28 [] irq_forced_thread_fn+0x30/0x74 [] irq_thread+0x158/0x1c4 [] kthread+0xd4/0xe8 [] ret_from_fork+0x14/0x20 INITIAL USE at: [] lock_acquire+0x9c/0x158 [] _raw_spin_lock_irqsave+0x54/0x68 [] pcs_enable+0x7c/0xe8 [] pinmux_enable_setting+0x178/0x220 [] pinctrl_select_state+0x110/0x194 [] pinctrl_bind_pins+0x7c/0x108 [] driver_probe_device+0x70/0x254 [] __driver_attach+0x9c/0xa0 [] bus_for_each_dev+0x78/0xac [] driver_attach+0x2c/0x30 [] bus_add_driver+0x15c/0x204 [] driver_register+0x88/0x108 [] __platform_driver_register+0x64/0x6c [] omap_hsmmc_driver_init+0x1c/0x20 [] do_one_initcall+0x110/0x170 [] kernel_init_freeable+0x140/0x1e4 [] kernel_init+0x1c/0xf8 [] ret_from_fork+0x14/0x20 } ... key at: [] __key.18572+0x0/0x8 ... acquired at: [] mark_lock+0x388/0x76c [] __lock_acquire+0x6d0/0x1f98 [] lock_acquire+0x9c/0x158 [] _raw_spin_lock+0x48/0x58 [] pcs_irq_handle+0x48/0x9c [] pcs_irq_handler+0x1c/0x28 [] irq_forced_thread_fn+0x30/0x74 [] irq_thread+0x158/0x1c4 [] kthread+0xd4/0xe8 [] ret_from_fork+0x14/0x20 stack backtrace: CPU: 1 PID: 927 Comm: irq/369-pinctrl Not tainted 3.14.43-rt42-00360-g96ff499-dirty #24 [] (unwind_backtrace) from [] (show_stack+0x20/0x24) [] (show_stack) from [] (dump_stack+0x84/0xd0) [] (dump_stack) from [] (print_irq_inversion_bug+0x1d0/0x21c) [] (print_irq_inversion_bug) from [] (check_usage_backwards+0xb4/0x11c) [] (check_usage_backwards) from [] (mark_lock+0x388/0x76c) [] (mark_lock) from [] (__lock_acquire+0x6d0/0x1f98) [] (__lock_acquire) from [] (lock_acquire+0x9c/0x158) [] (lock_acquire) from [] (_raw_spin_lock+0x48/0x58) [] (_raw_spin_lock) from [] (pcs_irq_handle+0x48/0x9c) [] (pcs_irq_handle) from [] (pcs_irq_handler+0x1c/0x28) [] (pcs_irq_handler) from [] (irq_forced_thread_fn+0x30/0x74) [] (irq_forced_thread_fn) from [] (irq_thread+0x158/0x1c4) [] (irq_thread) from [] (kthread+0xd4/0xe8) [] (kthread) from [] (ret_from_fork+0x14/0x20) To fix it use IRQF_NO_THREAD to ensure that pcs irq will not be forced threaded. Cc: Tony Lindgren Cc: Sebastian Andrzej Siewior Signed-off-by: Grygorii Strashko Acked-by: Tony Lindgren Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-single.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c index b2de09d3b1a0..0b8d480171a3 100644 --- a/drivers/pinctrl/pinctrl-single.c +++ b/drivers/pinctrl/pinctrl-single.c @@ -1760,7 +1760,8 @@ static int pcs_irq_init_chained_handler(struct pcs_device *pcs, int res; res = request_irq(pcs_soc->irq, pcs_irq_handler, - IRQF_SHARED | IRQF_NO_SUSPEND, + IRQF_SHARED | IRQF_NO_SUSPEND | + IRQF_NO_THREAD, name, pcs_soc); if (res) { pcs_soc->irq = -1; -- cgit v1.2.3 From 714b1dd8f72e39ef4bc0f38f7f341bb1d57d98bf Mon Sep 17 00:00:00 2001 From: Jonathan Bell Date: Tue, 30 Jun 2015 12:35:39 +0100 Subject: pinctrl: bcm2835: Clear the event latch register when disabling interrupts It's possible to hit a race condition if interrupts are generated on a GPIO pin when the IRQ line in question is being disabled. If the interrupt is freed, bcm2835_gpio_irq_disable() is called which disables the event generation sources (edge, level). If an event occurred between the last disabling of hard IRQs and the write to the event source registers, a bit would be set in the GPIO event detect register (GPEDSn) which goes unacknowledged by bcm2835_gpio_irq_handler() so Linux complains loudly. There is no per-GPIO mask register, so when disabling GPIO interrupts write 1 to the relevant bit in GPEDSn to clear out any stale events. Signed-off-by: Jonathan Bell Acked-by: Stephen Warren Signed-off-by: Linus Walleij --- drivers/pinctrl/bcm/pinctrl-bcm2835.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c index efcf2a2b3975..6177315ab74e 100644 --- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c +++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c @@ -473,6 +473,8 @@ static void bcm2835_gpio_irq_disable(struct irq_data *data) spin_lock_irqsave(&pc->irq_lock[bank], flags); bcm2835_gpio_irq_config(pc, gpio, false); + /* Clear events that were latched prior to clearing event sources */ + bcm2835_gpio_set_bit(pc, GPEDS0, gpio); clear_bit(offset, &pc->enabled_irq_map[bank]); spin_unlock_irqrestore(&pc->irq_lock[bank], flags); } -- cgit v1.2.3 From 9571b25df1dbf4db17191b54f59734e8b77fd591 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 17 Jul 2015 09:38:43 +0200 Subject: Subject: pinctrl: imx1-core: Fix debug output in .pin_config_set callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit imx1_pinconf_set assumes that the array of pins in struct imx1_pinctrl_soc_info can be indexed by pin id to get the pinctrl_pin_desc for a pin. This used to be correct up to commit 607af165c047 which removed some entries from the array and so made it wrong to access the array by pin id. The result of this bug is a wrong pin name in the output for small pin ids and an oops for the bigger ones. This patch is the result of a discussion that includes patches by Markus Pargmann and Chris Ruehl. Fixes: 607af165c047 ("pinctrl: i.MX27: Remove nonexistent pad definitions") Cc: stable@vger.kernel.org Reported-by: Chris Ruehl Signed-off-by: Uwe Kleine-König Reviewed-by: Markus Pargmann Signed-off-by: Linus Walleij --- drivers/pinctrl/freescale/pinctrl-imx1-core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/pinctrl/freescale/pinctrl-imx1-core.c b/drivers/pinctrl/freescale/pinctrl-imx1-core.c index 5fd4437cee15..88a7fac11bd4 100644 --- a/drivers/pinctrl/freescale/pinctrl-imx1-core.c +++ b/drivers/pinctrl/freescale/pinctrl-imx1-core.c @@ -403,14 +403,13 @@ static int imx1_pinconf_set(struct pinctrl_dev *pctldev, unsigned num_configs) { struct imx1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev); - const struct imx1_pinctrl_soc_info *info = ipctl->info; int i; for (i = 0; i != num_configs; ++i) { imx1_write_bit(ipctl, pin_id, configs[i] & 0x01, MX1_PUEN); dev_dbg(ipctl->dev, "pinconf set pullup pin %s\n", - info->pins[pin_id].name); + pin_desc_get(pctldev, pin_id)->name); } return 0; -- cgit v1.2.3 From 681ccdcc756f17f847beba5ac4cd3d03e0949489 Mon Sep 17 00:00:00 2001 From: Joachim Eastwood Date: Wed, 15 Jul 2015 00:25:26 +0200 Subject: pinctrl: lpc18xx: fix schmitt trigger setup The param_val variable is what determines if schmitt trigger is enabled on a pin or not. A typo here mean that schmitt trigger was always enabled for standard and i2c pins. Signed-off-by: Joachim Eastwood Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-lpc18xx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/pinctrl/pinctrl-lpc18xx.c b/drivers/pinctrl/pinctrl-lpc18xx.c index ef0b697639a7..347c763a6a78 100644 --- a/drivers/pinctrl/pinctrl-lpc18xx.c +++ b/drivers/pinctrl/pinctrl-lpc18xx.c @@ -823,7 +823,7 @@ static int lpc18xx_pconf_set_i2c0(struct pinctrl_dev *pctldev, break; case PIN_CONFIG_INPUT_SCHMITT_ENABLE: - if (param) + if (param_val) *reg &= ~(LPC18XX_SCU_I2C0_ZIF << shift); else *reg |= (LPC18XX_SCU_I2C0_ZIF << shift); @@ -876,7 +876,7 @@ static int lpc18xx_pconf_set_pin(struct pinctrl_dev *pctldev, break; case PIN_CONFIG_INPUT_SCHMITT_ENABLE: - if (param) + if (param_val) *reg &= ~LPC18XX_SCU_PIN_ZIF; else *reg |= LPC18XX_SCU_PIN_ZIF; -- cgit v1.2.3 From 5022813ddb28b7679e8285812d52aaeb7e1e7657 Mon Sep 17 00:00:00 2001 From: Maruthi Srinivas Bayyavarapu Date: Mon, 20 Jul 2015 19:56:18 +0530 Subject: ALSA: hda: add new AMD PCI IDs with proper driver caps Fixes audio problems on newer asics Signed-off-by: Maruthi Bayyavarapu Cc: stable@vger.kernel.org Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 996223706676..f581b12211e8 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2184,6 +2184,8 @@ static const struct pci_device_id azx_ids[] = { /* ATI HDMI */ { PCI_DEVICE(0x1002, 0x1308), .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS }, + { PCI_DEVICE(0x1002, 0x157a), + .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS }, { PCI_DEVICE(0x1002, 0x793b), .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, { PCI_DEVICE(0x1002, 0x7919), @@ -2238,8 +2240,14 @@ static const struct pci_device_id azx_ids[] = { .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS }, { PCI_DEVICE(0x1002, 0xaab0), .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS }, + { PCI_DEVICE(0x1002, 0xaac0), + .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS }, { PCI_DEVICE(0x1002, 0xaac8), .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS }, + { PCI_DEVICE(0x1002, 0xaad8), + .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS }, + { PCI_DEVICE(0x1002, 0xaae8), + .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS }, /* VIA VT8251/VT8237A */ { PCI_DEVICE(0x1106, 0x3288), .driver_data = AZX_DRIVER_VIA | AZX_DCAPS_POSFIX_VIA }, -- cgit v1.2.3 From 4696b8874d7de39850931888bc9f2aa12d29fb46 Mon Sep 17 00:00:00 2001 From: Lu Baolu Date: Thu, 4 Jun 2015 20:44:14 +0800 Subject: usb: ulpi: ulpi_init should be executed in subsys_initcall Phy drivers and the ulpi interface providers depend on the registration of the ulpi bus. Ulpi registers the bus in module_init(). This could cause unnecessary bus users' probe delays. i.e. unnecessary -EPROBE_DEFER happening on ulpi_drivers in case they're registered before ulpi bus itself. Reported-by: Zhuo Qiuxu Signed-off-by: Lu Baolu Acked-by: Heikki Krogerus Signed-off-by: Felipe Balbi --- drivers/usb/common/ulpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c index 0e6f968e93fe..01c0c0477a9e 100644 --- a/drivers/usb/common/ulpi.c +++ b/drivers/usb/common/ulpi.c @@ -242,7 +242,7 @@ static int __init ulpi_init(void) { return bus_register(&ulpi_bus); } -module_init(ulpi_init); +subsys_initcall(ulpi_init); static void __exit ulpi_exit(void) { -- cgit v1.2.3 From 53e20f2eb161fbe9eea28b54dccc870cec94eca2 Mon Sep 17 00:00:00 2001 From: Alexey Khoroshilov Date: Sun, 19 Jul 2015 23:13:28 +0700 Subject: usb: gadget: mv_udc_core: fix phy_regs I/O memory leak There was an omission in transition to devm_xxx resource handling. iounmap(udc->phy_regs) were removed, but ioremap() was left without devm_. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov Fixes: 3517c31a8ece6 ("usb: gadget: mv_udc: use devm_xxx for probe") Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/mv_udc_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/udc/mv_udc_core.c b/drivers/usb/gadget/udc/mv_udc_core.c index d32160d6463f..5da37c957b53 100644 --- a/drivers/usb/gadget/udc/mv_udc_core.c +++ b/drivers/usb/gadget/udc/mv_udc_core.c @@ -2167,7 +2167,7 @@ static int mv_udc_probe(struct platform_device *pdev) return -ENODEV; } - udc->phy_regs = ioremap(r->start, resource_size(r)); + udc->phy_regs = devm_ioremap(&pdev->dev, r->start, resource_size(r)); if (udc->phy_regs == NULL) { dev_err(&pdev->dev, "failed to map phy I/O memory\n"); return -EBUSY; -- cgit v1.2.3 From 7ace8fc8219e4cbbfd5b4790390d9a01a2541cdf Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Mon, 13 Jul 2015 18:10:05 +0900 Subject: usb: gadget: udc: core: Fix argument of dma_map_single for IOMMU The dma_map_single and dma_unmap_single should set "gadget->dev.parent" instead of "&gadget->dev" in the first argument because the parent has a udc controller's device pointer. Otherwise, iommu functions are not called in ARM environment. Signed-off-by: Yoshihiro Shimoda Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/udc-core.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/usb/gadget/udc/udc-core.c b/drivers/usb/gadget/udc/udc-core.c index d69c35558f68..362ee8af5fce 100644 --- a/drivers/usb/gadget/udc/udc-core.c +++ b/drivers/usb/gadget/udc/udc-core.c @@ -60,13 +60,15 @@ static DEFINE_MUTEX(udc_lock); int usb_gadget_map_request(struct usb_gadget *gadget, struct usb_request *req, int is_in) { + struct device *dev = gadget->dev.parent; + if (req->length == 0) return 0; if (req->num_sgs) { int mapped; - mapped = dma_map_sg(&gadget->dev, req->sg, req->num_sgs, + mapped = dma_map_sg(dev, req->sg, req->num_sgs, is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); if (mapped == 0) { dev_err(&gadget->dev, "failed to map SGs\n"); @@ -75,11 +77,11 @@ int usb_gadget_map_request(struct usb_gadget *gadget, req->num_mapped_sgs = mapped; } else { - req->dma = dma_map_single(&gadget->dev, req->buf, req->length, + req->dma = dma_map_single(dev, req->buf, req->length, is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); - if (dma_mapping_error(&gadget->dev, req->dma)) { - dev_err(&gadget->dev, "failed to map buffer\n"); + if (dma_mapping_error(dev, req->dma)) { + dev_err(dev, "failed to map buffer\n"); return -EFAULT; } } @@ -95,12 +97,12 @@ void usb_gadget_unmap_request(struct usb_gadget *gadget, return; if (req->num_mapped_sgs) { - dma_unmap_sg(&gadget->dev, req->sg, req->num_mapped_sgs, + dma_unmap_sg(gadget->dev.parent, req->sg, req->num_mapped_sgs, is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); req->num_mapped_sgs = 0; } else { - dma_unmap_single(&gadget->dev, req->dma, req->length, + dma_unmap_single(gadget->dev.parent, req->dma, req->length, is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); } } -- cgit v1.2.3 From 75993300d008f418ee2569a632185fc1d7d50674 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Wed, 15 Jul 2015 15:26:19 +0300 Subject: virtio_net: don't require ANY_LAYOUT with VERSION_1 ANY_LAYOUT is a compatibility feature. It's implied for VERSION_1 devices, and non-transitional devices might not offer it. Change code to behave accordingly. Signed-off-by: Michael S. Tsirkin Reviewed-by: Paolo Bonzini Reviewed-by: Stefan Hajnoczi Signed-off-by: David S. Miller --- drivers/net/virtio_net.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 63c7810e1545..7fbca37a1adf 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -1828,7 +1828,8 @@ static int virtnet_probe(struct virtio_device *vdev) else vi->hdr_len = sizeof(struct virtio_net_hdr); - if (virtio_has_feature(vdev, VIRTIO_F_ANY_LAYOUT)) + if (virtio_has_feature(vdev, VIRTIO_F_ANY_LAYOUT) || + virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) vi->any_header_sg = true; if (virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_VQ)) -- cgit v1.2.3 From 40a7166044a6fce3dbcaa8b5c89845980c218c98 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Wed, 15 Jul 2015 10:07:07 -0400 Subject: net: dsa: mv88e6xxx: fix fid_mask when leaving bridge The mv88e6xxx_priv_state structure contains an fid_mask, where 1 means the FID is free to use, 0 means the FID is in use. This patch fixes the bit clear in mv88e6xxx_leave_bridge() when assigning a new FID to a port. Example scenario: I have 7 ports, port 5 is CPU, port 6 is unused (no PHY). After setting the ports 0, 1 and 2 in bridge br0, and ports 3 and 4 in bridge br1, I have the following fid_mask: 0b111110010110 (0xf96). Indeed, br0 uses FID 0, and br1 uses FID 3. After setting nomaster for port 0, I get the wrong fid_mask: 0b10 (0x2). With this patch we correctly get 0b111110010100 (0xf94), meaning port 0 uses FID 1, br0 uses FID 0, and br1 uses FID 3. Signed-off-by: Vivien Didelot Reviewed-by: Guenter Roeck Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index fd8547c2b79d..561342466076 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -1163,7 +1163,7 @@ int mv88e6xxx_leave_bridge(struct dsa_switch *ds, int port, u32 br_port_mask) newfid = __ffs(ps->fid_mask); ps->fid[port] = newfid; - ps->fid_mask &= (1 << newfid); + ps->fid_mask &= ~(1 << newfid); ps->bridge_mask[fid] &= ~(1 << port); ps->bridge_mask[newfid] = 1 << port; -- cgit v1.2.3 From 06f6d1094aa0992432b1e2a0920b0ee86ccd83bf Mon Sep 17 00:00:00 2001 From: Nikolay Aleksandrov Date: Wed, 15 Jul 2015 21:52:51 +0200 Subject: bonding: fix destruction of bond with devices different from arphrd_ether When the bonding is being unloaded and the netdevice notifier is unregistered it executes NETDEV_UNREGISTER for each device which should remove the bond's proc entry but if the device enslaved is not of ARPHRD_ETHER type and is in front of the bonding, it may execute bond_release_and_destroy() first which would release the last slave and destroy the bond device leaving the proc entry and thus we will get the following error (with dynamic debug on for bond_netdev_event to see the events order): [ 908.963051] eql: event: 9 [ 908.963052] eql: IFF_SLAVE [ 908.963054] eql: event: 2 [ 908.963056] eql: IFF_SLAVE [ 908.963058] eql: event: 6 [ 908.963059] eql: IFF_SLAVE [ 908.963110] bond0: Releasing active interface eql [ 908.976168] bond0: Destroying bond bond0 [ 908.976266] bond0 (unregistering): Released all slaves [ 908.984097] ------------[ cut here ]------------ [ 908.984107] WARNING: CPU: 0 PID: 1787 at fs/proc/generic.c:575 remove_proc_entry+0x112/0x160() [ 908.984110] remove_proc_entry: removing non-empty directory 'net/bonding', leaking at least 'bond0' [ 908.984111] Modules linked in: bonding(-) eql(O) 9p nfsd auth_rpcgss oid_registry nfs_acl nfs lockd grace fscache sunrpc crct10dif_pclmul crc32_pclmul crc32c_intel ghash_clmulni_intel ppdev qxl drm_kms_helper snd_hda_codec_generic aesni_intel ttm aes_x86_64 glue_helper pcspkr lrw gf128mul ablk_helper cryptd snd_hda_intel virtio_console snd_hda_codec psmouse serio_raw snd_hwdep snd_hda_core 9pnet_virtio 9pnet evdev joydev drm virtio_balloon snd_pcm snd_timer snd soundcore i2c_piix4 i2c_core pvpanic acpi_cpufreq parport_pc parport processor thermal_sys button autofs4 ext4 crc16 mbcache jbd2 hid_generic usbhid hid sg sr_mod cdrom ata_generic virtio_blk virtio_net floppy ata_piix e1000 libata ehci_pci virtio_pci scsi_mod uhci_hcd ehci_hcd virtio_ring virtio usbcore usb_common [last unloaded: bonding] [ 908.984168] CPU: 0 PID: 1787 Comm: rmmod Tainted: G W O 4.2.0-rc2+ #8 [ 908.984170] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011 [ 908.984172] 0000000000000000 ffffffff81732d41 ffffffff81525b34 ffff8800358dfda8 [ 908.984175] ffffffff8106c521 ffff88003595af78 ffff88003595af40 ffff88003e3a4280 [ 908.984178] ffffffffa058d040 0000000000000000 ffffffff8106c59a ffffffff8172ebd0 [ 908.984181] Call Trace: [ 908.984188] [] ? dump_stack+0x40/0x50 [ 908.984193] [] ? warn_slowpath_common+0x81/0xb0 [ 908.984196] [] ? warn_slowpath_fmt+0x4a/0x50 [ 908.984199] [] ? remove_proc_entry+0x112/0x160 [ 908.984205] [] ? bond_destroy_proc_dir+0x26/0x30 [bonding] [ 908.984208] [] ? bond_net_exit+0x8e/0xa0 [bonding] [ 908.984217] [] ? ops_exit_list.isra.4+0x37/0x70 [ 908.984225] [] ? unregister_pernet_operations+0x8d/0xd0 [ 908.984228] [] ? unregister_pernet_subsys+0x1d/0x30 [ 908.984232] [] ? bonding_exit+0x23/0xdba [bonding] [ 908.984236] [] ? SyS_delete_module+0x18a/0x250 [ 908.984241] [] ? task_work_run+0x89/0xc0 [ 908.984244] [] ? entry_SYSCALL_64_fastpath+0x16/0x75 [ 908.984247] ---[ end trace 7c006ed4abbef24b ]--- Thus remove the proc entry manually if bond_release_and_destroy() is used. Because of the checks in bond_remove_proc_entry() it's not a problem for a bond device to change namespaces (the bug fixed by the Fixes commit) but since commit f9399814927ad ("bonding: Don't allow bond devices to change network namespaces.") that can't happen anyway. Reported-by: Carol Soto Signed-off-by: Nikolay Aleksandrov Fixes: a64d49c3dd50 ("bonding: Manage /proc/net/bonding/ entries from the netdev events") Tested-by: Carol L Soto Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 317a49480475..ec1404ec4d2f 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1916,6 +1916,7 @@ static int bond_release_and_destroy(struct net_device *bond_dev, bond_dev->priv_flags |= IFF_DISABLE_NETPOLL; netdev_info(bond_dev, "Destroying bond %s\n", bond_dev->name); + bond_remove_proc_entry(bond); unregister_netdevice(bond_dev); } return ret; -- cgit v1.2.3 From 8c4b4b0d19880354864f7720ee5e4e7ab11859d2 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Thu, 16 Jul 2015 20:55:34 +0200 Subject: drm: atmel-hlcdc: fix vblank initial state drm_vblank_on() now warns on nested use or if vblank is not properly initialized. This patch fixes Atmel HLCDC vblank initial state. Signed-off-by: Boris Brezillon Reported-by: Sylvain Rochet --- drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c | 1 + drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c | 12 ++++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c index f69b92535505..5ae5c6923128 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c @@ -355,6 +355,7 @@ int atmel_hlcdc_crtc_create(struct drm_device *dev) planes->overlays[i]->base.possible_crtcs = 1 << crtc->id; drm_crtc_helper_add(&crtc->base, &lcdc_crtc_helper_funcs); + drm_crtc_vblank_reset(&crtc->base); dc->crtc = &crtc->base; diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c index 60b0c13d7ff5..6fad1f9648f3 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c @@ -313,20 +313,20 @@ static int atmel_hlcdc_dc_load(struct drm_device *dev) pm_runtime_enable(dev->dev); - ret = atmel_hlcdc_dc_modeset_init(dev); + ret = drm_vblank_init(dev, 1); if (ret < 0) { - dev_err(dev->dev, "failed to initialize mode setting\n"); + dev_err(dev->dev, "failed to initialize vblank\n"); goto err_periph_clk_disable; } - drm_mode_config_reset(dev); - - ret = drm_vblank_init(dev, 1); + ret = atmel_hlcdc_dc_modeset_init(dev); if (ret < 0) { - dev_err(dev->dev, "failed to initialize vblank\n"); + dev_err(dev->dev, "failed to initialize mode setting\n"); goto err_periph_clk_disable; } + drm_mode_config_reset(dev); + pm_runtime_get_sync(dev->dev); ret = drm_irq_install(dev, dc->hlcdc->irq); pm_runtime_put_sync(dev->dev); -- cgit v1.2.3 From 7d5cd2ce5292b45e555de776cb9e72975a07460d Mon Sep 17 00:00:00 2001 From: Nikolay Aleksandrov Date: Wed, 15 Jul 2015 22:57:01 +0200 Subject: bonding: correctly handle bonding type change on enslave failure If the bond is enslaving a device with different type it will be setup by it, but if after being setup the enslave fails the bond doesn't switch back its type and also keeps pointers to foreign structures that can be long gone. Thus revert back any type changes if the enslave failed and the bond had to change its type. Example: Before patch: $ echo lo > bond0/bonding/slaves -bash: echo: write error: Cannot assign requested address $ ip l sh bond0 20: bond0: mtu 1500 qdisc noop state DOWN mode DEFAULT group default link/loopback 16:54:78:34:bd:41 brd 00:00:00:00:00:00 $ echo +eth1 > bond0/bonding/slaves $ ip l sh bond0 20: bond0: mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/ether 52:54:00:3f:47:69 brd ff:ff:ff:ff:ff:ff (notice the MASTER flag is gone) After patch: $ echo lo > bond0/bonding/slaves -bash: echo: write error: Cannot assign requested address $ ip l sh bond0 21: bond0: mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/ether 6e:66:94:f6:07:fc brd ff:ff:ff:ff:ff:ff $ echo +eth1 > bond0/bonding/slaves $ ip l sh bond0 21: bond0: mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/ether 52:54:00:3f:47:69 brd ff:ff:ff:ff:ff:ff Signed-off-by: Nikolay Aleksandrov Fixes: e36b9d16c6a6 ("bonding: clean muticast addresses when device changes type") Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index ec1404ec4d2f..1d26d6700c1d 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1725,9 +1725,16 @@ err_free: err_undo_flags: /* Enslave of first slave has failed and we need to fix master's mac */ - if (!bond_has_slaves(bond) && - ether_addr_equal_64bits(bond_dev->dev_addr, slave_dev->dev_addr)) - eth_hw_addr_random(bond_dev); + if (!bond_has_slaves(bond)) { + if (ether_addr_equal_64bits(bond_dev->dev_addr, + slave_dev->dev_addr)) + eth_hw_addr_random(bond_dev); + if (bond_dev->type != ARPHRD_ETHER) { + ether_setup(bond_dev); + bond_dev->flags |= IFF_MASTER; + bond_dev->priv_flags &= ~IFF_TX_SKB_SHARING; + } + } return res; } -- cgit v1.2.3 From b8c6cd1d316f3b01ae578d8e29179f6396c0eaa2 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 15 Jul 2015 16:09:32 -0700 Subject: net: dsa: bcm_sf2: do not use indirect reads and writes for 7445E0 7445E0 contains an ECO which disconnected the internal SF2 pseudo-PHY which was known to conflict with the external pseudo-PHY of BCM53125 switches. This motivated the need to utilize the internal SF2 MDIO controller via indirect register reads/writes to control external Broadcom switches due to this address conflict (both responded at address 30d). For 7445E0, the internal pseudo-PHY of the SF2 switch got disconnected, and as a consequence this prevents the internal SF2 MDIO bus controller from reading data (reads back everything as 0) since the MDI line is tied low. Fix this by making the indirect register reads and writes conditional to 7445D0, on 7445E0 we can utilize the SWITCH_MDIO controller (backed by mdio-unimac and not the DSA created slave MII bus). We utilize of_machine_is_compatible() here since this is the only way for use to differentiate between these two chips in a way that does not violate layers or becomes (too) vendor-specific. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/dsa/bcm_sf2.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c index 972982f8bea7..079897b3a955 100644 --- a/drivers/net/dsa/bcm_sf2.c +++ b/drivers/net/dsa/bcm_sf2.c @@ -696,9 +696,20 @@ static int bcm_sf2_sw_setup(struct dsa_switch *ds) } /* Include the pseudo-PHY address and the broadcast PHY address to - * divert reads towards our workaround + * divert reads towards our workaround. This is only required for + * 7445D0, since 7445E0 disconnects the internal switch pseudo-PHY such + * that we can use the regular SWITCH_MDIO master controller instead. + * + * By default, DSA initializes ds->phys_mii_mask to ds->phys_port_mask + * to have a 1:1 mapping between Port address and PHY address in order + * to utilize the slave_mii_bus instance to read from Port PHYs. This is + * not what we want here, so we initialize phys_mii_mask 0 to always + * utilize the "master" MDIO bus backed by the "mdio-unimac" driver. */ - ds->phys_mii_mask |= ((1 << BRCM_PSEUDO_PHY_ADDR) | (1 << 0)); + if (of_machine_is_compatible("brcm,bcm7445d0")) + ds->phys_mii_mask |= ((1 << BRCM_PSEUDO_PHY_ADDR) | (1 << 0)); + else + ds->phys_mii_mask = 0; rev = reg_readl(priv, REG_SWITCH_REVISION); priv->hw_params.top_rev = (rev >> SWITCH_TOP_REV_SHIFT) & -- cgit v1.2.3 From fdbf5b097bbd9693a86c0b8bfdd071a9a2117cfc Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Mon, 20 Jul 2015 17:55:38 +0800 Subject: Revert "sit: Add gro callbacks to sit_offload" This patch reverts 19424e052fb44da2f00d1a868cbb51f3e9f4bbb5 ("sit: Add gro callbacks to sit_offload") because it generates packets that cannot be handled even by our own GSO. Reported-by: Wolfgang Walter Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/ipv6/ip6_offload.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c index e893cd18612f..08b62047c67f 100644 --- a/net/ipv6/ip6_offload.c +++ b/net/ipv6/ip6_offload.c @@ -292,8 +292,6 @@ static struct packet_offload ipv6_packet_offload __read_mostly = { static const struct net_offload sit_offload = { .callbacks = { .gso_segment = ipv6_gso_segment, - .gro_receive = ipv6_gro_receive, - .gro_complete = ipv6_gro_complete, }, }; -- cgit v1.2.3 From a951bc1e6ba58f11df5ed5ddc41311e10f5fd20b Mon Sep 17 00:00:00 2001 From: dingtianhong Date: Thu, 16 Jul 2015 16:30:02 +0800 Subject: bonding: correct the MAC address for "follow" fail_over_mac policy The "follow" fail_over_mac policy is useful for multiport devices that either become confused or incur a performance penalty when multiple ports are programmed with the same MAC address, but the same MAC address still may happened by this steps for this policy: 1) echo +eth0 > /sys/class/net/bond0/bonding/slaves bond0 has the same mac address with eth0, it is MAC1. 2) echo +eth1 > /sys/class/net/bond0/bonding/slaves eth1 is backup, eth1 has MAC2. 3) ifconfig eth0 down eth1 became active slave, bond will swap MAC for eth0 and eth1, so eth1 has MAC1, and eth0 has MAC2. 4) ifconfig eth1 down there is no active slave, and eth1 still has MAC1, eth2 has MAC2. 5) ifconfig eth0 up the eth0 became active slave again, the bond set eth0 to MAC1. Something wrong here, then if you set eth1 up, the eth0 and eth1 will have the same MAC address, it will break this policy for ACTIVE_BACKUP mode. This patch will fix this problem by finding the old active slave and swap them MAC address before change active slave. Signed-off-by: Ding Tianhong Tested-by: Nikolay Aleksandrov Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 1d26d6700c1d..e1ccefce9a9d 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -625,6 +625,23 @@ static void bond_set_dev_addr(struct net_device *bond_dev, call_netdevice_notifiers(NETDEV_CHANGEADDR, bond_dev); } +static struct slave *bond_get_old_active(struct bonding *bond, + struct slave *new_active) +{ + struct slave *slave; + struct list_head *iter; + + bond_for_each_slave(bond, slave, iter) { + if (slave == new_active) + continue; + + if (ether_addr_equal(bond->dev->dev_addr, slave->dev->dev_addr)) + return slave; + } + + return NULL; +} + /* bond_do_fail_over_mac * * Perform special MAC address swapping for fail_over_mac settings @@ -652,6 +669,9 @@ static void bond_do_fail_over_mac(struct bonding *bond, if (!new_active) return; + if (!old_active) + old_active = bond_get_old_active(bond, new_active); + if (old_active) { ether_addr_copy(tmp_mac, new_active->dev->dev_addr); ether_addr_copy(saddr.sa_data, -- cgit v1.2.3 From 194ac06e39238685abc0eeb436efa82e6571b90f Mon Sep 17 00:00:00 2001 From: "Karicheri, Muralidharan" Date: Thu, 16 Jul 2015 15:32:14 -0400 Subject: net: netcp: fix improper initialization in netcp_ndo_open() The keystone qmss will raise interrupt when packet arrive at the receive queue. Only control available to avoid interrupt from happening is to keep the free descriptor queue (FDQ) empty in the receive side. So the filling of descriptors into the FDQ has to happen after request_irq() call is made as part of knav_queue_enable_notify(). So move the function netcp_rxpool_refill() after this call. Signed-off-by: Murali Karicheri Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/netcp_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/ti/netcp_core.c b/drivers/net/ethernet/ti/netcp_core.c index 5ec4ed3f6c8d..ec8ed30196f3 100644 --- a/drivers/net/ethernet/ti/netcp_core.c +++ b/drivers/net/ethernet/ti/netcp_core.c @@ -1617,11 +1617,11 @@ static int netcp_ndo_open(struct net_device *ndev) } mutex_unlock(&netcp_modules_lock); - netcp_rxpool_refill(netcp); napi_enable(&netcp->rx_napi); napi_enable(&netcp->tx_napi); knav_queue_enable_notify(netcp->tx_compl_q); knav_queue_enable_notify(netcp->rx_queue); + netcp_rxpool_refill(netcp); netif_tx_wake_all_queues(ndev); dev_dbg(netcp->ndev_dev, "netcp device %s opened\n", ndev->name); return 0; -- cgit v1.2.3 From 06613e38f1f2b098d46e9549756c0d5c040f2ef8 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Fri, 17 Jul 2015 00:28:38 +0300 Subject: ravb: fix race updating TCCR The TCCR.TSRQn bit may get clearead after TCCR gets read, so that TCCR write would get skipped. We don't need to check this bit before setting. Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/ravb_main.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c index 0e5fde321630..d08c250e843e 100644 --- a/drivers/net/ethernet/renesas/ravb_main.c +++ b/drivers/net/ethernet/renesas/ravb_main.c @@ -1275,7 +1275,6 @@ static netdev_tx_t ravb_start_xmit(struct sk_buff *skb, struct net_device *ndev) u32 dma_addr; void *buffer; u32 entry; - u32 tccr; spin_lock_irqsave(&priv->lock, flags); if (priv->cur_tx[q] - priv->dirty_tx[q] >= priv->num_tx_ring[q]) { @@ -1324,9 +1323,7 @@ static netdev_tx_t ravb_start_xmit(struct sk_buff *skb, struct net_device *ndev) dma_wmb(); desc->die_dt = DT_FSINGLE; - tccr = ravb_read(ndev, TCCR); - if (!(tccr & (TCCR_TSRQ0 << q))) - ravb_write(ndev, tccr | (TCCR_TSRQ0 << q), TCCR); + ravb_write(ndev, ravb_read(ndev, TCCR) | (TCCR_TSRQ0 << q), TCCR); priv->cur_tx[q]++; if (priv->cur_tx[q] - priv->dirty_tx[q] >= priv->num_tx_ring[q] && -- cgit v1.2.3 From e3426ca7bc2957ee072f61360c2b81b4adb629ad Mon Sep 17 00:00:00 2001 From: Reinhard Speyerer Date: Thu, 16 Jul 2015 23:28:14 +0200 Subject: qmi_wwan: add the second QMI/network interface for Sierra Wireless MC7305/MC7355 Sierra Wireless MC7305/MC7355 with USB ID 1199:9041 also provide a second QMI/network interface like the MC73xx with USB ID 1199:68c0 on USB interface #10 when used in the appropriate USB configuration. Add the corresponding QMI_FIXED_INTF entry to the qmi_wwan driver. Please note that the second QMI/network interface is not working for early MC73xx firmware versions like 01.08.x as the device does not respond to QMI messages on the second /dev/cdc-wdm port. Signed-off-by: Reinhard Speyerer Signed-off-by: David S. Miller --- drivers/net/usb/qmi_wwan.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index f603f362504b..9d43460ce3c7 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -757,6 +757,7 @@ static const struct usb_device_id products[] = { {QMI_FIXED_INTF(0x1199, 0x901c, 8)}, /* Sierra Wireless EM7700 */ {QMI_FIXED_INTF(0x1199, 0x901f, 8)}, /* Sierra Wireless EM7355 */ {QMI_FIXED_INTF(0x1199, 0x9041, 8)}, /* Sierra Wireless MC7305/MC7355 */ + {QMI_FIXED_INTF(0x1199, 0x9041, 10)}, /* Sierra Wireless MC7305/MC7355 */ {QMI_FIXED_INTF(0x1199, 0x9051, 8)}, /* Netgear AirCard 340U */ {QMI_FIXED_INTF(0x1199, 0x9053, 8)}, /* Sierra Wireless Modem */ {QMI_FIXED_INTF(0x1199, 0x9054, 8)}, /* Sierra Wireless Modem */ -- cgit v1.2.3 From bbc03778b9954a2ec93baed63718e4df0192f130 Mon Sep 17 00:00:00 2001 From: Dave Hansen Date: Mon, 20 Jul 2015 16:01:53 -0700 Subject: x86/mm: Add parenthesis for TLB tracepoint size calculation flush_tlb_info->flush_start/end are both normal virtual addresses. When calculating 'nr_pages' (only used for the tracepoint), I neglected to put parenthesis in. Thanks to David Koufaty for pointing this out. Signed-off-by: Dave Hansen Cc: Andrew Morton Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: dave@sr71.net Cc: Link: http://lkml.kernel.org/r/20150720230153.9E834081@viggo.jf.intel.com Signed-off-by: Ingo Molnar --- arch/x86/mm/tlb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c index 3250f2371aea..90b924acd982 100644 --- a/arch/x86/mm/tlb.c +++ b/arch/x86/mm/tlb.c @@ -117,7 +117,7 @@ static void flush_tlb_func(void *info) } else { unsigned long addr; unsigned long nr_pages = - f->flush_end - f->flush_start / PAGE_SIZE; + (f->flush_end - f->flush_start) / PAGE_SIZE; addr = f->flush_start; while (addr < f->flush_end) { __flush_tlb_single(addr); -- cgit v1.2.3 From a89652769470d12cd484ee3d3f7bde0742be8d96 Mon Sep 17 00:00:00 2001 From: "Kirill A. Shutemov" Date: Mon, 20 Jul 2015 14:29:58 -0700 Subject: x86/mpx: Do not set ->vm_ops on MPX VMAs MPX setups private anonymous mapping, but uses vma->vm_ops too. This can confuse core VM, as it relies on vm->vm_ops to distinguish file VMAs from anonymous. As result we will get SIGBUS, because handle_pte_fault() thinks it's file VMA without vm_ops->fault and it doesn't know how to handle the situation properly. Let's fix that by not setting ->vm_ops. We don't really need ->vm_ops here: MPX VMA can be detected with VM_MPX flag. And vma_merge() will not merge MPX VMA with non-MPX VMA, because ->vm_flags won't match. The only thing left is name of VMA. I'm not sure if it's part of ABI, or we can just drop it. The patch keep it by providing arch_vma_name() on x86. Signed-off-by: Kirill A. Shutemov Signed-off-by: Dave Hansen Cc: # Fixes: 6b7339f4 (mm: avoid setting up anonymous pages into file mapping) Cc: Andy Lutomirski Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: dave@sr71.net Link: http://lkml.kernel.org/r/20150720212958.305CC3E9@viggo.jf.intel.com Signed-off-by: Ingo Molnar --- arch/x86/mm/mmap.c | 7 +++++++ arch/x86/mm/mpx.c | 24 +++--------------------- 2 files changed, 10 insertions(+), 21 deletions(-) diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c index 9d518d693b4b..844b06d67df4 100644 --- a/arch/x86/mm/mmap.c +++ b/arch/x86/mm/mmap.c @@ -126,3 +126,10 @@ void arch_pick_mmap_layout(struct mm_struct *mm) mm->get_unmapped_area = arch_get_unmapped_area_topdown; } } + +const char *arch_vma_name(struct vm_area_struct *vma) +{ + if (vma->vm_flags & VM_MPX) + return "[mpx]"; + return NULL; +} diff --git a/arch/x86/mm/mpx.c b/arch/x86/mm/mpx.c index 7a657f58bbea..db1b0bc5017c 100644 --- a/arch/x86/mm/mpx.c +++ b/arch/x86/mm/mpx.c @@ -20,20 +20,6 @@ #define CREATE_TRACE_POINTS #include -static const char *mpx_mapping_name(struct vm_area_struct *vma) -{ - return "[mpx]"; -} - -static struct vm_operations_struct mpx_vma_ops = { - .name = mpx_mapping_name, -}; - -static int is_mpx_vma(struct vm_area_struct *vma) -{ - return (vma->vm_ops == &mpx_vma_ops); -} - static inline unsigned long mpx_bd_size_bytes(struct mm_struct *mm) { if (is_64bit_mm(mm)) @@ -53,9 +39,6 @@ static inline unsigned long mpx_bt_size_bytes(struct mm_struct *mm) /* * This is really a simplified "vm_mmap". it only handles MPX * bounds tables (the bounds directory is user-allocated). - * - * Later on, we use the vma->vm_ops to uniquely identify these - * VMAs. */ static unsigned long mpx_mmap(unsigned long len) { @@ -101,7 +84,6 @@ static unsigned long mpx_mmap(unsigned long len) ret = -ENOMEM; goto out; } - vma->vm_ops = &mpx_vma_ops; if (vm_flags & VM_LOCKED) { up_write(&mm->mmap_sem); @@ -812,7 +794,7 @@ static noinline int zap_bt_entries_mapping(struct mm_struct *mm, * so stop immediately and return an error. This * probably results in a SIGSEGV. */ - if (!is_mpx_vma(vma)) + if (!(vma->vm_flags & VM_MPX)) return -EINVAL; len = min(vma->vm_end, end) - addr; @@ -945,9 +927,9 @@ static int try_unmap_single_bt(struct mm_struct *mm, * lots of tables even though we have no actual table * entries in use. */ - while (next && is_mpx_vma(next)) + while (next && (next->vm_flags & VM_MPX)) next = next->vm_next; - while (prev && is_mpx_vma(prev)) + while (prev && (prev->vm_flags & VM_MPX)) prev = prev->vm_prev; /* * We know 'start' and 'end' lie within an area controlled -- cgit v1.2.3 From 5bc016f1abaa1c5ac0e3af23aa79faec4634a074 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Mon, 20 Jul 2015 08:49:01 +0100 Subject: x86/fpu: Disable dependent CPU features on "noxsave" Complete the set of dependent features that need disabling at once: XSAVEC, AVX-512 and all currently known to the kernel extensions to it, as well as MPX need to be disabled too. Signed-off-by: Jan Beulich Cc: Dave Hansen Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/55ACC40D0200007800092E6C@mail.emea.novell.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/fpu/init.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/x86/kernel/fpu/init.c b/arch/x86/kernel/fpu/init.c index 0b39173dd971..1e173f6285c7 100644 --- a/arch/x86/kernel/fpu/init.c +++ b/arch/x86/kernel/fpu/init.c @@ -351,9 +351,15 @@ static int __init x86_noxsave_setup(char *s) setup_clear_cpu_cap(X86_FEATURE_XSAVE); setup_clear_cpu_cap(X86_FEATURE_XSAVEOPT); + setup_clear_cpu_cap(X86_FEATURE_XSAVEC); setup_clear_cpu_cap(X86_FEATURE_XSAVES); setup_clear_cpu_cap(X86_FEATURE_AVX); setup_clear_cpu_cap(X86_FEATURE_AVX2); + setup_clear_cpu_cap(X86_FEATURE_AVX512F); + setup_clear_cpu_cap(X86_FEATURE_AVX512PF); + setup_clear_cpu_cap(X86_FEATURE_AVX512ER); + setup_clear_cpu_cap(X86_FEATURE_AVX512CD); + setup_clear_cpu_cap(X86_FEATURE_MPX); return 1; } -- cgit v1.2.3 From ca1fec58bc6a90be96a59b4769e951156846c6ca Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Mon, 20 Jul 2015 08:46:14 +0100 Subject: x86/mm/pat: Adjust default caching mode translation tables Make WT really mean WT (rather than UC). I can't see why commit 9cd25aac1f ("x86/mm/pat: Emulate PAT when it is disabled") didn't make this to match its changes to pat_init(). Signed-off-by: Jan Beulich Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Toshi Kani Link: http://lkml.kernel.org/r/55ACC3660200007800092E62@mail.emea.novell.com Signed-off-by: Ingo Molnar --- arch/x86/mm/init.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index 8533b46e6bee..7a4532229f51 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c @@ -43,18 +43,18 @@ uint16_t __cachemode2pte_tbl[_PAGE_CACHE_MODE_NUM] = { [_PAGE_CACHE_MODE_WC ] = 0 | _PAGE_PCD, [_PAGE_CACHE_MODE_UC_MINUS] = 0 | _PAGE_PCD, [_PAGE_CACHE_MODE_UC ] = _PAGE_PWT | _PAGE_PCD, - [_PAGE_CACHE_MODE_WT ] = 0 | _PAGE_PCD, + [_PAGE_CACHE_MODE_WT ] = _PAGE_PWT | 0, [_PAGE_CACHE_MODE_WP ] = 0 | _PAGE_PCD, }; EXPORT_SYMBOL(__cachemode2pte_tbl); uint8_t __pte2cachemode_tbl[8] = { [__pte2cm_idx( 0 | 0 | 0 )] = _PAGE_CACHE_MODE_WB, - [__pte2cm_idx(_PAGE_PWT | 0 | 0 )] = _PAGE_CACHE_MODE_UC_MINUS, + [__pte2cm_idx(_PAGE_PWT | 0 | 0 )] = _PAGE_CACHE_MODE_WT, [__pte2cm_idx( 0 | _PAGE_PCD | 0 )] = _PAGE_CACHE_MODE_UC_MINUS, [__pte2cm_idx(_PAGE_PWT | _PAGE_PCD | 0 )] = _PAGE_CACHE_MODE_UC, [__pte2cm_idx( 0 | 0 | _PAGE_PAT)] = _PAGE_CACHE_MODE_WB, - [__pte2cm_idx(_PAGE_PWT | 0 | _PAGE_PAT)] = _PAGE_CACHE_MODE_UC_MINUS, + [__pte2cm_idx(_PAGE_PWT | 0 | _PAGE_PAT)] = _PAGE_CACHE_MODE_WT, [__pte2cm_idx(0 | _PAGE_PCD | _PAGE_PAT)] = _PAGE_CACHE_MODE_UC_MINUS, [__pte2cm_idx(_PAGE_PWT | _PAGE_PCD | _PAGE_PAT)] = _PAGE_CACHE_MODE_UC, }; -- cgit v1.2.3 From b8a23e8d8e31abeda2f6cfa36a772414b2a86ffc Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 17 Jul 2015 10:19:23 +0200 Subject: caif: fix leaks and race in caif_queue_rcv_skb() 1) If sk_filter() is applied, skb was leaked (not freed) 2) Testing SOCK_DEAD twice is racy : packet could be freed while already queued. 3) Remove obsolete comment about caching skb->len Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/caif/caif_socket.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c index 3cc71b9f5517..cc858919108e 100644 --- a/net/caif/caif_socket.c +++ b/net/caif/caif_socket.c @@ -121,12 +121,13 @@ static void caif_flow_ctrl(struct sock *sk, int mode) * Copied from sock.c:sock_queue_rcv_skb(), but changed so packets are * not dropped, but CAIF is sending flow off instead. */ -static int caif_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) +static void caif_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) { int err; unsigned long flags; struct sk_buff_head *list = &sk->sk_receive_queue; struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); + bool queued = false; if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >= (unsigned int)sk->sk_rcvbuf && rx_flow_is_on(cf_sk)) { @@ -139,7 +140,8 @@ static int caif_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) err = sk_filter(sk, skb); if (err) - return err; + goto out; + if (!sk_rmem_schedule(sk, skb, skb->truesize) && rx_flow_is_on(cf_sk)) { set_rx_flow_off(cf_sk); net_dbg_ratelimited("sending flow OFF due to rmem_schedule\n"); @@ -147,21 +149,16 @@ static int caif_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) } skb->dev = NULL; skb_set_owner_r(skb, sk); - /* Cache the SKB length before we tack it onto the receive - * queue. Once it is added it no longer belongs to us and - * may be freed by other threads of control pulling packets - * from the queue. - */ spin_lock_irqsave(&list->lock, flags); - if (!sock_flag(sk, SOCK_DEAD)) + queued = !sock_flag(sk, SOCK_DEAD); + if (queued) __skb_queue_tail(list, skb); spin_unlock_irqrestore(&list->lock, flags); - - if (!sock_flag(sk, SOCK_DEAD)) +out: + if (queued) sk->sk_data_ready(sk); else kfree_skb(skb); - return 0; } /* Packet Receive Callback function called from CAIF Stack */ -- cgit v1.2.3 From 8bf4ada2e21378816b28205427ee6b0e1ca4c5f1 Mon Sep 17 00:00:00 2001 From: Konstantin Khlebnikov Date: Fri, 17 Jul 2015 14:01:11 +0300 Subject: net: ratelimit warnings about dst entry refcount underflow or overflow Kernel generates a lot of warnings when dst entry reference counter overflows and becomes negative. That bug was seen several times at machines with outdated 3.10.y kernels. Most like it's already fixed in upstream. Anyway that flood completely kills machine and makes further debugging impossible. Signed-off-by: Konstantin Khlebnikov Signed-off-by: David S. Miller --- net/core/dst.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/core/dst.c b/net/core/dst.c index e956ce6d1378..002144bea935 100644 --- a/net/core/dst.c +++ b/net/core/dst.c @@ -284,7 +284,9 @@ void dst_release(struct dst_entry *dst) int newrefcnt; newrefcnt = atomic_dec_return(&dst->__refcnt); - WARN_ON(newrefcnt < 0); + if (unlikely(newrefcnt < 0)) + net_warn_ratelimited("%s: dst:%p refcnt:%d\n", + __func__, dst, newrefcnt); if (unlikely(dst->flags & DST_NOCACHE) && !newrefcnt) call_rcu(&dst->rcu_head, dst_destroy_rcu); } -- cgit v1.2.3 From e0536cd910d5bc98300d7830f1d9317df9ab8afa Mon Sep 17 00:00:00 2001 From: Shaohui Xie Date: Fri, 17 Jul 2015 18:07:19 +0800 Subject: net/mdio: fix mdio_bus_match for c45 PHY We store c45 PHY's id information in c45_ids, so it should be used to check the matching between PHY driver and PHY device for c45 PHY. Signed-off-by: Shaohui Xie Signed-off-by: David S. Miller --- drivers/net/phy/mdio_bus.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 095ef3fe369a..46a14cbb0215 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -421,6 +421,8 @@ static int mdio_bus_match(struct device *dev, struct device_driver *drv) { struct phy_device *phydev = to_phy_device(dev); struct phy_driver *phydrv = to_phy_driver(drv); + const int num_ids = ARRAY_SIZE(phydev->c45_ids.device_ids); + int i; if (of_driver_match_device(dev, drv)) return 1; @@ -428,8 +430,21 @@ static int mdio_bus_match(struct device *dev, struct device_driver *drv) if (phydrv->match_phy_device) return phydrv->match_phy_device(phydev); - return (phydrv->phy_id & phydrv->phy_id_mask) == - (phydev->phy_id & phydrv->phy_id_mask); + if (phydev->is_c45) { + for (i = 1; i < num_ids; i++) { + if (!(phydev->c45_ids.devices_in_package & (1 << i))) + continue; + + if ((phydrv->phy_id & phydrv->phy_id_mask) == + (phydev->c45_ids.device_ids[i] & + phydrv->phy_id_mask)) + return 1; + } + return 0; + } else { + return (phydrv->phy_id & phydrv->phy_id_mask) == + (phydev->phy_id & phydrv->phy_id_mask); + } } #ifdef CONFIG_PM -- cgit v1.2.3 From f6bfc46da6292b630ba389592123f0dd02066172 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Fri, 17 Jul 2015 22:38:43 +0200 Subject: sched: cls_bpf: fix panic on filter replace The following test case causes a NULL pointer dereference in cls_bpf: FOO="1,6 0 0 4294967295," tc filter add dev foo parent 1: bpf bytecode "$FOO" flowid 1:1 action ok tc filter replace dev foo parent 1: pref 49152 handle 0x1 \ bpf bytecode "$FOO" flowid 1:1 action drop The problem is that commit 1f947bf151e9 ("net: sched: rcu'ify cls_bpf") accidentally swapped the arguments of list_replace_rcu(), the old element needs to be the first argument and the new element the second. Fixes: 1f947bf151e9 ("net: sched: rcu'ify cls_bpf") Signed-off-by: Daniel Borkmann Acked-by: John Fastabend Acked-by: Alexei Starovoitov Signed-off-by: David S. Miller --- net/sched/cls_bpf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c index c79ecfd36e0f..e5168f8b9640 100644 --- a/net/sched/cls_bpf.c +++ b/net/sched/cls_bpf.c @@ -378,7 +378,7 @@ static int cls_bpf_change(struct net *net, struct sk_buff *in_skb, goto errout; if (oldprog) { - list_replace_rcu(&prog->link, &oldprog->link); + list_replace_rcu(&oldprog->link, &prog->link); tcf_unbind_filter(tp, &oldprog->res); call_rcu(&oldprog->rcu, __cls_bpf_delete_prog); } else { -- cgit v1.2.3 From ff3532f2655b79058fec035ca54fced69a483084 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Fri, 17 Jul 2015 22:38:44 +0200 Subject: sched: cls_flower: fix panic on filter replace The following test case causes a NULL pointer dereference in cls_flower: tc filter add dev foo parent 1: flower eth_type ipv4 action ok flowid 1:1 tc filter replace dev foo parent 1: pref 49152 handle 0x1 \ flower eth_type ipv6 action ok flowid 1:1 The problem is that commit 77b9900ef53a ("tc: introduce Flower classifier") accidentally swapped the arguments of list_replace_rcu(), the old element needs to be the first argument and the new element the second. Fixes: 77b9900ef53a ("tc: introduce Flower classifier") Signed-off-by: Daniel Borkmann Acked-by: Jiri Pirko Signed-off-by: David S. Miller --- net/sched/cls_flower.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c index 9d37ccd95062..2f3d03f99487 100644 --- a/net/sched/cls_flower.c +++ b/net/sched/cls_flower.c @@ -499,7 +499,7 @@ static int fl_change(struct net *net, struct sk_buff *in_skb, *arg = (unsigned long) fnew; if (fold) { - list_replace_rcu(&fnew->list, &fold->list); + list_replace_rcu(&fold->list, &fnew->list); tcf_unbind_filter(tp, &fold->res); call_rcu(&fold->rcu, fl_destroy_filter); } else { -- cgit v1.2.3 From 32b2f4b196b37695fdb42b31afcbc15399d6ef91 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Fri, 17 Jul 2015 22:38:45 +0200 Subject: sched: cls_flow: fix panic on filter replace The following test case causes a NULL pointer dereference in cls_flow: tc filter add dev foo parent 1: handle 0x1 flow hash keys dst action ok tc filter replace dev foo parent 1: pref 49152 handle 0x1 \ flow hash keys mark action drop To be more precise, actually two different panics are fixed, the first occurs because tcf_exts_init() is not called on the newly allocated filter when we do a replace. And the second panic uncovered after that happens since the arguments of list_replace_rcu() are swapped, the old element needs to be the first argument and the new element the second. Fixes: 70da9f0bf999 ("net: sched: cls_flow use RCU") Signed-off-by: Daniel Borkmann Acked-by: John Fastabend Signed-off-by: David S. Miller --- net/sched/cls_flow.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/sched/cls_flow.c b/net/sched/cls_flow.c index 76bc3a20ffdb..bb2a0f529c1f 100644 --- a/net/sched/cls_flow.c +++ b/net/sched/cls_flow.c @@ -425,6 +425,8 @@ static int flow_change(struct net *net, struct sk_buff *in_skb, if (!fnew) goto err2; + tcf_exts_init(&fnew->exts, TCA_FLOW_ACT, TCA_FLOW_POLICE); + fold = (struct flow_filter *)*arg; if (fold) { err = -EINVAL; @@ -486,7 +488,6 @@ static int flow_change(struct net *net, struct sk_buff *in_skb, fnew->mask = ~0U; fnew->tp = tp; get_random_bytes(&fnew->hashrnd, 4); - tcf_exts_init(&fnew->exts, TCA_FLOW_ACT, TCA_FLOW_POLICE); } fnew->perturb_timer.function = flow_perturbation; @@ -526,7 +527,7 @@ static int flow_change(struct net *net, struct sk_buff *in_skb, if (*arg == 0) list_add_tail_rcu(&fnew->list, &head->filters); else - list_replace_rcu(&fnew->list, &fold->list); + list_replace_rcu(&fold->list, &fnew->list); *arg = (unsigned long)fnew; -- cgit v1.2.3 From a7a6268590bdc6760df52570a1df41654e3096ba Mon Sep 17 00:00:00 2001 From: Joachim Eastwood Date: Fri, 17 Jul 2015 23:48:17 +0200 Subject: stmmac: fix setting of driver data in stmmac_dvr_probe Commit 803f8fc46274b ("stmmac: move driver data setting into stmmac_dvr_probe") mistakenly set priv and not priv->dev as driver data. This meant that the remove, resume and suspend callbacks that fetched and tried to use this data would most likely explode. Fix the issue by using the correct variable. Fixes: 803f8fc46274b ("stmmac: move driver data setting into stmmac_dvr_probe") Signed-off-by: Joachim Eastwood Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 50f7a7a26821..864b476f7fd5 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -2843,7 +2843,7 @@ int stmmac_dvr_probe(struct device *device, if (res->mac) memcpy(priv->dev->dev_addr, res->mac, ETH_ALEN); - dev_set_drvdata(device, priv); + dev_set_drvdata(device, priv->dev); /* Verify driver arguments */ stmmac_verify_args(); -- cgit v1.2.3 From a84e32894191cfcbffa54180d78d7d4654d56c20 Mon Sep 17 00:00:00 2001 From: Simon Guinot Date: Sun, 19 Jul 2015 13:00:53 +0200 Subject: net: mvneta: fix refilling for Rx DMA buffers With the actual code, if a memory allocation error happens while refilling a Rx descriptor, then the original Rx buffer is both passed to the networking stack (in a SKB) and let in the Rx ring. This leads to various kernel oops and crashes. As a fix, this patch moves Rx descriptor refilling ahead of building SKB with the associated Rx buffer. In case of a memory allocation failure, data is dropped and the original DMA buffer is put back into the Rx ring. Signed-off-by: Simon Guinot Fixes: c5aff18204da ("net: mvneta: driver for Marvell Armada 370/XP network unit") Cc: # v3.8+ Tested-by: Yoann Sculo Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvneta.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 370e20ed224c..62e48bc0cb23 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -1462,7 +1462,7 @@ static int mvneta_rx(struct mvneta_port *pp, int rx_todo, struct mvneta_rx_queue *rxq) { struct net_device *dev = pp->dev; - int rx_done, rx_filled; + int rx_done; u32 rcvd_pkts = 0; u32 rcvd_bytes = 0; @@ -1473,7 +1473,6 @@ static int mvneta_rx(struct mvneta_port *pp, int rx_todo, rx_todo = rx_done; rx_done = 0; - rx_filled = 0; /* Fairness NAPI loop */ while (rx_done < rx_todo) { @@ -1484,7 +1483,6 @@ static int mvneta_rx(struct mvneta_port *pp, int rx_todo, int rx_bytes, err; rx_done++; - rx_filled++; rx_status = rx_desc->status; rx_bytes = rx_desc->data_size - (ETH_FCS_LEN + MVNETA_MH_SIZE); data = (unsigned char *)rx_desc->buf_cookie; @@ -1524,6 +1522,14 @@ static int mvneta_rx(struct mvneta_port *pp, int rx_todo, continue; } + /* Refill processing */ + err = mvneta_rx_refill(pp, rx_desc); + if (err) { + netdev_err(dev, "Linux processing - Can't refill\n"); + rxq->missed++; + goto err_drop_frame; + } + skb = build_skb(data, pp->frag_size > PAGE_SIZE ? 0 : pp->frag_size); if (!skb) goto err_drop_frame; @@ -1543,14 +1549,6 @@ static int mvneta_rx(struct mvneta_port *pp, int rx_todo, mvneta_rx_csum(pp, rx_status, skb); napi_gro_receive(&pp->napi, skb); - - /* Refill processing */ - err = mvneta_rx_refill(pp, rx_desc); - if (err) { - netdev_err(dev, "Linux processing - Can't refill\n"); - rxq->missed++; - rx_filled--; - } } if (rcvd_pkts) { @@ -1563,7 +1561,7 @@ static int mvneta_rx(struct mvneta_port *pp, int rx_todo, } /* Update rxq management counters */ - mvneta_rxq_desc_num_update(pp, rxq, rx_done, rx_filled); + mvneta_rxq_desc_num_update(pp, rxq, rx_done, rx_done); return rx_done; } -- cgit v1.2.3 From 6c3d91193d829bf58a35a10650415b05a736ca6c Mon Sep 17 00:00:00 2001 From: Aaron Plattner Date: Mon, 20 Jul 2015 17:14:14 -0700 Subject: ALSA: hda - Add new GPU codec ID 0x10de007d to snd-hda Vendor ID 0x10de007d is used by a yet-to-be-named GPU chip. This chip also has the 2-ch audio swapping bug, so patch_nvhdmi is appropriate here. Signed-off-by: Aaron Plattner Cc: Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 95158914cc6c..a97db5fc8a15 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -3512,6 +3512,7 @@ static const struct hda_codec_preset snd_hda_preset_hdmi[] = { { .id = 0x10de0070, .name = "GPU 70 HDMI/DP", .patch = patch_nvhdmi }, { .id = 0x10de0071, .name = "GPU 71 HDMI/DP", .patch = patch_nvhdmi }, { .id = 0x10de0072, .name = "GPU 72 HDMI/DP", .patch = patch_nvhdmi }, +{ .id = 0x10de007d, .name = "GPU 7d HDMI/DP", .patch = patch_nvhdmi }, { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch }, { .id = 0x11069f80, .name = "VX900 HDMI/DP", .patch = patch_via_hdmi }, { .id = 0x11069f81, .name = "VX900 HDMI/DP", .patch = patch_via_hdmi }, @@ -3576,6 +3577,7 @@ MODULE_ALIAS("snd-hda-codec-id:10de0067"); MODULE_ALIAS("snd-hda-codec-id:10de0070"); MODULE_ALIAS("snd-hda-codec-id:10de0071"); MODULE_ALIAS("snd-hda-codec-id:10de0072"); +MODULE_ALIAS("snd-hda-codec-id:10de007d"); MODULE_ALIAS("snd-hda-codec-id:10de8001"); MODULE_ALIAS("snd-hda-codec-id:11069f80"); MODULE_ALIAS("snd-hda-codec-id:11069f81"); -- cgit v1.2.3 From fd0a1b8607ef311a2c800dd54c9a4a3583756ea6 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Fri, 17 Jul 2015 14:07:24 -0700 Subject: x86/mm/pat, drivers/infiniband/ipath: Replace WARN() with pr_warn() WARN() may confuse users, fix that. ipath_init_one() is part the device's probe so this would only be triggered if a corresponding device was found. Signed-off-by: Luis R. Rodriguez Acked-by: Doug Ledford Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: andy@silverblocksystems.net Cc: benh@kernel.crashing.org Cc: bp@suse.de Cc: dan.j.williams@intel.com Cc: jkosina@suse.cz Cc: julia.lawall@lip6.fr Cc: luto@amacapital.net Cc: mchehab@osg.samsung.com Link: http://lkml.kernel.org/r/1437167245-28273-2-git-send-email-mcgrof@do-not-panic.com Signed-off-by: Ingo Molnar --- drivers/infiniband/hw/ipath/ipath_driver.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c index 2d7e503d13cb..871dbe56216a 100644 --- a/drivers/infiniband/hw/ipath/ipath_driver.c +++ b/drivers/infiniband/hw/ipath/ipath_driver.c @@ -31,6 +31,8 @@ * SOFTWARE. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -399,8 +401,8 @@ static int ipath_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) u32 bar0 = 0, bar1 = 0; #ifdef CONFIG_X86_64 - if (WARN(pat_enabled(), - "ipath needs PAT disabled, boot with nopat kernel parameter\n")) { + if (pat_enabled()) { + pr_warn("ipath needs PAT disabled, boot with nopat kernel parameter\n"); ret = -ENODEV; goto bail; } -- cgit v1.2.3 From f5530d5af835ffa82a0607f5f1977d63ac02551f Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Fri, 17 Jul 2015 14:07:25 -0700 Subject: x86/mm/pat, drivers/media/ivtv: Move the PAT warning and replace WARN() with pr_warn() On built-in kernels this warning will always splat, even if no ivtvfb hardware is present, as this is part of the module init: if (WARN(pat_enabled(), "ivtvfb needs PAT disabled, boot with nopat kernel parameter\n")) { Fix that by shifting the PAT requirement check out under the code that does the "quasi-probe" for the device. This device driver relies on an existing driver to find its own devices, it looks for that device driver and its own found devices, then uses driver_for_each_device() to try to see if it can probe each of those devices as a frambuffer device with ivtvfb_init_card(). We tuck the PAT requiremenet check then on the ivtvfb_init_card() call making the check at least require an ivtv device present before complaining. Reported-by: Fengguang Wu [0-day test robot] Signed-off-by: Luis R. Rodriguez Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: andy@silverblocksystems.net Cc: benh@kernel.crashing.org Cc: bp@suse.de Cc: dan.j.williams@intel.com Cc: dledford@redhat.com Cc: jkosina@suse.cz Cc: julia.lawall@lip6.fr Cc: luto@amacapital.net Cc: mchehab@osg.samsung.com Link: http://lkml.kernel.org/r/1437167245-28273-3-git-send-email-mcgrof@do-not-panic.com Signed-off-by: Ingo Molnar --- drivers/media/pci/ivtv/ivtvfb.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/media/pci/ivtv/ivtvfb.c b/drivers/media/pci/ivtv/ivtvfb.c index 4cb365d4ffdc..8b95eefb610b 100644 --- a/drivers/media/pci/ivtv/ivtvfb.c +++ b/drivers/media/pci/ivtv/ivtvfb.c @@ -38,6 +38,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -1171,6 +1173,13 @@ static int ivtvfb_init_card(struct ivtv *itv) { int rc; +#ifdef CONFIG_X86_64 + if (pat_enabled()) { + pr_warn("ivtvfb needs PAT disabled, boot with nopat kernel parameter\n"); + return -ENODEV; + } +#endif + if (itv->osd_info) { IVTVFB_ERR("Card %d already initialised\n", ivtvfb_card_id); return -EBUSY; @@ -1265,12 +1274,6 @@ static int __init ivtvfb_init(void) int registered = 0; int err; -#ifdef CONFIG_X86_64 - if (WARN(pat_enabled(), - "ivtvfb needs PAT disabled, boot with nopat kernel parameter\n")) { - return -ENODEV; - } -#endif if (ivtvfb_card_id < -1 || ivtvfb_card_id >= IVTV_MAX_CARDS) { printk(KERN_ERR "ivtvfb: ivtvfb_card_id parameter is out of range (valid range: -1 - %d)\n", -- cgit v1.2.3 From 648a9bc5308d952f2c80772301b339f73026f013 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 16 Jul 2015 12:37:56 +0100 Subject: drm/i915: Use two 32bit reads for select 64bit REG_READ ioctls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since the hardware sometimes mysteriously totally flummoxes the 64bit read of a 64bit register when read using a single instruction, split the read into two instructions. Since the read here is of automatically incrementing timestamp counters, we also have to be very careful in order to make sure that it does not increment between the two instructions. However, since userspace tried to workaround this issue and so enshrined this ABI for a broken hardware read and in the process neglected that the read only fails in some environments, we have to introduce a new uABI flag for userspace to request the 2x32 bit accurate read of the timestamp. v2: Fix alignment check and include details of the workaround for userspace. Reported-by: Karol Herbst Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=91317 Testcase: igt/gem_reg_read Signed-off-by: Chris Wilson Cc: Michał Winiarski Cc: stable@vger.kernel.org Tested-by: Michał Winiarski Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_uncore.c | 26 +++++++++++++++++++------- include/uapi/drm/i915_drm.h | 8 ++++++++ 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index a6d8a3ee7750..260389acfb77 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -1274,10 +1274,12 @@ int i915_reg_read_ioctl(struct drm_device *dev, struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_reg_read *reg = data; struct register_whitelist const *entry = whitelist; + unsigned size; + u64 offset; int i, ret = 0; for (i = 0; i < ARRAY_SIZE(whitelist); i++, entry++) { - if (entry->offset == reg->offset && + if (entry->offset == (reg->offset & -entry->size) && (1 << INTEL_INFO(dev)->gen & entry->gen_bitmask)) break; } @@ -1285,23 +1287,33 @@ int i915_reg_read_ioctl(struct drm_device *dev, if (i == ARRAY_SIZE(whitelist)) return -EINVAL; + /* We use the low bits to encode extra flags as the register should + * be naturally aligned (and those that are not so aligned merely + * limit the available flags for that register). + */ + offset = entry->offset; + size = entry->size; + size |= reg->offset ^ offset; + intel_runtime_pm_get(dev_priv); - switch (entry->size) { + switch (size) { + case 8 | 1: + reg->val = I915_READ64_2x32(offset, offset+4); + break; case 8: - reg->val = I915_READ64(reg->offset); + reg->val = I915_READ64(offset); break; case 4: - reg->val = I915_READ(reg->offset); + reg->val = I915_READ(offset); break; case 2: - reg->val = I915_READ16(reg->offset); + reg->val = I915_READ16(offset); break; case 1: - reg->val = I915_READ8(reg->offset); + reg->val = I915_READ8(offset); break; default: - MISSING_CASE(entry->size); ret = -EINVAL; goto out; } diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h index 6e1a2ed116cb..db809b722985 100644 --- a/include/uapi/drm/i915_drm.h +++ b/include/uapi/drm/i915_drm.h @@ -1070,6 +1070,14 @@ struct drm_i915_reg_read { __u64 offset; __u64 val; /* Return value */ }; +/* Known registers: + * + * Render engine timestamp - 0x2358 + 64bit - gen7+ + * - Note this register returns an invalid value if using the default + * single instruction 8byte read, in order to workaround that use + * offset (0x2538 | 1) instead. + * + */ struct drm_i915_reset_stats { __u32 ctx_id; -- cgit v1.2.3 From 0848f6428ba3a2e42db124d41ac6f548655735bf Mon Sep 17 00:00:00 2001 From: Edward Hyunkoo Jee Date: Tue, 21 Jul 2015 09:43:59 +0200 Subject: inet: frags: fix defragmented packet's IP header for af_packet When ip_frag_queue() computes positions, it assumes that the passed sk_buff does not contain L2 headers. However, when PACKET_FANOUT_FLAG_DEFRAG is used, IP reassembly functions can be called on outgoing packets that contain L2 headers. Also, IPv4 checksum is not corrected after reassembly. Fixes: 7736d33f4262 ("packet: Add pre-defragmentation support for ipv4 fanouts.") Signed-off-by: Edward Hyunkoo Jee Signed-off-by: Eric Dumazet Cc: Willem de Bruijn Cc: Jerry Chu Signed-off-by: David S. Miller --- net/ipv4/ip_fragment.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index a50dc6d408d1..31f71b15cfba 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c @@ -351,7 +351,7 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb) ihl = ip_hdrlen(skb); /* Determine the position of this fragment. */ - end = offset + skb->len - ihl; + end = offset + skb->len - skb_network_offset(skb) - ihl; err = -EINVAL; /* Is this the final fragment? */ @@ -381,7 +381,7 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb) goto err; err = -ENOMEM; - if (!pskb_pull(skb, ihl)) + if (!pskb_pull(skb, skb_network_offset(skb) + ihl)) goto err; err = pskb_trim_rcsum(skb, end - offset); @@ -641,6 +641,8 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev, iph->frag_off = 0; } + ip_send_check(iph); + IP_INC_STATS_BH(net, IPSTATS_MIB_REASMOKS); qp->q.fragments = NULL; qp->q.fragments_tail = NULL; -- cgit v1.2.3 From 1e353cddcf81fbb79dd637cab9a22c837e94c205 Mon Sep 17 00:00:00 2001 From: Mugunthan V N Date: Tue, 21 Jul 2015 16:00:42 +0530 Subject: drivers: net: cpsw: remove tx event processing in rx napi poll With commit c03abd84634d ("net: ethernet: cpsw: don't requests IRQs we don't use") common isr and napi are separated into separate tx isr and rx isr/napi, but still in rx napi tx events are handled. So removing the tx event handling in rx napi. Signed-off-by: Mugunthan V N Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/cpsw.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index f335bf119ab5..d155bf2573cd 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@ -793,9 +793,7 @@ static irqreturn_t cpsw_rx_interrupt(int irq, void *dev_id) static int cpsw_poll(struct napi_struct *napi, int budget) { struct cpsw_priv *priv = napi_to_priv(napi); - int num_tx, num_rx; - - num_tx = cpdma_chan_process(priv->txch, 128); + int num_rx; num_rx = cpdma_chan_process(priv->rxch, budget); if (num_rx < budget) { @@ -810,9 +808,8 @@ static int cpsw_poll(struct napi_struct *napi, int budget) } } - if (num_rx || num_tx) - cpsw_dbg(priv, intr, "poll %d rx, %d tx pkts\n", - num_rx, num_tx); + if (num_rx) + cpsw_dbg(priv, intr, "poll %d rx pkts\n", num_rx); return num_rx; } -- cgit v1.2.3 From d725e66c06ab440032f49ef17e960896d0ec6d49 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 21 Jul 2015 16:06:53 -0700 Subject: Revert "fsnotify: fix oops in fsnotify_clear_marks_by_group_flags()" This reverts commit a2673b6e040663bf16a552f8619e6bde9f4b9acf. Kinglong Mee reports a memory leak with that patch, and Jan Kara confirms: "Thanks for report! You are right that my patch introduces a race between fsnotify kthread and fsnotify_destroy_group() which can result in leaking inotify event on group destruction. I haven't yet decided whether the right fix is not to queue events for dying notification group (as that is pointless anyway) or whether we should just fix the original problem differently... Whenever I look at fsnotify code mark handling I get lost in the maze of locks, lists, and subtle differences between how different notification systems handle notification marks :( I'll think about it over night" and after thinking about it, Jan says: "OK, I have looked into the code some more and I found another relatively simple way of fixing the original oops. It will be IMHO better than trying to fixup this issue which has more potential for breakage. I'll ask Linus to revert the fsnotify fix he already merged and send a new fix" Reported-by: Kinglong Mee Requested-by: Jan Kara Cc: Andrew Morton Signed-off-by: Linus Torvalds --- fs/notify/mark.c | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/fs/notify/mark.c b/fs/notify/mark.c index 3e594ce41010..92e48c70f0f0 100644 --- a/fs/notify/mark.c +++ b/fs/notify/mark.c @@ -152,15 +152,31 @@ void fsnotify_destroy_mark_locked(struct fsnotify_mark *mark, BUG(); list_del_init(&mark->g_list); + spin_unlock(&mark->lock); if (inode && (mark->flags & FSNOTIFY_MARK_FLAG_OBJECT_PINNED)) iput(inode); + /* release lock temporarily */ + mutex_unlock(&group->mark_mutex); spin_lock(&destroy_lock); list_add(&mark->g_list, &destroy_list); spin_unlock(&destroy_lock); wake_up(&destroy_waitq); + /* + * We don't necessarily have a ref on mark from caller so the above destroy + * may have actually freed it, unless this group provides a 'freeing_mark' + * function which must be holding a reference. + */ + + /* + * Some groups like to know that marks are being freed. This is a + * callback to the group function to let it know that this mark + * is being freed. + */ + if (group->ops->freeing_mark) + group->ops->freeing_mark(mark, group); /* * __fsnotify_update_child_dentry_flags(inode); @@ -175,6 +191,8 @@ void fsnotify_destroy_mark_locked(struct fsnotify_mark *mark, */ atomic_dec(&group->num_marks); + + mutex_lock_nested(&group->mark_mutex, SINGLE_DEPTH_NESTING); } void fsnotify_destroy_mark(struct fsnotify_mark *mark, @@ -187,10 +205,7 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark, /* * Destroy all marks in the given list. The marks must be already detached from - * the original inode / vfsmount. Note that we can race with - * fsnotify_clear_marks_by_group_flags(). However we hold a reference to each - * mark so they won't get freed from under us and nobody else touches our - * free_list list_head. + * the original inode / vfsmount. */ void fsnotify_destroy_marks(struct list_head *to_free) { @@ -391,7 +406,7 @@ struct fsnotify_mark *fsnotify_find_mark(struct hlist_head *head, } /* - * Clear any marks in a group in which mark->flags & flags is true. + * clear any marks in a group in which mark->flags & flags is true */ void fsnotify_clear_marks_by_group_flags(struct fsnotify_group *group, unsigned int flags) @@ -445,7 +460,6 @@ static int fsnotify_mark_destroy(void *ignored) { struct fsnotify_mark *mark, *next; struct list_head private_destroy_list; - struct fsnotify_group *group; for (;;) { spin_lock(&destroy_lock); @@ -457,14 +471,6 @@ static int fsnotify_mark_destroy(void *ignored) list_for_each_entry_safe(mark, next, &private_destroy_list, g_list) { list_del_init(&mark->g_list); - group = mark->group; - /* - * Some groups like to know that marks are being freed. - * This is a callback to the group function to let it - * know that this mark is being freed. - */ - if (group && group->ops->freeing_mark) - group->ops->freeing_mark(mark, group); fsnotify_put_mark(mark); } -- cgit v1.2.3 From 2d5b569b665ea6d0b15c52529ff06300de81a7ce Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 6 Jul 2015 12:49:23 +1000 Subject: md/raid5: avoid races when changing cache size. Cache size can grow or shrink due to various pressures at any time. So when we resize the cache as part of a 'grow' operation (i.e. change the size to allow more devices) we need to blocks that automatic growing/shrinking. So introduce a mutex. auto grow/shrink uses mutex_trylock() and just doesn't bother if there is a blockage. Resizing the whole cache holds the mutex to ensure that the correct number of new stripes is allocated. This bug can result in some stripes not being freed when an array is stopped. This leads to the kmem_cache not being freed and a subsequent array can try to use the same kmem_cache and get confused. Fixes: edbe83ab4c27 ("md/raid5: allow the stripe_cache to grow and shrink.") Cc: stable@vger.kernel.org (4.1 - please delay until 2 weeks after release of 4.2) Signed-off-by: NeilBrown --- drivers/md/raid5.c | 31 +++++++++++++++++++++++++------ drivers/md/raid5.h | 3 ++- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 59e44e99eef3..38300ee3c4e1 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -2162,6 +2162,9 @@ static int resize_stripes(struct r5conf *conf, int newsize) if (!sc) return -ENOMEM; + /* Need to ensure auto-resizing doesn't interfere */ + mutex_lock(&conf->cache_size_mutex); + for (i = conf->max_nr_stripes; i; i--) { nsh = alloc_stripe(sc, GFP_KERNEL); if (!nsh) @@ -2178,6 +2181,7 @@ static int resize_stripes(struct r5conf *conf, int newsize) kmem_cache_free(sc, nsh); } kmem_cache_destroy(sc); + mutex_unlock(&conf->cache_size_mutex); return -ENOMEM; } /* Step 2 - Must use GFP_NOIO now. @@ -2224,6 +2228,7 @@ static int resize_stripes(struct r5conf *conf, int newsize) } else err = -ENOMEM; + mutex_unlock(&conf->cache_size_mutex); /* Step 4, return new stripes to service */ while(!list_empty(&newstripes)) { nsh = list_entry(newstripes.next, struct stripe_head, lru); @@ -5857,12 +5862,14 @@ static void raid5d(struct md_thread *thread) pr_debug("%d stripes handled\n", handled); spin_unlock_irq(&conf->device_lock); - if (test_and_clear_bit(R5_ALLOC_MORE, &conf->cache_state)) { + if (test_and_clear_bit(R5_ALLOC_MORE, &conf->cache_state) && + mutex_trylock(&conf->cache_size_mutex)) { grow_one_stripe(conf, __GFP_NOWARN); /* Set flag even if allocation failed. This helps * slow down allocation requests when mem is short */ set_bit(R5_DID_ALLOC, &conf->cache_state); + mutex_unlock(&conf->cache_size_mutex); } async_tx_issue_pending_all(); @@ -5894,18 +5901,22 @@ raid5_set_cache_size(struct mddev *mddev, int size) return -EINVAL; conf->min_nr_stripes = size; + mutex_lock(&conf->cache_size_mutex); while (size < conf->max_nr_stripes && drop_one_stripe(conf)) ; + mutex_unlock(&conf->cache_size_mutex); err = md_allow_write(mddev); if (err) return err; + mutex_lock(&conf->cache_size_mutex); while (size > conf->max_nr_stripes) if (!grow_one_stripe(conf, GFP_KERNEL)) break; + mutex_unlock(&conf->cache_size_mutex); return 0; } @@ -6371,11 +6382,18 @@ static unsigned long raid5_cache_scan(struct shrinker *shrink, struct shrink_control *sc) { struct r5conf *conf = container_of(shrink, struct r5conf, shrinker); - int ret = 0; - while (ret < sc->nr_to_scan) { - if (drop_one_stripe(conf) == 0) - return SHRINK_STOP; - ret++; + unsigned long ret = SHRINK_STOP; + + if (mutex_trylock(&conf->cache_size_mutex)) { + ret= 0; + while (ret < sc->nr_to_scan) { + if (drop_one_stripe(conf) == 0) { + ret = SHRINK_STOP; + break; + } + ret++; + } + mutex_unlock(&conf->cache_size_mutex); } return ret; } @@ -6444,6 +6462,7 @@ static struct r5conf *setup_conf(struct mddev *mddev) goto abort; spin_lock_init(&conf->device_lock); seqcount_init(&conf->gen_lock); + mutex_init(&conf->cache_size_mutex); init_waitqueue_head(&conf->wait_for_quiescent); for (i = 0; i < NR_STRIPE_HASH_LOCKS; i++) { init_waitqueue_head(&conf->wait_for_stripe[i]); diff --git a/drivers/md/raid5.h b/drivers/md/raid5.h index 02c3bf8fbfe7..d05144278690 100644 --- a/drivers/md/raid5.h +++ b/drivers/md/raid5.h @@ -482,7 +482,8 @@ struct r5conf { */ int active_name; char cache_name[2][32]; - struct kmem_cache *slab_cache; /* for allocating stripes */ + struct kmem_cache *slab_cache; /* for allocating stripes */ + struct mutex cache_size_mutex; /* Protect changes to cache size */ int seq_flush, seq_write; int quiesce; -- cgit v1.2.3 From 299b0685e31c9f3dcc2d58ee3beca761a40b44b3 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 6 Jul 2015 17:37:49 +1000 Subject: md/raid10: always set reshape_safe when initializing reshape_position. 'reshape_position' tracks where in the reshape we have reached. 'reshape_safe' tracks where in the reshape we have safely recorded in the metadata. These are compared to determine when to update the metadata. So it is important that reshape_safe is initialised properly. Currently it isn't. When starting a reshape from the beginning it usually has the correct value by luck. But when reducing the number of devices in a RAID10, it has the wrong value and this leads to the metadata not being updated correctly. This can lead to corruption if the reshape is not allowed to complete. This patch is suitable for any -stable kernel which supports RAID10 reshape, which is 3.5 and later. Fixes: 3ea7daa5d7fd ("md/raid10: add reshape support") Cc: stable@vger.kernel.org (v3.5+ please wait for -final to be out for 2 weeks) Signed-off-by: NeilBrown --- drivers/md/raid10.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 940f2f365461..38c58e19cfce 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -3556,6 +3556,7 @@ static struct r10conf *setup_conf(struct mddev *mddev) /* far_copies must be 1 */ conf->prev.stride = conf->dev_sectors; } + conf->reshape_safe = conf->reshape_progress; spin_lock_init(&conf->device_lock); INIT_LIST_HEAD(&conf->retry_list); @@ -3760,7 +3761,6 @@ static int run(struct mddev *mddev) } conf->offset_diff = min_offset_diff; - conf->reshape_safe = conf->reshape_progress; clear_bit(MD_RECOVERY_SYNC, &mddev->recovery); clear_bit(MD_RECOVERY_CHECK, &mddev->recovery); set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery); @@ -4103,6 +4103,7 @@ static int raid10_start_reshape(struct mddev *mddev) conf->reshape_progress = size; } else conf->reshape_progress = 0; + conf->reshape_safe = conf->reshape_progress; spin_unlock_irq(&conf->device_lock); if (mddev->delta_disks && mddev->bitmap) { @@ -4170,6 +4171,7 @@ abort: rdev->new_data_offset = rdev->data_offset; smp_wmb(); conf->reshape_progress = MaxSector; + conf->reshape_safe = MaxSector; mddev->reshape_position = MaxSector; spin_unlock_irq(&conf->device_lock); return ret; @@ -4524,6 +4526,7 @@ static void end_reshape(struct r10conf *conf) md_finish_reshape(conf->mddev); smp_wmb(); conf->reshape_progress = MaxSector; + conf->reshape_safe = MaxSector; spin_unlock_irq(&conf->device_lock); /* read-ahead size must cover two whole stripes, which is -- cgit v1.2.3 From ee5d004fd0591536a061451eba2b187092e9127c Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 22 Jul 2015 10:20:07 +1000 Subject: md: flush ->event_work before stopping array. The 'event_work' worker used by dm-raid may still be running when the array is stopped. This can result in an oops. So flush the workqueue on which it is run after detaching and before destroying the device. Reported-by: Heinz Mauelshagen Signed-off-by: NeilBrown Cc: stable@vger.kernel.org (2.6.38+ please delay 2 weeks after -final release) Fixes: 9d09e663d550 ("dm: raid456 basic support") --- drivers/md/md.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/md/md.c b/drivers/md/md.c index df92d30ca054..5025b3ec13cd 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -5382,6 +5382,8 @@ static void __md_stop(struct mddev *mddev) { struct md_personality *pers = mddev->pers; mddev_detach(mddev); + /* Ensure ->event_work is done */ + flush_workqueue(md_misc_wq); spin_lock(&mddev->lock); mddev->ready = 0; mddev->pers = NULL; -- cgit v1.2.3 From 89e478a2aa58af2548b7f316e4d5b6bcc9eade5b Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 22 Jul 2015 07:02:00 +0200 Subject: tcp: suppress a division by zero warning Andrew Morton reported following warning on one ARM build with gcc-4.4 : net/ipv4/inet_hashtables.c: In function 'inet_ehash_locks_alloc': net/ipv4/inet_hashtables.c:617: warning: division by zero Even guarded with a test on sizeof(spinlock_t), compiler does not like current construct on a !CONFIG_SMP build. Remove the warning by using a temporary variable. Fixes: 095dc8e0c368 ("tcp: fix/cleanup inet_ehash_locks_alloc()") Reported-by: Andrew Morton Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/inet_hashtables.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index 5f9b063bbe8a..0cb9165421d4 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c @@ -624,22 +624,21 @@ EXPORT_SYMBOL_GPL(inet_hashinfo_init); int inet_ehash_locks_alloc(struct inet_hashinfo *hashinfo) { + unsigned int locksz = sizeof(spinlock_t); unsigned int i, nblocks = 1; - if (sizeof(spinlock_t) != 0) { + if (locksz != 0) { /* allocate 2 cache lines or at least one spinlock per cpu */ - nblocks = max_t(unsigned int, - 2 * L1_CACHE_BYTES / sizeof(spinlock_t), - 1); + nblocks = max(2U * L1_CACHE_BYTES / locksz, 1U); nblocks = roundup_pow_of_two(nblocks * num_possible_cpus()); /* no more locks than number of hash buckets */ nblocks = min(nblocks, hashinfo->ehash_mask + 1); - hashinfo->ehash_locks = kmalloc_array(nblocks, sizeof(spinlock_t), + hashinfo->ehash_locks = kmalloc_array(nblocks, locksz, GFP_KERNEL | __GFP_NOWARN); if (!hashinfo->ehash_locks) - hashinfo->ehash_locks = vmalloc(nblocks * sizeof(spinlock_t)); + hashinfo->ehash_locks = vmalloc(nblocks * locksz); if (!hashinfo->ehash_locks) return -ENOMEM; -- cgit v1.2.3 From 7aed35cb65348fc8b9ce0c2394ff675e5fc750da Mon Sep 17 00:00:00 2001 From: Nicolas Schichan Date: Tue, 21 Jul 2015 14:14:12 +0200 Subject: ARM: net: fix condition for load_order > 0 when translating load instructions. To check whether the load should take the fast path or not, the code would check that (r_skb_hlen - load_order) is greater than the offset of the access using an "Unsigned higher or same" condition. For halfword accesses and an skb length of 1 at offset 0, that test is valid, as we end up comparing 0xffffffff(-1) and 0, so the fast path is taken and the filter allows the load to wrongly succeed. A similar issue exists for word loads at offset 0 and an skb length of less than 4. Fix that by using the condition "Signed greater than or equal" condition for the fast path code for load orders greater than 0. Signed-off-by: Nicolas Schichan Signed-off-by: David S. Miller --- arch/arm/net/bpf_jit_32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c index 4550d247e308..21f5ace156fd 100644 --- a/arch/arm/net/bpf_jit_32.c +++ b/arch/arm/net/bpf_jit_32.c @@ -547,7 +547,7 @@ load_common: emit(ARM_SUB_I(r_scratch, r_skb_hl, 1 << load_order), ctx); emit(ARM_CMP_R(r_scratch, r_off), ctx); - condt = ARM_COND_HS; + condt = ARM_COND_GE; } else { emit(ARM_CMP_R(r_skb_hl, r_off), ctx); condt = ARM_COND_HI; -- cgit v1.2.3 From 6d715e301e950e3314d590bdbabf0c26e4fed94b Mon Sep 17 00:00:00 2001 From: Nicolas Schichan Date: Tue, 21 Jul 2015 14:14:13 +0200 Subject: ARM: net: handle negative offsets in BPF JIT. Previously, the JIT would reject negative offsets known during code generation and mishandle negative offsets provided at runtime. Fix that by calling bpf_internal_load_pointer_neg_helper() appropriately in the jit_get_skb_{b,h,w} slow path helpers and by forcing the execution flow to the slow path helpers when the offset is negative. Signed-off-by: Nicolas Schichan Signed-off-by: David S. Miller --- arch/arm/net/bpf_jit_32.c | 47 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c index 21f5ace156fd..d9b25242f743 100644 --- a/arch/arm/net/bpf_jit_32.c +++ b/arch/arm/net/bpf_jit_32.c @@ -74,32 +74,52 @@ struct jit_ctx { int bpf_jit_enable __read_mostly; -static u64 jit_get_skb_b(struct sk_buff *skb, unsigned offset) +static inline int call_neg_helper(struct sk_buff *skb, int offset, void *ret, + unsigned int size) +{ + void *ptr = bpf_internal_load_pointer_neg_helper(skb, offset, size); + + if (!ptr) + return -EFAULT; + memcpy(ret, ptr, size); + return 0; +} + +static u64 jit_get_skb_b(struct sk_buff *skb, int offset) { u8 ret; int err; - err = skb_copy_bits(skb, offset, &ret, 1); + if (offset < 0) + err = call_neg_helper(skb, offset, &ret, 1); + else + err = skb_copy_bits(skb, offset, &ret, 1); return (u64)err << 32 | ret; } -static u64 jit_get_skb_h(struct sk_buff *skb, unsigned offset) +static u64 jit_get_skb_h(struct sk_buff *skb, int offset) { u16 ret; int err; - err = skb_copy_bits(skb, offset, &ret, 2); + if (offset < 0) + err = call_neg_helper(skb, offset, &ret, 2); + else + err = skb_copy_bits(skb, offset, &ret, 2); return (u64)err << 32 | ntohs(ret); } -static u64 jit_get_skb_w(struct sk_buff *skb, unsigned offset) +static u64 jit_get_skb_w(struct sk_buff *skb, int offset) { u32 ret; int err; - err = skb_copy_bits(skb, offset, &ret, 4); + if (offset < 0) + err = call_neg_helper(skb, offset, &ret, 4); + else + err = skb_copy_bits(skb, offset, &ret, 4); return (u64)err << 32 | ntohl(ret); } @@ -536,9 +556,6 @@ static int build_body(struct jit_ctx *ctx) case BPF_LD | BPF_B | BPF_ABS: load_order = 0; load: - /* the interpreter will deal with the negative K */ - if ((int)k < 0) - return -ENOTSUPP; emit_mov_i(r_off, k, ctx); load_common: ctx->seen |= SEEN_DATA | SEEN_CALL; @@ -553,6 +570,18 @@ load_common: condt = ARM_COND_HI; } + /* + * test for negative offset, only if we are + * currently scheduled to take the fast + * path. this will update the flags so that + * the slowpath instruction are ignored if the + * offset is negative. + * + * for loard_order == 0 the HI condition will + * make loads at offset 0 take the slow path too. + */ + _emit(condt, ARM_CMP_I(r_off, 0), ctx); + _emit(condt, ARM_ADD_R(r_scratch, r_off, r_skb_data), ctx); -- cgit v1.2.3 From c18fe54b3f8d7daa6a43270f82676d6a563582a4 Mon Sep 17 00:00:00 2001 From: Nicolas Schichan Date: Tue, 21 Jul 2015 14:14:14 +0200 Subject: ARM: net: fix vlan access instructions in ARM JIT. This makes BPF_ANC | SKF_AD_VLAN_TAG and BPF_ANC | SKF_AD_VLAN_TAG_PRESENT have the same behaviour as the in kernel VM and makes the test_bpf LD_VLAN_TAG and LD_VLAN_TAG_PRESENT tests pass. Signed-off-by: Nicolas Schichan Signed-off-by: David S. Miller --- arch/arm/net/bpf_jit_32.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c index d9b25242f743..c011e2296cb1 100644 --- a/arch/arm/net/bpf_jit_32.c +++ b/arch/arm/net/bpf_jit_32.c @@ -889,9 +889,11 @@ b_epilogue: off = offsetof(struct sk_buff, vlan_tci); emit(ARM_LDRH_I(r_A, r_skb, off), ctx); if (code == (BPF_ANC | SKF_AD_VLAN_TAG)) - OP_IMM3(ARM_AND, r_A, r_A, VLAN_VID_MASK, ctx); - else - OP_IMM3(ARM_AND, r_A, r_A, VLAN_TAG_PRESENT, ctx); + OP_IMM3(ARM_AND, r_A, r_A, ~VLAN_TAG_PRESENT, ctx); + else { + OP_IMM3(ARM_LSR, r_A, r_A, 12, ctx); + OP_IMM3(ARM_AND, r_A, r_A, 0x1, ctx); + } break; case BPF_ANC | SKF_AD_QUEUE: ctx->seen |= SEEN_SKB; -- cgit v1.2.3 From 0470eb99b4721586ccac954faac3fa4472da0845 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Tue, 21 Jul 2015 16:33:50 +0200 Subject: netlink: don't hold mutex in rcu callback when releasing mmapd ring Kirill A. Shutemov says: This simple test-case trigers few locking asserts in kernel: int main(int argc, char **argv) { unsigned int block_size = 16 * 4096; struct nl_mmap_req req = { .nm_block_size = block_size, .nm_block_nr = 64, .nm_frame_size = 16384, .nm_frame_nr = 64 * block_size / 16384, }; unsigned int ring_size; int fd; fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC); if (setsockopt(fd, SOL_NETLINK, NETLINK_RX_RING, &req, sizeof(req)) < 0) exit(1); if (setsockopt(fd, SOL_NETLINK, NETLINK_TX_RING, &req, sizeof(req)) < 0) exit(1); ring_size = req.nm_block_nr * req.nm_block_size; mmap(NULL, 2 * ring_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); return 0; } +++ exited with 0 +++ BUG: sleeping function called from invalid context at /home/kas/git/public/linux-mm/kernel/locking/mutex.c:616 in_atomic(): 1, irqs_disabled(): 0, pid: 1, name: init 3 locks held by init/1: #0: (reboot_mutex){+.+...}, at: [] SyS_reboot+0xa9/0x220 #1: ((reboot_notifier_list).rwsem){.+.+..}, at: [] __blocking_notifier_call_chain+0x39/0x70 #2: (rcu_callback){......}, at: [] rcu_do_batch.isra.49+0x160/0x10c0 Preemption disabled at:[] __delay+0xf/0x20 CPU: 1 PID: 1 Comm: init Not tainted 4.1.0-00009-gbddf4c4818e0 #253 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS Debian-1.8.2-1 04/01/2014 ffff88017b3d8000 ffff88027bc03c38 ffffffff81929ceb 0000000000000102 0000000000000000 ffff88027bc03c68 ffffffff81085a9d 0000000000000002 ffffffff81ca2a20 0000000000000268 0000000000000000 ffff88027bc03c98 Call Trace: [] dump_stack+0x4f/0x7b [] ___might_sleep+0x16d/0x270 [] __might_sleep+0x4d/0x90 [] mutex_lock_nested+0x2f/0x430 [] ? _raw_spin_unlock_irqrestore+0x5d/0x80 [] ? __this_cpu_preempt_check+0x13/0x20 [] netlink_set_ring+0x1ed/0x350 [] ? netlink_undo_bind+0x70/0x70 [] netlink_sock_destruct+0x80/0x150 [] __sk_free+0x1d/0x160 [] sk_free+0x19/0x20 [..] Cong Wang says: We can't hold mutex lock in a rcu callback, [..] Thomas Graf says: The socket should be dead at this point. It might be simpler to add a netlink_release_ring() function which doesn't require locking at all. Reported-by: "Kirill A. Shutemov" Diagnosed-by: Cong Wang Suggested-by: Thomas Graf Signed-off-by: Florian Westphal Signed-off-by: David S. Miller --- net/netlink/af_netlink.c | 79 ++++++++++++++++++++++++++++-------------------- 1 file changed, 47 insertions(+), 32 deletions(-) diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 9a0ae7172f92..d8e2e3918ce2 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -357,25 +357,52 @@ err1: return NULL; } + +static void +__netlink_set_ring(struct sock *sk, struct nl_mmap_req *req, bool tx_ring, void **pg_vec, + unsigned int order) +{ + struct netlink_sock *nlk = nlk_sk(sk); + struct sk_buff_head *queue; + struct netlink_ring *ring; + + queue = tx_ring ? &sk->sk_write_queue : &sk->sk_receive_queue; + ring = tx_ring ? &nlk->tx_ring : &nlk->rx_ring; + + spin_lock_bh(&queue->lock); + + ring->frame_max = req->nm_frame_nr - 1; + ring->head = 0; + ring->frame_size = req->nm_frame_size; + ring->pg_vec_pages = req->nm_block_size / PAGE_SIZE; + + swap(ring->pg_vec_len, req->nm_block_nr); + swap(ring->pg_vec_order, order); + swap(ring->pg_vec, pg_vec); + + __skb_queue_purge(queue); + spin_unlock_bh(&queue->lock); + + WARN_ON(atomic_read(&nlk->mapped)); + + if (pg_vec) + free_pg_vec(pg_vec, order, req->nm_block_nr); +} + static int netlink_set_ring(struct sock *sk, struct nl_mmap_req *req, - bool closing, bool tx_ring) + bool tx_ring) { struct netlink_sock *nlk = nlk_sk(sk); struct netlink_ring *ring; - struct sk_buff_head *queue; void **pg_vec = NULL; unsigned int order = 0; - int err; ring = tx_ring ? &nlk->tx_ring : &nlk->rx_ring; - queue = tx_ring ? &sk->sk_write_queue : &sk->sk_receive_queue; - if (!closing) { - if (atomic_read(&nlk->mapped)) - return -EBUSY; - if (atomic_read(&ring->pending)) - return -EBUSY; - } + if (atomic_read(&nlk->mapped)) + return -EBUSY; + if (atomic_read(&ring->pending)) + return -EBUSY; if (req->nm_block_nr) { if (ring->pg_vec != NULL) @@ -407,31 +434,19 @@ static int netlink_set_ring(struct sock *sk, struct nl_mmap_req *req, return -EINVAL; } - err = -EBUSY; mutex_lock(&nlk->pg_vec_lock); - if (closing || atomic_read(&nlk->mapped) == 0) { - err = 0; - spin_lock_bh(&queue->lock); - - ring->frame_max = req->nm_frame_nr - 1; - ring->head = 0; - ring->frame_size = req->nm_frame_size; - ring->pg_vec_pages = req->nm_block_size / PAGE_SIZE; - - swap(ring->pg_vec_len, req->nm_block_nr); - swap(ring->pg_vec_order, order); - swap(ring->pg_vec, pg_vec); - - __skb_queue_purge(queue); - spin_unlock_bh(&queue->lock); - - WARN_ON(atomic_read(&nlk->mapped)); + if (atomic_read(&nlk->mapped) == 0) { + __netlink_set_ring(sk, req, tx_ring, pg_vec, order); + mutex_unlock(&nlk->pg_vec_lock); + return 0; } + mutex_unlock(&nlk->pg_vec_lock); if (pg_vec) free_pg_vec(pg_vec, order, req->nm_block_nr); - return err; + + return -EBUSY; } static void netlink_mm_open(struct vm_area_struct *vma) @@ -900,10 +915,10 @@ static void netlink_sock_destruct(struct sock *sk) memset(&req, 0, sizeof(req)); if (nlk->rx_ring.pg_vec) - netlink_set_ring(sk, &req, true, false); + __netlink_set_ring(sk, &req, false, NULL, 0); memset(&req, 0, sizeof(req)); if (nlk->tx_ring.pg_vec) - netlink_set_ring(sk, &req, true, true); + __netlink_set_ring(sk, &req, true, NULL, 0); } #endif /* CONFIG_NETLINK_MMAP */ @@ -2223,7 +2238,7 @@ static int netlink_setsockopt(struct socket *sock, int level, int optname, return -EINVAL; if (copy_from_user(&req, optval, sizeof(req))) return -EFAULT; - err = netlink_set_ring(sk, &req, false, + err = netlink_set_ring(sk, &req, optname == NETLINK_TX_RING); break; } -- cgit v1.2.3 From bac541e46319c2dc6ff9fd5ad6df59cd38686bdb Mon Sep 17 00:00:00 2001 From: Chris J Arges Date: Tue, 21 Jul 2015 12:36:33 -0500 Subject: openvswitch: allocate nr_node_ids flow_stats instead of num_possible_nodes Some architectures like POWER can have a NUMA node_possible_map that contains sparse entries. This causes memory corruption with openvswitch since it allocates flow_cache with a multiple of num_possible_nodes() and assumes the node variable returned by for_each_node will index into flow->stats[node]. Use nr_node_ids to allocate a maximal sparse array instead of num_possible_nodes(). The crash was noticed after 3af229f2 was applied as it changed the node_possible_map to match node_online_map on boot. Fixes: 3af229f2071f5b5cb31664be6109561fbe19c861 Signed-off-by: Chris J Arges Acked-by: Pravin B Shelar Acked-by: Nishanth Aravamudan Signed-off-by: David S. Miller --- net/openvswitch/flow_table.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/openvswitch/flow_table.c b/net/openvswitch/flow_table.c index 4613df8c8290..65523948fb95 100644 --- a/net/openvswitch/flow_table.c +++ b/net/openvswitch/flow_table.c @@ -752,7 +752,7 @@ int ovs_flow_init(void) BUILD_BUG_ON(sizeof(struct sw_flow_key) % sizeof(long)); flow_cache = kmem_cache_create("sw_flow", sizeof(struct sw_flow) - + (num_possible_nodes() + + (nr_node_ids * sizeof(struct flow_stats *)), 0, 0, NULL); if (flow_cache == NULL) -- cgit v1.2.3 From a46fa260f6f5e8f80a725b28e4aee5a04d1bd79e Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Tue, 21 Jul 2015 12:06:45 -0500 Subject: net: phy: dp83867: Fix warning check for setting the internal delay MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix warning: logical ‘or’ of collectively exhaustive tests is always true Change the internal delay check from an 'or' condition to an 'and' condition. Reported-by: David Binderman Signed-off-by: Dan Murphy Acked-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/dp83867.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/phy/dp83867.c b/drivers/net/phy/dp83867.c index c7a12e2e07b7..8a3bf5469892 100644 --- a/drivers/net/phy/dp83867.c +++ b/drivers/net/phy/dp83867.c @@ -164,7 +164,7 @@ static int dp83867_config_init(struct phy_device *phydev) return ret; } - if ((phydev->interface >= PHY_INTERFACE_MODE_RGMII_ID) || + if ((phydev->interface >= PHY_INTERFACE_MODE_RGMII_ID) && (phydev->interface <= PHY_INTERFACE_MODE_RGMII_RXID)) { val = phy_read_mmd_indirect(phydev, DP83867_RGMIICTL, DP83867_DEVADDR, phydev->addr); -- cgit v1.2.3 From d8b48911fd249bc1a3431a9515619403c96d6af3 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 22 Jul 2015 01:31:59 +0300 Subject: ravb: fix ring memory allocation The driver is written as if it can adapt to a low memory situation allocating less RX skbs and TX aligned buffers than the respective RX/TX ring sizes. In reality though the driver would malfunction in this case. Stop being overly smart and just fail in such situation -- this is achieved by moving the memory allocation from ravb_ring_format() to ravb_ring_init(). We leave dma_map_single() calls in place but make their failure non-fatal by marking the corresponding RX descriptors with zero data size which should prevent DMA to an invalid addresses. Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/ravb_main.c | 59 ++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 25 deletions(-) diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c index d08c250e843e..78849dd4ef8e 100644 --- a/drivers/net/ethernet/renesas/ravb_main.c +++ b/drivers/net/ethernet/renesas/ravb_main.c @@ -228,9 +228,7 @@ static void ravb_ring_format(struct net_device *ndev, int q) struct ravb_desc *desc = NULL; int rx_ring_size = sizeof(*rx_desc) * priv->num_rx_ring[q]; int tx_ring_size = sizeof(*tx_desc) * priv->num_tx_ring[q]; - struct sk_buff *skb; dma_addr_t dma_addr; - void *buffer; int i; priv->cur_rx[q] = 0; @@ -241,41 +239,28 @@ static void ravb_ring_format(struct net_device *ndev, int q) memset(priv->rx_ring[q], 0, rx_ring_size); /* Build RX ring buffer */ for (i = 0; i < priv->num_rx_ring[q]; i++) { - priv->rx_skb[q][i] = NULL; - skb = netdev_alloc_skb(ndev, PKT_BUF_SZ + RAVB_ALIGN - 1); - if (!skb) - break; - ravb_set_buffer_align(skb); /* RX descriptor */ rx_desc = &priv->rx_ring[q][i]; /* The size of the buffer should be on 16-byte boundary. */ rx_desc->ds_cc = cpu_to_le16(ALIGN(PKT_BUF_SZ, 16)); - dma_addr = dma_map_single(&ndev->dev, skb->data, + dma_addr = dma_map_single(&ndev->dev, priv->rx_skb[q][i]->data, ALIGN(PKT_BUF_SZ, 16), DMA_FROM_DEVICE); - if (dma_mapping_error(&ndev->dev, dma_addr)) { - dev_kfree_skb(skb); - break; - } - priv->rx_skb[q][i] = skb; + /* We just set the data size to 0 for a failed mapping which + * should prevent DMA from happening... + */ + if (dma_mapping_error(&ndev->dev, dma_addr)) + rx_desc->ds_cc = cpu_to_le16(0); rx_desc->dptr = cpu_to_le32(dma_addr); rx_desc->die_dt = DT_FEMPTY; } rx_desc = &priv->rx_ring[q][i]; rx_desc->dptr = cpu_to_le32((u32)priv->rx_desc_dma[q]); rx_desc->die_dt = DT_LINKFIX; /* type */ - priv->dirty_rx[q] = (u32)(i - priv->num_rx_ring[q]); memset(priv->tx_ring[q], 0, tx_ring_size); /* Build TX ring buffer */ for (i = 0; i < priv->num_tx_ring[q]; i++) { - priv->tx_skb[q][i] = NULL; - priv->tx_buffers[q][i] = NULL; - buffer = kmalloc(PKT_BUF_SZ + RAVB_ALIGN - 1, GFP_KERNEL); - if (!buffer) - break; - /* Aligned TX buffer */ - priv->tx_buffers[q][i] = buffer; tx_desc = &priv->tx_ring[q][i]; tx_desc->die_dt = DT_EEMPTY; } @@ -298,7 +283,10 @@ static void ravb_ring_format(struct net_device *ndev, int q) static int ravb_ring_init(struct net_device *ndev, int q) { struct ravb_private *priv = netdev_priv(ndev); + struct sk_buff *skb; int ring_size; + void *buffer; + int i; /* Allocate RX and TX skb rings */ priv->rx_skb[q] = kcalloc(priv->num_rx_ring[q], @@ -308,12 +296,28 @@ static int ravb_ring_init(struct net_device *ndev, int q) if (!priv->rx_skb[q] || !priv->tx_skb[q]) goto error; + for (i = 0; i < priv->num_rx_ring[q]; i++) { + skb = netdev_alloc_skb(ndev, PKT_BUF_SZ + RAVB_ALIGN - 1); + if (!skb) + goto error; + ravb_set_buffer_align(skb); + priv->rx_skb[q][i] = skb; + } + /* Allocate rings for the aligned buffers */ priv->tx_buffers[q] = kcalloc(priv->num_tx_ring[q], sizeof(*priv->tx_buffers[q]), GFP_KERNEL); if (!priv->tx_buffers[q]) goto error; + for (i = 0; i < priv->num_tx_ring[q]; i++) { + buffer = kmalloc(PKT_BUF_SZ + RAVB_ALIGN - 1, GFP_KERNEL); + if (!buffer) + goto error; + /* Aligned TX buffer */ + priv->tx_buffers[q][i] = buffer; + } + /* Allocate all RX descriptors. */ ring_size = sizeof(struct ravb_ex_rx_desc) * (priv->num_rx_ring[q] + 1); priv->rx_ring[q] = dma_alloc_coherent(NULL, ring_size, @@ -524,6 +528,10 @@ static bool ravb_rx(struct net_device *ndev, int *quota, int q) if (--boguscnt < 0) break; + /* We use 0-byte descriptors to mark the DMA mapping errors */ + if (!pkt_len) + continue; + if (desc_status & MSC_MC) stats->multicast++; @@ -587,10 +595,11 @@ static bool ravb_rx(struct net_device *ndev, int *quota, int q) le16_to_cpu(desc->ds_cc), DMA_FROM_DEVICE); skb_checksum_none_assert(skb); - if (dma_mapping_error(&ndev->dev, dma_addr)) { - dev_kfree_skb_any(skb); - break; - } + /* We just set the data size to 0 for a failed mapping + * which should prevent DMA from happening... + */ + if (dma_mapping_error(&ndev->dev, dma_addr)) + desc->ds_cc = cpu_to_le16(0); desc->dptr = cpu_to_le32(dma_addr); priv->rx_skb[q][entry] = skb; } -- cgit v1.2.3 From 21e9d017b88ea0baa367ef0b6516d794fa23e85e Mon Sep 17 00:00:00 2001 From: Hui Wang Date: Wed, 22 Jul 2015 10:33:34 +0800 Subject: ALSA: hda - remove one pin from ALC292_STANDARD_PINS One more Dell laptop with alc293 codec needs ALC293_FIXUP_DELL1_MIC_NO_PRESENCE, but the pin 0x1e does not match the corresponding one in the ALC292_STANDARD_PINS. To use this macro for this machine, we need to remove pin 0x1e from it. BugLink: https://bugs.launchpad.net/bugs/1476888 Cc: Signed-off-by: Hui Wang Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index caba66b2311c..ee6f13af647d 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -5430,8 +5430,7 @@ static const struct hda_model_fixup alc269_fixup_models[] = { {0x15, 0x0221401f}, \ {0x1a, 0x411111f0}, \ {0x1b, 0x411111f0}, \ - {0x1d, 0x40700001}, \ - {0x1e, 0x411111f0} + {0x1d, 0x40700001} #define ALC298_STANDARD_PINS \ {0x18, 0x411111f0}, \ @@ -5690,35 +5689,48 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { {0x13, 0x411111f0}, {0x16, 0x01014020}, {0x18, 0x411111f0}, - {0x19, 0x01a19030}), + {0x19, 0x01a19030}, + {0x1e, 0x411111f0}), SND_HDA_PIN_QUIRK(0x10ec0292, 0x1028, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE, ALC292_STANDARD_PINS, {0x12, 0x90a60140}, {0x13, 0x411111f0}, {0x16, 0x01014020}, {0x18, 0x02a19031}, - {0x19, 0x01a1903e}), + {0x19, 0x01a1903e}, + {0x1e, 0x411111f0}), SND_HDA_PIN_QUIRK(0x10ec0292, 0x1028, "Dell", ALC269_FIXUP_DELL3_MIC_NO_PRESENCE, ALC292_STANDARD_PINS, {0x12, 0x90a60140}, {0x13, 0x411111f0}, {0x16, 0x411111f0}, {0x18, 0x411111f0}, - {0x19, 0x411111f0}), + {0x19, 0x411111f0}, + {0x1e, 0x411111f0}), SND_HDA_PIN_QUIRK(0x10ec0293, 0x1028, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE, ALC292_STANDARD_PINS, {0x12, 0x40000000}, {0x13, 0x90a60140}, {0x16, 0x21014020}, {0x18, 0x411111f0}, - {0x19, 0x21a19030}), + {0x19, 0x21a19030}, + {0x1e, 0x411111f0}), SND_HDA_PIN_QUIRK(0x10ec0293, 0x1028, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE, ALC292_STANDARD_PINS, {0x12, 0x40000000}, {0x13, 0x90a60140}, {0x16, 0x411111f0}, {0x18, 0x411111f0}, - {0x19, 0x411111f0}), + {0x19, 0x411111f0}, + {0x1e, 0x411111f0}), + SND_HDA_PIN_QUIRK(0x10ec0293, 0x1028, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE, + ALC292_STANDARD_PINS, + {0x12, 0x40000000}, + {0x13, 0x90a60140}, + {0x16, 0x21014020}, + {0x18, 0x411111f0}, + {0x19, 0x21a19030}, + {0x1e, 0x411111ff}), SND_HDA_PIN_QUIRK(0x10ec0298, 0x1028, "Dell", ALC298_FIXUP_DELL1_MIC_NO_PRESENCE, ALC298_STANDARD_PINS, {0x12, 0x90a60130}, -- cgit v1.2.3 From cba59972a1191a0c1647a52fe745eed7a4b34b38 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Wed, 22 Jul 2015 10:00:25 +0200 Subject: ALSA: hda - Add headset mic pin quirk for a Dell device Without this patch, the headset mic will not work on this machine. BugLink: https://bugs.launchpad.net/bugs/1476987 Signed-off-by: David Henningsson Cc: Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index ee6f13af647d..742fc626f9e1 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -5461,6 +5461,17 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { {0x17, 0x40000000}, {0x1d, 0x40700001}, {0x21, 0x02211030}), + SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, + {0x12, 0x40000000}, + {0x14, 0x90170130}, + {0x17, 0x411111f0}, + {0x18, 0x411111f0}, + {0x19, 0x411111f0}, + {0x1a, 0x411111f0}, + {0x1b, 0x01014020}, + {0x1d, 0x4054c029}, + {0x1e, 0x411111f0}, + {0x21, 0x0221103f}), SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, {0x12, 0x90a60160}, {0x14, 0x90170120}, -- cgit v1.2.3 From c0d3fce5e192c6b45a9d8e06aecfcec546f73884 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Mon, 20 Jul 2015 15:14:53 +0100 Subject: arm64: switch_to: calculate cpu context pointer using separate register Commit 0c8c0f03e3a2 ("x86/fpu, sched: Dynamically allocate 'struct fpu'") moved the thread_struct to the bottom of task_struct. As a result, the offset is now too large to be used in an immediate add on arm64 with some kernel configs: arch/arm64/kernel/entry.S: Assembler messages: arch/arm64/kernel/entry.S:588: Error: immediate out of range arch/arm64/kernel/entry.S:597: Error: immediate out of range This patch calculates the offset using an additional register instead of an immediate offset. Fixes: 0c8c0f03e3a2 ("x86/fpu, sched: Dynamically allocate 'struct fpu'") Cc: Dave Hansen Cc: Olof Johansson Cc: Ingo Molnar Signed-off-by: Will Deacon Tested-by: Guenter Roeck Signed-off-by: Catalin Marinas --- arch/arm64/kernel/entry.S | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index f860bfda454a..e16351819fed 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -585,7 +585,8 @@ ENDPROC(el0_irq) * */ ENTRY(cpu_switch_to) - add x8, x0, #THREAD_CPU_CONTEXT + mov x10, #THREAD_CPU_CONTEXT + add x8, x0, x10 mov x9, sp stp x19, x20, [x8], #16 // store callee-saved registers stp x21, x22, [x8], #16 @@ -594,7 +595,7 @@ ENTRY(cpu_switch_to) stp x27, x28, [x8], #16 stp x29, x9, [x8], #16 str lr, [x8] - add x8, x1, #THREAD_CPU_CONTEXT + add x8, x1, x10 ldp x19, x20, [x8], #16 // restore callee-saved registers ldp x21, x22, [x8], #16 ldp x23, x24, [x8], #16 -- cgit v1.2.3 From 3bc38fc110c642c0a455a5214465bb4d62805a75 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Mon, 13 Jul 2015 20:30:04 +0000 Subject: ARM64/irq: Use access helper irq_data_get_affinity_mask() This is a preparatory patch for moving irq_data struct members. Signed-off-by: Jiang Liu Reviewed-by: Hanjun Guo Cc: linux-arm-kernel@lists.infradead.org Signed-off-by: Thomas Gleixner Signed-off-by: Catalin Marinas --- arch/arm64/kernel/irq.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/kernel/irq.c b/arch/arm64/kernel/irq.c index 240b75c0e94f..463fa2e7e34c 100644 --- a/arch/arm64/kernel/irq.c +++ b/arch/arm64/kernel/irq.c @@ -61,7 +61,7 @@ void __init init_IRQ(void) static bool migrate_one_irq(struct irq_desc *desc) { struct irq_data *d = irq_desc_get_irq_data(desc); - const struct cpumask *affinity = d->affinity; + const struct cpumask *affinity = irq_data_get_affinity_mask(d); struct irq_chip *c; bool ret = false; @@ -81,7 +81,7 @@ static bool migrate_one_irq(struct irq_desc *desc) if (!c->irq_set_affinity) pr_debug("IRQ%u: unable to set affinity\n", d->irq); else if (c->irq_set_affinity(d, affinity, false) == IRQ_SET_MASK_OK && ret) - cpumask_copy(d->affinity, affinity); + cpumask_copy(irq_data_get_affinity_mask(d), affinity); return ret; } -- cgit v1.2.3 From 5677d67ae3949f09f57357241b88222d49b8c782 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 16 Jul 2015 16:47:50 +0200 Subject: drm: Stop resetting connector state to unknown MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's causing piles of issues since we've stopped forcing full detect cycles in the sysfs interfaces with commit c484f02d0f02fbbfc6decc945a69aae011041a27 Author: Chris Wilson Date: Fri Mar 6 12:36:42 2015 +0000 drm: Lighten sysfs connector 'status' The original justification for this was that the hpd handlers could use the unknown state as a hint to force a full detection. But current i915 code isn't doing that any more, and no one else really uses reset on resume. So instead just keep the old state around. References: http://article.gmane.org/gmane.comp.freedesktop.xorg.drivers.intel/62584 Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=100641 Cc: Rui Matos Cc: Julien Wajsberg Cc: kuddel.mail@gmx.de Cc: Lennart Poettering Cc: stable@vger.kernel.org Acked-by: Rob Clark Tested-by: Rui Tiago Cação Matos Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_crtc.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 357bd04a173b..fed748311b92 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -5398,12 +5398,9 @@ void drm_mode_config_reset(struct drm_device *dev) if (encoder->funcs->reset) encoder->funcs->reset(encoder); - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - connector->status = connector_status_unknown; - + list_for_each_entry(connector, &dev->mode_config.connector_list, head) if (connector->funcs->reset) connector->funcs->reset(connector); - } } EXPORT_SYMBOL(drm_mode_config_reset); -- cgit v1.2.3 From aebda618718157a69c0dc0adb978d69bc2b8723c Mon Sep 17 00:00:00 2001 From: John Youn Date: Mon, 17 Sep 2001 00:00:00 -0700 Subject: usb: dwc3: Reset the transfer resource index on SET_INTERFACE This fixes an issue introduced in commit b23c843992b6 (usb: dwc3: gadget: fix DEPSTARTCFG for non-EP0 EPs) that made sure we would only use DEPSTARTCFG once per SetConfig. The trick is that we should use one DEPSTARTCFG per SetConfig *OR* SetInterface. SetInterface was completely missed from the original patch. This problem became aparent after commit 76e838c9f776 (usb: dwc3: gadget: return error if command sent to DEPCMD register fails) added checking of the return status of device endpoint commands. 'Set Endpoint Transfer Resource' command was caught failing occasionally. This is because the Transfer Resource Index was not getting reset during a SET_INTERFACE request. Finally, to fix the issue, was we have to do is make sure that our start_config_issued flag gets reset whenever we receive a SetInterface request. To verify the problem (and its fix), all we have to do is run test 9 from testusb with 'testusb -t 9 -s 2048 -a -c 5000'. Tested-by: Huang Rui Tested-by: Subbaraya Sundeep Bhatta Fixes: b23c843992b6 (usb: dwc3: gadget: fix DEPSTARTCFG for non-EP0 EPs) Cc: # v3.2+ Signed-off-by: John Youn Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/ep0.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 2ef3c8d6a9db..69e769c35cf5 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -727,6 +727,10 @@ static int dwc3_ep0_std_request(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) dwc3_trace(trace_dwc3_ep0, "USB_REQ_SET_ISOCH_DELAY"); ret = dwc3_ep0_set_isoch_delay(dwc, ctrl); break; + case USB_REQ_SET_INTERFACE: + dwc3_trace(trace_dwc3_ep0, "USB_REQ_SET_INTERFACE"); + dwc->start_config_issued = false; + /* Fall through */ default: dwc3_trace(trace_dwc3_ep0, "Forwarding to gadget driver"); ret = dwc3_ep0_delegate_req(dwc, ctrl); -- cgit v1.2.3 From 1c9cf9b211030a454a84cbc1cb15b82d9aa49011 Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Thu, 16 Jul 2015 17:23:14 -0600 Subject: x86/mm: Move warning from __ioremap_check_ram() to the call site __ioremap_check_ram() has a WARN_ONCE() which is emitted when the given pfn range is not RAM. The warning is bogus in two aspects: - it never triggers since walk_system_ram_range() only calls __ioremap_check_ram() for RAM ranges. - the warning message is wrong as it says: "ioremap on RAM' after it established that the pfn range is not RAM. Move the WARN_ONCE() to __ioremap_caller(), and update the message to include the address range so we get an actual warning when something tries to ioremap system RAM. [ tglx: Massaged changelog ] Signed-off-by: Toshi Kani Reviewed-by: Dan Williams Cc: Roland Dreier Cc: Luis R. Rodriguez Cc: H. Peter Anvin Cc: Ingo Molnar Cc: Borislav Petkov Cc: linux-mm@kvack.org Link: http://lkml.kernel.org/r/1437088996-28511-2-git-send-email-toshi.kani@hp.com Signed-off-by: Thomas Gleixner --- arch/x86/mm/ioremap.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c index cc5ccc415cc0..fd3df0ddb4d4 100644 --- a/arch/x86/mm/ioremap.c +++ b/arch/x86/mm/ioremap.c @@ -63,8 +63,6 @@ static int __ioremap_check_ram(unsigned long start_pfn, unsigned long nr_pages, !PageReserved(pfn_to_page(start_pfn + i))) return 1; - WARN_ONCE(1, "ioremap on RAM pfn 0x%lx\n", start_pfn); - return 0; } @@ -131,8 +129,11 @@ static void __iomem *__ioremap_caller(resource_size_t phys_addr, pfn = phys_addr >> PAGE_SHIFT; last_pfn = last_addr >> PAGE_SHIFT; if (walk_system_ram_range(pfn, last_pfn - pfn + 1, NULL, - __ioremap_check_ram) == 1) + __ioremap_check_ram) == 1) { + WARN_ONCE(1, "ioremap on RAM at 0x%llx - 0x%llx\n", + phys_addr, last_addr); return NULL; + } } /* * Mappings have to be page-aligned -- cgit v1.2.3 From 9a58eebe1ace609bedf8c5a65e70a097459f5696 Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Thu, 16 Jul 2015 17:23:15 -0600 Subject: x86/mm: Remove region_is_ram() call from ioremap __ioremap_caller() calls region_is_ram() to walk through the iomem_resource table to check if a target range is in RAM, which was added to improve the lookup performance over page_is_ram() (commit 906e36c5c717 "x86: use optimized ioresource lookup in ioremap function"). page_is_ram() was no longer used when this change was added, though. __ioremap_caller() then calls walk_system_ram_range(), which had replaced page_is_ram() to improve the lookup performance (commit c81c8a1eeede "x86, ioremap: Speed up check for RAM pages"). Since both checks walk through the same iomem_resource table for the same purpose, there is no need to call both functions. Aside of that walk_system_ram_range() is the only useful check at the moment because region_is_ram() always returns -1 due to an implementation bug. That bug in region_is_ram() cannot be fixed without breaking existing ioremap callers, which rely on the subtle difference of walk_system_ram_range() versus non page aligned ranges. Once these offending callers are fixed we can use region_is_ram() and remove walk_system_ram_range(). [ tglx: Massaged changelog ] Signed-off-by: Toshi Kani Reviewed-by: Dan Williams Cc: Roland Dreier Cc: Mike Travis Cc: Luis R. Rodriguez Cc: H. Peter Anvin Cc: Ingo Molnar Cc: Borislav Petkov Cc: linux-mm@kvack.org Link: http://lkml.kernel.org/r/1437088996-28511-3-git-send-email-toshi.kani@hp.com Signed-off-by: Thomas Gleixner --- arch/x86/mm/ioremap.c | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c index fd3df0ddb4d4..b9d4a33017fd 100644 --- a/arch/x86/mm/ioremap.c +++ b/arch/x86/mm/ioremap.c @@ -92,7 +92,6 @@ static void __iomem *__ioremap_caller(resource_size_t phys_addr, pgprot_t prot; int retval; void __iomem *ret_addr; - int ram_region; /* Don't allow wraparound or zero size */ last_addr = phys_addr + size - 1; @@ -115,26 +114,15 @@ static void __iomem *__ioremap_caller(resource_size_t phys_addr, /* * Don't allow anybody to remap normal RAM that we're using.. */ - /* First check if whole region can be identified as RAM or not */ - ram_region = region_is_ram(phys_addr, size); - if (ram_region > 0) { - WARN_ONCE(1, "ioremap on RAM at 0x%lx - 0x%lx\n", - (unsigned long int)phys_addr, - (unsigned long int)last_addr); - return NULL; - } - - /* If could not be identified(-1), check page by page */ - if (ram_region < 0) { - pfn = phys_addr >> PAGE_SHIFT; - last_pfn = last_addr >> PAGE_SHIFT; - if (walk_system_ram_range(pfn, last_pfn - pfn + 1, NULL, + pfn = phys_addr >> PAGE_SHIFT; + last_pfn = last_addr >> PAGE_SHIFT; + if (walk_system_ram_range(pfn, last_pfn - pfn + 1, NULL, __ioremap_check_ram) == 1) { - WARN_ONCE(1, "ioremap on RAM at 0x%llx - 0x%llx\n", + WARN_ONCE(1, "ioremap on RAM at 0x%llx - 0x%llx\n", phys_addr, last_addr); - return NULL; - } + return NULL; } + /* * Mappings have to be page-aligned */ -- cgit v1.2.3 From 8c38de992be9aed0b34c4fab8f972c83d3b00dc4 Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Thu, 16 Jul 2015 17:23:16 -0600 Subject: mm: Fix bugs in region_is_ram() region_is_ram() looks up the iomem_resource table to check if a target range is in RAM. However, it always returns with -1 due to invalid range checks. It always breaks the loop at the first entry of the table. Another issue is that it compares p->flags and flags, but it always fails. flags is declared as int, which makes it as a negative value with IORESOURCE_BUSY (0x80000000) set while p->flags is unsigned long. Fix the range check and flags so that region_is_ram() works as advertised. Signed-off-by: Toshi Kani Reviewed-by: Dan Williams Cc: Mike Travis Cc: Luis R. Rodriguez Cc: Andrew Morton Cc: Roland Dreier Cc: linux-mm@kvack.org Link: http://lkml.kernel.org/r/1437088996-28511-4-git-send-email-toshi.kani@hp.com Signed-off-by: Thomas Gleixner --- kernel/resource.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/resource.c b/kernel/resource.c index 90552aab5f2d..fed052a1bc9f 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -504,13 +504,13 @@ int region_is_ram(resource_size_t start, unsigned long size) { struct resource *p; resource_size_t end = start + size - 1; - int flags = IORESOURCE_MEM | IORESOURCE_BUSY; + unsigned long flags = IORESOURCE_MEM | IORESOURCE_BUSY; const char *name = "System RAM"; int ret = -1; read_lock(&resource_lock); for (p = iomem_resource.child; p ; p = p->sibling) { - if (end < p->start) + if (p->end < start) continue; if (p->start <= start && end <= p->end) { @@ -521,7 +521,7 @@ int region_is_ram(resource_size_t start, unsigned long size) ret = 1; break; } - if (p->end < start) + if (end < p->start) break; /* not found */ } read_unlock(&resource_lock); -- cgit v1.2.3 From 21974061cfb3c4b0b1a83447fb5e7cdcd06e56dc Mon Sep 17 00:00:00 2001 From: Mike Krinkin Date: Sun, 19 Jul 2015 09:53:17 +0300 Subject: null_blk: fix use-after-free problem end_cmd finishes request associated with nullb_cmd struct, so we should save pointer to request_queue in a local variable before calling end_cmd. The problem was causes general protection fault with slab poisoning enabled. Fixes: 8b70f45e2eb2 ("null_blk: restart request processing on completion handler") Tested-by: Akinobu Mita Signed-off-by: Mike Krinkin Signed-off-by: Jens Axboe --- drivers/block/null_blk.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/block/null_blk.c b/drivers/block/null_blk.c index 69de41a87b74..3177b245d2bd 100644 --- a/drivers/block/null_blk.c +++ b/drivers/block/null_blk.c @@ -240,19 +240,19 @@ static enum hrtimer_restart null_cmd_timer_expired(struct hrtimer *timer) while ((entry = llist_del_all(&cq->list)) != NULL) { entry = llist_reverse_order(entry); do { + struct request_queue *q = NULL; + cmd = container_of(entry, struct nullb_cmd, ll_list); entry = entry->next; + if (cmd->rq) + q = cmd->rq->q; end_cmd(cmd); - if (cmd->rq) { - struct request_queue *q = cmd->rq->q; - - if (!q->mq_ops && blk_queue_stopped(q)) { - spin_lock(q->queue_lock); - if (blk_queue_stopped(q)) - blk_start_queue(q); - spin_unlock(q->queue_lock); - } + if (q && !q->mq_ops && blk_queue_stopped(q)) { + spin_lock(q->queue_lock); + if (blk_queue_stopped(q)) + blk_start_queue(q); + spin_unlock(q->queue_lock); } } while (entry); } -- cgit v1.2.3 From c3c5819a350952439c3198aa46581f9e4c46557f Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Tue, 21 Jul 2015 17:20:25 +0300 Subject: xhci: call BIOS workaround to enable runtime suspend on Intel Braswell Intel xhci hw that require XHCI_PME_STUCK quirk have as default disabled xhci from going to D3 state in runtime suspend. Driver needs to verify it can deal with the hw by calling an ACPI _DSM method to get D3 enabled. Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-pci.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 4a4cb1d91ac8..da10dc728acb 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "xhci.h" #include "xhci-trace.h" @@ -190,6 +191,19 @@ static void xhci_pme_quirk(struct xhci_hcd *xhci) readl(reg); } +#ifdef CONFIG_ACPI +static void xhci_pme_acpi_rtd3_enable(struct pci_dev *dev) +{ + static const u8 intel_dsm_uuid[] = { + 0xb7, 0x0c, 0x34, 0xac, 0x01, 0xe9, 0xbf, 0x45, + 0xb7, 0xe6, 0x2b, 0x34, 0xec, 0x93, 0x1e, 0x23, + }; + acpi_evaluate_dsm(ACPI_HANDLE(&dev->dev), intel_dsm_uuid, 3, 1, NULL); +} +#else + static void xhci_pme_acpi_rtd3_enable(struct pci_dev *dev) { } +#endif /* CONFIG_ACPI */ + /* called during probe() after chip reset completes */ static int xhci_pci_setup(struct usb_hcd *hcd) { @@ -263,6 +277,9 @@ static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) HCC_MAX_PSA(xhci->hcc_params) >= 4) xhci->shared_hcd->can_do_streams = 1; + if (xhci->quirks & XHCI_PME_STUCK_QUIRK) + xhci_pme_acpi_rtd3_enable(dev); + /* USB-2 and USB-3 roothubs initialized, allow runtime pm suspend */ pm_runtime_put_noidle(&dev->dev); -- cgit v1.2.3 From abce329c27b315cfc01be1a305ee976ee13ed4cf Mon Sep 17 00:00:00 2001 From: Rajmohan Mani Date: Tue, 21 Jul 2015 17:20:26 +0300 Subject: xhci: Workaround to get D3 working in Intel xHCI The xHCI in Intel CherryView / Braswell Platform requires a driver workaround to get xHCI D3 working. Without this workaround, xHCI might not enter D3. Workaround is to configure SSIC PORT as "unused" before D3 entry and "used" after D3 exit. This is done through a vendor specific register (PORT2_SSIC_CONFIG_REG2 at offset 0x883c), in xhci suspend / resume callbacks. Verified xHCI D3 works fine in CherryView / Braswell platform. Signed-off-by: Rajmohan Mani Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-pci.c | 40 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index da10dc728acb..5590eac2b22d 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -28,6 +28,10 @@ #include "xhci.h" #include "xhci-trace.h" +#define PORT2_SSIC_CONFIG_REG2 0x883c +#define PROG_DONE (1 << 30) +#define SSIC_PORT_UNUSED (1 << 31) + /* Device for a quirk */ #define PCI_VENDOR_ID_FRESCO_LOGIC 0x1b73 #define PCI_DEVICE_ID_FRESCO_LOGIC_PDK 0x1000 @@ -177,14 +181,44 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) } /* + * In some Intel xHCI controllers, in order to get D3 working, + * through a vendor specific SSIC CONFIG register at offset 0x883c, + * SSIC PORT need to be marked as "unused" before putting xHCI + * into D3. After D3 exit, the SSIC port need to be marked as "used". + * Without this change, xHCI might not enter D3 state. * Make sure PME works on some Intel xHCI controllers by writing 1 to clear * the Internal PME flag bit in vendor specific PMCTRL register at offset 0x80a4 */ -static void xhci_pme_quirk(struct xhci_hcd *xhci) +static void xhci_pme_quirk(struct usb_hcd *hcd, bool suspend) { + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + struct pci_dev *pdev = to_pci_dev(hcd->self.controller); u32 val; void __iomem *reg; + if (pdev->vendor == PCI_VENDOR_ID_INTEL && + pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI) { + + reg = (void __iomem *) xhci->cap_regs + PORT2_SSIC_CONFIG_REG2; + + /* Notify SSIC that SSIC profile programming is not done */ + val = readl(reg) & ~PROG_DONE; + writel(val, reg); + + /* Mark SSIC port as unused(suspend) or used(resume) */ + val = readl(reg); + if (suspend) + val |= SSIC_PORT_UNUSED; + else + val &= ~SSIC_PORT_UNUSED; + writel(val, reg); + + /* Notify SSIC that SSIC profile programming is done */ + val = readl(reg) | PROG_DONE; + writel(val, reg); + readl(reg); + } + reg = (void __iomem *) xhci->cap_regs + 0x80a4; val = readl(reg); writel(val | BIT(28), reg); @@ -324,7 +358,7 @@ static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup) pdev->no_d3cold = true; if (xhci->quirks & XHCI_PME_STUCK_QUIRK) - xhci_pme_quirk(xhci); + xhci_pme_quirk(hcd, true); return xhci_suspend(xhci, do_wakeup); } @@ -357,7 +391,7 @@ static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated) usb_enable_intel_xhci_ports(pdev); if (xhci->quirks & XHCI_PME_STUCK_QUIRK) - xhci_pme_quirk(xhci); + xhci_pme_quirk(hcd, false); retval = xhci_resume(xhci, hibernated); return retval; -- cgit v1.2.3 From 3496810663922617d4b706ef2780c279252ddd6a Mon Sep 17 00:00:00 2001 From: AMAN DEEP Date: Tue, 21 Jul 2015 17:20:27 +0300 Subject: usb: xhci: Bugfix for NULL pointer deference in xhci_endpoint_init() function virt_dev->num_cached_rings counts on freed ring and is not updated correctly. In xhci_free_or_cache_endpoint_ring() function, the free ring is added into cache and then num_rings_cache is incremented as below: virt_dev->ring_cache[rings_cached] = virt_dev->eps[ep_index].ring; virt_dev->num_rings_cached++; here, free ring pointer is added to a current index and then index is incremented. So current index always points to empty location in the ring cache. For getting available free ring, current index should be decremented first and then corresponding ring buffer value should be taken from ring cache. But In function xhci_endpoint_init(), the num_rings_cached index is accessed before decrement. virt_dev->eps[ep_index].new_ring = virt_dev->ring_cache[virt_dev->num_rings_cached]; virt_dev->ring_cache[virt_dev->num_rings_cached] = NULL; virt_dev->num_rings_cached--; This is bug in manipulating the index of ring cache. And it should be as below: virt_dev->num_rings_cached--; virt_dev->eps[ep_index].new_ring = virt_dev->ring_cache[virt_dev->num_rings_cached]; virt_dev->ring_cache[virt_dev->num_rings_cached] = NULL; Cc: Signed-off-by: Aman Deep Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-mem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index f8336408ef07..3e442f77a2b9 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1427,10 +1427,10 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, /* Attempt to use the ring cache */ if (virt_dev->num_rings_cached == 0) return -ENOMEM; + virt_dev->num_rings_cached--; virt_dev->eps[ep_index].new_ring = virt_dev->ring_cache[virt_dev->num_rings_cached]; virt_dev->ring_cache[virt_dev->num_rings_cached] = NULL; - virt_dev->num_rings_cached--; xhci_reinit_cached_ring(xhci, virt_dev->eps[ep_index].new_ring, 1, type); } -- cgit v1.2.3 From 326124a027abc9a7f43f72dc94f6f0f7a55b02b3 Mon Sep 17 00:00:00 2001 From: Brian Campbell Date: Tue, 21 Jul 2015 17:20:28 +0300 Subject: xhci: Calculate old endpoints correctly on device reset When resetting a device the number of active TTs may need to be corrected by xhci_update_tt_active_eps, but the number of old active endpoints supplied to it was always zero, so the number of TTs and the bandwidth reserved for them was not updated, and could rise unnecessarily. This affected systems using Intel's Patherpoint chipset, which rely on software bandwidth checking. For example, a Lenovo X230 would lose the ability to use ports on the docking station after enough suspend/resume cycles because the bandwidth calculated would rise with every cycle when a suitable device is attached. The correct number of active endpoints is calculated in the same way as in xhci_reserve_bandwidth. Cc: Signed-off-by: Brian Campbell Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 7da0d6043d33..526ebc0c7e72 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -3453,6 +3453,9 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev) return -EINVAL; } + if (virt_dev->tt_info) + old_active_eps = virt_dev->tt_info->active_eps; + if (virt_dev->udev != udev) { /* If the virt_dev and the udev does not match, this virt_dev * may belong to another udev. -- cgit v1.2.3 From 243292a2ad3dc365849b820a64868927168894ac Mon Sep 17 00:00:00 2001 From: Zhuang Jin Can Date: Tue, 21 Jul 2015 17:20:29 +0300 Subject: xhci: report U3 when link is in resume state xhci_hub_report_usb3_link_state() returns pls as U0 when the link is in resume state, and this causes usb core to think the link is in U0 while actually it's in resume state. When usb core transfers control request on the link, it fails with TRB error as the link is not ready for transfer. To fix the issue, report U3 when the link is in resume state, thus usb core knows the link it's not ready for transfer. Cc: Signed-off-by: Zhuang Jin Can Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-hub.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index e75c565feb53..7df8878cc37b 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -484,10 +484,13 @@ static void xhci_hub_report_usb3_link_state(struct xhci_hcd *xhci, u32 pls = status_reg & PORT_PLS_MASK; /* resume state is a xHCI internal state. - * Do not report it to usb core. + * Do not report it to usb core, instead, pretend to be U3, + * thus usb core knows it's not ready for transfer */ - if (pls == XDEV_RESUME) + if (pls == XDEV_RESUME) { + *status |= USB_SS_PORT_LS_U3; return; + } /* When the CAS bit is set then warm reset * should be performed on port -- cgit v1.2.3 From fac4271d1126c45ceaceb7f4a336317b771eb121 Mon Sep 17 00:00:00 2001 From: Zhuang Jin Can Date: Tue, 21 Jul 2015 17:20:30 +0300 Subject: xhci: prevent bus_suspend if SS port resuming in phase 1 When the link is just waken, it's in Resume state, and driver sets PLS to U0. This refers to Phase 1. Phase 2 refers to when the link has completed the transition from Resume state to U0. With the fix of xhci: report U3 when link is in resume state, it also exposes an issue that usb3 roothub and controller can suspend right after phase 1, and this causes a hard hang in controller. To fix the issue, we need to prevent usb3 bus suspend if any port is resuming in phase 1. [merge separate USB2 and USB3 port resume checking to one -Mathias] Cc: Signed-off-by: Zhuang Jin Can Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-hub.c | 6 +++--- drivers/usb/host/xhci-ring.c | 3 +++ drivers/usb/host/xhci.h | 1 + 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 7df8878cc37b..fdca8edc5836 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -1123,10 +1123,10 @@ int xhci_bus_suspend(struct usb_hcd *hcd) spin_lock_irqsave(&xhci->lock, flags); if (hcd->self.root_hub->do_remote_wakeup) { - if (bus_state->resuming_ports) { + if (bus_state->resuming_ports || /* USB2 */ + bus_state->port_remote_wakeup) { /* USB3 */ spin_unlock_irqrestore(&xhci->lock, flags); - xhci_dbg(xhci, "suspend failed because " - "a port is resuming\n"); + xhci_dbg(xhci, "suspend failed because a port is resuming\n"); return -EBUSY; } } diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 94416ff70810..6a8fc52aed58 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1546,6 +1546,9 @@ static void handle_port_status(struct xhci_hcd *xhci, usb_hcd_resume_root_hub(hcd); } + if (hcd->speed == HCD_USB3 && (temp & PORT_PLS_MASK) == XDEV_INACTIVE) + bus_state->port_remote_wakeup &= ~(1 << faked_port_index); + if ((temp & PORT_PLC) && (temp & PORT_PLS_MASK) == XDEV_RESUME) { xhci_dbg(xhci, "port resume event for port %d\n", port_id); diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 31e46cc55807..ed2ebf647c38 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -285,6 +285,7 @@ struct xhci_op_regs { #define XDEV_U0 (0x0 << 5) #define XDEV_U2 (0x2 << 5) #define XDEV_U3 (0x3 << 5) +#define XDEV_INACTIVE (0x6 << 5) #define XDEV_RESUME (0xf << 5) /* true: port has power (see HCC_PPC) */ #define PORT_POWER (1 << 9) -- cgit v1.2.3 From aca3a0489ac019b58cf32794d5362bb284cb9b94 Mon Sep 17 00:00:00 2001 From: Zhuang Jin Can Date: Tue, 21 Jul 2015 17:20:31 +0300 Subject: xhci: do not report PLC when link is in internal resume state Port link change with port in resume state should not be reported to usbcore, as this is an internal state to be handled by xhci driver. Reporting PLC to usbcore may cause usbcore clearing PLC first and port change event irq won't be generated. Cc: Signed-off-by: Zhuang Jin Can Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-hub.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index fdca8edc5836..78241b5550df 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -591,7 +591,14 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd, status |= USB_PORT_STAT_C_RESET << 16; /* USB3.0 only */ if (hcd->speed == HCD_USB3) { - if ((raw_port_status & PORT_PLC)) + /* Port link change with port in resume state should not be + * reported to usbcore, as this is an internal state to be + * handled by xhci driver. Reporting PLC to usbcore may + * cause usbcore clearing PLC first and port change event + * irq won't be generated. + */ + if ((raw_port_status & PORT_PLC) && + (raw_port_status & PORT_PLS_MASK) != XDEV_RESUME) status |= USB_PORT_STAT_C_LINK_STATE << 16; if ((raw_port_status & PORT_WRC)) status |= USB_PORT_STAT_C_BH_RESET << 16; -- cgit v1.2.3 From 2d2a316765d956bc5cb6bb367b2ec52ca59ab8e9 Mon Sep 17 00:00:00 2001 From: Lu Baolu Date: Tue, 16 Jun 2015 09:08:26 +0800 Subject: usb: core: lpm: set lpm_capable for root hub device Commit 25cd2882e2fc ("usb/xhci: Change how we indicate a host supports Link PM.") removed the code to set lpm_capable for USB 3.0 super-speed root hub. The intention of that change was to avoid touching usb core internal field, a.k.a. lpm_capable, and let usb core to set it by checking U1 and U2 exit latency values in the descriptor. Usb core checks and sets lpm_capable in hub_port_init(). Unfortunately, root hub is a special usb device as it has no parent. Hub_port_init() will never be called for a root hub device. That means lpm_capable will by no means be set for the root hub. As the result, lpm isn't functional at all in Linux kernel. This patch add the code to check and set lpm_capable when registering a root hub device. It could be back-ported to kernels as old as v3.15, that contains the Commit 25cd2882e2fc ("usb/xhci: Change how we indicate a host supports Link PM."). Cc: stable@vger.kernel.org # 3.15 Reported-by: Kevin Strasser Signed-off-by: Lu Baolu Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd.c | 7 +++++-- drivers/usb/core/hub.c | 2 +- drivers/usb/core/usb.h | 1 + 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index be5b2074f906..cbcd0920fb51 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1022,9 +1022,12 @@ static int register_root_hub(struct usb_hcd *hcd) dev_name(&usb_dev->dev), retval); return (retval < 0) ? retval : -EMSGSIZE; } - if (usb_dev->speed == USB_SPEED_SUPER) { + + if (le16_to_cpu(usb_dev->descriptor.bcdUSB) >= 0x0201) { retval = usb_get_bos_descriptor(usb_dev); - if (retval < 0) { + if (!retval) { + usb_dev->lpm_capable = usb_device_supports_lpm(usb_dev); + } else if (usb_dev->speed == USB_SPEED_SUPER) { mutex_unlock(&usb_bus_list_lock); dev_dbg(parent_dev, "can't read %s bos descriptor %d\n", dev_name(&usb_dev->dev), retval); diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 43cb2f2e3b43..73dfa194160b 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -122,7 +122,7 @@ struct usb_hub *usb_hub_to_struct_hub(struct usb_device *hdev) return usb_get_intfdata(hdev->actconfig->interface[0]); } -static int usb_device_supports_lpm(struct usb_device *udev) +int usb_device_supports_lpm(struct usb_device *udev) { /* USB 2.1 (and greater) devices indicate LPM support through * their USB 2.0 Extended Capabilities BOS descriptor. diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 7eb1e26798e5..457255a3306a 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -65,6 +65,7 @@ extern int usb_hub_init(void); extern void usb_hub_cleanup(void); extern int usb_major_init(void); extern void usb_major_cleanup(void); +extern int usb_device_supports_lpm(struct usb_device *udev); #ifdef CONFIG_PM -- cgit v1.2.3 From 7d8021c967648accd1b78e5e1ddaad655cd2c61f Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 30 Jun 2015 11:25:54 -0400 Subject: USB: OHCI: Fix race between ED unlink and URB submission This patch fixes a bug introduced by commit 977dcfdc6031 ("USB: OHCI: don't lose track of EDs when a controller dies"). The commit changed ed_state from ED_UNLINK to ED_IDLE too early, before finish_urb() had been called. The user-visible consequence is that the driver occasionally crashes or locks up when an URB is submitted while another URB for the same endpoint is being unlinked. This patch moves the ED state change later, to the right place. The drawback is that now we may unnecessarily execute some instructions multiple times when a controller dies. Since controllers dying is an exceptional occurrence, a little wasted time won't matter. Signed-off-by: Alan Stern Reported-by: Heiko Przybyl Tested-by: Heiko Przybyl Fixes: 977dcfdc60311e7aa571cabf6f39c36dde13339e CC: Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-q.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c index f7d561ed3c23..d029bbe9eb36 100644 --- a/drivers/usb/host/ohci-q.c +++ b/drivers/usb/host/ohci-q.c @@ -981,10 +981,6 @@ rescan_all: int completed, modified; __hc32 *prev; - /* Is this ED already invisible to the hardware? */ - if (ed->state == ED_IDLE) - goto ed_idle; - /* only take off EDs that the HC isn't using, accounting for * frame counter wraps and EDs with partially retired TDs */ @@ -1012,12 +1008,10 @@ skip_ed: } /* ED's now officially unlinked, hc doesn't see */ - ed->state = ED_IDLE; ed->hwHeadP &= ~cpu_to_hc32(ohci, ED_H); ed->hwNextED = 0; wmb(); ed->hwINFO &= ~cpu_to_hc32(ohci, ED_SKIP | ED_DEQUEUE); -ed_idle: /* reentrancy: if we drop the schedule lock, someone might * have modified this list. normally it's just prepending @@ -1088,6 +1082,7 @@ rescan_this: if (list_empty(&ed->td_list)) { *last = ed->ed_next; ed->ed_next = NULL; + ed->state = ED_IDLE; list_del(&ed->in_use_list); } else if (ohci->rh_state == OHCI_RH_RUNNING) { *last = ed->ed_next; -- cgit v1.2.3 From 5fb2c782f451a4fb9c19c076e2c442839faf0f76 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Mon, 6 Jul 2015 13:12:32 +0200 Subject: usb-storage: ignore ZTE MF 823 card reader in mode 0x1225 This device automatically switches itself to another mode (0x1405) unless the specific access pattern of Windows is followed in its initial mode. That makes a dirty unmount of the internal storage devices inevitable if they are mounted. So the card reader of such a device should be ignored, lest an unclean removal become inevitable. This replaces an earlier patch that ignored all LUNs of this device. That patch was overly broad. Signed-off-by: Oliver Neukum CC: stable@vger.kernel.org Reviewed-by: Lars Melin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index caf188800c67..87898ca2ed17 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -2065,6 +2065,18 @@ UNUSUAL_DEV( 0x1908, 0x3335, 0x0200, 0x0200, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NO_READ_DISC_INFO ), +/* Reported by Oliver Neukum + * This device morphes spontaneously into another device if the access + * pattern of Windows isn't followed. Thus writable media would be dirty + * if the initial instance is used. So the device is limited to its + * virtual CD. + * And yes, the concept that BCD goes up to 9 is not heeded */ +UNUSUAL_DEV( 0x19d2, 0x1225, 0x0000, 0xffff, + "ZTE,Incorporated", + "ZTE WCDMA Technologies MSM", + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_SINGLE_LUN ), + /* Reported by Sven Geggus * This encrypted pen drive returns bogus data for the initial READ(10). */ -- cgit v1.2.3 From 2d64f31bdfbb2ea66cbd4271c079f11808c79c28 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 8 Jul 2015 14:03:41 +0200 Subject: usb-storage: Add ignore-device quirk for gm12u320 based usb mini projectors Grain-media GM12U320 based devices are mini video projectors using USB for both power and video data transport. Their usb-storage interface is a virtual windows driver CD. The gm12u320 kms driver needs these interfaces to talk to the device and export it as framebuffer & kms dri device nodes, so make sure that the usb-storage driver does not bind to it. Signed-off-by: Hans de Goede Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 87898ca2ed17..6b2479123de7 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -2086,6 +2086,17 @@ UNUSUAL_DEV( 0x1b1c, 0x1ab5, 0x0200, 0x0200, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_INITIAL_READ10 ), +/* Reported by Hans de Goede + * These are mini projectors using USB for both power and video data transport + * The usb-storage interface is a virtual windows driver CD, which the gm12u320 + * driver automatically converts into framebuffer & kms dri device nodes. + */ +UNUSUAL_DEV( 0x1de1, 0xc102, 0x0000, 0xffff, + "Grain-media Technology Corp.", + "USB3.0 Device GM12U320", + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_IGNORE_DEVICE ), + /* Patch by Richard Schütz * This external hard drive enclosure uses a JMicron chip which * needs the US_FL_IGNORE_RESIDUE flag to work properly. */ -- cgit v1.2.3 From 91b725600d8f27d759d211e36dda6182c6f93ec6 Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Wed, 8 Jul 2015 17:25:42 +0200 Subject: cdc-acm: Destroy acm_minors IDR on module exit Destroy acm_minors IDR on module exit, reclaiming the allocated memory. This was detected by the following semantic patch (written by Luis Rodriguez ) @ defines_module_init @ declarer name module_init, module_exit; declarer name DEFINE_IDR; identifier init; @@ module_init(init); @ defines_module_exit @ identifier exit; @@ module_exit(exit); @ declares_idr depends on defines_module_init && defines_module_exit @ identifier idr; @@ DEFINE_IDR(idr); @ on_exit_calls_destroy depends on declares_idr && defines_module_exit @ identifier declares_idr.idr, defines_module_exit.exit; @@ exit(void) { ... idr_destroy(&idr); ... } @ missing_module_idr_destroy depends on declares_idr && defines_module_exit && !on_exit_calls_destroy @ identifier declares_idr.idr, defines_module_exit.exit; @@ exit(void) { ... +idr_destroy(&idr); } Signed-off-by: Johannes Thumshirn Acked-by: Oliver Neukum Acked-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 519a77ba214c..b30e7423549b 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1944,6 +1944,7 @@ static void __exit acm_exit(void) usb_deregister(&acm_driver); tty_unregister_driver(acm_tty_driver); put_tty_driver(acm_tty_driver); + idr_destroy(&acm_minors); } module_init(acm_init); -- cgit v1.2.3 From 1209544d8a2a6084f58625ca66f5cd77580df53f Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 8 Jul 2015 12:14:56 -0400 Subject: USB: OHCI: fix bad #define in ohci-tmio.c An incorrect definition of CCR_PM_USBPW3 in ohci-tmio.c is a perennial source of invalid diagnoses from static scanners, such as in . This patch fixes the definition. Signed-off-by: Alan Stern Reported-by: David Binderman CC: Dmitry Eremin-Solenikov Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-tmio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/ohci-tmio.c b/drivers/usb/host/ohci-tmio.c index e9a6eec39142..cfcfadfc94fc 100644 --- a/drivers/usb/host/ohci-tmio.c +++ b/drivers/usb/host/ohci-tmio.c @@ -58,7 +58,7 @@ #define CCR_PM_CKRNEN 0x0002 #define CCR_PM_USBPW1 0x0004 #define CCR_PM_USBPW2 0x0008 -#define CCR_PM_USBPW3 0x0008 +#define CCR_PM_USBPW3 0x0010 #define CCR_PM_PMEE 0x0100 #define CCR_PM_PMES 0x8000 -- cgit v1.2.3 From 5f6c2d2b7dbb541c1e922538c49fa04c494ae3d7 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 22 Jul 2015 18:05:53 -0400 Subject: blkcg: fix gendisk reference leak in blkg_conf_prep() When a blkcg configuration is targeted to a partition rather than a whole device, blkg_conf_prep fails with -EINVAL; unfortunately, it forgets to put the gendisk ref in that case. Fix it. Signed-off-by: Tejun Heo Cc: stable@vger.kernel.org Signed-off-by: Jens Axboe --- block/blk-cgroup.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c index 9da02c021ebe..d6283b3f5db5 100644 --- a/block/blk-cgroup.c +++ b/block/blk-cgroup.c @@ -718,8 +718,12 @@ int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol, return -EINVAL; disk = get_gendisk(MKDEV(major, minor), &part); - if (!disk || part) + if (!disk) return -EINVAL; + if (part) { + put_disk(disk); + return -EINVAL; + } rcu_read_lock(); spin_lock_irq(disk->queue->queue_lock); -- cgit v1.2.3 From d3b178adb3a3adf54ecf77758138b654c3ee7f09 Mon Sep 17 00:00:00 2001 From: Goldwyn Rodrigues Date: Wed, 22 Jul 2015 12:09:17 -0500 Subject: md: Skip cluster setup for dm-raid There is a bug that the bitmap superblock isn't initialised properly for dm-raid, so a new field can have garbage in new fields. (dm-raid does initialisation in the kernel - md initialised the superblock in mdadm). This means that for dm-raid we cannot currently trust the new ->nodes field. So: - use __GFP_ZERO to initialise the superblock properly for all new arrays - initialise all fields in bitmap_info in bitmap_new_disk_sb - ignore ->nodes for dm arrays (yes, this is a hack) This bug exposes dm-raid to bug in the (still experimental) md-cluster code, so it is suitable for -stable. It does cause crashes. References: https://bugzilla.kernel.org/show_bug.cgi?id=100491 Cc: stable@vger.kernel.org (v4.1) Signed-off-By: Goldwyn Rodrigues Signed-off-by: NeilBrown --- drivers/md/bitmap.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 135a0907e9de..c90118e90708 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -494,7 +494,7 @@ static int bitmap_new_disk_sb(struct bitmap *bitmap) bitmap_super_t *sb; unsigned long chunksize, daemon_sleep, write_behind; - bitmap->storage.sb_page = alloc_page(GFP_KERNEL); + bitmap->storage.sb_page = alloc_page(GFP_KERNEL | __GFP_ZERO); if (bitmap->storage.sb_page == NULL) return -ENOMEM; bitmap->storage.sb_page->index = 0; @@ -541,6 +541,7 @@ static int bitmap_new_disk_sb(struct bitmap *bitmap) sb->state = cpu_to_le32(bitmap->flags); bitmap->events_cleared = bitmap->mddev->events; sb->events_cleared = cpu_to_le64(bitmap->mddev->events); + bitmap->mddev->bitmap_info.nodes = 0; kunmap_atomic(sb); @@ -611,8 +612,16 @@ re_read: daemon_sleep = le32_to_cpu(sb->daemon_sleep) * HZ; write_behind = le32_to_cpu(sb->write_behind); sectors_reserved = le32_to_cpu(sb->sectors_reserved); - nodes = le32_to_cpu(sb->nodes); - strlcpy(bitmap->mddev->bitmap_info.cluster_name, sb->cluster_name, 64); + /* XXX: This is a hack to ensure that we don't use clustering + * in case: + * - dm-raid is in use and + * - the nodes written in bitmap_sb is erroneous. + */ + if (!bitmap->mddev->sync_super) { + nodes = le32_to_cpu(sb->nodes); + strlcpy(bitmap->mddev->bitmap_info.cluster_name, + sb->cluster_name, 64); + } /* verify that the bitmap-specific fields are valid */ if (sb->magic != cpu_to_le32(BITMAP_MAGIC)) -- cgit v1.2.3 From f2d0a123bcf16d1a9cf7942ddc98e0ef77862c2b Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Fri, 17 Jul 2015 14:15:30 -0500 Subject: mnt: Clarify and correct the disconnect logic in umount_tree rmdir mntpoint will result in an infinite loop when there is a mount locked on the mountpoint in another mount namespace. This is because the logic to test to see if a mount should be disconnected in umount_tree is buggy. Move the logic to decide if a mount should remain connected to it's mountpoint into it's own function disconnect_mount so that clarity of expression instead of terseness of expression becomes a virtue. When the conditions where it is invalid to leave a mount connected are first ruled out, the logic for deciding if a mount should be disconnected becomes much clearer and simpler. Fixes: e0c9c0afd2fc958ffa34b697972721d81df8a56f mnt: Update detach_mounts to leave mounts connected Fixes: ce07d891a0891d3c0d0c2d73d577490486b809e1 mnt: Honor MNT_LOCKED when detaching mounts Cc: stable@vger.kernel.org Signed-off-by: "Eric W. Biederman" --- fs/namespace.c | 35 +++++++++++++++++++++++++++++++---- fs/pnode.h | 2 -- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/fs/namespace.c b/fs/namespace.c index c7cb8a526c05..7829eab0b706 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -1361,6 +1361,36 @@ enum umount_tree_flags { UMOUNT_PROPAGATE = 2, UMOUNT_CONNECTED = 4, }; + +static bool disconnect_mount(struct mount *mnt, enum umount_tree_flags how) +{ + /* Leaving mounts connected is only valid for lazy umounts */ + if (how & UMOUNT_SYNC) + return true; + + /* A mount without a parent has nothing to be connected to */ + if (!mnt_has_parent(mnt)) + return true; + + /* Because the reference counting rules change when mounts are + * unmounted and connected, umounted mounts may not be + * connected to mounted mounts. + */ + if (!(mnt->mnt_parent->mnt.mnt_flags & MNT_UMOUNT)) + return true; + + /* Has it been requested that the mount remain connected? */ + if (how & UMOUNT_CONNECTED) + return false; + + /* Is the mount locked such that it needs to remain connected? */ + if (IS_MNT_LOCKED(mnt)) + return false; + + /* By default disconnect the mount */ + return true; +} + /* * mount_lock must be held * namespace_sem must be held for write @@ -1398,10 +1428,7 @@ static void umount_tree(struct mount *mnt, enum umount_tree_flags how) if (how & UMOUNT_SYNC) p->mnt.mnt_flags |= MNT_SYNC_UMOUNT; - disconnect = !(((how & UMOUNT_CONNECTED) && - mnt_has_parent(p) && - (p->mnt_parent->mnt.mnt_flags & MNT_UMOUNT)) || - IS_MNT_LOCKED_AND_LAZY(p)); + disconnect = disconnect_mount(p, how); pin_insert_group(&p->mnt_umount, &p->mnt_parent->mnt, disconnect ? &unmounted : NULL); diff --git a/fs/pnode.h b/fs/pnode.h index 7114ce6e6b9e..0fcdbe7ca648 100644 --- a/fs/pnode.h +++ b/fs/pnode.h @@ -20,8 +20,6 @@ #define SET_MNT_MARK(m) ((m)->mnt.mnt_flags |= MNT_MARKED) #define CLEAR_MNT_MARK(m) ((m)->mnt.mnt_flags &= ~MNT_MARKED) #define IS_MNT_LOCKED(m) ((m)->mnt.mnt_flags & MNT_LOCKED) -#define IS_MNT_LOCKED_AND_LAZY(m) \ - (((m)->mnt.mnt_flags & (MNT_LOCKED|MNT_SYNC_UMOUNT)) == MNT_LOCKED) #define CL_EXPIRE 0x01 #define CL_SLAVE 0x02 -- cgit v1.2.3 From cabea695875e3a07313c205a9753c7416126dfa2 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Mon, 15 Jun 2015 20:05:49 +0530 Subject: parport: fix error handling After registering the device if exclusive access fails for any reason then we need to unregister the device to remove all references. Signed-off-by: Sudip Mukherjee Signed-off-by: Greg Kroah-Hartman --- drivers/parport/share.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/parport/share.c b/drivers/parport/share.c index 8067f54ce050..d8079e37a606 100644 --- a/drivers/parport/share.c +++ b/drivers/parport/share.c @@ -907,7 +907,8 @@ parport_register_dev_model(struct parport *port, const char *name, spin_unlock(&port->physport->pardevice_lock); pr_debug("%s: cannot grant exclusive access for device %s\n", port->name, name); - goto err_put_dev; + device_unregister(&par_dev->dev); + goto err_put_port; } port->flags |= PARPORT_FLAG_EXCL; } -- cgit v1.2.3 From 23c405912b881e3ca516554efde852c2ad550b31 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Mon, 15 Jun 2015 20:05:50 +0530 Subject: parport: fix memory leak After the reference count becomes 0 when put_device() is called, it will execute the release callback where we are freeing all the allocated memory associated with the device. We missed freeing par_dev->state. Signed-off-by: Sudip Mukherjee Signed-off-by: Greg Kroah-Hartman --- drivers/parport/share.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/parport/share.c b/drivers/parport/share.c index d8079e37a606..1efec44e03aa 100644 --- a/drivers/parport/share.c +++ b/drivers/parport/share.c @@ -816,6 +816,7 @@ static void free_pardevice(struct device *dev) struct pardevice *par_dev = to_pardevice(dev); kfree(par_dev->name); + kfree(par_dev->state); kfree(par_dev); } -- cgit v1.2.3 From 68d35c7b3b1aa686e3039eb2626bf5e3ea8dbe81 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Mon, 15 Jun 2015 20:05:51 +0530 Subject: parport: fix freeing freed memory After the reference count becomes 0 when put_device() is called, it will execute the release callback where we are freeing all the allocated memory associated with the device. So if we just continue on the error path then we are again freeing devname and trying to dereference par_dev which has already been free-ed in the release callback. Signed-off-by: Sudip Mukherjee Signed-off-by: Greg Kroah-Hartman --- drivers/parport/share.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/parport/share.c b/drivers/parport/share.c index 1efec44e03aa..c02b5f27798b 100644 --- a/drivers/parport/share.c +++ b/drivers/parport/share.c @@ -892,8 +892,10 @@ parport_register_dev_model(struct parport *port, const char *name, par_dev->dev.release = free_pardevice; par_dev->devmodel = true; ret = device_register(&par_dev->dev); - if (ret) - goto err_put_dev; + if (ret) { + put_device(&par_dev->dev); + goto err_put_port; + } /* Chain this onto the list */ par_dev->prev = NULL; @@ -940,8 +942,6 @@ parport_register_dev_model(struct parport *port, const char *name, return par_dev; -err_put_dev: - put_device(&par_dev->dev); err_free_devname: kfree(devname); err_free_par_dev: -- cgit v1.2.3 From a63444375f08a18a6b2286351606f08d6e9fa63d Mon Sep 17 00:00:00 2001 From: Sudeep Dutt Date: Wed, 22 Jul 2015 11:50:10 -0700 Subject: misc: mic: scif bug fix for vmalloc_to_page crash v4.2-rc1 enabled huge page support for ioremap(..). Calling vmalloc_to_page after v4.2-rc1 results in the crash shown below on the host upon booting X100 coprocessors: BUG: unable to handle kernel paging request at ffffc47c00000000 IP: [] vmalloc_to_page+0x6c/0xb0 This patch fixes this crash by obtaining the fake struct page pointer which is required to be passed into dma_map_sg(..) by calling pfn_to_page(..) instead of vmalloc_to_page(..). Link: https://lkml.org/lkml/2015/7/18/110 Reviewed-by: Nikhil Rao Suggested-by: Toshi Kani Signed-off-by: Ashutosh Dixit Signed-off-by: Sudeep Dutt Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mic/scif/scif_nodeqp.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/drivers/misc/mic/scif/scif_nodeqp.c b/drivers/misc/mic/scif/scif_nodeqp.c index 41e3bdb10061..6dfdae3452d6 100644 --- a/drivers/misc/mic/scif/scif_nodeqp.c +++ b/drivers/misc/mic/scif/scif_nodeqp.c @@ -357,7 +357,7 @@ static void scif_p2p_freesg(struct scatterlist *sg) } static struct scatterlist * -scif_p2p_setsg(void __iomem *va, int page_size, int page_cnt) +scif_p2p_setsg(phys_addr_t pa, int page_size, int page_cnt) { struct scatterlist *sg; struct page *page; @@ -368,16 +368,11 @@ scif_p2p_setsg(void __iomem *va, int page_size, int page_cnt) return NULL; sg_init_table(sg, page_cnt); for (i = 0; i < page_cnt; i++) { - page = vmalloc_to_page((void __force *)va); - if (!page) - goto p2p_sg_err; + page = pfn_to_page(pa >> PAGE_SHIFT); sg_set_page(&sg[i], page, page_size, 0); - va += page_size; + pa += page_size; } return sg; -p2p_sg_err: - kfree(sg); - return NULL; } /* Init p2p mappings required to access peerdev from scifdev */ @@ -395,14 +390,14 @@ scif_init_p2p_info(struct scif_dev *scifdev, struct scif_dev *peerdev) p2p = kzalloc(sizeof(*p2p), GFP_KERNEL); if (!p2p) return NULL; - p2p->ppi_sg[SCIF_PPI_MMIO] = scif_p2p_setsg(psdev->mmio->va, + p2p->ppi_sg[SCIF_PPI_MMIO] = scif_p2p_setsg(psdev->mmio->pa, PAGE_SIZE, num_mmio_pages); if (!p2p->ppi_sg[SCIF_PPI_MMIO]) goto free_p2p; p2p->sg_nentries[SCIF_PPI_MMIO] = num_mmio_pages; sg_page_shift = get_order(min(psdev->aper->len, (u64)(1 << 30))); num_aper_chunks = num_aper_pages >> (sg_page_shift - PAGE_SHIFT); - p2p->ppi_sg[SCIF_PPI_APER] = scif_p2p_setsg(psdev->aper->va, + p2p->ppi_sg[SCIF_PPI_APER] = scif_p2p_setsg(psdev->aper->pa, 1 << sg_page_shift, num_aper_chunks); p2p->sg_nentries[SCIF_PPI_APER] = num_aper_chunks; -- cgit v1.2.3 From 154322f47376fed6ab1e4b350aa45fffa15a61aa Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Thu, 18 Jun 2015 11:41:03 +0300 Subject: mei: prevent unloading mei hw modules while the device is opened. chrdev_open() increases reference counter on cdev->owner. Instead of assigning the owner to mei subsystem, the owner has to be set to the underlaying HW module (mei_me or mei_txe), so once the device is opened the HW module cannot be unloaded. Cc: #3.17+ Signed-off-by: Tomas Winkler Signed-off-by: Alexander Usyskin Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index 8eb0a9500a90..e9513d651cd3 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -682,7 +682,7 @@ int mei_register(struct mei_device *dev, struct device *parent) /* Fill in the data structures */ devno = MKDEV(MAJOR(mei_devt), dev->minor); cdev_init(&dev->cdev, &mei_fops); - dev->cdev.owner = mei_fops.owner; + dev->cdev.owner = parent->driver->owner; /* Add the device */ ret = cdev_add(&dev->cdev, devno, 1); -- cgit v1.2.3 From 10dc331ff5e7e4668c0f0c95b1a873aba9b70826 Mon Sep 17 00:00:00 2001 From: Xiao Guangrong Date: Thu, 16 Jul 2015 03:25:54 +0800 Subject: KVM: MTRR: fix memory type handling if MTRR is completely disabled Currently code uses default memory type if MTRR is fully disabled, fix it by using UC instead. Signed-off-by: Xiao Guangrong Tested-by: Alex Williamson Signed-off-by: Paolo Bonzini --- arch/x86/kvm/mtrr.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/mtrr.c b/arch/x86/kvm/mtrr.c index de1d2d8062e2..e2750134a22b 100644 --- a/arch/x86/kvm/mtrr.c +++ b/arch/x86/kvm/mtrr.c @@ -120,6 +120,16 @@ static u8 mtrr_default_type(struct kvm_mtrr *mtrr_state) return mtrr_state->deftype & IA32_MTRR_DEF_TYPE_TYPE_MASK; } +static u8 mtrr_disabled_type(void) +{ + /* + * Intel SDM 11.11.2.2: all MTRRs are disabled when + * IA32_MTRR_DEF_TYPE.E bit is cleared, and the UC + * memory type is applied to all of physical memory. + */ + return MTRR_TYPE_UNCACHABLE; +} + /* * Three terms are used in the following code: * - segment, it indicates the address segments covered by fixed MTRRs. @@ -434,6 +444,8 @@ struct mtrr_iter { /* output fields. */ int mem_type; + /* mtrr is completely disabled? */ + bool mtrr_disabled; /* [start, end) is not fully covered in MTRRs? */ bool partial_map; @@ -549,7 +561,7 @@ static void mtrr_lookup_var_next(struct mtrr_iter *iter) static void mtrr_lookup_start(struct mtrr_iter *iter) { if (!mtrr_is_enabled(iter->mtrr_state)) { - iter->partial_map = true; + iter->mtrr_disabled = true; return; } @@ -563,6 +575,7 @@ static void mtrr_lookup_init(struct mtrr_iter *iter, iter->mtrr_state = mtrr_state; iter->start = start; iter->end = end; + iter->mtrr_disabled = false; iter->partial_map = false; iter->fixed = false; iter->range = NULL; @@ -656,6 +669,9 @@ u8 kvm_mtrr_get_guest_memory_type(struct kvm_vcpu *vcpu, gfn_t gfn) return MTRR_TYPE_WRBACK; } + if (iter.mtrr_disabled) + return mtrr_disabled_type(); + /* It is not covered by MTRRs. */ if (iter.partial_map) { /* @@ -689,6 +705,9 @@ bool kvm_mtrr_check_gfn_range_consistency(struct kvm_vcpu *vcpu, gfn_t gfn, return false; } + if (iter.mtrr_disabled) + return true; + if (!iter.partial_map) return true; -- cgit v1.2.3 From 3e5d2fdceda172554e681b68c853bf5d08205bbf Mon Sep 17 00:00:00 2001 From: Xiao Guangrong Date: Thu, 16 Jul 2015 03:25:55 +0800 Subject: KVM: MTRR: simplify kvm_mtrr_get_guest_memory_type kvm_mtrr_get_guest_memory_type never returns -1 which is implied in the current code since if @type = -1 (means no MTRR contains the range), iter.partial_map must be true Simplify the code to indicate this fact Signed-off-by: Xiao Guangrong Tested-by: Alex Williamson Signed-off-by: Paolo Bonzini --- arch/x86/kvm/mtrr.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/arch/x86/kvm/mtrr.c b/arch/x86/kvm/mtrr.c index e2750134a22b..dc0a84a6f309 100644 --- a/arch/x86/kvm/mtrr.c +++ b/arch/x86/kvm/mtrr.c @@ -672,15 +672,16 @@ u8 kvm_mtrr_get_guest_memory_type(struct kvm_vcpu *vcpu, gfn_t gfn) if (iter.mtrr_disabled) return mtrr_disabled_type(); - /* It is not covered by MTRRs. */ - if (iter.partial_map) { - /* - * We just check one page, partially covered by MTRRs is - * impossible. - */ - WARN_ON(type != -1); - type = mtrr_default_type(mtrr_state); - } + /* + * We just check one page, partially covered by MTRRs is + * impossible. + */ + WARN_ON(iter.partial_map); + + /* not contained in any MTRRs. */ + if (type == -1) + return mtrr_default_type(mtrr_state); + return type; } EXPORT_SYMBOL_GPL(kvm_mtrr_get_guest_memory_type); -- cgit v1.2.3 From 41dbc6bcd9722bba8f09256655d060af30c63d34 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 23 Jul 2015 08:22:45 +0200 Subject: KVM: x86: introduce kvm_check_has_quirk The logic of the disabled_quirks field usually results in a double negation. Wrap it in a simple function that checks the bit and negates it. Based on a patch from Xiao Guangrong. Signed-off-by: Paolo Bonzini --- arch/x86/kvm/lapic.c | 2 +- arch/x86/kvm/svm.c | 2 +- arch/x86/kvm/x86.h | 5 +++++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 954e98a8c2e3..1c425443a41a 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -1595,7 +1595,7 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu, bool init_event) for (i = 0; i < APIC_LVT_NUM; i++) apic_set_reg(apic, APIC_LVTT + 0x10 * i, APIC_LVT_MASKED); apic_update_lvtt(apic); - if (!(vcpu->kvm->arch.disabled_quirks & KVM_QUIRK_LINT0_REENABLED)) + if (kvm_check_has_quirk(vcpu->kvm, KVM_QUIRK_LINT0_REENABLED)) apic_set_reg(apic, APIC_LVT0, SET_APIC_DELIVERY_MODE(0, APIC_MODE_EXTINT)); apic_manage_nmi_watchdog(apic, kvm_apic_get_reg(apic, APIC_LVT0)); diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index bbc678a66b18..8cbec765b08d 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -1672,7 +1672,7 @@ static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) * does not do it - this results in some delay at * reboot */ - if (!(vcpu->kvm->arch.disabled_quirks & KVM_QUIRK_CD_NW_CLEARED)) + if (kvm_check_has_quirk(vcpu->kvm, KVM_QUIRK_CD_NW_CLEARED)) cr0 &= ~(X86_CR0_CD | X86_CR0_NW); svm->vmcb->save.cr0 = cr0; mark_dirty(svm->vmcb, VMCB_CR); diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h index edc8cdcd786b..0ca2f3e4803c 100644 --- a/arch/x86/kvm/x86.h +++ b/arch/x86/kvm/x86.h @@ -147,6 +147,11 @@ static inline void kvm_register_writel(struct kvm_vcpu *vcpu, return kvm_register_write(vcpu, reg, val); } +static inline bool kvm_check_has_quirk(struct kvm *kvm, u64 quirk) +{ + return !(kvm->arch.disabled_quirks & quirk); +} + void kvm_before_handle_nmi(struct kvm_vcpu *vcpu); void kvm_after_handle_nmi(struct kvm_vcpu *vcpu); void kvm_set_pending_timer(struct kvm_vcpu *vcpu); -- cgit v1.2.3 From fb279950ba02e3210a16b11ecfa8871f3ee0ca49 Mon Sep 17 00:00:00 2001 From: Xiao Guangrong Date: Thu, 16 Jul 2015 03:25:56 +0800 Subject: KVM: vmx: obey KVM_QUIRK_CD_NW_CLEARED OVMF depends on WB to boot fast, because it only clears caches after it has set up MTRRs---which is too late. Let's do writeback if CR0.CD is set to make it happy, similar to what SVM is already doing. Signed-off-by: Xiao Guangrong Tested-by: Alex Williamson Signed-off-by: Paolo Bonzini --- arch/x86/kvm/vmx.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 5b4e9384717a..e9e1fc517ab5 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -8650,7 +8650,10 @@ static u64 vmx_get_mt_mask(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio) if (kvm_read_cr0(vcpu) & X86_CR0_CD) { ipat = VMX_EPT_IPAT_BIT; - cache = MTRR_TYPE_UNCACHABLE; + if (kvm_check_has_quirk(vcpu->kvm, KVM_QUIRK_CD_NW_CLEARED)) + cache = MTRR_TYPE_WRBACK; + else + cache = MTRR_TYPE_UNCACHABLE; goto exit; } -- cgit v1.2.3 From 0da029ed7ee5fdf49a2a0e14160c3e9999be9292 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 23 Jul 2015 08:24:42 +0200 Subject: KVM: x86: rename quirk constants to KVM_X86_QUIRK_* Make them clearly architecture-dependent; the capability is valid for all architectures, but the argument is not. Signed-off-by: Paolo Bonzini --- arch/x86/include/uapi/asm/kvm.h | 4 ++-- arch/x86/kvm/lapic.c | 2 +- arch/x86/kvm/svm.c | 2 +- arch/x86/kvm/vmx.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/x86/include/uapi/asm/kvm.h b/arch/x86/include/uapi/asm/kvm.h index a4ae82eb82aa..cd54147cb365 100644 --- a/arch/x86/include/uapi/asm/kvm.h +++ b/arch/x86/include/uapi/asm/kvm.h @@ -354,7 +354,7 @@ struct kvm_xcrs { struct kvm_sync_regs { }; -#define KVM_QUIRK_LINT0_REENABLED (1 << 0) -#define KVM_QUIRK_CD_NW_CLEARED (1 << 1) +#define KVM_X86_QUIRK_LINT0_REENABLED (1 << 0) +#define KVM_X86_QUIRK_CD_NW_CLEARED (1 << 1) #endif /* _ASM_X86_KVM_H */ diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 1c425443a41a..2a5ca97c263b 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -1595,7 +1595,7 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu, bool init_event) for (i = 0; i < APIC_LVT_NUM; i++) apic_set_reg(apic, APIC_LVTT + 0x10 * i, APIC_LVT_MASKED); apic_update_lvtt(apic); - if (kvm_check_has_quirk(vcpu->kvm, KVM_QUIRK_LINT0_REENABLED)) + if (kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_LINT0_REENABLED)) apic_set_reg(apic, APIC_LVT0, SET_APIC_DELIVERY_MODE(0, APIC_MODE_EXTINT)); apic_manage_nmi_watchdog(apic, kvm_apic_get_reg(apic, APIC_LVT0)); diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 8cbec765b08d..8e0c0844c6b9 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -1672,7 +1672,7 @@ static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) * does not do it - this results in some delay at * reboot */ - if (kvm_check_has_quirk(vcpu->kvm, KVM_QUIRK_CD_NW_CLEARED)) + if (kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_CD_NW_CLEARED)) cr0 &= ~(X86_CR0_CD | X86_CR0_NW); svm->vmcb->save.cr0 = cr0; mark_dirty(svm->vmcb, VMCB_CR); diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index e9e1fc517ab5..83b7b5cd75d5 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -8650,7 +8650,7 @@ static u64 vmx_get_mt_mask(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio) if (kvm_read_cr0(vcpu) & X86_CR0_CD) { ipat = VMX_EPT_IPAT_BIT; - if (kvm_check_has_quirk(vcpu->kvm, KVM_QUIRK_CD_NW_CLEARED)) + if (kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_CD_NW_CLEARED)) cache = MTRR_TYPE_WRBACK; else cache = MTRR_TYPE_UNCACHABLE; -- cgit v1.2.3 From 46ebb7af7b93792de65e124e1ab8b89a108a41f2 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Tue, 14 Jul 2015 14:48:53 -0600 Subject: iommu/vt-d: Fix VM domain ID leak This continues the attempt to fix commit fb170fb4c548 ("iommu/vt-d: Introduce helper functions to make code symmetric for readability"). The previous attempt in commit 71684406905f ("iommu/vt-d: Detach domain *only* from attached iommus") overlooked the fact that dmar_domain.iommu_bmp gets cleared for VM domains when devices are detached: intel_iommu_detach_device domain_remove_one_dev_info domain_detach_iommu The domain is detached from the iommu, but the iommu is still attached to the domain, for whatever reason. Thus when we get to domain_exit(), we can't rely on iommu_bmp for VM domains to find the active iommus, we must check them all. Without that, the corresponding bit in intel_iommu.domain_ids doesn't get cleared and repeated VM domain creation and destruction will run out of domain IDs. Meanwhile we still can't call iommu_detach_domain() on arbitrary non-VM domains or we risk clearing in-use domain IDs, as 71684406905f attempted to address. It's tempting to modify iommu_detach_domain() to test the domain iommu_bmp, but the call ordering from domain_remove_one_dev_info() prevents it being able to work as fb170fb4c548 seems to have intended. Caching of unused VM domains on the iommu object seems to be the root of the problem, but this code is far too fragile for that kind of rework to be proposed for stable, so we simply revert this chunk to its state prior to fb170fb4c548. Fixes: fb170fb4c548 ("iommu/vt-d: Introduce helper functions to make code symmetric for readability") Fixes: 71684406905f ("iommu/vt-d: Detach domain *only* from attached iommus") Signed-off-by: Alex Williamson Cc: Jiang Liu Cc: stable@vger.kernel.org # v3.17+ Signed-off-by: Joerg Roedel --- drivers/iommu/intel-iommu.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index a98a7b27aca1..0649b94f5958 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -1830,8 +1830,9 @@ static int domain_init(struct dmar_domain *domain, int guest_width) static void domain_exit(struct dmar_domain *domain) { + struct dmar_drhd_unit *drhd; + struct intel_iommu *iommu; struct page *freelist = NULL; - int i; /* Domain 0 is reserved, so dont process it */ if (!domain) @@ -1851,8 +1852,10 @@ static void domain_exit(struct dmar_domain *domain) /* clear attached or cached domains */ rcu_read_lock(); - for_each_set_bit(i, domain->iommu_bmp, g_num_of_iommus) - iommu_detach_domain(domain, g_iommus[i]); + for_each_active_iommu(iommu, drhd) + if (domain_type_is_vm(domain) || + test_bit(iommu->seq_id, domain->iommu_bmp)) + iommu_detach_domain(domain, iommu); rcu_read_unlock(); dma_free_pagelist(freelist); -- cgit v1.2.3 From d84b272a12a6aa96897372449e47e57f72f2730f Mon Sep 17 00:00:00 2001 From: Michel Dänzer Date: Thu, 16 Jul 2015 10:45:10 +0900 Subject: drm/amdgpu/dce11: Re-set VBLANK interrupt state when enabling a CRTC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Something (ATOM BIOS?) seems to be clobbering the LB_INTERRUPT_MASK register while the CRTC is off, which caused e.g. glxgears or gnome-shell to hang after a modeset. Reviewed-and-Tested-by: Alex Deucher Tested-by: Sonny Jiang Signed-off-by: Michel Dänzer --- drivers/gpu/drm/amd/amdgpu/dce_v11_0.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c index 7f7abb0e0be5..dcb402ee048a 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c @@ -2631,6 +2631,7 @@ static void dce_v11_0_crtc_dpms(struct drm_crtc *crtc, int mode) struct drm_device *dev = crtc->dev; struct amdgpu_device *adev = dev->dev_private; struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); + unsigned type; switch (mode) { case DRM_MODE_DPMS_ON: @@ -2639,6 +2640,9 @@ static void dce_v11_0_crtc_dpms(struct drm_crtc *crtc, int mode) dce_v11_0_vga_enable(crtc, true); amdgpu_atombios_crtc_blank(crtc, ATOM_DISABLE); dce_v11_0_vga_enable(crtc, false); + /* Make sure VBLANK interrupt is still enabled */ + type = amdgpu_crtc_idx_to_irq_type(adev, amdgpu_crtc->crtc_id); + amdgpu_irq_update(adev, &adev->crtc_irq, type); drm_vblank_post_modeset(dev, amdgpu_crtc->crtc_id); dce_v11_0_crtc_load_lut(crtc); break; -- cgit v1.2.3 From 5e6775abb5ce7ada76fa17c67857576176d0b60f Mon Sep 17 00:00:00 2001 From: Michel Dänzer Date: Fri, 17 Jul 2015 11:20:18 +0900 Subject: drm/amdgpu/dce10: Re-set VBLANK interrupt state when enabling a CRTC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This doesn't seem strictly necessary with Tonga right now, but that might change with future power management enhancements. Reviewed-by: Alex Deucher Signed-off-by: Michel Dänzer --- drivers/gpu/drm/amd/amdgpu/dce_v10_0.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c index 6e77964f1b64..e70a26f587a0 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c @@ -2632,6 +2632,7 @@ static void dce_v10_0_crtc_dpms(struct drm_crtc *crtc, int mode) struct drm_device *dev = crtc->dev; struct amdgpu_device *adev = dev->dev_private; struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); + unsigned type; switch (mode) { case DRM_MODE_DPMS_ON: @@ -2640,6 +2641,9 @@ static void dce_v10_0_crtc_dpms(struct drm_crtc *crtc, int mode) dce_v10_0_vga_enable(crtc, true); amdgpu_atombios_crtc_blank(crtc, ATOM_DISABLE); dce_v10_0_vga_enable(crtc, false); + /* Make sure VBLANK interrupt is still enabled */ + type = amdgpu_crtc_idx_to_irq_type(adev, amdgpu_crtc->crtc_id); + amdgpu_irq_update(adev, &adev->crtc_irq, type); drm_vblank_post_modeset(dev, amdgpu_crtc->crtc_id); dce_v10_0_crtc_load_lut(crtc); break; -- cgit v1.2.3 From 6a585777c832f45c05d1aa8a4872b2b292a908c2 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 10 Jul 2015 14:16:24 -0400 Subject: drm/amdgpu: implement VCE 3.0 harvesting support (v4) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For boards with bad VCE blocks, only configure the working block. v2: use the harvest info for pipe setup v3: fix mask check as noted by Leo v4: add dGPU support Reviewed-by: Christian König (v2) Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 4 +++ drivers/gpu/drm/amd/amdgpu/vce_v3_0.c | 48 +++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 01657830b470..e9fde72cf038 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -1614,6 +1614,9 @@ struct amdgpu_uvd { #define AMDGPU_MAX_VCE_HANDLES 16 #define AMDGPU_VCE_FIRMWARE_OFFSET 256 +#define AMDGPU_VCE_HARVEST_VCE0 (1 << 0) +#define AMDGPU_VCE_HARVEST_VCE1 (1 << 1) + struct amdgpu_vce { struct amdgpu_bo *vcpu_bo; uint64_t gpu_addr; @@ -1626,6 +1629,7 @@ struct amdgpu_vce { const struct firmware *fw; /* VCE firmware */ struct amdgpu_ring ring[AMDGPU_MAX_VCE_RINGS]; struct amdgpu_irq_src irq; + unsigned harvest_config; }; /* diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c index d62c4002e39c..d1064ca3670e 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c @@ -35,6 +35,8 @@ #include "oss/oss_2_0_d.h" #include "oss/oss_2_0_sh_mask.h" #include "gca/gfx_8_0_d.h" +#include "smu/smu_7_1_2_d.h" +#include "smu/smu_7_1_2_sh_mask.h" #define GRBM_GFX_INDEX__VCE_INSTANCE__SHIFT 0x04 #define GRBM_GFX_INDEX__VCE_INSTANCE_MASK 0x10 @@ -112,6 +114,10 @@ static int vce_v3_0_start(struct amdgpu_device *adev) mutex_lock(&adev->grbm_idx_mutex); for (idx = 0; idx < 2; ++idx) { + + if (adev->vce.harvest_config & (1 << idx)) + continue; + if(idx == 0) WREG32_P(mmGRBM_GFX_INDEX, 0, ~GRBM_GFX_INDEX__VCE_INSTANCE_MASK); @@ -190,10 +196,52 @@ static int vce_v3_0_start(struct amdgpu_device *adev) return 0; } +#define ixVCE_HARVEST_FUSE_MACRO__ADDRESS 0xC0014074 +#define VCE_HARVEST_FUSE_MACRO__SHIFT 27 +#define VCE_HARVEST_FUSE_MACRO__MASK 0x18000000 + +static unsigned vce_v3_0_get_harvest_config(struct amdgpu_device *adev) +{ + u32 tmp; + unsigned ret; + + if (adev->flags & AMDGPU_IS_APU) + tmp = (RREG32_SMC(ixVCE_HARVEST_FUSE_MACRO__ADDRESS) & + VCE_HARVEST_FUSE_MACRO__MASK) >> + VCE_HARVEST_FUSE_MACRO__SHIFT; + else + tmp = (RREG32_SMC(ixCC_HARVEST_FUSES) & + CC_HARVEST_FUSES__VCE_DISABLE_MASK) >> + CC_HARVEST_FUSES__VCE_DISABLE__SHIFT; + + switch (tmp) { + case 1: + ret = AMDGPU_VCE_HARVEST_VCE0; + break; + case 2: + ret = AMDGPU_VCE_HARVEST_VCE1; + break; + case 3: + ret = AMDGPU_VCE_HARVEST_VCE0 | AMDGPU_VCE_HARVEST_VCE1; + break; + default: + ret = 0; + } + + return ret; +} + static int vce_v3_0_early_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; + adev->vce.harvest_config = vce_v3_0_get_harvest_config(adev); + + if ((adev->vce.harvest_config & + (AMDGPU_VCE_HARVEST_VCE0 | AMDGPU_VCE_HARVEST_VCE1)) == + (AMDGPU_VCE_HARVEST_VCE0 | AMDGPU_VCE_HARVEST_VCE1)) + return -ENOENT; + vce_v3_0_set_ring_funcs(adev); vce_v3_0_set_irq_funcs(adev); -- cgit v1.2.3 From fa92754e9c47cf3e5607c0865f4cf59d090cda37 Mon Sep 17 00:00:00 2001 From: Leo Liu Date: Mon, 13 Jul 2015 12:46:23 -0400 Subject: drm/amdgpu: add VCE harvesting instance query MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Leo Liu Reviewed-by: Alex Deucher Reviewed-by: Christian König --- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 1 + include/uapi/drm/amdgpu_drm.h | 2 ++ 2 files changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index 5533434c7a8f..31ad444c6386 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -459,6 +459,7 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file memcpy(&dev_info.cu_bitmap[0], &cu_info.bitmap[0], sizeof(cu_info.bitmap)); dev_info.vram_type = adev->mc.vram_type; dev_info.vram_bit_width = adev->mc.vram_width; + dev_info.vce_harvest_config = adev->vce.harvest_config; return copy_to_user(out, &dev_info, min((size_t)size, sizeof(dev_info))) ? -EFAULT : 0; diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h index b6fce900a833..d708a53b8fb1 100644 --- a/include/uapi/drm/amdgpu_drm.h +++ b/include/uapi/drm/amdgpu_drm.h @@ -614,6 +614,8 @@ struct drm_amdgpu_info_device { uint32_t vram_type; /** video memory bit width*/ uint32_t vram_bit_width; + /* vce harvesting instance */ + uint32_t vce_harvest_config; }; struct drm_amdgpu_info_hw_ip { -- cgit v1.2.3 From fe78fcc85a2046c51f1535710996860557eeec20 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Fri, 17 Jul 2015 14:54:27 -0500 Subject: mnt: In detach_mounts detach the appropriate unmounted mount The handling of in detach_mounts of unmounted but connected mounts is buggy and can lead to an infinite loop. Correct the handling of unmounted mounts in detach_mount. When the mountpoint of an unmounted but connected mount is connected to a dentry, and that dentry is deleted we need to disconnect that mount from the parent mount and the deleted dentry. Nothing changes for the unmounted and connected children. They can be safely ignored. Cc: stable@vger.kernel.org Fixes: ce07d891a0891d3c0d0c2d73d577490486b809e1 mnt: Honor MNT_LOCKED when detaching mounts Signed-off-by: "Eric W. Biederman" --- fs/namespace.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/fs/namespace.c b/fs/namespace.c index 7829eab0b706..2b8aa15fd6df 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -1565,11 +1565,8 @@ void __detach_mounts(struct dentry *dentry) while (!hlist_empty(&mp->m_list)) { mnt = hlist_entry(mp->m_list.first, struct mount, mnt_mp_list); if (mnt->mnt.mnt_flags & MNT_UMOUNT) { - struct mount *p, *tmp; - list_for_each_entry_safe(p, tmp, &mnt->mnt_mounts, mnt_child) { - hlist_add_head(&p->mnt_umount.s_list, &unmounted); - umount_mnt(p); - } + hlist_add_head(&mnt->mnt_umount.s_list, &unmounted); + umount_mnt(mnt); } else umount_tree(mnt, UMOUNT_CONNECTED); } -- cgit v1.2.3 From 3f81d2447b37ac697b3c600039f2c6b628c06e21 Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Thu, 23 Jul 2015 14:11:09 -0400 Subject: tile: use free_bootmem_late() for initrd We were previously using free_bootmem() and just getting lucky that nothing too bad happened. Signed-off-by: Chris Metcalf Cc: stable@vger.kernel.org --- arch/tile/kernel/setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/tile/kernel/setup.c b/arch/tile/kernel/setup.c index 99c9ff87e018..6b755d125783 100644 --- a/arch/tile/kernel/setup.c +++ b/arch/tile/kernel/setup.c @@ -1139,7 +1139,7 @@ static void __init load_hv_initrd(void) void __init free_initrd_mem(unsigned long begin, unsigned long end) { - free_bootmem(__pa(begin), end - begin); + free_bootmem_late(__pa(begin), end - begin); } static int __init setup_initrd(char *str) -- cgit v1.2.3 From f2d52cd4db08db06200176cfebead9778878d4fc Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 14 Jul 2015 16:16:29 -0400 Subject: drm/amdgpu/cz: implement voltage validation properly CZ uses a different set of registers compared to previous asics and supports separate NB and GFX planes. Reviewed-by: Jammy Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/cz_dpm.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/cz_dpm.c b/drivers/gpu/drm/amd/amdgpu/cz_dpm.c index 1a2d419cbf16..1316d540ec85 100644 --- a/drivers/gpu/drm/amd/amdgpu/cz_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/cz_dpm.c @@ -494,6 +494,13 @@ static void cz_dpm_fini(struct amdgpu_device *adev) amdgpu_free_extended_power_table(adev); } +#define ixSMUSVI_NB_CURRENTVID 0xD8230044 +#define CURRENT_NB_VID_MASK 0xff000000 +#define CURRENT_NB_VID__SHIFT 24 +#define ixSMUSVI_GFX_CURRENTVID 0xD8230048 +#define CURRENT_GFX_VID_MASK 0xff000000 +#define CURRENT_GFX_VID__SHIFT 24 + static void cz_dpm_debugfs_print_current_performance_level(struct amdgpu_device *adev, struct seq_file *m) @@ -505,18 +512,20 @@ cz_dpm_debugfs_print_current_performance_level(struct amdgpu_device *adev, TARGET_AND_CURRENT_PROFILE_INDEX__CURR_SCLK_INDEX_MASK) >> TARGET_AND_CURRENT_PROFILE_INDEX__CURR_SCLK_INDEX__SHIFT; u32 sclk, tmp; - u16 vddc; + u16 vddnb, vddgfx; if (current_index >= NUM_SCLK_LEVELS) { seq_printf(m, "invalid dpm profile %d\n", current_index); } else { sclk = table->entries[current_index].clk; - tmp = (RREG32_SMC(ixSMU_VOLTAGE_STATUS) & - SMU_VOLTAGE_STATUS__SMU_VOLTAGE_CURRENT_LEVEL_MASK) >> - SMU_VOLTAGE_STATUS__SMU_VOLTAGE_CURRENT_LEVEL__SHIFT; - vddc = cz_convert_8bit_index_to_voltage(adev, (u16)tmp); - seq_printf(m, "power level %d sclk: %u vddc: %u\n", - current_index, sclk, vddc); + tmp = (RREG32_SMC(ixSMUSVI_NB_CURRENTVID) & + CURRENT_NB_VID_MASK) >> CURRENT_NB_VID__SHIFT; + vddnb = cz_convert_8bit_index_to_voltage(adev, (u16)tmp); + tmp = (RREG32_SMC(ixSMUSVI_GFX_CURRENTVID) & + CURRENT_GFX_VID_MASK) >> CURRENT_GFX_VID__SHIFT; + vddgfx = cz_convert_8bit_index_to_voltage(adev, (u16)tmp); + seq_printf(m, "power level %d sclk: %u vddnb: %u vddgfx: %u\n", + current_index, sclk, vddnb, vddgfx); } } -- cgit v1.2.3 From acc6a1a69b79fad70c4794a925dbfffa9fd6b21b Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 22 Jul 2015 12:03:50 -0400 Subject: drm/amdgpu/cz/dpm: properly report UVD and VCE clock levels VCE, UVD DPM work similarly to SCLK DPM. Report the current clock levels for UVD and VCE via debugfs. Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/cz_dpm.c | 61 +++++++++++++++++++++++++++---------- 1 file changed, 45 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/cz_dpm.c b/drivers/gpu/drm/amd/amdgpu/cz_dpm.c index 1316d540ec85..ace870afc7d4 100644 --- a/drivers/gpu/drm/amd/amdgpu/cz_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/cz_dpm.c @@ -505,27 +505,56 @@ static void cz_dpm_debugfs_print_current_performance_level(struct amdgpu_device *adev, struct seq_file *m) { + struct cz_power_info *pi = cz_get_pi(adev); struct amdgpu_clock_voltage_dependency_table *table = &adev->pm.dpm.dyn_state.vddc_dependency_on_sclk; - u32 current_index = - (RREG32_SMC(ixTARGET_AND_CURRENT_PROFILE_INDEX) & - TARGET_AND_CURRENT_PROFILE_INDEX__CURR_SCLK_INDEX_MASK) >> - TARGET_AND_CURRENT_PROFILE_INDEX__CURR_SCLK_INDEX__SHIFT; - u32 sclk, tmp; + struct amdgpu_uvd_clock_voltage_dependency_table *uvd_table = + &adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table; + struct amdgpu_vce_clock_voltage_dependency_table *vce_table = + &adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table; + u32 sclk_index = REG_GET_FIELD(RREG32_SMC(ixTARGET_AND_CURRENT_PROFILE_INDEX), + TARGET_AND_CURRENT_PROFILE_INDEX, CURR_SCLK_INDEX); + u32 uvd_index = REG_GET_FIELD(RREG32_SMC(ixTARGET_AND_CURRENT_PROFILE_INDEX_2), + TARGET_AND_CURRENT_PROFILE_INDEX_2, CURR_UVD_INDEX); + u32 vce_index = REG_GET_FIELD(RREG32_SMC(ixTARGET_AND_CURRENT_PROFILE_INDEX_2), + TARGET_AND_CURRENT_PROFILE_INDEX_2, CURR_VCE_INDEX); + u32 sclk, vclk, dclk, ecclk, tmp; u16 vddnb, vddgfx; - if (current_index >= NUM_SCLK_LEVELS) { - seq_printf(m, "invalid dpm profile %d\n", current_index); + if (sclk_index >= NUM_SCLK_LEVELS) { + seq_printf(m, "invalid sclk dpm profile %d\n", sclk_index); } else { - sclk = table->entries[current_index].clk; - tmp = (RREG32_SMC(ixSMUSVI_NB_CURRENTVID) & - CURRENT_NB_VID_MASK) >> CURRENT_NB_VID__SHIFT; - vddnb = cz_convert_8bit_index_to_voltage(adev, (u16)tmp); - tmp = (RREG32_SMC(ixSMUSVI_GFX_CURRENTVID) & - CURRENT_GFX_VID_MASK) >> CURRENT_GFX_VID__SHIFT; - vddgfx = cz_convert_8bit_index_to_voltage(adev, (u16)tmp); - seq_printf(m, "power level %d sclk: %u vddnb: %u vddgfx: %u\n", - current_index, sclk, vddnb, vddgfx); + sclk = table->entries[sclk_index].clk; + seq_printf(m, "%u sclk: %u\n", sclk_index, sclk); + } + + tmp = (RREG32_SMC(ixSMUSVI_NB_CURRENTVID) & + CURRENT_NB_VID_MASK) >> CURRENT_NB_VID__SHIFT; + vddnb = cz_convert_8bit_index_to_voltage(adev, (u16)tmp); + tmp = (RREG32_SMC(ixSMUSVI_GFX_CURRENTVID) & + CURRENT_GFX_VID_MASK) >> CURRENT_GFX_VID__SHIFT; + vddgfx = cz_convert_8bit_index_to_voltage(adev, (u16)tmp); + seq_printf(m, "vddnb: %u vddgfx: %u\n", vddnb, vddgfx); + + seq_printf(m, "uvd %sabled\n", pi->uvd_power_gated ? "dis" : "en"); + if (!pi->uvd_power_gated) { + if (uvd_index >= CZ_MAX_HARDWARE_POWERLEVELS) { + seq_printf(m, "invalid uvd dpm level %d\n", uvd_index); + } else { + vclk = uvd_table->entries[uvd_index].vclk; + dclk = uvd_table->entries[uvd_index].dclk; + seq_printf(m, "%u uvd vclk: %u dclk: %u\n", uvd_index, vclk, dclk); + } + } + + seq_printf(m, "vce %sabled\n", pi->vce_power_gated ? "dis" : "en"); + if (!pi->vce_power_gated) { + if (vce_index >= CZ_MAX_HARDWARE_POWERLEVELS) { + seq_printf(m, "invalid vce dpm level %d\n", vce_index); + } else { + ecclk = vce_table->entries[vce_index].ecclk; + seq_printf(m, "%u vce ecclk: %u\n", vce_index, ecclk); + } } } -- cgit v1.2.3 From 5aa2a96b34073fb775917fbc7d5578a04164b9f7 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 23 Jul 2015 14:27:09 -0400 Subject: block: export bio_associate_*() and wbc_account_io() bio_associate_blkcg(), bio_associate_current() and wbc_account_io() are used to implement cgroup writeback support for filesystems and thus need to be exported. Export them. Signed-off-by: Tejun Heo Reported-by: Stephen Rothwell Signed-off-by: Jens Axboe --- block/bio.c | 2 ++ fs/fs-writeback.c | 1 + 2 files changed, 3 insertions(+) diff --git a/block/bio.c b/block/bio.c index 2a00d349cd68..b671a0ff731c 100644 --- a/block/bio.c +++ b/block/bio.c @@ -2009,6 +2009,7 @@ int bio_associate_blkcg(struct bio *bio, struct cgroup_subsys_state *blkcg_css) bio->bi_css = blkcg_css; return 0; } +EXPORT_SYMBOL_GPL(bio_associate_blkcg); /** * bio_associate_current - associate a bio with %current @@ -2039,6 +2040,7 @@ int bio_associate_current(struct bio *bio) bio->bi_css = task_get_css(current, blkio_cgrp_id); return 0; } +EXPORT_SYMBOL_GPL(bio_associate_current); /** * bio_disassociate_task - undo bio_associate_current() diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index f0520bcf2094..518c6294bf6c 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -702,6 +702,7 @@ void wbc_account_io(struct writeback_control *wbc, struct page *page, else wbc->wb_tcand_bytes -= min(bytes, wbc->wb_tcand_bytes); } +EXPORT_SYMBOL_GPL(wbc_account_io); /** * inode_congested - test whether an inode is congested -- cgit v1.2.3 From 968491709e5b1aaf429428814fff3d932fa90b60 Mon Sep 17 00:00:00 2001 From: Bernhard Bender Date: Thu, 23 Jul 2015 13:58:08 -0700 Subject: Input: usbtouchscreen - avoid unresponsive TSC-30 touch screen This patch fixes a problem in the usbtouchscreen driver for DMC TSC-30 touch screen. Due to a missing delay between the RESET and SET_RATE commands, the touch screen may become unresponsive during system startup or driver loading. According to the DMC documentation, a delay is needed after the RESET command to allow the chip to complete its internal initialization. As this delay is not guaranteed, we had a system where the touch screen occasionally did not send any touch data. There was no other indication of the problem. The patch fixes the problem by adding a 150ms delay between the RESET and SET_RATE commands. Cc: stable@vger.kernel.org Suggested-by: Jakob Mustafa Signed-off-by: Bernhard Bender Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/usbtouchscreen.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c index f2c6c352c55a..2c41107240de 100644 --- a/drivers/input/touchscreen/usbtouchscreen.c +++ b/drivers/input/touchscreen/usbtouchscreen.c @@ -627,6 +627,9 @@ static int dmc_tsc10_init(struct usbtouch_usb *usbtouch) goto err_out; } + /* TSC-25 data sheet specifies a delay after the RESET command */ + msleep(150); + /* set coordinate output rate */ buf[0] = buf[1] = 0xFF; ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0), -- cgit v1.2.3 From 3b19e032295647b7be2aa3be62510db4aaeda759 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 27 Jun 2015 09:21:32 -0400 Subject: n_tty: signal and flush atomically When handling signalling char, claim the termios write lock before signalling waiting readers and writers to prevent further i/o before flushing the echo and output buffers. This prevents a userspace signal handler which may output from racing the terminal flush. Reference: Bugzilla #99351 ("Output truncated in ssh session after...") Fixes: commit d2b6f44779d3 ("n_tty: Fix signal handling flushes") Reported-by: Filipe Brandenburger Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index c9c27f69e101..ee8bfacf2071 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1108,19 +1108,29 @@ static void eraser(unsigned char c, struct tty_struct *tty) * Locking: ctrl_lock */ -static void isig(int sig, struct tty_struct *tty) +static void __isig(int sig, struct tty_struct *tty) { - struct n_tty_data *ldata = tty->disc_data; struct pid *tty_pgrp = tty_get_pgrp(tty); if (tty_pgrp) { kill_pgrp(tty_pgrp, sig, 1); put_pid(tty_pgrp); } +} - if (!L_NOFLSH(tty)) { +static void isig(int sig, struct tty_struct *tty) +{ + struct n_tty_data *ldata = tty->disc_data; + + if (L_NOFLSH(tty)) { + /* signal only */ + __isig(sig, tty); + + } else { /* signal and flush */ up_read(&tty->termios_rwsem); down_write(&tty->termios_rwsem); + __isig(sig, tty); + /* clear echo buffer */ mutex_lock(&ldata->output_lock); ldata->echo_head = ldata->echo_tail = 0; -- cgit v1.2.3 From 97a60eac33f663d2150ee1b3c69253d87ba53dff Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 9 Jul 2015 22:21:41 +0900 Subject: serial: amba-pl011: Fix devm_ioremap_resource return value check Value returned by devm_ioremap_resource() was checked for non-NULL but devm_ioremap_resource() returns IOMEM_ERR_PTR, not NULL. In case of error this could lead to dereference of ERR_PTR. Signed-off-by: Krzysztof Kozlowski Cc: Fixes: 3873e2d7f63a ("drivers: PL011: refactor pl011_probe()") Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/amba-pl011.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 50cf5b10ceed..fd27e986b1dd 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -2310,8 +2310,8 @@ static int pl011_setup_port(struct device *dev, struct uart_amba_port *uap, void __iomem *base; base = devm_ioremap_resource(dev, mmiobase); - if (!base) - return -ENOMEM; + if (IS_ERR(base)) + return PTR_ERR(base); index = pl011_probe_dt_alias(index, dev); -- cgit v1.2.3 From 08b33249d89700ba555d4ab5cc88714192b8ee46 Mon Sep 17 00:00:00 2001 From: Dongxing Zhang Date: Wed, 10 Jun 2015 15:21:10 +0800 Subject: tty/vt: Fix the memory leak in visual_init If vc->vc_uni_pagedir_loc is not NULL, its refcount needs to be decreased before vc_uni_pagedir_loc is re-assigned. unreferenced object 0xffff88002cdd13b0 (size 512): comm "setfont", pid 503, jiffies 4294896503 (age 722.828s) hex dump (first 32 bytes): 40 92 61 2b 00 88 ff ff 00 00 00 00 00 00 00 00 @.a+............ 00 00 00 00 00 00 00 00 a0 ad 61 2b 00 88 ff ff ..........a+.... backtrace: [] kmemleak_alloc+0x4e/0xb0 [] kmem_cache_alloc_trace+0x1c8/0x240 [] con_do_clear_unimap.isra.2+0x83/0xe0 [] con_clear_unimap+0x22/0x40 [] vt_ioctl+0xeb8/0x1170 [] tty_ioctl+0x208/0xca0 [] do_vfs_ioctl+0x2f8/0x510 [] SyS_ioctl+0x81/0xa0 [] system_call_fastpath+0x16/0x75 [] 0xffffffffffffffff unreferenced object 0xffff88002b619240 (size 256): comm "setfont", pid 503, jiffies 4294896503 (age 722.828s) hex dump (first 32 bytes): 90 bc 84 d5 00 88 ff ff 58 85 84 d5 00 88 ff ff ........X....... 88 ac 84 d5 00 88 ff ff e0 b1 84 d5 00 88 ff ff ................ backtrace: [] kmemleak_alloc+0x4e/0xb0 [] kmem_cache_alloc_trace+0x1c8/0x240 [] con_insert_unipair+0x86/0x170 [] con_set_unimap+0x1b7/0x280 [] vt_ioctl+0xe65/0x1170 [] tty_ioctl+0x208/0xca0 [] do_vfs_ioctl+0x2f8/0x510 [] SyS_ioctl+0x81/0xa0 [] system_call_fastpath+0x16/0x75 [] 0xffffffffffffffff Signed-off-by: Dongxing Zhang Signed-off-by: Xiaoming Wang Reviewed-by: Peter Hurley Tested-by: Konstantin Khlebnikov Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 8fe52989b380..4462d167900c 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -742,6 +742,8 @@ static void visual_init(struct vc_data *vc, int num, int init) __module_get(vc->vc_sw->owner); vc->vc_num = num; vc->vc_display_fg = &master_display_fg; + if (vc->vc_uni_pagedir_loc) + con_free_unimap(vc); vc->vc_uni_pagedir_loc = &vc->vc_uni_pagedir; vc->vc_uni_pagedir = NULL; vc->vc_hi_font_mask = 0; -- cgit v1.2.3 From f3f5da624e0a891c34d8cd513c57f1d9b0c7dadc Mon Sep 17 00:00:00 2001 From: "Martin K. Petersen" Date: Wed, 22 Jul 2015 07:57:12 -0400 Subject: block: Do a full clone when splitting discard bios This fixes a data corruption bug when using discard on top of MD linear, raid0 and raid10 personalities. Commit 20d0189b1012 "block: Introduce new bio_split()" permits sharing the bio_vec between the two resulting bios. That is fine for read/write requests where the bio_vec is immutable. For discards, however, we need to be able to attach a payload and update the bio_vec so the page can get mapped to a scatterlist entry. Therefore the bio_vec can not be shared when splitting discards and we must do a full clone. Signed-off-by: Martin K. Petersen Reported-by: Seunguk Shin Tested-by: Seunguk Shin Cc: Seunguk Shin Cc: Jens Axboe Cc: Kent Overstreet Cc: # v3.14+ Reviewed-by: Christoph Hellwig Signed-off-by: Jens Axboe --- block/bio.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/block/bio.c b/block/bio.c index b671a0ff731c..d6e5ba3399f0 100644 --- a/block/bio.c +++ b/block/bio.c @@ -1831,8 +1831,9 @@ EXPORT_SYMBOL(bio_endio); * Allocates and returns a new bio which represents @sectors from the start of * @bio, and updates @bio to represent the remaining sectors. * - * The newly allocated bio will point to @bio's bi_io_vec; it is the caller's - * responsibility to ensure that @bio is not freed before the split. + * Unless this is a discard request the newly allocated bio will point + * to @bio's bi_io_vec; it is the caller's responsibility to ensure that + * @bio is not freed before the split. */ struct bio *bio_split(struct bio *bio, int sectors, gfp_t gfp, struct bio_set *bs) @@ -1842,7 +1843,15 @@ struct bio *bio_split(struct bio *bio, int sectors, BUG_ON(sectors <= 0); BUG_ON(sectors >= bio_sectors(bio)); - split = bio_clone_fast(bio, gfp, bs); + /* + * Discards need a mutable bio_vec to accommodate the payload + * required by the DSM TRIM and UNMAP commands. + */ + if (bio->bi_rw & REQ_DISCARD) + split = bio_clone_bioset(bio, gfp, bs); + else + split = bio_clone_fast(bio, gfp, bs); + if (!split) return NULL; -- cgit v1.2.3 From d8c2c0d89205a3538c5fd77dc9d4767ee6bebc70 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 28 Jun 2015 09:45:08 +0800 Subject: serial: etraxfs-uart: Fix release etraxfs_uart_ports In probe, we use dev_id as array index of etraxfs_uart_ports and store the index in port->line. So etraxfs_uart_ports[port->line] should be released when unload the module. Signed-off-by: Axel Lin Acked-by: Niklas Cassel Acked-by: Jesper Nilsson Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/etraxfs-uart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/serial/etraxfs-uart.c b/drivers/tty/serial/etraxfs-uart.c index a57301a6fe42..679709f51fd4 100644 --- a/drivers/tty/serial/etraxfs-uart.c +++ b/drivers/tty/serial/etraxfs-uart.c @@ -950,7 +950,7 @@ static int etraxfs_uart_remove(struct platform_device *pdev) port = platform_get_drvdata(pdev); uart_remove_one_port(&etraxfs_uart_driver, port); - etraxfs_uart_ports[pdev->id] = NULL; + etraxfs_uart_ports[port->line] = NULL; return 0; } -- cgit v1.2.3 From 32aa6339d9c5156de5d881b103e0e360934d6a74 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Wed, 1 Jul 2015 14:19:52 +0200 Subject: sc16is7xx: fix Kconfig dependencies When I2C=m and SPI=y or-ing them will produce =y while what we need is the lower bound, i.e. =m. Fortunately SPI is a boolean so we need to handle only one special case. Reported-by: kbuild test robot Signed-off-by: Jakub Kicinski Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 76e65b714471..15b4079a335e 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -1185,7 +1185,7 @@ config SERIAL_SC16IS7XX_CORE config SERIAL_SC16IS7XX tristate "SC16IS7xx serial support" select SERIAL_CORE - depends on I2C || SPI_MASTER + depends on (SPI_MASTER && !I2C) || I2C help This selects support for SC16IS7xx serial ports. Supported ICs are SC16IS740, SC16IS741, SC16IS750, SC16IS752, -- cgit v1.2.3 From dec273ecc1169ade46999bb0feca3814915f5c11 Mon Sep 17 00:00:00 2001 From: Bo Svangård Date: Sat, 13 Jun 2015 13:40:20 +0200 Subject: sc16is7xx: fix FIFO address of secondary UART MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Calls to regmap_raw_read/write needed register rewrite in a similar way as function calls to regmap_read/write already had. This enables reading/writing the serial datastream to the device. Signed-off-by: Bo Svangård Signed-off-by: Jakub Kicinski Signed-off-by: Jon Ringle Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sc16is7xx.c | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c index 9e6576004a42..5ccc698cbbfa 100644 --- a/drivers/tty/serial/sc16is7xx.c +++ b/drivers/tty/serial/sc16is7xx.c @@ -354,6 +354,26 @@ static void sc16is7xx_port_write(struct uart_port *port, u8 reg, u8 val) (reg << SC16IS7XX_REG_SHIFT) | port->line, val); } +static void sc16is7xx_fifo_read(struct uart_port *port, unsigned int rxlen) +{ + struct sc16is7xx_port *s = dev_get_drvdata(port->dev); + u8 addr = (SC16IS7XX_RHR_REG << SC16IS7XX_REG_SHIFT) | port->line; + + regcache_cache_bypass(s->regmap, true); + regmap_raw_read(s->regmap, addr, s->buf, rxlen); + regcache_cache_bypass(s->regmap, false); +} + +static void sc16is7xx_fifo_write(struct uart_port *port, u8 to_send) +{ + struct sc16is7xx_port *s = dev_get_drvdata(port->dev); + u8 addr = (SC16IS7XX_THR_REG << SC16IS7XX_REG_SHIFT) | port->line; + + regcache_cache_bypass(s->regmap, true); + regmap_raw_write(s->regmap, addr, s->buf, to_send); + regcache_cache_bypass(s->regmap, false); +} + static void sc16is7xx_port_update(struct uart_port *port, u8 reg, u8 mask, u8 val) { @@ -508,10 +528,7 @@ static void sc16is7xx_handle_rx(struct uart_port *port, unsigned int rxlen, s->buf[0] = sc16is7xx_port_read(port, SC16IS7XX_RHR_REG); bytes_read = 1; } else { - regcache_cache_bypass(s->regmap, true); - regmap_raw_read(s->regmap, SC16IS7XX_RHR_REG, - s->buf, rxlen); - regcache_cache_bypass(s->regmap, false); + sc16is7xx_fifo_read(port, rxlen); bytes_read = rxlen; } @@ -591,9 +608,8 @@ static void sc16is7xx_handle_tx(struct uart_port *port) s->buf[i] = xmit->buf[xmit->tail]; xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); } - regcache_cache_bypass(s->regmap, true); - regmap_raw_write(s->regmap, SC16IS7XX_THR_REG, s->buf, to_send); - regcache_cache_bypass(s->regmap, false); + + sc16is7xx_fifo_write(port, to_send); } if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) -- cgit v1.2.3 From 907eda32a36fcdb979bdb91ea097abb3dd2c23c9 Mon Sep 17 00:00:00 2001 From: David Jander Date: Fri, 26 Jun 2015 08:11:30 +0200 Subject: Revert "serial: imx: initialized DMA w/o HW flow enabled" This reverts commit 068500e08dc87ea9a453cc4a500cf3ab28d0f936. According to some tests, SDMA support is broken at least for i.MX6 without HW flow control. Different forms of data-corruption appear either with the ROM firmware for the SDMA controller as well as when loading Freescale provided SDMA firmware versions 1.1 or 3.1. Signed-off-by: David Jander Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/imx.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 2c90dc31bfaa..54fdc7866ea1 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -1121,11 +1121,6 @@ static int imx_startup(struct uart_port *port) writel(temp & ~UCR4_DREN, sport->port.membase + UCR4); - /* Can we enable the DMA support? */ - if (is_imx6q_uart(sport) && !uart_console(port) && - !sport->dma_is_inited) - imx_uart_dma_init(sport); - spin_lock_irqsave(&sport->port.lock, flags); /* Reset fifo's and state machines */ i = 100; @@ -1143,9 +1138,6 @@ static int imx_startup(struct uart_port *port) writel(USR1_RTSD, sport->port.membase + USR1); writel(USR2_ORE, sport->port.membase + USR2); - if (sport->dma_is_inited && !sport->dma_is_enabled) - imx_enable_dma(sport); - temp = readl(sport->port.membase + UCR1); temp |= UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN; @@ -1316,6 +1308,11 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios, } else { ucr2 |= UCR2_CTSC; } + + /* Can we enable the DMA support? */ + if (is_imx6q_uart(sport) && !uart_console(port) + && !sport->dma_is_inited) + imx_uart_dma_init(sport); } else { termios->c_cflag &= ~CRTSCTS; } @@ -1432,6 +1429,8 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios, if (UART_ENABLE_MS(&sport->port, termios->c_cflag)) imx_enable_ms(&sport->port); + if (sport->dma_is_inited && !sport->dma_is_enabled) + imx_enable_dma(sport); spin_unlock_irqrestore(&sport->port.lock, flags); } -- cgit v1.2.3 From 7525a9901b5ee3c84933ad069e41506c37404ddc Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Wed, 8 Jul 2015 23:10:06 -0400 Subject: m32r: Add ioreadXX/iowriteXX big-endian mmio accessors commit c627f2ceb692 ("serial: 8250: Add support for big-endian MMIO accesses") added support for 32-bit big-endian mmio to the 8250 driver. Support for ioreadXXbe/iowriteXXbe io accessors was missing from m32r arch, which caused build errors. Add trivial macro mmio accessors. Reported-by: Fengguang Wu Cc: Kevin Cernekee Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- arch/m32r/include/asm/io.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/m32r/include/asm/io.h b/arch/m32r/include/asm/io.h index 0c3f25ee3381..f8de767ce2bc 100644 --- a/arch/m32r/include/asm/io.h +++ b/arch/m32r/include/asm/io.h @@ -174,6 +174,11 @@ static inline void _writel(unsigned long l, unsigned long addr) #define iowrite16 writew #define iowrite32 writel +#define ioread16be(addr) be16_to_cpu(readw(addr)) +#define ioread32be(addr) be32_to_cpu(readl(addr)) +#define iowrite16be(v, addr) writew(cpu_to_be16(v), (addr)) +#define iowrite32be(v, addr) writel(cpu_to_be32(v), (addr)) + #define mmiowb() #define flush_write_buffers() do { } while (0) /* M32R_FIXME */ -- cgit v1.2.3 From e144c58cad6667876173dd76977e9e6557e34941 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 12 Jul 2015 21:05:26 -0400 Subject: serial: core: Fix crashes while echoing when closing While closing, new rx data may be received after the input buffers have been flushed but before stop_rx() halts receiving [1]. The new data might not be processed by flush_to_ldisc() until after uart_shutdown() and normal input processing is re-enabled (ie., tty->closing = 0). The race is outlined below: CPU 0 | CPU 1 | uart_close() | tty_port_close_start() | tty->closing = 1 | tty_ldisc_flush() | | => IRQ | while (LSR & data ready) | uart_insert_char() | tty_flip_buffer_push() | <= EOI stop_rx() | . uart_shutdown() | . free xmit.buf | . tty_port_tty_set(NULL) | . tty->closing = 0 | . | flush_to_ldisc() | n_tty_receive_buf_common() | __receive_buf() | ... | commit_echoes() | uart_flush_chars() | __uart_start() | ** OOPS on port.tty deref ** tty_ldisc_flush() | Input processing must be prevented from echoing (tty->closing = 1) until _after_ the input buffers have been flushed again at the end of uart_close(). [1] In fact, some input may actually be buffered _after_ stop_rx() since the rx interrupt may have already triggered but not yet been handled when stop_rx() disables rx interrupts. Fixes: 2e758910832d ("serial: core: Flush ldisc after dropping port mutex in uart_close()") Reported-by: Robert Elliott Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 7ae1592f7ec9..f36852067f20 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1418,7 +1418,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp) mutex_lock(&port->mutex); uart_shutdown(tty, state); tty_port_tty_set(port, NULL); - tty->closing = 0; + spin_lock_irqsave(&port->lock, flags); if (port->blocked_open) { @@ -1444,6 +1444,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp) mutex_unlock(&port->mutex); tty_ldisc_flush(tty); + tty->closing = 0; } static void uart_wait_until_sent(struct tty_struct *tty, int timeout) -- cgit v1.2.3 From 61e86cc90af49cecef9c54ccea1f572fbcb695ac Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 12 Jul 2015 20:47:35 -0400 Subject: tty: vt: Fix !TASK_RUNNING diagnostic warning from paste_selection() Pasting text with gpm on a VC produced warning [1]. Reset task state to TASK_RUNNING in the paste_selection() loop, if the loop did not sleep. [1] WARNING: CPU: 6 PID: 1960 at /home/peter/src/kernels/mainline/kernel/sched/core.c:7286 __might_sleep+0x7f/0x90() do not call blocking ops when !TASK_RUNNING; state=1 set at [] paste_selection+0x9e/0x1a0 Modules linked in: btrfs xor raid6_pq ufs qnx4 hfsplus hfs minix ntfs msdos jfs xfs libcrc32c ..... CPU: 6 PID: 1960 Comm: gpm Not tainted 4.1.0-rc7+tty-xeon+debug #rc7+tty Hardware name: Dell Inc. Precision WorkStation T5400 /0RW203, BIOS A11 04/30/2012 ffffffff81c9c0a0 ffff8802b0fd3ac8 ffffffff8185778a 0000000000000001 ffff8802b0fd3b18 ffff8802b0fd3b08 ffffffff8108039a ffffffff82ae8510 ffffffff81c9ce00 0000000000000015 0000000000000000 0000000000000000 Call Trace: [] dump_stack+0x4f/0x7b [] warn_slowpath_common+0x8a/0xc0 [] warn_slowpath_fmt+0x46/0x50 [] ? __lock_acquire+0xe2d/0x13a0 [] ? paste_selection+0x9e/0x1a0 [] ? paste_selection+0x9e/0x1a0 [] __might_sleep+0x7f/0x90 [] down_read+0x2a/0xa0 [] ? sched_clock_cpu+0xb8/0xe0 [] n_tty_receive_buf_common+0x4c/0xba0 [] ? mark_held_locks+0x75/0xa0 [] ? _raw_spin_unlock_irqrestore+0x65/0x80 [] ? get_parent_ip+0x11/0x50 [] n_tty_receive_buf2+0x14/0x20 [] paste_selection+0x157/0x1a0 [] ? wake_up_state+0x20/0x20 [] tioclinux+0xb8/0x2c0 [] vt_ioctl+0xaee/0x11a0 [] ? sched_clock_local+0x25/0x90 [] ? vtime_account_user+0x91/0xa0 [] tty_ioctl+0x20c/0xe20 [] ? vtime_account_user+0x91/0xa0 [] ? get_parent_ip+0x11/0x50 [] ? preempt_count_sub+0x49/0x50 [] ? context_tracking_exit+0x5c/0x290 [] ? context_tracking_exit+0x5c/0x290 [] do_vfs_ioctl+0x318/0x570 [] ? trace_hardirqs_on+0xd/0x10 [] ? trace_hardirqs_on_caller+0x115/0x1e0 [] ? __fget_light+0x6c/0xa0 [] SyS_ioctl+0x81/0xa0 [] system_call_fastpath+0x16/0x7a Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/selection.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c index ea27804d87af..381a2b13682c 100644 --- a/drivers/tty/vt/selection.c +++ b/drivers/tty/vt/selection.c @@ -356,6 +356,7 @@ int paste_selection(struct tty_struct *tty) schedule(); continue; } + __set_current_state(TASK_RUNNING); count = sel_buffer_lth - pasted; count = tty_ldisc_receive_buf(ld, sel_buffer + pasted, NULL, count); -- cgit v1.2.3 From f135b978c2dab3d439eacb8353d3c0aac6af072a Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Wed, 1 Jul 2015 17:32:29 +0900 Subject: drm/ttm: recognize ARM64 arch in ioprot handler Return proper pgprot for ARM64. This is required for objects like Nouveau fences to be mapped with expected coherency. Signed-off-by: Alexandre Courbot Signed-off-by: Dave Airlie --- drivers/gpu/drm/ttm/ttm_bo_util.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 882cccdad272..ac6fe40b99f7 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -490,7 +490,8 @@ pgprot_t ttm_io_prot(uint32_t caching_flags, pgprot_t tmp) else if (boot_cpu_data.x86 > 3) tmp = pgprot_noncached(tmp); #endif -#if defined(__ia64__) || defined(__arm__) || defined(__powerpc__) +#if defined(__ia64__) || defined(__arm__) || defined(__aarch64__) || \ + defined(__powerpc__) if (caching_flags & TTM_PL_FLAG_WC) tmp = pgprot_writecombine(tmp); else -- cgit v1.2.3 From 34cab6f42003cb06f48f86a86652984dec338ae9 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Fri, 24 Jul 2015 09:22:16 +1000 Subject: md/raid1: fix test for 'was read error from last working device'. When we get a read error from the last working device, we don't try to repair it, and don't fail the device. We simple report a read error to the caller. However the current test for 'is this the last working device' is wrong. When there is only one fully working device, it assumes that a non-faulty device is that device. However a spare which is rebuilding would be non-faulty but so not the only working device. So change the test from "!Faulty" to "In_sync". If ->degraded says there is only one fully working device and this device is in_sync, this must be the one. This bug has existed since we allowed read_balance to read from a recovering spare in v3.0 Reported-and-tested-by: Alexander Lyakas Fixes: 76073054c95b ("md/raid1: clean up read_balance.") Cc: stable@vger.kernel.org (v3.0+) Signed-off-by: NeilBrown --- drivers/md/raid1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index f80f1af61ce7..50cf0c893b16 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -336,7 +336,7 @@ static void raid1_end_read_request(struct bio *bio, int error) spin_lock_irqsave(&conf->device_lock, flags); if (r1_bio->mddev->degraded == conf->raid_disks || (r1_bio->mddev->degraded == conf->raid_disks-1 && - !test_bit(Faulty, &conf->mirrors[mirror].rdev->flags))) + test_bit(In_sync, &conf->mirrors[mirror].rdev->flags))) uptodate = 1; spin_unlock_irqrestore(&conf->device_lock, flags); } -- cgit v1.2.3 From f7357273198adc86fe11c2a7be8a0816f44103bb Mon Sep 17 00:00:00 2001 From: Goldwyn Rodrigues Date: Wed, 22 Jul 2015 12:09:16 -0500 Subject: md: Skip cluster setup in case of error while reading bitmap If the bitmap read fails, the error code set is -EINVAL. However, we don't check for errors and go ahead with cluster_setup. Skip the cluster setup in case of error. Signed-off-by: Goldwyn Rodrigues Signed-off-by: NeilBrown --- drivers/md/bitmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index c90118e90708..a4ab51350f40 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -680,7 +680,7 @@ out: kunmap_atomic(sb); /* Assiging chunksize is required for "re_read" */ bitmap->mddev->bitmap_info.chunksize = chunksize; - if (nodes && (bitmap->cluster_slot < 0)) { + if (err == 0 && nodes && (bitmap->cluster_slot < 0)) { err = md_setup_cluster(bitmap->mddev, nodes); if (err) { pr_err("%s: Could not setup cluster service (%d)\n", -- cgit v1.2.3 From b0c26a79d6993b280931f8e2b406ca4b220bb58f Mon Sep 17 00:00:00 2001 From: Goldwyn Rodrigues Date: Wed, 22 Jul 2015 12:09:15 -0500 Subject: md: Return error if request_module fails and returns positive value request_module() can return 256 (process exited) in some cases, which is not as specified in the documentation before the request_module() definition. Convert the error to -ENOENT. The positive error number results in bitmap_create() returning a value that is meant to be an error but doesn't look like one, so it is dereferenced as a point and causes a crash. (not needed for stable as this is "experimental" code) Fixes: edb39c9deda8 ("Introduce md_cluster_operations to handle cluster functions") Signed-off-By: Goldwyn Rodrigues Signed-off-by: NeilBrown --- drivers/md/md.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index 5025b3ec13cd..0fcf6de2415a 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -7439,7 +7439,7 @@ int md_setup_cluster(struct mddev *mddev, int nodes) err = request_module("md-cluster"); if (err) { pr_err("md-cluster module not found.\n"); - return err; + return -ENOENT; } spin_lock(&pers_lock); -- cgit v1.2.3 From 33e38ac6887d975fe2635c7fcaefb6d5495cb2e1 Mon Sep 17 00:00:00 2001 From: Goldwyn Rodrigues Date: Wed, 1 Jul 2015 12:19:56 +1000 Subject: md-cluster: fix bitmap sub-offset in bitmap_read_sb bitmap_read_sb is modifying mddev->bitmap_info.offset. This works for the first bitmap read. However, when multiple bitmaps need to be opened by the same node, it ends up corrupting the offset. Fix it by using a local variable. Also, bitmap_read_sb is not required in bitmap_copy_from_slot since it is called in bitmap_create. Remove bitmap_read_sb(). Signed-off-by: Goldwyn Rodrigues Signed-off-by: NeilBrown --- drivers/md/bitmap.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index a4ab51350f40..1b9c2df718c6 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -559,6 +559,7 @@ static int bitmap_read_sb(struct bitmap *bitmap) unsigned long sectors_reserved = 0; int err = -EINVAL; struct page *sb_page; + loff_t offset = bitmap->mddev->bitmap_info.offset; if (!bitmap->storage.file && !bitmap->mddev->bitmap_info.offset) { chunksize = 128 * 1024 * 1024; @@ -585,9 +586,9 @@ re_read: bm_blocks = ((bm_blocks+7) >> 3) + sizeof(bitmap_super_t); /* to 4k blocks */ bm_blocks = DIV_ROUND_UP_SECTOR_T(bm_blocks, 4096); - bitmap->mddev->bitmap_info.offset += bitmap->cluster_slot * (bm_blocks << 3); + offset = bitmap->mddev->bitmap_info.offset + (bitmap->cluster_slot * (bm_blocks << 3)); pr_info("%s:%d bm slot: %d offset: %llu\n", __func__, __LINE__, - bitmap->cluster_slot, (unsigned long long)bitmap->mddev->bitmap_info.offset); + bitmap->cluster_slot, offset); } if (bitmap->storage.file) { @@ -598,7 +599,7 @@ re_read: bitmap, bytes, sb_page); } else { err = read_sb_page(bitmap->mddev, - bitmap->mddev->bitmap_info.offset, + offset, sb_page, 0, sizeof(bitmap_super_t)); } @@ -1875,10 +1876,6 @@ int bitmap_copy_from_slot(struct mddev *mddev, int slot, if (IS_ERR(bitmap)) return PTR_ERR(bitmap); - rv = bitmap_read_sb(bitmap); - if (rv) - goto err; - rv = bitmap_init_from_disk(bitmap, 0); if (rv) goto err; -- cgit v1.2.3 From 90382ed9afeafd42ef193f0eadc6b2a252d6c24d Mon Sep 17 00:00:00 2001 From: Goldwyn Rodrigues Date: Wed, 24 Jun 2015 09:30:32 -0500 Subject: Fix read-balancing during node failure During a node failure, We need to suspend read balancing so that the reads are directed to the first device and stale data is not read. Suspending writes is not required because these would be recorded and synced eventually. A new flag MD_CLUSTER_SUSPEND_READ_BALANCING is set in recover_prep(). area_resyncing() will respond true for the entire devices if this flag is set and the request type is READ. The flag is cleared in recover_done(). Signed-off-by: Goldwyn Rodrigues Reported-By: David Teigland Signed-off-by: NeilBrown --- drivers/md/md-cluster.c | 12 +++++++++++- drivers/md/md-cluster.h | 2 +- drivers/md/raid1.c | 7 ++++--- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/drivers/md/md-cluster.c b/drivers/md/md-cluster.c index fcfc4b9b2672..0072190515e0 100644 --- a/drivers/md/md-cluster.c +++ b/drivers/md/md-cluster.c @@ -44,6 +44,7 @@ struct resync_info { /* md_cluster_info flags */ #define MD_CLUSTER_WAITING_FOR_NEWDISK 1 +#define MD_CLUSTER_SUSPEND_READ_BALANCING 2 struct md_cluster_info { @@ -275,6 +276,9 @@ clear_bit: static void recover_prep(void *arg) { + struct mddev *mddev = arg; + struct md_cluster_info *cinfo = mddev->cluster_info; + set_bit(MD_CLUSTER_SUSPEND_READ_BALANCING, &cinfo->state); } static void recover_slot(void *arg, struct dlm_slot *slot) @@ -307,6 +311,7 @@ static void recover_done(void *arg, struct dlm_slot *slots, cinfo->slot_number = our_slot; complete(&cinfo->completion); + clear_bit(MD_CLUSTER_SUSPEND_READ_BALANCING, &cinfo->state); } static const struct dlm_lockspace_ops md_ls_ops = { @@ -816,12 +821,17 @@ static void resync_finish(struct mddev *mddev) resync_send(mddev, RESYNCING, 0, 0); } -static int area_resyncing(struct mddev *mddev, sector_t lo, sector_t hi) +static int area_resyncing(struct mddev *mddev, int direction, + sector_t lo, sector_t hi) { struct md_cluster_info *cinfo = mddev->cluster_info; int ret = 0; struct suspend_info *s; + if ((direction == READ) && + test_bit(MD_CLUSTER_SUSPEND_READ_BALANCING, &cinfo->state)) + return 1; + spin_lock_irq(&cinfo->suspend_lock); if (list_empty(&cinfo->suspend_list)) goto out; diff --git a/drivers/md/md-cluster.h b/drivers/md/md-cluster.h index 6817ee00e053..00defe2badbc 100644 --- a/drivers/md/md-cluster.h +++ b/drivers/md/md-cluster.h @@ -18,7 +18,7 @@ struct md_cluster_operations { int (*metadata_update_start)(struct mddev *mddev); int (*metadata_update_finish)(struct mddev *mddev); int (*metadata_update_cancel)(struct mddev *mddev); - int (*area_resyncing)(struct mddev *mddev, sector_t lo, sector_t hi); + int (*area_resyncing)(struct mddev *mddev, int direction, sector_t lo, sector_t hi); int (*add_new_disk_start)(struct mddev *mddev, struct md_rdev *rdev); int (*add_new_disk_finish)(struct mddev *mddev); int (*new_disk_ack)(struct mddev *mddev, bool ack); diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 50cf0c893b16..94f5b55069e0 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -541,7 +541,7 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect if ((conf->mddev->recovery_cp < this_sector + sectors) || (mddev_is_clustered(conf->mddev) && - md_cluster_ops->area_resyncing(conf->mddev, this_sector, + md_cluster_ops->area_resyncing(conf->mddev, READ, this_sector, this_sector + sectors))) choose_first = 1; else @@ -1111,7 +1111,8 @@ static void make_request(struct mddev *mddev, struct bio * bio) ((bio_end_sector(bio) > mddev->suspend_lo && bio->bi_iter.bi_sector < mddev->suspend_hi) || (mddev_is_clustered(mddev) && - md_cluster_ops->area_resyncing(mddev, bio->bi_iter.bi_sector, bio_end_sector(bio))))) { + md_cluster_ops->area_resyncing(mddev, WRITE, + bio->bi_iter.bi_sector, bio_end_sector(bio))))) { /* As the suspend_* range is controlled by * userspace, we want an interruptible * wait. @@ -1124,7 +1125,7 @@ static void make_request(struct mddev *mddev, struct bio * bio) if (bio_end_sector(bio) <= mddev->suspend_lo || bio->bi_iter.bi_sector >= mddev->suspend_hi || (mddev_is_clustered(mddev) && - !md_cluster_ops->area_resyncing(mddev, + !md_cluster_ops->area_resyncing(mddev, WRITE, bio->bi_iter.bi_sector, bio_end_sector(bio)))) break; schedule(); -- cgit v1.2.3 From e6030cb06c40e4ab4e8c712f13f494a09638ed2c Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Fri, 17 Jul 2015 13:26:23 +1000 Subject: md/raid5: clear R5_NeedReplace when no longer needed. This flag is currently never cleared, which can in rare cases trigger a warn-on if it is still set but the block isn't InSync. So clear it when it isn't need, which includes if the replacement device has failed. Signed-off-by: NeilBrown --- drivers/md/raid5.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 38300ee3c4e1..643d217bfa13 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -4066,8 +4066,10 @@ static void analyse_stripe(struct stripe_head *sh, struct stripe_head_state *s) &first_bad, &bad_sectors)) set_bit(R5_ReadRepl, &dev->flags); else { - if (rdev) + if (rdev && !test_bit(Faulty, &rdev->flags)) set_bit(R5_NeedReplace, &dev->flags); + else + clear_bit(R5_NeedReplace, &dev->flags); rdev = rcu_dereference(conf->disks[i].rdev); clear_bit(R5_ReadRepl, &dev->flags); } -- cgit v1.2.3 From 408806f740497c5d71f9c305b3d6aad260ff186d Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Tue, 16 Jun 2015 16:07:17 +0530 Subject: mmc: omap_hsmmc: Fix DTO and DCRC handling DTO/DCRC errors were not being informed to the mmc core since commit ae4bf788ee9b ("mmc: omap_hsmmc: consolidate error report handling of HSMMC IRQ"). This commit made sure 'end_trans' is never set on DTO/DCRC errors. This is because after this commit 'host->data' is checked after it has been cleared to NULL by omap_hsmmc_dma_cleanup(). Because 'end_trans' is never set, omap_hsmmc_xfer_done() is never invoked making core layer not to be aware of DTO/DCRC errors. Because of this any command invoked after DTO/DCRC error leads to a hang. Fix this by checking for 'host->data' before it is actually cleared. Fixes: ae4bf788ee9b ("mmc: omap_hsmmc: consolidate error report handling of HSMMC IRQ") CC: stable@vger.kernel.org Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Vignesh R Tested-by: Andreas Fenkart Signed-off-by: Ulf Hansson --- drivers/mmc/host/omap_hsmmc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index b2b411da297b..0132ba75a437 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -1062,6 +1062,10 @@ static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status) if (status & (CTO_EN | CCRC_EN)) end_cmd = 1; + if (host->data || host->response_busy) { + end_trans = !end_cmd; + host->response_busy = 0; + } if (status & (CTO_EN | DTO_EN)) hsmmc_command_incomplete(host, -ETIMEDOUT, end_cmd); else if (status & (CCRC_EN | DCRC_EN)) @@ -1081,10 +1085,6 @@ static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status) } dev_dbg(mmc_dev(host->mmc), "AC12 err: 0x%x\n", ac12); } - if (host->data || host->response_busy) { - end_trans = !end_cmd; - host->response_busy = 0; - } } OMAP_HSMMC_WRITE(host->base, STAT, status); -- cgit v1.2.3 From 5027cd1e323d2f8136abb32ac7c8e1e1a94eac05 Mon Sep 17 00:00:00 2001 From: Vignesh R Date: Tue, 16 Jun 2015 16:07:18 +0530 Subject: mmc: omap_hsmmc: Handle BADA, DEB and CEB interrupts Sometimes BADA, DEB or CEB error interrupts occur when sd card is unplugged during data transfer. These interrupts are currently ignored by the interrupt handler. But, this results in card not being recognised on subsequent insertion. This is because mmcqd is waiting forever for the data transfer(for which error occurred) to complete. Fix this, by reporting BADA, DEB, CEB errors to mmc-core as -EILSEQ, so that the core can do appropriate handling. Signed-off-by: Vignesh R Tested-by: Andreas Fenkart Signed-off-by: Ulf Hansson --- drivers/mmc/host/omap_hsmmc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 0132ba75a437..4d1203236890 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -1068,7 +1068,8 @@ static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status) } if (status & (CTO_EN | DTO_EN)) hsmmc_command_incomplete(host, -ETIMEDOUT, end_cmd); - else if (status & (CCRC_EN | DCRC_EN)) + else if (status & (CCRC_EN | DCRC_EN | DEB_EN | CEB_EN | + BADA_EN)) hsmmc_command_incomplete(host, -EILSEQ, end_cmd); if (status & ACE_EN) { -- cgit v1.2.3 From 7ac020366b0a436d726408841160b5dc32c19214 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Mon, 22 Jun 2015 11:41:23 +0800 Subject: mmc: sdhci check parameters before call dma_free_coherent We should not call dma_free_coherent if host->adma_table is NULL, otherwise may trigger panic. Fixes: d1e49f77d7c7 ("mmc: sdhci: convert ADMA descriptors to a...") Signed-off-by: Peng Fan Acked-by: Adrian Hunter Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index bc1445238fb3..655900f55244 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -2978,8 +2978,11 @@ int sdhci_add_host(struct sdhci_host *host) GFP_KERNEL); host->align_buffer = kmalloc(host->align_buffer_sz, GFP_KERNEL); if (!host->adma_table || !host->align_buffer) { - dma_free_coherent(mmc_dev(mmc), host->adma_table_sz, - host->adma_table, host->adma_addr); + if (host->adma_table) + dma_free_coherent(mmc_dev(mmc), + host->adma_table_sz, + host->adma_table, + host->adma_addr); kfree(host->align_buffer); pr_warn("%s: Unable to allocate ADMA buffers - falling back to standard DMA\n", mmc_hostname(mmc)); -- cgit v1.2.3 From c2b22fff7186f8a6bd6dbfe960ad00421ba82a52 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 26 Jun 2015 14:09:26 +0200 Subject: mmc: MMC_MTK should depend on HAS_DMA If NO_DMA=y: ERROR: "dma_alloc_coherent" [drivers/mmc/host/mtk-sd.ko] undefined! ERROR: "dma_unmap_sg" [drivers/mmc/host/mtk-sd.ko] undefined! ERROR: "dma_map_sg" [drivers/mmc/host/mtk-sd.ko] undefined! ERROR: "dma_free_coherent" [drivers/mmc/host/mtk-sd.ko] undefined! Add a dependency on HAS_DMA to fix this. Signed-off-by: Geert Uytterhoeven Signed-off-by: Ulf Hansson --- drivers/mmc/host/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index fd9a58e216a5..6a0f9c79be26 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -779,6 +779,7 @@ config MMC_TOSHIBA_PCI config MMC_MTK tristate "MediaTek SD/MMC Card Interface support" + depends on HAS_DMA help This selects the MediaTek(R) Secure digital and Multimedia card Interface. If you have a machine with a integrated SD/MMC card reader, say Y or M here. -- cgit v1.2.3 From 9098f84cced870f54d8c410dd2444cfa61467fa0 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Thu, 16 Jul 2015 15:50:45 +0200 Subject: mmc: block: Add missing mmc_blk_put() in power_ro_lock_show() Enclosing mmc_blk_put() is missing in power_ro_lock_show() sysfs handler, let's add it. Fixes: add710eaa886 ("mmc: boot partition ro lock support") Signed-off-by: Tomas Winkler Signed-off-by: Ulf Hansson --- drivers/mmc/card/block.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index c9c3d20b784b..a1b820fcb2a6 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -208,6 +208,8 @@ static ssize_t power_ro_lock_show(struct device *dev, ret = snprintf(buf, PAGE_SIZE, "%d\n", locked); + mmc_blk_put(md); + return ret; } -- cgit v1.2.3 From 8e91125ff3f57f15c6568e2a6d32743b3f7815e4 Mon Sep 17 00:00:00 2001 From: Joakim Tjernlund Date: Wed, 22 Jul 2015 16:44:26 +0200 Subject: mmc: sdhci-esdhc: Make 8BIT bus work Support for 8BIT bus with was added some time ago to sdhci-esdhc but then missed to remove the 8BIT from the reserved bit mask which made 8BIT non functional. Fixes: 66b50a00992d ("mmc: esdhc: Add support for 8-bit bus width and..") Signed-off-by: Joakim Tjernlund Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-esdhc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci-esdhc.h b/drivers/mmc/host/sdhci-esdhc.h index 3497cfaf683c..a870c42731d7 100644 --- a/drivers/mmc/host/sdhci-esdhc.h +++ b/drivers/mmc/host/sdhci-esdhc.h @@ -45,6 +45,6 @@ #define ESDHC_DMA_SYSCTL 0x40c #define ESDHC_DMA_SNOOP 0x00000040 -#define ESDHC_HOST_CONTROL_RES 0x05 +#define ESDHC_HOST_CONTROL_RES 0x01 #endif /* _DRIVERS_MMC_SDHCI_ESDHC_H */ -- cgit v1.2.3 From aca45c0e95dad1c4ba4d38da192756b0e10cbbbd Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Wed, 22 Jul 2015 20:53:00 +0800 Subject: dts: imx51: fix sd card gpio polarity specified in device tree cd-gpios polarity should be changed to GPIO_ACTIVE_LOW and wp-gpios should be changed to GPIO_ACTIVE_HIGH. Otherwise, the SD may not work properly due to wrong polarity inversion specified in DT after switch to common parsing function mmc_of_parse(). Signed-off-by: Dong Aisheng Acked-by: Shawn Guo Signed-off-by: Ulf Hansson --- arch/arm/boot/dts/imx51-apf51dev.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/imx51-apf51dev.dts b/arch/arm/boot/dts/imx51-apf51dev.dts index 93d3ea12328c..0f3fe29b816e 100644 --- a/arch/arm/boot/dts/imx51-apf51dev.dts +++ b/arch/arm/boot/dts/imx51-apf51dev.dts @@ -98,7 +98,7 @@ &esdhc1 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_esdhc1>; - cd-gpios = <&gpio2 29 GPIO_ACTIVE_HIGH>; + cd-gpios = <&gpio2 29 GPIO_ACTIVE_LOW>; bus-width = <4>; status = "okay"; }; -- cgit v1.2.3 From 94d76946859b4bcfa0da373357f14feda2af0622 Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Wed, 22 Jul 2015 20:53:01 +0800 Subject: dts: imx53: fix sd card gpio polarity specified in device tree cd-gpios polarity should be changed to GPIO_ACTIVE_LOW and wp-gpios should be changed to GPIO_ACTIVE_HIGH. Otherwise, the SD may not work properly due to wrong polarity inversion specified in DT after switch to common parsing function mmc_of_parse(). Signed-off-by: Dong Aisheng Acked-by: Shawn Guo Signed-off-by: Ulf Hansson --- arch/arm/boot/dts/imx53-ard.dts | 4 ++-- arch/arm/boot/dts/imx53-m53evk.dts | 4 ++-- arch/arm/boot/dts/imx53-qsb-common.dtsi | 4 ++-- arch/arm/boot/dts/imx53-smd.dts | 4 ++-- arch/arm/boot/dts/imx53-tqma53.dtsi | 4 ++-- arch/arm/boot/dts/imx53-tx53.dtsi | 4 ++-- arch/arm/boot/dts/imx53-voipac-bsb.dts | 4 ++-- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/arch/arm/boot/dts/imx53-ard.dts b/arch/arm/boot/dts/imx53-ard.dts index e9337ad52f59..3bc18835fb4b 100644 --- a/arch/arm/boot/dts/imx53-ard.dts +++ b/arch/arm/boot/dts/imx53-ard.dts @@ -103,8 +103,8 @@ &esdhc1 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_esdhc1>; - cd-gpios = <&gpio1 1 0>; - wp-gpios = <&gpio1 9 0>; + cd-gpios = <&gpio1 1 GPIO_ACTIVE_LOW>; + wp-gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>; status = "okay"; }; diff --git a/arch/arm/boot/dts/imx53-m53evk.dts b/arch/arm/boot/dts/imx53-m53evk.dts index d0e0f57eb432..53f40885c530 100644 --- a/arch/arm/boot/dts/imx53-m53evk.dts +++ b/arch/arm/boot/dts/imx53-m53evk.dts @@ -124,8 +124,8 @@ &esdhc1 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_esdhc1>; - cd-gpios = <&gpio1 1 0>; - wp-gpios = <&gpio1 9 0>; + cd-gpios = <&gpio1 1 GPIO_ACTIVE_LOW>; + wp-gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>; status = "okay"; }; diff --git a/arch/arm/boot/dts/imx53-qsb-common.dtsi b/arch/arm/boot/dts/imx53-qsb-common.dtsi index ab4ba39f2ed9..b0d5542ac829 100644 --- a/arch/arm/boot/dts/imx53-qsb-common.dtsi +++ b/arch/arm/boot/dts/imx53-qsb-common.dtsi @@ -147,8 +147,8 @@ &esdhc3 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_esdhc3>; - cd-gpios = <&gpio3 11 0>; - wp-gpios = <&gpio3 12 0>; + cd-gpios = <&gpio3 11 GPIO_ACTIVE_LOW>; + wp-gpios = <&gpio3 12 GPIO_ACTIVE_HIGH>; bus-width = <8>; status = "okay"; }; diff --git a/arch/arm/boot/dts/imx53-smd.dts b/arch/arm/boot/dts/imx53-smd.dts index 1d325576bcc0..fc89ce1e5763 100644 --- a/arch/arm/boot/dts/imx53-smd.dts +++ b/arch/arm/boot/dts/imx53-smd.dts @@ -41,8 +41,8 @@ &esdhc1 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_esdhc1>; - cd-gpios = <&gpio3 13 0>; - wp-gpios = <&gpio4 11 0>; + cd-gpios = <&gpio3 13 GPIO_ACTIVE_LOW>; + wp-gpios = <&gpio4 11 GPIO_ACTIVE_HIGH>; status = "okay"; }; diff --git a/arch/arm/boot/dts/imx53-tqma53.dtsi b/arch/arm/boot/dts/imx53-tqma53.dtsi index 4f1f0e2868bf..e03373a58760 100644 --- a/arch/arm/boot/dts/imx53-tqma53.dtsi +++ b/arch/arm/boot/dts/imx53-tqma53.dtsi @@ -41,8 +41,8 @@ pinctrl-0 = <&pinctrl_esdhc2>, <&pinctrl_esdhc2_cdwp>; vmmc-supply = <®_3p3v>; - wp-gpios = <&gpio1 2 0>; - cd-gpios = <&gpio1 4 0>; + wp-gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>; + cd-gpios = <&gpio1 4 GPIO_ACTIVE_LOW>; status = "disabled"; }; diff --git a/arch/arm/boot/dts/imx53-tx53.dtsi b/arch/arm/boot/dts/imx53-tx53.dtsi index 704bd72cbfec..d3e50b22064f 100644 --- a/arch/arm/boot/dts/imx53-tx53.dtsi +++ b/arch/arm/boot/dts/imx53-tx53.dtsi @@ -183,7 +183,7 @@ }; &esdhc1 { - cd-gpios = <&gpio3 24 GPIO_ACTIVE_HIGH>; + cd-gpios = <&gpio3 24 GPIO_ACTIVE_LOW>; fsl,wp-controller; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_esdhc1>; @@ -191,7 +191,7 @@ }; &esdhc2 { - cd-gpios = <&gpio3 25 GPIO_ACTIVE_HIGH>; + cd-gpios = <&gpio3 25 GPIO_ACTIVE_LOW>; fsl,wp-controller; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_esdhc2>; diff --git a/arch/arm/boot/dts/imx53-voipac-bsb.dts b/arch/arm/boot/dts/imx53-voipac-bsb.dts index c17d3ad6dba5..fc51b87ad208 100644 --- a/arch/arm/boot/dts/imx53-voipac-bsb.dts +++ b/arch/arm/boot/dts/imx53-voipac-bsb.dts @@ -119,8 +119,8 @@ &esdhc2 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_esdhc2>; - cd-gpios = <&gpio3 25 0>; - wp-gpios = <&gpio2 19 0>; + cd-gpios = <&gpio3 25 GPIO_ACTIVE_LOW>; + wp-gpios = <&gpio2 19 GPIO_ACTIVE_HIGH>; vmmc-supply = <®_3p3v>; status = "okay"; }; -- cgit v1.2.3 From 89c1a8cf63f8c69dfddb6e377c04df8b25ab1c88 Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Wed, 22 Jul 2015 20:53:02 +0800 Subject: dts: imx6: fix sd card gpio polarity specified in device tree cd-gpios polarity should be changed to GPIO_ACTIVE_LOW and wp-gpios should be changed to GPIO_ACTIVE_HIGH. Otherwise, the SD may not work properly due to wrong polarity inversion specified in DT after switch to common parsing function mmc_of_parse(). Signed-off-by: Dong Aisheng Acked-by: Shawn Guo Signed-off-by: Ulf Hansson --- arch/arm/boot/dts/imx6dl-riotboard.dts | 8 ++++---- arch/arm/boot/dts/imx6q-arm2.dts | 5 +++-- arch/arm/boot/dts/imx6q-gk802.dts | 3 ++- arch/arm/boot/dts/imx6q-tbs2910.dts | 4 ++-- arch/arm/boot/dts/imx6qdl-aristainetos.dtsi | 4 ++-- arch/arm/boot/dts/imx6qdl-aristainetos2.dtsi | 4 ++-- arch/arm/boot/dts/imx6qdl-cubox-i.dtsi | 2 +- arch/arm/boot/dts/imx6qdl-dfi-fs700-m60.dtsi | 4 +++- arch/arm/boot/dts/imx6qdl-gw52xx.dtsi | 2 +- arch/arm/boot/dts/imx6qdl-gw53xx.dtsi | 2 +- arch/arm/boot/dts/imx6qdl-gw54xx.dtsi | 2 +- arch/arm/boot/dts/imx6qdl-hummingboard.dtsi | 2 +- arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi | 4 ++-- arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi | 8 ++++---- arch/arm/boot/dts/imx6qdl-rex.dtsi | 4 ++-- arch/arm/boot/dts/imx6qdl-sabreauto.dtsi | 4 ++-- arch/arm/boot/dts/imx6qdl-sabrelite.dtsi | 6 +++--- arch/arm/boot/dts/imx6qdl-sabresd.dtsi | 8 ++++---- arch/arm/boot/dts/imx6qdl-tx6.dtsi | 4 ++-- arch/arm/boot/dts/imx6qdl-wandboard.dtsi | 6 ++++-- arch/arm/boot/dts/imx6sl-evk.dts | 10 +++++----- arch/arm/boot/dts/imx6sx-sabreauto.dts | 4 ++-- arch/arm/boot/dts/imx6sx-sdb.dtsi | 4 ++-- 23 files changed, 55 insertions(+), 49 deletions(-) diff --git a/arch/arm/boot/dts/imx6dl-riotboard.dts b/arch/arm/boot/dts/imx6dl-riotboard.dts index 43cb3fd76be7..5111f5170d53 100644 --- a/arch/arm/boot/dts/imx6dl-riotboard.dts +++ b/arch/arm/boot/dts/imx6dl-riotboard.dts @@ -305,8 +305,8 @@ &usdhc2 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usdhc2>; - cd-gpios = <&gpio1 4 0>; - wp-gpios = <&gpio1 2 0>; + cd-gpios = <&gpio1 4 GPIO_ACTIVE_LOW>; + wp-gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>; vmmc-supply = <®_3p3v>; status = "okay"; }; @@ -314,8 +314,8 @@ &usdhc3 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usdhc3>; - cd-gpios = <&gpio7 0 0>; - wp-gpios = <&gpio7 1 0>; + cd-gpios = <&gpio7 0 GPIO_ACTIVE_LOW>; + wp-gpios = <&gpio7 1 GPIO_ACTIVE_HIGH>; vmmc-supply = <®_3p3v>; status = "okay"; }; diff --git a/arch/arm/boot/dts/imx6q-arm2.dts b/arch/arm/boot/dts/imx6q-arm2.dts index 78df05e9d1ce..d6515f7a56c4 100644 --- a/arch/arm/boot/dts/imx6q-arm2.dts +++ b/arch/arm/boot/dts/imx6q-arm2.dts @@ -11,6 +11,7 @@ */ /dts-v1/; +#include #include "imx6q.dtsi" / { @@ -196,8 +197,8 @@ }; &usdhc3 { - cd-gpios = <&gpio6 11 0>; - wp-gpios = <&gpio6 14 0>; + cd-gpios = <&gpio6 11 GPIO_ACTIVE_LOW>; + wp-gpios = <&gpio6 14 GPIO_ACTIVE_HIGH>; vmmc-supply = <®_3p3v>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usdhc3 diff --git a/arch/arm/boot/dts/imx6q-gk802.dts b/arch/arm/boot/dts/imx6q-gk802.dts index 703539cf36d3..00bd63e63d0c 100644 --- a/arch/arm/boot/dts/imx6q-gk802.dts +++ b/arch/arm/boot/dts/imx6q-gk802.dts @@ -7,6 +7,7 @@ */ /dts-v1/; +#include #include "imx6q.dtsi" / { @@ -161,7 +162,7 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usdhc3>; bus-width = <4>; - cd-gpios = <&gpio6 11 0>; + cd-gpios = <&gpio6 11 GPIO_ACTIVE_LOW>; vmmc-supply = <®_3p3v>; status = "okay"; }; diff --git a/arch/arm/boot/dts/imx6q-tbs2910.dts b/arch/arm/boot/dts/imx6q-tbs2910.dts index a43abfa21e33..5645d52850a7 100644 --- a/arch/arm/boot/dts/imx6q-tbs2910.dts +++ b/arch/arm/boot/dts/imx6q-tbs2910.dts @@ -251,7 +251,7 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usdhc2>; bus-width = <4>; - cd-gpios = <&gpio2 2 GPIO_ACTIVE_HIGH>; + cd-gpios = <&gpio2 2 GPIO_ACTIVE_LOW>; vmmc-supply = <®_3p3v>; status = "okay"; }; @@ -260,7 +260,7 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usdhc3>; bus-width = <4>; - cd-gpios = <&gpio2 0 GPIO_ACTIVE_HIGH>; + cd-gpios = <&gpio2 0 GPIO_ACTIVE_LOW>; wp-gpios = <&gpio2 1 GPIO_ACTIVE_HIGH>; vmmc-supply = <®_3p3v>; status = "okay"; diff --git a/arch/arm/boot/dts/imx6qdl-aristainetos.dtsi b/arch/arm/boot/dts/imx6qdl-aristainetos.dtsi index e6d9195a1da7..f4d6ae564ead 100644 --- a/arch/arm/boot/dts/imx6qdl-aristainetos.dtsi +++ b/arch/arm/boot/dts/imx6qdl-aristainetos.dtsi @@ -173,7 +173,7 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usdhc1>; vmmc-supply = <®_3p3v>; - cd-gpios = <&gpio4 7 GPIO_ACTIVE_HIGH>; + cd-gpios = <&gpio4 7 GPIO_ACTIVE_LOW>; status = "okay"; }; @@ -181,7 +181,7 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usdhc2>; vmmc-supply = <®_3p3v>; - cd-gpios = <&gpio4 8 GPIO_ACTIVE_HIGH>; + cd-gpios = <&gpio4 8 GPIO_ACTIVE_LOW>; status = "okay"; }; diff --git a/arch/arm/boot/dts/imx6qdl-aristainetos2.dtsi b/arch/arm/boot/dts/imx6qdl-aristainetos2.dtsi index 1d85de2befb3..a47a0399a172 100644 --- a/arch/arm/boot/dts/imx6qdl-aristainetos2.dtsi +++ b/arch/arm/boot/dts/imx6qdl-aristainetos2.dtsi @@ -392,7 +392,7 @@ &usdhc1 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usdhc1>; - cd-gpios = <&gpio1 27 GPIO_ACTIVE_HIGH>; + cd-gpios = <&gpio1 27 GPIO_ACTIVE_LOW>; no-1-8-v; status = "okay"; }; @@ -400,7 +400,7 @@ &usdhc2 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usdhc2>; - cd-gpios = <&gpio4 5 GPIO_ACTIVE_HIGH>; + cd-gpios = <&gpio4 5 GPIO_ACTIVE_LOW>; wp-gpios = <&gpio2 10 GPIO_ACTIVE_HIGH>; no-1-8-v; status = "okay"; diff --git a/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi b/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi index 59e5d15e3ec4..ff41f83551de 100644 --- a/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi +++ b/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi @@ -258,6 +258,6 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_cubox_i_usdhc2_aux &pinctrl_cubox_i_usdhc2>; vmmc-supply = <®_3p3v>; - cd-gpios = <&gpio1 4 0>; + cd-gpios = <&gpio1 4 GPIO_ACTIVE_LOW>; status = "okay"; }; diff --git a/arch/arm/boot/dts/imx6qdl-dfi-fs700-m60.dtsi b/arch/arm/boot/dts/imx6qdl-dfi-fs700-m60.dtsi index 2c253d6d20bd..45e7c39e80d5 100644 --- a/arch/arm/boot/dts/imx6qdl-dfi-fs700-m60.dtsi +++ b/arch/arm/boot/dts/imx6qdl-dfi-fs700-m60.dtsi @@ -1,3 +1,5 @@ +#include + / { regulators { compatible = "simple-bus"; @@ -181,7 +183,7 @@ &usdhc2 { /* module slot */ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usdhc2>; - cd-gpios = <&gpio2 2 0>; + cd-gpios = <&gpio2 2 GPIO_ACTIVE_LOW>; status = "okay"; }; diff --git a/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi b/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi index b5756c21ea1d..4493f6e99330 100644 --- a/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi +++ b/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi @@ -318,7 +318,7 @@ &usdhc3 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usdhc3>; - cd-gpios = <&gpio7 0 GPIO_ACTIVE_HIGH>; + cd-gpios = <&gpio7 0 GPIO_ACTIVE_LOW>; vmmc-supply = <®_3p3v>; status = "okay"; }; diff --git a/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi b/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi index 86f03c1b147c..a857d1294609 100644 --- a/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi +++ b/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi @@ -324,7 +324,7 @@ &usdhc3 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usdhc3>; - cd-gpios = <&gpio7 0 GPIO_ACTIVE_HIGH>; + cd-gpios = <&gpio7 0 GPIO_ACTIVE_LOW>; vmmc-supply = <®_3p3v>; status = "okay"; }; diff --git a/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi b/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi index 4a8d97f47759..1afe3385e2d2 100644 --- a/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi +++ b/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi @@ -417,7 +417,7 @@ &usdhc3 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usdhc3>; - cd-gpios = <&gpio7 0 GPIO_ACTIVE_HIGH>; + cd-gpios = <&gpio7 0 GPIO_ACTIVE_LOW>; vmmc-supply = <®_3p3v>; status = "okay"; }; diff --git a/arch/arm/boot/dts/imx6qdl-hummingboard.dtsi b/arch/arm/boot/dts/imx6qdl-hummingboard.dtsi index 62a82f3eba88..6dd0b764e036 100644 --- a/arch/arm/boot/dts/imx6qdl-hummingboard.dtsi +++ b/arch/arm/boot/dts/imx6qdl-hummingboard.dtsi @@ -299,6 +299,6 @@ &pinctrl_hummingboard_usdhc2 >; vmmc-supply = <®_3p3v>; - cd-gpios = <&gpio1 4 0>; + cd-gpios = <&gpio1 4 GPIO_ACTIVE_LOW>; status = "okay"; }; diff --git a/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi b/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi index 3af16dfe417b..d7fe6672d00c 100644 --- a/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi +++ b/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi @@ -453,7 +453,7 @@ &usdhc3 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usdhc3>; - cd-gpios = <&gpio7 0 0>; + cd-gpios = <&gpio7 0 GPIO_ACTIVE_LOW>; vmmc-supply = <®_3p3v>; status = "okay"; }; @@ -461,7 +461,7 @@ &usdhc4 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usdhc4>; - cd-gpios = <&gpio2 6 0>; + cd-gpios = <&gpio2 6 GPIO_ACTIVE_LOW>; vmmc-supply = <®_3p3v>; status = "okay"; }; diff --git a/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi b/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi index 1ce6133b67f5..9e6ecd99b472 100644 --- a/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi +++ b/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi @@ -409,8 +409,8 @@ &usdhc2 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usdhc2>; - cd-gpios = <&gpio1 4 0>; - wp-gpios = <&gpio1 2 0>; + cd-gpios = <&gpio1 4 GPIO_ACTIVE_LOW>; + wp-gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>; status = "disabled"; }; @@ -418,7 +418,7 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usdhc3 &pinctrl_usdhc3_cdwp>; - cd-gpios = <&gpio1 27 0>; - wp-gpios = <&gpio1 29 0>; + cd-gpios = <&gpio1 27 GPIO_ACTIVE_LOW>; + wp-gpios = <&gpio1 29 GPIO_ACTIVE_HIGH>; status = "disabled"; }; diff --git a/arch/arm/boot/dts/imx6qdl-rex.dtsi b/arch/arm/boot/dts/imx6qdl-rex.dtsi index 488a640796ac..3373fd958e95 100644 --- a/arch/arm/boot/dts/imx6qdl-rex.dtsi +++ b/arch/arm/boot/dts/imx6qdl-rex.dtsi @@ -342,7 +342,7 @@ pinctrl-0 = <&pinctrl_usdhc2>; bus-width = <4>; cd-gpios = <&gpio2 2 GPIO_ACTIVE_LOW>; - wp-gpios = <&gpio2 3 GPIO_ACTIVE_LOW>; + wp-gpios = <&gpio2 3 GPIO_ACTIVE_HIGH>; status = "okay"; }; @@ -351,6 +351,6 @@ pinctrl-0 = <&pinctrl_usdhc3>; bus-width = <4>; cd-gpios = <&gpio2 0 GPIO_ACTIVE_LOW>; - wp-gpios = <&gpio2 1 GPIO_ACTIVE_LOW>; + wp-gpios = <&gpio2 1 GPIO_ACTIVE_HIGH>; status = "okay"; }; diff --git a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi index 3b24b12651b2..e329ca5c3322 100644 --- a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi +++ b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi @@ -467,8 +467,8 @@ pinctrl-0 = <&pinctrl_usdhc3>; pinctrl-1 = <&pinctrl_usdhc3_100mhz>; pinctrl-2 = <&pinctrl_usdhc3_200mhz>; - cd-gpios = <&gpio6 15 0>; - wp-gpios = <&gpio1 13 0>; + cd-gpios = <&gpio6 15 GPIO_ACTIVE_LOW>; + wp-gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>; status = "okay"; }; diff --git a/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi b/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi index e00c44f6a0df..782379320517 100644 --- a/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi +++ b/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi @@ -448,8 +448,8 @@ &usdhc3 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usdhc3>; - cd-gpios = <&gpio7 0 0>; - wp-gpios = <&gpio7 1 0>; + cd-gpios = <&gpio7 0 GPIO_ACTIVE_LOW>; + wp-gpios = <&gpio7 1 GPIO_ACTIVE_HIGH>; vmmc-supply = <®_3p3v>; status = "okay"; }; @@ -457,7 +457,7 @@ &usdhc4 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usdhc4>; - cd-gpios = <&gpio2 6 0>; + cd-gpios = <&gpio2 6 GPIO_ACTIVE_LOW>; vmmc-supply = <®_3p3v>; status = "okay"; }; diff --git a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi index a626e6dd8022..944eb81cb2b8 100644 --- a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi +++ b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi @@ -562,8 +562,8 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usdhc2>; bus-width = <8>; - cd-gpios = <&gpio2 2 0>; - wp-gpios = <&gpio2 3 0>; + cd-gpios = <&gpio2 2 GPIO_ACTIVE_LOW>; + wp-gpios = <&gpio2 3 GPIO_ACTIVE_HIGH>; status = "okay"; }; @@ -571,8 +571,8 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usdhc3>; bus-width = <8>; - cd-gpios = <&gpio2 0 0>; - wp-gpios = <&gpio2 1 0>; + cd-gpios = <&gpio2 0 GPIO_ACTIVE_LOW>; + wp-gpios = <&gpio2 1 GPIO_ACTIVE_HIGH>; status = "okay"; }; diff --git a/arch/arm/boot/dts/imx6qdl-tx6.dtsi b/arch/arm/boot/dts/imx6qdl-tx6.dtsi index f02b80b41d4f..da08de324e9e 100644 --- a/arch/arm/boot/dts/imx6qdl-tx6.dtsi +++ b/arch/arm/boot/dts/imx6qdl-tx6.dtsi @@ -680,7 +680,7 @@ pinctrl-0 = <&pinctrl_usdhc1>; bus-width = <4>; no-1-8-v; - cd-gpios = <&gpio7 2 0>; + cd-gpios = <&gpio7 2 GPIO_ACTIVE_LOW>; fsl,wp-controller; status = "okay"; }; @@ -690,7 +690,7 @@ pinctrl-0 = <&pinctrl_usdhc2>; bus-width = <4>; no-1-8-v; - cd-gpios = <&gpio7 3 0>; + cd-gpios = <&gpio7 3 GPIO_ACTIVE_LOW>; fsl,wp-controller; status = "okay"; }; diff --git a/arch/arm/boot/dts/imx6qdl-wandboard.dtsi b/arch/arm/boot/dts/imx6qdl-wandboard.dtsi index 5fb091675582..9e096d811bed 100644 --- a/arch/arm/boot/dts/imx6qdl-wandboard.dtsi +++ b/arch/arm/boot/dts/imx6qdl-wandboard.dtsi @@ -9,6 +9,8 @@ * */ +#include + / { regulators { compatible = "simple-bus"; @@ -250,13 +252,13 @@ &usdhc1 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usdhc1>; - cd-gpios = <&gpio1 2 0>; + cd-gpios = <&gpio1 2 GPIO_ACTIVE_LOW>; status = "okay"; }; &usdhc3 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usdhc3>; - cd-gpios = <&gpio3 9 0>; + cd-gpios = <&gpio3 9 GPIO_ACTIVE_LOW>; status = "okay"; }; diff --git a/arch/arm/boot/dts/imx6sl-evk.dts b/arch/arm/boot/dts/imx6sl-evk.dts index 945887d3fdb3..b84dff2e94ea 100644 --- a/arch/arm/boot/dts/imx6sl-evk.dts +++ b/arch/arm/boot/dts/imx6sl-evk.dts @@ -617,8 +617,8 @@ pinctrl-1 = <&pinctrl_usdhc1_100mhz>; pinctrl-2 = <&pinctrl_usdhc1_200mhz>; bus-width = <8>; - cd-gpios = <&gpio4 7 0>; - wp-gpios = <&gpio4 6 0>; + cd-gpios = <&gpio4 7 GPIO_ACTIVE_LOW>; + wp-gpios = <&gpio4 6 GPIO_ACTIVE_HIGH>; status = "okay"; }; @@ -627,8 +627,8 @@ pinctrl-0 = <&pinctrl_usdhc2>; pinctrl-1 = <&pinctrl_usdhc2_100mhz>; pinctrl-2 = <&pinctrl_usdhc2_200mhz>; - cd-gpios = <&gpio5 0 0>; - wp-gpios = <&gpio4 29 0>; + cd-gpios = <&gpio5 0 GPIO_ACTIVE_LOW>; + wp-gpios = <&gpio4 29 GPIO_ACTIVE_HIGH>; status = "okay"; }; @@ -637,6 +637,6 @@ pinctrl-0 = <&pinctrl_usdhc3>; pinctrl-1 = <&pinctrl_usdhc3_100mhz>; pinctrl-2 = <&pinctrl_usdhc3_200mhz>; - cd-gpios = <&gpio3 22 0>; + cd-gpios = <&gpio3 22 GPIO_ACTIVE_LOW>; status = "okay"; }; diff --git a/arch/arm/boot/dts/imx6sx-sabreauto.dts b/arch/arm/boot/dts/imx6sx-sabreauto.dts index e3c0b63c2205..115f3fd78971 100644 --- a/arch/arm/boot/dts/imx6sx-sabreauto.dts +++ b/arch/arm/boot/dts/imx6sx-sabreauto.dts @@ -49,7 +49,7 @@ pinctrl-1 = <&pinctrl_usdhc3_100mhz>; pinctrl-2 = <&pinctrl_usdhc3_200mhz>; bus-width = <8>; - cd-gpios = <&gpio7 10 GPIO_ACTIVE_HIGH>; + cd-gpios = <&gpio7 10 GPIO_ACTIVE_LOW>; wp-gpios = <&gpio3 19 GPIO_ACTIVE_HIGH>; keep-power-in-suspend; enable-sdio-wakeup; @@ -61,7 +61,7 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usdhc4>; bus-width = <8>; - cd-gpios = <&gpio7 11 GPIO_ACTIVE_HIGH>; + cd-gpios = <&gpio7 11 GPIO_ACTIVE_LOW>; no-1-8-v; keep-power-in-suspend; enable-sdio-wakup; diff --git a/arch/arm/boot/dts/imx6sx-sdb.dtsi b/arch/arm/boot/dts/imx6sx-sdb.dtsi index cef04cef3a80..ac88c3467078 100644 --- a/arch/arm/boot/dts/imx6sx-sdb.dtsi +++ b/arch/arm/boot/dts/imx6sx-sdb.dtsi @@ -293,7 +293,7 @@ pinctrl-1 = <&pinctrl_usdhc3_100mhz>; pinctrl-2 = <&pinctrl_usdhc3_200mhz>; bus-width = <8>; - cd-gpios = <&gpio2 10 GPIO_ACTIVE_HIGH>; + cd-gpios = <&gpio2 10 GPIO_ACTIVE_LOW>; wp-gpios = <&gpio2 15 GPIO_ACTIVE_HIGH>; keep-power-in-suspend; enable-sdio-wakeup; @@ -304,7 +304,7 @@ &usdhc4 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usdhc4>; - cd-gpios = <&gpio6 21 GPIO_ACTIVE_HIGH>; + cd-gpios = <&gpio6 21 GPIO_ACTIVE_LOW>; wp-gpios = <&gpio6 20 GPIO_ACTIVE_HIGH>; status = "okay"; }; -- cgit v1.2.3 From cf75eb15be2bdd054a76aeef6458beaa4a6ab770 Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Wed, 22 Jul 2015 20:53:03 +0800 Subject: dts: imx25: fix sd card gpio polarity specified in device tree cd-gpios polarity should be changed to GPIO_ACTIVE_LOW and wp-gpios should be changed to GPIO_ACTIVE_HIGH. Otherwise, the SD may not work properly due to wrong polarity inversion specified in DT after switch to common parsing function mmc_of_parse(). Signed-off-by: Dong Aisheng Acked-by: Shawn Guo Signed-off-by: Ulf Hansson --- arch/arm/boot/dts/imx25-pdk.dts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/imx25-pdk.dts b/arch/arm/boot/dts/imx25-pdk.dts index dd45e6971bc3..9351296356dc 100644 --- a/arch/arm/boot/dts/imx25-pdk.dts +++ b/arch/arm/boot/dts/imx25-pdk.dts @@ -10,6 +10,7 @@ */ /dts-v1/; +#include #include #include "imx25.dtsi" @@ -114,8 +115,8 @@ &esdhc1 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_esdhc1>; - cd-gpios = <&gpio2 1 0>; - wp-gpios = <&gpio2 0 0>; + cd-gpios = <&gpio2 1 GPIO_ACTIVE_LOW>; + wp-gpios = <&gpio2 0 GPIO_ACTIVE_HIGH>; status = "okay"; }; -- cgit v1.2.3 From 1cd55947f2bfdb99a2a741d65c7463d106ef9132 Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Wed, 22 Jul 2015 20:53:04 +0800 Subject: dts: imx7: fix sd card gpio polarity specified in device tree cd-gpios polarity should be changed to GPIO_ACTIVE_LOW and wp-gpios should be changed to GPIO_ACTIVE_HIGH. Otherwise, the SD may not work properly due to wrong polarity inversion specified in DT after switch to common parsing function mmc_of_parse(). Signed-off-by: Dong Aisheng Acked-by: Shawn Guo Signed-off-by: Ulf Hansson --- arch/arm/boot/dts/imx7d-sdb.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/imx7d-sdb.dts b/arch/arm/boot/dts/imx7d-sdb.dts index 4d1a4b977d84..fdd1d7c9a5cc 100644 --- a/arch/arm/boot/dts/imx7d-sdb.dts +++ b/arch/arm/boot/dts/imx7d-sdb.dts @@ -234,8 +234,8 @@ &usdhc1 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usdhc1>; - cd-gpios = <&gpio5 0 0>; - wp-gpios = <&gpio5 1 0>; + cd-gpios = <&gpio5 0 GPIO_ACTIVE_LOW>; + wp-gpios = <&gpio5 1 GPIO_ACTIVE_HIGH>; enable-sdio-wakeup; keep-power-in-suspend; status = "okay"; -- cgit v1.2.3 From 4800e87a2ee886c1972deb73f057d1a6541edb36 Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Wed, 22 Jul 2015 20:53:05 +0800 Subject: mmc: sdhci-esdhc-imx: fix cd regression for dt platform Current card detect probe process is that when driver finds a valid ESDHC_CD_GPIO, it will clear the quirk SDHCI_QUIRK_BROKEN_CARD_DETECTION which is set by default for all esdhc/usdhc controllers. Then host driver will know there's a valid card detect function. Commit 8d86e4fcccf6 ("mmc: sdhci-esdhc-imx: Call mmc_of_parse()") breaks GPIO CD function for dt platform that it will return directly when find ESDHC_CD_GPIO for dt platform which result in the later wrongly to keep SDHCI_QUIRK_BROKEN_CARD_DETECTION for all dt platforms. Then MMC_CAP_NEEDS_POLL will be used instead even there's a valid GPIO card detect. This patch adds back this function and follows the original approach to clear the quirk if find an valid CD GPIO for dt platforms. Fixes: 8d86e4fcccf6 ("mmc: sdhci-esdhc-imx: Call mmc_of_parse()") Signed-off-by: Dong Aisheng Reviewed-by: Johan Derycke Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-esdhc-imx.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index faf0cb910c96..48153917ed08 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -881,6 +881,7 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, struct esdhc_platform_data *boarddata) { struct device_node *np = pdev->dev.of_node; + int ret; if (!np) return -ENODEV; @@ -917,7 +918,14 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, mmc_of_parse_voltage(np, &host->ocr_mask); /* call to generic mmc_of_parse to support additional capabilities */ - return mmc_of_parse(host->mmc); + ret = mmc_of_parse(host->mmc); + if (ret) + return ret; + + if (!IS_ERR_VALUE(mmc_gpio_get_cd(host->mmc))) + host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION; + + return 0; } #else static inline int -- cgit v1.2.3 From 91fa4252878afccc9e75edd84f31047899ddd1b7 Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Wed, 22 Jul 2015 20:53:06 +0800 Subject: mmc: sdhci-esdhc-imx: move all non dt probe code into one function This is an incremental fix of commit e62bd351b("mmc: sdhci-esdhc-imx: Do not break platform data boards"). After commit 8d86e4fcccf6 ("mmc: sdhci-esdhc-imx: Call mmc_of_parse()"), we do not need to run the check of boarddata->wp_type/cd_type/max_bus_width again for dt platform since those are already handled by mmc_of_parse(). Current code only exclude the checking of wp_type for dt platform which does not make sense. This patch moves all non dt probe code into one function. Besides, since we only support SD3.0/eMMC HS200 for dt platform, the support_vsel checking and ultra high speed pinctrl state are also merged into sdhci_esdhc_imx_probe_dt. Then we have two separately probe function for dt and non dt type. This can make the driver probe more clearly. Signed-off-by: Dong Aisheng Reviewed-by: Johan Derycke Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-esdhc-imx.c | 179 +++++++++++++++++++------------------ 1 file changed, 94 insertions(+), 85 deletions(-) diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 48153917ed08..10f03ee027ac 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -878,14 +878,12 @@ static const struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = { static int sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, struct sdhci_host *host, - struct esdhc_platform_data *boarddata) + struct pltfm_imx_data *imx_data) { struct device_node *np = pdev->dev.of_node; + struct esdhc_platform_data *boarddata = &imx_data->boarddata; int ret; - if (!np) - return -ENODEV; - if (of_get_property(np, "non-removable", NULL)) boarddata->cd_type = ESDHC_CD_PERMANENT; @@ -917,6 +915,26 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, mmc_of_parse_voltage(np, &host->ocr_mask); + /* sdr50 and sdr104 needs work on 1.8v signal voltage */ + if ((boarddata->support_vsel) && esdhc_is_usdhc(imx_data) && + !IS_ERR(imx_data->pins_default)) { + imx_data->pins_100mhz = pinctrl_lookup_state(imx_data->pinctrl, + ESDHC_PINCTRL_STATE_100MHZ); + imx_data->pins_200mhz = pinctrl_lookup_state(imx_data->pinctrl, + ESDHC_PINCTRL_STATE_200MHZ); + if (IS_ERR(imx_data->pins_100mhz) || + IS_ERR(imx_data->pins_200mhz)) { + dev_warn(mmc_dev(host->mmc), + "could not get ultra high speed state, work on normal mode\n"); + /* + * fall back to not support uhs by specify no 1.8v quirk + */ + host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V; + } + } else { + host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V; + } + /* call to generic mmc_of_parse to support additional capabilities */ ret = mmc_of_parse(host->mmc); if (ret) @@ -931,22 +949,85 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, static inline int sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, struct sdhci_host *host, - struct esdhc_platform_data *boarddata) + struct pltfm_imx_data *imx_data) { return -ENODEV; } #endif +static int sdhci_esdhc_imx_probe_nondt(struct platform_device *pdev, + struct sdhci_host *host, + struct pltfm_imx_data *imx_data) +{ + struct esdhc_platform_data *boarddata = &imx_data->boarddata; + int err; + + if (!host->mmc->parent->platform_data) { + dev_err(mmc_dev(host->mmc), "no board data!\n"); + return -EINVAL; + } + + imx_data->boarddata = *((struct esdhc_platform_data *) + host->mmc->parent->platform_data); + /* write_protect */ + if (boarddata->wp_type == ESDHC_WP_GPIO) { + err = mmc_gpio_request_ro(host->mmc, boarddata->wp_gpio); + if (err) { + dev_err(mmc_dev(host->mmc), + "failed to request write-protect gpio!\n"); + return err; + } + host->mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH; + } + + /* card_detect */ + switch (boarddata->cd_type) { + case ESDHC_CD_GPIO: + err = mmc_gpio_request_cd(host->mmc, boarddata->cd_gpio, 0); + if (err) { + dev_err(mmc_dev(host->mmc), + "failed to request card-detect gpio!\n"); + return err; + } + /* fall through */ + + case ESDHC_CD_CONTROLLER: + /* we have a working card_detect back */ + host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION; + break; + + case ESDHC_CD_PERMANENT: + host->mmc->caps |= MMC_CAP_NONREMOVABLE; + break; + + case ESDHC_CD_NONE: + break; + } + + switch (boarddata->max_bus_width) { + case 8: + host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_4_BIT_DATA; + break; + case 4: + host->mmc->caps |= MMC_CAP_4_BIT_DATA; + break; + case 1: + default: + host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA; + break; + } + + return 0; +} + static int sdhci_esdhc_imx_probe(struct platform_device *pdev) { const struct of_device_id *of_id = of_match_device(imx_esdhc_dt_ids, &pdev->dev); struct sdhci_pltfm_host *pltfm_host; struct sdhci_host *host; - struct esdhc_platform_data *boarddata; int err; struct pltfm_imx_data *imx_data; - bool dt = true; host = sdhci_pltfm_init(pdev, &sdhci_esdhc_imx_pdata, 0); if (IS_ERR(host)) @@ -1038,84 +1119,12 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) if (imx_data->socdata->flags & ESDHC_FLAG_ERR004536) host->quirks |= SDHCI_QUIRK_BROKEN_ADMA; - boarddata = &imx_data->boarddata; - if (sdhci_esdhc_imx_probe_dt(pdev, host, boarddata) < 0) { - if (!host->mmc->parent->platform_data) { - dev_err(mmc_dev(host->mmc), "no board data!\n"); - err = -EINVAL; - goto disable_clk; - } - imx_data->boarddata = *((struct esdhc_platform_data *) - host->mmc->parent->platform_data); - dt = false; - } - /* write_protect */ - if (boarddata->wp_type == ESDHC_WP_GPIO && !dt) { - err = mmc_gpio_request_ro(host->mmc, boarddata->wp_gpio); - if (err) { - dev_err(mmc_dev(host->mmc), - "failed to request write-protect gpio!\n"); - goto disable_clk; - } - host->mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH; - } - - /* card_detect */ - switch (boarddata->cd_type) { - case ESDHC_CD_GPIO: - if (dt) - break; - err = mmc_gpio_request_cd(host->mmc, boarddata->cd_gpio, 0); - if (err) { - dev_err(mmc_dev(host->mmc), - "failed to request card-detect gpio!\n"); - goto disable_clk; - } - /* fall through */ - - case ESDHC_CD_CONTROLLER: - /* we have a working card_detect back */ - host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION; - break; - - case ESDHC_CD_PERMANENT: - host->mmc->caps |= MMC_CAP_NONREMOVABLE; - break; - - case ESDHC_CD_NONE: - break; - } - - switch (boarddata->max_bus_width) { - case 8: - host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_4_BIT_DATA; - break; - case 4: - host->mmc->caps |= MMC_CAP_4_BIT_DATA; - break; - case 1: - default: - host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA; - break; - } - - /* sdr50 and sdr104 needs work on 1.8v signal voltage */ - if ((boarddata->support_vsel) && esdhc_is_usdhc(imx_data) && - !IS_ERR(imx_data->pins_default)) { - imx_data->pins_100mhz = pinctrl_lookup_state(imx_data->pinctrl, - ESDHC_PINCTRL_STATE_100MHZ); - imx_data->pins_200mhz = pinctrl_lookup_state(imx_data->pinctrl, - ESDHC_PINCTRL_STATE_200MHZ); - if (IS_ERR(imx_data->pins_100mhz) || - IS_ERR(imx_data->pins_200mhz)) { - dev_warn(mmc_dev(host->mmc), - "could not get ultra high speed state, work on normal mode\n"); - /* fall back to not support uhs by specify no 1.8v quirk */ - host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V; - } - } else { - host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V; - } + if (of_id) + err = sdhci_esdhc_imx_probe_dt(pdev, host, imx_data); + else + err = sdhci_esdhc_imx_probe_nondt(pdev, host, imx_data); + if (err) + goto disable_clk; err = sdhci_add_host(host); if (err) -- cgit v1.2.3 From 5924175755a0ed902d91f2f2660e914032fa63e5 Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Wed, 22 Jul 2015 20:53:07 +0800 Subject: mmc: sdhci: make max-frequency property in device tree work Device tree provides option to specify the max freqency with property "max-frequency" in dts and common parse function mmc_of_parse() will parse it and use this value to set host->f_max to tell the MMC core the maxinum frequency the host works. However, current sdhci driver will finally overwrite this value with host->max_clk regardless of the max-frequency property. This patch makes sure not overwrite the max-frequency set from device tree and do basic sanity check. Signed-off-by: Dong Aisheng Reviewed-by: Johan Derycke Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 655900f55244..1dbe93232030 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -2866,6 +2866,7 @@ int sdhci_add_host(struct sdhci_host *host) u32 max_current_caps; unsigned int ocr_avail; unsigned int override_timeout_clk; + u32 max_clk; int ret; WARN_ON(host == NULL); @@ -3050,18 +3051,22 @@ int sdhci_add_host(struct sdhci_host *host) * Set host parameters. */ mmc->ops = &sdhci_ops; - mmc->f_max = host->max_clk; + max_clk = host->max_clk; + if (host->ops->get_min_clock) mmc->f_min = host->ops->get_min_clock(host); else if (host->version >= SDHCI_SPEC_300) { if (host->clk_mul) { mmc->f_min = (host->max_clk * host->clk_mul) / 1024; - mmc->f_max = host->max_clk * host->clk_mul; + max_clk = host->max_clk * host->clk_mul; } else mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_300; } else mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200; + if (!mmc->f_max || (mmc->f_max && (mmc->f_max > max_clk))) + mmc->f_max = max_clk; + if (!(host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)) { host->timeout_clk = (caps[0] & SDHCI_TIMEOUT_CLK_MASK) >> SDHCI_TIMEOUT_CLK_SHIFT; -- cgit v1.2.3 From 2e05d66b6b6cbe6018c8dcc15a379d913efdea83 Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Wed, 22 Jul 2015 20:53:08 +0800 Subject: mmc: sdhci-esdhc-imx: remove duplicated dts parsing After commit 8d86e4fcccf6 ("mmc: sdhci-esdhc-imx: Call mmc_of_parse()"), we do not need those duplicated parsing anymore. Note: fsl,cd-controller is also deleted due to the driver does not support controller card detection anymore after switch to runtime pm. And there's no user of it right now in device tree. wp-gpios is kept because we're still support fsl,wp-controller, so we need a way to check if it's gpio wp or controller wp. Signed-off-by: Dong Aisheng Reviewed-by: Johan Derycke Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-esdhc-imx.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 10f03ee027ac..1b0e61847e73 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -884,27 +884,13 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, struct esdhc_platform_data *boarddata = &imx_data->boarddata; int ret; - if (of_get_property(np, "non-removable", NULL)) - boarddata->cd_type = ESDHC_CD_PERMANENT; - - if (of_get_property(np, "fsl,cd-controller", NULL)) - boarddata->cd_type = ESDHC_CD_CONTROLLER; - if (of_get_property(np, "fsl,wp-controller", NULL)) boarddata->wp_type = ESDHC_WP_CONTROLLER; - boarddata->cd_gpio = of_get_named_gpio(np, "cd-gpios", 0); - if (gpio_is_valid(boarddata->cd_gpio)) - boarddata->cd_type = ESDHC_CD_GPIO; - boarddata->wp_gpio = of_get_named_gpio(np, "wp-gpios", 0); if (gpio_is_valid(boarddata->wp_gpio)) boarddata->wp_type = ESDHC_WP_GPIO; - of_property_read_u32(np, "bus-width", &boarddata->max_bus_width); - - of_property_read_u32(np, "max-frequency", &boarddata->f_max); - if (of_find_property(np, "no-1-8-v", NULL)) boarddata->support_vsel = false; else -- cgit v1.2.3 From a3bd4f989f532694337dd30538b635d5213ab86a Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Wed, 22 Jul 2015 20:53:09 +0800 Subject: mmc: sdhci-esdhc-imx: clear f_max in boarddata After commit 8d86e4fcccf6 ("mmc: sdhci-esdhc-imx: Call mmc_of_parse()"), it's not used anymore. Signed-off-by: Dong Aisheng Reviewed-by: Johan Derycke Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-esdhc-imx.c | 7 +------ include/linux/platform_data/mmc-esdhc-imx.h | 1 - 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 1b0e61847e73..c6b9f6492e1a 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -581,13 +581,8 @@ static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg) static unsigned int esdhc_pltfm_get_max_clock(struct sdhci_host *host) { struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); - struct pltfm_imx_data *imx_data = pltfm_host->priv; - struct esdhc_platform_data *boarddata = &imx_data->boarddata; - if (boarddata->f_max && (boarddata->f_max < pltfm_host->clock)) - return boarddata->f_max; - else - return pltfm_host->clock; + return pltfm_host->clock; } static unsigned int esdhc_pltfm_get_min_clock(struct sdhci_host *host) diff --git a/include/linux/platform_data/mmc-esdhc-imx.h b/include/linux/platform_data/mmc-esdhc-imx.h index 75f70f6ac137..e1571efa3f2b 100644 --- a/include/linux/platform_data/mmc-esdhc-imx.h +++ b/include/linux/platform_data/mmc-esdhc-imx.h @@ -43,7 +43,6 @@ struct esdhc_platform_data { enum wp_types wp_type; enum cd_types cd_type; int max_bus_width; - unsigned int f_max; bool support_vsel; unsigned int delay_line; }; -- cgit v1.2.3 From cae13e792f8f863a60cee2cfdbe704ea84cf2a07 Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Wed, 22 Jul 2015 20:53:10 +0800 Subject: dts: mmc: fsl-imx-esdhc: remove fsl,cd-controller support It's not supported by driver anymore after using runtime pm and there's no user of it, so delete it now. Signed-off-by: Dong Aisheng Reviewed-by: Johan Derycke Signed-off-by: Ulf Hansson --- Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt index 5d0376b8f202..211e7785f4d2 100644 --- a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt +++ b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt @@ -17,7 +17,6 @@ Required properties: "fsl,imx6sx-usdhc" Optional properties: -- fsl,cd-controller : Indicate to use controller internal card detection - fsl,wp-controller : Indicate to use controller internal write protection - fsl,delay-line : Specify the number of delay cells for override mode. This is used to set the clock delay for DLL(Delay Line) on override mode @@ -35,7 +34,6 @@ esdhc@70004000 { compatible = "fsl,imx51-esdhc"; reg = <0x70004000 0x4000>; interrupts = <1>; - fsl,cd-controller; fsl,wp-controller; }; -- cgit v1.2.3 From 9cd76049f0d90ae241f5ad80e311489824527000 Mon Sep 17 00:00:00 2001 From: Jingju Hou Date: Thu, 23 Jul 2015 17:56:23 +0800 Subject: mmc: sdhci-pxav3: fix platform_data is not initialized pdev->dev.platform_data is not initialized if match is true in function sdhci_pxav3_probe. Just local variable pdata is assigned the return value from function pxav3_get_mmc_pdata(). static int sdhci_pxav3_probe(struct platform_device *pdev) { struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data; ... if (match) { ret = mmc_of_parse(host->mmc); if (ret) goto err_of_parse; sdhci_get_of_property(pdev); pdata = pxav3_get_mmc_pdata(dev); } ... } Signed-off-by: Jingju Hou Fixes: b650352dd3df("mmc: sdhci-pxa: Add device tree support") Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-pxav3.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c index 9cd5fc62f130..946d37f94a31 100644 --- a/drivers/mmc/host/sdhci-pxav3.c +++ b/drivers/mmc/host/sdhci-pxav3.c @@ -411,6 +411,7 @@ static int sdhci_pxav3_probe(struct platform_device *pdev) goto err_of_parse; sdhci_get_of_property(pdev); pdata = pxav3_get_mmc_pdata(dev); + pdev->dev.platform_data = pdata; } else if (pdata) { /* on-chip device */ if (pdata->flags & PXA_FLAG_CARD_PERMANENT) -- cgit v1.2.3 From 8a0a5da6d9cbf1b142115ff6e6b253a82633c3d9 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 24 Jul 2015 16:13:43 +0200 Subject: x86/mm: Fix newly introduced printk format warnings Signed-off-by: Thomas Gleixner --- arch/x86/mm/ioremap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c index b9d4a33017fd..b9c78f3bcd67 100644 --- a/arch/x86/mm/ioremap.c +++ b/arch/x86/mm/ioremap.c @@ -118,8 +118,8 @@ static void __iomem *__ioremap_caller(resource_size_t phys_addr, last_pfn = last_addr >> PAGE_SHIFT; if (walk_system_ram_range(pfn, last_pfn - pfn + 1, NULL, __ioremap_check_ram) == 1) { - WARN_ONCE(1, "ioremap on RAM at 0x%llx - 0x%llx\n", - phys_addr, last_addr); + WARN_ONCE(1, "ioremap on RAM at %pa - %pa\n", + &phys_addr, &last_addr); return NULL; } -- cgit v1.2.3 From c0c3322e98029e752526d906d9e3a680ed213c03 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 24 Jul 2015 14:16:43 +0200 Subject: x86/asm/entry/32: Revert 'Do not use R9 in SYSCALL32' commit This change reverts most of commit 53e9accf0f 'Do not use R9 in SYSCALL32'. I don't yet understand how, but code in that commit sometimes fails to preserve EBP. See https://bugzilla.kernel.org/show_bug.cgi?id=101061 "Problems while executing 32-bit code on AMD64" Reported-and-tested-by: Krzysztof A. Sobiecki Signed-off-by: Denys Vlasenko Cc: Linus Torvalds Cc: Steven Rostedt Cc: Borislav Petkov Cc: Andy Lutomirski Cc: Oleg Nesterov Cc: Frederic Weisbecker Cc: Alexei Starovoitov Cc: Will Drewry Cc: Kees Cook CC: x86@kernel.org Link: http://lkml.kernel.org/r/1437740203-11552-1-git-send-email-dvlasenk@redhat.com Signed-off-by: Thomas Gleixner --- arch/x86/entry/entry_64_compat.S | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/arch/x86/entry/entry_64_compat.S b/arch/x86/entry/entry_64_compat.S index bb187a6a877c..5a1844765a7a 100644 --- a/arch/x86/entry/entry_64_compat.S +++ b/arch/x86/entry/entry_64_compat.S @@ -205,7 +205,6 @@ sysexit_from_sys_call: movl RDX(%rsp), %edx /* arg3 */ movl RSI(%rsp), %ecx /* arg4 */ movl RDI(%rsp), %r8d /* arg5 */ - movl %ebp, %r9d /* arg6 */ .endm .macro auditsys_exit exit @@ -236,6 +235,7 @@ sysexit_from_sys_call: sysenter_auditsys: auditsys_entry_common + movl %ebp, %r9d /* reload 6th syscall arg */ jmp sysenter_dispatch sysexit_audit: @@ -336,7 +336,7 @@ ENTRY(entry_SYSCALL_compat) * 32-bit zero extended: */ ASM_STAC -1: movl (%r8), %ebp +1: movl (%r8), %r9d _ASM_EXTABLE(1b, ia32_badarg) ASM_CLAC orl $TS_COMPAT, ASM_THREAD_INFO(TI_status, %rsp, SIZEOF_PTREGS) @@ -346,7 +346,7 @@ ENTRY(entry_SYSCALL_compat) cstar_do_call: /* 32-bit syscall -> 64-bit C ABI argument conversion */ movl %edi, %r8d /* arg5 */ - movl %ebp, %r9d /* arg6 */ + /* r9 already loaded */ /* arg6 */ xchg %ecx, %esi /* rsi:arg2, rcx:arg4 */ movl %ebx, %edi /* arg1 */ movl %edx, %edx /* arg3 (zero extension) */ @@ -358,7 +358,6 @@ cstar_dispatch: call *ia32_sys_call_table(, %rax, 8) movq %rax, RAX(%rsp) 1: - movl RCX(%rsp), %ebp DISABLE_INTERRUPTS(CLBR_NONE) TRACE_IRQS_OFF testl $_TIF_ALLWORK_MASK, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS) @@ -392,7 +391,9 @@ sysretl_from_sys_call: #ifdef CONFIG_AUDITSYSCALL cstar_auditsys: + movl %r9d, R9(%rsp) /* register to be clobbered by call */ auditsys_entry_common + movl R9(%rsp), %r9d /* reload 6th syscall arg */ jmp cstar_dispatch sysretl_audit: @@ -404,14 +405,16 @@ cstar_tracesys: testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT), ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS) jz cstar_auditsys #endif + xchgl %r9d, %ebp SAVE_EXTRA_REGS xorl %eax, %eax /* Do not leak kernel information */ movq %rax, R11(%rsp) movq %rax, R10(%rsp) - movq %rax, R9(%rsp) + movq %r9, R9(%rsp) movq %rax, R8(%rsp) movq %rsp, %rdi /* &pt_regs -> arg1 */ call syscall_trace_enter + movl R9(%rsp), %r9d /* Reload arg registers from stack. (see sysenter_tracesys) */ movl RCX(%rsp), %ecx @@ -421,6 +424,7 @@ cstar_tracesys: movl %eax, %eax /* zero extension */ RESTORE_EXTRA_REGS + xchgl %ebp, %r9d jmp cstar_do_call END(entry_SYSCALL_compat) -- cgit v1.2.3 From f6ee9b582d2db652497b73c1f117591dfb6d3a90 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 24 Jul 2015 15:01:08 +0200 Subject: spi: imx: Fix small DMA transfers DMA transfers must be greater than the watermark level size. spi_imx->rx_wml and spi_imx->tx_wml contain the watermark level in 32bit words whereas struct spi_transfer contains the transfer len in bytes. Fix the check if DMA is possible for a transfer accordingly. This fixes transfers with sizes between 33 and 128 bytes for which previously was claimed that DMA is possible. Fixes: f62caccd12c17e4 (spi: spi-imx: add DMA support) Signed-off-by: Sascha Hauer Cc: stable@vger.kernel.org Signed-off-by: Mark Brown --- drivers/spi/spi-imx.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index eb7d3a6fb14c..f9deb84e4e55 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -201,8 +201,9 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi, { struct spi_imx_data *spi_imx = spi_master_get_devdata(master); - if (spi_imx->dma_is_inited && (transfer->len > spi_imx->rx_wml) - && (transfer->len > spi_imx->tx_wml)) + if (spi_imx->dma_is_inited + && transfer->len > spi_imx->rx_wml * sizeof(u32) + && transfer->len > spi_imx->tx_wml * sizeof(u32)) return true; return false; } -- cgit v1.2.3 From b38ebd1d4b6656582b8c16358bb88d059d28b794 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 22 Jul 2015 14:56:39 -0700 Subject: Input: LEDs - skip unnamed LEDs Devices may declare more LEDs than what is known to input-leds (HID does this for some devices). Instead of showing ugly warnings on connect and, even worse, oopsing on disconnect, let's simply ignore LEDs that are not known to us. Reported-and-tested-by: Vlastimil Babka Signed-off-by: Dmitry Torokhov --- drivers/input/input-leds.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/input/input-leds.c b/drivers/input/input-leds.c index 074a65ed17bb..766bf2660116 100644 --- a/drivers/input/input-leds.c +++ b/drivers/input/input-leds.c @@ -71,6 +71,18 @@ static void input_leds_event(struct input_handle *handle, unsigned int type, { } +static int input_leds_get_count(struct input_dev *dev) +{ + unsigned int led_code; + int count = 0; + + for_each_set_bit(led_code, dev->ledbit, LED_CNT) + if (input_led_info[led_code].name) + count++; + + return count; +} + static int input_leds_connect(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id) @@ -81,7 +93,7 @@ static int input_leds_connect(struct input_handler *handler, int led_no; int error; - num_leds = bitmap_weight(dev->ledbit, LED_CNT); + num_leds = input_leds_get_count(dev); if (!num_leds) return -ENXIO; @@ -112,7 +124,7 @@ static int input_leds_connect(struct input_handler *handler, led->handle = &leds->handle; led->code = led_code; - if (WARN_ON(!input_led_info[led_code].name)) + if (!input_led_info[led_code].name) continue; led->cdev.name = kasprintf(GFP_KERNEL, "%s::%s", -- cgit v1.2.3 From 8b5a359c5b3e631f17eeb1dcb930474000d33d49 Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Fri, 24 Jul 2015 09:08:53 -0700 Subject: Input: goodix - fix touch coordinates on WinBook TW100 and TW700 The touchscreen on the WinBook TW100 and TW700 don't match the default display, with 0,0 touches being reported when touching at the bottom right of the screen. 1280,800 0,800 +-------------+ | | | | | | +-------------+ 1280,0 0,0 It's unfortunately impossible to detect this problem with data from the DSDT, or other auxiliary metadata, so fallback to quirking this specific model of tablet instead. Signed-off-by: Bastien Nocera Reviewed-by: Benjamin Tissoires Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/goodix.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c index b4d12e29abff..e36162b28c2a 100644 --- a/drivers/input/touchscreen/goodix.c +++ b/drivers/input/touchscreen/goodix.c @@ -15,6 +15,7 @@ */ #include +#include #include #include #include @@ -34,6 +35,7 @@ struct goodix_ts_data { int abs_y_max; unsigned int max_touch_num; unsigned int int_trigger_type; + bool rotated_screen; }; #define GOODIX_MAX_HEIGHT 4096 @@ -60,6 +62,30 @@ static const unsigned long goodix_irq_flags[] = { IRQ_TYPE_LEVEL_HIGH, }; +/* + * Those tablets have their coordinates origin at the bottom right + * of the tablet, as if rotated 180 degrees + */ +static const struct dmi_system_id rotated_screen[] = { +#if defined(CONFIG_DMI) && defined(CONFIG_X86) + { + .ident = "WinBook TW100", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "WinBook"), + DMI_MATCH(DMI_PRODUCT_NAME, "TW100") + } + }, + { + .ident = "WinBook TW700", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "WinBook"), + DMI_MATCH(DMI_PRODUCT_NAME, "TW700") + }, + }, +#endif + {} +}; + /** * goodix_i2c_read - read data from a register of the i2c slave device. * @@ -129,6 +155,11 @@ static void goodix_ts_report_touch(struct goodix_ts_data *ts, u8 *coor_data) int input_y = get_unaligned_le16(&coor_data[3]); int input_w = get_unaligned_le16(&coor_data[5]); + if (ts->rotated_screen) { + input_x = ts->abs_x_max - input_x; + input_y = ts->abs_y_max - input_y; + } + input_mt_slot(ts->input_dev, id); input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, true); input_report_abs(ts->input_dev, ABS_MT_POSITION_X, input_x); @@ -223,6 +254,11 @@ static void goodix_read_config(struct goodix_ts_data *ts) ts->abs_y_max = GOODIX_MAX_HEIGHT; ts->max_touch_num = GOODIX_MAX_CONTACTS; } + + ts->rotated_screen = dmi_check_system(rotated_screen); + if (ts->rotated_screen) + dev_dbg(&ts->client->dev, + "Applying '180 degrees rotated screen' quirk\n"); } /** -- cgit v1.2.3 From e3eea1404f5ff7a2ceb7b5e7ba412a6fd94f2935 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Red Hat)" Date: Fri, 24 Jul 2015 10:38:12 -0400 Subject: ftrace: Fix breakage of set_ftrace_pid Commit 4104d326b670 ("ftrace: Remove global function list and call function directly") simplified the ftrace code by removing the global_ops list with a new design. But this cleanup also broke the filtering of PIDs that are added to the set_ftrace_pid file. Add back the proper hooks to have pid filtering working once again. Cc: stable@vger.kernel.org # 3.16+ Reported-by: Matt Fleming Reported-by: Richard Weinberger Tested-by: Matt Fleming Signed-off-by: Steven Rostedt --- include/linux/ftrace.h | 3 +++ kernel/trace/ftrace.c | 52 +++++++++++++++++++++++++++++++++----------------- 2 files changed, 37 insertions(+), 18 deletions(-) diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h index 1da602982cf9..6cd8c0ee4b6f 100644 --- a/include/linux/ftrace.h +++ b/include/linux/ftrace.h @@ -116,6 +116,7 @@ ftrace_func_t ftrace_ops_get_func(struct ftrace_ops *ops); * SAVE_REGS. If another ops with this flag set is already registered * for any of the functions that this ops will be registered for, then * this ops will fail to register or set_filter_ip. + * PID - Is affected by set_ftrace_pid (allows filtering on those pids) */ enum { FTRACE_OPS_FL_ENABLED = 1 << 0, @@ -132,6 +133,7 @@ enum { FTRACE_OPS_FL_MODIFYING = 1 << 11, FTRACE_OPS_FL_ALLOC_TRAMP = 1 << 12, FTRACE_OPS_FL_IPMODIFY = 1 << 13, + FTRACE_OPS_FL_PID = 1 << 14, }; #ifdef CONFIG_DYNAMIC_FTRACE @@ -159,6 +161,7 @@ struct ftrace_ops { struct ftrace_ops *next; unsigned long flags; void *private; + ftrace_func_t saved_func; int __percpu *disabled; #ifdef CONFIG_DYNAMIC_FTRACE int nr_trampolines; diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 02bece4a99ea..eb11011b5292 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -98,6 +98,13 @@ struct ftrace_pid { struct pid *pid; }; +static bool ftrace_pids_enabled(void) +{ + return !list_empty(&ftrace_pids); +} + +static void ftrace_update_trampoline(struct ftrace_ops *ops); + /* * ftrace_disabled is set when an anomaly is discovered. * ftrace_disabled is much stronger than ftrace_enabled. @@ -109,7 +116,6 @@ static DEFINE_MUTEX(ftrace_lock); static struct ftrace_ops *ftrace_control_list __read_mostly = &ftrace_list_end; static struct ftrace_ops *ftrace_ops_list __read_mostly = &ftrace_list_end; ftrace_func_t ftrace_trace_function __read_mostly = ftrace_stub; -ftrace_func_t ftrace_pid_function __read_mostly = ftrace_stub; static struct ftrace_ops global_ops; static struct ftrace_ops control_ops; @@ -183,14 +189,7 @@ static void ftrace_pid_func(unsigned long ip, unsigned long parent_ip, if (!test_tsk_trace_trace(current)) return; - ftrace_pid_function(ip, parent_ip, op, regs); -} - -static void set_ftrace_pid_function(ftrace_func_t func) -{ - /* do not set ftrace_pid_function to itself! */ - if (func != ftrace_pid_func) - ftrace_pid_function = func; + op->saved_func(ip, parent_ip, op, regs); } /** @@ -202,7 +201,6 @@ static void set_ftrace_pid_function(ftrace_func_t func) void clear_ftrace_function(void) { ftrace_trace_function = ftrace_stub; - ftrace_pid_function = ftrace_stub; } static void control_ops_disable_all(struct ftrace_ops *ops) @@ -436,6 +434,12 @@ static int __register_ftrace_function(struct ftrace_ops *ops) } else add_ftrace_ops(&ftrace_ops_list, ops); + /* Always save the function, and reset at unregistering */ + ops->saved_func = ops->func; + + if (ops->flags & FTRACE_OPS_FL_PID && ftrace_pids_enabled()) + ops->func = ftrace_pid_func; + ftrace_update_trampoline(ops); if (ftrace_enabled) @@ -463,15 +467,28 @@ static int __unregister_ftrace_function(struct ftrace_ops *ops) if (ftrace_enabled) update_ftrace_function(); + ops->func = ops->saved_func; + return 0; } static void ftrace_update_pid_func(void) { + bool enabled = ftrace_pids_enabled(); + struct ftrace_ops *op; + /* Only do something if we are tracing something */ if (ftrace_trace_function == ftrace_stub) return; + do_for_each_ftrace_op(op, ftrace_ops_list) { + if (op->flags & FTRACE_OPS_FL_PID) { + op->func = enabled ? ftrace_pid_func : + op->saved_func; + ftrace_update_trampoline(op); + } + } while_for_each_ftrace_op(op); + update_ftrace_function(); } @@ -1133,7 +1150,8 @@ static struct ftrace_ops global_ops = { .local_hash.filter_hash = EMPTY_HASH, INIT_OPS_HASH(global_ops) .flags = FTRACE_OPS_FL_RECURSION_SAFE | - FTRACE_OPS_FL_INITIALIZED, + FTRACE_OPS_FL_INITIALIZED | + FTRACE_OPS_FL_PID, }; /* @@ -5023,7 +5041,9 @@ static void ftrace_update_trampoline(struct ftrace_ops *ops) static struct ftrace_ops global_ops = { .func = ftrace_stub, - .flags = FTRACE_OPS_FL_RECURSION_SAFE | FTRACE_OPS_FL_INITIALIZED, + .flags = FTRACE_OPS_FL_RECURSION_SAFE | + FTRACE_OPS_FL_INITIALIZED | + FTRACE_OPS_FL_PID, }; static int __init ftrace_nodyn_init(void) @@ -5080,11 +5100,6 @@ void ftrace_init_array_ops(struct trace_array *tr, ftrace_func_t func) if (WARN_ON(tr->ops->func != ftrace_stub)) printk("ftrace ops had %pS for function\n", tr->ops->func); - /* Only the top level instance does pid tracing */ - if (!list_empty(&ftrace_pids)) { - set_ftrace_pid_function(func); - func = ftrace_pid_func; - } } tr->ops->func = func; tr->ops->private = tr; @@ -5371,7 +5386,7 @@ static void *fpid_start(struct seq_file *m, loff_t *pos) { mutex_lock(&ftrace_lock); - if (list_empty(&ftrace_pids) && (!*pos)) + if (!ftrace_pids_enabled() && (!*pos)) return (void *) 1; return seq_list_start(&ftrace_pids, *pos); @@ -5610,6 +5625,7 @@ static struct ftrace_ops graph_ops = { .func = ftrace_stub, .flags = FTRACE_OPS_FL_RECURSION_SAFE | FTRACE_OPS_FL_INITIALIZED | + FTRACE_OPS_FL_PID | FTRACE_OPS_FL_STUB, #ifdef FTRACE_GRAPH_TRAMP_ADDR .trampoline = FTRACE_GRAPH_TRAMP_ADDR, -- cgit v1.2.3 From 8ca243536d21ae2d08f61b1c5af4ac3d4bb697e4 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 24 Jul 2015 23:42:34 -0400 Subject: libnvdimm: fix namespace seed creation A new BLK namespace "seed" device is created whenever the current seed is successfully probed. However, if that namespace is assigned to a BTT it may never directly experience a successful probe as it is a subordinate device to a BTT configuration. The effect of the current code is that no new namespaces can be instantiated, after the seed namespace, to consume available BLK DPA capacity. Fix this by treating a successful BTT probe event as a successful probe event for the backing namespace. Reported-by: Nicholas Moulin Signed-off-by: Dan Williams --- drivers/nvdimm/region_devs.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c index a5233422f9dc..7384455792bf 100644 --- a/drivers/nvdimm/region_devs.c +++ b/drivers/nvdimm/region_devs.c @@ -458,10 +458,15 @@ static void nd_region_notify_driver_action(struct nvdimm_bus *nvdimm_bus, nvdimm_bus_unlock(dev); } if (is_nd_btt(dev) && probe) { + struct nd_btt *nd_btt = to_nd_btt(dev); + nd_region = to_nd_region(dev->parent); nvdimm_bus_lock(dev); if (nd_region->btt_seed == dev) nd_region_create_btt_seed(nd_region); + if (nd_region->ns_seed == &nd_btt->ndns->dev && + is_nd_blk(dev->parent)) + nd_region_create_blk_seed(nd_region); nvdimm_bus_unlock(dev); } } -- cgit v1.2.3 From 4e5a74f1db8d6bea48306126fd445e2720f07a95 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Sat, 25 Jul 2015 13:19:40 +0530 Subject: parport: Revert "parport: fix memory leak" This reverts commit 23c405912b88 ("parport: fix memory leak") par_dev->state was already being removed in parport_unregister_device(). Reported-by: Ying Huang Signed-off-by: Sudip Mukherjee Signed-off-by: Greg Kroah-Hartman --- drivers/parport/share.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/parport/share.c b/drivers/parport/share.c index c02b5f27798b..5ce5ef211bdb 100644 --- a/drivers/parport/share.c +++ b/drivers/parport/share.c @@ -816,7 +816,6 @@ static void free_pardevice(struct device *dev) struct pardevice *par_dev = to_pardevice(dev); kfree(par_dev->name); - kfree(par_dev->state); kfree(par_dev); } -- cgit v1.2.3 From 2c534c0da0a68418693e10ce1c4146e085f39518 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Tue, 21 Jul 2015 15:55:09 +0100 Subject: perf/x86/intel/cqm: Return cached counter value from IRQ context Peter reported the following potential crash which I was able to reproduce with his test program, [ 148.765788] ------------[ cut here ]------------ [ 148.765796] WARNING: CPU: 34 PID: 2840 at kernel/smp.c:417 smp_call_function_many+0xb6/0x260() [ 148.765797] Modules linked in: [ 148.765800] CPU: 34 PID: 2840 Comm: perf Not tainted 4.2.0-rc1+ #4 [ 148.765803] ffffffff81cdc398 ffff88085f105950 ffffffff818bdfd5 0000000000000007 [ 148.765805] 0000000000000000 ffff88085f105990 ffffffff810e413a 0000000000000000 [ 148.765807] ffffffff82301080 0000000000000022 ffffffff8107f640 ffffffff8107f640 [ 148.765809] Call Trace: [ 148.765810] [] dump_stack+0x45/0x57 [ 148.765818] [] warn_slowpath_common+0x8a/0xc0 [ 148.765822] [] ? intel_cqm_stable+0x60/0x60 [ 148.765824] [] ? intel_cqm_stable+0x60/0x60 [ 148.765825] [] warn_slowpath_null+0x1a/0x20 [ 148.765827] [] smp_call_function_many+0xb6/0x260 [ 148.765829] [] ? intel_cqm_stable+0x60/0x60 [ 148.765831] [] on_each_cpu_mask+0x28/0x60 [ 148.765832] [] intel_cqm_event_count+0x7f/0xe0 [ 148.765836] [] perf_output_read+0x2a5/0x400 [ 148.765839] [] perf_output_sample+0x31a/0x590 [ 148.765840] [] ? perf_prepare_sample+0x26d/0x380 [ 148.765841] [] perf_event_output+0x47/0x60 [ 148.765843] [] __perf_event_overflow+0x215/0x240 [ 148.765844] [] perf_event_overflow+0x14/0x20 [ 148.765847] [] intel_pmu_handle_irq+0x1d4/0x440 [ 148.765849] [] ? __perf_event_task_sched_in+0x36/0xa0 [ 148.765853] [] ? vunmap_page_range+0x19d/0x2f0 [ 148.765854] [] ? unmap_kernel_range_noflush+0x11/0x20 [ 148.765859] [] ? ghes_copy_tofrom_phys+0x11e/0x2a0 [ 148.765863] [] ? native_apic_msr_write+0x2b/0x30 [ 148.765865] [] ? x2apic_send_IPI_self+0x1d/0x20 [ 148.765869] [] ? arch_irq_work_raise+0x35/0x40 [ 148.765872] [] ? irq_work_queue+0x66/0x80 [ 148.765875] [] perf_event_nmi_handler+0x26/0x40 [ 148.765877] [] nmi_handle+0x79/0x100 [ 148.765879] [] default_do_nmi+0x42/0x100 [ 148.765880] [] do_nmi+0x83/0xb0 [ 148.765884] [] end_repeat_nmi+0x1e/0x2e [ 148.765886] [] ? __perf_event_task_sched_in+0x36/0xa0 [ 148.765888] [] ? __perf_event_task_sched_in+0x36/0xa0 [ 148.765890] [] ? __perf_event_task_sched_in+0x36/0xa0 [ 148.765891] <> [] finish_task_switch+0x156/0x210 [ 148.765898] [] __schedule+0x341/0x920 [ 148.765899] [] schedule+0x37/0x80 [ 148.765903] [] ? do_page_fault+0x2f/0x80 [ 148.765905] [] schedule_user+0x1a/0x50 [ 148.765907] [] retint_careful+0x14/0x32 [ 148.765908] ---[ end trace e33ff2be78e14901 ]--- The CQM task events are not safe to be called from within interrupt context because they require performing an IPI to read the counter value on all sockets. And performing IPIs from within IRQ context is a "no-no". Make do with the last read counter value currently event in event->count when we're invoked in this context. Reported-by: Peter Zijlstra Signed-off-by: Matt Fleming Cc: Thomas Gleixner Cc: Vikas Shivappa Cc: Kanaka Juvva Cc: Will Auld Cc: Link: http://lkml.kernel.org/r/1437490509-15373-1-git-send-email-matt@codeblueprint.co.uk Signed-off-by: Thomas Gleixner --- arch/x86/kernel/cpu/perf_event_intel_cqm.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/x86/kernel/cpu/perf_event_intel_cqm.c b/arch/x86/kernel/cpu/perf_event_intel_cqm.c index 188076161c1b..63eb68b73589 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_cqm.c +++ b/arch/x86/kernel/cpu/perf_event_intel_cqm.c @@ -951,6 +951,14 @@ static u64 intel_cqm_event_count(struct perf_event *event) if (!cqm_group_leader(event)) return 0; + /* + * Getting up-to-date values requires an SMP IPI which is not + * possible if we're being called in interrupt context. Return + * the cached values instead. + */ + if (unlikely(in_interrupt())) + goto out; + /* * Notice that we don't perform the reading of an RMID * atomically, because we can't hold a spin lock across the -- cgit v1.2.3 From 1a4e8795711f474b31ff6eac37f3efd304ed8a93 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Sun, 26 Jul 2015 10:27:37 +0200 Subject: x86/mm/pat: Revert 'Adjust default caching mode translation tables' Toshi explains: "No, the default values need to be set to the fallback types, i.e. minimal supported mode. For WC and WT, UC is the fallback type. When PAT is disabled, pat_init() does update the tables below to enable WT per the default BIOS setup. However, when PAT is enabled, but CPU has PAT -errata, WT falls back to UC per the default values." Revert: ca1fec58bc6a 'x86/mm/pat: Adjust default caching mode translation tables' Requested-by: Toshi Kani Cc: Jan Beulich Link: http://lkml.kernel.org/r/1437577776.3214.252.camel@hp.com Signed-off-by: Thomas Gleixner --- arch/x86/mm/init.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index 7a4532229f51..8533b46e6bee 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c @@ -43,18 +43,18 @@ uint16_t __cachemode2pte_tbl[_PAGE_CACHE_MODE_NUM] = { [_PAGE_CACHE_MODE_WC ] = 0 | _PAGE_PCD, [_PAGE_CACHE_MODE_UC_MINUS] = 0 | _PAGE_PCD, [_PAGE_CACHE_MODE_UC ] = _PAGE_PWT | _PAGE_PCD, - [_PAGE_CACHE_MODE_WT ] = _PAGE_PWT | 0, + [_PAGE_CACHE_MODE_WT ] = 0 | _PAGE_PCD, [_PAGE_CACHE_MODE_WP ] = 0 | _PAGE_PCD, }; EXPORT_SYMBOL(__cachemode2pte_tbl); uint8_t __pte2cachemode_tbl[8] = { [__pte2cm_idx( 0 | 0 | 0 )] = _PAGE_CACHE_MODE_WB, - [__pte2cm_idx(_PAGE_PWT | 0 | 0 )] = _PAGE_CACHE_MODE_WT, + [__pte2cm_idx(_PAGE_PWT | 0 | 0 )] = _PAGE_CACHE_MODE_UC_MINUS, [__pte2cm_idx( 0 | _PAGE_PCD | 0 )] = _PAGE_CACHE_MODE_UC_MINUS, [__pte2cm_idx(_PAGE_PWT | _PAGE_PCD | 0 )] = _PAGE_CACHE_MODE_UC, [__pte2cm_idx( 0 | 0 | _PAGE_PAT)] = _PAGE_CACHE_MODE_WB, - [__pte2cm_idx(_PAGE_PWT | 0 | _PAGE_PAT)] = _PAGE_CACHE_MODE_WT, + [__pte2cm_idx(_PAGE_PWT | 0 | _PAGE_PAT)] = _PAGE_CACHE_MODE_UC_MINUS, [__pte2cm_idx(0 | _PAGE_PCD | _PAGE_PAT)] = _PAGE_CACHE_MODE_UC_MINUS, [__pte2cm_idx(_PAGE_PWT | _PAGE_PCD | _PAGE_PAT)] = _PAGE_CACHE_MODE_UC, }; -- cgit v1.2.3 From cbfe8fa6cd672011c755c3cd85c9ffd4e2d10a6f Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 26 Jul 2015 12:26:21 -0700 Subject: Linux 4.2-rc4 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index a9ad4908e870..afabc44a349b 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 4 PATCHLEVEL = 2 SUBLEVEL = 0 -EXTRAVERSION = -rc3 +EXTRAVERSION = -rc4 NAME = Hurr durr I'ma sheep # *DOCUMENTATION* -- cgit v1.2.3 From 00a2916f7f82c348a2a94dbb572874173bc308a3 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 27 Jul 2015 10:35:07 +0200 Subject: perf: Fix running time accounting A recent fix to the shadow timestamp inadvertly broke the running time accounting. We must not update the running timestamp if we fail to schedule the event, the event will not have ran. This can (and did) result in negative total runtime because the stopped timestamp was before the running timestamp (we 'started' but never stopped the event -- because it never really started we didn't have to stop it either). Reported-and-Tested-by: Vince Weaver Fixes: 72f669c0086f ("perf: Update shadow timestamp before add event") Signed-off-by: Peter Zijlstra (Intel) Cc: stable@vger.kernel.org # 4.1 Cc: Shaohua Li Signed-off-by: Thomas Gleixner --- kernel/events/core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/events/core.c b/kernel/events/core.c index d3dae3419b99..10d076b2572c 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -1868,8 +1868,6 @@ event_sched_in(struct perf_event *event, perf_pmu_disable(event->pmu); - event->tstamp_running += tstamp - event->tstamp_stopped; - perf_set_shadow_time(event, ctx, tstamp); perf_log_itrace_start(event); @@ -1881,6 +1879,8 @@ event_sched_in(struct perf_event *event, goto out; } + event->tstamp_running += tstamp - event->tstamp_stopped; + if (!is_software_event(event)) cpuctx->active_oncpu++; if (!ctx->nr_active++) -- cgit v1.2.3 From 5497628576a3c5f3dbab224fa5a5d027f43d8b50 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Mon, 27 Jul 2015 16:24:51 -0700 Subject: perf stat: Fix transaction lenght metrics The transaction length metrics in perf stat -T broke recently. It would not match the metric correctly and always print K/sec. This was caused by a incorrect update of the cycles_in_tx statistics. Update the correct variable. Also the check for zero division was reversed, which resulted in K/sec being printed for no transactions. Fix this also up. Signed-off-by: Andi Kleen Acked-by: Jiri Olsa Link: http://lkml.kernel.org/r/1438039491-22091-1-git-send-email-andi@firstfloor.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/stat-shadow.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c index 53e8bb7bc852..2a5d8d7698ae 100644 --- a/tools/perf/util/stat-shadow.c +++ b/tools/perf/util/stat-shadow.c @@ -85,7 +85,7 @@ void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 *count, else if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES)) update_stats(&runtime_cycles_stats[ctx][cpu], count[0]); else if (perf_stat_evsel__is(counter, CYCLES_IN_TX)) - update_stats(&runtime_transaction_stats[ctx][cpu], count[0]); + update_stats(&runtime_cycles_in_tx_stats[ctx][cpu], count[0]); else if (perf_stat_evsel__is(counter, TRANSACTION_START)) update_stats(&runtime_transaction_stats[ctx][cpu], count[0]); else if (perf_stat_evsel__is(counter, ELISION_START)) @@ -398,20 +398,18 @@ void perf_stat__print_shadow_stats(FILE *out, struct perf_evsel *evsel, " # %5.2f%% aborted cycles ", 100.0 * ((total2-avg) / total)); } else if (perf_stat_evsel__is(evsel, TRANSACTION_START) && - avg > 0 && runtime_cycles_in_tx_stats[ctx][cpu].n != 0) { total = avg_stats(&runtime_cycles_in_tx_stats[ctx][cpu]); - if (total) + if (avg) ratio = total / avg; fprintf(out, " # %8.0f cycles / transaction ", ratio); } else if (perf_stat_evsel__is(evsel, ELISION_START) && - avg > 0 && runtime_cycles_in_tx_stats[ctx][cpu].n != 0) { total = avg_stats(&runtime_cycles_in_tx_stats[ctx][cpu]); - if (total) + if (avg) ratio = total / avg; fprintf(out, " # %8.0f cycles / elision ", ratio); -- cgit v1.2.3 From 0927beeca5f9d1a7978f8da9c9d28647859816d3 Mon Sep 17 00:00:00 2001 From: Pawel Moll Date: Tue, 28 Jul 2015 15:10:13 +0100 Subject: perf tools: Fix test build error when bindir contains double slash MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When building with a prefix ending with a slash, for example: $ make prefix=/usr/local/ one of the perf tests fail to compile due to BUILD_STR macro mishandling bindir_SQ string containing with two slashes: -DBINDIR="BUILD_STR(/usr/local//bin)" with the following error: CC tests/attr.o tests/attr.c: In function ‘test__attr’: tests/attr.c:168:50: error: expected ‘)’ before ‘;’ token snprintf(path_perf, PATH_MAX, "%s/perf", BINDIR); ^ tests/attr.c:176:1: error: expected ‘;’ before ‘}’ token } ^ tests/attr.c:176:1: error: control reaches end of non-void function [-Werror=return-type] } ^ cc1: all warnings being treated as errors This patch works around the problem by "cleaning" the bindir string using make's abspath function. Signed-off-by: Pawel Moll Acked-by: Jiri Olsa Cc: Adrian Hunter Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1438092613-21014-1-git-send-email-pawel.moll@arm.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/config/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile index 094ddaee104c..d31fac19c30b 100644 --- a/tools/perf/config/Makefile +++ b/tools/perf/config/Makefile @@ -638,7 +638,7 @@ ifndef DESTDIR prefix ?= $(HOME) endif bindir_relative = bin -bindir = $(prefix)/$(bindir_relative) +bindir = $(abspath $(prefix)/$(bindir_relative)) mandir = share/man infodir = share/info perfexecdir = libexec/perf-core -- cgit v1.2.3