From 6272c0de13abf1480f701d38288f28a11b4301c4 Mon Sep 17 00:00:00 2001 From: Matt Ranostay Date: Fri, 14 Apr 2017 16:38:19 -0700 Subject: iio: proximity: as3935: recalibrate RCO after resume According to the datasheet the RCO must be recalibrated on every power-on-reset. Also remove mutex locking in the calibration function since callers other than the probe function (which doesn't need it) will have a lock. Fixes: 24ddb0e4bba4 ("iio: Add AS3935 lightning sensor support") Cc: George McCollister Signed-off-by: Matt Ranostay Signed-off-by: Jonathan Cameron --- drivers/iio/proximity/as3935.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/iio/proximity/as3935.c b/drivers/iio/proximity/as3935.c index ddf9bee89f77..d0f5e53aad59 100644 --- a/drivers/iio/proximity/as3935.c +++ b/drivers/iio/proximity/as3935.c @@ -269,8 +269,6 @@ static irqreturn_t as3935_interrupt_handler(int irq, void *private) static void calibrate_as3935(struct as3935_state *st) { - mutex_lock(&st->lock); - /* mask disturber interrupt bit */ as3935_write(st, AS3935_INT, BIT(5)); @@ -280,8 +278,6 @@ static void calibrate_as3935(struct as3935_state *st) mdelay(2); as3935_write(st, AS3935_TUNE_CAP, (st->tune_cap / TUNE_CAP_DIV)); - - mutex_unlock(&st->lock); } #ifdef CONFIG_PM_SLEEP @@ -318,6 +314,8 @@ static int as3935_resume(struct device *dev) val &= ~AS3935_AFE_PWR_BIT; ret = as3935_write(st, AS3935_AFE_GAIN, val); + calibrate_as3935(st); + err_resume: mutex_unlock(&st->lock); -- cgit v1.2.3 From 35fa70dfd6e6f270d7aabb3470855208b11ac9fb Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 20 Apr 2017 13:26:18 +0300 Subject: iio: adc: Max9611: checking for ERR_PTR instead of NULL in probe devm_iio_device_alloc() doesn't return ERR_PTRs, it returns NULLs. Fixes: 69780a3bbc0b ("iio: adc: Add Maxim max9611 ADC driver") Signed-off-by: Dan Carpenter Signed-off-by: Jonathan Cameron --- drivers/iio/adc/max9611.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/iio/adc/max9611.c b/drivers/iio/adc/max9611.c index ec82106480e1..dc3869bf3248 100644 --- a/drivers/iio/adc/max9611.c +++ b/drivers/iio/adc/max9611.c @@ -536,8 +536,8 @@ static int max9611_probe(struct i2c_client *client, int ret; indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*max9611)); - if (IS_ERR(indio_dev)) - return PTR_ERR(indio_dev); + if (!indio_dev) + return -ENOMEM; i2c_set_clientdata(client, indio_dev); -- cgit v1.2.3 From 0de0e198bc7191a0e46cf71f66fec4d07ca91396 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 25 Apr 2017 12:58:31 -0700 Subject: ACPI / sysfs: fix acpi_get_table() leak / acpi-sysfs denial of service Reading an ACPI table through the /sys/firmware/acpi/tables interface more than 65,536 times leads to the following log message: ACPI Error: Table ffff88033595eaa8, Validation count is zero after increment (20170119/tbutils-423) ...and the table being unavailable until the next reboot. Add the missing acpi_put_table() so the table ->validation_count is decremented after each read. Reported-by: Anush Seetharaman Fixes: 174cc7187e6f "ACPICA: Tables: Back port acpi_get_table_with_size() ..." Signed-off-by: Dan Williams Cc: 4.10+ # 4.10+ Signed-off-by: Rafael J. Wysocki --- drivers/acpi/sysfs.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c index cf05ae973381..5180fef9eb49 100644 --- a/drivers/acpi/sysfs.c +++ b/drivers/acpi/sysfs.c @@ -333,14 +333,17 @@ static ssize_t acpi_table_show(struct file *filp, struct kobject *kobj, container_of(bin_attr, struct acpi_table_attr, attr); struct acpi_table_header *table_header = NULL; acpi_status status; + ssize_t rc; status = acpi_get_table(table_attr->name, table_attr->instance, &table_header); if (ACPI_FAILURE(status)) return -ENODEV; - return memory_read_from_buffer(buf, count, &offset, - table_header, table_header->length); + rc = memory_read_from_buffer(buf, count, &offset, table_header, + table_header->length); + acpi_put_table(table_header); + return rc; } static int acpi_table_attr_init(struct kobject *tables_obj, -- cgit v1.2.3 From 275292d3a3d62670b1b13484707b74e5239b4bb0 Mon Sep 17 00:00:00 2001 From: Matt Ranostay Date: Thu, 27 Apr 2017 00:52:32 -0700 Subject: iio: proximity: as3935: fix AS3935_INT mask AS3935 interrupt mask has been incorrect so valid lightning events would never trigger an buffer event. Also noise interrupt should be BIT(0). Fixes: 24ddb0e4bba4 ("iio: Add AS3935 lightning sensor support") CC: stable@vger.kernel.org Signed-off-by: Matt Ranostay Signed-off-by: Jonathan Cameron --- drivers/iio/proximity/as3935.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/iio/proximity/as3935.c b/drivers/iio/proximity/as3935.c index d0f5e53aad59..2e94e5ad884b 100644 --- a/drivers/iio/proximity/as3935.c +++ b/drivers/iio/proximity/as3935.c @@ -40,9 +40,9 @@ #define AS3935_AFE_PWR_BIT BIT(0) #define AS3935_INT 0x03 -#define AS3935_INT_MASK 0x07 +#define AS3935_INT_MASK 0x0f #define AS3935_EVENT_INT BIT(3) -#define AS3935_NOISE_INT BIT(1) +#define AS3935_NOISE_INT BIT(0) #define AS3935_DATA 0x07 #define AS3935_DATA_MASK 0x3F -- cgit v1.2.3 From 0e78a87306a6f55b1c7bbafad1de62c3975953ca Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Wed, 3 May 2017 08:44:27 +0200 Subject: esp4: Fix udpencap for local TCP packets. Locally generated TCP packets are usually cloned, so we do skb_cow_data() on this packets. After that we need to reload the pointer to the esp header. On udpencap this header has an offset to skb_transport_header, so take this offset into account. Fixes: 67d349ed603 ("net/esp4: Fix invalid esph pointer crash") Fixes: fca11ebde3f0 ("esp4: Reorganize esp_output") Reported-by: Don Bowman Signed-off-by: Steffen Klassert --- net/ipv4/esp4.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index 65cc02bd82bc..93322f895eab 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c @@ -248,6 +248,7 @@ int esp_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info * u8 *tail; u8 *vaddr; int nfrags; + int esph_offset; struct page *page; struct sk_buff *trailer; int tailen = esp->tailen; @@ -313,11 +314,13 @@ int esp_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info * } cow: + esph_offset = (unsigned char *)esp->esph - skb_transport_header(skb); + nfrags = skb_cow_data(skb, tailen, &trailer); if (nfrags < 0) goto out; tail = skb_tail_pointer(trailer); - esp->esph = ip_esp_hdr(skb); + esp->esph = (struct ip_esp_hdr *)(skb_transport_header(skb) + esph_offset); skip_cow: esp_output_fill_trailer(tail, esp->tfclen, esp->plen, esp->proto); -- cgit v1.2.3 From 9b3eb54106cf6acd03f07cf0ab01c13676a226c2 Mon Sep 17 00:00:00 2001 From: Sabrina Dubroca Date: Wed, 3 May 2017 16:43:19 +0200 Subject: xfrm: fix stack access out of bounds with CONFIG_XFRM_SUB_POLICY When CONFIG_XFRM_SUB_POLICY=y, xfrm_dst stores a copy of the flowi for that dst. Unfortunately, the code that allocates and fills this copy doesn't care about what type of flowi (flowi, flowi4, flowi6) gets passed. In multiple code paths (from raw_sendmsg, from TCP when replying to a FIN, in vxlan, geneve, and gre), the flowi that gets passed to xfrm is actually an on-stack flowi4, so we end up reading stuff from the stack past the end of the flowi4 struct. Since xfrm_dst->origin isn't used anywhere following commit ca116922afa8 ("xfrm: Eliminate "fl" and "pol" args to xfrm_bundle_ok()."), just get rid of it. xfrm_dst->partner isn't used either, so get rid of that too. Fixes: 9d6ec938019c ("ipv4: Use flowi4 in public route lookup interfaces.") Signed-off-by: Sabrina Dubroca Signed-off-by: Steffen Klassert --- include/net/xfrm.h | 10 ---------- net/xfrm/xfrm_policy.c | 47 ----------------------------------------------- 2 files changed, 57 deletions(-) diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 6793a30c66b1..7e7e2b0d2915 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -979,10 +979,6 @@ struct xfrm_dst { struct flow_cache_object flo; struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX]; int num_pols, num_xfrms; -#ifdef CONFIG_XFRM_SUB_POLICY - struct flowi *origin; - struct xfrm_selector *partner; -#endif u32 xfrm_genid; u32 policy_genid; u32 route_mtu_cached; @@ -998,12 +994,6 @@ static inline void xfrm_dst_destroy(struct xfrm_dst *xdst) dst_release(xdst->route); if (likely(xdst->u.dst.xfrm)) xfrm_state_put(xdst->u.dst.xfrm); -#ifdef CONFIG_XFRM_SUB_POLICY - kfree(xdst->origin); - xdst->origin = NULL; - kfree(xdst->partner); - xdst->partner = NULL; -#endif } #endif diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index b00a1d5a7f52..ed4e52d95172 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -1797,43 +1797,6 @@ free_dst: goto out; } -#ifdef CONFIG_XFRM_SUB_POLICY -static int xfrm_dst_alloc_copy(void **target, const void *src, int size) -{ - if (!*target) { - *target = kmalloc(size, GFP_ATOMIC); - if (!*target) - return -ENOMEM; - } - - memcpy(*target, src, size); - return 0; -} -#endif - -static int xfrm_dst_update_parent(struct dst_entry *dst, - const struct xfrm_selector *sel) -{ -#ifdef CONFIG_XFRM_SUB_POLICY - struct xfrm_dst *xdst = (struct xfrm_dst *)dst; - return xfrm_dst_alloc_copy((void **)&(xdst->partner), - sel, sizeof(*sel)); -#else - return 0; -#endif -} - -static int xfrm_dst_update_origin(struct dst_entry *dst, - const struct flowi *fl) -{ -#ifdef CONFIG_XFRM_SUB_POLICY - struct xfrm_dst *xdst = (struct xfrm_dst *)dst; - return xfrm_dst_alloc_copy((void **)&(xdst->origin), fl, sizeof(*fl)); -#else - return 0; -#endif -} - static int xfrm_expand_policies(const struct flowi *fl, u16 family, struct xfrm_policy **pols, int *num_pols, int *num_xfrms) @@ -1905,16 +1868,6 @@ xfrm_resolve_and_create_bundle(struct xfrm_policy **pols, int num_pols, xdst = (struct xfrm_dst *)dst; xdst->num_xfrms = err; - if (num_pols > 1) - err = xfrm_dst_update_parent(dst, &pols[1]->selector); - else - err = xfrm_dst_update_origin(dst, fl); - if (unlikely(err)) { - dst_free(dst); - XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTBUNDLECHECKERROR); - return ERR_PTR(err); - } - xdst->num_pols = num_pols; memcpy(xdst->pols, pols, sizeof(struct xfrm_policy *) * num_pols); xdst->policy_genid = atomic_read(&pols[0]->genid); -- cgit v1.2.3 From 2ac97f0f6654da14312d125005c77a6010e0ea38 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Tue, 25 Apr 2017 11:29:56 -0700 Subject: HID: wacom: Have wacom_tpc_irq guard against possible NULL dereference The following Smatch complaint was generated in response to commit 2a6cdbd ("HID: wacom: Introduce new 'touch_input' device"): drivers/hid/wacom_wac.c:1586 wacom_tpc_irq() error: we previously assumed 'wacom->touch_input' could be null (see line 1577) The 'touch_input' and 'pen_input' variables point to the 'struct input_dev' used for relaying touch and pen events to userspace, respectively. If a device does not have a touch interface or pen interface, the associated input variable is NULL. The 'wacom_tpc_irq()' function is responsible for forwarding input reports to a more-specific IRQ handler function. An unknown report could theoretically be mistaken as e.g. a touch report on a device which does not have a touch interface. This can be prevented by only calling the pen/touch functions are called when the pen/touch pointers are valid. Fixes: 2a6cdbd ("HID: wacom: Introduce new 'touch_input' device") Signed-off-by: Jason Gerecke Reviewed-by: Ping Cheng Cc: stable@vger.kernel.org Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 45 +++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 4b225fb19a16..e274c9dc32f3 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -1571,37 +1571,38 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len) { unsigned char *data = wacom->data; - if (wacom->pen_input) + if (wacom->pen_input) { dev_dbg(wacom->pen_input->dev.parent, "%s: received report #%d\n", __func__, data[0]); - else if (wacom->touch_input) + + if (len == WACOM_PKGLEN_PENABLED || + data[0] == WACOM_REPORT_PENABLED) + return wacom_tpc_pen(wacom); + } + else if (wacom->touch_input) { dev_dbg(wacom->touch_input->dev.parent, "%s: received report #%d\n", __func__, data[0]); - switch (len) { - case WACOM_PKGLEN_TPC1FG: - return wacom_tpc_single_touch(wacom, len); + switch (len) { + case WACOM_PKGLEN_TPC1FG: + return wacom_tpc_single_touch(wacom, len); - case WACOM_PKGLEN_TPC2FG: - return wacom_tpc_mt_touch(wacom); + case WACOM_PKGLEN_TPC2FG: + return wacom_tpc_mt_touch(wacom); - case WACOM_PKGLEN_PENABLED: - return wacom_tpc_pen(wacom); + default: + switch (data[0]) { + case WACOM_REPORT_TPC1FG: + case WACOM_REPORT_TPCHID: + case WACOM_REPORT_TPCST: + case WACOM_REPORT_TPC1FGE: + return wacom_tpc_single_touch(wacom, len); - default: - switch (data[0]) { - case WACOM_REPORT_TPC1FG: - case WACOM_REPORT_TPCHID: - case WACOM_REPORT_TPCST: - case WACOM_REPORT_TPC1FGE: - return wacom_tpc_single_touch(wacom, len); - - case WACOM_REPORT_TPCMT: - case WACOM_REPORT_TPCMT2: - return wacom_mt_touch(wacom); + case WACOM_REPORT_TPCMT: + case WACOM_REPORT_TPCMT2: + return wacom_mt_touch(wacom); - case WACOM_REPORT_PENABLED: - return wacom_tpc_pen(wacom); + } } } -- cgit v1.2.3 From f4b65b9563216b3e01a5cc844c3ba68901d9b195 Mon Sep 17 00:00:00 2001 From: Che-Liang Chiou Date: Fri, 7 Apr 2017 10:12:36 +0200 Subject: HID: magicmouse: Set multi-touch keybits for Magic Mouse The driver emits multi-touch events for Magic Trackpad as well as Magic Mouse, but it does not set keybits that are related to multi-touch event for Magic Mouse; so set these keybits. The keybits that are not set cause trouble because user programs often probe these keybits for self-configuration and thus they cannot operate properly if the keybits are not set. One of such troubles is that libevdev will not be able to emit correct touch count, causing gestures library failed to do fling stop. Signed-off-by: Che-Liang Chiou Signed-off-by: Thierry Escande Signed-off-by: Jiri Kosina --- drivers/hid/hid-magicmouse.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c index 20b40ad26325..1d6c997b3001 100644 --- a/drivers/hid/hid-magicmouse.c +++ b/drivers/hid/hid-magicmouse.c @@ -349,6 +349,7 @@ static int magicmouse_raw_event(struct hid_device *hdev, if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) { magicmouse_emit_buttons(msc, clicks & 3); + input_mt_report_pointer_emulation(input, true); input_report_rel(input, REL_X, x); input_report_rel(input, REL_Y, y); } else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */ @@ -388,16 +389,16 @@ static int magicmouse_setup_input(struct input_dev *input, struct hid_device *hd __clear_bit(BTN_RIGHT, input->keybit); __clear_bit(BTN_MIDDLE, input->keybit); __set_bit(BTN_MOUSE, input->keybit); - __set_bit(BTN_TOOL_FINGER, input->keybit); - __set_bit(BTN_TOOL_DOUBLETAP, input->keybit); - __set_bit(BTN_TOOL_TRIPLETAP, input->keybit); - __set_bit(BTN_TOOL_QUADTAP, input->keybit); - __set_bit(BTN_TOOL_QUINTTAP, input->keybit); - __set_bit(BTN_TOUCH, input->keybit); - __set_bit(INPUT_PROP_POINTER, input->propbit); __set_bit(INPUT_PROP_BUTTONPAD, input->propbit); } + __set_bit(BTN_TOOL_FINGER, input->keybit); + __set_bit(BTN_TOOL_DOUBLETAP, input->keybit); + __set_bit(BTN_TOOL_TRIPLETAP, input->keybit); + __set_bit(BTN_TOOL_QUADTAP, input->keybit); + __set_bit(BTN_TOOL_QUINTTAP, input->keybit); + __set_bit(BTN_TOUCH, input->keybit); + __set_bit(INPUT_PROP_POINTER, input->propbit); __set_bit(EV_ABS, input->evbit); -- cgit v1.2.3 From 9122b54f266ddee09654fe3fbc503c1a60f4a01c Mon Sep 17 00:00:00 2001 From: Matt Ranostay Date: Thu, 4 May 2017 17:32:19 -0700 Subject: iio: proximity: as3935: fix iio_trigger_poll issue Using iio_trigger_poll() can oops when multiple interrupts happen before the first is handled. Use iio_trigger_poll_chained() instead and use the timestamp when processed, since it will be in theory be 2 ms max latency. Fixes: 24ddb0e4bba4 ("iio: Add AS3935 lightning sensor support") Cc: stable@vger.kernel.org Signed-off-by: Matt Ranostay Signed-off-by: Jonathan Cameron --- drivers/iio/proximity/as3935.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/iio/proximity/as3935.c b/drivers/iio/proximity/as3935.c index 2e94e5ad884b..aa4df0dcc8c9 100644 --- a/drivers/iio/proximity/as3935.c +++ b/drivers/iio/proximity/as3935.c @@ -215,7 +215,7 @@ static irqreturn_t as3935_trigger_handler(int irq, void *private) st->buffer[0] = val & AS3935_DATA_MASK; iio_push_to_buffers_with_timestamp(indio_dev, &st->buffer, - pf->timestamp); + iio_get_time_ns(indio_dev)); err_read: iio_trigger_notify_done(indio_dev->trig); @@ -244,7 +244,7 @@ static void as3935_event_work(struct work_struct *work) switch (val) { case AS3935_EVENT_INT: - iio_trigger_poll(st->trig); + iio_trigger_poll_chained(st->trig); break; case AS3935_NOISE_INT: dev_warn(&st->spi->dev, "noise level is too high\n"); -- cgit v1.2.3 From f83e36e0a372c012a31d57e9d3e69d29a158264e Mon Sep 17 00:00:00 2001 From: Eduardo Molinas Date: Mon, 1 May 2017 18:45:58 -0400 Subject: iio: adc: sun4i-gpadc-iio: Fix module autoload when PLATFORM devices are registered If the driver is built as a module, it won't be autloaded if the devices are registered via PLATFORM code because the PLATFORM device table entries are not exported as aliases Before the patch: $ modinfo drivers/iio/adc/sun4i-gpadc-iio.ko | grep alias $ After the patch: $ modinfo drivers/iio/adc/sun4i-gpadc-iio.ko | grep alias alias: platform:sun6i-a31-gpadc-iio alias: platform:sun5i-a13-gpadc-iio alias: platform:sun4i-a10-gpadc-iio Signed-off-by: Eduardo Molinas Acked-by: Chen-Yu Tsai Signed-off-by: Jonathan Cameron --- drivers/iio/adc/sun4i-gpadc-iio.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c index b23527309088..c3d7ba100a48 100644 --- a/drivers/iio/adc/sun4i-gpadc-iio.c +++ b/drivers/iio/adc/sun4i-gpadc-iio.c @@ -700,6 +700,7 @@ static const struct platform_device_id sun4i_gpadc_id[] = { { "sun6i-a31-gpadc-iio", (kernel_ulong_t)&sun6i_gpadc_data }, { /* sentinel */ }, }; +MODULE_DEVICE_TABLE(platform, sun4i_gpadc_id); static struct platform_driver sun4i_gpadc_driver = { .driver = { -- cgit v1.2.3 From f35327f16b0cbe51d47a366aaf5dd9a3d4fac01b Mon Sep 17 00:00:00 2001 From: Eduardo Molinas Date: Mon, 1 May 2017 18:45:59 -0400 Subject: iio: adc: sun4i-gpadc-iio: Fix module autoload when OF devices are registered If the driver is built as a module, it won't be autloaded if the devices are registered via OF code because the OF device table entries are not exported as aliases Before the patch: $ modinfo drivers/iio/adc/sun4i-gpadc-iio.ko | grep alias alias: platform:sun6i-a31-gpadc-iio alias: platform:sun5i-a13-gpadc-iio alias: platform:sun4i-a10-gpadc-iio After the patch: $ modinfo drivers/iio/adc/sun4i-gpadc-iio.ko | grep alias alias: of:N*T*Callwinner,sun8i-a33-thsC* alias: of:N*T*Callwinner,sun8i-a33-ths alias: platform:sun6i-a31-gpadc-iio alias: platform:sun5i-a13-gpadc-iio alias: platform:sun4i-a10-gpadc-iio Signed-off-by: Eduardo Molinas Signed-off-by: Jonathan Cameron --- drivers/iio/adc/sun4i-gpadc-iio.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c index c3d7ba100a48..1c83b45043bf 100644 --- a/drivers/iio/adc/sun4i-gpadc-iio.c +++ b/drivers/iio/adc/sun4i-gpadc-iio.c @@ -712,6 +712,7 @@ static struct platform_driver sun4i_gpadc_driver = { .probe = sun4i_gpadc_probe, .remove = sun4i_gpadc_remove, }; +MODULE_DEVICE_TABLE(of, sun4i_gpadc_of_id); module_platform_driver(sun4i_gpadc_driver); -- cgit v1.2.3 From 1c005f9c129201121ef90bde57c374a4403ccfa6 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 28 Apr 2017 00:22:15 -0400 Subject: MAINTAINERS: Remove Javier Martinez Canillas as reviewer for Exynos I left Samsung and lost access to most Exynos hardware and documentation. Also, I likely won't be able to keep an eye on the platform anymore in the short term so remove myself as a reviewer for Exynos. Signed-off-by: Javier Martinez Canillas Signed-off-by: Krzysztof Kozlowski --- MAINTAINERS | 1 - 1 file changed, 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 38d3e4ed7208..7e80e28c92df 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1692,7 +1692,6 @@ N: rockchip ARM/SAMSUNG EXYNOS ARM ARCHITECTURES M: Kukjin Kim M: Krzysztof Kozlowski -R: Javier Martinez Canillas L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) L: linux-samsung-soc@vger.kernel.org (moderated for non-subscribers) Q: https://patchwork.kernel.org/project/linux-samsung-soc/list/ -- cgit v1.2.3 From d90c902449a7561f1b1d58ba5a0d11728ce8b0b2 Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Fri, 5 May 2017 07:40:42 +0200 Subject: af_key: Fix slab-out-of-bounds in pfkey_compile_policy. The sadb_x_sec_len is stored in the unit 'byte divided by eight'. So we have to multiply this value by eight before we can do size checks. Otherwise we may get a slab-out-of-bounds when we memcpy the user sec_ctx. Fixes: df71837d502 ("[LSM-IPSec]: Security association restriction.") Reported-by: Andrey Konovalov Tested-by: Andrey Konovalov Signed-off-by: Steffen Klassert --- net/key/af_key.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/key/af_key.c b/net/key/af_key.c index c1950bb14735..512dc43d0ce6 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -3285,7 +3285,7 @@ static struct xfrm_policy *pfkey_compile_policy(struct sock *sk, int opt, p += pol->sadb_x_policy_len*8; sec_ctx = (struct sadb_x_sec_ctx *)p; if (len < pol->sadb_x_policy_len*8 + - sec_ctx->sadb_x_sec_len) { + sec_ctx->sadb_x_sec_len*8) { *dir = -EINVAL; goto out; } -- cgit v1.2.3 From 2c1497bbc8fdee897341ab48ee9c9209b421b8c0 Mon Sep 17 00:00:00 2001 From: Ilan Tayari Date: Mon, 8 May 2017 10:30:18 +0300 Subject: xfrm: Fix NETDEV_DOWN with IPSec offload Upon NETDEV_DOWN event, all xfrm_state objects which are bound to the device are flushed. The condition for this is wrong, though, testing dev->hw_features instead of dev->features. If a device has non-user-modifiable NETIF_F_HW_ESP, then its xfrm_state objects are not flushed, causing a crash later on after the device is deleted. Check dev->features instead of dev->hw_features. Fixes: d77e38e612a0 ("xfrm: Add an IPsec hardware offloading API") Signed-off-by: Ilan Tayari Signed-off-by: Steffen Klassert --- net/xfrm/xfrm_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/xfrm/xfrm_device.c b/net/xfrm/xfrm_device.c index 8ec8a3fcf8d4..574e6f32f94f 100644 --- a/net/xfrm/xfrm_device.c +++ b/net/xfrm/xfrm_device.c @@ -170,7 +170,7 @@ static int xfrm_dev_feat_change(struct net_device *dev) static int xfrm_dev_down(struct net_device *dev) { - if (dev->hw_features & NETIF_F_HW_ESP) + if (dev->features & NETIF_F_HW_ESP) xfrm_dev_state_flush(dev_net(dev), dev, true); xfrm_garbage_collect(dev_net(dev)); -- cgit v1.2.3 From 0bb7a37f8d15e5fb5d21776875f9fbc74e10753a Mon Sep 17 00:00:00 2001 From: Diego Elio Pettenò Date: Wed, 26 Apr 2017 17:37:04 +0100 Subject: HID: elecom: extend to fix the descriptor for DEFT trackballs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ELECOM DEFT trackballs report only five buttons, when the device actually has 8. Change the descriptor so that the HID driver can see all of them. For completeness and future reference, I included a side-by-side diff of the part of the descriptor that is being edited. Cc: Jiri Kosina Cc: Benjamin Tissoires Cc: Yuxuan Shui Signed-off-by: Diego Elio Pettenò Signed-off-by: Jiri Kosina --- drivers/hid/Kconfig | 6 +++-- drivers/hid/hid-core.c | 2 ++ drivers/hid/hid-elecom.c | 62 +++++++++++++++++++++++++++++++++++++++++------- drivers/hid/hid-ids.h | 2 ++ 4 files changed, 61 insertions(+), 11 deletions(-) diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index fe40e5e499dd..687705c50794 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -275,10 +275,12 @@ config HID_EMS_FF - Trio Linker Plus II config HID_ELECOM - tristate "ELECOM BM084 bluetooth mouse" + tristate "ELECOM HID devices" depends on HID ---help--- - Support for the ELECOM BM084 (bluetooth mouse). + Support for ELECOM devices: + - BM084 Bluetooth Mouse + - DEFT Trackball (Wired and wireless) config HID_ELO tristate "ELO USB 4000/4500 touchscreen" diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 37084b645785..38d041510e1d 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1891,6 +1891,8 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, USB_DEVICE_ID_DREAM_CHEEKY_WN) }, { HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, USB_DEVICE_ID_DREAM_CHEEKY_FA) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRED) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRELESS) }, { HID_USB_DEVICE(USB_VENDOR_ID_ELO, 0x0009) }, { HID_USB_DEVICE(USB_VENDOR_ID_ELO, 0x0030) }, { HID_USB_DEVICE(USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_ACCUTOUCH_2216) }, diff --git a/drivers/hid/hid-elecom.c b/drivers/hid/hid-elecom.c index 6e3848a8d8dd..e2c7465df69f 100644 --- a/drivers/hid/hid-elecom.c +++ b/drivers/hid/hid-elecom.c @@ -1,10 +1,8 @@ /* - * HID driver for Elecom BM084 (bluetooth mouse). - * Removes a non-existing horizontal wheel from - * the HID descriptor. - * (This module is based on "hid-ortek".) - * + * HID driver for ELECOM devices. * Copyright (c) 2010 Richard Nauber + * Copyright (c) 2016 Yuxuan Shui + * Copyright (c) 2017 Diego Elio Pettenò */ /* @@ -23,15 +21,61 @@ static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { - if (*rsize >= 48 && rdesc[46] == 0x05 && rdesc[47] == 0x0c) { - hid_info(hdev, "Fixing up Elecom BM084 report descriptor\n"); - rdesc[47] = 0x00; + switch (hdev->product) { + case USB_DEVICE_ID_ELECOM_BM084: + /* The BM084 Bluetooth mouse includes a non-existing horizontal + * wheel in the HID descriptor. */ + if (*rsize >= 48 && rdesc[46] == 0x05 && rdesc[47] == 0x0c) { + hid_info(hdev, "Fixing up Elecom BM084 report descriptor\n"); + rdesc[47] = 0x00; + } + break; + case USB_DEVICE_ID_ELECOM_DEFT_WIRED: + case USB_DEVICE_ID_ELECOM_DEFT_WIRELESS: + /* The DEFT trackball has eight buttons, but its descriptor only + * reports five, disabling the three Fn buttons on the top of + * the mouse. + * + * Apply the following diff to the descriptor: + * + * Collection (Physical), Collection (Physical), + * Report ID (1), Report ID (1), + * Report Count (5), -> Report Count (8), + * Report Size (1), Report Size (1), + * Usage Page (Button), Usage Page (Button), + * Usage Minimum (01h), Usage Minimum (01h), + * Usage Maximum (05h), -> Usage Maximum (08h), + * Logical Minimum (0), Logical Minimum (0), + * Logical Maximum (1), Logical Maximum (1), + * Input (Variable), Input (Variable), + * Report Count (1), -> Report Count (0), + * Report Size (3), Report Size (3), + * Input (Constant), Input (Constant), + * Report Size (16), Report Size (16), + * Report Count (2), Report Count (2), + * Usage Page (Desktop), Usage Page (Desktop), + * Usage (X), Usage (X), + * Usage (Y), Usage (Y), + * Logical Minimum (-32768), Logical Minimum (-32768), + * Logical Maximum (32767), Logical Maximum (32767), + * Input (Variable, Relative), Input (Variable, Relative), + * End Collection, End Collection, + */ + if (*rsize == 213 && rdesc[13] == 5 && rdesc[21] == 5) { + hid_info(hdev, "Fixing up Elecom DEFT Fn buttons\n"); + rdesc[13] = 8; /* Button/Variable Report Count */ + rdesc[21] = 8; /* Button/Variable Usage Maximum */ + rdesc[29] = 0; /* Button/Constant Report Count */ + } + break; } return rdesc; } static const struct hid_device_id elecom_devices[] = { - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084)}, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRED) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRELESS) }, { } }; MODULE_DEVICE_TABLE(hid, elecom_devices); diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 643390ba749d..8e8a1baee090 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -358,6 +358,8 @@ #define USB_VENDOR_ID_ELECOM 0x056e #define USB_DEVICE_ID_ELECOM_BM084 0x0061 +#define USB_DEVICE_ID_ELECOM_DEFT_WIRED 0x00fe +#define USB_DEVICE_ID_ELECOM_DEFT_WIRELESS 0x00ff #define USB_VENDOR_ID_DREAM_CHEEKY 0x1d34 #define USB_DEVICE_ID_DREAM_CHEEKY_WN 0x0004 -- cgit v1.2.3 From ab1b732d53c18f26f51cad49371be3244fe67504 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Thu, 4 May 2017 14:09:10 +0530 Subject: ASoC: Intel: Skylake: Move i915 registration to worker thread The i915 component framework expects the caller to be invoking snd_hdac_i915_init() from a thread context. Otherwise it results in lockups on drm side. So move the registering of component interface and probing of codecs on this bus to a worker thread. init_failed in skl structure is not used currently, so renamed to init_done and used to track the initialization done in worker thread. Reported-by: Imre Deak Signed-off-by: Vinod Koul Signed-off-by: Sodhi, VunnyX Signed-off-by: Subhransu S. Prusty Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl.c | 162 +++++++++++++++++++++++------------------- sound/soc/intel/skylake/skl.h | 4 +- 2 files changed, 91 insertions(+), 75 deletions(-) diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index 6df3b317a476..4c9b5781282b 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c @@ -410,7 +410,7 @@ static int skl_free(struct hdac_ext_bus *ebus) struct skl *skl = ebus_to_skl(ebus); struct hdac_bus *bus = ebus_to_hbus(ebus); - skl->init_failed = 1; /* to be sure */ + skl->init_done = 0; /* to be sure */ snd_hdac_ext_stop_streams(ebus); @@ -428,8 +428,10 @@ static int skl_free(struct hdac_ext_bus *ebus) snd_hdac_ext_bus_exit(ebus); + cancel_work_sync(&skl->probe_work); if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) snd_hdac_i915_exit(&ebus->bus); + return 0; } @@ -566,6 +568,84 @@ static const struct hdac_bus_ops bus_core_ops = { .get_response = snd_hdac_bus_get_response, }; +static int skl_i915_init(struct hdac_bus *bus) +{ + int err; + + /* + * The HDMI codec is in GPU so we need to ensure that it is powered + * up and ready for probe + */ + err = snd_hdac_i915_init(bus); + if (err < 0) + return err; + + err = snd_hdac_display_power(bus, true); + if (err < 0) + dev_err(bus->dev, "Cannot turn on display power on i915\n"); + + return err; +} + +static void skl_probe_work(struct work_struct *work) +{ + struct skl *skl = container_of(work, struct skl, probe_work); + struct hdac_ext_bus *ebus = &skl->ebus; + struct hdac_bus *bus = ebus_to_hbus(ebus); + struct hdac_ext_link *hlink = NULL; + int err; + + if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) { + err = skl_i915_init(bus); + if (err < 0) + return; + } + + err = skl_init_chip(bus, true); + if (err < 0) { + dev_err(bus->dev, "Init chip failed with err: %d\n", err); + goto out_err; + } + + /* codec detection */ + if (!bus->codec_mask) + dev_info(bus->dev, "no hda codecs found!\n"); + + /* create codec instances */ + err = skl_codec_create(ebus); + if (err < 0) + goto out_err; + + if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) { + err = snd_hdac_display_power(bus, false); + if (err < 0) { + dev_err(bus->dev, "Cannot turn off display power on i915\n"); + return; + } + } + + /* register platform dai and controls */ + err = skl_platform_register(bus->dev); + if (err < 0) + return; + /* + * we are done probing so decrement link counts + */ + list_for_each_entry(hlink, &ebus->hlink_list, list) + snd_hdac_ext_bus_link_put(ebus, hlink); + + /* configure PM */ + pm_runtime_put_noidle(bus->dev); + pm_runtime_allow(bus->dev); + skl->init_done = 1; + + return; + +out_err: + if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) + err = snd_hdac_display_power(bus, false); +} + /* * constructor */ @@ -593,6 +673,7 @@ static int skl_create(struct pci_dev *pci, snd_hdac_ext_bus_init(ebus, &pci->dev, &bus_core_ops, io_ops); ebus->bus.use_posbuf = 1; skl->pci = pci; + INIT_WORK(&skl->probe_work, skl_probe_work); ebus->bus.bdl_pos_adj = 0; @@ -601,27 +682,6 @@ static int skl_create(struct pci_dev *pci, return 0; } -static int skl_i915_init(struct hdac_bus *bus) -{ - int err; - - /* - * The HDMI codec is in GPU so we need to ensure that it is powered - * up and ready for probe - */ - err = snd_hdac_i915_init(bus); - if (err < 0) - return err; - - err = snd_hdac_display_power(bus, true); - if (err < 0) { - dev_err(bus->dev, "Cannot turn on display power on i915\n"); - return err; - } - - return err; -} - static int skl_first_init(struct hdac_ext_bus *ebus) { struct skl *skl = ebus_to_skl(ebus); @@ -684,20 +744,7 @@ static int skl_first_init(struct hdac_ext_bus *ebus) /* initialize chip */ skl_init_pci(skl); - if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) { - err = skl_i915_init(bus); - if (err < 0) - return err; - } - - skl_init_chip(bus, true); - - /* codec detection */ - if (!bus->codec_mask) { - dev_info(bus->dev, "no hda codecs found!\n"); - } - - return 0; + return skl_init_chip(bus, true); } static int skl_probe(struct pci_dev *pci, @@ -706,7 +753,6 @@ static int skl_probe(struct pci_dev *pci, struct skl *skl; struct hdac_ext_bus *ebus = NULL; struct hdac_bus *bus = NULL; - struct hdac_ext_link *hlink = NULL; int err; /* we use ext core ops, so provide NULL for ops here */ @@ -729,7 +775,7 @@ static int skl_probe(struct pci_dev *pci, if (skl->nhlt == NULL) { err = -ENODEV; - goto out_display_power_off; + goto out_free; } err = skl_nhlt_create_sysfs(skl); @@ -760,56 +806,24 @@ static int skl_probe(struct pci_dev *pci, if (bus->mlcap) snd_hdac_ext_bus_get_ml_capabilities(ebus); + snd_hdac_bus_stop_chip(bus); + /* create device for soc dmic */ err = skl_dmic_device_register(skl); if (err < 0) goto out_dsp_free; - /* register platform dai and controls */ - err = skl_platform_register(bus->dev); - if (err < 0) - goto out_dmic_free; - - /* create codec instances */ - err = skl_codec_create(ebus); - if (err < 0) - goto out_unregister; - - if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) { - err = snd_hdac_display_power(bus, false); - if (err < 0) { - dev_err(bus->dev, "Cannot turn off display power on i915\n"); - return err; - } - } - - /* - * we are done probling so decrement link counts - */ - list_for_each_entry(hlink, &ebus->hlink_list, list) - snd_hdac_ext_bus_link_put(ebus, hlink); - - /* configure PM */ - pm_runtime_put_noidle(bus->dev); - pm_runtime_allow(bus->dev); + schedule_work(&skl->probe_work); return 0; -out_unregister: - skl_platform_unregister(bus->dev); -out_dmic_free: - skl_dmic_device_unregister(skl); out_dsp_free: skl_free_dsp(skl); out_mach_free: skl_machine_device_unregister(skl); out_nhlt_free: skl_nhlt_free(skl->nhlt); -out_display_power_off: - if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) - snd_hdac_display_power(bus, false); out_free: - skl->init_failed = 1; skl_free(ebus); return err; @@ -828,7 +842,7 @@ static void skl_shutdown(struct pci_dev *pci) skl = ebus_to_skl(ebus); - if (skl->init_failed) + if (!skl->init_done) return; snd_hdac_ext_stop_streams(ebus); diff --git a/sound/soc/intel/skylake/skl.h b/sound/soc/intel/skylake/skl.h index a454f6035f3e..2a630fcb7f08 100644 --- a/sound/soc/intel/skylake/skl.h +++ b/sound/soc/intel/skylake/skl.h @@ -46,7 +46,7 @@ struct skl { struct hdac_ext_bus ebus; struct pci_dev *pci; - unsigned int init_failed:1; /* delayed init failed */ + unsigned int init_done:1; /* delayed init status */ struct platform_device *dmic_dev; struct platform_device *i2s_dev; struct snd_soc_platform *platform; @@ -64,6 +64,8 @@ struct skl { const struct firmware *tplg; int supend_active; + + struct work_struct probe_work; }; #define skl_to_ebus(s) (&(s)->ebus) -- cgit v1.2.3 From fe0dfd6358a17c79bd7d6996af7512ba452a7059 Mon Sep 17 00:00:00 2001 From: Yifeng Li Date: Thu, 4 May 2017 01:34:14 +0800 Subject: rt286: add Thinkpad Helix 2 to force_combo_jack_table Thinkpad Helix 2 is a tablet PC, the audio is powered by Core M broadwell-audio and rt286 codec. For all versions of Linux kernel, the stereo output doesn't work properly when earphones are plugged in, the sound was coming out from both channels even if the audio contains only the left or right channel. Furthermore, if a music recorded in stereo is played, the two channels cancle out each other out, as a result, no voice but only distorted background music can be heard, like a sound card with builtin a Karaoke sount effect. Apparently this tablet uses a combo jack with polarity incorrectly set by rt286 driver. This patch adds DMI information of Thinkpad Helix 2 to force_combo_jack_table[] and the issue is resolved. The microphone input doesn't work regardless to the presence of this patch and still needs help from other developers to investigate. This is my first patch to LKML directly, sorry for CC-ing too many people here. Link: https://bugzilla.kernel.org/show_bug.cgi?id=93841 Signed-off-by: Yifeng Li Signed-off-by: Mark Brown --- sound/soc/codecs/rt286.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c index 9c365a7f758d..7899a2cdeb42 100644 --- a/sound/soc/codecs/rt286.c +++ b/sound/soc/codecs/rt286.c @@ -1108,6 +1108,13 @@ static const struct dmi_system_id force_combo_jack_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Kabylake Client platform") } }, + { + .ident = "Thinkpad Helix 2nd", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad Helix 2nd") + } + }, { } }; -- cgit v1.2.3 From 14f814fbedd749992476bb365b454b2170b3b225 Mon Sep 17 00:00:00 2001 From: Adam Thomson Date: Wed, 3 May 2017 16:15:53 +0100 Subject: ASoC: da7213: Fix incorrect usage of bitwise '&' operator for SRM check In the SRM lock check section of code the '&' bitwise operator is used as part of checking lock status. Functionally the code works as intended, but the conditional statement is a boolean comparison so should really use '&&' logical operator instead. This commit rectifies this discrepancy. Signed-off-by: Adam Thomson Signed-off-by: Mark Brown --- sound/soc/codecs/da7213.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/da7213.c b/sound/soc/codecs/da7213.c index 6dd7578f0bb8..024d83fa6a7f 100644 --- a/sound/soc/codecs/da7213.c +++ b/sound/soc/codecs/da7213.c @@ -772,7 +772,7 @@ static int da7213_dai_event(struct snd_soc_dapm_widget *w, ++i; msleep(50); } - } while ((i < DA7213_SRM_CHECK_RETRIES) & (!srm_lock)); + } while ((i < DA7213_SRM_CHECK_RETRIES) && (!srm_lock)); if (!srm_lock) dev_warn(codec->dev, "SRM failed to lock\n"); -- cgit v1.2.3 From eb8df543e444492328f506adffc7dfe94111f1bd Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Fri, 5 May 2017 11:57:44 +0200 Subject: dmaengine: mv_xor_v2: handle mv_xor_v2_prep_sw_desc() error properly The mv_xor_v2_prep_sw_desc() is called from a few different places in the driver, but we never take into account the fact that it might return NULL. This commit fixes that, ensuring that we don't panic if there are no more descriptors available. Fixes: 19a340b1a820 ("dmaengine: mv_xor_v2: new driver") Cc: Signed-off-by: Thomas Petazzoni Signed-off-by: Vinod Koul --- drivers/dma/mv_xor_v2.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/dma/mv_xor_v2.c b/drivers/dma/mv_xor_v2.c index a28a01fcba67..e9280207ac19 100644 --- a/drivers/dma/mv_xor_v2.c +++ b/drivers/dma/mv_xor_v2.c @@ -389,6 +389,8 @@ mv_xor_v2_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, __func__, len, &src, &dest, flags); sw_desc = mv_xor_v2_prep_sw_desc(xor_dev); + if (!sw_desc) + return NULL; sw_desc->async_tx.flags = flags; @@ -443,6 +445,8 @@ mv_xor_v2_prep_dma_xor(struct dma_chan *chan, dma_addr_t dest, dma_addr_t *src, __func__, src_cnt, len, &dest, flags); sw_desc = mv_xor_v2_prep_sw_desc(xor_dev); + if (!sw_desc) + return NULL; sw_desc->async_tx.flags = flags; @@ -491,6 +495,8 @@ mv_xor_v2_prep_dma_interrupt(struct dma_chan *chan, unsigned long flags) container_of(chan, struct mv_xor_v2_device, dmachan); sw_desc = mv_xor_v2_prep_sw_desc(xor_dev); + if (!sw_desc) + return NULL; /* set the HW descriptor */ hw_descriptor = &sw_desc->hw_desc; -- cgit v1.2.3 From 2aab4e18152cd30cb5d2f4c27629fc8a04aed979 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Fri, 5 May 2017 11:57:45 +0200 Subject: dmaengine: mv_xor_v2: properly handle wrapping in the array of HW descriptors mv_xor_v2_tasklet() is looping over completed HW descriptors. Before the loop, it initializes 'next_pending_hw_desc' to the first HW descriptor to handle, and then the loop simply increments this point, without taking care of wrapping when we reach the last HW descriptor. The 'pending_ptr' index was being wrapped back to 0 at the end, but it wasn't used in each iteration of the loop to calculate next_pending_hw_desc. This commit fixes that, and makes next_pending_hw_desc a variable local to the loop itself. Fixes: 19a340b1a820 ("dmaengine: mv_xor_v2: new driver") Cc: Signed-off-by: Thomas Petazzoni Signed-off-by: Vinod Koul --- drivers/dma/mv_xor_v2.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/drivers/dma/mv_xor_v2.c b/drivers/dma/mv_xor_v2.c index e9280207ac19..bdfb36ecff81 100644 --- a/drivers/dma/mv_xor_v2.c +++ b/drivers/dma/mv_xor_v2.c @@ -560,7 +560,6 @@ static void mv_xor_v2_tasklet(unsigned long data) { struct mv_xor_v2_device *xor_dev = (struct mv_xor_v2_device *) data; int pending_ptr, num_of_pending, i; - struct mv_xor_v2_descriptor *next_pending_hw_desc = NULL; struct mv_xor_v2_sw_desc *next_pending_sw_desc = NULL; dev_dbg(xor_dev->dmadev.dev, "%s %d\n", __func__, __LINE__); @@ -568,17 +567,10 @@ static void mv_xor_v2_tasklet(unsigned long data) /* get the pending descriptors parameters */ num_of_pending = mv_xor_v2_get_pending_params(xor_dev, &pending_ptr); - /* next HW descriptor */ - next_pending_hw_desc = xor_dev->hw_desq_virt + pending_ptr; - /* loop over free descriptors */ for (i = 0; i < num_of_pending; i++) { - - if (pending_ptr > MV_XOR_V2_DESC_NUM) - pending_ptr = 0; - - if (next_pending_sw_desc != NULL) - next_pending_hw_desc++; + struct mv_xor_v2_descriptor *next_pending_hw_desc = + xor_dev->hw_desq_virt + pending_ptr; /* get the SW descriptor related to the HW descriptor */ next_pending_sw_desc = @@ -614,6 +606,8 @@ static void mv_xor_v2_tasklet(unsigned long data) /* increment the next descriptor */ pending_ptr++; + if (pending_ptr >= MV_XOR_V2_DESC_NUM) + pending_ptr = 0; } if (num_of_pending != 0) { -- cgit v1.2.3 From bc473da1ed726c975ad47f8d7d27631de11356d8 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Fri, 5 May 2017 11:57:46 +0200 Subject: dmaengine: mv_xor_v2: do not use descriptors not acked by async_tx Descriptors that have not been acknowledged by the async_tx layer should not be re-used, so this commit adjusts the implementation of mv_xor_v2_prep_sw_desc() to skip descriptors for which async_tx_test_ack() is false. Fixes: 19a340b1a820 ("dmaengine: mv_xor_v2: new driver") Cc: Signed-off-by: Thomas Petazzoni Signed-off-by: Vinod Koul --- drivers/dma/mv_xor_v2.c | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/drivers/dma/mv_xor_v2.c b/drivers/dma/mv_xor_v2.c index bdfb36ecff81..cb60e7c4aa16 100644 --- a/drivers/dma/mv_xor_v2.c +++ b/drivers/dma/mv_xor_v2.c @@ -344,6 +344,7 @@ static struct mv_xor_v2_sw_desc * mv_xor_v2_prep_sw_desc(struct mv_xor_v2_device *xor_dev) { struct mv_xor_v2_sw_desc *sw_desc; + bool found = false; /* Lock the channel */ spin_lock_bh(&xor_dev->lock); @@ -355,19 +356,23 @@ mv_xor_v2_prep_sw_desc(struct mv_xor_v2_device *xor_dev) return NULL; } - /* get a free SW descriptor from the SW DESQ */ - sw_desc = list_first_entry(&xor_dev->free_sw_desc, - struct mv_xor_v2_sw_desc, free_list); + list_for_each_entry(sw_desc, &xor_dev->free_sw_desc, free_list) { + if (async_tx_test_ack(&sw_desc->async_tx)) { + found = true; + break; + } + } + + if (!found) { + spin_unlock_bh(&xor_dev->lock); + return NULL; + } + list_del(&sw_desc->free_list); /* Release the channel */ spin_unlock_bh(&xor_dev->lock); - /* set the async tx descriptor */ - dma_async_tx_descriptor_init(&sw_desc->async_tx, &xor_dev->dmachan); - sw_desc->async_tx.tx_submit = mv_xor_v2_tx_submit; - async_tx_ack(&sw_desc->async_tx); - return sw_desc; } @@ -785,8 +790,15 @@ static int mv_xor_v2_probe(struct platform_device *pdev) /* add all SW descriptors to the free list */ for (i = 0; i < MV_XOR_V2_DESC_NUM; i++) { - xor_dev->sw_desq[i].idx = i; - list_add(&xor_dev->sw_desq[i].free_list, + struct mv_xor_v2_sw_desc *sw_desc = + xor_dev->sw_desq + i; + sw_desc->idx = i; + dma_async_tx_descriptor_init(&sw_desc->async_tx, + &xor_dev->dmachan); + sw_desc->async_tx.tx_submit = mv_xor_v2_tx_submit; + async_tx_ack(&sw_desc->async_tx); + + list_add(&sw_desc->free_list, &xor_dev->free_sw_desc); } -- cgit v1.2.3 From ab2c5f0a77fe49bdb6e307b397496373cb47d2c2 Mon Sep 17 00:00:00 2001 From: Hanna Hawa Date: Fri, 5 May 2017 11:57:47 +0200 Subject: dmaengine: mv_xor_v2: enable XOR engine after its configuration The engine was enabled prior to its configuration, which isn't correct. This patch relocates the activation of the XOR engine, to be after the configuration of the XOR engine. Fixes: 19a340b1a820 ("dmaengine: mv_xor_v2: new driver") Cc: Signed-off-by: Hanna Hawa Signed-off-by: Thomas Petazzoni Signed-off-by: Vinod Koul --- drivers/dma/mv_xor_v2.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/dma/mv_xor_v2.c b/drivers/dma/mv_xor_v2.c index cb60e7c4aa16..211b8c0e3cfb 100644 --- a/drivers/dma/mv_xor_v2.c +++ b/drivers/dma/mv_xor_v2.c @@ -653,9 +653,6 @@ static int mv_xor_v2_descq_init(struct mv_xor_v2_device *xor_dev) writel((xor_dev->hw_desq & 0xFFFF00000000) >> 32, xor_dev->dma_base + MV_XOR_V2_DMA_DESQ_BAHR_OFF); - /* enable the DMA engine */ - writel(0, xor_dev->dma_base + MV_XOR_V2_DMA_DESQ_STOP_OFF); - /* * This is a temporary solution, until we activate the * SMMU. Set the attributes for reading & writing data buffers @@ -699,6 +696,9 @@ static int mv_xor_v2_descq_init(struct mv_xor_v2_device *xor_dev) reg |= MV_XOR_V2_GLOB_PAUSE_AXI_TIME_DIS_VAL; writel(reg, xor_dev->glob_base + MV_XOR_V2_GLOB_PAUSE); + /* enable the DMA engine */ + writel(0, xor_dev->dma_base + MV_XOR_V2_DMA_DESQ_STOP_OFF); + return 0; } -- cgit v1.2.3 From 44d5887a8bf1e86915c8ff647337cb138149da82 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Fri, 5 May 2017 11:57:48 +0200 Subject: dmaengine: mv_xor_v2: fix tx_submit() implementation The mv_xor_v2_tx_submit() gets the next available HW descriptor by calling mv_xor_v2_get_desq_write_ptr(), which reads a HW register telling the next available HW descriptor. This was working fine when HW descriptors were issued for processing directly in tx_submit(). However, as part of the review process of the driver, a change was requested to move the actual kick-off of HW descriptors processing to ->issue_pending(). Due to this, reading the HW register to know the next available HW descriptor no longer works. So instead of using this HW register, we implemented a software index pointing to the next available HW descriptor. Fixes: 19a340b1a820 ("dmaengine: mv_xor_v2: new driver") Cc: Signed-off-by: Thomas Petazzoni Signed-off-by: Vinod Koul --- drivers/dma/mv_xor_v2.c | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/drivers/dma/mv_xor_v2.c b/drivers/dma/mv_xor_v2.c index 211b8c0e3cfb..4684eceea759 100644 --- a/drivers/dma/mv_xor_v2.c +++ b/drivers/dma/mv_xor_v2.c @@ -161,6 +161,7 @@ struct mv_xor_v2_device { struct mv_xor_v2_sw_desc *sw_desq; int desc_size; unsigned int npendings; + unsigned int hw_queue_idx; }; /** @@ -213,18 +214,6 @@ static void mv_xor_v2_set_data_buffers(struct mv_xor_v2_device *xor_dev, } } -/* - * Return the next available index in the DESQ. - */ -static int mv_xor_v2_get_desq_write_ptr(struct mv_xor_v2_device *xor_dev) -{ - /* read the index for the next available descriptor in the DESQ */ - u32 reg = readl(xor_dev->dma_base + MV_XOR_V2_DMA_DESQ_ALLOC_OFF); - - return ((reg >> MV_XOR_V2_DMA_DESQ_ALLOC_WRPTR_SHIFT) - & MV_XOR_V2_DMA_DESQ_ALLOC_WRPTR_MASK); -} - /* * notify the engine of new descriptors, and update the available index. */ @@ -306,7 +295,6 @@ static irqreturn_t mv_xor_v2_interrupt_handler(int irq, void *data) static dma_cookie_t mv_xor_v2_tx_submit(struct dma_async_tx_descriptor *tx) { - int desq_ptr; void *dest_hw_desc; dma_cookie_t cookie; struct mv_xor_v2_sw_desc *sw_desc = @@ -322,15 +310,15 @@ mv_xor_v2_tx_submit(struct dma_async_tx_descriptor *tx) spin_lock_bh(&xor_dev->lock); cookie = dma_cookie_assign(tx); - /* get the next available slot in the DESQ */ - desq_ptr = mv_xor_v2_get_desq_write_ptr(xor_dev); - /* copy the HW descriptor from the SW descriptor to the DESQ */ - dest_hw_desc = xor_dev->hw_desq_virt + desq_ptr; + dest_hw_desc = xor_dev->hw_desq_virt + xor_dev->hw_queue_idx; memcpy(dest_hw_desc, &sw_desc->hw_desc, xor_dev->desc_size); xor_dev->npendings++; + xor_dev->hw_queue_idx++; + if (xor_dev->hw_queue_idx >= MV_XOR_V2_DESC_NUM) + xor_dev->hw_queue_idx = 0; spin_unlock_bh(&xor_dev->lock); -- cgit v1.2.3 From 9dd4f319bac25334a869d9276b19eac9e478fd33 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Fri, 5 May 2017 11:57:49 +0200 Subject: dmaengine: mv_xor_v2: remove interrupt coalescing The current implementation of interrupt coalescing doesn't work, because it doesn't configure the coalescing timer, which is needed to make sure we get an interrupt at some point. As a fix for stable, we simply remove the interrupt coalescing functionality. It will be re-introduced properly in a future commit. Fixes: 19a340b1a820 ("dmaengine: mv_xor_v2: new driver") Cc: Signed-off-by: Thomas Petazzoni Signed-off-by: Vinod Koul --- drivers/dma/mv_xor_v2.c | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/drivers/dma/mv_xor_v2.c b/drivers/dma/mv_xor_v2.c index 4684eceea759..b133fe29d788 100644 --- a/drivers/dma/mv_xor_v2.c +++ b/drivers/dma/mv_xor_v2.c @@ -246,22 +246,6 @@ static int mv_xor_v2_set_desc_size(struct mv_xor_v2_device *xor_dev) return MV_XOR_V2_EXT_DESC_SIZE; } -/* - * Set the IMSG threshold - */ -static inline -void mv_xor_v2_set_imsg_thrd(struct mv_xor_v2_device *xor_dev, int thrd_val) -{ - u32 reg; - - reg = readl(xor_dev->dma_base + MV_XOR_V2_DMA_IMSG_THRD_OFF); - - reg &= (~MV_XOR_V2_DMA_IMSG_THRD_MASK << MV_XOR_V2_DMA_IMSG_THRD_SHIFT); - reg |= (thrd_val << MV_XOR_V2_DMA_IMSG_THRD_SHIFT); - - writel(reg, xor_dev->dma_base + MV_XOR_V2_DMA_IMSG_THRD_OFF); -} - static irqreturn_t mv_xor_v2_interrupt_handler(int irq, void *data) { struct mv_xor_v2_device *xor_dev = data; @@ -277,12 +261,6 @@ static irqreturn_t mv_xor_v2_interrupt_handler(int irq, void *data) if (!ndescs) return IRQ_NONE; - /* - * Update IMSG threshold, to disable new IMSG interrupts until - * end of the tasklet - */ - mv_xor_v2_set_imsg_thrd(xor_dev, MV_XOR_V2_DESC_NUM); - /* schedule a tasklet to handle descriptors callbacks */ tasklet_schedule(&xor_dev->irq_tasklet); @@ -607,9 +585,6 @@ static void mv_xor_v2_tasklet(unsigned long data) /* free the descriptores */ mv_xor_v2_free_desc_from_desq(xor_dev, num_of_pending); } - - /* Update IMSG threshold, to enable new IMSG interrupts */ - mv_xor_v2_set_imsg_thrd(xor_dev, 0); } /* -- cgit v1.2.3 From b2d3c270f9f2fb82518ac500a9849c3aaf503852 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Fri, 5 May 2017 11:57:50 +0200 Subject: dmaengine: mv_xor_v2: set DMA mask to 40 bits The XORv2 engine on Armada 7K/8K can only access the first 40 bits of the physical address space, so the DMA mask must be set accordingly. Fixes: 19a340b1a820 ("dmaengine: mv_xor_v2: new driver") Cc: Signed-off-by: Thomas Petazzoni Signed-off-by: Vinod Koul --- drivers/dma/mv_xor_v2.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/dma/mv_xor_v2.c b/drivers/dma/mv_xor_v2.c index b133fe29d788..f3e211f8f6c5 100644 --- a/drivers/dma/mv_xor_v2.c +++ b/drivers/dma/mv_xor_v2.c @@ -693,6 +693,10 @@ static int mv_xor_v2_probe(struct platform_device *pdev) platform_set_drvdata(pdev, xor_dev); + ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(40)); + if (ret) + return ret; + xor_dev->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(xor_dev->clk) && PTR_ERR(xor_dev->clk) == -EPROBE_DEFER) return -EPROBE_DEFER; -- cgit v1.2.3 From 5ba5b437efaa7a502eec393c045d3bf90c92c4e9 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 10 May 2017 08:51:09 +0300 Subject: iio: adc: ti_am335x_adc: allocating too much in probe We should be allocating enough information for a tiadc_device struct which is about 400 bytes but instead we allocate enough for a second iio_dev struct which is over 2000 bytes. Fixes: fea89e2dfcea ("iio: adc: ti_am335x_adc: use variable names for sizeof() operator") Signed-off-by: Dan Carpenter Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ti_am335x_adc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c index 4282ceca3d8f..6cbed7eb118a 100644 --- a/drivers/iio/adc/ti_am335x_adc.c +++ b/drivers/iio/adc/ti_am335x_adc.c @@ -614,7 +614,7 @@ static int tiadc_probe(struct platform_device *pdev) return -EINVAL; } - indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*indio_dev)); + indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*adc_dev)); if (indio_dev == NULL) { dev_err(&pdev->dev, "failed to allocate iio device\n"); return -ENOMEM; -- cgit v1.2.3 From c54517196811b0561079833c147083ab2c9cc5e1 Mon Sep 17 00:00:00 2001 From: Jacopo Mondi Date: Tue, 9 May 2017 09:57:57 +0200 Subject: iio: adc: max9611: Fix attribute measure unit The power and current "shunt-resistor" attribute's 'show' function displays the resistor value in milli-Ohms, while the ABI description specifies it should be displayed in Ohms. Fix it. Reported-by: Geert Uytterhoeven Signed-off-by: Jacopo Mondi Tested-by: Geert Uytterhoeven Signed-off-by: Jonathan Cameron --- drivers/iio/adc/max9611.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/iio/adc/max9611.c b/drivers/iio/adc/max9611.c index dc3869bf3248..b0526e4b9530 100644 --- a/drivers/iio/adc/max9611.c +++ b/drivers/iio/adc/max9611.c @@ -438,10 +438,10 @@ static ssize_t max9611_shunt_resistor_show(struct device *dev, struct max9611_dev *max9611 = iio_priv(dev_to_iio_dev(dev)); unsigned int i, r; - i = max9611->shunt_resistor_uohm / 1000; - r = max9611->shunt_resistor_uohm % 1000; + i = max9611->shunt_resistor_uohm / 1000000; + r = max9611->shunt_resistor_uohm % 1000000; - return sprintf(buf, "%u.%03u\n", i, r); + return sprintf(buf, "%u.%06u\n", i, r); } static IIO_DEVICE_ATTR(in_power_shunt_resistor, 0444, -- cgit v1.2.3 From 72d42504bd7faa6de1c1644b5e46652933e040a6 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 11 May 2017 13:34:29 +0200 Subject: ovl: select EXPORTFS We get a link error when EXPORTFS is not enabled: ERROR: "exportfs_encode_fh" [fs/overlayfs/overlay.ko] undefined! ERROR: "exportfs_decode_fh" [fs/overlayfs/overlay.ko] undefined! This adds a Kconfig 'select' statement for overlayfs, the same way that it is done for the other users of exportfs. Fixes: 3a1e819b4e80 ("ovl: store file handle of lower inode on copy up") Signed-off-by: Arnd Bergmann Signed-off-by: Miklos Szeredi --- fs/overlayfs/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/overlayfs/Kconfig b/fs/overlayfs/Kconfig index 0daac5112f7a..c0c9683934b7 100644 --- a/fs/overlayfs/Kconfig +++ b/fs/overlayfs/Kconfig @@ -1,5 +1,6 @@ config OVERLAY_FS tristate "Overlay filesystem support" + select EXPORTFS help An overlay filesystem combines two filesystems - an 'upper' filesystem and a 'lower' filesystem. When a name exists in both filesystems, the -- cgit v1.2.3 From 41b80bb1db5c4c547cf187d1bc0c6c6feb7c14af Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 19 Apr 2017 19:48:07 +0200 Subject: memory: atmel-ebi: mark PM ops as __maybe_unused We get a harmless warning without CONFIG_PM: drivers/memory/atmel-ebi.c:584:12: error: 'atmel_ebi_resume' defined but not used [-Werror=unused-function] Marking the function as __maybe_unused does the right thing here and drops it silently when unused. Fixes: a483fb10e5ea ("memory: atmel-ebi: Add PM ops") Signed-off-by: Arnd Bergmann Signed-off-by: Alexandre Belloni --- drivers/memory/atmel-ebi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/memory/atmel-ebi.c b/drivers/memory/atmel-ebi.c index 35910f945bfa..99e644cda4d1 100644 --- a/drivers/memory/atmel-ebi.c +++ b/drivers/memory/atmel-ebi.c @@ -581,7 +581,7 @@ static int atmel_ebi_probe(struct platform_device *pdev) return of_platform_populate(np, NULL, NULL, dev); } -static int atmel_ebi_resume(struct device *dev) +static __maybe_unused int atmel_ebi_resume(struct device *dev) { struct atmel_ebi *ebi = dev_get_drvdata(dev); struct atmel_ebi_dev *ebid; -- cgit v1.2.3 From b0804ed0cadd7e38d94d2f15cdcc0d9695818856 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 9 May 2017 10:04:30 +0100 Subject: ARM: dts: bcm283x: Reserve first page for firmware The Raspberry Pi startup stub files for multi-core BCM283X processors make the secondary CPUs spin until the corresponding mailbox is written. These stubs are loaded at physical address 0x00000xxx (as seen by the ARMs), but this page will be reused by the kernel unless it is explicitly reserved, causing the waiting cores to execute random code. Use the /memreserve/ Device Tree directive to mark the first page as off-limits to the kernel. See: https://github.com/raspberrypi/linux/issues/1989 Signed-off-by: Phil Elwell Signed-off-by: Eric Anholt Reviewed-by: Eric Anholt --- arch/arm/boot/dts/bcm283x.dtsi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm/boot/dts/bcm283x.dtsi b/arch/arm/boot/dts/bcm283x.dtsi index 35cea3fcaf5c..1ac7c0dc6577 100644 --- a/arch/arm/boot/dts/bcm283x.dtsi +++ b/arch/arm/boot/dts/bcm283x.dtsi @@ -3,6 +3,11 @@ #include #include +/* firmware-provided startup stubs live here, where the secondary CPUs are + * spinning. + */ +/memreserve/ 0x00000000 0x00001000; + /* This include file covers the common peripherals and configuration between * bcm2835 and bcm2836 implementations, leaving the CPU configuration to * bcm2835.dtsi and bcm2836.dtsi. -- cgit v1.2.3 From 98883f1b5415ea9dce60d5178877d15f4faa10b8 Mon Sep 17 00:00:00 2001 From: "Bryant G. Ly" Date: Tue, 9 May 2017 11:50:26 -0500 Subject: ibmvscsis: Clear left-over abort_cmd pointers With the addition of ibmvscsis->abort_cmd pointer within commit 25e78531268e ("ibmvscsis: Do not send aborted task response"), make sure to explicitly NULL these pointers when clearing DELAY_SEND flag. Do this for two cases, when getting the new new ibmvscsis descriptor in ibmvscsis_get_free_cmd() and before posting the response completion in ibmvscsis_send_messages(). Signed-off-by: Bryant G. Ly Reviewed-by: Michael Cyr Cc: # v4.8+ Signed-off-by: Nicholas Bellinger --- drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c index d390325c99ec..ee64241865e6 100644 --- a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c +++ b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c @@ -1170,6 +1170,8 @@ static struct ibmvscsis_cmd *ibmvscsis_get_free_cmd(struct scsi_info *vscsi) cmd = list_first_entry_or_null(&vscsi->free_cmd, struct ibmvscsis_cmd, list); if (cmd) { + if (cmd->abort_cmd) + cmd->abort_cmd = NULL; cmd->flags &= ~(DELAY_SEND); list_del(&cmd->list); cmd->iue = iue; @@ -1774,6 +1776,7 @@ static void ibmvscsis_send_messages(struct scsi_info *vscsi) if (cmd->abort_cmd) { retry = true; cmd->abort_cmd->flags &= ~(DELAY_SEND); + cmd->abort_cmd = NULL; } /* -- cgit v1.2.3 From 75dbf2d36f6b122ad3c1070fe4bf95f71bbff321 Mon Sep 17 00:00:00 2001 From: "Bryant G. Ly" Date: Wed, 10 May 2017 14:35:47 -0500 Subject: ibmvscsis: Fix the incorrect req_lim_delta The current code is not correctly calculating the req_lim_delta. We want to make sure vscsi->credit is always incremented when we do not send a response for the scsi op. Thus for the case where there is a successfully aborted task we need to make sure the vscsi->credit is incremented. v2 - Moves the original location of the vscsi->credit increment to a better spot. Since if we increment credit, the next command we send back will have increased req_lim_delta. But we probably shouldn't be doing that until the aborted cmd is actually released. Otherwise the client will think that it can send a new command, and we could find ourselves short of command elements. Not likely, but could happen. This patch depends on both: commit 25e78531268e ("ibmvscsis: Do not send aborted task response") commit 98883f1b5415 ("ibmvscsis: Clear left-over abort_cmd pointers") Signed-off-by: Bryant G. Ly Reviewed-by: Michael Cyr Cc: # v4.8+ Signed-off-by: Nicholas Bellinger --- drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c index ee64241865e6..abf6026645dd 100644 --- a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c +++ b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c @@ -1791,6 +1791,25 @@ static void ibmvscsis_send_messages(struct scsi_info *vscsi) list_del(&cmd->list); ibmvscsis_free_cmd_resources(vscsi, cmd); + /* + * With a successfully aborted op + * through LIO we want to increment the + * the vscsi credit so that when we dont + * send a rsp to the original scsi abort + * op (h_send_crq), but the tm rsp to + * the abort is sent, the credit is + * correctly sent with the abort tm rsp. + * We would need 1 for the abort tm rsp + * and 1 credit for the aborted scsi op. + * Thus we need to increment here. + * Also we want to increment the credit + * here because we want to make sure + * cmd is actually released first + * otherwise the client will think it + * it can send a new cmd, and we could + * find ourselves short of cmd elements. + */ + vscsi->credit += 1; } else { iue = cmd->iue; @@ -2965,10 +2984,7 @@ static long srp_build_response(struct scsi_info *vscsi, rsp->opcode = SRP_RSP; - if (vscsi->credit > 0 && vscsi->state == SRP_PROCESSING) - rsp->req_lim_delta = cpu_to_be32(vscsi->credit); - else - rsp->req_lim_delta = cpu_to_be32(1 + vscsi->credit); + rsp->req_lim_delta = cpu_to_be32(1 + vscsi->credit); rsp->tag = cmd->rsp.tag; rsp->flags = 0; -- cgit v1.2.3 From 4ff83daa0200affe1894bd33d17bac404e3d78d4 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Thu, 11 May 2017 01:07:24 -0700 Subject: target: Re-add check to reject control WRITEs with overflow data During v4.3 when the overflow/underflow check was relaxed by commit c72c525022: commit c72c5250224d475614a00c1d7e54a67f77cd3410 Author: Roland Dreier Date: Wed Jul 22 15:08:18 2015 -0700 target: allow underflow/overflow for PR OUT etc. commands to allow underflow/overflow for Windows compliance + FCP, a consequence was to allow control CDBs to process overflow data for iscsi-target with immediate data as well. As per Roland's original change, continue to allow underflow cases for control CDBs to make Windows compliance + FCP happy, but until overflow for control CDBs is supported tree-wide, explicitly reject all control WRITEs with overflow following pre v4.3.y logic. Reported-by: Bart Van Assche Cc: Roland Dreier Cc: # v4.3+ Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 37f57357d4a0..6025935036c9 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1160,15 +1160,28 @@ target_cmd_size_check(struct se_cmd *cmd, unsigned int size) if (cmd->unknown_data_length) { cmd->data_length = size; } else if (size != cmd->data_length) { - pr_warn("TARGET_CORE[%s]: Expected Transfer Length:" + pr_warn_ratelimited("TARGET_CORE[%s]: Expected Transfer Length:" " %u does not match SCSI CDB Length: %u for SAM Opcode:" " 0x%02x\n", cmd->se_tfo->get_fabric_name(), cmd->data_length, size, cmd->t_task_cdb[0]); - if (cmd->data_direction == DMA_TO_DEVICE && - cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) { - pr_err("Rejecting underflow/overflow WRITE data\n"); - return TCM_INVALID_CDB_FIELD; + if (cmd->data_direction == DMA_TO_DEVICE) { + if (cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) { + pr_err_ratelimited("Rejecting underflow/overflow" + " for WRITE data CDB\n"); + return TCM_INVALID_CDB_FIELD; + } + /* + * Some fabric drivers like iscsi-target still expect to + * always reject overflow writes. Reject this case until + * full fabric driver level support for overflow writes + * is introduced tree-wide. + */ + if (size > cmd->data_length) { + pr_err_ratelimited("Rejecting overflow for" + " WRITE control CDB\n"); + return TCM_INVALID_CDB_FIELD; + } } /* * Reject READ_* or WRITE_* with overflow/underflow for -- cgit v1.2.3 From 9a445bbb1607d9f14556a532453dd86d1b7e381e Mon Sep 17 00:00:00 2001 From: Hiroyuki Yokoyama Date: Mon, 15 May 2017 17:49:52 +0900 Subject: dmaengine: usb-dmac: Fix DMAOR AE bit definition This patch fixes the register definition of AE (Address Error flag) bit. Fixes: 0c1c8ff32fa2 ("dmaengine: usb-dmac: Add Renesas USB DMA Controller (USB-DMAC) driver") Cc: # v4.1+ Signed-off-by: Hiroyuki Yokoyama [Shimoda: add Fixes and Cc tags in the commit log] Signed-off-by: Yoshihiro Shimoda Reviewed-by: Geert Uytterhoeven Signed-off-by: Vinod Koul --- drivers/dma/sh/usb-dmac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/sh/usb-dmac.c b/drivers/dma/sh/usb-dmac.c index 72c649713ace..31a145154e9f 100644 --- a/drivers/dma/sh/usb-dmac.c +++ b/drivers/dma/sh/usb-dmac.c @@ -117,7 +117,7 @@ struct usb_dmac { #define USB_DMASWR 0x0008 #define USB_DMASWR_SWR (1 << 0) #define USB_DMAOR 0x0060 -#define USB_DMAOR_AE (1 << 2) +#define USB_DMAOR_AE (1 << 1) #define USB_DMAOR_DME (1 << 0) #define USB_DMASAR 0x0000 -- cgit v1.2.3 From 4751832da990a927c37526ae67b9226ea01eb99e Mon Sep 17 00:00:00 2001 From: Qu Wenruo Date: Fri, 7 Apr 2017 10:43:15 +0800 Subject: btrfs: fiemap: Cache and merge fiemap extent before submit it to user [BUG] Cycle mount btrfs can cause fiemap to return different result. Like: # mount /dev/vdb5 /mnt/btrfs # dd if=/dev/zero bs=16K count=4 oflag=dsync of=/mnt/btrfs/file # xfs_io -c "fiemap -v" /mnt/btrfs/file /mnt/test/file: EXT: FILE-OFFSET BLOCK-RANGE TOTAL FLAGS 0: [0..127]: 25088..25215 128 0x1 # umount /mnt/btrfs # mount /dev/vdb5 /mnt/btrfs # xfs_io -c "fiemap -v" /mnt/btrfs/file /mnt/test/file: EXT: FILE-OFFSET BLOCK-RANGE TOTAL FLAGS 0: [0..31]: 25088..25119 32 0x0 1: [32..63]: 25120..25151 32 0x0 2: [64..95]: 25152..25183 32 0x0 3: [96..127]: 25184..25215 32 0x1 But after above fiemap, we get correct merged result if we call fiemap again. # xfs_io -c "fiemap -v" /mnt/btrfs/file /mnt/test/file: EXT: FILE-OFFSET BLOCK-RANGE TOTAL FLAGS 0: [0..127]: 25088..25215 128 0x1 [REASON] Btrfs will try to merge extent map when inserting new extent map. btrfs_fiemap(start=0 len=(u64)-1) |- extent_fiemap(start=0 len=(u64)-1) |- get_extent_skip_holes(start=0 len=64k) | |- btrfs_get_extent_fiemap(start=0 len=64k) | |- btrfs_get_extent(start=0 len=64k) | | Found on-disk (ino, EXTENT_DATA, 0) | |- add_extent_mapping() | |- Return (em->start=0, len=16k) | |- fiemap_fill_next_extent(logic=0 phys=X len=16k) | |- get_extent_skip_holes(start=0 len=64k) | |- btrfs_get_extent_fiemap(start=0 len=64k) | |- btrfs_get_extent(start=16k len=48k) | | Found on-disk (ino, EXTENT_DATA, 16k) | |- add_extent_mapping() | | |- try_merge_map() | | Merge with previous em start=0 len=16k | | resulting em start=0 len=32k | |- Return (em->start=0, len=32K) << Merged result |- Stripe off the unrelated range (0~16K) of return em |- fiemap_fill_next_extent(logic=16K phys=X+16K len=16K) ^^^ Causing split fiemap extent. And since in add_extent_mapping(), em is already merged, in next fiemap() call, we will get merged result. [FIX] Here we introduce a new structure, fiemap_cache, which records previous fiemap extent. And will always try to merge current fiemap_cache result before calling fiemap_fill_next_extent(). Only when we failed to merge current fiemap extent with cached one, we will call fiemap_fill_next_extent() to submit cached one. So by this method, we can merge all fiemap extents. It can also be done in fs/ioctl.c, however the problem is if fieinfo->fi_extents_max == 0, we have no space to cache previous fiemap extent. So I choose to merge it in btrfs. Signed-off-by: Qu Wenruo Reviewed-by: Liu Bo Reviewed-by: David Sterba Signed-off-by: David Sterba --- fs/btrfs/extent_io.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 122 insertions(+), 2 deletions(-) diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index d8da3edf2ac3..4317ed3ad830 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -4377,6 +4377,123 @@ static struct extent_map *get_extent_skip_holes(struct inode *inode, return NULL; } +/* + * To cache previous fiemap extent + * + * Will be used for merging fiemap extent + */ +struct fiemap_cache { + u64 offset; + u64 phys; + u64 len; + u32 flags; + bool cached; +}; + +/* + * Helper to submit fiemap extent. + * + * Will try to merge current fiemap extent specified by @offset, @phys, + * @len and @flags with cached one. + * And only when we fails to merge, cached one will be submitted as + * fiemap extent. + * + * Return value is the same as fiemap_fill_next_extent(). + */ +static int emit_fiemap_extent(struct fiemap_extent_info *fieinfo, + struct fiemap_cache *cache, + u64 offset, u64 phys, u64 len, u32 flags) +{ + int ret = 0; + + if (!cache->cached) + goto assign; + + /* + * Sanity check, extent_fiemap() should have ensured that new + * fiemap extent won't overlap with cahced one. + * Not recoverable. + * + * NOTE: Physical address can overlap, due to compression + */ + if (cache->offset + cache->len > offset) { + WARN_ON(1); + return -EINVAL; + } + + /* + * Only merges fiemap extents if + * 1) Their logical addresses are continuous + * + * 2) Their physical addresses are continuous + * So truly compressed (physical size smaller than logical size) + * extents won't get merged with each other + * + * 3) Share same flags except FIEMAP_EXTENT_LAST + * So regular extent won't get merged with prealloc extent + */ + if (cache->offset + cache->len == offset && + cache->phys + cache->len == phys && + (cache->flags & ~FIEMAP_EXTENT_LAST) == + (flags & ~FIEMAP_EXTENT_LAST)) { + cache->len += len; + cache->flags |= flags; + goto try_submit_last; + } + + /* Not mergeable, need to submit cached one */ + ret = fiemap_fill_next_extent(fieinfo, cache->offset, cache->phys, + cache->len, cache->flags); + cache->cached = false; + if (ret) + return ret; +assign: + cache->cached = true; + cache->offset = offset; + cache->phys = phys; + cache->len = len; + cache->flags = flags; +try_submit_last: + if (cache->flags & FIEMAP_EXTENT_LAST) { + ret = fiemap_fill_next_extent(fieinfo, cache->offset, + cache->phys, cache->len, cache->flags); + cache->cached = false; + } + return ret; +} + +/* + * Sanity check for fiemap cache + * + * All fiemap cache should be submitted by emit_fiemap_extent() + * Iteration should be terminated either by last fiemap extent or + * fieinfo->fi_extents_max. + * So no cached fiemap should exist. + */ +static int check_fiemap_cache(struct btrfs_fs_info *fs_info, + struct fiemap_extent_info *fieinfo, + struct fiemap_cache *cache) +{ + int ret; + + if (!cache->cached) + return 0; + + /* Small and recoverbale problem, only to info developer */ +#ifdef CONFIG_BTRFS_DEBUG + WARN_ON(1); +#endif + btrfs_warn(fs_info, + "unhandled fiemap cache detected: offset=%llu phys=%llu len=%llu flags=0x%x", + cache->offset, cache->phys, cache->len, cache->flags); + ret = fiemap_fill_next_extent(fieinfo, cache->offset, cache->phys, + cache->len, cache->flags); + cache->cached = false; + if (ret > 0) + ret = 0; + return ret; +} + int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, __u64 start, __u64 len, get_extent_t *get_extent) { @@ -4394,6 +4511,7 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, struct extent_state *cached_state = NULL; struct btrfs_path *path; struct btrfs_root *root = BTRFS_I(inode)->root; + struct fiemap_cache cache = { 0 }; int end = 0; u64 em_start = 0; u64 em_len = 0; @@ -4573,8 +4691,8 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, flags |= FIEMAP_EXTENT_LAST; end = 1; } - ret = fiemap_fill_next_extent(fieinfo, em_start, disko, - em_len, flags); + ret = emit_fiemap_extent(fieinfo, &cache, em_start, disko, + em_len, flags); if (ret) { if (ret == 1) ret = 0; @@ -4582,6 +4700,8 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, } } out_free: + if (!ret) + ret = check_fiemap_cache(root->fs_info, fieinfo, &cache); free_extent_map(em); out: btrfs_free_path(path); -- cgit v1.2.3 From 8d91012528b3c95c159e6b6779e367421df9cbb5 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 2 May 2017 17:03:50 +0200 Subject: btrfs: Make flush bios explicitely sync Commit b685d3d65ac7 "block: treat REQ_FUA and REQ_PREFLUSH as synchronous" removed REQ_SYNC flag from WRITE_{FUA|PREFLUSH|...} definitions. generic_make_request_checks() however strips REQ_FUA and REQ_PREFLUSH flags from a bio when the storage doesn't report volatile write cache and thus write effectively becomes asynchronous which can lead to performance regressions Fix the problem by making sure all bios which are synchronous are properly marked with REQ_SYNC. CC: David Sterba CC: linux-btrfs@vger.kernel.org Fixes: b685d3d65ac791406e0dfd8779cc9b3707fea5a3 Signed-off-by: Jan Kara Reviewed-by: Liu Bo Signed-off-by: David Sterba --- fs/btrfs/disk-io.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 683194242deb..b3579d11fb26 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -3488,10 +3488,12 @@ static int write_dev_supers(struct btrfs_device *device, * we fua the first super. The others we allow * to go down lazy. */ - if (i == 0) - ret = btrfsic_submit_bh(REQ_OP_WRITE, REQ_FUA, bh); - else + if (i == 0) { + ret = btrfsic_submit_bh(REQ_OP_WRITE, + REQ_SYNC | REQ_FUA, bh); + } else { ret = btrfsic_submit_bh(REQ_OP_WRITE, REQ_SYNC, bh); + } if (ret) errors++; } @@ -3556,7 +3558,7 @@ static int write_dev_flush(struct btrfs_device *device, int wait) bio->bi_end_io = btrfs_end_empty_barrier; bio->bi_bdev = device->bdev; - bio->bi_opf = REQ_OP_WRITE | REQ_PREFLUSH; + bio->bi_opf = REQ_OP_WRITE | REQ_SYNC | REQ_PREFLUSH; init_completion(&device->flush_wait); bio->bi_private = &device->flush_wait; device->flush_bio = bio; -- cgit v1.2.3 From bff5baf8aa37a97293725a16c03f49872249c07e Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 9 May 2017 18:14:01 +0100 Subject: btrfs: fix incorrect error return ret being passed to mapping_set_error The setting of return code ret should be based on the error code passed into function end_extent_writepage and not on ret. Thanks to Liu Bo for spotting this mistake in the original fix I submitted. Detected by CoverityScan, CID#1414312 ("Logically dead code") Fixes: 5dca6eea91653e ("Btrfs: mark mapping with error flag to report errors to userspace") Signed-off-by: Colin Ian King Reviewed-by: Liu Bo Signed-off-by: David Sterba --- fs/btrfs/extent_io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 4317ed3ad830..d3619e010005 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -2458,7 +2458,7 @@ void end_extent_writepage(struct page *page, int err, u64 start, u64 end) if (!uptodate) { ClearPageUptodate(page); SetPageError(page); - ret = ret < 0 ? ret : -EIO; + ret = err < 0 ? err : -EIO; mapping_set_error(page->mapping, ret); } } -- cgit v1.2.3 From 6ceec6953efe7f371218082ddee1fe022a13e8ab Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Tue, 16 May 2017 16:54:53 +0200 Subject: MAINTAINERS: update RTC mailing list The RTC subsystem mailing list is moving to vger. Signed-off-by: Alexandre Belloni --- MAINTAINERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index f7d568b8f133..b3863ec142d7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10447,7 +10447,7 @@ S: Orphan PXA RTC DRIVER M: Robert Jarzmik -L: rtc-linux@googlegroups.com +L: linux-rtc@vger.kernel.org S: Maintained QAT DRIVER @@ -10754,7 +10754,7 @@ X: kernel/torture.c REAL TIME CLOCK (RTC) SUBSYSTEM M: Alessandro Zummo M: Alexandre Belloni -L: rtc-linux@googlegroups.com +L: linux-rtc@vger.kernel.org Q: http://patchwork.ozlabs.org/project/rtc-linux/list/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux.git S: Maintained -- cgit v1.2.3 From 8bfd174312629866efa535193d9e563768ff4307 Mon Sep 17 00:00:00 2001 From: Sui Chen Date: Tue, 9 May 2017 07:47:22 -0500 Subject: ahci: Acer SA5-271 SSD Not Detected Fix (Correction in this resend: fixed function name acer_sa5_271_workaround; fixed the always-true condition in the function; fixed description.) On the Acer Switch Alpha 12 (model number: SA5-271), the internal SSD may not get detected because the port_map and CAP.nr_ports combination causes the driver to skip the port that is actually connected to the SSD. More specifically, either all SATA ports are identified as DUMMY, or all ports get ``link down'' and never get up again. This problem occurs occasionally. When this problem occurs, CAP may hold a value of 0xC734FF00 or 0xC734FF01 and port_map may hold a value of 0x00 or 0x01. When this problem does not occur, CAP holds a value of 0xC734FF02 and port_map may hold a value of 0x07. Overriding the CAP value to 0xC734FF02 and port_map to 0x7 significantly reduces the occurrence of this problem. Link: https://bugzilla.kernel.org/attachment.cgi?id=253091 Signed-off-by: Sui Chen Tested-by: Damian Ivanov Cc: stable@vger.kernel.org Signed-off-by: Tejun Heo --- drivers/ata/ahci.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 2fc52407306c..c69954023c2e 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -1364,6 +1364,40 @@ static inline void ahci_gtf_filter_workaround(struct ata_host *host) {} #endif +/* + * On the Acer Aspire Switch Alpha 12, sometimes all SATA ports are detected + * as DUMMY, or detected but eventually get a "link down" and never get up + * again. When this happens, CAP.NP may hold a value of 0x00 or 0x01, and the + * port_map may hold a value of 0x00. + * + * Overriding CAP.NP to 0x02 and the port_map to 0x7 will reveal all 3 ports + * and can significantly reduce the occurrence of the problem. + * + * https://bugzilla.kernel.org/show_bug.cgi?id=189471 + */ +static void acer_sa5_271_workaround(struct ahci_host_priv *hpriv, + struct pci_dev *pdev) +{ + static const struct dmi_system_id sysids[] = { + { + .ident = "Acer Switch Alpha 12", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "Switch SA5-271") + }, + }, + { } + }; + + if (dmi_check_system(sysids)) { + dev_info(&pdev->dev, "enabling Acer Switch Alpha 12 workaround\n"); + if ((hpriv->saved_cap & 0xC734FF00) == 0xC734FF00) { + hpriv->port_map = 0x7; + hpriv->cap = 0xC734FF02; + } + } +} + #ifdef CONFIG_ARM64 /* * Due to ERRATA#22536, ThunderX needs to handle HOST_IRQ_STAT differently. @@ -1636,6 +1670,10 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) "online status unreliable, applying workaround\n"); } + + /* Acer SA5-271 workaround modifies private_data */ + acer_sa5_271_workaround(hpriv, pdev); + /* CAP.NP sometimes indicate the index of the last enabled * port, at other times, that of the last possible port, so * determining the maximum port number requires looking at -- cgit v1.2.3 From 5dc63fdcc09f47fb226b8bc7d83a61feb787d817 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Tue, 9 May 2017 16:00:28 +0530 Subject: ata: sata_rcar: Handle return value of clk_prepare_enable Here, Clock enable can failed. So adding an error check for clk_prepare_enable. tj: minor style updates Signed-off-by: Arvind Yadav Signed-off-by: Tejun Heo --- drivers/ata/sata_rcar.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/ata/sata_rcar.c b/drivers/ata/sata_rcar.c index 5d38245a7a73..b7939a2c1fab 100644 --- a/drivers/ata/sata_rcar.c +++ b/drivers/ata/sata_rcar.c @@ -890,7 +890,10 @@ static int sata_rcar_probe(struct platform_device *pdev) dev_err(&pdev->dev, "failed to get access to sata clock\n"); return PTR_ERR(priv->clk); } - clk_prepare_enable(priv->clk); + + ret = clk_prepare_enable(priv->clk); + if (ret) + return ret; host = ata_host_alloc(&pdev->dev, 1); if (!host) { @@ -970,8 +973,11 @@ static int sata_rcar_resume(struct device *dev) struct ata_host *host = dev_get_drvdata(dev); struct sata_rcar_priv *priv = host->private_data; void __iomem *base = priv->base; + int ret; - clk_prepare_enable(priv->clk); + ret = clk_prepare_enable(priv->clk); + if (ret) + return ret; /* ack and mask */ iowrite32(0, base + SATAINTSTAT_REG); @@ -988,8 +994,11 @@ static int sata_rcar_restore(struct device *dev) { struct ata_host *host = dev_get_drvdata(dev); struct sata_rcar_priv *priv = host->private_data; + int ret; - clk_prepare_enable(priv->clk); + ret = clk_prepare_enable(priv->clk); + if (ret) + return ret; sata_rcar_setup_port(host); -- cgit v1.2.3 From c034640a32f8456018d9c8c83799ead683046b95 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Tue, 16 May 2017 14:06:12 +0200 Subject: ata: libahci: properly propagate return value of platform_get_irq() When platform_get_irq() fails, it returns an error code, which libahci_platform and replaces it by -EINVAL. This commit fixes that by propagating the error code. It fixes the situation where platform_get_irq() returns -EPROBE_DEFER because the interrupt controller is not available yet, and generally looks like the right thing to do. We pay attention to not show the "no irq" message when we are in an EPROBE_DEFER situation, because the driver probing will be retried later on, once the interrupt controller becomes available to provide the interrupt. Signed-off-by: Thomas Petazzoni Reviewed-by: Hans de Goede Signed-off-by: Tejun Heo --- drivers/ata/libahci_platform.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c index aaa761b9081c..cd2eab6aa92e 100644 --- a/drivers/ata/libahci_platform.c +++ b/drivers/ata/libahci_platform.c @@ -514,8 +514,9 @@ int ahci_platform_init_host(struct platform_device *pdev, irq = platform_get_irq(pdev, 0); if (irq <= 0) { - dev_err(dev, "no irq\n"); - return -EINVAL; + if (irq != -EPROBE_DEFER) + dev_err(dev, "no irq\n"); + return irq; } hpriv->irq = irq; -- cgit v1.2.3 From 9512a16b0e1217bbef73d276a67c28b5fbb46512 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Tue, 16 May 2017 15:57:42 -0400 Subject: nfsd: Revert "nfsd: check for oversized NFSv2/v3 arguments" This reverts commit 51f567777799 "nfsd: check for oversized NFSv2/v3 arguments", which breaks support for NFSv3 ACLs. That patch was actually an earlier draft of a fix for the problem that was eventually fixed by e6838a29ecb "nfsd: check for oversized NFSv2/v3 arguments". But somehow I accidentally left this earlier draft in the branch that was part of my 2.12 pull request. Reported-by: Eryu Guan Cc: stable@vger.kernel.org Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs3xdr.c | 23 ++++++----------------- fs/nfsd/nfsxdr.c | 13 +++---------- include/linux/sunrpc/svc.h | 3 ++- 3 files changed, 11 insertions(+), 28 deletions(-) diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c index 12feac6ee2fd..452334694a5d 100644 --- a/fs/nfsd/nfs3xdr.c +++ b/fs/nfsd/nfs3xdr.c @@ -334,11 +334,8 @@ nfs3svc_decode_readargs(struct svc_rqst *rqstp, __be32 *p, if (!p) return 0; p = xdr_decode_hyper(p, &args->offset); - args->count = ntohl(*p++); - - if (!xdr_argsize_check(rqstp, p)) - return 0; + args->count = ntohl(*p++); len = min(args->count, max_blocksize); /* set up the kvec */ @@ -352,7 +349,7 @@ nfs3svc_decode_readargs(struct svc_rqst *rqstp, __be32 *p, v++; } args->vlen = v; - return 1; + return xdr_argsize_check(rqstp, p); } int @@ -544,11 +541,9 @@ nfs3svc_decode_readlinkargs(struct svc_rqst *rqstp, __be32 *p, p = decode_fh(p, &args->fh); if (!p) return 0; - if (!xdr_argsize_check(rqstp, p)) - return 0; args->buffer = page_address(*(rqstp->rq_next_page++)); - return 1; + return xdr_argsize_check(rqstp, p); } int @@ -574,14 +569,10 @@ nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, __be32 *p, args->verf = p; p += 2; args->dircount = ~0; args->count = ntohl(*p++); - - if (!xdr_argsize_check(rqstp, p)) - return 0; - args->count = min_t(u32, args->count, PAGE_SIZE); args->buffer = page_address(*(rqstp->rq_next_page++)); - return 1; + return xdr_argsize_check(rqstp, p); } int @@ -599,9 +590,6 @@ nfs3svc_decode_readdirplusargs(struct svc_rqst *rqstp, __be32 *p, args->dircount = ntohl(*p++); args->count = ntohl(*p++); - if (!xdr_argsize_check(rqstp, p)) - return 0; - len = args->count = min(args->count, max_blocksize); while (len > 0) { struct page *p = *(rqstp->rq_next_page++); @@ -609,7 +597,8 @@ nfs3svc_decode_readdirplusargs(struct svc_rqst *rqstp, __be32 *p, args->buffer = page_address(p); len -= PAGE_SIZE; } - return 1; + + return xdr_argsize_check(rqstp, p); } int diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c index 6a4947a3f4fa..de07ff625777 100644 --- a/fs/nfsd/nfsxdr.c +++ b/fs/nfsd/nfsxdr.c @@ -257,9 +257,6 @@ nfssvc_decode_readargs(struct svc_rqst *rqstp, __be32 *p, len = args->count = ntohl(*p++); p++; /* totalcount - unused */ - if (!xdr_argsize_check(rqstp, p)) - return 0; - len = min_t(unsigned int, len, NFSSVC_MAXBLKSIZE_V2); /* set up somewhere to store response. @@ -275,7 +272,7 @@ nfssvc_decode_readargs(struct svc_rqst *rqstp, __be32 *p, v++; } args->vlen = v; - return 1; + return xdr_argsize_check(rqstp, p); } int @@ -365,11 +362,9 @@ nfssvc_decode_readlinkargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd_readli p = decode_fh(p, &args->fh); if (!p) return 0; - if (!xdr_argsize_check(rqstp, p)) - return 0; args->buffer = page_address(*(rqstp->rq_next_page++)); - return 1; + return xdr_argsize_check(rqstp, p); } int @@ -407,11 +402,9 @@ nfssvc_decode_readdirargs(struct svc_rqst *rqstp, __be32 *p, args->cookie = ntohl(*p++); args->count = ntohl(*p++); args->count = min_t(u32, args->count, PAGE_SIZE); - if (!xdr_argsize_check(rqstp, p)) - return 0; args->buffer = page_address(*(rqstp->rq_next_page++)); - return 1; + return xdr_argsize_check(rqstp, p); } /* diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h index 94631026f79c..11cef5a7bc87 100644 --- a/include/linux/sunrpc/svc.h +++ b/include/linux/sunrpc/svc.h @@ -336,7 +336,8 @@ xdr_argsize_check(struct svc_rqst *rqstp, __be32 *p) { char *cp = (char *)p; struct kvec *vec = &rqstp->rq_arg.head[0]; - return cp == (char *)vec->iov_base + vec->iov_len; + return cp >= (char*)vec->iov_base + && cp <= (char*)vec->iov_base + vec->iov_len; } static inline int -- cgit v1.2.3 From f3f6cc814f9cb61cfb738af2b126a8bf19e5ab4c Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sat, 13 May 2017 13:40:05 +0200 Subject: ARM: davinci: PM: Free resources in error handling path in 'davinci_pm_init' If 'sram_alloc' fails, we need to free already allocated resources. Fixes: aa9aa1ec2df6 ("ARM: davinci: PM: rework init, remove platform device") Signed-off-by: Christophe JAILLET Signed-off-by: Sekhar Nori --- arch/arm/mach-davinci/pm.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-davinci/pm.c b/arch/arm/mach-davinci/pm.c index efb80354f303..d282b0783ecf 100644 --- a/arch/arm/mach-davinci/pm.c +++ b/arch/arm/mach-davinci/pm.c @@ -153,7 +153,8 @@ int __init davinci_pm_init(void) davinci_sram_suspend = sram_alloc(davinci_cpu_suspend_sz, NULL); if (!davinci_sram_suspend) { pr_err("PM: cannot allocate SRAM memory\n"); - return -ENOMEM; + ret = -ENOMEM; + goto no_sram_mem; } davinci_sram_push(davinci_sram_suspend, davinci_cpu_suspend, @@ -161,6 +162,8 @@ int __init davinci_pm_init(void) suspend_set_ops(&davinci_pm_ops); +no_sram_mem: + iounmap(pm_config.ddrpsc_reg_base); no_ddrpsc_mem: iounmap(pm_config.ddrpll_reg_base); no_ddrpll_mem: -- cgit v1.2.3 From 90431eb49bff6d79814cbf0c96e13597ad53095c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 16 May 2017 01:51:41 +0000 Subject: ASoC: rsnd: don't use PDTA bit for 24bit on SSI Current SSI uses PDTA bit which indicates data that Input/Output data are Right-Aligned. But, 24bit sound should be Left-Aligned in this HW. Because Linux is using Right-Aligned data, and HW uses Left-Aligned data, current 24bit data is missing lower 8bit. To fix this issue, this patch removes PDTA bit, and shift 8bit in necessary module Reported-by: Hiroyuki Yokoyama Signed-off-by: Kuninori Morimoto Tested-by: Hiroyuki Yokoyama Signed-off-by: Mark Brown --- sound/soc/sh/rcar/cmd.c | 1 + sound/soc/sh/rcar/core.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++ sound/soc/sh/rcar/gen.c | 1 + sound/soc/sh/rcar/rsnd.h | 2 ++ sound/soc/sh/rcar/src.c | 12 ++++++++++-- sound/soc/sh/rcar/ssi.c | 2 +- sound/soc/sh/rcar/ssiu.c | 3 ++- 7 files changed, 68 insertions(+), 4 deletions(-) diff --git a/sound/soc/sh/rcar/cmd.c b/sound/soc/sh/rcar/cmd.c index 7d92a24b7cfa..d879c010cf03 100644 --- a/sound/soc/sh/rcar/cmd.c +++ b/sound/soc/sh/rcar/cmd.c @@ -89,6 +89,7 @@ static int rsnd_cmd_init(struct rsnd_mod *mod, dev_dbg(dev, "ctu/mix path = 0x%08x", data); rsnd_mod_write(mod, CMD_ROUTE_SLCT, data); + rsnd_mod_write(mod, CMD_BUSIF_MODE, rsnd_get_busif_shift(io, mod) | 1); rsnd_mod_write(mod, CMD_BUSIF_DALIGN, rsnd_get_dalign(mod, io)); rsnd_adg_set_cmd_timsel_gen2(mod, io); diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 1744015408c3..8c1f4e2e0c4f 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -343,6 +343,57 @@ u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io) return 0x76543210; } +u32 rsnd_get_busif_shift(struct rsnd_dai_stream *io, struct rsnd_mod *mod) +{ + enum rsnd_mod_type playback_mods[] = { + RSND_MOD_SRC, + RSND_MOD_CMD, + RSND_MOD_SSIU, + }; + enum rsnd_mod_type capture_mods[] = { + RSND_MOD_CMD, + RSND_MOD_SRC, + RSND_MOD_SSIU, + }; + struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); + struct rsnd_mod *tmod = NULL; + enum rsnd_mod_type *mods = + rsnd_io_is_play(io) ? + playback_mods : capture_mods; + int i; + + /* + * This is needed for 24bit data + * We need to shift 8bit + * + * Linux 24bit data is located as 0x00****** + * HW 24bit data is located as 0x******00 + * + */ + switch (runtime->sample_bits) { + case 16: + return 0; + case 32: + break; + } + + for (i = 0; i < ARRAY_SIZE(playback_mods); i++) { + tmod = rsnd_io_to_mod(io, mods[i]); + if (tmod) + break; + } + + if (tmod != mod) + return 0; + + if (rsnd_io_is_play(io)) + return (0 << 20) | /* shift to Left */ + (8 << 16); /* 8bit */ + else + return (1 << 20) | /* shift to Right */ + (8 << 16); /* 8bit */ +} + /* * rsnd_dai functions */ diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index 63b6d3c28021..4b0980728e13 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -236,6 +236,7 @@ static int rsnd_gen2_probe(struct rsnd_priv *priv) RSND_GEN_M_REG(SRC_ROUTE_MODE0, 0xc, 0x20), RSND_GEN_M_REG(SRC_CTRL, 0x10, 0x20), RSND_GEN_M_REG(SRC_INT_ENABLE0, 0x18, 0x20), + RSND_GEN_M_REG(CMD_BUSIF_MODE, 0x184, 0x20), RSND_GEN_M_REG(CMD_BUSIF_DALIGN,0x188, 0x20), RSND_GEN_M_REG(CMD_ROUTE_SLCT, 0x18c, 0x20), RSND_GEN_M_REG(CMD_CTRL, 0x190, 0x20), diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index dbf4163427e8..323af41ecfcb 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -73,6 +73,7 @@ enum rsnd_reg { RSND_REG_SCU_SYS_INT_EN0, RSND_REG_SCU_SYS_INT_EN1, RSND_REG_CMD_CTRL, + RSND_REG_CMD_BUSIF_MODE, RSND_REG_CMD_BUSIF_DALIGN, RSND_REG_CMD_ROUTE_SLCT, RSND_REG_CMDOUT_TIMSEL, @@ -204,6 +205,7 @@ void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg, u32 mask, u32 data); u32 rsnd_get_adinr_bit(struct rsnd_mod *mod, struct rsnd_dai_stream *io); u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io); +u32 rsnd_get_busif_shift(struct rsnd_dai_stream *io, struct rsnd_mod *mod); /* * R-Car DMA diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c index 20b5b2ec625e..76a477a3ccb5 100644 --- a/sound/soc/sh/rcar/src.c +++ b/sound/soc/sh/rcar/src.c @@ -190,11 +190,13 @@ static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io, struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct device *dev = rsnd_priv_to_dev(priv); struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); + int is_play = rsnd_io_is_play(io); int use_src = 0; u32 fin, fout; u32 ifscr, fsrate, adinr; u32 cr, route; u32 bsdsr, bsisr; + u32 i_busif, o_busif, tmp; uint ratio; if (!runtime) @@ -270,6 +272,11 @@ static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io, break; } + /* BUSIF_MODE */ + tmp = rsnd_get_busif_shift(io, mod); + i_busif = ( is_play ? tmp : 0) | 1; + o_busif = (!is_play ? tmp : 0) | 1; + rsnd_mod_write(mod, SRC_ROUTE_MODE0, route); rsnd_mod_write(mod, SRC_SRCIR, 1); /* initialize */ @@ -281,8 +288,9 @@ static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io, rsnd_mod_write(mod, SRC_BSISR, bsisr); rsnd_mod_write(mod, SRC_SRCIR, 0); /* cancel initialize */ - rsnd_mod_write(mod, SRC_I_BUSIF_MODE, 1); - rsnd_mod_write(mod, SRC_O_BUSIF_MODE, 1); + rsnd_mod_write(mod, SRC_I_BUSIF_MODE, i_busif); + rsnd_mod_write(mod, SRC_O_BUSIF_MODE, o_busif); + rsnd_mod_write(mod, SRC_BUSIF_DALIGN, rsnd_get_dalign(mod, io)); rsnd_adg_set_src_timesel_gen2(mod, io, fin, fout); diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 135c5669f796..e43277a5068c 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -302,7 +302,7 @@ static void rsnd_ssi_config_init(struct rsnd_mod *mod, * always use 32bit system word. * see also rsnd_ssi_master_clk_enable() */ - cr_own = FORCE | SWL_32 | PDTA; + cr_own = FORCE | SWL_32; if (rdai->bit_clk_inv) cr_own |= SCKP; diff --git a/sound/soc/sh/rcar/ssiu.c b/sound/soc/sh/rcar/ssiu.c index 14fafdaf1395..512d238b79e2 100644 --- a/sound/soc/sh/rcar/ssiu.c +++ b/sound/soc/sh/rcar/ssiu.c @@ -144,7 +144,8 @@ static int rsnd_ssiu_init_gen2(struct rsnd_mod *mod, (rsnd_io_is_play(io) ? rsnd_runtime_channel_after_ctu(io) : rsnd_runtime_channel_original(io))); - rsnd_mod_write(mod, SSI_BUSIF_MODE, 1); + rsnd_mod_write(mod, SSI_BUSIF_MODE, + rsnd_get_busif_shift(io, mod) | 1); rsnd_mod_write(mod, SSI_BUSIF_DALIGN, rsnd_get_dalign(mod, io)); } -- cgit v1.2.3 From 61abce1312bf97eac62eef704260ce9a8f9b85f6 Mon Sep 17 00:00:00 2001 From: Quentin Schulz Date: Mon, 15 May 2017 10:36:17 +0200 Subject: ASoC: atmel-classd: sync regcache when resuming The PM functions used in this driver are the ones defined in sounc/soc/soc-core.c. When suspending (using snd_soc_suspend), the regcache is marked dirty but is never synced on resume. Sync regcache on resume of Atmel ClassD device. Signed-off-by: Quentin Schulz Acked-by: Alexandre Belloni Acked-by: Nicolas Ferre Signed-off-by: Mark Brown --- sound/soc/atmel/atmel-classd.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/sound/soc/atmel/atmel-classd.c b/sound/soc/atmel/atmel-classd.c index 7ae46c2647d4..b7ef8c59b49a 100644 --- a/sound/soc/atmel/atmel-classd.c +++ b/sound/soc/atmel/atmel-classd.c @@ -301,6 +301,14 @@ static int atmel_classd_codec_probe(struct snd_soc_codec *codec) return 0; } +static int atmel_classd_codec_resume(struct snd_soc_codec *codec) +{ + struct snd_soc_card *card = snd_soc_codec_get_drvdata(codec); + struct atmel_classd *dd = snd_soc_card_get_drvdata(card); + + return regcache_sync(dd->regmap); +} + static struct regmap *atmel_classd_codec_get_remap(struct device *dev) { return dev_get_regmap(dev, NULL); @@ -308,6 +316,7 @@ static struct regmap *atmel_classd_codec_get_remap(struct device *dev) static struct snd_soc_codec_driver soc_codec_dev_classd = { .probe = atmel_classd_codec_probe, + .resume = atmel_classd_codec_resume, .get_regmap = atmel_classd_codec_get_remap, .component_driver = { .controls = atmel_classd_snd_controls, -- cgit v1.2.3 From 95d7c1f18bf8ac03b0fc48eac1f1b11f867765b8 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sat, 13 May 2017 13:40:20 +0200 Subject: ARM: davinci: PM: Do not free useful resources in normal path in 'davinci_pm_init' It is wrong to iounmap resources in the normal path of davinci_pm_init() The 3 ioremap'ed fields of 'pm_config' can be accessed later on in other functions, so we should return 'success' instead of unrolling everything. Fixes: aa9aa1ec2df6 ("ARM: davinci: PM: rework init, remove platform device") Signed-off-by: Christophe JAILLET [nsekhar@ti.com: commit message and minor style fixes] Signed-off-by: Sekhar Nori --- arch/arm/mach-davinci/pm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/mach-davinci/pm.c b/arch/arm/mach-davinci/pm.c index d282b0783ecf..b5cc05dc2cb2 100644 --- a/arch/arm/mach-davinci/pm.c +++ b/arch/arm/mach-davinci/pm.c @@ -162,6 +162,8 @@ int __init davinci_pm_init(void) suspend_set_ops(&davinci_pm_ops); + return 0; + no_sram_mem: iounmap(pm_config.ddrpsc_reg_base); no_ddrpsc_mem: -- cgit v1.2.3 From 5667c86acf021e6dcf02584408b4484a273ac68f Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Sun, 14 May 2017 21:41:55 -0700 Subject: mac80211: strictly check mesh address extension mode Mesh forwarding path checks for address extension mode to fetch appropriate proxied address and MPP address. Existing condition that looks for 6 address format is not strict enough so that frames with improper values are processed and invalid entries are added into MPP table. Fix that by adding a stricter check before processing the packet. Per IEEE Std 802.11s-2011 spec. Table 7-6g1 lists address extension mode 0x3 as reserved one. And also Table Table 9-13 does not specify 0x3 as valid address field. Fixes: 9b395bc3be1c ("mac80211: verify that skb data is present") Signed-off-by: Rajkumar Manoharan Signed-off-by: Johannes Berg --- net/mac80211/rx.c | 3 ++- net/wireless/util.c | 10 ++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 35f4c7d7a500..1f75280ba26c 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -2492,7 +2492,8 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) if (is_multicast_ether_addr(hdr->addr1)) { mpp_addr = hdr->addr3; proxied_addr = mesh_hdr->eaddr1; - } else if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6) { + } else if ((mesh_hdr->flags & MESH_FLAGS_AE) == + MESH_FLAGS_AE_A5_A6) { /* has_a4 already checked in ieee80211_rx_mesh_check */ mpp_addr = hdr->addr4; proxied_addr = mesh_hdr->eaddr2; diff --git a/net/wireless/util.c b/net/wireless/util.c index 7198373e2920..4992f1025c9d 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -454,6 +454,8 @@ int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr, if (iftype == NL80211_IFTYPE_MESH_POINT) skb_copy_bits(skb, hdrlen, &mesh_flags, 1); + mesh_flags &= MESH_FLAGS_AE; + switch (hdr->frame_control & cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) { case cpu_to_le16(IEEE80211_FCTL_TODS): @@ -469,9 +471,9 @@ int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr, iftype != NL80211_IFTYPE_STATION)) return -1; if (iftype == NL80211_IFTYPE_MESH_POINT) { - if (mesh_flags & MESH_FLAGS_AE_A4) + if (mesh_flags == MESH_FLAGS_AE_A4) return -1; - if (mesh_flags & MESH_FLAGS_AE_A5_A6) { + if (mesh_flags == MESH_FLAGS_AE_A5_A6) { skb_copy_bits(skb, hdrlen + offsetof(struct ieee80211s_hdr, eaddr1), tmp.h_dest, 2 * ETH_ALEN); @@ -487,9 +489,9 @@ int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr, ether_addr_equal(tmp.h_source, addr))) return -1; if (iftype == NL80211_IFTYPE_MESH_POINT) { - if (mesh_flags & MESH_FLAGS_AE_A5_A6) + if (mesh_flags == MESH_FLAGS_AE_A5_A6) return -1; - if (mesh_flags & MESH_FLAGS_AE_A4) + if (mesh_flags == MESH_FLAGS_AE_A4) skb_copy_bits(skb, hdrlen + offsetof(struct ieee80211s_hdr, eaddr1), tmp.h_source, ETH_ALEN); -- cgit v1.2.3 From 33c35aa4817864e056fd772230b0c6b552e36ea2 Mon Sep 17 00:00:00 2001 From: Waiman Long Date: Mon, 15 May 2017 09:34:06 -0400 Subject: cgroup: Prevent kill_css() from being called more than once The kill_css() function may be called more than once under the condition that the css was killed but not physically removed yet followed by the removal of the cgroup that is hosting the css. This patch prevents any harmm from being done when that happens. Signed-off-by: Waiman Long Signed-off-by: Tejun Heo Cc: stable@vger.kernel.org # v4.5+ --- include/linux/cgroup-defs.h | 1 + kernel/cgroup/cgroup.c | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/include/linux/cgroup-defs.h b/include/linux/cgroup-defs.h index 21745946cae1..ec47101cb1bf 100644 --- a/include/linux/cgroup-defs.h +++ b/include/linux/cgroup-defs.h @@ -48,6 +48,7 @@ enum { CSS_ONLINE = (1 << 1), /* between ->css_online() and ->css_offline() */ CSS_RELEASED = (1 << 2), /* refcnt reached zero, released */ CSS_VISIBLE = (1 << 3), /* css is visible to userland */ + CSS_DYING = (1 << 4), /* css is dying */ }; /* bits in struct cgroup flags field */ diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c index c3c9a0e1b3c9..8d4e85eae42c 100644 --- a/kernel/cgroup/cgroup.c +++ b/kernel/cgroup/cgroup.c @@ -4265,6 +4265,11 @@ static void kill_css(struct cgroup_subsys_state *css) { lockdep_assert_held(&cgroup_mutex); + if (css->flags & CSS_DYING) + return; + + css->flags |= CSS_DYING; + /* * This must happen before css is disassociated with its cgroup. * See seq_css() for details. -- cgit v1.2.3 From 62b97d502bb76c6e8d589e42e02bfcb7bdff0453 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Mon, 15 May 2017 06:48:58 -0700 Subject: usb: chipidea: imx: Do not access CLKONOFF on i.MX51 Unlike i.MX53, i.MX51's USBOH3 register file does not implemenent registers past offset 0x018, which includes MX53_USB_CLKONOFF_CTRL_OFFSET and trying to access that register on said platform results in external abort. Fix it by enabling CLKONOFF accessing codepath only for i.MX53. Cc: stable Fixes 3be3251db088 ("usb: chipidea: imx: Disable internal 60Mhz clock with ULPI PHY") Cc: cphealy@gmail.com Cc: Greg Kroah-Hartman Cc: linux-usb@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Andrey Smirnov Signed-off-by: Peter Chen --- drivers/usb/chipidea/usbmisc_imx.c | 41 +++++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/drivers/usb/chipidea/usbmisc_imx.c b/drivers/usb/chipidea/usbmisc_imx.c index e77a4ed4f021..9f4a0185dd60 100644 --- a/drivers/usb/chipidea/usbmisc_imx.c +++ b/drivers/usb/chipidea/usbmisc_imx.c @@ -108,6 +108,8 @@ struct imx_usbmisc { const struct usbmisc_ops *ops; }; +static inline bool is_imx53_usbmisc(struct imx_usbmisc_data *data); + static int usbmisc_imx25_init(struct imx_usbmisc_data *data) { struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); @@ -242,10 +244,15 @@ static int usbmisc_imx53_init(struct imx_usbmisc_data *data) val = readl(reg) | MX53_USB_UHx_CTRL_WAKE_UP_EN | MX53_USB_UHx_CTRL_ULPI_INT_EN; writel(val, reg); - /* Disable internal 60Mhz clock */ - reg = usbmisc->base + MX53_USB_CLKONOFF_CTRL_OFFSET; - val = readl(reg) | MX53_USB_CLKONOFF_CTRL_H2_INT60CKOFF; - writel(val, reg); + if (is_imx53_usbmisc(data)) { + /* Disable internal 60Mhz clock */ + reg = usbmisc->base + + MX53_USB_CLKONOFF_CTRL_OFFSET; + val = readl(reg) | + MX53_USB_CLKONOFF_CTRL_H2_INT60CKOFF; + writel(val, reg); + } + } if (data->disable_oc) { reg = usbmisc->base + MX53_USB_UH2_CTRL_OFFSET; @@ -267,10 +274,15 @@ static int usbmisc_imx53_init(struct imx_usbmisc_data *data) val = readl(reg) | MX53_USB_UHx_CTRL_WAKE_UP_EN | MX53_USB_UHx_CTRL_ULPI_INT_EN; writel(val, reg); - /* Disable internal 60Mhz clock */ - reg = usbmisc->base + MX53_USB_CLKONOFF_CTRL_OFFSET; - val = readl(reg) | MX53_USB_CLKONOFF_CTRL_H3_INT60CKOFF; - writel(val, reg); + + if (is_imx53_usbmisc(data)) { + /* Disable internal 60Mhz clock */ + reg = usbmisc->base + + MX53_USB_CLKONOFF_CTRL_OFFSET; + val = readl(reg) | + MX53_USB_CLKONOFF_CTRL_H3_INT60CKOFF; + writel(val, reg); + } } if (data->disable_oc) { reg = usbmisc->base + MX53_USB_UH3_CTRL_OFFSET; @@ -456,6 +468,10 @@ static const struct usbmisc_ops imx27_usbmisc_ops = { .init = usbmisc_imx27_init, }; +static const struct usbmisc_ops imx51_usbmisc_ops = { + .init = usbmisc_imx53_init, +}; + static const struct usbmisc_ops imx53_usbmisc_ops = { .init = usbmisc_imx53_init, }; @@ -479,6 +495,13 @@ static const struct usbmisc_ops imx7d_usbmisc_ops = { .set_wakeup = usbmisc_imx7d_set_wakeup, }; +static inline bool is_imx53_usbmisc(struct imx_usbmisc_data *data) +{ + struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); + + return usbmisc->ops == &imx53_usbmisc_ops; +} + int imx_usbmisc_init(struct imx_usbmisc_data *data) { struct imx_usbmisc *usbmisc; @@ -536,7 +559,7 @@ static const struct of_device_id usbmisc_imx_dt_ids[] = { }, { .compatible = "fsl,imx51-usbmisc", - .data = &imx53_usbmisc_ops, + .data = &imx51_usbmisc_ops, }, { .compatible = "fsl,imx53-usbmisc", -- cgit v1.2.3 From aa1f058d7d9244423b8c5a75b9484b1115df7f02 Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Mon, 24 Apr 2017 12:35:51 +0000 Subject: usb: chipidea: udc: fix NULL pointer dereference if udc_start failed Fix below NULL pointer dereference. we set ci->roles[CI_ROLE_GADGET] too early in ci_hdrc_gadget_init(), if udc_start() fails due to some reason, the ci->roles[CI_ROLE_GADGET] check in ci_hdrc_gadget_destroy can't protect us. We fix this issue by only setting ci->roles[CI_ROLE_GADGET] if udc_start() succeed. [ 1.398550] Unable to handle kernel NULL pointer dereference at virtual address 00000000 ... [ 1.448600] PC is at dma_pool_free+0xb8/0xf0 [ 1.453012] LR is at dma_pool_free+0x28/0xf0 [ 2.113369] [] dma_pool_free+0xb8/0xf0 [ 2.118857] [] destroy_eps+0x4c/0x68 [ 2.124165] [] ci_hdrc_gadget_destroy+0x28/0x50 [ 2.130461] [] ci_hdrc_probe+0x588/0x7e8 [ 2.136129] [] platform_drv_probe+0x50/0xb8 [ 2.142066] [] driver_probe_device+0x1fc/0x2a8 [ 2.148270] [] __device_attach_driver+0x9c/0xf8 [ 2.154563] [] bus_for_each_drv+0x58/0x98 [ 2.160317] [] __device_attach+0xc4/0x138 [ 2.166072] [] device_initial_probe+0x10/0x18 [ 2.172185] [] bus_probe_device+0x94/0xa0 [ 2.177940] [] device_add+0x3f0/0x560 [ 2.183337] [] platform_device_add+0x180/0x240 [ 2.189541] [] ci_hdrc_add_device+0x440/0x4f8 [ 2.195654] [] ci_hdrc_usb2_probe+0x13c/0x2d8 [ 2.201769] [] platform_drv_probe+0x50/0xb8 [ 2.207705] [] driver_probe_device+0x1fc/0x2a8 [ 2.213910] [] __driver_attach+0xac/0xb0 [ 2.219575] [] bus_for_each_dev+0x60/0xa0 [ 2.225329] [] driver_attach+0x20/0x28 [ 2.230816] [] bus_add_driver+0x1d0/0x238 [ 2.236571] [] driver_register+0x60/0xf8 [ 2.242237] [] __platform_driver_register+0x44/0x50 [ 2.248891] [] ci_hdrc_usb2_driver_init+0x18/0x20 [ 2.255365] [] do_one_initcall+0x38/0x128 [ 2.261121] [] kernel_init_freeable+0x1ac/0x250 [ 2.267414] [] kernel_init+0x10/0x100 [ 2.272810] [] ret_from_fork+0x10/0x50 Cc: stable Fixes: 3f124d233e97 ("usb: chipidea: add role init and destroy APIs") Signed-off-by: Jisheng Zhang Signed-off-by: Peter Chen --- drivers/usb/chipidea/udc.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index 56d2d3213076..d68b125796f9 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -1993,6 +1993,7 @@ static void udc_id_switch_for_host(struct ci_hdrc *ci) int ci_hdrc_gadget_init(struct ci_hdrc *ci) { struct ci_role_driver *rdrv; + int ret; if (!hw_read(ci, CAP_DCCPARAMS, DCCPARAMS_DC)) return -ENXIO; @@ -2005,7 +2006,10 @@ int ci_hdrc_gadget_init(struct ci_hdrc *ci) rdrv->stop = udc_id_switch_for_host; rdrv->irq = udc_irq; rdrv->name = "gadget"; - ci->roles[CI_ROLE_GADGET] = rdrv; - return udc_start(ci); + ret = udc_start(ci); + if (!ret) + ci->roles[CI_ROLE_GADGET] = rdrv; + + return ret; } -- cgit v1.2.3 From 4681ee21d62cfed4364e09ec50ee8e88185dd628 Mon Sep 17 00:00:00 2001 From: Joonas Lahtinen Date: Thu, 18 May 2017 11:49:39 +0300 Subject: drm/i915: Do not sync RCU during shrinking Due to the complex dependencies between workqueues and RCU, which are not easily detected by lockdep, do not synchronize RCU during shrinking. On low-on-memory systems (mem=1G for example), the RCU sync leads to all system workqueus freezing and unrelated lockdep splats are displayed according to reports. GIT bisecting done by J. R. Okajima points to the commit where RCU syncing was extended. RCU sync gains us very little benefit in real life scenarios where the amount of memory used by object backing storage is dominant over the metadata under RCU, so drop it altogether. " Yeeeaah, if core could just, go ahead and reclaim RCU queues, that'd be great. " - Chris Wilson, 2016 (0eafec6d3244) v2: More information to commit message. v3: Remove "grep _rcu_" escapee from i915_gem_shrink_all (Andrea) Fixes: c053b5a506d3 ("drm/i915: Don't call synchronize_rcu_expedited under struct_mutex") Suggested-by: Chris Wilson Reported-by: J. R. Okajima Signed-off-by: Joonas Lahtinen Reviewed-by: Chris Wilson Tested-by: Hugh Dickins Tested-by: Andrea Arcangeli Cc: Chris Wilson Cc: Tvrtko Ursulin Cc: J. R. Okajima Cc: Andrea Arcangeli Cc: Hugh Dickins Cc: Jani Nikula Cc: # v4.11+ (cherry picked from commit 73cc0b9aa9afa5ba65d92e46ded61d29430d72a4) Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1495097379-573-1-git-send-email-joonas.lahtinen@linux.intel.com --- drivers/gpu/drm/i915/i915_gem_shrinker.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_shrinker.c b/drivers/gpu/drm/i915/i915_gem_shrinker.c index 129ed303a6c4..57d9f7f4ef15 100644 --- a/drivers/gpu/drm/i915/i915_gem_shrinker.c +++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c @@ -59,9 +59,6 @@ static void i915_gem_shrinker_unlock(struct drm_device *dev, bool unlock) return; mutex_unlock(&dev->struct_mutex); - - /* expedite the RCU grace period to free some request slabs */ - synchronize_rcu_expedited(); } static bool any_vma_pinned(struct drm_i915_gem_object *obj) @@ -274,8 +271,6 @@ unsigned long i915_gem_shrink_all(struct drm_i915_private *dev_priv) I915_SHRINK_ACTIVE); intel_runtime_pm_put(dev_priv); - synchronize_rcu(); /* wait for our earlier RCU delayed slab frees */ - return freed; } -- cgit v1.2.3 From 171d8b9363725e122b164e6b9ef2acf2f751e387 Mon Sep 17 00:00:00 2001 From: Matthew Auld Date: Tue, 16 May 2017 09:55:14 +0100 Subject: drm/i915: use vma->size for appgtt allocate_va_range For the aliasing ppgtt we clear the va range up to vma->size, but seem to allocate up to vma->node.size, which is a little inconsistent given that vma->node.size >= vma->size. Not that is really matters all that much since we preallocate anyway, but for consistency just use vma->size. Fixes: ff685975d97f ("drm/i915: Move allocate_va_range to GTT") Signed-off-by: Matthew Auld Cc: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/20170516085514.5853-1-matthew.auld@intel.com Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson (cherry picked from commit d567232cbd9ec2a289ddffea4013b7265bbcc3d5) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_gem_gtt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index a0563e18d753..50b8f1139ff9 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -2313,7 +2313,7 @@ static int aliasing_gtt_bind_vma(struct i915_vma *vma, appgtt->base.allocate_va_range) { ret = appgtt->base.allocate_va_range(&appgtt->base, vma->node.start, - vma->node.size); + vma->size); if (ret) goto err_pages; } -- cgit v1.2.3 From d8db7ae4eeebb278aa68a231a003e7102f635a4d Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 18 May 2017 13:06:44 +0200 Subject: drm/i915: Fix new -Wint-in-bool-context gcc compiler warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit fixes the following compiler warning: drivers/gpu/drm/i915/intel_dsi.c: In function ‘intel_dsi_prepare’: drivers/gpu/drm/i915/intel_dsi.c:1487:23: warning: ?: using integer constants in boolean context [-Wint-in-bool-context] PORT_A ? PORT_C : PORT_A), Fixes: f4c3a88e5f04 ("drm/i915: Tighten mmio arrays for MIPI_PORT") Signed-off-by: Hans de Goede Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/20170518110644.9902-1-hdegoede@redhat.com (cherry picked from commit 0ad4dc887d4168448e8c801aa4edd8fe1e0bd534) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_reg.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 5a7c63e64381..65b837e96fe6 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -8280,7 +8280,7 @@ enum { /* MIPI DSI registers */ -#define _MIPI_PORT(port, a, c) ((port) ? c : a) /* ports A and C only */ +#define _MIPI_PORT(port, a, c) (((port) == PORT_A) ? a : c) /* ports A and C only */ #define _MMIO_MIPI(port, a, c) _MMIO(_MIPI_PORT(port, a, c)) #define MIPIO_TXESC_CLK_DIV1 _MMIO(0x160004) -- cgit v1.2.3 From 8137ae26d25303e7b5cfb418fd28b976461e5b6e Mon Sep 17 00:00:00 2001 From: Amir Goldstein Date: Tue, 16 May 2017 08:45:46 +0300 Subject: ovl: fix creds leak in copy up error path Fixes: 42f269b92540 ("ovl: rearrange code in ovl_copy_up_locked()") Cc: # v4.11 Signed-off-by: Amir Goldstein Signed-off-by: Miklos Szeredi --- fs/overlayfs/copy_up.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c index 9008ab9fbd2e..061a8448e6c4 100644 --- a/fs/overlayfs/copy_up.c +++ b/fs/overlayfs/copy_up.c @@ -343,12 +343,13 @@ static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir, temp = ovl_do_tmpfile(upperdir, stat->mode); else temp = ovl_lookup_temp(workdir, dentry); - err = PTR_ERR(temp); - if (IS_ERR(temp)) - goto out1; - err = 0; - if (!tmpfile) + if (IS_ERR(temp)) { + err = PTR_ERR(temp); + temp = NULL; + } + + if (!err && !tmpfile) err = ovl_create_real(wdir, temp, &cattr, NULL, true); if (new_creds) { -- cgit v1.2.3 From 82b749b2c65e9d108c1c5598dc0a5f436b525f42 Mon Sep 17 00:00:00 2001 From: Amir Goldstein Date: Wed, 17 May 2017 00:12:40 +0300 Subject: ovl: check on mount time if upper fs supports setting xattr xattr are needed by overlayfs for setting opaque dir, redirect dir and copy up origin. Check at mount time by trying to set the overlay.opaque xattr on the workdir and if that fails issue a warning message. Signed-off-by: Amir Goldstein Signed-off-by: Miklos Szeredi --- fs/overlayfs/overlayfs.h | 3 +++ fs/overlayfs/ovl_entry.h | 1 + fs/overlayfs/super.c | 13 +++++++++++++ fs/overlayfs/util.c | 21 +++++++++++++++++++++ 4 files changed, 38 insertions(+) diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index caa36cb9c46d..ce7c3aba61e4 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h @@ -279,3 +279,6 @@ int ovl_copy_up(struct dentry *dentry); int ovl_copy_up_flags(struct dentry *dentry, int flags); int ovl_copy_xattr(struct dentry *old, struct dentry *new); int ovl_set_attr(struct dentry *upper, struct kstat *stat); +int ovl_check_setxattr(struct dentry *dentry, struct dentry *upperdentry, + const char *name, const void *value, size_t size, + int xerr); diff --git a/fs/overlayfs/ovl_entry.h b/fs/overlayfs/ovl_entry.h index b2023ddb8532..ad86c0a302eb 100644 --- a/fs/overlayfs/ovl_entry.h +++ b/fs/overlayfs/ovl_entry.h @@ -28,6 +28,7 @@ struct ovl_fs { /* creds of process who forced instantiation of super block */ const struct cred *creator_cred; bool tmpfile; + bool noxattr; wait_queue_head_t copyup_wq; /* sb common to all layers */ struct super_block *same_sb; diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index 9828b7de8999..f1647626a882 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -891,6 +891,19 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) dput(temp); else pr_warn("overlayfs: upper fs does not support tmpfile.\n"); + + /* + * Check if upper/work fs supports trusted.overlay.* + * xattr + */ + err = ovl_do_setxattr(ufs->workdir, OVL_XATTR_OPAQUE, + "0", 1, 0); + if (err) { + ufs->noxattr = true; + pr_warn("overlayfs: upper fs does not support xattr.\n"); + } else { + vfs_removexattr(ufs->workdir, OVL_XATTR_OPAQUE); + } } } diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c index cfdea47313a1..b5a0dc36ee96 100644 --- a/fs/overlayfs/util.c +++ b/fs/overlayfs/util.c @@ -303,3 +303,24 @@ void ovl_copy_up_end(struct dentry *dentry) wake_up_locked(&ofs->copyup_wq); spin_unlock(&ofs->copyup_wq.lock); } + +int ovl_check_setxattr(struct dentry *dentry, struct dentry *upperdentry, + const char *name, const void *value, size_t size, + int xerr) +{ + int err; + struct ovl_fs *ofs = dentry->d_sb->s_fs_info; + + if (ofs->noxattr) + return xerr; + + err = ovl_do_setxattr(upperdentry, name, value, size, 0); + + if (err == -EOPNOTSUPP) { + pr_warn("overlayfs: cannot set %s xattr on upper\n", name); + ofs->noxattr = true; + return xerr; + } + + return err; +} -- cgit v1.2.3 From 6266d465bde044a105f6c2d4e244680f951a2d70 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Thu, 18 May 2017 16:11:24 +0200 Subject: ovl: don't fail copy-up if upper doesn't support xattr Signed-off-by: Miklos Szeredi --- fs/overlayfs/copy_up.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c index 061a8448e6c4..f92ab35d43a6 100644 --- a/fs/overlayfs/copy_up.c +++ b/fs/overlayfs/copy_up.c @@ -300,7 +300,11 @@ static int ovl_set_origin(struct dentry *dentry, struct dentry *lower, return PTR_ERR(fh); } - err = ovl_do_setxattr(upper, OVL_XATTR_ORIGIN, fh, fh ? fh->len : 0, 0); + /* + * Do not fail when upper doesn't support xattrs. + */ + err = ovl_check_setxattr(dentry, upper, OVL_XATTR_ORIGIN, fh, + fh ? fh->len : 0, 0); kfree(fh); return err; -- cgit v1.2.3 From 4c4fc90964b1cf205a67df566cc82ea1731bcb00 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 18 May 2017 12:29:55 +0100 Subject: drivers/tty: 8250: only call fintek_8250_probe when doing port I/O Commit fa01e2ca9f53 ("serial: 8250: Integrate Fintek into 8250_base") modified the probing logic for PNP0501 devices, to remove a collision between the generic 16550A driver and the Fintek driver, which reused the same ACPI _HID. The Fintek device probe is now incorporated into the common 8250 probe path, and gets called for all discovered 16550A compatible devices, including ones that are MMIO mapped rather than IO mapped. However, the Fintek driver assumes the port base is a I/O address, and proceeds to probe some arbitrary offsets above it. This is generally a wrong thing to do, but on ARM systems (having no native port I/O), this may result in faulting accesses of completely unrelated MMIO regions in the PCI I/O space. Given that this is at serial probe time, this results in hard to diagnose crashes at boot. So let's restrict the Fintek probe to devices that we know are using port I/O in the first place. Fixes: fa01e2ca9f53 ("serial: 8250: Integrate Fintek into 8250_base") Suggested-by: Arnd Bergmann Reviewed-by: Ricardo Ribalda Signed-off-by: Ard Biesheuvel Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_port.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 09a65a3ec7f7..e7765f010fe8 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1337,7 +1337,7 @@ out_lock: /* * Check if the device is a Fintek F81216A */ - if (port->type == PORT_16550A) + if (port->type == PORT_16550A && port->iotype == UPIO_PORT) fintek_8250_probe(up); if (up->capabilities != old_capabilities) { -- cgit v1.2.3 From d3ba126a226a6b6da021ebfea444a2a807cde945 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 11 Apr 2017 19:07:28 +0200 Subject: Revert "tty_port: register tty ports with serdev bus" This reverts commit 8ee3fde047589dc9c201251f07d0ca1dc776feca. The new serdev bus hooked into the tty layer in tty_port_register_device() by registering a serdev controller instead of a tty device whenever a serdev client is present, and by deregistering the controller in the tty-port destructor. This is broken in several ways: Firstly, it leads to a NULL-pointer dereference whenever a tty driver later deregisters its devices as no corresponding character device will exist. Secondly, far from every tty driver uses tty-port refcounting (e.g. serial core) so the serdev devices might never be deregistered or deallocated. Thirdly, deregistering at tty-port destruction is too late as the underlying device and structures may be long gone by then. A port is not released before an open tty device is closed, something which a registered serdev client can prevent from ever happening. A driver callback while the device is gone typically also leads to crashes. Many tty drivers even keep their ports around until the driver is unloaded (e.g. serial core), something which even if a late callback never happens, leads to leaks if a device is unbound from its driver and is later rebound. The right solution here is to add a new tty_port_unregister_device() helper and to never call tty_device_unregister() whenever the port has been claimed by serdev, but since this requires modifying just about every tty driver (and multiple subsystems) it will need to be done incrementally. Reverting the offending patch is the first step in fixing the broken lifetime assumptions. A follow-up patch will add a new pair of tty-device registration helpers, which a vetted tty driver can use to support serdev (initially serial core). When every tty driver uses the serdev helpers (at least for deregistration), we can add serdev registration to tty_port_register_device() again. Note that this also fixes another issue with serdev, which currently allocates and registers a serdev controller for every tty device registered using tty_port_device_register() only to immediately deregister and deallocate it when the corresponding OF node or serdev child node is missing. This should be addressed before enabling serdev for hot-pluggable buses. Signed-off-by: Johan Hovold Reviewed-by: Rob Herring Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_port.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c index 1d21a9c1d33e..0c880f17d27e 100644 --- a/drivers/tty/tty_port.c +++ b/drivers/tty/tty_port.c @@ -16,7 +16,6 @@ #include #include #include -#include static int tty_port_default_receive_buf(struct tty_port *port, const unsigned char *p, @@ -129,15 +128,7 @@ struct device *tty_port_register_device_attr(struct tty_port *port, struct device *device, void *drvdata, const struct attribute_group **attr_grp) { - struct device *dev; - tty_port_link_device(port, driver, index); - - dev = serdev_tty_port_register(port, device, driver, index); - if (PTR_ERR(dev) != -ENODEV) - /* Skip creating cdev if we registered a serdev device */ - return dev; - return tty_register_device_attr(driver, index, device, drvdata, attr_grp); } @@ -189,9 +180,6 @@ static void tty_port_destructor(struct kref *kref) /* check if last port ref was dropped before tty release */ if (WARN_ON(port->itty)) return; - - serdev_tty_port_unregister(port); - if (port->xmit_buf) free_page((unsigned long)port->xmit_buf); tty_port_destroy(port); -- cgit v1.2.3 From aee5da7838787f8ed47f825dbe09e2812acdf97b Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 11 Apr 2017 19:07:29 +0200 Subject: serdev: fix tty-port client deregistration The port client data must be set when registering the serdev controller or client deregistration will fail (and the serdev devices are left registered and allocated) if the port was never opened in between. Make sure to clear the port client data on any probe errors to avoid a use-after-free when the client is later deregistered unconditionally (e.g. in a tty-port deregistration helper). Also move port client operation initialisation to registration. Note that the client ops must be restored on failed probe. Fixes: bed35c6dfa6a ("serdev: add a tty port controller driver") Signed-off-by: Johan Hovold Reviewed-by: Rob Herring Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serdev/serdev-ttyport.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/tty/serdev/serdev-ttyport.c b/drivers/tty/serdev/serdev-ttyport.c index 487c88f6aa0e..013efffd2e82 100644 --- a/drivers/tty/serdev/serdev-ttyport.c +++ b/drivers/tty/serdev/serdev-ttyport.c @@ -102,9 +102,6 @@ static int ttyport_open(struct serdev_controller *ctrl) return PTR_ERR(tty); serport->tty = tty; - serport->port->client_ops = &client_ops; - serport->port->client_data = ctrl; - if (tty->ops->open) tty->ops->open(serport->tty, NULL); else @@ -215,6 +212,7 @@ struct device *serdev_tty_port_register(struct tty_port *port, struct device *parent, struct tty_driver *drv, int idx) { + const struct tty_port_client_operations *old_ops; struct serdev_controller *ctrl; struct serport *serport; int ret; @@ -233,15 +231,22 @@ struct device *serdev_tty_port_register(struct tty_port *port, ctrl->ops = &ctrl_ops; + old_ops = port->client_ops; + port->client_ops = &client_ops; + port->client_data = ctrl; + ret = serdev_controller_add(ctrl); if (ret) - goto err_controller_put; + goto err_reset_data; dev_info(&ctrl->dev, "tty port %s%d registered\n", drv->name, idx); return &ctrl->dev; -err_controller_put: +err_reset_data: + port->client_data = NULL; + port->client_ops = old_ops; serdev_controller_put(ctrl); + return ERR_PTR(ret); } -- cgit v1.2.3 From be40597a1bc173bf9dadccdf5388b956f620ae8f Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Fri, 12 May 2017 16:35:45 +0200 Subject: serial: efm32: Fix parity management in 'efm32_uart_console_get_options()' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit UARTn_FRAME_PARITY_ODD is 0x0300 UARTn_FRAME_PARITY_EVEN is 0x0200 So if the UART is configured for EVEN parity, it would be reported as ODD. Fix it by correctly testing if the 2 bits are set. Fixes: 3afbd89c9639 ("serial/efm32: add new driver") Signed-off-by: Christophe JAILLET Acked-by: Uwe Kleine-König Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/efm32-uart.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/tty/serial/efm32-uart.c b/drivers/tty/serial/efm32-uart.c index ebd8569f9ad5..9fff25be87f9 100644 --- a/drivers/tty/serial/efm32-uart.c +++ b/drivers/tty/serial/efm32-uart.c @@ -27,6 +27,7 @@ #define UARTn_FRAME 0x04 #define UARTn_FRAME_DATABITS__MASK 0x000f #define UARTn_FRAME_DATABITS(n) ((n) - 3) +#define UARTn_FRAME_PARITY__MASK 0x0300 #define UARTn_FRAME_PARITY_NONE 0x0000 #define UARTn_FRAME_PARITY_EVEN 0x0200 #define UARTn_FRAME_PARITY_ODD 0x0300 @@ -572,12 +573,16 @@ static void efm32_uart_console_get_options(struct efm32_uart_port *efm_port, 16 * (4 + (clkdiv >> 6))); frame = efm32_uart_read32(efm_port, UARTn_FRAME); - if (frame & UARTn_FRAME_PARITY_ODD) + switch (frame & UARTn_FRAME_PARITY__MASK) { + case UARTn_FRAME_PARITY_ODD: *parity = 'o'; - else if (frame & UARTn_FRAME_PARITY_EVEN) + break; + case UARTn_FRAME_PARITY_EVEN: *parity = 'e'; - else + break; + default: *parity = 'n'; + } *bits = (frame & UARTn_FRAME_DATABITS__MASK) - UARTn_FRAME_DATABITS(4) + 4; -- cgit v1.2.3 From 2c0ac5b48a3586f612b85755b041ed7733dc8e6b Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 24 Apr 2017 12:30:15 +0200 Subject: serial: exar: Fix stuck MSIs After migrating 8250_exar to MSI in 172c33cb61da, we can get stuck without further interrupts because of the special wake-up event these chips send. They are only cleared by reading INT0. As we fail to do so during startup and shutdown, we can leave the interrupt line asserted, which is fatal with edge-triggered MSIs. Add the required reading of INT0 to startup and shutdown. Also account for the fact that a pending wake-up interrupt means we have to return 1 from exar_handle_irq. Drop the unneeded reading of INT1..3 along with this - those never reset anything. An alternative approach would have been disabling the wake-up interrupt. Unfortunately, this feature (REGB[17] = 1) is not available on the XR17D15X. Fixes: 172c33cb61da ("serial: exar: Enable MSI support") Signed-off-by: Jan Kiszka Reviewed-by: Andy Shevchenko Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_port.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index e7765f010fe8..68fd045a7025 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -47,6 +47,7 @@ /* * These are definitions for the Exar XR17V35X and XR17(C|D)15X */ +#define UART_EXAR_INT0 0x80 #define UART_EXAR_SLEEP 0x8b /* Sleep mode */ #define UART_EXAR_DVID 0x8d /* Device identification */ @@ -1869,17 +1870,13 @@ static int serial8250_default_handle_irq(struct uart_port *port) static int exar_handle_irq(struct uart_port *port) { unsigned int iir = serial_port_in(port, UART_IIR); - int ret; + int ret = 0; - ret = serial8250_handle_irq(port, iir); + if (((port->type == PORT_XR17V35X) || (port->type == PORT_XR17D15X)) && + serial_port_in(port, UART_EXAR_INT0) != 0) + ret = 1; - if ((port->type == PORT_XR17V35X) || - (port->type == PORT_XR17D15X)) { - serial_port_in(port, 0x80); - serial_port_in(port, 0x81); - serial_port_in(port, 0x82); - serial_port_in(port, 0x83); - } + ret |= serial8250_handle_irq(port, iir); return ret; } @@ -2177,6 +2174,8 @@ int serial8250_do_startup(struct uart_port *port) serial_port_in(port, UART_RX); serial_port_in(port, UART_IIR); serial_port_in(port, UART_MSR); + if ((port->type == PORT_XR17V35X) || (port->type == PORT_XR17D15X)) + serial_port_in(port, UART_EXAR_INT0); /* * At this point, there's no way the LSR could still be 0xff; @@ -2335,6 +2334,8 @@ dont_test_tx_en: serial_port_in(port, UART_RX); serial_port_in(port, UART_IIR); serial_port_in(port, UART_MSR); + if ((port->type == PORT_XR17V35X) || (port->type == PORT_XR17D15X)) + serial_port_in(port, UART_EXAR_INT0); up->lsr_saved_flags = 0; up->msr_saved_flags = 0; -- cgit v1.2.3 From 5c9d6abed9e0a061de252a53ab687a1171502e81 Mon Sep 17 00:00:00 2001 From: Alexey Khoroshilov Date: Sat, 13 May 2017 00:36:22 +0300 Subject: serial: altera_jtaguart: adding iounmap() The driver does ioremap(port->mapbase, ALTERA_JTAGUART_SIZE), but there is no any iounmap(). Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov Acked-by: Tobias Klauser Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/altera_jtaguart.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/tty/serial/altera_jtaguart.c b/drivers/tty/serial/altera_jtaguart.c index 18e3f8342b85..0475f5d261ce 100644 --- a/drivers/tty/serial/altera_jtaguart.c +++ b/drivers/tty/serial/altera_jtaguart.c @@ -478,6 +478,7 @@ static int altera_jtaguart_remove(struct platform_device *pdev) port = &altera_jtaguart_ports[i].port; uart_remove_one_port(&altera_jtaguart_driver, port); + iounmap(port->membase); return 0; } -- cgit v1.2.3 From 1e948479b3d63e3ac0ecca13cbf4921c7d17c168 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 26 Apr 2017 12:24:21 +0200 Subject: serial: ifx6x60: fix use-after-free on module unload Make sure to deregister the SPI driver before releasing the tty driver to avoid use-after-free in the SPI remove callback where the tty devices are deregistered. Fixes: 72d4724ea54c ("serial: ifx6x60: Add modem power off function in the platform reboot process") Cc: stable # 3.8 Cc: Jun Chen Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/ifx6x60.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c index 157883653256..f190a84a0246 100644 --- a/drivers/tty/serial/ifx6x60.c +++ b/drivers/tty/serial/ifx6x60.c @@ -1382,9 +1382,9 @@ static struct spi_driver ifx_spi_driver = { static void __exit ifx_spi_exit(void) { /* unregister */ + spi_unregister_driver(&ifx_spi_driver); tty_unregister_driver(tty_drv); put_tty_driver(tty_drv); - spi_unregister_driver(&ifx_spi_driver); unregister_reboot_notifier(&ifx_modem_reboot_notifier_block); } -- cgit v1.2.3 From 11d4d32158eeaf36fe1073a4a260193d7a19ccf1 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 26 Apr 2017 12:30:04 +0200 Subject: tty: ehv_bytechan: clean up init error handling Straighten out the initcall error handling to avoid deregistering a never-registered tty driver (something which would lead to a NULL-pointer dereference) in the most unlikely event that driver registration fails (e.g. we've run out of major numbers). Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/tty/ehv_bytechan.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/drivers/tty/ehv_bytechan.c b/drivers/tty/ehv_bytechan.c index 7ac9bcdf1e61..61fe8d6fd24e 100644 --- a/drivers/tty/ehv_bytechan.c +++ b/drivers/tty/ehv_bytechan.c @@ -764,7 +764,7 @@ static int __init ehv_bc_init(void) ehv_bc_driver = alloc_tty_driver(count); if (!ehv_bc_driver) { ret = -ENOMEM; - goto error; + goto err_free_bcs; } ehv_bc_driver->driver_name = "ehv-bc"; @@ -778,24 +778,23 @@ static int __init ehv_bc_init(void) ret = tty_register_driver(ehv_bc_driver); if (ret) { pr_err("ehv-bc: could not register tty driver (ret=%i)\n", ret); - goto error; + goto err_put_tty_driver; } ret = platform_driver_register(&ehv_bc_tty_driver); if (ret) { pr_err("ehv-bc: could not register platform driver (ret=%i)\n", ret); - goto error; + goto err_deregister_tty_driver; } return 0; -error: - if (ehv_bc_driver) { - tty_unregister_driver(ehv_bc_driver); - put_tty_driver(ehv_bc_driver); - } - +err_deregister_tty_driver: + tty_unregister_driver(ehv_bc_driver); +err_put_tty_driver: + put_tty_driver(ehv_bc_driver); +err_free_bcs: kfree(bcs); return ret; -- cgit v1.2.3 From 925bb1ce47f429f69aad35876df7ecd8c53deb7e Mon Sep 17 00:00:00 2001 From: Vegard Nossum Date: Thu, 11 May 2017 12:18:52 +0200 Subject: tty: fix port buffer locking tty_insert_flip_string_fixed_flag() is racy against itself when called from the ioctl(TCXONC, TCION/TCIOFF) path [1] and the flush_to_ldisc() workqueue path [2]. The problem is that port->buf.tail->used is modified without consistent locking; the ioctl path takes tty->atomic_write_lock, whereas the workqueue path takes ldata->output_lock. We cannot simply take ldata->output_lock, since that is specific to the N_TTY line discipline. It might seem natural to try to take port->buf.lock inside tty_insert_flip_string_fixed_flag() and friends (where port->buf is actually used/modified), but this creates problems for flush_to_ldisc() which takes it before grabbing tty->ldisc_sem, o_tty->termios_rwsem, and ldata->output_lock. Therefore, the simplest solution for now seems to be to take tty->atomic_write_lock inside tty_port_default_receive_buf(). This lock is also used in the write path [3] with a consistent ordering. [1]: Call Trace: tty_insert_flip_string_fixed_flag pty_write tty_send_xchar // down_read(&o_tty->termios_rwsem) // mutex_lock(&tty->atomic_write_lock) n_tty_ioctl_helper n_tty_ioctl tty_ioctl // down_read(&tty->ldisc_sem) do_vfs_ioctl SyS_ioctl [2]: Workqueue: events_unbound flush_to_ldisc Call Trace: tty_insert_flip_string_fixed_flag pty_write tty_put_char __process_echoes commit_echoes // mutex_lock(&ldata->output_lock) n_tty_receive_buf_common n_tty_receive_buf2 tty_ldisc_receive_buf // down_read(&o_tty->termios_rwsem) tty_port_default_receive_buf // down_read(&tty->ldisc_sem) flush_to_ldisc // mutex_lock(&port->buf.lock) process_one_work [3]: Call Trace: tty_insert_flip_string_fixed_flag pty_write n_tty_write // mutex_lock(&ldata->output_lock) // down_read(&tty->termios_rwsem) do_tty_write (inline) // mutex_lock(&tty->atomic_write_lock) tty_write // down_read(&tty->ldisc_sem) __vfs_write vfs_write SyS_write The bug can result in about a dozen different crashes depending on what exactly gets corrupted when port->buf.tail->used points outside the buffer. The patch passes my LOCKDEP/PROVE_LOCKING testing but more testing is always welcome. Found using syzkaller. Cc: Signed-off-by: Vegard Nossum Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_port.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c index 0c880f17d27e..88dac3b79369 100644 --- a/drivers/tty/tty_port.c +++ b/drivers/tty/tty_port.c @@ -33,7 +33,9 @@ static int tty_port_default_receive_buf(struct tty_port *port, if (!disc) return 0; + mutex_lock(&tty->atomic_write_lock); ret = tty_ldisc_receive_buf(disc, p, (char *)f, count); + mutex_unlock(&tty->atomic_write_lock); tty_ldisc_deref(disc); -- cgit v1.2.3 From 88e2582e90bb89fe895ff0dceeb5d5ab65d07997 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Thu, 11 May 2017 12:56:14 +0200 Subject: serial: core: fix crash in uart_suspend_port With serdev we might end up with serial ports that have no cdev exported to userspace, as they are used as the bus interface to other devices. In that case serial_match_port() won't be able to find a matching tty_dev. Skip the irq wakeup enabling in that case, as serdev will make sure to keep the port active, as long as there are devices depending on it. Fixes: 8ee3fde04758 (tty_port: register tty ports with serdev bus) Signed-off-by: Lucas Stach Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 0f45b7884a2c..bc6caea6099f 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -2083,7 +2083,7 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport) mutex_lock(&port->mutex); tty_dev = device_find_child(uport->dev, &match, serial_match_port); - if (device_may_wakeup(tty_dev)) { + if (tty_dev && device_may_wakeup(tty_dev)) { if (!enable_irq_wake(uport->irq)) uport->irq_wake = 1; put_device(tty_dev); -- cgit v1.2.3 From 6bdc00d01e202ae11fa1cae0dacbef895434483d Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Fri, 28 Apr 2017 13:47:21 +0200 Subject: serdev: Restore serdev_device_write_buf for atomic context Starting with commit 6fe729c4bdae ("serdev: Add serdev_device_write subroutine") the function serdev_device_write_buf cannot be used in atomic context anymore (mutex_lock is sleeping). So restore the old behavior. Signed-off-by: Stefan Wahren Fixes: 6fe729c4bdae ("serdev: Add serdev_device_write subroutine") Acked-by: Rob Herring Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serdev/core.c | 12 ++++++++++++ include/linux/serdev.h | 14 +++++++------- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c index 433de5ea9b02..f71b47334149 100644 --- a/drivers/tty/serdev/core.c +++ b/drivers/tty/serdev/core.c @@ -122,6 +122,18 @@ void serdev_device_write_wakeup(struct serdev_device *serdev) } EXPORT_SYMBOL_GPL(serdev_device_write_wakeup); +int serdev_device_write_buf(struct serdev_device *serdev, + const unsigned char *buf, size_t count) +{ + struct serdev_controller *ctrl = serdev->ctrl; + + if (!ctrl || !ctrl->ops->write_buf) + return -EINVAL; + + return ctrl->ops->write_buf(ctrl, buf, count); +} +EXPORT_SYMBOL_GPL(serdev_device_write_buf); + int serdev_device_write(struct serdev_device *serdev, const unsigned char *buf, size_t count, unsigned long timeout) diff --git a/include/linux/serdev.h b/include/linux/serdev.h index cda76c6506ca..e2a225bf716d 100644 --- a/include/linux/serdev.h +++ b/include/linux/serdev.h @@ -195,6 +195,7 @@ int serdev_device_open(struct serdev_device *); void serdev_device_close(struct serdev_device *); unsigned int serdev_device_set_baudrate(struct serdev_device *, unsigned int); void serdev_device_set_flow_control(struct serdev_device *, bool); +int serdev_device_write_buf(struct serdev_device *, const unsigned char *, size_t); void serdev_device_wait_until_sent(struct serdev_device *, long); int serdev_device_get_tiocm(struct serdev_device *); int serdev_device_set_tiocm(struct serdev_device *, int, int); @@ -236,6 +237,12 @@ static inline unsigned int serdev_device_set_baudrate(struct serdev_device *sdev return 0; } static inline void serdev_device_set_flow_control(struct serdev_device *sdev, bool enable) {} +static inline int serdev_device_write_buf(struct serdev_device *serdev, + const unsigned char *buf, + size_t count) +{ + return -ENODEV; +} static inline void serdev_device_wait_until_sent(struct serdev_device *sdev, long timeout) {} static inline int serdev_device_get_tiocm(struct serdev_device *serdev) { @@ -312,11 +319,4 @@ static inline struct device *serdev_tty_port_register(struct tty_port *port, static inline void serdev_tty_port_unregister(struct tty_port *port) {} #endif /* CONFIG_SERIAL_DEV_CTRL_TTYPORT */ -static inline int serdev_device_write_buf(struct serdev_device *serdev, - const unsigned char *data, - size_t count) -{ - return serdev_device_write(serdev, data, count, 0); -} - #endif /*_LINUX_SERDEV_H */ -- cgit v1.2.3 From 8cde11b2baa1d02eb2eb955dfd47d9f2a12f12cf Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 18 May 2017 17:33:00 +0200 Subject: tty/serdev: add serdev registration interface Add a new interface for registering a serdev controller and clients, and a helper function to deregister serdev devices (or a tty device) that were previously registered using the new interface. Once every driver currently using the tty_port_register_device() helpers have been vetted and converted to use the new serdev registration interface (at least for deregistration), we can move serdev registration to the current helpers and get rid of the serdev-specific functions. Reviewed-by: Rob Herring Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serdev/serdev-ttyport.c | 6 ++- drivers/tty/tty_port.c | 75 +++++++++++++++++++++++++++++++++++++ include/linux/serdev.h | 7 +++- include/linux/tty.h | 9 +++++ 4 files changed, 93 insertions(+), 4 deletions(-) diff --git a/drivers/tty/serdev/serdev-ttyport.c b/drivers/tty/serdev/serdev-ttyport.c index 013efffd2e82..d0a021c93986 100644 --- a/drivers/tty/serdev/serdev-ttyport.c +++ b/drivers/tty/serdev/serdev-ttyport.c @@ -250,16 +250,18 @@ err_reset_data: return ERR_PTR(ret); } -void serdev_tty_port_unregister(struct tty_port *port) +int serdev_tty_port_unregister(struct tty_port *port) { struct serdev_controller *ctrl = port->client_data; struct serport *serport = serdev_controller_get_drvdata(ctrl); if (!serport) - return; + return -ENODEV; serdev_controller_remove(ctrl); port->client_ops = NULL; port->client_data = NULL; serdev_controller_put(ctrl); + + return 0; } diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c index 88dac3b79369..4fb3165384c4 100644 --- a/drivers/tty/tty_port.c +++ b/drivers/tty/tty_port.c @@ -16,6 +16,7 @@ #include #include #include +#include static int tty_port_default_receive_buf(struct tty_port *port, const unsigned char *p, @@ -136,6 +137,80 @@ struct device *tty_port_register_device_attr(struct tty_port *port, } EXPORT_SYMBOL_GPL(tty_port_register_device_attr); +/** + * tty_port_register_device_attr_serdev - register tty or serdev device + * @port: tty_port of the device + * @driver: tty_driver for this device + * @index: index of the tty + * @device: parent if exists, otherwise NULL + * @drvdata: driver data for the device + * @attr_grp: attribute group for the device + * + * Register a serdev or tty device depending on if the parent device has any + * defined serdev clients or not. + */ +struct device *tty_port_register_device_attr_serdev(struct tty_port *port, + struct tty_driver *driver, unsigned index, + struct device *device, void *drvdata, + const struct attribute_group **attr_grp) +{ + struct device *dev; + + tty_port_link_device(port, driver, index); + + dev = serdev_tty_port_register(port, device, driver, index); + if (PTR_ERR(dev) != -ENODEV) { + /* Skip creating cdev if we registered a serdev device */ + return dev; + } + + return tty_register_device_attr(driver, index, device, drvdata, + attr_grp); +} +EXPORT_SYMBOL_GPL(tty_port_register_device_attr_serdev); + +/** + * tty_port_register_device_serdev - register tty or serdev device + * @port: tty_port of the device + * @driver: tty_driver for this device + * @index: index of the tty + * @device: parent if exists, otherwise NULL + * + * Register a serdev or tty device depending on if the parent device has any + * defined serdev clients or not. + */ +struct device *tty_port_register_device_serdev(struct tty_port *port, + struct tty_driver *driver, unsigned index, + struct device *device) +{ + return tty_port_register_device_attr_serdev(port, driver, index, + device, NULL, NULL); +} +EXPORT_SYMBOL_GPL(tty_port_register_device_serdev); + +/** + * tty_port_unregister_device - deregister a tty or serdev device + * @port: tty_port of the device + * @driver: tty_driver for this device + * @index: index of the tty + * + * If a tty or serdev device is registered with a call to + * tty_port_register_device_serdev() then this function must be called when + * the device is gone. + */ +void tty_port_unregister_device(struct tty_port *port, + struct tty_driver *driver, unsigned index) +{ + int ret; + + ret = serdev_tty_port_unregister(port); + if (ret == 0) + return; + + tty_unregister_device(driver, index); +} +EXPORT_SYMBOL_GPL(tty_port_unregister_device); + int tty_port_alloc_xmit_buf(struct tty_port *port) { /* We may sleep in get_zeroed_page() */ diff --git a/include/linux/serdev.h b/include/linux/serdev.h index e2a225bf716d..e69402d4a8ae 100644 --- a/include/linux/serdev.h +++ b/include/linux/serdev.h @@ -308,7 +308,7 @@ struct tty_driver; struct device *serdev_tty_port_register(struct tty_port *port, struct device *parent, struct tty_driver *drv, int idx); -void serdev_tty_port_unregister(struct tty_port *port); +int serdev_tty_port_unregister(struct tty_port *port); #else static inline struct device *serdev_tty_port_register(struct tty_port *port, struct device *parent, @@ -316,7 +316,10 @@ static inline struct device *serdev_tty_port_register(struct tty_port *port, { return ERR_PTR(-ENODEV); } -static inline void serdev_tty_port_unregister(struct tty_port *port) {} +static inline int serdev_tty_port_unregister(struct tty_port *port) +{ + return -ENODEV; +} #endif /* CONFIG_SERIAL_DEV_CTRL_TTYPORT */ #endif /*_LINUX_SERDEV_H */ diff --git a/include/linux/tty.h b/include/linux/tty.h index d07cd2105a6c..eccb4ec30a8a 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -558,6 +558,15 @@ extern struct device *tty_port_register_device_attr(struct tty_port *port, struct tty_driver *driver, unsigned index, struct device *device, void *drvdata, const struct attribute_group **attr_grp); +extern struct device *tty_port_register_device_serdev(struct tty_port *port, + struct tty_driver *driver, unsigned index, + struct device *device); +extern struct device *tty_port_register_device_attr_serdev(struct tty_port *port, + struct tty_driver *driver, unsigned index, + struct device *device, void *drvdata, + const struct attribute_group **attr_grp); +extern void tty_port_unregister_device(struct tty_port *port, + struct tty_driver *driver, unsigned index); extern int tty_port_alloc_xmit_buf(struct tty_port *port); extern void tty_port_free_xmit_buf(struct tty_port *port); extern void tty_port_destroy(struct tty_port *port); -- cgit v1.2.3 From da4c279942b05727088774df224c0734688b4cbc Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 18 May 2017 17:33:01 +0200 Subject: serial: enable serdev support Enable serdev support by using the new device-registration helpers. Reviewed-by: Rob Herring Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index bc6caea6099f..13bfd5dcffce 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -2782,7 +2782,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport) * Register the port whether it's detected or not. This allows * setserial to be used to alter this port's parameters. */ - tty_dev = tty_port_register_device_attr(port, drv->tty_driver, + tty_dev = tty_port_register_device_attr_serdev(port, drv->tty_driver, uport->line, uport->dev, port, uport->tty_groups); if (likely(!IS_ERR(tty_dev))) { device_set_wakeup_capable(tty_dev, 1); @@ -2845,7 +2845,7 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport) /* * Remove the devices from the tty layer */ - tty_unregister_device(drv->tty_driver, uport->line); + tty_port_unregister_device(port, drv->tty_driver, uport->line); tty = tty_port_tty_get(port); if (tty) { -- cgit v1.2.3 From 21a228781104ae6fed7e720137ab024575071feb Mon Sep 17 00:00:00 2001 From: Amir Goldstein Date: Wed, 17 May 2017 00:12:41 +0300 Subject: ovl: handle rename when upper doesn't support xattr On failure to set opaque/redirect xattr on rename, skip setting xattr and return -EXDEV. On failure to set opaque xattr when creating a new directory, -EIO is returned instead of -EOPNOTSUPP. Any failure to set those xattr will be recorded in super block and then setting any xattr on upper won't be attempted again. Signed-off-by: Amir Goldstein Signed-off-by: Miklos Szeredi --- fs/overlayfs/dir.c | 29 +++++++++++++++++++---------- fs/overlayfs/overlayfs.h | 1 - fs/overlayfs/util.c | 9 +-------- 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c index 723b98b90698..80e0e202a346 100644 --- a/fs/overlayfs/dir.c +++ b/fs/overlayfs/dir.c @@ -127,17 +127,28 @@ int ovl_create_real(struct inode *dir, struct dentry *newdentry, return err; } -static int ovl_set_opaque(struct dentry *dentry, struct dentry *upperdentry) +static int ovl_set_opaque_xerr(struct dentry *dentry, struct dentry *upper, + int xerr) { int err; - err = ovl_do_setxattr(upperdentry, OVL_XATTR_OPAQUE, "y", 1, 0); + err = ovl_check_setxattr(dentry, upper, OVL_XATTR_OPAQUE, "y", 1, xerr); if (!err) ovl_dentry_set_opaque(dentry); return err; } +static int ovl_set_opaque(struct dentry *dentry, struct dentry *upperdentry) +{ + /* + * Fail with -EIO when trying to create opaque dir and upper doesn't + * support xattrs. ovl_rename() calls ovl_set_opaque_xerr(-EXDEV) to + * return a specific error for noxattr case. + */ + return ovl_set_opaque_xerr(dentry, upperdentry, -EIO); +} + /* Common operations required to be done after creation of file on upper */ static void ovl_instantiate(struct dentry *dentry, struct inode *inode, struct dentry *newdentry, bool hardlink) @@ -846,18 +857,16 @@ static int ovl_set_redirect(struct dentry *dentry, bool samedir) if (IS_ERR(redirect)) return PTR_ERR(redirect); - err = ovl_do_setxattr(ovl_dentry_upper(dentry), OVL_XATTR_REDIRECT, - redirect, strlen(redirect), 0); + err = ovl_check_setxattr(dentry, ovl_dentry_upper(dentry), + OVL_XATTR_REDIRECT, + redirect, strlen(redirect), -EXDEV); if (!err) { spin_lock(&dentry->d_lock); ovl_dentry_set_redirect(dentry, redirect); spin_unlock(&dentry->d_lock); } else { kfree(redirect); - if (err == -EOPNOTSUPP) - ovl_clear_redirect_dir(dentry->d_sb); - else - pr_warn_ratelimited("overlay: failed to set redirect (%i)\n", err); + pr_warn_ratelimited("overlay: failed to set redirect (%i)\n", err); /* Fall back to userspace copy-up */ err = -EXDEV; } @@ -992,7 +1001,7 @@ static int ovl_rename(struct inode *olddir, struct dentry *old, if (ovl_type_merge_or_lower(old)) err = ovl_set_redirect(old, samedir); else if (!old_opaque && ovl_type_merge(new->d_parent)) - err = ovl_set_opaque(old, olddentry); + err = ovl_set_opaque_xerr(old, olddentry, -EXDEV); if (err) goto out_dput; } @@ -1000,7 +1009,7 @@ static int ovl_rename(struct inode *olddir, struct dentry *old, if (ovl_type_merge_or_lower(new)) err = ovl_set_redirect(new, samedir); else if (!new_opaque && ovl_type_merge(old->d_parent)) - err = ovl_set_opaque(new, newdentry); + err = ovl_set_opaque_xerr(new, newdentry, -EXDEV); if (err) goto out_dput; } diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index ce7c3aba61e4..505b18b56330 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h @@ -206,7 +206,6 @@ bool ovl_dentry_is_opaque(struct dentry *dentry); bool ovl_dentry_is_whiteout(struct dentry *dentry); void ovl_dentry_set_opaque(struct dentry *dentry); bool ovl_redirect_dir(struct super_block *sb); -void ovl_clear_redirect_dir(struct super_block *sb); const char *ovl_dentry_get_redirect(struct dentry *dentry); void ovl_dentry_set_redirect(struct dentry *dentry, const char *redirect); void ovl_dentry_update(struct dentry *dentry, struct dentry *upperdentry); diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c index b5a0dc36ee96..4d541a8d0834 100644 --- a/fs/overlayfs/util.c +++ b/fs/overlayfs/util.c @@ -191,14 +191,7 @@ bool ovl_redirect_dir(struct super_block *sb) { struct ovl_fs *ofs = sb->s_fs_info; - return ofs->config.redirect_dir; -} - -void ovl_clear_redirect_dir(struct super_block *sb) -{ - struct ovl_fs *ofs = sb->s_fs_info; - - ofs->config.redirect_dir = false; + return ofs->config.redirect_dir && !ofs->noxattr; } const char *ovl_dentry_get_redirect(struct dentry *dentry) -- cgit v1.2.3 From 3d27573ce32b47ba54e6680c77c26a700d67cc16 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Fri, 19 May 2017 09:33:49 +0200 Subject: ovl: remove unused arg from ovl_lookup_temp() Signed-off-by: Miklos Szeredi --- fs/overlayfs/copy_up.c | 2 +- fs/overlayfs/dir.c | 8 ++++---- fs/overlayfs/overlayfs.h | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c index f92ab35d43a6..843ed2a2d7db 100644 --- a/fs/overlayfs/copy_up.c +++ b/fs/overlayfs/copy_up.c @@ -346,7 +346,7 @@ static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir, if (tmpfile) temp = ovl_do_tmpfile(upperdir, stat->mode); else - temp = ovl_lookup_temp(workdir, dentry); + temp = ovl_lookup_temp(workdir); err = 0; if (IS_ERR(temp)) { err = PTR_ERR(temp); diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c index 80e0e202a346..369ee7c4cdc0 100644 --- a/fs/overlayfs/dir.c +++ b/fs/overlayfs/dir.c @@ -41,7 +41,7 @@ void ovl_cleanup(struct inode *wdir, struct dentry *wdentry) } } -struct dentry *ovl_lookup_temp(struct dentry *workdir, struct dentry *dentry) +struct dentry *ovl_lookup_temp(struct dentry *workdir) { struct dentry *temp; char name[20]; @@ -68,7 +68,7 @@ static struct dentry *ovl_whiteout(struct dentry *workdir, struct dentry *whiteout; struct inode *wdir = workdir->d_inode; - whiteout = ovl_lookup_temp(workdir, dentry); + whiteout = ovl_lookup_temp(workdir); if (IS_ERR(whiteout)) return whiteout; @@ -261,7 +261,7 @@ static struct dentry *ovl_clear_empty(struct dentry *dentry, if (upper->d_parent->d_inode != udir) goto out_unlock; - opaquedir = ovl_lookup_temp(workdir, dentry); + opaquedir = ovl_lookup_temp(workdir); err = PTR_ERR(opaquedir); if (IS_ERR(opaquedir)) goto out_unlock; @@ -393,7 +393,7 @@ static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode, if (err) goto out; - newdentry = ovl_lookup_temp(workdir, dentry); + newdentry = ovl_lookup_temp(workdir); err = PTR_ERR(newdentry); if (IS_ERR(newdentry)) goto out_unlock; diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index 505b18b56330..7c56932bfc2f 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h @@ -262,7 +262,7 @@ static inline void ovl_copyattr(struct inode *from, struct inode *to) /* dir.c */ extern const struct inode_operations ovl_dir_inode_operations; -struct dentry *ovl_lookup_temp(struct dentry *workdir, struct dentry *dentry); +struct dentry *ovl_lookup_temp(struct dentry *workdir); struct cattr { dev_t rdev; umode_t mode; -- cgit v1.2.3 From ee1d6d37b6b884383b501089be93ce94f2153028 Mon Sep 17 00:00:00 2001 From: Amir Goldstein Date: Thu, 11 May 2017 16:42:26 +0300 Subject: ovl: mark upper dir with type origin entries "impure" When moving a merge dir or non-dir with copy up origin into a non-merge upper dir (a.k.a pure upper dir), we are marking the target parent dir "impure". ovl_iterate() iterates pure upper dirs directly, because there is no need to filter out whiteouts and merge dir content with lower dir. But for the case of an "impure" upper dir, ovl_iterate() will not be able to iterate the real upper dir directly, because it will need to lookup the origin inode and use it to fill d_ino. Signed-off-by: Amir Goldstein Signed-off-by: Miklos Szeredi --- fs/overlayfs/dir.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ fs/overlayfs/namei.c | 18 ++++++++++++++++-- fs/overlayfs/overlayfs.h | 3 +++ fs/overlayfs/ovl_entry.h | 1 + fs/overlayfs/util.c | 14 ++++++++++++++ 5 files changed, 79 insertions(+), 2 deletions(-) diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c index 369ee7c4cdc0..f2a118ba00e4 100644 --- a/fs/overlayfs/dir.c +++ b/fs/overlayfs/dir.c @@ -149,6 +149,22 @@ static int ovl_set_opaque(struct dentry *dentry, struct dentry *upperdentry) return ovl_set_opaque_xerr(dentry, upperdentry, -EIO); } +static int ovl_set_impure(struct dentry *dentry, struct dentry *upperdentry) +{ + int err; + + /* + * Do not fail when upper doesn't support xattrs. + * Upper inodes won't have origin nor redirect xattr anyway. + */ + err = ovl_check_setxattr(dentry, upperdentry, OVL_XATTR_IMPURE, + "y", 1, 0); + if (!err) + ovl_dentry_set_impure(dentry); + + return err; +} + /* Common operations required to be done after creation of file on upper */ static void ovl_instantiate(struct dentry *dentry, struct inode *inode, struct dentry *newdentry, bool hardlink) @@ -173,6 +189,11 @@ static bool ovl_type_merge(struct dentry *dentry) return OVL_TYPE_MERGE(ovl_path_type(dentry)); } +static bool ovl_type_origin(struct dentry *dentry) +{ + return OVL_TYPE_ORIGIN(ovl_path_type(dentry)); +} + static int ovl_create_upper(struct dentry *dentry, struct inode *inode, struct cattr *attr, struct dentry *hardlink) { @@ -952,6 +973,30 @@ static int ovl_rename(struct inode *olddir, struct dentry *old, old_upperdir = ovl_dentry_upper(old->d_parent); new_upperdir = ovl_dentry_upper(new->d_parent); + if (!samedir) { + /* + * When moving a merge dir or non-dir with copy up origin into + * a non-merge upper dir (a.k.a pure upper dir), we are making + * the target parent dir "impure". ovl_iterate() iterates pure + * upper dirs directly, because there is no need to filter out + * whiteouts and merge dir content with lower dir. But for the + * case of an "impure" upper dir, ovl_iterate() cannot iterate + * the real directory directly, because it looks for the inode + * numbers to fill d_ino in the entries origin inode. + */ + if (ovl_type_origin(old) && !ovl_type_merge(new->d_parent)) { + err = ovl_set_impure(new->d_parent, new_upperdir); + if (err) + goto out_revert_creds; + } + if (!overwrite && ovl_type_origin(new) && + !ovl_type_merge(old->d_parent)) { + err = ovl_set_impure(old->d_parent, old_upperdir); + if (err) + goto out_revert_creds; + } + } + trap = lock_rename(new_upperdir, old_upperdir); olddentry = lookup_one_len(old->d_name.name, old_upperdir, diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c index bad0f665a635..0c72a5909db2 100644 --- a/fs/overlayfs/namei.c +++ b/fs/overlayfs/namei.c @@ -167,7 +167,7 @@ invalid: goto out; } -static bool ovl_is_opaquedir(struct dentry *dentry) +static bool ovl_check_dir_xattr(struct dentry *dentry, const char *name) { int res; char val; @@ -175,13 +175,23 @@ static bool ovl_is_opaquedir(struct dentry *dentry) if (!d_is_dir(dentry)) return false; - res = vfs_getxattr(dentry, OVL_XATTR_OPAQUE, &val, 1); + res = vfs_getxattr(dentry, name, &val, 1); if (res == 1 && val == 'y') return true; return false; } +static bool ovl_is_opaquedir(struct dentry *dentry) +{ + return ovl_check_dir_xattr(dentry, OVL_XATTR_OPAQUE); +} + +static bool ovl_is_impuredir(struct dentry *dentry) +{ + return ovl_check_dir_xattr(dentry, OVL_XATTR_IMPURE); +} + static int ovl_lookup_single(struct dentry *base, struct ovl_lookup_data *d, const char *name, unsigned int namelen, size_t prelen, const char *post, @@ -351,6 +361,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, unsigned int ctr = 0; struct inode *inode = NULL; bool upperopaque = false; + bool upperimpure = false; char *upperredirect = NULL; struct dentry *this; unsigned int i; @@ -395,6 +406,8 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, poe = roe; } upperopaque = d.opaque; + if (upperdentry && d.is_dir) + upperimpure = ovl_is_impuredir(upperdentry); } if (!d.stop && poe->numlower) { @@ -463,6 +476,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, revert_creds(old_cred); oe->opaque = upperopaque; + oe->impure = upperimpure; oe->redirect = upperredirect; oe->__upperdentry = upperdentry; memcpy(oe->lowerstack, stack, sizeof(struct path) * ctr); diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index 7c56932bfc2f..a9fb958fd5d4 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h @@ -24,6 +24,7 @@ enum ovl_path_type { #define OVL_XATTR_OPAQUE OVL_XATTR_PREFIX "opaque" #define OVL_XATTR_REDIRECT OVL_XATTR_PREFIX "redirect" #define OVL_XATTR_ORIGIN OVL_XATTR_PREFIX "origin" +#define OVL_XATTR_IMPURE OVL_XATTR_PREFIX "impure" /* * The tuple (fh,uuid) is a universal unique identifier for a copy up origin, @@ -203,8 +204,10 @@ struct dentry *ovl_dentry_real(struct dentry *dentry); struct ovl_dir_cache *ovl_dir_cache(struct dentry *dentry); void ovl_set_dir_cache(struct dentry *dentry, struct ovl_dir_cache *cache); bool ovl_dentry_is_opaque(struct dentry *dentry); +bool ovl_dentry_is_impure(struct dentry *dentry); bool ovl_dentry_is_whiteout(struct dentry *dentry); void ovl_dentry_set_opaque(struct dentry *dentry); +void ovl_dentry_set_impure(struct dentry *dentry); bool ovl_redirect_dir(struct super_block *sb); const char *ovl_dentry_get_redirect(struct dentry *dentry); void ovl_dentry_set_redirect(struct dentry *dentry, const char *redirect); diff --git a/fs/overlayfs/ovl_entry.h b/fs/overlayfs/ovl_entry.h index ad86c0a302eb..34bc4a9f5c61 100644 --- a/fs/overlayfs/ovl_entry.h +++ b/fs/overlayfs/ovl_entry.h @@ -43,6 +43,7 @@ struct ovl_entry { u64 version; const char *redirect; bool opaque; + bool impure; bool copying; }; struct rcu_head rcu; diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c index 4d541a8d0834..e0dfb07d5457 100644 --- a/fs/overlayfs/util.c +++ b/fs/overlayfs/util.c @@ -175,6 +175,13 @@ bool ovl_dentry_is_opaque(struct dentry *dentry) return oe->opaque; } +bool ovl_dentry_is_impure(struct dentry *dentry) +{ + struct ovl_entry *oe = dentry->d_fsdata; + + return oe->impure; +} + bool ovl_dentry_is_whiteout(struct dentry *dentry) { return !dentry->d_inode && ovl_dentry_is_opaque(dentry); @@ -187,6 +194,13 @@ void ovl_dentry_set_opaque(struct dentry *dentry) oe->opaque = true; } +void ovl_dentry_set_impure(struct dentry *dentry) +{ + struct ovl_entry *oe = dentry->d_fsdata; + + oe->impure = true; +} + bool ovl_redirect_dir(struct super_block *sb) { struct ovl_fs *ofs = sb->s_fs_info; -- cgit v1.2.3 From 53bf9590151e06e3f74212fea8da2eca2385db76 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 25 Apr 2017 03:14:54 +0000 Subject: phy: qcom-qmp: fix return value check in qcom_qmp_phy_create() In case of error, the function of_iomap() returns NULL pointer not ERR_PTR(). The IS_ERR() test in the return value check should be replaced with NULL test. Fixes: e78f3d15e115 ("phy: qcom-qmp: new qmp phy driver for qcom-chipsets") Reviewed-by: Vivek Gautam Signed-off-by: Wei Yongjun Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/phy-qcom-qmp.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/phy/phy-qcom-qmp.c b/drivers/phy/phy-qcom-qmp.c index 727e23be7cac..a25c29d5fdf6 100644 --- a/drivers/phy/phy-qcom-qmp.c +++ b/drivers/phy/phy-qcom-qmp.c @@ -983,16 +983,16 @@ int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id) * Resources are indexed as: tx -> 0; rx -> 1; pcs -> 2. */ qphy->tx = of_iomap(np, 0); - if (IS_ERR(qphy->tx)) - return PTR_ERR(qphy->tx); + if (!qphy->tx) + return -ENOMEM; qphy->rx = of_iomap(np, 1); - if (IS_ERR(qphy->rx)) - return PTR_ERR(qphy->rx); + if (!qphy->rx) + return -ENOMEM; qphy->pcs = of_iomap(np, 2); - if (IS_ERR(qphy->pcs)) - return PTR_ERR(qphy->pcs); + if (!qphy->pcs) + return -ENOMEM; /* * Get PHY's Pipe clock, if any. USB3 and PCIe are PIPE3 -- cgit v1.2.3 From 46cd902f6d9a746f0da816cbdfb04b9baf6d7967 Mon Sep 17 00:00:00 2001 From: Chuanxiao Dong Date: Thu, 11 May 2017 18:07:42 +0800 Subject: drm/i915: set initialised only when init_context callback is NULL During execlist_context_deferred_alloc() we presumed that the context is uninitialised (we only just allocated the state object for it!) and chose to optimise away the later call to engine->init_context() if engine->init_context were NULL. This breaks with GVT's contexts that are marked as pre-initialised to avoid us annoyingly calling engine->init_context(). The fix is to not override ce->initialised if it is already true. Cc: Chris Wilson Signed-off-by: Chuanxiao Dong Link: http://patchwork.freedesktop.org/patch/msgid/1494497262-24855-1-git-send-email-chuanxiao.dong@intel.com Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson (cherry picked from commit 0d402a24df8c8160727af934d83293f3d44d31a3) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_lrc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index c8f7c631fc1f..dac4e003c1f3 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1989,7 +1989,7 @@ static int execlists_context_deferred_alloc(struct i915_gem_context *ctx, ce->ring = ring; ce->state = vma; - ce->initialised = engine->init_context == NULL; + ce->initialised |= engine->init_context == NULL; return 0; -- cgit v1.2.3 From fe06fe860250a4f01d0eaf70a2563b1997174a74 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Fri, 19 May 2017 11:29:04 +1000 Subject: selftests/powerpc: Fix TM resched DSCR test with some compilers The tm-resched-dscr test has started failing sometimes, depending on what compiler it's built with, eg: test: tm_resched_dscr Check DSCR TM context switch: tm-resched-dscr: tm-resched-dscr.c:76: test_body: Assertion `rv' failed. !! child died by signal 6 When it fails we see that the compiler doesn't initialise rv to 1 before entering the inline asm block. Although that's counter intuitive, it is allowed because we tell the compiler that the inline asm will write to rv (using "=r"), meaning the original value is irrelevant. Marking it as a read/write parameter would presumably work, but it seems simpler to fix it by setting the initial value of rv in the inline asm. Fixes: 96d016108640 ("powerpc: Correct DSCR during TM context switch") Signed-off-by: Michael Ellerman Acked-by: Michael Neuling --- tools/testing/selftests/powerpc/tm/tm-resched-dscr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/testing/selftests/powerpc/tm/tm-resched-dscr.c b/tools/testing/selftests/powerpc/tm/tm-resched-dscr.c index d9c49f41515e..e79ccd6aada1 100644 --- a/tools/testing/selftests/powerpc/tm/tm-resched-dscr.c +++ b/tools/testing/selftests/powerpc/tm/tm-resched-dscr.c @@ -42,12 +42,12 @@ int test_body(void) printf("Check DSCR TM context switch: "); fflush(stdout); for (;;) { - rv = 1; asm __volatile__ ( /* set a known value into the DSCR */ "ld 3, %[dscr1];" "mtspr %[sprn_dscr], 3;" + "li %[rv], 1;" /* start and suspend a transaction */ "tbegin.;" "beq 1f;" -- cgit v1.2.3 From a486cd23661c9387fb076c3f6ae8b2aa9d20d54a Mon Sep 17 00:00:00 2001 From: Antony Antony Date: Fri, 19 May 2017 12:47:00 +0200 Subject: xfrm: fix state migration copy replay sequence numbers During xfrm migration copy replay and preplay sequence numbers from the previous state. Here is a tcpdump output showing the problem. 10.0.10.46 is running vanilla kernel, is the IKE/IPsec responder. After the migration it sent wrong sequence number, reset to 1. The migration is from 10.0.0.52 to 10.0.0.53. IP 10.0.0.52.4500 > 10.0.10.46.4500: UDP-encap: ESP(spi=0x43ef462d,seq=0x7cf), length 136 IP 10.0.10.46.4500 > 10.0.0.52.4500: UDP-encap: ESP(spi=0xca1c282d,seq=0x7cf), length 136 IP 10.0.0.52.4500 > 10.0.10.46.4500: UDP-encap: ESP(spi=0x43ef462d,seq=0x7d0), length 136 IP 10.0.10.46.4500 > 10.0.0.52.4500: UDP-encap: ESP(spi=0xca1c282d,seq=0x7d0), length 136 IP 10.0.0.53.4500 > 10.0.10.46.4500: NONESP-encap: isakmp: child_sa inf2[I] IP 10.0.10.46.4500 > 10.0.0.53.4500: NONESP-encap: isakmp: child_sa inf2[R] IP 10.0.0.53.4500 > 10.0.10.46.4500: NONESP-encap: isakmp: child_sa inf2[I] IP 10.0.10.46.4500 > 10.0.0.53.4500: NONESP-encap: isakmp: child_sa inf2[R] IP 10.0.0.53.4500 > 10.0.10.46.4500: UDP-encap: ESP(spi=0x43ef462d,seq=0x7d1), length 136 NOTE: next sequence is wrong 0x1 IP 10.0.10.46.4500 > 10.0.0.53.4500: UDP-encap: ESP(spi=0xca1c282d,seq=0x1), length 136 IP 10.0.0.53.4500 > 10.0.10.46.4500: UDP-encap: ESP(spi=0x43ef462d,seq=0x7d2), length 136 IP 10.0.10.46.4500 > 10.0.0.53.4500: UDP-encap: ESP(spi=0xca1c282d,seq=0x2), length 136 Signed-off-by: Antony Antony Reviewed-by: Richard Guy Briggs Signed-off-by: Steffen Klassert --- net/xfrm/xfrm_state.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index fc3c5aa38754..2e291bc5f1fc 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -1383,6 +1383,8 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig) x->curlft.add_time = orig->curlft.add_time; x->km.state = orig->km.state; x->km.seq = orig->km.seq; + x->replay = orig->replay; + x->preplay = orig->preplay; return x; -- cgit v1.2.3 From 1f8754d4daea5f257370a52a30fcb22798c54516 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 16 May 2017 01:48:24 +0000 Subject: ASoC: rsnd: don't call free_irq() on Parent SSI If SSI uses shared pin, some SSI will be used as parent SSI. Then, normal SSI's remove and Parent SSI's remove (these are same SSI) will be called when unbind or remove timing. In this case, free_irq() will be called twice. This patch solve this issue. Signed-off-by: Kuninori Morimoto Tested-by: Hiroyuki Yokoyama Reported-by: Hiroyuki Yokoyama Signed-off-by: Mark Brown --- sound/soc/sh/rcar/ssi.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index e43277a5068c..c224695c1484 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -709,6 +709,11 @@ static int rsnd_ssi_dma_remove(struct rsnd_mod *mod, struct rsnd_priv *priv) { struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); + struct rsnd_mod *ssi_parent_mod = rsnd_io_to_mod_ssip(io); + + /* Do nothing for SSI parent mod */ + if (ssi_parent_mod == mod) + return 0; /* PIO will request IRQ again */ free_irq(ssi->irq, mod); -- cgit v1.2.3 From f746aa5e8636c83e53bbb2d988bb614f732b2b80 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Mon, 15 May 2017 14:00:31 -0700 Subject: ASoC: simple-card: fix mic jack initialization Initialize asoc_simple_card_init_mic with the correct struct asoc_simple_jack. Fixes: 9eac361877b3 ("ASoC: simple-card: add new asoc_simple_jack and use it") Signed-off-by: Stefan Agner Acked-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/generic/simple-card.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 2c9dedab5184..bc136d2bd7cd 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -202,7 +202,7 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) if (ret < 0) return ret; - ret = asoc_simple_card_init_mic(rtd->card, &priv->hp_jack, PREFIX); + ret = asoc_simple_card_init_mic(rtd->card, &priv->mic_jack, PREFIX); if (ret < 0) return ret; -- cgit v1.2.3 From 3780578761921f094179c6289072a74b2228c602 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Sat, 20 May 2017 15:03:29 -0500 Subject: x86/boot: Use CROSS_COMPILE prefix for readelf The boot code Makefile contains a straight 'readelf' invocation. This causes build warnings in cross compile environments, when there is no unprefixed readelf accessible via $PATH. Add the missing $(CROSS_COMPILE) prefix. [ tglx: Rewrote changelog ] Fixes: 98f78525371b ("x86/boot: Refuse to build with data relocations") Signed-off-by: Rob Landley Acked-by: Kees Cook Cc: Jiri Kosina Cc: Paul Bolle Cc: "H.J. Lu" Cc: stable@vger.kernel.org Link: http://lkml.kernel.org/r/ced18878-693a-9576-a024-113ef39a22c0@landley.net Signed-off-by: Thomas Gleixner --- arch/x86/boot/compressed/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile index 44163e8c3868..2c860ad4fe06 100644 --- a/arch/x86/boot/compressed/Makefile +++ b/arch/x86/boot/compressed/Makefile @@ -94,7 +94,7 @@ vmlinux-objs-$(CONFIG_EFI_MIXED) += $(obj)/efi_thunk_$(BITS).o quiet_cmd_check_data_rel = DATAREL $@ define cmd_check_data_rel for obj in $(filter %.o,$^); do \ - readelf -S $$obj | grep -qF .rel.local && { \ + ${CROSS_COMPILE}readelf -S $$obj | grep -qF .rel.local && { \ echo "error: $$obj has data relocations!" >&2; \ exit 1; \ } || true; \ -- cgit v1.2.3 From 4eecbe81885180c9f6217ecfd679b1f285967218 Mon Sep 17 00:00:00 2001 From: Marcin Niestroj Date: Thu, 18 May 2017 09:12:06 +0200 Subject: iio: trigger: fix NULL pointer dereference in iio_trigger_write_current() In case oldtrig == trig == NULL (which happens when we set none trigger, when there is already none set) there is a NULL pointer dereference during iio_trigger_put(trig). Below is kernel output when this occurs: [ 26.741790] Unable to handle kernel NULL pointer dereference at virtual address 00000000 [ 26.750179] pgd = cacc0000 [ 26.752936] [00000000] *pgd=8adc6835, *pte=00000000, *ppte=00000000 [ 26.759531] Internal error: Oops: 17 [#1] SMP ARM [ 26.764261] Modules linked in: usb_f_ncm u_ether usb_f_acm u_serial usb_f_fs libcomposite configfs evbug [ 26.773844] CPU: 0 PID: 152 Comm: synchro Not tainted 4.12.0-rc1 #2 [ 26.780128] Hardware name: Freescale i.MX6 Ultralite (Device Tree) [ 26.786329] task: cb1de200 task.stack: cac92000 [ 26.790892] PC is at iio_trigger_write_current+0x188/0x1f4 [ 26.796403] LR is at lock_release+0xf8/0x20c [ 26.800696] pc : [] lr : [] psr: 600d0013 [ 26.800696] sp : cac93e30 ip : cac93db0 fp : cac93e5c [ 26.812193] r10: c0e64fe8 r9 : 00000000 r8 : 00000001 [ 26.817436] r7 : cb190810 r6 : 00000010 r5 : 00000001 r4 : 00000000 [ 26.823982] r3 : 00000000 r2 : 00000000 r1 : cb1de200 r0 : 00000000 [ 26.830528] Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment none [ 26.837683] Control: 10c5387d Table: 8acc006a DAC: 00000051 [ 26.843448] Process synchro (pid: 152, stack limit = 0xcac92210) [ 26.849475] Stack: (0xcac93e30 to 0xcac94000) [ 26.853857] 3e20: 00000001 c0736dac c054033c cae6b680 [ 26.862060] 3e40: cae6b680 00000000 00000001 cb3f8610 cac93e74 cac93e60 c054035c c0736db8 [ 26.870264] 3e60: 00000001 c054033c cac93e94 cac93e78 c029bf34 c0540348 00000000 00000000 [ 26.878469] 3e80: cb3f8600 cae6b680 cac93ed4 cac93e98 c029b320 c029bef0 00000000 00000000 [ 26.886672] 3ea0: 00000000 cac93f78 cb2d41fc caed3280 c029b214 cac93f78 00000001 000e20f8 [ 26.894874] 3ec0: 00000001 00000000 cac93f44 cac93ed8 c0221dcc c029b220 c0e1ca39 cb2d41fc [ 26.903079] 3ee0: cac93f04 cac93ef0 c0183ef0 c0183ab0 cb2d41fc 00000000 cac93f44 cac93f08 [ 26.911282] 3f00: c0225eec c0183ebc 00000001 00000000 c0223728 00000000 c0245454 00000001 [ 26.919485] 3f20: 00000001 caed3280 000e20f8 cac93f78 000e20f8 00000001 cac93f74 cac93f48 [ 26.927690] 3f40: c0223680 c0221da4 c0246520 c0245460 caed3283 caed3280 00000000 00000000 [ 26.935893] 3f60: 000e20f8 00000001 cac93fa4 cac93f78 c0224520 c02235e4 00000000 00000000 [ 26.944096] 3f80: 00000001 000e20f8 00000001 00000004 c0107f84 cac92000 00000000 cac93fa8 [ 26.952299] 3fa0: c0107de0 c02244e8 00000001 000e20f8 0000000e 000e20f8 00000001 fbad2484 [ 26.960502] 3fc0: 00000001 000e20f8 00000001 00000004 beb6b698 00064260 0006421c beb6b4b4 [ 26.968705] 3fe0: 00000000 beb6b450 b6f219a0 b6e2f268 800d0010 0000000e cac93ff4 cac93ffc [ 26.976896] Backtrace: [ 26.979388] [] (iio_trigger_write_current) from [] (dev_attr_store+0x20/0x2c) [ 26.988289] r10:cb3f8610 r9:00000001 r8:00000000 r7:cae6b680 r6:cae6b680 r5:c054033c [ 26.996138] r4:c0736dac r3:00000001 [ 26.999747] [] (dev_attr_store) from [] (sysfs_kf_write+0x50/0x54) [ 27.007686] r5:c054033c r4:00000001 [ 27.011290] [] (sysfs_kf_write) from [] (kernfs_fop_write+0x10c/0x224) [ 27.019579] r7:cae6b680 r6:cb3f8600 r5:00000000 r4:00000000 [ 27.025271] [] (kernfs_fop_write) from [] (__vfs_write+0x34/0x120) [ 27.033214] r10:00000000 r9:00000001 r8:000e20f8 r7:00000001 r6:cac93f78 r5:c029b214 [ 27.041059] r4:caed3280 [ 27.043622] [] (__vfs_write) from [] (vfs_write+0xa8/0x170) [ 27.050959] r9:00000001 r8:000e20f8 r7:cac93f78 r6:000e20f8 r5:caed3280 r4:00000001 [ 27.058731] [] (vfs_write) from [] (SyS_write+0x44/0x98) [ 27.065806] r9:00000001 r8:000e20f8 r7:00000000 r6:00000000 r5:caed3280 r4:caed3283 [ 27.073582] [] (SyS_write) from [] (ret_fast_syscall+0x0/0x1c) [ 27.081179] r9:cac92000 r8:c0107f84 r7:00000004 r6:00000001 r5:000e20f8 r4:00000001 [ 27.088947] Code: 1a000009 e1a04009 e3a06010 e1a05008 (e5943000) [ 27.095244] ---[ end trace 06d1dab86d6e6bab ]--- To fix that problem call iio_trigger_put(trig) only when trig is not NULL. Fixes: d5d24bcc0a10 ("iio: trigger: close race condition in acquiring trigger reference") Signed-off-by: Marcin Niestroj Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/industrialio-trigger.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/iio/industrialio-trigger.c b/drivers/iio/industrialio-trigger.c index 978e1592c2a3..4061fed93f1f 100644 --- a/drivers/iio/industrialio-trigger.c +++ b/drivers/iio/industrialio-trigger.c @@ -451,7 +451,8 @@ static ssize_t iio_trigger_write_current(struct device *dev, return len; out_trigger_put: - iio_trigger_put(trig); + if (trig) + iio_trigger_put(trig); return ret; } -- cgit v1.2.3 From f7d86ecf83cb66d3c4c6ac4edb1dd50c0919aa2b Mon Sep 17 00:00:00 2001 From: Raveendra Padasalagi Date: Tue, 16 May 2017 12:22:42 +0530 Subject: iio: adc: bcm_iproc_adc: swap primary and secondary isr handler's The third argument of devm_request_threaded_irq() is the primary handler. It is called in hardirq context and checks whether the interrupt is relevant to the device. If the primary handler returns IRQ_WAKE_THREAD, the secondary handler (a.k.a. handler thread) is scheduled to run in process context. bcm_iproc_adc.c uses the secondary handler as the primary one and the other way around. So this patch fixes the same, along with re-naming the secondary handler and primary handler names properly. Tested on the BCM9583XX iProc SoC based boards. Fixes: 4324c97ecedc ("iio: Add driver for Broadcom iproc-static-adc") Reported-by: Pavel Roskin Signed-off-by: Raveendra Padasalagi Cc: stable@vger.kernel.org Signed-off-by: Jonathan Cameron --- drivers/iio/adc/bcm_iproc_adc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/iio/adc/bcm_iproc_adc.c b/drivers/iio/adc/bcm_iproc_adc.c index 21d38c8af21e..7f4f9c4150e3 100644 --- a/drivers/iio/adc/bcm_iproc_adc.c +++ b/drivers/iio/adc/bcm_iproc_adc.c @@ -143,7 +143,7 @@ static void iproc_adc_reg_dump(struct iio_dev *indio_dev) iproc_adc_dbg_reg(dev, adc_priv, IPROC_SOFT_BYPASS_DATA); } -static irqreturn_t iproc_adc_interrupt_handler(int irq, void *data) +static irqreturn_t iproc_adc_interrupt_thread(int irq, void *data) { u32 channel_intr_status; u32 intr_status; @@ -167,7 +167,7 @@ static irqreturn_t iproc_adc_interrupt_handler(int irq, void *data) return IRQ_NONE; } -static irqreturn_t iproc_adc_interrupt_thread(int irq, void *data) +static irqreturn_t iproc_adc_interrupt_handler(int irq, void *data) { irqreturn_t retval = IRQ_NONE; struct iproc_adc_priv *adc_priv; @@ -181,7 +181,7 @@ static irqreturn_t iproc_adc_interrupt_thread(int irq, void *data) adc_priv = iio_priv(indio_dev); regmap_read(adc_priv->regmap, IPROC_INTERRUPT_STATUS, &intr_status); - dev_dbg(&indio_dev->dev, "iproc_adc_interrupt_thread(),INTRPT_STS:%x\n", + dev_dbg(&indio_dev->dev, "iproc_adc_interrupt_handler(),INTRPT_STS:%x\n", intr_status); intr_channels = (intr_status & IPROC_ADC_INTR_MASK) >> IPROC_ADC_INTR; @@ -566,8 +566,8 @@ static int iproc_adc_probe(struct platform_device *pdev) } ret = devm_request_threaded_irq(&pdev->dev, adc_priv->irqno, - iproc_adc_interrupt_thread, iproc_adc_interrupt_handler, + iproc_adc_interrupt_thread, IRQF_SHARED, "iproc-adc", indio_dev); if (ret) { dev_err(&pdev->dev, "request_irq error %d\n", ret); -- cgit v1.2.3 From 7cc3bff4efe6164a0c8163331c8aa55454799f42 Mon Sep 17 00:00:00 2001 From: Franziska Naepelt Date: Wed, 17 May 2017 12:41:19 +0200 Subject: iio: light: ltr501 Fix interchanged als/ps register field The register mapping for the IIO driver for the Liteon Light and Proximity sensor LTR501 interrupt mode is interchanged (ALS/PS). There is a register called INTERRUPT register (address 0x8F) Bit 0 represents PS measurement trigger. Bit 1 represents ALS measurement trigger. This two bit fields are interchanged within the driver. see datasheet page 24: http://optoelectronics.liteon.com/upload/download/DS86-2012-0006/S_110_LTR-501ALS-01_PrelimDS_ver1%5B1%5D.pdf Signed-off-by: Franziska Naepelt Fixes: 7ac702b3144b6 ("iio: ltr501: Add interrupt support") Acked-by: Peter Meerwald-Stadler Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/light/ltr501.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c index b30e0c1c6cc4..67838edd8b37 100644 --- a/drivers/iio/light/ltr501.c +++ b/drivers/iio/light/ltr501.c @@ -74,9 +74,9 @@ static const int int_time_mapping[] = {100000, 50000, 200000, 400000}; static const struct reg_field reg_field_it = REG_FIELD(LTR501_ALS_MEAS_RATE, 3, 4); static const struct reg_field reg_field_als_intr = - REG_FIELD(LTR501_INTR, 0, 0); -static const struct reg_field reg_field_ps_intr = REG_FIELD(LTR501_INTR, 1, 1); +static const struct reg_field reg_field_ps_intr = + REG_FIELD(LTR501_INTR, 0, 0); static const struct reg_field reg_field_als_rate = REG_FIELD(LTR501_ALS_MEAS_RATE, 0, 2); static const struct reg_field reg_field_ps_rate = -- cgit v1.2.3 From 82237f268281d338aa35cd014be8ffb0b5445482 Mon Sep 17 00:00:00 2001 From: Quentin Schulz Date: Thu, 18 May 2017 08:36:07 +0200 Subject: iio: adc: sun4i-gpadc-iio: fix parent device being used in devm function For the sake of DT binding stability, this IIO driver is a child of an MFD driver for Allwinner A10, A13 and A31 because there already exists a DT binding for this IP. The MFD driver has a DT node but the IIO driver does not. The IIO device registers the temperature sensor in the thermal framework using the DT node of the parent, the MFD device, so the thermal framework could match the phandle to the MFD device in the DT and the struct device used to register in the thermal framework. devm_thermal_zone_of_sensor_register was previously used to register the thermal sensor with the parent struct device of the IIO device, representing the MFD device. By doing so, we registered actually the parent in the devm routine and not the actual IIO device. This lead to the devm unregister function not being called when the IIO module driver is removed. It resulted in the thermal framework still polling the get_temp function of the IIO module while the device doesn't exist anymore, thus generated a kernel panic. Use the non-devm function instead and do the unregister manually in the remove function. Fixes: d1caa9905538 ("iio: adc: add support for Allwinner SoCs ADC") Signed-off-by: Quentin Schulz Reported-by: Corentin Labbe Reviewed-by: Maxime Ripard Signed-off-by: Jonathan Cameron --- drivers/iio/adc/sun4i-gpadc-iio.c | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c index 1c83b45043bf..81d4c39e414a 100644 --- a/drivers/iio/adc/sun4i-gpadc-iio.c +++ b/drivers/iio/adc/sun4i-gpadc-iio.c @@ -105,6 +105,8 @@ struct sun4i_gpadc_iio { bool no_irq; /* prevents concurrent reads of temperature and ADC */ struct mutex mutex; + struct thermal_zone_device *tzd; + struct device *sensor_device; }; #define SUN4I_GPADC_ADC_CHANNEL(_channel, _name) { \ @@ -502,7 +504,6 @@ static int sun4i_gpadc_probe_dt(struct platform_device *pdev, { struct sun4i_gpadc_iio *info = iio_priv(indio_dev); const struct of_device_id *of_dev; - struct thermal_zone_device *tzd; struct resource *mem; void __iomem *base; int ret; @@ -532,13 +533,14 @@ static int sun4i_gpadc_probe_dt(struct platform_device *pdev, if (!IS_ENABLED(CONFIG_THERMAL_OF)) return 0; - tzd = devm_thermal_zone_of_sensor_register(&pdev->dev, 0, info, - &sun4i_ts_tz_ops); - if (IS_ERR(tzd)) + info->sensor_device = &pdev->dev; + info->tzd = thermal_zone_of_sensor_register(info->sensor_device, 0, + info, &sun4i_ts_tz_ops); + if (IS_ERR(info->tzd)) dev_err(&pdev->dev, "could not register thermal sensor: %ld\n", - PTR_ERR(tzd)); + PTR_ERR(info->tzd)); - return PTR_ERR_OR_ZERO(tzd); + return PTR_ERR_OR_ZERO(info->tzd); } static int sun4i_gpadc_probe_mfd(struct platform_device *pdev, @@ -584,15 +586,15 @@ static int sun4i_gpadc_probe_mfd(struct platform_device *pdev, * of_node, and the device from this driver as third argument to * return the temperature. */ - struct thermal_zone_device *tzd; - tzd = devm_thermal_zone_of_sensor_register(pdev->dev.parent, 0, - info, - &sun4i_ts_tz_ops); - if (IS_ERR(tzd)) { + info->sensor_device = pdev->dev.parent; + info->tzd = thermal_zone_of_sensor_register(info->sensor_device, + 0, info, + &sun4i_ts_tz_ops); + if (IS_ERR(info->tzd)) { dev_err(&pdev->dev, "could not register thermal sensor: %ld\n", - PTR_ERR(tzd)); - return PTR_ERR(tzd); + PTR_ERR(info->tzd)); + return PTR_ERR(info->tzd); } } else { indio_dev->num_channels = @@ -688,7 +690,13 @@ static int sun4i_gpadc_remove(struct platform_device *pdev) pm_runtime_put(&pdev->dev); pm_runtime_disable(&pdev->dev); - if (!info->no_irq && IS_ENABLED(CONFIG_THERMAL_OF)) + + if (!IS_ENABLED(CONFIG_THERMAL_OF)) + return 0; + + thermal_zone_of_sensor_unregister(info->sensor_device, info->tzd); + + if (!info->no_irq) iio_map_array_unregister(indio_dev); return 0; -- cgit v1.2.3 From 2d1f406139ec20320bf38bcd2461aa8e358084b5 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Fri, 19 May 2017 11:39:09 +0200 Subject: x86/MCE: Export memory_error() Export the function which checks whether an MCE is a memory error to other users so that we can reuse the logic. Drop the boot_cpu_data use, while at it, as mce.cpuvendor already has the CPU vendor in there. Integrate a piece from a patch from Vishal Verma to export it for modules (nfit). The main reason we're exporting it is that the nfit handler nfit_handle_mce() needs to detect a memory error properly before doing its recovery actions. Signed-off-by: Borislav Petkov Cc: Tony Luck Cc: Vishal Verma Cc: Link: http://lkml.kernel.org/r/20170519093915.15413-2-bp@alien8.de Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/mce.h | 1 + arch/x86/kernel/cpu/mcheck/mce.c | 13 ++++++------- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h index 4fd5195deed0..3f9a3d2a5209 100644 --- a/arch/x86/include/asm/mce.h +++ b/arch/x86/include/asm/mce.h @@ -266,6 +266,7 @@ static inline int umc_normaddr_to_sysaddr(u64 norm_addr, u16 nid, u8 umc, u64 *s #endif int mce_available(struct cpuinfo_x86 *c); +bool mce_is_memory_error(struct mce *m); DECLARE_PER_CPU(unsigned, mce_exception_count); DECLARE_PER_CPU(unsigned, mce_poll_count); diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index 5abd4bf73d6e..5cfbaeb6529a 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c @@ -499,16 +499,14 @@ static int mce_usable_address(struct mce *m) return 1; } -static bool memory_error(struct mce *m) +bool mce_is_memory_error(struct mce *m) { - struct cpuinfo_x86 *c = &boot_cpu_data; - - if (c->x86_vendor == X86_VENDOR_AMD) { + if (m->cpuvendor == X86_VENDOR_AMD) { /* ErrCodeExt[20:16] */ u8 xec = (m->status >> 16) & 0x1f; return (xec == 0x0 || xec == 0x8); - } else if (c->x86_vendor == X86_VENDOR_INTEL) { + } else if (m->cpuvendor == X86_VENDOR_INTEL) { /* * Intel SDM Volume 3B - 15.9.2 Compound Error Codes * @@ -529,6 +527,7 @@ static bool memory_error(struct mce *m) return false; } +EXPORT_SYMBOL_GPL(mce_is_memory_error); static bool cec_add_mce(struct mce *m) { @@ -536,7 +535,7 @@ static bool cec_add_mce(struct mce *m) return false; /* We eat only correctable DRAM errors with usable addresses. */ - if (memory_error(m) && + if (mce_is_memory_error(m) && !(m->status & MCI_STATUS_UC) && mce_usable_address(m)) if (!cec_add_elem(m->addr >> PAGE_SHIFT)) @@ -713,7 +712,7 @@ bool machine_check_poll(enum mcp_flags flags, mce_banks_t *b) severity = mce_severity(&m, mca_cfg.tolerant, NULL, false); - if (severity == MCE_DEFERRED_SEVERITY && memory_error(&m)) + if (severity == MCE_DEFERRED_SEVERITY && mce_is_memory_error(&m)) if (m.status & MCI_STATUS_ADDRV) m.severity = severity; -- cgit v1.2.3 From fc08a4703a418a398bbb575ac311d36d110ac786 Mon Sep 17 00:00:00 2001 From: Vishal Verma Date: Fri, 19 May 2017 11:39:10 +0200 Subject: acpi, nfit: Fix the memory error check in nfit_handle_mce() The check for an MCE being a memory error in the NFIT mce handler was bogus. Use the new mce_is_memory_error() helper to detect the error properly. Reported-by: Tony Luck Signed-off-by: Vishal Verma Signed-off-by: Borislav Petkov Cc: Link: http://lkml.kernel.org/r/20170519093915.15413-3-bp@alien8.de Signed-off-by: Thomas Gleixner --- drivers/acpi/nfit/mce.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/nfit/mce.c b/drivers/acpi/nfit/mce.c index 3ba1c3472cf9..fd86bec98dea 100644 --- a/drivers/acpi/nfit/mce.c +++ b/drivers/acpi/nfit/mce.c @@ -26,7 +26,7 @@ static int nfit_handle_mce(struct notifier_block *nb, unsigned long val, struct nfit_spa *nfit_spa; /* We only care about memory errors */ - if (!(mce->status & MCACOD)) + if (!mce_is_memory_error(mce)) return NOTIFY_DONE; /* -- cgit v1.2.3 From 964edf66bf9ab70cb387b27946c0aef7b94c4d1b Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Sun, 21 May 2017 22:31:23 -0400 Subject: ext4: clear lockdep subtype for quota files on quota off Quota files have special ranking of i_data_sem lock. We inform lockdep about it when turning on quotas however when turning quotas off, we don't clear the lockdep subclass from i_data_sem lock and thus when the inode gets later reused for a normal file or directory, lockdep gets confused and complains about possible deadlocks. Fix the problem by resetting lockdep subclass of i_data_sem on quota off. Cc: stable@vger.kernel.org Fixes: daf647d2dd58cec59570d7698a45b98e580f2076 Reported-and-tested-by: Ross Zwisler Reviewed-by: Andreas Dilger Signed-off-by: Jan Kara Signed-off-by: Theodore Ts'o --- fs/ext4/super.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 0b177da9ea82..8f05c72bc4ec 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -848,14 +848,9 @@ static inline void ext4_quota_off_umount(struct super_block *sb) { int type; - if (ext4_has_feature_quota(sb)) { - dquot_disable(sb, -1, - DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED); - } else { - /* Use our quota_off function to clear inode flags etc. */ - for (type = 0; type < EXT4_MAXQUOTAS; type++) - ext4_quota_off(sb, type); - } + /* Use our quota_off function to clear inode flags etc. */ + for (type = 0; type < EXT4_MAXQUOTAS; type++) + ext4_quota_off(sb, type); } #else static inline void ext4_quota_off_umount(struct super_block *sb) @@ -5485,7 +5480,7 @@ static int ext4_quota_off(struct super_block *sb, int type) goto out; err = dquot_quota_off(sb, type); - if (err) + if (err || ext4_has_feature_quota(sb)) goto out_put; inode_lock(inode); @@ -5505,6 +5500,7 @@ static int ext4_quota_off(struct super_block *sb, int type) out_unlock: inode_unlock(inode); out_put: + lockdep_set_quota_inode(inode, I_DATA_SEM_NORMAL); iput(inode); return err; out: -- cgit v1.2.3 From b4709067ac0944e4a5b94eabdc26155c6f2efbd7 Mon Sep 17 00:00:00 2001 From: Tahsin Erdogan Date: Sun, 21 May 2017 22:32:23 -0400 Subject: jbd2: preserve original nofs flag during journal restart When a transaction starts, start_this_handle() saves current PF_MEMALLOC_NOFS value so that it can be restored at journal stop time. Journal restart is a special case that calls start_this_handle() without stopping the transaction. start_this_handle() isn't aware that the original value is already stored so it overwrites it with current value. For instance, a call sequence like below leaves PF_MEMALLOC_NOFS flag set at the end: jbd2_journal_start() jbd2__journal_restart() jbd2_journal_stop() Make jbd2__journal_restart() restore the original value before calling start_this_handle(). Fixes: 81378da64de6 ("jbd2: mark the transaction context with the scope GFP_NOFS context") Signed-off-by: Tahsin Erdogan Signed-off-by: Theodore Ts'o Reviewed-by: Jan Kara --- fs/jbd2/transaction.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index 9ee4832b6f8b..2d30a6da7013 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c @@ -680,6 +680,12 @@ int jbd2__journal_restart(handle_t *handle, int nblocks, gfp_t gfp_mask) rwsem_release(&journal->j_trans_commit_map, 1, _THIS_IP_); handle->h_buffer_credits = nblocks; + /* + * Restore the original nofs context because the journal restart + * is basically the same thing as journal stop and start. + * start_this_handle will start a new nofs context. + */ + memalloc_nofs_restore(handle->saved_alloc_context); ret = start_this_handle(journal, handle, gfp_mask); return ret; } -- cgit v1.2.3 From 7d95eddf313c88b24f99d4ca9c2411a4b82fef33 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Sun, 21 May 2017 22:33:23 -0400 Subject: ext4: fix SEEK_HOLE Currently, SEEK_HOLE implementation in ext4 may both return that there's a hole at some offset although that offset already has data and skip some holes during a search for the next hole. The first problem is demostrated by: xfs_io -c "falloc 0 256k" -c "pwrite 0 56k" -c "seek -h 0" file wrote 57344/57344 bytes at offset 0 56 KiB, 14 ops; 0.0000 sec (2.054 GiB/sec and 538461.5385 ops/sec) Whence Result HOLE 0 Where we can see that SEEK_HOLE wrongly returned offset 0 as containing a hole although we have written data there. The second problem can be demonstrated by: xfs_io -c "falloc 0 256k" -c "pwrite 0 56k" -c "pwrite 128k 8k" -c "seek -h 0" file wrote 57344/57344 bytes at offset 0 56 KiB, 14 ops; 0.0000 sec (1.978 GiB/sec and 518518.5185 ops/sec) wrote 8192/8192 bytes at offset 131072 8 KiB, 2 ops; 0.0000 sec (2 GiB/sec and 500000.0000 ops/sec) Whence Result HOLE 139264 Where we can see that hole at offsets 56k..128k has been ignored by the SEEK_HOLE call. The underlying problem is in the ext4_find_unwritten_pgoff() which is just buggy. In some cases it fails to update returned offset when it finds a hole (when no pages are found or when the first found page has higher index than expected), in some cases conditions for detecting hole are just missing (we fail to detect a situation where indices of returned pages are not contiguous). Fix ext4_find_unwritten_pgoff() to properly detect non-contiguous page indices and also handle all cases where we got less pages then expected in one place and handle it properly there. CC: stable@vger.kernel.org Fixes: c8c0df241cc2719b1262e627f999638411934f60 CC: Zheng Liu Signed-off-by: Jan Kara Signed-off-by: Theodore Ts'o --- fs/ext4/file.c | 50 ++++++++++++++------------------------------------ 1 file changed, 14 insertions(+), 36 deletions(-) diff --git a/fs/ext4/file.c b/fs/ext4/file.c index 831fd6beebf0..bbea2dccd584 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c @@ -484,47 +484,27 @@ static int ext4_find_unwritten_pgoff(struct inode *inode, num = min_t(pgoff_t, end - index, PAGEVEC_SIZE); nr_pages = pagevec_lookup(&pvec, inode->i_mapping, index, (pgoff_t)num); - if (nr_pages == 0) { - if (whence == SEEK_DATA) - break; - - BUG_ON(whence != SEEK_HOLE); - /* - * If this is the first time to go into the loop and - * offset is not beyond the end offset, it will be a - * hole at this offset - */ - if (lastoff == startoff || lastoff < endoff) - found = 1; - break; - } - - /* - * If this is the first time to go into the loop and - * offset is smaller than the first page offset, it will be a - * hole at this offset. - */ - if (lastoff == startoff && whence == SEEK_HOLE && - lastoff < page_offset(pvec.pages[0])) { - found = 1; + if (nr_pages == 0) break; - } for (i = 0; i < nr_pages; i++) { struct page *page = pvec.pages[i]; struct buffer_head *bh, *head; /* - * If the current offset is not beyond the end of given - * range, it will be a hole. + * If current offset is smaller than the page offset, + * there is a hole at this offset. */ - if (lastoff < endoff && whence == SEEK_HOLE && - page->index > end) { + if (whence == SEEK_HOLE && lastoff < endoff && + lastoff < page_offset(pvec.pages[i])) { found = 1; *offset = lastoff; goto out; } + if (page->index > end) + goto out; + lock_page(page); if (unlikely(page->mapping != inode->i_mapping)) { @@ -564,20 +544,18 @@ static int ext4_find_unwritten_pgoff(struct inode *inode, unlock_page(page); } - /* - * The no. of pages is less than our desired, that would be a - * hole in there. - */ - if (nr_pages < num && whence == SEEK_HOLE) { - found = 1; - *offset = lastoff; + /* The no. of pages is less than our desired, we are done. */ + if (nr_pages < num) break; - } index = pvec.pages[i - 1]->index + 1; pagevec_release(&pvec); } while (index <= end); + if (whence == SEEK_HOLE && lastoff < endoff) { + found = 1; + *offset = lastoff; + } out: pagevec_release(&pvec); return found; -- cgit v1.2.3 From 3f1d5bad3fae983da07be01cff2fde13293bb7b9 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Sun, 21 May 2017 22:34:23 -0400 Subject: ext4: fix off-by-in in loop termination in ext4_find_unwritten_pgoff() There is an off-by-one error in loop termination conditions in ext4_find_unwritten_pgoff() since 'end' may index a page beyond end of desired range if 'endoff' is page aligned. It doesn't have any visible effects but still it is good to fix it. Signed-off-by: Jan Kara Signed-off-by: Theodore Ts'o --- fs/ext4/file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ext4/file.c b/fs/ext4/file.c index bbea2dccd584..2b00bf84c05b 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c @@ -474,7 +474,7 @@ static int ext4_find_unwritten_pgoff(struct inode *inode, endoff = (loff_t)end_blk << blkbits; index = startoff >> PAGE_SHIFT; - end = endoff >> PAGE_SHIFT; + end = (endoff - 1) >> PAGE_SHIFT; pagevec_init(&pvec, 0); do { -- cgit v1.2.3 From 9651e6b2e20648d04d5e1fe6479a3056047e8781 Mon Sep 17 00:00:00 2001 From: Konstantin Khlebnikov Date: Sun, 21 May 2017 22:35:23 -0400 Subject: ext4: handle the rest of ext4_mb_load_buddy() ENOMEM errors I've got another report about breaking ext4 by ENOMEM error returned from ext4_mb_load_buddy() caused by memory shortage in memory cgroup. This time inside ext4_discard_preallocations(). This patch replaces ext4_error() with ext4_warning() where errors returned from ext4_mb_load_buddy() are not fatal and handled by caller: * ext4_mb_discard_group_preallocations() - called before generating ENOSPC, we'll try to discard other group or return ENOSPC into user-space. * ext4_trim_all_free() - just stop trimming and return ENOMEM from ioctl. Some callers cannot handle errors, thus __GFP_NOFAIL is used for them: * ext4_discard_preallocations() * ext4_mb_discard_lg_preallocations() Fixes: adb7ef600cc9 ("ext4: use __GFP_NOFAIL in ext4_free_blocks()") Signed-off-by: Konstantin Khlebnikov Signed-off-by: Theodore Ts'o --- fs/ext4/mballoc.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 5083bce20ac4..b7928cddd539 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -3887,7 +3887,8 @@ ext4_mb_discard_group_preallocations(struct super_block *sb, err = ext4_mb_load_buddy(sb, group, &e4b); if (err) { - ext4_error(sb, "Error loading buddy information for %u", group); + ext4_warning(sb, "Error %d loading buddy information for %u", + err, group); put_bh(bitmap_bh); return 0; } @@ -4044,10 +4045,11 @@ repeat: BUG_ON(pa->pa_type != MB_INODE_PA); group = ext4_get_group_number(sb, pa->pa_pstart); - err = ext4_mb_load_buddy(sb, group, &e4b); + err = ext4_mb_load_buddy_gfp(sb, group, &e4b, + GFP_NOFS|__GFP_NOFAIL); if (err) { - ext4_error(sb, "Error loading buddy information for %u", - group); + ext4_error(sb, "Error %d loading buddy information for %u", + err, group); continue; } @@ -4303,11 +4305,14 @@ ext4_mb_discard_lg_preallocations(struct super_block *sb, spin_unlock(&lg->lg_prealloc_lock); list_for_each_entry_safe(pa, tmp, &discard_list, u.pa_tmp_list) { + int err; group = ext4_get_group_number(sb, pa->pa_pstart); - if (ext4_mb_load_buddy(sb, group, &e4b)) { - ext4_error(sb, "Error loading buddy information for %u", - group); + err = ext4_mb_load_buddy_gfp(sb, group, &e4b, + GFP_NOFS|__GFP_NOFAIL); + if (err) { + ext4_error(sb, "Error %d loading buddy information for %u", + err, group); continue; } ext4_lock_group(sb, group); @@ -5127,8 +5132,8 @@ ext4_trim_all_free(struct super_block *sb, ext4_group_t group, ret = ext4_mb_load_buddy(sb, group, &e4b); if (ret) { - ext4_error(sb, "Error in loading buddy " - "information for %u", group); + ext4_warning(sb, "Error %d loading buddy information for %u", + ret, group); return ret; } bitmap = e4b.bd_bitmap; -- cgit v1.2.3 From 887a9730614727c4fff7cb756711b190593fc1df Mon Sep 17 00:00:00 2001 From: Konstantin Khlebnikov Date: Sun, 21 May 2017 22:36:23 -0400 Subject: ext4: keep existing extra fields when inode expands ext4_expand_extra_isize() should clear only space between old and new size. Fixes: 6dd4ee7cab7e # v2.6.23 Cc: stable@vger.kernel.org Signed-off-by: Konstantin Khlebnikov Signed-off-by: Theodore Ts'o --- fs/ext4/inode.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 1bd0bfa547f6..7cd99de8c4ba 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -5637,8 +5637,9 @@ static int ext4_expand_extra_isize(struct inode *inode, /* No extended attributes present */ if (!ext4_test_inode_state(inode, EXT4_STATE_XATTR) || header->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC)) { - memset((void *)raw_inode + EXT4_GOOD_OLD_INODE_SIZE, 0, - new_extra_isize); + memset((void *)raw_inode + EXT4_GOOD_OLD_INODE_SIZE + + EXT4_I(inode)->i_extra_isize, 0, + new_extra_isize - EXT4_I(inode)->i_extra_isize); EXT4_I(inode)->i_extra_isize = new_extra_isize; return 0; } -- cgit v1.2.3 From 2dffdc0724004f38f5e39907747b53e4b0d80e59 Mon Sep 17 00:00:00 2001 From: Guoqing Jiang Date: Tue, 16 May 2017 14:01:25 +0800 Subject: md-cluster: fix potential lock issue in add_new_disk The add_new_disk returns with communication locked if __sendmsg returns failure, fix it with call unlock_comm before return. Reported-by: Dan Carpenter CC: Goldwyn Rodrigues Signed-off-by: Guoqing Jiang Signed-off-by: Shaohua Li --- drivers/md/md-cluster.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/md/md-cluster.c b/drivers/md/md-cluster.c index 7299ce2f08a8..03082e17c65c 100644 --- a/drivers/md/md-cluster.c +++ b/drivers/md/md-cluster.c @@ -1311,8 +1311,10 @@ static int add_new_disk(struct mddev *mddev, struct md_rdev *rdev) cmsg.raid_slot = cpu_to_le32(rdev->desc_nr); lock_comm(cinfo, 1); ret = __sendmsg(cinfo, &cmsg); - if (ret) + if (ret) { + unlock_comm(cinfo); return ret; + } cinfo->no_new_dev_lockres->flags |= DLM_LKF_NOQUEUE; ret = dlm_lock_sync(cinfo->no_new_dev_lockres, DLM_LOCK_EX); cinfo->no_new_dev_lockres->flags &= ~DLM_LKF_NOQUEUE; -- cgit v1.2.3 From f752413e26bdc9f73a8a12e280770646555c82fc Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 21 Apr 2017 13:51:43 +0300 Subject: drm/mediatek: fix a timeout loop This code causes a static checker warning because it treats "i == 0" as a timeout but, because it's a post-op, the loop actually ends with "i" set to -1. Philipp Zabel points out that it would be cleaner to use readl_poll_timeout() instead. Fixes: 21898816831f ("drm/mediatek: add dsi transfer function") Signed-off-by: Dan Carpenter Signed-off-by: CK Hu Reviewed-by: Philipp Zabel --- drivers/gpu/drm/mediatek/mtk_dsi.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c index 808b995a990f..b5cc6e12334c 100644 --- a/drivers/gpu/drm/mediatek/mtk_dsi.c +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -900,16 +901,12 @@ static int mtk_dsi_host_detach(struct mipi_dsi_host *host, static void mtk_dsi_wait_for_idle(struct mtk_dsi *dsi) { - u32 timeout_ms = 500000; /* total 1s ~ 2s timeout */ - - while (timeout_ms--) { - if (!(readl(dsi->regs + DSI_INTSTA) & DSI_BUSY)) - break; - - usleep_range(2, 4); - } + int ret; + u32 val; - if (timeout_ms == 0) { + ret = readl_poll_timeout(dsi->regs + DSI_INTSTA, val, !(val & DSI_BUSY), + 4, 2000000); + if (ret) { DRM_WARN("polling dsi wait not busy timeout!\n"); mtk_dsi_enable(dsi); -- cgit v1.2.3 From 014580ffab654bb83256783a2b185cf6c06dffaa Mon Sep 17 00:00:00 2001 From: YYS Date: Tue, 21 Mar 2017 16:27:03 +0800 Subject: drm/mediatek: fix mtk_hdmi_setup_vendor_specific_infoframe mistake mtk_hdmi_setup_vendor_specific_infoframe will return before handle mtk_hdmi_hw_send_info_frame.Because hdmi_vendor_infoframe_pack returns the number of bytes packed into the binary buffer or a negative error code on failure. So correct it. Fixes: 8f83f26891e1 ("drm/mediatek: Add HDMI support") Signed-off-by: Nickey Yang Signed-off-by: CK Hu --- drivers/gpu/drm/mediatek/mtk_hdmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c index 41a1c03b0347..0a4ffd724146 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c @@ -1062,7 +1062,7 @@ static int mtk_hdmi_setup_vendor_specific_infoframe(struct mtk_hdmi *hdmi, } err = hdmi_vendor_infoframe_pack(&frame, buffer, sizeof(buffer)); - if (err) { + if (err < 0) { dev_err(hdmi->dev, "Failed to pack vendor infoframe: %zd\n", err); return err; -- cgit v1.2.3 From 44d4182e23c555cbfa8b8a0ad2d94664d23850d3 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Mon, 1 May 2017 17:04:50 -0700 Subject: mtd: nand: don't leak buffers when ->scan_bbt() fails This bug seems to have been here forever, although we came close to fixing all of them in [1]! [1] 11eaf6df1cce ("mtd: nand: Remove BUG() abuse in nand_scan_tail") Signed-off-by: Brian Norris Acked-by: Ezequiel Garcia Signed-off-by: Boris Brezillon --- drivers/mtd/nand/nand_base.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index d474378ed810..66782291a762 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -4842,7 +4842,11 @@ int nand_scan_tail(struct mtd_info *mtd) return 0; /* Build bad block table */ - return chip->scan_bbt(mtd); + ret = chip->scan_bbt(mtd); + if (ret) + goto err_free; + return 0; + err_free: if (nbuf) { kfree(nbuf->databuf); -- cgit v1.2.3 From 0545c1720277dd246bd682b23aee425f3830a14f Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Mon, 1 May 2017 17:04:52 -0700 Subject: mtd: nand: drop unneeded module.h include nand_ids isn't a separate module anymore and doesn't need this header. Signed-off-by: Brian Norris Signed-off-by: Boris Brezillon --- drivers/mtd/nand/nand_ids.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c index 9d5ca0e540b5..92e2cf8e9ff9 100644 --- a/drivers/mtd/nand/nand_ids.c +++ b/drivers/mtd/nand/nand_ids.c @@ -6,7 +6,6 @@ * published by the Free Software Foundation. * */ -#include #include #include -- cgit v1.2.3 From 787710492911e21148975e1d1914c7409fb32c7e Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Mon, 1 May 2017 17:04:53 -0700 Subject: mtd: nand: free vendor-specific resources in init failure paths If we fail any time after calling nand_detect(), then we don't call the vendor-specific ->cleanup() callback, and we'll leak any resources the vendor-specific code might have allocated. Mark the "fix" against the first commit that started allocating anything in ->init(). Fixes: 626994e07480 ("mtd: nand: hynix: Add read-retry support for 1x nm MLC NANDs") Signed-off-by: Brian Norris Signed-off-by: Boris Brezillon --- drivers/mtd/nand/nand_base.c | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 66782291a762..81f77f9cd784 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -4361,7 +4361,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips, /* Initialize the ->data_interface field. */ ret = nand_init_data_interface(chip); if (ret) - return ret; + goto err_nand_init; /* * Setup the data interface correctly on the chip and controller side. @@ -4373,7 +4373,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips, */ ret = nand_setup_data_interface(chip); if (ret) - return ret; + goto err_nand_init; nand_maf_id = chip->id.data[0]; nand_dev_id = chip->id.data[1]; @@ -4404,6 +4404,12 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips, mtd->size = i * chip->chipsize; return 0; + +err_nand_init: + /* Free manufacturer priv data. */ + nand_manufacturer_cleanup(chip); + + return ret; } EXPORT_SYMBOL(nand_scan_ident); @@ -4574,18 +4580,23 @@ int nand_scan_tail(struct mtd_info *mtd) /* New bad blocks should be marked in OOB, flash-based BBT, or both */ if (WARN_ON((chip->bbt_options & NAND_BBT_NO_OOB_BBM) && - !(chip->bbt_options & NAND_BBT_USE_FLASH))) - return -EINVAL; + !(chip->bbt_options & NAND_BBT_USE_FLASH))) { + ret = -EINVAL; + goto err_ident; + } if (invalid_ecc_page_accessors(chip)) { pr_err("Invalid ECC page accessors setup\n"); - return -EINVAL; + ret = -EINVAL; + goto err_ident; } if (!(chip->options & NAND_OWN_BUFFERS)) { nbuf = kzalloc(sizeof(*nbuf), GFP_KERNEL); - if (!nbuf) - return -ENOMEM; + if (!nbuf) { + ret = -ENOMEM; + goto err_ident; + } nbuf->ecccalc = kmalloc(mtd->oobsize, GFP_KERNEL); if (!nbuf->ecccalc) { @@ -4608,8 +4619,10 @@ int nand_scan_tail(struct mtd_info *mtd) chip->buffers = nbuf; } else { - if (!chip->buffers) - return -ENOMEM; + if (!chip->buffers) { + ret = -ENOMEM; + goto err_ident; + } } /* Set the internal oob buffer location, just after the page data */ @@ -4854,6 +4867,13 @@ err_free: kfree(nbuf->ecccalc); kfree(nbuf); } + +err_ident: + /* Clean up nand_scan_ident(). */ + + /* Free manufacturer priv data. */ + nand_manufacturer_cleanup(chip); + return ret; } EXPORT_SYMBOL(nand_scan_tail); -- cgit v1.2.3 From d24197907454b902908e025bce4b8bc677d3ba6b Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Mon, 1 May 2017 17:04:55 -0700 Subject: mtd: nand: samsung: warn about un-parseable ECC info We don't handle cases larger than 7. We probably shouldn't pretend we know the ECC step size in this case, and it's probably also good to WARN() like we do in many other similar cases. Fixes: 8fc82d456e40 ("mtd: nand: samsung: Retrieve ECC requirements from extended ID") Signed-off-by: Brian Norris Signed-off-by: Boris Brezillon --- drivers/mtd/nand/nand_samsung.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/mtd/nand/nand_samsung.c b/drivers/mtd/nand/nand_samsung.c index 9cfc4035a420..1e0755997762 100644 --- a/drivers/mtd/nand/nand_samsung.c +++ b/drivers/mtd/nand/nand_samsung.c @@ -84,6 +84,9 @@ static void samsung_nand_decode_id(struct nand_chip *chip) case 7: chip->ecc_strength_ds = 60; break; + default: + WARN(1, "Could not decode ECC info"); + chip->ecc_step_ds = 0; } } } else { -- cgit v1.2.3 From 2761b4f12b017f6d3e5add386733a700a490df47 Mon Sep 17 00:00:00 2001 From: Andres Galacho Date: Mon, 1 May 2017 16:30:15 -0400 Subject: mtd: nand: tango: Export OF device ID table as module aliases The device table is required to load modules based on modaliases. After adding MODULE_DEVICE_TABLE, below entries for example will be added to module.alias: alias: of:N*T*Csigma,smp8758-nandC* alias: of:N*T*Csigma,smp8758-nand Fixes: 6956e2385a16 ("mtd: nand: add tango NAND flash controller support") Cc: stable@vger.kernel.org Signed-off-by: Andres Galacho Acked-by: Brian Norris Signed-off-by: Boris Brezillon --- drivers/mtd/nand/tango_nand.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mtd/nand/tango_nand.c b/drivers/mtd/nand/tango_nand.c index 05b6e1065203..82fea9b4c358 100644 --- a/drivers/mtd/nand/tango_nand.c +++ b/drivers/mtd/nand/tango_nand.c @@ -663,6 +663,7 @@ static const struct of_device_id tango_nand_ids[] = { { .compatible = "sigma,smp8758-nand" }, { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, tango_nand_ids); static struct platform_driver tango_nand_driver = { .probe = tango_nand_probe, -- cgit v1.2.3 From 60cf0ce14b09b54e7ee79dc3ef498de6ef0e41e9 Mon Sep 17 00:00:00 2001 From: Marc Gonzalez Date: Fri, 12 May 2017 17:34:01 +0200 Subject: mtd: nand: tango: Update ecc_stats.corrected According to Boris, some user-space tools expect MTD drivers to update ecc_stats.corrected, and it's better to provide a lower bound than to provide no information at all. Fixes: 6956e2385a16 ("mtd: nand: add tango NAND flash controller support") Cc: stable@vger.kernel.org Reported-by: Pavel Machek Signed-off-by: Marc Gonzalez Signed-off-by: Boris Brezillon --- drivers/mtd/nand/tango_nand.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/drivers/mtd/nand/tango_nand.c b/drivers/mtd/nand/tango_nand.c index 82fea9b4c358..49b286c6c10f 100644 --- a/drivers/mtd/nand/tango_nand.c +++ b/drivers/mtd/nand/tango_nand.c @@ -55,10 +55,10 @@ * byte 1 for other packets in the page (PKT_N, for N > 0) * ERR_COUNT_PKT_N is the max error count over all but the first packet. */ -#define DECODE_OK_PKT_0(v) ((v) & BIT(7)) -#define DECODE_OK_PKT_N(v) ((v) & BIT(15)) #define ERR_COUNT_PKT_0(v) (((v) >> 0) & 0x3f) #define ERR_COUNT_PKT_N(v) (((v) >> 8) & 0x3f) +#define DECODE_FAIL_PKT_0(v) (((v) & BIT(7)) == 0) +#define DECODE_FAIL_PKT_N(v) (((v) & BIT(15)) == 0) /* Offsets relative to pbus_base */ #define PBUS_CS_CTRL 0x83c @@ -193,6 +193,8 @@ static int check_erased_page(struct nand_chip *chip, u8 *buf) chip->ecc.strength); if (res < 0) mtd->ecc_stats.failed++; + else + mtd->ecc_stats.corrected += res; bitflips = max(res, bitflips); buf += pkt_size; @@ -202,9 +204,11 @@ static int check_erased_page(struct nand_chip *chip, u8 *buf) return bitflips; } -static int decode_error_report(struct tango_nfc *nfc) +static int decode_error_report(struct nand_chip *chip) { u32 status, res; + struct mtd_info *mtd = nand_to_mtd(chip); + struct tango_nfc *nfc = to_tango_nfc(chip->controller); status = readl_relaxed(nfc->reg_base + NFC_XFER_STATUS); if (status & PAGE_IS_EMPTY) @@ -212,10 +216,14 @@ static int decode_error_report(struct tango_nfc *nfc) res = readl_relaxed(nfc->mem_base + ERROR_REPORT); - if (DECODE_OK_PKT_0(res) && DECODE_OK_PKT_N(res)) - return max(ERR_COUNT_PKT_0(res), ERR_COUNT_PKT_N(res)); + if (DECODE_FAIL_PKT_0(res) || DECODE_FAIL_PKT_N(res)) + return -EBADMSG; + + /* ERR_COUNT_PKT_N is max, not sum, but that's all we have */ + mtd->ecc_stats.corrected += + ERR_COUNT_PKT_0(res) + ERR_COUNT_PKT_N(res); - return -EBADMSG; + return max(ERR_COUNT_PKT_0(res), ERR_COUNT_PKT_N(res)); } static void tango_dma_callback(void *arg) @@ -282,7 +290,7 @@ static int tango_read_page(struct mtd_info *mtd, struct nand_chip *chip, if (err) return err; - res = decode_error_report(nfc); + res = decode_error_report(chip); if (res < 0) { chip->ecc.read_oob_raw(mtd, chip, page); res = check_erased_page(chip, buf); -- cgit v1.2.3 From d4ed3b9015b5eebc90d629579d9e7944607cbae5 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 4 May 2017 13:11:00 +0100 Subject: mtd: nand: make nand_ooblayout_lp_hamming_ops static nand_ooblayout_lp_hamming_ops can be made static as it does not need to be in global scope. Signed-off-by: Colin Ian King Acked-by: Boris Brezillon Signed-off-by: Boris Brezillon --- drivers/mtd/nand/nand_base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 81f77f9cd784..b1dd12729f19 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -202,7 +202,7 @@ static int nand_ooblayout_free_lp_hamming(struct mtd_info *mtd, int section, return 0; } -const struct mtd_ooblayout_ops nand_ooblayout_lp_hamming_ops = { +static const struct mtd_ooblayout_ops nand_ooblayout_lp_hamming_ops = { .ecc = nand_ooblayout_ecc_lp_hamming, .free = nand_ooblayout_free_lp_hamming, }; -- cgit v1.2.3 From df563c85de690ec0a1c7e49bd1d43ff743dfb1ce Mon Sep 17 00:00:00 2001 From: Joel Stanley Date: Tue, 2 May 2017 15:38:24 +0930 Subject: gpio: aspeed: Don't attempt to debounce if disabled We warn the user at driver probe time that debouncing is disabled. However, if they request debouncing later on we print a confusing error message: gpio_aspeed 1e780000.gpio: Failed to convert 5000us to cycles at 0Hz: -524 Instead bail out when the clock is not present. Fixes: 5ae4cb94b3133 (gpio: aspeed: Add debounce support) Signed-off-by: Joel Stanley Signed-off-by: Linus Walleij --- drivers/gpio/gpio-aspeed.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c index ccea609676ee..4ca436e66bdb 100644 --- a/drivers/gpio/gpio-aspeed.c +++ b/drivers/gpio/gpio-aspeed.c @@ -646,6 +646,9 @@ static int enable_debounce(struct gpio_chip *chip, unsigned int offset, int rc; int i; + if (!gpio->clk) + return -EINVAL; + rc = usecs_to_cycles(gpio, usecs, &requested_cycles); if (rc < 0) { dev_warn(chip->parent, "Failed to convert %luus to cycles at %luHz: %d\n", -- cgit v1.2.3 From a9de080bbcd5c4e213a3d7bbb1e314d60980e943 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 25 Apr 2017 06:22:05 +0000 Subject: pinctrl: cherryview: Add terminate entry for dmi_system_id tables Make sure dmi_system_id tables are NULL terminated. Fixes: 703650278372 ("pinctrl: cherryview: Add a quirk to make Acer Chromebook keyboard work again") Signed-off-by: Wei Yongjun Acked-by: Mika Westerberg Signed-off-by: Linus Walleij --- drivers/pinctrl/intel/pinctrl-cherryview.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c index 2debba62fac9..e35d0fe4c737 100644 --- a/drivers/pinctrl/intel/pinctrl-cherryview.c +++ b/drivers/pinctrl/intel/pinctrl-cherryview.c @@ -1547,7 +1547,8 @@ static const struct dmi_system_id chv_no_valid_mask[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Edgar"), DMI_MATCH(DMI_BIOS_DATE, "05/21/2016"), }, - } + }, + {} }; static int chv_gpio_probe(struct chv_pinctrl *pctrl, int irq) -- cgit v1.2.3 From b4d2ea2af95cb77e2f320e24da526280d4aa2f6b Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 8 May 2017 10:48:21 +0200 Subject: Revert "pinctrl: generic: Add bi-directional and output-enable" This reverts commit 8c58f1a7a4b6d1d723bf25fef9d842d5a11200d0. It turns out that applying these generic properties was premature: the properties used in the driver using this are of unclear electrical nature and the subject need to be discussed. Signed-off-by: Linus Walleij --- Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt | 2 -- drivers/pinctrl/pinconf-generic.c | 3 --- include/linux/pinctrl/pinconf-generic.h | 3 --- 3 files changed, 8 deletions(-) diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt index 71a3c134af1b..f01d154090da 100644 --- a/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt +++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt @@ -247,7 +247,6 @@ bias-bus-hold - latch weakly bias-pull-up - pull up the pin bias-pull-down - pull down the pin bias-pull-pin-default - use pin-default pull state -bi-directional - pin supports simultaneous input/output operations drive-push-pull - drive actively high and low drive-open-drain - drive with open drain drive-open-source - drive with open source @@ -260,7 +259,6 @@ input-debounce - debounce mode with debound time X power-source - select between different power supplies low-power-enable - enable low power mode low-power-disable - disable low power mode -output-enable - enable output on pin regardless of output value output-low - set the pin to output mode with low level output-high - set the pin to output mode with high level slew-rate - set the slew rate diff --git a/drivers/pinctrl/pinconf-generic.c b/drivers/pinctrl/pinconf-generic.c index 0d6b7f4b82af..720a19fd38d2 100644 --- a/drivers/pinctrl/pinconf-generic.c +++ b/drivers/pinctrl/pinconf-generic.c @@ -35,7 +35,6 @@ static const struct pin_config_item conf_items[] = { PCONFDUMP(PIN_CONFIG_BIAS_PULL_PIN_DEFAULT, "input bias pull to pin specific state", NULL, false), PCONFDUMP(PIN_CONFIG_BIAS_PULL_UP, "input bias pull up", NULL, false), - PCONFDUMP(PIN_CONFIG_BIDIRECTIONAL, "bi-directional pin operations", NULL, false), PCONFDUMP(PIN_CONFIG_DRIVE_OPEN_DRAIN, "output drive open drain", NULL, false), PCONFDUMP(PIN_CONFIG_DRIVE_OPEN_SOURCE, "output drive open source", NULL, false), PCONFDUMP(PIN_CONFIG_DRIVE_PUSH_PULL, "output drive push pull", NULL, false), @@ -161,7 +160,6 @@ static const struct pinconf_generic_params dt_params[] = { { "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 }, { "bias-pull-pin-default", PIN_CONFIG_BIAS_PULL_PIN_DEFAULT, 1 }, { "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 }, - { "bi-directional", PIN_CONFIG_BIDIRECTIONAL, 1 }, { "drive-open-drain", PIN_CONFIG_DRIVE_OPEN_DRAIN, 0 }, { "drive-open-source", PIN_CONFIG_DRIVE_OPEN_SOURCE, 0 }, { "drive-push-pull", PIN_CONFIG_DRIVE_PUSH_PULL, 0 }, @@ -174,7 +172,6 @@ static const struct pinconf_generic_params dt_params[] = { { "input-schmitt-enable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 1 }, { "low-power-disable", PIN_CONFIG_LOW_POWER_MODE, 0 }, { "low-power-enable", PIN_CONFIG_LOW_POWER_MODE, 1 }, - { "output-enable", PIN_CONFIG_OUTPUT, 1, }, { "output-high", PIN_CONFIG_OUTPUT, 1, }, { "output-low", PIN_CONFIG_OUTPUT, 0, }, { "power-source", PIN_CONFIG_POWER_SOURCE, 0 }, diff --git a/include/linux/pinctrl/pinconf-generic.h b/include/linux/pinctrl/pinconf-generic.h index 279e3c5326e3..7620eb127cff 100644 --- a/include/linux/pinctrl/pinconf-generic.h +++ b/include/linux/pinctrl/pinconf-generic.h @@ -42,8 +42,6 @@ * @PIN_CONFIG_BIAS_PULL_UP: the pin will be pulled up (usually with high * impedance to VDD). If the argument is != 0 pull-up is enabled, * if it is 0, pull-up is total, i.e. the pin is connected to VDD. - * @PIN_CONFIG_BIDIRECTIONAL: the pin will be configured to allow simultaneous - * input and output operations. * @PIN_CONFIG_DRIVE_OPEN_DRAIN: the pin will be driven with open drain (open * collector) which means it is usually wired with other output ports * which are then pulled up with an external resistor. Setting this @@ -98,7 +96,6 @@ enum pin_config_param { PIN_CONFIG_BIAS_PULL_DOWN, PIN_CONFIG_BIAS_PULL_PIN_DEFAULT, PIN_CONFIG_BIAS_PULL_UP, - PIN_CONFIG_BIDIRECTIONAL, PIN_CONFIG_DRIVE_OPEN_DRAIN, PIN_CONFIG_DRIVE_OPEN_SOURCE, PIN_CONFIG_DRIVE_PUSH_PULL, -- cgit v1.2.3 From 020e0b1c8f19f1fc3bce23beeccd80c574ca0e49 Mon Sep 17 00:00:00 2001 From: Anatolij Gustschin Date: Thu, 11 May 2017 20:24:31 +0200 Subject: gpiolib: Add stubs for gpiod lookup table interface Add stubs for gpiod_add_lookup_table() and gpiod_remove_lookup_table() for the !GPIOLIB case to prevent build errors. Signed-off-by: Anatolij Gustschin Reviewed-by: Andy Shevchenko Signed-off-by: Linus Walleij --- include/linux/gpio/machine.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/linux/gpio/machine.h b/include/linux/gpio/machine.h index c0d712d22b07..f738d50cc17d 100644 --- a/include/linux/gpio/machine.h +++ b/include/linux/gpio/machine.h @@ -56,7 +56,14 @@ struct gpiod_lookup_table { .flags = _flags, \ } +#ifdef CONFIG_GPIOLIB void gpiod_add_lookup_table(struct gpiod_lookup_table *table); void gpiod_remove_lookup_table(struct gpiod_lookup_table *table); +#else +static inline +void gpiod_add_lookup_table(struct gpiod_lookup_table *table) {} +static inline +void gpiod_remove_lookup_table(struct gpiod_lookup_table *table) {} +#endif #endif /* __LINUX_GPIO_MACHINE_H */ -- cgit v1.2.3 From 76dd1fbebbaebab294dc09230960238746b883b1 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 15 May 2017 09:31:41 +0200 Subject: HID: asus: Add support for T100 keyboard The keyboard dock used with the Asus Transformer T100 series, uses the same vendor-defined 0xff31 usage-page as some other Asus keyboards. But with a small twist, it has a small descriptor bug which needs to be fixed up for things to work. This commit adds the USB-ID for this keyboard to the hid-asus driver and makes asus_report_fixup fix the descriptor issue, fixing various special function keys on this keyboard not working. Signed-off-by: Hans de Goede Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-asus.c | 10 ++++++++++ drivers/hid/hid-core.c | 1 + drivers/hid/hid-ids.h | 1 + 3 files changed, 12 insertions(+) diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c index 16df6cc90235..101ab2e63d18 100644 --- a/drivers/hid/hid-asus.c +++ b/drivers/hid/hid-asus.c @@ -69,6 +69,7 @@ MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad"); #define QUIRK_IS_MULTITOUCH BIT(3) #define QUIRK_NO_CONSUMER_USAGES BIT(4) #define QUIRK_USE_KBD_BACKLIGHT BIT(5) +#define QUIRK_T100_KEYBOARD BIT(6) #define I2C_KEYBOARD_QUIRKS (QUIRK_FIX_NOTEBOOK_REPORT | \ QUIRK_NO_INIT_REPORTS | \ @@ -548,6 +549,12 @@ static __u8 *asus_report_fixup(struct hid_device *hdev, __u8 *rdesc, hid_info(hdev, "Fixing up Asus notebook report descriptor\n"); rdesc[55] = 0xdd; } + if (drvdata->quirks & QUIRK_T100_KEYBOARD && + *rsize == 76 && rdesc[73] == 0x81 && rdesc[74] == 0x01) { + hid_info(hdev, "Fixing up Asus T100 keyb report descriptor\n"); + rdesc[74] &= ~HID_MAIN_ITEM_CONSTANT; + } + return rdesc; } @@ -560,6 +567,9 @@ static const struct hid_device_id asus_devices[] = { USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD1) }, { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD2), QUIRK_USE_KBD_BACKLIGHT }, + { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, + USB_DEVICE_ID_ASUSTEK_T100_KEYBOARD), + QUIRK_T100_KEYBOARD | QUIRK_NO_CONSUMER_USAGES }, { } }; MODULE_DEVICE_TABLE(hid, asus_devices); diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 38d041510e1d..04cee65531d7 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1855,6 +1855,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_I2C_TOUCHPAD) }, { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD1) }, { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD2) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_T100_KEYBOARD) }, { HID_USB_DEVICE(USB_VENDOR_ID_AUREAL, USB_DEVICE_ID_AUREAL_W01RN) }, { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) }, { HID_USB_DEVICE(USB_VENDOR_ID_BETOP_2185BFM, 0x2208) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 8e8a1baee090..8ca1e8ce0af2 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -173,6 +173,7 @@ #define USB_VENDOR_ID_ASUSTEK 0x0b05 #define USB_DEVICE_ID_ASUSTEK_LCM 0x1726 #define USB_DEVICE_ID_ASUSTEK_LCM2 0x175b +#define USB_DEVICE_ID_ASUSTEK_T100_KEYBOARD 0x17e0 #define USB_DEVICE_ID_ASUSTEK_I2C_KEYBOARD 0x8585 #define USB_DEVICE_ID_ASUSTEK_I2C_TOUCHPAD 0x0101 #define USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD1 0x1854 -- cgit v1.2.3 From 664b7c4728821767e0228ee161bab87db2be58f1 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Fri, 12 May 2017 08:47:57 -0700 Subject: pinctrl: core: Fix warning by removing bogus code Andre Przywara noticed that we can get the following warning with -EPROBE_DEFER: "WARNING: CPU: 1 PID: 89 at drivers/base/dd.c:349 driver_probe_device+0x2ac/0x2e8" Let's fix the issue by removing the indices as suggested by Tejun Heo . All we have to do here is kill the radix tree. I probably ended up with the indices after grepping for removal of all entries using radix_tree_for_each_slot() and the first match found was gmap_radix_tree_free(). Anyways, no need for indices here, and we can just do remove all the entries using radix_tree_for_each_slot() along how the item_kill_tree() test case does. Fixes: c7059c5ac70a ("pinctrl: core: Add generic pinctrl functions for managing groups") Fixes: a76edc89b100 ("pinctrl: core: Add generic pinctrl functions for managing groups") Reported-by: Andre Przywara Signed-off-by: Tony Lindgren Reviewed-by: Andre Przywara Tested-by: Andre Przywara Signed-off-by: Linus Walleij --- drivers/pinctrl/core.c | 20 +++----------------- drivers/pinctrl/pinmux.c | 21 ++++----------------- 2 files changed, 7 insertions(+), 34 deletions(-) diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index 1653cbda6a82..bd459a93b0e7 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c @@ -680,30 +680,16 @@ EXPORT_SYMBOL_GPL(pinctrl_generic_remove_group); * pinctrl_generic_free_groups() - removes all pin groups * @pctldev: pin controller device * - * Note that the caller must take care of locking. + * Note that the caller must take care of locking. The pinctrl groups + * are allocated with devm_kzalloc() so no need to free them here. */ static void pinctrl_generic_free_groups(struct pinctrl_dev *pctldev) { struct radix_tree_iter iter; - struct group_desc *group; - unsigned long *indices; void **slot; - int i = 0; - - indices = devm_kzalloc(pctldev->dev, sizeof(*indices) * - pctldev->num_groups, GFP_KERNEL); - if (!indices) - return; radix_tree_for_each_slot(slot, &pctldev->pin_group_tree, &iter, 0) - indices[i++] = iter.index; - - for (i = 0; i < pctldev->num_groups; i++) { - group = radix_tree_lookup(&pctldev->pin_group_tree, - indices[i]); - radix_tree_delete(&pctldev->pin_group_tree, indices[i]); - devm_kfree(pctldev->dev, group); - } + radix_tree_delete(&pctldev->pin_group_tree, iter.index); pctldev->num_groups = 0; } diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c index 9fd6d9087dc5..16b3ae5e4f44 100644 --- a/drivers/pinctrl/pinmux.c +++ b/drivers/pinctrl/pinmux.c @@ -826,30 +826,17 @@ EXPORT_SYMBOL_GPL(pinmux_generic_remove_function); * pinmux_generic_free_functions() - removes all functions * @pctldev: pin controller device * - * Note that the caller must take care of locking. + * Note that the caller must take care of locking. The pinctrl + * functions are allocated with devm_kzalloc() so no need to free + * them here. */ void pinmux_generic_free_functions(struct pinctrl_dev *pctldev) { struct radix_tree_iter iter; - struct function_desc *function; - unsigned long *indices; void **slot; - int i = 0; - - indices = devm_kzalloc(pctldev->dev, sizeof(*indices) * - pctldev->num_functions, GFP_KERNEL); - if (!indices) - return; radix_tree_for_each_slot(slot, &pctldev->pin_function_tree, &iter, 0) - indices[i++] = iter.index; - - for (i = 0; i < pctldev->num_functions; i++) { - function = radix_tree_lookup(&pctldev->pin_function_tree, - indices[i]); - radix_tree_delete(&pctldev->pin_function_tree, indices[i]); - devm_kfree(pctldev->dev, function); - } + radix_tree_delete(&pctldev->pin_function_tree, iter.index); pctldev->num_functions = 0; } -- cgit v1.2.3 From f52236e0b0a0820e938e16a776309e76b7bd6c43 Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Thu, 18 May 2017 13:47:25 +0300 Subject: dm verity: fix no salt use case DM-Verity has an (undocumented) mode where no salt is used. This was never handled directly by the DM-Verity code, instead working due to the fact that calling crypto_shash_update() with a zero length data is an implicit noop. This is no longer the case now that we have switched to crypto_ahash_update(). Fix the issue by introducing explicit handling of the no salt use case to DM-Verity. Signed-off-by: Gilad Ben-Yossef Reported-by: Marian Csontos Fixes: d1ac3ff ("dm verity: switch to using asynchronous hash crypto API") Tested-by: Milan Broz Signed-off-by: Mike Snitzer --- drivers/md/dm-verity-target.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/md/dm-verity-target.c b/drivers/md/dm-verity-target.c index 97de961a3bfc..1ec9b2c51c07 100644 --- a/drivers/md/dm-verity-target.c +++ b/drivers/md/dm-verity-target.c @@ -166,7 +166,7 @@ static int verity_hash_init(struct dm_verity *v, struct ahash_request *req, return r; } - if (likely(v->version >= 1)) + if (likely(v->salt_size && (v->version >= 1))) r = verity_hash_update(v, req, v->salt, v->salt_size, res); return r; @@ -177,7 +177,7 @@ static int verity_hash_final(struct dm_verity *v, struct ahash_request *req, { int r; - if (unlikely(!v->version)) { + if (unlikely(v->salt_size && (!v->version))) { r = verity_hash_update(v, req, v->salt, v->salt_size, res); if (r < 0) { -- cgit v1.2.3 From 702a6204f804bad946c455e7cd8d50d79c9d1629 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Sat, 20 May 2017 14:56:21 -0400 Subject: dm integrity: use kvmalloc() instead of dm_integrity_kvmalloc() Signed-off-by: Mikulas Patocka Signed-off-by: Mike Snitzer --- drivers/md/dm-integrity.c | 27 ++++++--------------------- 1 file changed, 6 insertions(+), 21 deletions(-) diff --git a/drivers/md/dm-integrity.c b/drivers/md/dm-integrity.c index c7f7c8d76576..1feeb2ccf5a1 100644 --- a/drivers/md/dm-integrity.c +++ b/drivers/md/dm-integrity.c @@ -2374,21 +2374,6 @@ static void dm_integrity_set(struct dm_target *ti, struct dm_integrity_c *ic) blk_queue_max_integrity_segments(disk->queue, UINT_MAX); } -/* FIXME: use new kvmalloc */ -static void *dm_integrity_kvmalloc(size_t size, gfp_t gfp) -{ - void *ptr = NULL; - - if (size <= PAGE_SIZE) - ptr = kmalloc(size, GFP_KERNEL | gfp); - if (!ptr && size <= KMALLOC_MAX_SIZE) - ptr = kmalloc(size, GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY | gfp); - if (!ptr) - ptr = __vmalloc(size, GFP_KERNEL | gfp, PAGE_KERNEL); - - return ptr; -} - static void dm_integrity_free_page_list(struct dm_integrity_c *ic, struct page_list *pl) { unsigned i; @@ -2407,7 +2392,7 @@ static struct page_list *dm_integrity_alloc_page_list(struct dm_integrity_c *ic) struct page_list *pl; unsigned i; - pl = dm_integrity_kvmalloc(page_list_desc_size, __GFP_ZERO); + pl = kvmalloc(page_list_desc_size, GFP_KERNEL | __GFP_ZERO); if (!pl) return NULL; @@ -2437,7 +2422,7 @@ static struct scatterlist **dm_integrity_alloc_journal_scatterlist(struct dm_int struct scatterlist **sl; unsigned i; - sl = dm_integrity_kvmalloc(ic->journal_sections * sizeof(struct scatterlist *), __GFP_ZERO); + sl = kvmalloc(ic->journal_sections * sizeof(struct scatterlist *), GFP_KERNEL | __GFP_ZERO); if (!sl) return NULL; @@ -2453,7 +2438,7 @@ static struct scatterlist **dm_integrity_alloc_journal_scatterlist(struct dm_int n_pages = (end_index - start_index + 1); - s = dm_integrity_kvmalloc(n_pages * sizeof(struct scatterlist), 0); + s = kvmalloc(n_pages * sizeof(struct scatterlist), GFP_KERNEL); if (!s) { dm_integrity_free_journal_scatterlist(ic, sl); return NULL; @@ -2617,7 +2602,7 @@ static int create_journal(struct dm_integrity_c *ic, char **error) goto bad; } - sg = dm_integrity_kvmalloc((ic->journal_pages + 1) * sizeof(struct scatterlist), 0); + sg = kvmalloc((ic->journal_pages + 1) * sizeof(struct scatterlist), GFP_KERNEL); if (!sg) { *error = "Unable to allocate sg list"; r = -ENOMEM; @@ -2673,7 +2658,7 @@ static int create_journal(struct dm_integrity_c *ic, char **error) r = -ENOMEM; goto bad; } - ic->sk_requests = dm_integrity_kvmalloc(ic->journal_sections * sizeof(struct skcipher_request *), __GFP_ZERO); + ic->sk_requests = kvmalloc(ic->journal_sections * sizeof(struct skcipher_request *), GFP_KERNEL | __GFP_ZERO); if (!ic->sk_requests) { *error = "Unable to allocate sk requests"; r = -ENOMEM; @@ -2740,7 +2725,7 @@ retest_commit_id: r = -ENOMEM; goto bad; } - ic->journal_tree = dm_integrity_kvmalloc(journal_tree_size, 0); + ic->journal_tree = kvmalloc(journal_tree_size, GFP_KERNEL); if (!ic->journal_tree) { *error = "Could not allocate memory for journal tree"; r = -ENOMEM; -- cgit v1.2.3 From aace34c0bb8ea3c8bdcec865b6a4be4db0a68e33 Mon Sep 17 00:00:00 2001 From: Tin Huynh Date: Mon, 22 May 2017 16:19:20 +0700 Subject: leds: pca955x: Correct I2C Functionality The driver checks an incorrect flag of functionality of adapter. When a driver requires i2c_smbus_read_byte_data and i2c_smbus_write_byte_data, it should check I2C_FUNC_SMBUS_BYTE_DATA instead I2C_FUNC_I2C. This patch fixes the problem. Signed-off-by: Tin Huynh Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-pca955x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/leds/leds-pca955x.c b/drivers/leds/leds-pca955x.c index 78a7ce816a47..9a873118ea5f 100644 --- a/drivers/leds/leds-pca955x.c +++ b/drivers/leds/leds-pca955x.c @@ -285,7 +285,7 @@ static int pca955x_probe(struct i2c_client *client, "slave address 0x%02x\n", client->name, chip->bits, client->addr); - if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -EIO; if (pdata) { -- cgit v1.2.3 From 04dc1b2fff4e96cb4142227fbdc63c8871ad4ed9 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Fri, 19 May 2017 17:48:50 +0200 Subject: futex,rt_mutex: Fix rt_mutex_cleanup_proxy_lock() Markus reported that the glibc/nptl/tst-robustpi8 test was failing after commit: cfafcd117da0 ("futex: Rework futex_lock_pi() to use rt_mutex_*_proxy_lock()") The following trace shows the problem: ld-linux-x86-64-2161 [019] .... 410.760971: SyS_futex: 00007ffbeb76b028: 80000875 op=FUTEX_LOCK_PI ld-linux-x86-64-2161 [019] ...1 410.760972: lock_pi_update_atomic: 00007ffbeb76b028: curval=80000875 uval=80000875 newval=80000875 ret=0 ld-linux-x86-64-2165 [011] .... 410.760978: SyS_futex: 00007ffbeb76b028: 80000875 op=FUTEX_UNLOCK_PI ld-linux-x86-64-2165 [011] d..1 410.760979: do_futex: 00007ffbeb76b028: curval=80000875 uval=80000875 newval=80000871 ret=0 ld-linux-x86-64-2165 [011] .... 410.760980: SyS_futex: 00007ffbeb76b028: 80000871 ret=0000 ld-linux-x86-64-2161 [019] .... 410.760980: SyS_futex: 00007ffbeb76b028: 80000871 ret=ETIMEDOUT Task 2165 does an UNLOCK_PI, assigning the lock to the waiter task 2161 which then returns with -ETIMEDOUT. That wrecks the lock state, because now the owner isn't aware it acquired the lock and removes the pending robust list entry. If 2161 is killed, the robust list will not clear out this futex and the subsequent acquire on this futex will then (correctly) result in -ESRCH which is unexpected by glibc, triggers an internal assertion and dies. Task 2161 Task 2165 rt_mutex_wait_proxy_lock() timeout(); /* T2161 is still queued in the waiter list */ return -ETIMEDOUT; futex_unlock_pi() spin_lock(hb->lock); rtmutex_unlock() remove_rtmutex_waiter(T2161); mark_lock_available(); /* Make the next waiter owner of the user space side */ futex_uval = 2161; spin_unlock(hb->lock); spin_lock(hb->lock); rt_mutex_cleanup_proxy_lock() if (rtmutex_owner() !== current) ... return FAIL; .... return -ETIMEOUT; This means that rt_mutex_cleanup_proxy_lock() needs to call try_to_take_rt_mutex() so it can take over the rtmutex correctly which was assigned by the waker. If the rtmutex is owned by some other task then this call is harmless and just confirmes that the waiter is not able to acquire it. While there, fix what looks like a merge error which resulted in rt_mutex_cleanup_proxy_lock() having two calls to fixup_rt_mutex_waiters() and rt_mutex_wait_proxy_lock() not having any. Both should have one, since both potentially touch the waiter list. Fixes: 38d589f2fd08 ("futex,rt_mutex: Restructure rt_mutex_finish_proxy_lock()") Reported-by: Markus Trippelsdorf Bug-Spotted-by: Thomas Gleixner Signed-off-by: Peter Zijlstra (Intel) Cc: Florian Weimer Cc: Darren Hart Cc: Sebastian Andrzej Siewior Cc: Markus Trippelsdorf Link: http://lkml.kernel.org/r/20170519154850.mlomgdsd26drq5j6@hirez.programming.kicks-ass.net Signed-off-by: Thomas Gleixner --- kernel/locking/rtmutex.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/kernel/locking/rtmutex.c b/kernel/locking/rtmutex.c index b95509416909..28cd09e635ed 100644 --- a/kernel/locking/rtmutex.c +++ b/kernel/locking/rtmutex.c @@ -1785,12 +1785,14 @@ int rt_mutex_wait_proxy_lock(struct rt_mutex *lock, int ret; raw_spin_lock_irq(&lock->wait_lock); - - set_current_state(TASK_INTERRUPTIBLE); - /* sleep on the mutex */ + set_current_state(TASK_INTERRUPTIBLE); ret = __rt_mutex_slowlock(lock, TASK_INTERRUPTIBLE, to, waiter); - + /* + * try_to_take_rt_mutex() sets the waiter bit unconditionally. We might + * have to fix that up. + */ + fixup_rt_mutex_waiters(lock); raw_spin_unlock_irq(&lock->wait_lock); return ret; @@ -1821,16 +1823,26 @@ bool rt_mutex_cleanup_proxy_lock(struct rt_mutex *lock, bool cleanup = false; raw_spin_lock_irq(&lock->wait_lock); + /* + * Do an unconditional try-lock, this deals with the lock stealing + * state where __rt_mutex_futex_unlock() -> mark_wakeup_next_waiter() + * sets a NULL owner. + * + * We're not interested in the return value, because the subsequent + * test on rt_mutex_owner() will infer that. If the trylock succeeded, + * we will own the lock and it will have removed the waiter. If we + * failed the trylock, we're still not owner and we need to remove + * ourselves. + */ + try_to_take_rt_mutex(lock, current, waiter); /* * Unless we're the owner; we're still enqueued on the wait_list. * So check if we became owner, if not, take us off the wait_list. */ if (rt_mutex_owner(lock) != current) { remove_waiter(lock, waiter); - fixup_rt_mutex_waiters(lock); cleanup = true; } - /* * try_to_take_rt_mutex() sets the waiter bit unconditionally. We might * have to fix that up. -- cgit v1.2.3 From 4d6501dce079c1eb6bf0b1d8f528a5e81770109e Mon Sep 17 00:00:00 2001 From: Vegard Nossum Date: Tue, 9 May 2017 09:39:59 +0200 Subject: kthread: Fix use-after-free if kthread fork fails If a kthread forks (e.g. usermodehelper since commit 1da5c46fa965) but fails in copy_process() between calling dup_task_struct() and setting p->set_child_tid, then the value of p->set_child_tid will be inherited from the parent and get prematurely freed by free_kthread_struct(). kthread() - worker_thread() - process_one_work() | - call_usermodehelper_exec_work() | - kernel_thread() | - _do_fork() | - copy_process() | - dup_task_struct() | - arch_dup_task_struct() | - tsk->set_child_tid = current->set_child_tid // implied | - ... | - goto bad_fork_* | - ... | - free_task(tsk) | - free_kthread_struct(tsk) | - kfree(tsk->set_child_tid) - ... - schedule() - __schedule() - wq_worker_sleeping() - kthread_data(task)->flags // UAF The problem started showing up with commit 1da5c46fa965 since it reused ->set_child_tid for the kthread worker data. A better long-term solution might be to get rid of the ->set_child_tid abuse. The comment in set_kthread_struct() also looks slightly wrong. Debugged-by: Jamie Iles Fixes: 1da5c46fa965 ("kthread: Make struct kthread kmalloc'ed") Signed-off-by: Vegard Nossum Acked-by: Oleg Nesterov Cc: Peter Zijlstra Cc: Greg Kroah-Hartman Cc: Andy Lutomirski Cc: Frederic Weisbecker Cc: Jamie Iles Cc: stable@vger.kernel.org Link: http://lkml.kernel.org/r/20170509073959.17858-1-vegard.nossum@oracle.com Signed-off-by: Thomas Gleixner --- kernel/fork.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/kernel/fork.c b/kernel/fork.c index d681f8f10d2d..b7cdea10239c 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1553,6 +1553,18 @@ static __latent_entropy struct task_struct *copy_process( if (!p) goto fork_out; + /* + * This _must_ happen before we call free_task(), i.e. before we jump + * to any of the bad_fork_* labels. This is to avoid freeing + * p->set_child_tid which is (ab)used as a kthread's data pointer for + * kernel threads (PF_KTHREAD). + */ + p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL; + /* + * Clear TID on mm_release()? + */ + p->clear_child_tid = (clone_flags & CLONE_CHILD_CLEARTID) ? child_tidptr : NULL; + ftrace_graph_init_task(p); rt_mutex_init_task(p); @@ -1716,11 +1728,6 @@ static __latent_entropy struct task_struct *copy_process( } } - p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL; - /* - * Clear TID on mm_release()? - */ - p->clear_child_tid = (clone_flags & CLONE_CHILD_CLEARTID) ? child_tidptr : NULL; #ifdef CONFIG_BLOCK p->plug = NULL; #endif -- cgit v1.2.3 From 8c1e2162f27b319da913683143c0c6c09b083ebb Mon Sep 17 00:00:00 2001 From: Junaid Shahid Date: Thu, 18 May 2017 12:00:51 -0700 Subject: dm ioctl: restore __GFP_HIGH in copy_params() Commit d224e9381897 ("drivers/md/dm-ioctl.c: use kvmalloc rather than opencoded variant") left out the __GFP_HIGH flag when converting from __vmalloc to kvmalloc. This can cause the DM ioctl to fail in some low memory situations where it wouldn't have failed earlier. Add __GFP_HIGH back to avoid any potential regression. Fixes: d224e9381897 ("drivers/md/dm-ioctl.c: use kvmalloc rather than opencoded variant") Signed-off-by: Junaid Shahid Signed-off-by: Mikulas Patocka Acked-by: David Rientjes Signed-off-by: Mike Snitzer --- drivers/md/dm-ioctl.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index 0555b4410e05..41852ae287a5 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -1710,12 +1710,13 @@ static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl *param_kern } /* - * Try to avoid low memory issues when a device is suspended. + * Use __GFP_HIGH to avoid low memory issues when a device is + * suspended and the ioctl is needed to resume it. * Use kmalloc() rather than vmalloc() when we can. */ dmi = NULL; noio_flag = memalloc_noio_save(); - dmi = kvmalloc(param_kernel->data_size, GFP_KERNEL); + dmi = kvmalloc(param_kernel->data_size, GFP_KERNEL | __GFP_HIGH); memalloc_noio_restore(noio_flag); if (!dmi) { -- cgit v1.2.3 From aa3d4409b664813ceb86a24bd09458cdd29cbb8a Mon Sep 17 00:00:00 2001 From: Martin Kepplinger Date: Mon, 22 May 2017 17:19:45 -0700 Subject: Input: edt-ft5x06 - increase allowed data range for threshold parameter The datasheet and application note does not mention an allowed range for the M09_REGISTER_THRESHOLD parameter. One of our customers needs to set lower values than 20 and they seem to work just fine on EDT EP0xx0M09 with T5x06 touch. So, lacking a known lower limit, we increase the range for thresholds, and set the lower limit to 0. The documentation is updated accordingly. Signed-off-by: Schoefegger Stefan Signed-off-by: Manfred Schlaegl Signed-off-by: Martin Kepplinger Acked-by: Rob Herring Signed-off-by: Dmitry Torokhov --- Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.txt | 2 +- Documentation/input/devices/edt-ft5x06.rst | 2 +- drivers/input/touchscreen/edt-ft5x06.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.txt b/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.txt index 6db22103e2dd..025cf8c9324a 100644 --- a/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.txt +++ b/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.txt @@ -36,7 +36,7 @@ Optional properties: control gpios - threshold: allows setting the "click"-threshold in the range - from 20 to 80. + from 0 to 80. - gain: allows setting the sensitivity in the range from 0 to 31. Note that lower values indicate higher diff --git a/Documentation/input/devices/edt-ft5x06.rst b/Documentation/input/devices/edt-ft5x06.rst index 2032f0b7a8fa..1ccc94b192b7 100644 --- a/Documentation/input/devices/edt-ft5x06.rst +++ b/Documentation/input/devices/edt-ft5x06.rst @@ -15,7 +15,7 @@ It has been tested with the following devices: The driver allows configuration of the touch screen via a set of sysfs files: /sys/class/input/eventX/device/device/threshold: - allows setting the "click"-threshold in the range from 20 to 80. + allows setting the "click"-threshold in the range from 0 to 80. /sys/class/input/eventX/device/device/gain: allows setting the sensitivity in the range from 0 to 31. Note that diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index 8cf8d8d5d4ef..f872817e81e4 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c @@ -471,7 +471,7 @@ static EDT_ATTR(gain, S_IWUSR | S_IRUGO, WORK_REGISTER_GAIN, static EDT_ATTR(offset, S_IWUSR | S_IRUGO, WORK_REGISTER_OFFSET, M09_REGISTER_OFFSET, 0, 31); static EDT_ATTR(threshold, S_IWUSR | S_IRUGO, WORK_REGISTER_THRESHOLD, - M09_REGISTER_THRESHOLD, 20, 80); + M09_REGISTER_THRESHOLD, 0, 80); static EDT_ATTR(report_rate, S_IWUSR | S_IRUGO, WORK_REGISTER_REPORT_RATE, NO_REGISTER, 3, 14); -- cgit v1.2.3 From 089b50d95948f691589cca4d81f1f8761747dbaa Mon Sep 17 00:00:00 2001 From: Maxime Roussin-Bélanger Date: Fri, 19 May 2017 14:59:03 -0700 Subject: Input: atmel_mxt_ts - add T100 as a readable object MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When using the 'object' sysfs attribute, T100 is not displayed in the output. Signed-off-by: Maxime Roussin-Bélanger Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/atmel_mxt_ts.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 2302aef2b2d4..dd042a9b0aaa 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -350,6 +350,7 @@ static bool mxt_object_readable(unsigned int type) case MXT_TOUCH_KEYARRAY_T15: case MXT_TOUCH_PROXIMITY_T23: case MXT_TOUCH_PROXKEY_T52: + case MXT_TOUCH_MULTITOUCHSCREEN_T100: case MXT_PROCI_GRIPFACE_T20: case MXT_PROCG_NOISE_T22: case MXT_PROCI_ONETOUCH_T24: -- cgit v1.2.3 From 0340ff83cd4475261e7474033a381bc125b45244 Mon Sep 17 00:00:00 2001 From: Michael Thalmeier Date: Thu, 18 May 2017 16:14:14 +0200 Subject: usb: chipidea: debug: check before accessing ci_role ci_role BUGs when the role is >= CI_ROLE_END. Cc: stable@vger.kernel.org #v3.10+ Signed-off-by: Michael Thalmeier Signed-off-by: Peter Chen --- drivers/usb/chipidea/debug.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/chipidea/debug.c b/drivers/usb/chipidea/debug.c index 6d23eede4d8c..1c31e8a08810 100644 --- a/drivers/usb/chipidea/debug.c +++ b/drivers/usb/chipidea/debug.c @@ -294,7 +294,8 @@ static int ci_role_show(struct seq_file *s, void *data) { struct ci_hdrc *ci = s->private; - seq_printf(s, "%s\n", ci_role(ci)->name); + if (ci->role != CI_ROLE_END) + seq_printf(s, "%s\n", ci_role(ci)->name); return 0; } -- cgit v1.2.3 From cbb22ebcfb9920380ed69854a7095d497798063d Mon Sep 17 00:00:00 2001 From: Michael Thalmeier Date: Fri, 19 May 2017 10:32:09 +0200 Subject: usb: chipidea: core: check before accessing ci_role in ci_role_show ci_role BUGs when the role is >= CI_ROLE_END. This is the case while the role is changing. Signed-off-by: Michael Thalmeier Signed-off-by: Peter Chen --- drivers/usb/chipidea/core.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index 9e217b1361ea..fe4fe2440729 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c @@ -843,7 +843,10 @@ static ssize_t ci_role_show(struct device *dev, struct device_attribute *attr, { struct ci_hdrc *ci = dev_get_drvdata(dev); - return sprintf(buf, "%s\n", ci_role(ci)->name); + if (ci->role != CI_ROLE_END) + return sprintf(buf, "%s\n", ci_role(ci)->name); + + return 0; } static ssize_t ci_role_store(struct device *dev, -- cgit v1.2.3 From e68368aed56324e2e38d4f6b044bb8cf82077fc2 Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Thu, 18 May 2017 16:29:23 +0300 Subject: crypto: asymmetric_keys - handle EBUSY due to backlog correctly public_key_verify_signature() was passing the CRYPTO_TFM_REQ_MAY_BACKLOG flag to akcipher_request_set_callback() but was not handling correctly the case where a -EBUSY error could be returned from the call to crypto_akcipher_verify() if backlog was used, possibly casuing data corruption due to use-after-free of buffers. Resolve this by handling -EBUSY correctly. Signed-off-by: Gilad Ben-Yossef CC: stable@vger.kernel.org Signed-off-by: Herbert Xu --- crypto/asymmetric_keys/public_key.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c index d3a989e718f5..3cd6e12cfc46 100644 --- a/crypto/asymmetric_keys/public_key.c +++ b/crypto/asymmetric_keys/public_key.c @@ -141,7 +141,7 @@ int public_key_verify_signature(const struct public_key *pkey, * signature and returns that to us. */ ret = crypto_akcipher_verify(req); - if (ret == -EINPROGRESS) { + if ((ret == -EINPROGRESS) || (ret == -EBUSY)) { wait_for_completion(&compl.completion); ret = compl.err; } -- cgit v1.2.3 From a5dfefb1c3f3db81662556393fd9283511e08430 Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Thu, 18 May 2017 16:29:24 +0300 Subject: crypto: drbg - wait for crypto op not signal safe drbg_kcapi_sym_ctr() was using wait_for_completion_interruptible() to wait for completion of async crypto op but if a signal occurs it may return before DMA ops of HW crypto provider finish, thus corrupting the output buffer. Resolve this by using wait_for_completion() instead. Reported-by: Eric Biggers Signed-off-by: Gilad Ben-Yossef CC: stable@vger.kernel.org Signed-off-by: Herbert Xu --- crypto/drbg.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/crypto/drbg.c b/crypto/drbg.c index fa749f470135..cdb27ac4b226 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -1767,9 +1767,8 @@ static int drbg_kcapi_sym_ctr(struct drbg_state *drbg, break; case -EINPROGRESS: case -EBUSY: - ret = wait_for_completion_interruptible( - &drbg->ctr_completion); - if (!ret && !drbg->ctr_async_err) { + wait_for_completion(&drbg->ctr_completion); + if (!drbg->ctr_async_err) { reinit_completion(&drbg->ctr_completion); break; } -- cgit v1.2.3 From f3ad587070d6bd961ab942b3fd7a85d00dfc934b Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Thu, 18 May 2017 16:29:25 +0300 Subject: crypto: gcm - wait for crypto op not signal safe crypto_gcm_setkey() was using wait_for_completion_interruptible() to wait for completion of async crypto op but if a signal occurs it may return before DMA ops of HW crypto provider finish, thus corrupting the data buffer that is kfree'ed in this case. Resolve this by using wait_for_completion() instead. Reported-by: Eric Biggers Signed-off-by: Gilad Ben-Yossef CC: stable@vger.kernel.org Signed-off-by: Herbert Xu --- crypto/gcm.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/crypto/gcm.c b/crypto/gcm.c index b7ad808be3d4..3841b5eafa7e 100644 --- a/crypto/gcm.c +++ b/crypto/gcm.c @@ -152,10 +152,8 @@ static int crypto_gcm_setkey(struct crypto_aead *aead, const u8 *key, err = crypto_skcipher_encrypt(&data->req); if (err == -EINPROGRESS || err == -EBUSY) { - err = wait_for_completion_interruptible( - &data->result.completion); - if (!err) - err = data->result.err; + wait_for_completion(&data->result.completion); + err = data->result.err; } if (err) -- cgit v1.2.3 From 1999f108c983a7287a847b09e29dac25b9301dee Mon Sep 17 00:00:00 2001 From: Chuanxiao Dong Date: Wed, 17 May 2017 15:49:01 +0800 Subject: drm/i915/gvt: Disable compression workaround for Gen9 With enabling this workaround, can observe GPU hang issue on Gen9. As currently host side doesn't have this workaround, disable it from GVT side. v2: - Fix indent error.(Zhenyu) Cc: Zhenyu Wang Signed-off-by: Chuanxiao Dong Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/handlers.c | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index c995e540ff96..0ffd69654592 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -1366,18 +1366,28 @@ static int skl_misc_ctl_write(struct intel_vgpu *vgpu, unsigned int offset, void *p_data, unsigned int bytes) { struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; - i915_reg_t reg = {.reg = offset}; + u32 v = *(u32 *)p_data; + + if (!IS_SKYLAKE(dev_priv) && !IS_KABYLAKE(dev_priv)) + return intel_vgpu_default_mmio_write(vgpu, + offset, p_data, bytes); switch (offset) { case 0x4ddc: - vgpu_vreg(vgpu, offset) = 0x8000003c; - /* WaCompressedResourceSamplerPbeMediaNewHashMode:skl */ - I915_WRITE(reg, vgpu_vreg(vgpu, offset)); + /* bypass WaCompressedResourceSamplerPbeMediaNewHashMode */ + vgpu_vreg(vgpu, offset) = v & ~(1 << 31); break; case 0x42080: - vgpu_vreg(vgpu, offset) = 0x8000; - /* WaCompressedResourceDisplayNewHashMode:skl */ - I915_WRITE(reg, vgpu_vreg(vgpu, offset)); + /* bypass WaCompressedResourceDisplayNewHashMode */ + vgpu_vreg(vgpu, offset) = v & ~(1 << 15); + break; + case 0xe194: + /* bypass WaCompressedResourceSamplerPbeMediaNewHashMode */ + vgpu_vreg(vgpu, offset) = v & ~(1 << 8); + break; + case 0x7014: + /* bypass WaCompressedResourceSamplerPbeMediaNewHashMode */ + vgpu_vreg(vgpu, offset) = v & ~(1 << 13); break; default: return -EINVAL; @@ -1634,7 +1644,8 @@ static int init_generic_mmio_info(struct intel_gvt *gvt) MMIO_DFH(GAM_ECOCHK, D_ALL, F_CMD_ACCESS, NULL, NULL); MMIO_DFH(GEN7_COMMON_SLICE_CHICKEN1, D_ALL, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL); - MMIO_DFH(COMMON_SLICE_CHICKEN2, D_ALL, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL); + MMIO_DFH(COMMON_SLICE_CHICKEN2, D_ALL, F_MODE_MASK | F_CMD_ACCESS, NULL, + skl_misc_ctl_write); MMIO_DFH(0x9030, D_ALL, F_CMD_ACCESS, NULL, NULL); MMIO_DFH(0x20a0, D_ALL, F_CMD_ACCESS, NULL, NULL); MMIO_DFH(0x2420, D_ALL, F_CMD_ACCESS, NULL, NULL); @@ -2568,7 +2579,8 @@ static int init_broadwell_mmio_info(struct intel_gvt *gvt) MMIO_D(0x6e570, D_BDW_PLUS); MMIO_D(0x65f10, D_BDW_PLUS); - MMIO_DFH(0xe194, D_BDW_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL); + MMIO_DFH(0xe194, D_BDW_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL, + skl_misc_ctl_write); MMIO_DFH(0xe188, D_BDW_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL); MMIO_DFH(HALF_SLICE_CHICKEN2, D_BDW_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL); MMIO_DFH(0x2580, D_BDW_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL); -- cgit v1.2.3 From 9a752b4c9ab924033bfdb8784c680d50b2bd5684 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 13 May 2017 14:39:53 +0200 Subject: gpio: crystalcove: Do not write regular gpio registers for virtual GPIOs The Crystal Cove PMIC has 16 real GPIOs but the ACPI code for devices with this PMIC may address up to 95 GPIOs, these extra GPIOs are called virtual GPIOs and are used by the ACPI code as a method of accessing various non GPIO bits of PMIC. Commit dcdc3018d635 ("gpio: crystalcove: support virtual GPIO") added dummy support for these to avoid a bunch of ACPI errors, but instead of ignoring writes / reads to them by doing: if (gpio >= CRYSTALCOVE_GPIO_NUM) return 0; It accidentally introduced the following wrong check: if (gpio > CRYSTALCOVE_VGPIO_NUM) return 0; Which means that attempts by the ACPI code to access these gpios causes some arbitrary gpio to get touched through for example GPIO1P0CTLO + gpionr % 8. Since we do support input/output (but not interrupts) on the 0x5e virtual GPIO, this commit makes to_reg return -ENOTSUPP for unsupported virtual GPIOs so as to not have to check for (gpio >= CRYSTALCOVE_GPIO_NUM && gpio != 0x5e) everywhere and to make it easier to add support for more virtual GPIOs in the future. It then adds a check for to_reg returning an error to all callers where this may happen fixing the ACPI code accessing virtual GPIOs accidentally causing changes to real GPIOs. Fixes: dcdc3018d635 ("gpio: crystalcove: support virtual GPIO") Cc: Aaron Lu Signed-off-by: Hans de Goede Reviewed-by: Andy Shevchenko Signed-off-by: Linus Walleij --- drivers/gpio/gpio-crystalcove.c | 54 +++++++++++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 18 deletions(-) diff --git a/drivers/gpio/gpio-crystalcove.c b/drivers/gpio/gpio-crystalcove.c index 2197368cc899..e60156ec0c18 100644 --- a/drivers/gpio/gpio-crystalcove.c +++ b/drivers/gpio/gpio-crystalcove.c @@ -90,8 +90,18 @@ static inline int to_reg(int gpio, enum ctrl_register reg_type) { int reg; - if (gpio == 94) - return GPIOPANELCTL; + if (gpio >= CRYSTALCOVE_GPIO_NUM) { + /* + * Virtual GPIO called from ACPI, for now we only support + * the panel ctl. + */ + switch (gpio) { + case 0x5e: + return GPIOPANELCTL; + default: + return -EOPNOTSUPP; + } + } if (reg_type == CTRL_IN) { if (gpio < 8) @@ -130,36 +140,36 @@ static void crystalcove_update_irq_ctrl(struct crystalcove_gpio *cg, int gpio) static int crystalcove_gpio_dir_in(struct gpio_chip *chip, unsigned gpio) { struct crystalcove_gpio *cg = gpiochip_get_data(chip); + int reg = to_reg(gpio, CTRL_OUT); - if (gpio > CRYSTALCOVE_VGPIO_NUM) + if (reg < 0) return 0; - return regmap_write(cg->regmap, to_reg(gpio, CTRL_OUT), - CTLO_INPUT_SET); + return regmap_write(cg->regmap, reg, CTLO_INPUT_SET); } static int crystalcove_gpio_dir_out(struct gpio_chip *chip, unsigned gpio, int value) { struct crystalcove_gpio *cg = gpiochip_get_data(chip); + int reg = to_reg(gpio, CTRL_OUT); - if (gpio > CRYSTALCOVE_VGPIO_NUM) + if (reg < 0) return 0; - return regmap_write(cg->regmap, to_reg(gpio, CTRL_OUT), - CTLO_OUTPUT_SET | value); + return regmap_write(cg->regmap, reg, CTLO_OUTPUT_SET | value); } static int crystalcove_gpio_get(struct gpio_chip *chip, unsigned gpio) { struct crystalcove_gpio *cg = gpiochip_get_data(chip); - int ret; unsigned int val; + int ret, reg = to_reg(gpio, CTRL_IN); - if (gpio > CRYSTALCOVE_VGPIO_NUM) + if (reg < 0) return 0; - ret = regmap_read(cg->regmap, to_reg(gpio, CTRL_IN), &val); + ret = regmap_read(cg->regmap, reg, &val); if (ret) return ret; @@ -170,14 +180,15 @@ static void crystalcove_gpio_set(struct gpio_chip *chip, unsigned gpio, int value) { struct crystalcove_gpio *cg = gpiochip_get_data(chip); + int reg = to_reg(gpio, CTRL_OUT); - if (gpio > CRYSTALCOVE_VGPIO_NUM) + if (reg < 0) return; if (value) - regmap_update_bits(cg->regmap, to_reg(gpio, CTRL_OUT), 1, 1); + regmap_update_bits(cg->regmap, reg, 1, 1); else - regmap_update_bits(cg->regmap, to_reg(gpio, CTRL_OUT), 1, 0); + regmap_update_bits(cg->regmap, reg, 1, 0); } static int crystalcove_irq_type(struct irq_data *data, unsigned type) @@ -185,6 +196,9 @@ static int crystalcove_irq_type(struct irq_data *data, unsigned type) struct crystalcove_gpio *cg = gpiochip_get_data(irq_data_get_irq_chip_data(data)); + if (data->hwirq >= CRYSTALCOVE_GPIO_NUM) + return 0; + switch (type) { case IRQ_TYPE_NONE: cg->intcnt_value = CTLI_INTCNT_DIS; @@ -235,8 +249,10 @@ static void crystalcove_irq_unmask(struct irq_data *data) struct crystalcove_gpio *cg = gpiochip_get_data(irq_data_get_irq_chip_data(data)); - cg->set_irq_mask = false; - cg->update |= UPDATE_IRQ_MASK; + if (data->hwirq < CRYSTALCOVE_GPIO_NUM) { + cg->set_irq_mask = false; + cg->update |= UPDATE_IRQ_MASK; + } } static void crystalcove_irq_mask(struct irq_data *data) @@ -244,8 +260,10 @@ static void crystalcove_irq_mask(struct irq_data *data) struct crystalcove_gpio *cg = gpiochip_get_data(irq_data_get_irq_chip_data(data)); - cg->set_irq_mask = true; - cg->update |= UPDATE_IRQ_MASK; + if (data->hwirq < CRYSTALCOVE_GPIO_NUM) { + cg->set_irq_mask = true; + cg->update |= UPDATE_IRQ_MASK; + } } static struct irq_chip crystalcove_irqchip = { -- cgit v1.2.3 From c61872c9833d17d3807fb999096917c1f9eaada0 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Wed, 17 May 2017 13:25:12 +0300 Subject: firmware: dmi: Add DMI_PRODUCT_FAMILY identification string Sometimes it is more convenient to be able to match a whole family of products, like in case of bunch of Chromebooks based on Intel_Strago to apply a driver quirk instead of quirking each machine one-by-one. This adds support for DMI_PRODUCT_FAMILY identification string and also exports it to the userspace through sysfs attribute just like the existing ones. Suggested-by: Dmitry Torokhov Signed-off-by: Mika Westerberg Reviewed-by: Andy Shevchenko Signed-off-by: Linus Walleij --- drivers/firmware/dmi-id.c | 2 ++ drivers/firmware/dmi_scan.c | 1 + include/linux/mod_devicetable.h | 1 + 3 files changed, 4 insertions(+) diff --git a/drivers/firmware/dmi-id.c b/drivers/firmware/dmi-id.c index 44c01390d035..dc269cb288c2 100644 --- a/drivers/firmware/dmi-id.c +++ b/drivers/firmware/dmi-id.c @@ -47,6 +47,7 @@ DEFINE_DMI_ATTR_WITH_SHOW(product_name, 0444, DMI_PRODUCT_NAME); DEFINE_DMI_ATTR_WITH_SHOW(product_version, 0444, DMI_PRODUCT_VERSION); DEFINE_DMI_ATTR_WITH_SHOW(product_serial, 0400, DMI_PRODUCT_SERIAL); DEFINE_DMI_ATTR_WITH_SHOW(product_uuid, 0400, DMI_PRODUCT_UUID); +DEFINE_DMI_ATTR_WITH_SHOW(product_family, 0400, DMI_PRODUCT_FAMILY); DEFINE_DMI_ATTR_WITH_SHOW(board_vendor, 0444, DMI_BOARD_VENDOR); DEFINE_DMI_ATTR_WITH_SHOW(board_name, 0444, DMI_BOARD_NAME); DEFINE_DMI_ATTR_WITH_SHOW(board_version, 0444, DMI_BOARD_VERSION); @@ -191,6 +192,7 @@ static void __init dmi_id_init_attr_table(void) ADD_DMI_ATTR(product_version, DMI_PRODUCT_VERSION); ADD_DMI_ATTR(product_serial, DMI_PRODUCT_SERIAL); ADD_DMI_ATTR(product_uuid, DMI_PRODUCT_UUID); + ADD_DMI_ATTR(product_family, DMI_PRODUCT_FAMILY); ADD_DMI_ATTR(board_vendor, DMI_BOARD_VENDOR); ADD_DMI_ATTR(board_name, DMI_BOARD_NAME); ADD_DMI_ATTR(board_version, DMI_BOARD_VERSION); diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index 54be60ead08f..93f7acdaac7a 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c @@ -430,6 +430,7 @@ static void __init dmi_decode(const struct dmi_header *dm, void *dummy) dmi_save_ident(dm, DMI_PRODUCT_VERSION, 6); dmi_save_ident(dm, DMI_PRODUCT_SERIAL, 7); dmi_save_uuid(dm, DMI_PRODUCT_UUID, 8); + dmi_save_ident(dm, DMI_PRODUCT_FAMILY, 26); break; case 2: /* Base Board Information */ dmi_save_ident(dm, DMI_BOARD_VENDOR, 4); diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index 566fda587fcf..3f74ef2281e8 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h @@ -467,6 +467,7 @@ enum dmi_field { DMI_PRODUCT_VERSION, DMI_PRODUCT_SERIAL, DMI_PRODUCT_UUID, + DMI_PRODUCT_FAMILY, DMI_BOARD_VENDOR, DMI_BOARD_NAME, DMI_BOARD_VERSION, -- cgit v1.2.3 From 2a8209fa68236ad65363dba03db5dbced520268a Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Wed, 17 May 2017 13:25:14 +0300 Subject: pinctrl: cherryview: Extend the Chromebook DMI quirk to Intel_Strago systems It turns out there are quite many Chromebooks out there that have the same keyboard issue than Acer Chromebook. All of them are based on Intel_Strago reference and report their DMI_PRODUCT_FAMILY as "Intel_Strago" (Samsung Chromebook 3 and Cyan Chromebooks are exceptions for which we add separate entries). Instead of adding each machine to the quirk table, we use DMI_PRODUCT_FAMILY of "Intel_Strago" that hopefully covers most of the machines out there currently. Link: https://bugzilla.kernel.org/show_bug.cgi?id=194945 Suggested: Dmitry Torokhov Signed-off-by: Mika Westerberg Reviewed-by: Andy Shevchenko Signed-off-by: Linus Walleij --- drivers/pinctrl/intel/pinctrl-cherryview.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c index e35d0fe4c737..20f1b4493994 100644 --- a/drivers/pinctrl/intel/pinctrl-cherryview.c +++ b/drivers/pinctrl/intel/pinctrl-cherryview.c @@ -1539,13 +1539,26 @@ static void chv_gpio_irq_handler(struct irq_desc *desc) * is not listed below. */ static const struct dmi_system_id chv_no_valid_mask[] = { + /* See https://bugzilla.kernel.org/show_bug.cgi?id=194945 */ { - /* See https://bugzilla.kernel.org/show_bug.cgi?id=194945 */ - .ident = "Acer Chromebook (CYAN)", + .ident = "Intel_Strago based Chromebooks (All models)", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"), - DMI_MATCH(DMI_PRODUCT_NAME, "Edgar"), - DMI_MATCH(DMI_BIOS_DATE, "05/21/2016"), + DMI_MATCH(DMI_PRODUCT_FAMILY, "Intel_Strago"), + }, + }, + { + .ident = "Acer Chromebook R11 (Cyan)", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"), + DMI_MATCH(DMI_PRODUCT_NAME, "Cyan"), + }, + }, + { + .ident = "Samsung Chromebook 3 (Celes)", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"), + DMI_MATCH(DMI_PRODUCT_NAME, "Celes"), }, }, {} -- cgit v1.2.3 From 0377f49fb4f83edf40a6ff355eb8df6697491ea1 Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Fri, 12 May 2017 10:01:18 -0700 Subject: MAINTAINERS: remove self from GPIO maintainers I have not been able to dedicate time to the GPIO subsystem since quite some time, and I don't see the situation improving in the near future. Update the maintainers list to reflect this unfortunate fact. Signed-off-by: Alexandre Courbot Signed-off-by: Linus Walleij --- MAINTAINERS | 1 - 1 file changed, 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 9e984645c4b0..e45b74a576a8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5667,7 +5667,6 @@ F: tools/testing/selftests/gpio/ GPIO SUBSYSTEM M: Linus Walleij -M: Alexandre Courbot L: linux-gpio@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio.git S: Maintained -- cgit v1.2.3 From da6c2addf66d7ff7d0b090d6267d4292f951e4e6 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Thu, 18 May 2017 11:23:55 +0200 Subject: pinctrl: mxs: atomically switch mux and drive strength config MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To set the mux mode of a pin two bits must be set. Up to now this is implemented using the following idiom: writel(mask, reg + CLR); writel(value, reg + SET); . This however results in the mux mode being 0 between the two writes. On my machine there is an IC's reset pin connected to LCD_D20. The bootloader configures this pin as GPIO output-high (i.e. not holding the IC in reset). When Linux reconfigures the pin to GPIO the short time LCD_D20 is muxed as LCD_D20 instead of GPIO_1_20 is enough to confuse the connected IC. The same problem is present for the pin's drive strength setting which is reset to low drive strength before using the right value. So instead of relying on the hardware to modify the register setting using two writes implement the bit toggling using read-modify-write. Fixes: 17723111e64f ("pinctrl: add pinctrl-mxs support") Signed-off-by: Uwe Kleine-König Acked-by: Shawn Guo Signed-off-by: Linus Walleij --- drivers/pinctrl/freescale/pinctrl-mxs.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/pinctrl/freescale/pinctrl-mxs.c b/drivers/pinctrl/freescale/pinctrl-mxs.c index 41b5b07d5a2b..6852010a6d70 100644 --- a/drivers/pinctrl/freescale/pinctrl-mxs.c +++ b/drivers/pinctrl/freescale/pinctrl-mxs.c @@ -194,6 +194,16 @@ static int mxs_pinctrl_get_func_groups(struct pinctrl_dev *pctldev, return 0; } +static void mxs_pinctrl_rmwl(u32 value, u32 mask, u8 shift, void __iomem *reg) +{ + u32 tmp; + + tmp = readl(reg); + tmp &= ~(mask << shift); + tmp |= value << shift; + writel(tmp, reg); +} + static int mxs_pinctrl_set_mux(struct pinctrl_dev *pctldev, unsigned selector, unsigned group) { @@ -211,8 +221,7 @@ static int mxs_pinctrl_set_mux(struct pinctrl_dev *pctldev, unsigned selector, reg += bank * 0x20 + pin / 16 * 0x10; shift = pin % 16 * 2; - writel(0x3 << shift, reg + CLR); - writel(g->muxsel[i] << shift, reg + SET); + mxs_pinctrl_rmwl(g->muxsel[i], 0x3, shift, reg); } return 0; @@ -279,8 +288,7 @@ static int mxs_pinconf_group_set(struct pinctrl_dev *pctldev, /* mA */ if (config & MA_PRESENT) { shift = pin % 8 * 4; - writel(0x3 << shift, reg + CLR); - writel(ma << shift, reg + SET); + mxs_pinctrl_rmwl(ma, 0x3, shift, reg); } /* vol */ -- cgit v1.2.3 From 7903d4f5e1dec53963cba9b1bc472a76a3532e07 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Mon, 22 May 2017 14:25:49 +0800 Subject: pinctrl: sunxi: Fix SPDIF function name for A83T We use well known standard names for functions that have name, such as I2C, SPI, SPDIF, etc.. Fix the function name of SPDIF, which was named OWA (One Wire Audio) based on Allwinner datasheets. Fixes: 4730f33f0d82 ("pinctrl: sunxi: add allwinner A83T PIO controller support") Signed-off-by: Chen-Yu Tsai Acked-by: Maxime Ripard Signed-off-by: Linus Walleij --- drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c b/drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c index 9aec1d2232dd..6624499eae72 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c +++ b/drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c @@ -394,7 +394,7 @@ static const struct sunxi_desc_pin sun8i_a83t_pins[] = { SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 18), SUNXI_FUNCTION(0x0, "gpio_in"), SUNXI_FUNCTION(0x1, "gpio_out"), - SUNXI_FUNCTION(0x3, "owa")), /* DOUT */ + SUNXI_FUNCTION(0x3, "spdif")), /* DOUT */ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 19), SUNXI_FUNCTION(0x0, "gpio_in"), SUNXI_FUNCTION(0x1, "gpio_out")), -- cgit v1.2.3 From 1b57b6210f4e52904393be97c62122aae69bc8aa Mon Sep 17 00:00:00 2001 From: Arend Van Spriel Date: Tue, 23 May 2017 09:58:07 +0100 Subject: cfg80211: make cfg80211_sched_scan_results() work from atomic context Drivers should be able to call cfg80211_sched_scan_results() from atomic context. However, with the introduction of multiple scheduled scan feature this requirement was not taken into account resulting in regression shown below. [ 119.021594] BUG: scheduling while atomic: irq/47-iwlwifi/517/0x00000200 [ 119.021604] Modules linked in: [...] [ 119.021759] CPU: 1 PID: 517 Comm: irq/47-iwlwifi Not tainted 4.12.0-rc2-t440s-20170522+ #1 [ 119.021763] Hardware name: LENOVO 20AQS03H00/20AQS03H00, BIOS GJET91WW (2.41 ) 09/21/2016 [ 119.021766] Call Trace: [ 119.021778] ? dump_stack+0x5c/0x84 [ 119.021784] ? __schedule_bug+0x4c/0x70 [ 119.021792] ? __schedule+0x496/0x5c0 [ 119.021798] ? schedule+0x2d/0x80 [ 119.021804] ? schedule_preempt_disabled+0x5/0x10 [ 119.021810] ? __mutex_lock.isra.0+0x18e/0x4c0 [ 119.021817] ? __wake_up+0x2f/0x50 [ 119.021833] ? cfg80211_sched_scan_results+0x19/0x60 [cfg80211] [ 119.021844] ? cfg80211_sched_scan_results+0x19/0x60 [cfg80211] [ 119.021859] ? iwl_mvm_rx_lmac_scan_iter_complete_notif+0x17/0x30 [iwlmvm] [ 119.021869] ? iwl_pcie_rx_handle+0x2a9/0x7e0 [iwlwifi] [ 119.021878] ? iwl_pcie_irq_handler+0x17c/0x730 [iwlwifi] [ 119.021884] ? irq_forced_thread_fn+0x60/0x60 [ 119.021887] ? irq_thread_fn+0x16/0x40 [ 119.021892] ? irq_thread+0x109/0x180 [ 119.021896] ? wake_threads_waitq+0x30/0x30 [ 119.021901] ? kthread+0xf2/0x130 [ 119.021905] ? irq_thread_dtor+0x90/0x90 [ 119.021910] ? kthread_create_on_node+0x40/0x40 [ 119.021915] ? ret_from_fork+0x26/0x40 Fixes: b34939b98369 ("cfg80211: add request id to cfg80211_sched_scan_*() api") Reported-by: Sander Eikelenboom Signed-off-by: Arend van Spriel Signed-off-by: Johannes Berg --- net/wireless/scan.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 14d5f0c8c45f..9f0901f3e42b 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -322,9 +322,9 @@ cfg80211_find_sched_scan_req(struct cfg80211_registered_device *rdev, u64 reqid) { struct cfg80211_sched_scan_request *pos; - ASSERT_RTNL(); + WARN_ON_ONCE(!rcu_read_lock_held() && !lockdep_rtnl_is_held()); - list_for_each_entry(pos, &rdev->sched_scan_req_list, list) { + list_for_each_entry_rcu(pos, &rdev->sched_scan_req_list, list) { if (pos->reqid == reqid) return pos; } @@ -398,13 +398,13 @@ void cfg80211_sched_scan_results(struct wiphy *wiphy, u64 reqid) trace_cfg80211_sched_scan_results(wiphy, reqid); /* ignore if we're not scanning */ - rtnl_lock(); + rcu_read_lock(); request = cfg80211_find_sched_scan_req(rdev, reqid); if (request) { request->report_results = true; queue_work(cfg80211_wq, &rdev->sched_scan_res_wk); } - rtnl_unlock(); + rcu_read_unlock(); } EXPORT_SYMBOL(cfg80211_sched_scan_results); -- cgit v1.2.3 From cdc5a7f363be34287ac6c2345e5d1d3b37cf4a23 Mon Sep 17 00:00:00 2001 From: Or Gerlitz Date: Tue, 9 May 2017 20:45:06 +0300 Subject: net/mlx5e: Use the correct delete call on offloaded TC encap entry detach We wrongly direcly invoke hlist_del_rcu() and not hash_del_rcu() which does a slightly different call now and may change later, fix that. Fixes: a54e20b4fcae ('net/mlx5e: Add basic TC tunnel set action for SRIOV offloads') Signed-off-by: Or Gerlitz Reported-by: Paul Blakey Reviewed-by: Paul Blakey Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 11c27e4fadf6..a90dd26ea51c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -384,7 +384,7 @@ static void mlx5e_detach_encap(struct mlx5e_priv *priv, if (e->flags & MLX5_ENCAP_ENTRY_VALID) mlx5_encap_dealloc(priv->mdev, e->encap_id); - hlist_del_rcu(&e->encap_hlist); + hash_del_rcu(&e->encap_hlist); kfree(e->encap_header); kfree(e); } -- cgit v1.2.3 From 3aa4266405a6c2e03eb0ff12d7c573d3d903da4c Mon Sep 17 00:00:00 2001 From: Or Gerlitz Date: Wed, 10 May 2017 13:48:41 +0300 Subject: net/sched: act_csum: Add accessors for offloading drivers Add the accessors for realizing if this is a csum action, and for which fields checksum is needed. Signed-off-by: Or Gerlitz Reviewed-by: Paul Blakey Signed-off-by: Saeed Mahameed --- include/net/tc_act/tc_csum.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/include/net/tc_act/tc_csum.h b/include/net/tc_act/tc_csum.h index f31fb6331a53..3248beaf16b0 100644 --- a/include/net/tc_act/tc_csum.h +++ b/include/net/tc_act/tc_csum.h @@ -3,6 +3,7 @@ #include #include +#include struct tcf_csum { struct tc_action common; @@ -11,4 +12,18 @@ struct tcf_csum { }; #define to_tcf_csum(a) ((struct tcf_csum *)a) +static inline bool is_tcf_csum(const struct tc_action *a) +{ +#ifdef CONFIG_NET_CLS_ACT + if (a->ops && a->ops->type == TCA_ACT_CSUM) + return true; +#endif + return false; +} + +static inline u32 tcf_csum_update_flags(const struct tc_action *a) +{ + return to_tcf_csum(a)->update_flags; +} + #endif /* __NET_TC_CSUM_H */ -- cgit v1.2.3 From 26c02749936f064abf771a0f5f49b280fcfd8b66 Mon Sep 17 00:00:00 2001 From: Or Gerlitz Date: Wed, 10 May 2017 13:59:54 +0300 Subject: net/mlx5e: Allow TC csum offload if applied together with pedit action When offloading header re-writes, the HW re-calculates the relevant L3/L4 checksums. Hence, when upper layers (as done by OVS) ask for TC checksum action offload together with pedit offload, don't err. This command now works: tc filter add dev ens1f0 protocol ip parent ffff: prio 20 flower skip_sw ip_proto tcp dst_port 9001 action pedit ex munge tcp dport set 0x1234 pipe action csum tcp Signed-off-by: Or Gerlitz Reported-by: Paul Blakey Reviewed-by: Paul Blakey Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 39 +++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index a90dd26ea51c..9dd83c7e4c51 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include "en.h" @@ -1109,6 +1110,28 @@ out_err: return err; } +static bool csum_offload_supported(struct mlx5e_priv *priv, u32 action, u32 update_flags) +{ + u32 prot_flags = TCA_CSUM_UPDATE_FLAG_IPV4HDR | TCA_CSUM_UPDATE_FLAG_TCP | + TCA_CSUM_UPDATE_FLAG_UDP; + + /* The HW recalcs checksums only if re-writing headers */ + if (!(action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)) { + netdev_warn(priv->netdev, + "TC csum action is only offloaded with pedit\n"); + return false; + } + + if (update_flags & ~prot_flags) { + netdev_warn(priv->netdev, + "can't offload TC csum action for some header/s - flags %#x\n", + update_flags); + return false; + } + + return true; +} + static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts, struct mlx5e_tc_flow_parse_attr *parse_attr, struct mlx5e_tc_flow *flow) @@ -1149,6 +1172,14 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts, continue; } + if (is_tcf_csum(a)) { + if (csum_offload_supported(priv, attr->action, + tcf_csum_update_flags(a))) + continue; + + return -EOPNOTSUPP; + } + if (is_tcf_skbedit_mark(a)) { u32 mark = tcf_skbedit_mark(a); @@ -1651,6 +1682,14 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts, continue; } + if (is_tcf_csum(a)) { + if (csum_offload_supported(priv, attr->action, + tcf_csum_update_flags(a))) + continue; + + return -EOPNOTSUPP; + } + if (is_tcf_mirred_egress_redirect(a)) { int ifindex = tcf_mirred_ifindex(a); struct net_device *out_dev, *encap_dev = NULL; -- cgit v1.2.3 From d824bf3fe2d352fc2c52b7ede05b1a0e95d946be Mon Sep 17 00:00:00 2001 From: Or Gerlitz Date: Tue, 9 May 2017 19:02:42 +0300 Subject: net/mlx5e: Properly enforce disallowing of partial field re-write offload Currently we don't support partial header re-writes through TC pedit action offloading. However, the code that enforces that wasn't err-ing on cases where the first and last bits of the mask are set but there is some zero bit between them, such as in the below example, fix that! tc filter add dev enp1s0 protocol ip parent ffff: prio 10 flower ip_proto udp dst_port 2001 skip_sw action pedit munge ip src set 1.0.0.1 retain 0xff0000ff Fixes: d79b6df6b10a ('net/mlx5e: Add parsing of TC pedit actions to HW format') Signed-off-by: Or Gerlitz Reviewed-by: Paul Blakey Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 9dd83c7e4c51..0387c321f0a2 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -926,7 +926,7 @@ static int offload_pedit_fields(struct pedit_headers *masks, struct mlx5e_tc_flow_parse_attr *parse_attr) { struct pedit_headers *set_masks, *add_masks, *set_vals, *add_vals; - int i, action_size, nactions, max_actions, first, last; + int i, action_size, nactions, max_actions, first, last, first_z; void *s_masks_p, *a_masks_p, *vals_p; u32 s_mask, a_mask, val; struct mlx5_fields *f; @@ -985,9 +985,10 @@ static int offload_pedit_fields(struct pedit_headers *masks, memcpy(&val, vals_p, f->size); field_bsize = f->size * BITS_PER_BYTE; + first_z = find_first_zero_bit(&mask, field_bsize); first = find_first_bit(&mask, field_bsize); last = find_last_bit(&mask, field_bsize); - if (first > 0 || last != (field_bsize - 1)) { + if (first > 0 || last != (field_bsize - 1) || first_z < last) { printk(KERN_WARNING "mlx5: partial rewrite (mask %lx) is currently not offloaded\n", mask); return -EOPNOTSUPP; -- cgit v1.2.3 From e3ca4e0583a02a04503d9c827fb5c5d50abc4ff5 Mon Sep 17 00:00:00 2001 From: Or Gerlitz Date: Tue, 9 May 2017 13:37:26 +0300 Subject: net/mlx5e: Fix warnings around parsing of TC pedit actions The sparse tool emits these correct complaints: drivers/net/ethernet/mellanox/mlx5/core//en_tc.c:1005:25: warning: cast to restricted __be32 drivers/net/ethernet/mellanox/mlx5/core//en_tc.c:1007:25: warning: cast to restricted __be16 The value is provided from user-space in network order, but there's no way for them to realize that, avoid the warnings by casting to the appropriate type. Fixes: d79b6df6b10a ('net/mlx5e: Add parsing of TC pedit actions to HW format') Signed-off-by: Or Gerlitz Reported-by: Leon Romanovsky Reviewed-by: Paul Blakey Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 0387c321f0a2..ec63158ab643 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -928,9 +928,9 @@ static int offload_pedit_fields(struct pedit_headers *masks, struct pedit_headers *set_masks, *add_masks, *set_vals, *add_vals; int i, action_size, nactions, max_actions, first, last, first_z; void *s_masks_p, *a_masks_p, *vals_p; - u32 s_mask, a_mask, val; struct mlx5_fields *f; u8 cmd, field_bsize; + u32 s_mask, a_mask; unsigned long mask; void *action; @@ -947,7 +947,8 @@ static int offload_pedit_fields(struct pedit_headers *masks, for (i = 0; i < ARRAY_SIZE(fields); i++) { f = &fields[i]; /* avoid seeing bits set from previous iterations */ - s_mask = a_mask = mask = val = 0; + s_mask = 0; + a_mask = 0; s_masks_p = (void *)set_masks + f->offset; a_masks_p = (void *)add_masks + f->offset; @@ -982,9 +983,8 @@ static int offload_pedit_fields(struct pedit_headers *masks, memset(a_masks_p, 0, f->size); } - memcpy(&val, vals_p, f->size); - field_bsize = f->size * BITS_PER_BYTE; + first_z = find_first_zero_bit(&mask, field_bsize); first = find_first_bit(&mask, field_bsize); last = find_last_bit(&mask, field_bsize); @@ -1004,11 +1004,11 @@ static int offload_pedit_fields(struct pedit_headers *masks, } if (field_bsize == 32) - MLX5_SET(set_action_in, action, data, ntohl(val)); + MLX5_SET(set_action_in, action, data, ntohl(*(__be32 *)vals_p)); else if (field_bsize == 16) - MLX5_SET(set_action_in, action, data, ntohs(val)); + MLX5_SET(set_action_in, action, data, ntohs(*(__be16 *)vals_p)); else if (field_bsize == 8) - MLX5_SET(set_action_in, action, data, val); + MLX5_SET(set_action_in, action, data, *(u8 *)vals_p); action += action_size; nactions++; -- cgit v1.2.3 From b57fe691961cc8f00541f9a435c70df45d41e514 Mon Sep 17 00:00:00 2001 From: Erez Shitrit Date: Thu, 27 Apr 2017 17:59:00 +0300 Subject: net/mlx5e: IPoIB, handle RX packet correctly IPoIB packet contains the pseudo header area, we need to pull it prior to reset_mac_header in order to let the GRO work well. In more details: GRO checks the mac address of the new coming packet, it does that by comparing the hard_header_len size of the current packet to the previous one in that session, the comparison is over hard_header_len size. Now, the driver prepares that area in the skb by allocating area from the reserved part and resetting the correct mac header to it. Fixes: 9d6bd752c63c ("net/mlx5e: IPoIB, RX handler") Signed-off-by: Erez Shitrit Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_rx.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c index 7b1566f0ae58..66b5fec15313 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c @@ -1041,6 +1041,8 @@ void mlx5e_free_xdpsq_descs(struct mlx5e_xdpsq *sq) #define MLX5_IB_GRH_BYTES 40 #define MLX5_IPOIB_ENCAP_LEN 4 #define MLX5_GID_SIZE 16 +#define MLX5_IPOIB_PSEUDO_LEN 20 +#define MLX5_IPOIB_HARD_LEN (MLX5_IPOIB_PSEUDO_LEN + MLX5_IPOIB_ENCAP_LEN) static inline void mlx5i_complete_rx_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe, @@ -1048,6 +1050,7 @@ static inline void mlx5i_complete_rx_cqe(struct mlx5e_rq *rq, struct sk_buff *skb) { struct net_device *netdev = rq->netdev; + char *pseudo_header; u8 *dgid; u8 g; @@ -1076,8 +1079,11 @@ static inline void mlx5i_complete_rx_cqe(struct mlx5e_rq *rq, if (likely(netdev->features & NETIF_F_RXHASH)) mlx5e_skb_set_hash(cqe, skb); + /* 20 bytes of ipoib header and 4 for encap existing */ + pseudo_header = skb_push(skb, MLX5_IPOIB_PSEUDO_LEN); + memset(pseudo_header, 0, MLX5_IPOIB_PSEUDO_LEN); skb_reset_mac_header(skb); - skb_pull(skb, MLX5_IPOIB_ENCAP_LEN); + skb_pull(skb, MLX5_IPOIB_HARD_LEN); skb->dev = netdev; -- cgit v1.2.3 From 73dd3a4839c1d27c36d4dcc92e1ff44225ecbeb7 Mon Sep 17 00:00:00 2001 From: Mohamad Haj Yahia Date: Thu, 23 Feb 2017 11:19:36 +0200 Subject: net/mlx5: Avoid using pending command interface slots Currently when firmware command gets stuck or it takes long time to complete, the driver command will get timeout and the command slot is freed and can be used for new commands, and if the firmware receive new command on the old busy slot its behavior is unexpected and this could be harmful. To fix this when the driver command gets timeout we return failure, but we don't free the command slot and we wait for the firmware to explicitly respond to that command. Once all the entries are busy we will stop processing new firmware commands. Fixes: 9cba4ebcf374 ('net/mlx5: Fix potential deadlock in command mode change') Signed-off-by: Mohamad Haj Yahia Cc: kernel-team@fb.com Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/cmd.c | 41 +++++++++++++++++++++--- drivers/net/ethernet/mellanox/mlx5/core/eq.c | 2 +- drivers/net/ethernet/mellanox/mlx5/core/health.c | 2 +- include/linux/mlx5/driver.h | 7 +++- 4 files changed, 44 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c index 5bdaf3d545b2..10d282841f5b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c @@ -774,7 +774,7 @@ static void cb_timeout_handler(struct work_struct *work) mlx5_core_warn(dev, "%s(0x%x) timeout. Will cause a leak of a command resource\n", mlx5_command_str(msg_to_opcode(ent->in)), msg_to_opcode(ent->in)); - mlx5_cmd_comp_handler(dev, 1UL << ent->idx); + mlx5_cmd_comp_handler(dev, 1UL << ent->idx, true); } static void cmd_work_handler(struct work_struct *work) @@ -804,6 +804,7 @@ static void cmd_work_handler(struct work_struct *work) } cmd->ent_arr[ent->idx] = ent; + set_bit(MLX5_CMD_ENT_STATE_PENDING_COMP, &ent->state); lay = get_inst(cmd, ent->idx); ent->lay = lay; memset(lay, 0, sizeof(*lay)); @@ -825,6 +826,20 @@ static void cmd_work_handler(struct work_struct *work) if (ent->callback) schedule_delayed_work(&ent->cb_timeout_work, cb_timeout); + /* Skip sending command to fw if internal error */ + if (pci_channel_offline(dev->pdev) || + dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) { + u8 status = 0; + u32 drv_synd; + + ent->ret = mlx5_internal_err_ret_value(dev, msg_to_opcode(ent->in), &drv_synd, &status); + MLX5_SET(mbox_out, ent->out, status, status); + MLX5_SET(mbox_out, ent->out, syndrome, drv_synd); + + mlx5_cmd_comp_handler(dev, 1UL << ent->idx, true); + return; + } + /* ring doorbell after the descriptor is valid */ mlx5_core_dbg(dev, "writing 0x%x to command doorbell\n", 1 << ent->idx); wmb(); @@ -835,7 +850,7 @@ static void cmd_work_handler(struct work_struct *work) poll_timeout(ent); /* make sure we read the descriptor after ownership is SW */ rmb(); - mlx5_cmd_comp_handler(dev, 1UL << ent->idx); + mlx5_cmd_comp_handler(dev, 1UL << ent->idx, (ent->ret == -ETIMEDOUT)); } } @@ -879,7 +894,7 @@ static int wait_func(struct mlx5_core_dev *dev, struct mlx5_cmd_work_ent *ent) wait_for_completion(&ent->done); } else if (!wait_for_completion_timeout(&ent->done, timeout)) { ent->ret = -ETIMEDOUT; - mlx5_cmd_comp_handler(dev, 1UL << ent->idx); + mlx5_cmd_comp_handler(dev, 1UL << ent->idx, true); } err = ent->ret; @@ -1375,7 +1390,7 @@ static void free_msg(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *msg) } } -void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec) +void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec, bool forced) { struct mlx5_cmd *cmd = &dev->cmd; struct mlx5_cmd_work_ent *ent; @@ -1395,6 +1410,19 @@ void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec) struct semaphore *sem; ent = cmd->ent_arr[i]; + + /* if we already completed the command, ignore it */ + if (!test_and_clear_bit(MLX5_CMD_ENT_STATE_PENDING_COMP, + &ent->state)) { + /* only real completion can free the cmd slot */ + if (!forced) { + mlx5_core_err(dev, "Command completion arrived after timeout (entry idx = %d).\n", + ent->idx); + free_ent(cmd, ent->idx); + } + continue; + } + if (ent->callback) cancel_delayed_work(&ent->cb_timeout_work); if (ent->page_queue) @@ -1417,7 +1445,10 @@ void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec) mlx5_core_dbg(dev, "command completed. ret 0x%x, delivery status %s(0x%x)\n", ent->ret, deliv_status_to_str(ent->status), ent->status); } - free_ent(cmd, ent->idx); + + /* only real completion will free the entry slot */ + if (!forced) + free_ent(cmd, ent->idx); if (ent->callback) { ds = ent->ts2 - ent->ts1; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c index ea5d8d37a75c..33eae5ad2fb0 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c @@ -422,7 +422,7 @@ static irqreturn_t mlx5_eq_int(int irq, void *eq_ptr) break; case MLX5_EVENT_TYPE_CMD: - mlx5_cmd_comp_handler(dev, be32_to_cpu(eqe->data.cmd.vector)); + mlx5_cmd_comp_handler(dev, be32_to_cpu(eqe->data.cmd.vector), false); break; case MLX5_EVENT_TYPE_PORT_CHANGE: diff --git a/drivers/net/ethernet/mellanox/mlx5/core/health.c b/drivers/net/ethernet/mellanox/mlx5/core/health.c index d0515391d33b..44f59b1d6f0f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/health.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/health.c @@ -90,7 +90,7 @@ static void trigger_cmd_completions(struct mlx5_core_dev *dev) spin_unlock_irqrestore(&dev->cmd.alloc_lock, flags); mlx5_core_dbg(dev, "vector 0x%llx\n", vector); - mlx5_cmd_comp_handler(dev, vector); + mlx5_cmd_comp_handler(dev, vector, true); return; no_trig: diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h index bcdf739ee41a..93273d9ea4d1 100644 --- a/include/linux/mlx5/driver.h +++ b/include/linux/mlx5/driver.h @@ -787,7 +787,12 @@ enum { typedef void (*mlx5_cmd_cbk_t)(int status, void *context); +enum { + MLX5_CMD_ENT_STATE_PENDING_COMP, +}; + struct mlx5_cmd_work_ent { + unsigned long state; struct mlx5_cmd_msg *in; struct mlx5_cmd_msg *out; void *uout; @@ -976,7 +981,7 @@ void mlx5_cq_completion(struct mlx5_core_dev *dev, u32 cqn); void mlx5_rsc_event(struct mlx5_core_dev *dev, u32 rsn, int event_type); void mlx5_srq_event(struct mlx5_core_dev *dev, u32 srqn, int event_type); struct mlx5_core_srq *mlx5_core_get_srq(struct mlx5_core_dev *dev, u32 srqn); -void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec); +void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec, bool forced); void mlx5_cq_event(struct mlx5_core_dev *dev, u32 cqn, int event_type); int mlx5_create_map_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq, u8 vecidx, int nent, u64 mask, const char *name, -- cgit v1.2.3 From b665d98edc9ab295169be2fc5bb4e89a46de0a1a Mon Sep 17 00:00:00 2001 From: Tariq Toukan Date: Thu, 18 May 2017 13:34:43 +0300 Subject: net/mlx5: Tolerate irq_set_affinity_hint() failures Add tolerance to failures of irq_set_affinity_hint(). Its role is to give hints that optimizes performance, and should not block the driver load. In non-SMP systems, functionality is not available as there is a single core, and all these calls definitely fail. Hence, do not call the function and avoid the warning prints. Fixes: db058a186f98 ("net/mlx5_core: Set irq affinity hints") Signed-off-by: Tariq Toukan Cc: kernel-team@fb.com Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/main.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index 0c123d571b4c..fe5546bb4153 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -612,7 +612,6 @@ static int mlx5_irq_set_affinity_hint(struct mlx5_core_dev *mdev, int i) struct mlx5_priv *priv = &mdev->priv; struct msix_entry *msix = priv->msix_arr; int irq = msix[i + MLX5_EQ_VEC_COMP_BASE].vector; - int err; if (!zalloc_cpumask_var(&priv->irq_info[i].mask, GFP_KERNEL)) { mlx5_core_warn(mdev, "zalloc_cpumask_var failed"); @@ -622,18 +621,12 @@ static int mlx5_irq_set_affinity_hint(struct mlx5_core_dev *mdev, int i) cpumask_set_cpu(cpumask_local_spread(i, priv->numa_node), priv->irq_info[i].mask); - err = irq_set_affinity_hint(irq, priv->irq_info[i].mask); - if (err) { - mlx5_core_warn(mdev, "irq_set_affinity_hint failed,irq 0x%.4x", - irq); - goto err_clear_mask; - } +#ifdef CONFIG_SMP + if (irq_set_affinity_hint(irq, priv->irq_info[i].mask)) + mlx5_core_warn(mdev, "irq_set_affinity_hint failed, irq 0x%.4x", irq); +#endif return 0; - -err_clear_mask: - free_cpumask_var(priv->irq_info[i].mask); - return err; } static void mlx5_irq_clear_affinity_hint(struct mlx5_core_dev *mdev, int i) -- cgit v1.2.3 From e7c1572f6565d8b2b2e3be9cffa022a8cd6a6643 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Thu, 18 May 2017 14:58:52 +0200 Subject: MAINTAINERS: sort F entries for Marvell EBU maintainers This commit sorts alphabetically the file entries of the Marvell EBU maintainers in the MAINTAINERS file. Signed-off-by: Thomas Petazzoni Acked-by: Jason Cooper Signed-off-by: Gregory CLEMENT --- MAINTAINERS | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 9e984645c4b0..c186b9533c08 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1489,13 +1489,13 @@ M: Gregory Clement M: Sebastian Hesselbarth L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained -F: arch/arm/mach-mvebu/ -F: drivers/rtc/rtc-armada38x.c F: arch/arm/boot/dts/armada* F: arch/arm/boot/dts/kirkwood* +F: arch/arm/configs/mvebu_*_defconfig +F: arch/arm/mach-mvebu/ F: arch/arm64/boot/dts/marvell/armada* F: drivers/cpufreq/mvebu-cpufreq.c -F: arch/arm/configs/mvebu_*_defconfig +F: drivers/rtc/rtc-armada38x.c ARM/Marvell Berlin SoC support M: Jisheng Zhang -- cgit v1.2.3 From 1cb0b57fec06a616d98deaeda1924f8e45e1e4de Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Thu, 18 May 2017 14:58:53 +0200 Subject: MAINTAINERS: add irqchip related drivers to Marvell EBU maintainers This commit updates the MAINTAINERS file so that the Marvell EBU maintainers are also responsible for their irqchip drivers in drivers/irqchip/. Signed-off-by: Thomas Petazzoni Acked-by: Jason Cooper Signed-off-by: Gregory CLEMENT --- MAINTAINERS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index c186b9533c08..7217bb538023 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1495,6 +1495,8 @@ F: arch/arm/configs/mvebu_*_defconfig F: arch/arm/mach-mvebu/ F: arch/arm64/boot/dts/marvell/armada* F: drivers/cpufreq/mvebu-cpufreq.c +F: drivers/irqchip/irq-armada-370-xp.c +F: drivers/irqchip/irq-mvebu-* F: drivers/rtc/rtc-armada38x.c ARM/Marvell Berlin SoC support -- cgit v1.2.3 From 7f65b1f5adc5f8496ca8bec4947de66fefe36220 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Mon, 22 May 2017 14:50:30 +0200 Subject: cdc-ether: divorce initialisation with a filter reset and a generic method Some devices need their multicast filter reset but others are crashed by that. So the methods need to be separated. Signed-off-by: Oliver Neukum Reported-by: "Ridgway, Keith" Signed-off-by: David S. Miller --- drivers/net/usb/cdc_ether.c | 31 ++++++++++++++++++++++++------- include/linux/usb/usbnet.h | 1 + 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index f3ae88fdf332..8ab281b478f2 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -310,6 +310,26 @@ skip: return -ENODEV; } + return 0; + +bad_desc: + dev_info(&dev->udev->dev, "bad CDC descriptors\n"); + return -ENODEV; +} +EXPORT_SYMBOL_GPL(usbnet_generic_cdc_bind); + + +/* like usbnet_generic_cdc_bind() but handles filter initialization + * correctly + */ +int usbnet_ether_cdc_bind(struct usbnet *dev, struct usb_interface *intf) +{ + int rv; + + rv = usbnet_generic_cdc_bind(dev, intf); + if (rv < 0) + goto bail_out; + /* Some devices don't initialise properly. In particular * the packet filter is not reset. There are devices that * don't do reset all the way. So the packet filter should @@ -317,13 +337,10 @@ skip: */ usbnet_cdc_update_filter(dev); - return 0; - -bad_desc: - dev_info(&dev->udev->dev, "bad CDC descriptors\n"); - return -ENODEV; +bail_out: + return rv; } -EXPORT_SYMBOL_GPL(usbnet_generic_cdc_bind); +EXPORT_SYMBOL_GPL(usbnet_ether_cdc_bind); void usbnet_cdc_unbind(struct usbnet *dev, struct usb_interface *intf) { @@ -417,7 +434,7 @@ int usbnet_cdc_bind(struct usbnet *dev, struct usb_interface *intf) BUILD_BUG_ON((sizeof(((struct usbnet *)0)->data) < sizeof(struct cdc_state))); - status = usbnet_generic_cdc_bind(dev, intf); + status = usbnet_ether_cdc_bind(dev, intf); if (status < 0) return status; diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h index 7dffa5624ea6..97116379db5f 100644 --- a/include/linux/usb/usbnet.h +++ b/include/linux/usb/usbnet.h @@ -206,6 +206,7 @@ struct cdc_state { }; extern int usbnet_generic_cdc_bind(struct usbnet *, struct usb_interface *); +extern int usbnet_ether_cdc_bind(struct usbnet *dev, struct usb_interface *intf); extern int usbnet_cdc_bind(struct usbnet *, struct usb_interface *); extern void usbnet_cdc_unbind(struct usbnet *, struct usb_interface *); extern void usbnet_cdc_status(struct usbnet *, struct urb *); -- cgit v1.2.3 From 12e8b570e732eaa5eae3a2895ba3fbcf91bde2b4 Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer Date: Mon, 22 May 2017 20:13:07 +0200 Subject: mlx5: fix bug reading rss_hash_type from CQE Masks for extracting part of the Completion Queue Entry (CQE) field rss_hash_type was swapped, namely CQE_RSS_HTYPE_IP and CQE_RSS_HTYPE_L4. The bug resulted in setting skb->l4_hash, even-though the rss_hash_type indicated that hash was NOT computed over the L4 (UDP or TCP) part of the packet. Added comments from the datasheet, to make it more clear what these masks are selecting. Signed-off-by: Jesper Dangaard Brouer Acked-by: Saeed Mahameed Signed-off-by: David S. Miller --- include/linux/mlx5/device.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/include/linux/mlx5/device.h b/include/linux/mlx5/device.h index dd9a263ed368..a940ec6a046c 100644 --- a/include/linux/mlx5/device.h +++ b/include/linux/mlx5/device.h @@ -787,8 +787,14 @@ enum { }; enum { - CQE_RSS_HTYPE_IP = 0x3 << 6, - CQE_RSS_HTYPE_L4 = 0x3 << 2, + CQE_RSS_HTYPE_IP = 0x3 << 2, + /* cqe->rss_hash_type[3:2] - IP destination selected for hash + * (00 = none, 01 = IPv4, 10 = IPv6, 11 = Reserved) + */ + CQE_RSS_HTYPE_L4 = 0x3 << 6, + /* cqe->rss_hash_type[7:6] - L4 destination selected for hash + * (00 = none, 01 = TCP. 10 = UDP, 11 = IPSEC.SPI + */ }; enum { -- cgit v1.2.3 From efad8396e906d095521791e0408293c101543e50 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Mon, 8 May 2017 21:36:37 -0700 Subject: wcn36xx: Close SMD channel on device removal The SMD channel is not the primary WCNSS channel and must explicitly be closed as the device is removed, or the channel will already by open on a subsequent probe call in e.g. the case of reloading the kernel module. This issue was introduced because I simplified the underlying SMD implementation while the SMD adaptions of the driver sat on the mailing list, but missed to update these patches. The patch does however only apply back to the transition to rpmsg, hence the limited Fixes. Fixes: 5052de8deff5 ("soc: qcom: smd: Transition client drivers from smd to rpmsg") Reported-by: Eyal Ilsar Signed-off-by: Bjorn Andersson Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wcn36xx/main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index d5e993dc9b23..517a315e259b 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -1271,6 +1271,8 @@ static int wcn36xx_remove(struct platform_device *pdev) qcom_smem_state_put(wcn->tx_enable_state); qcom_smem_state_put(wcn->tx_rings_empty_state); + rpmsg_destroy_ept(wcn->smd_channel); + iounmap(wcn->dxe_base); iounmap(wcn->ccu_base); -- cgit v1.2.3 From 29226b198bb26f8e23985d011a9301cee5550da8 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Thu, 18 May 2017 17:09:59 +0100 Subject: ARM: 8675/1: MCPM: ensure not to enter __hyp_soft_restart from loopback and cpu_power_down Commit 9da5ac236de6 ("ARM: soft-reboot into same mode that we entered the kernel") added support to enter the new kernel in the same processor mode as the previous one when we soft-reboot from one kernel into another by pass a flag to cpu_reset() so it knows what to do exactly. However it missed to make similar changes in MCPM code. Due to the missing flag, the CPUs enter HYP mode which is not supported with MCPM. MCPM works only in secure mode as it manages CCI. This patch aligns the cpu_reset call in MCPM with other changes in the above mentioned commit by making phys_reset_t to follow the prototype of cpu_reset(). Fixes: 9da5ac236de6 ("ARM: soft-reboot into same mode that we entered the kernel") Acked-by: Nicolas Pitre Signed-off-by: Sudeep Holla Signed-off-by: Russell King --- arch/arm/common/mcpm_entry.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/common/mcpm_entry.c b/arch/arm/common/mcpm_entry.c index cf062472e07b..2b913f17d50f 100644 --- a/arch/arm/common/mcpm_entry.c +++ b/arch/arm/common/mcpm_entry.c @@ -235,7 +235,7 @@ int mcpm_cpu_power_up(unsigned int cpu, unsigned int cluster) return ret; } -typedef void (*phys_reset_t)(unsigned long); +typedef typeof(cpu_reset) phys_reset_t; void mcpm_cpu_power_down(void) { @@ -300,7 +300,7 @@ void mcpm_cpu_power_down(void) * on the CPU. */ phys_reset = (phys_reset_t)(unsigned long)__pa_symbol(cpu_reset); - phys_reset(__pa_symbol(mcpm_entry_point)); + phys_reset(__pa_symbol(mcpm_entry_point), false); /* should never get here */ BUG(); @@ -389,7 +389,7 @@ static int __init nocache_trampoline(unsigned long _arg) __mcpm_cpu_down(cpu, cluster); phys_reset = (phys_reset_t)(unsigned long)__pa_symbol(cpu_reset); - phys_reset(__pa_symbol(mcpm_entry_point)); + phys_reset(__pa_symbol(mcpm_entry_point), false); BUG(); } -- cgit v1.2.3 From 9a307403d374b993061f5992a6e260c944920d0b Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Tue, 23 May 2017 12:24:40 -0400 Subject: nfsd4: fix null dereference on replay if we receive a compound such that: - the sessionid, slot, and sequence number in the SEQUENCE op match a cached succesful reply with N ops, and - the Nth operation of the compound is a PUTFH, PUTPUBFH, PUTROOTFH, or RESTOREFH, then nfsd4_sequence will return 0 and set cstate->status to nfserr_replay_cache. The current filehandle will not be set. This will cause us to call check_nfsd_access with first argument NULL. To nfsd4_compound it looks like we just succesfully executed an operation that set a filehandle, but the current filehandle is not set. Fix this by moving the nfserr_replay_cache earlier. There was never any reason to have it after the encode_op label, since the only case where he hit that is when opdesc->op_func sets it. Note that there are two ways we could hit this case: - a client is resending a previously sent compound that ended with one of the four PUTFH-like operations, or - a client is sending a *new* compound that (incorrectly) shares sessionid, slot, and sequence number with a previously sent compound, and the length of the previously sent compound happens to match the position of a PUTFH-like operation in the new compound. The second is obviously incorrect client behavior. The first is also very strange--the only purpose of a PUTFH-like operation is to set the current filehandle to be used by the following operation, so there's no point in having it as the last in a compound. So it's likely this requires a buggy or malicious client to reproduce. Reported-by: Scott Mayhew Cc: stable@kernel.vger.org Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4proc.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index c453a1998e00..dadb3bf305b2 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -1769,6 +1769,12 @@ nfsd4_proc_compound(struct svc_rqst *rqstp, opdesc->op_get_currentstateid(cstate, &op->u); op->status = opdesc->op_func(rqstp, cstate, &op->u); + /* Only from SEQUENCE */ + if (cstate->status == nfserr_replay_cache) { + dprintk("%s NFS4.1 replay from cache\n", __func__); + status = op->status; + goto out; + } if (!op->status) { if (opdesc->op_set_currentstateid) opdesc->op_set_currentstateid(cstate, &op->u); @@ -1779,14 +1785,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp, if (need_wrongsec_check(rqstp)) op->status = check_nfsd_access(current_fh->fh_export, rqstp); } - encode_op: - /* Only from SEQUENCE */ - if (cstate->status == nfserr_replay_cache) { - dprintk("%s NFS4.1 replay from cache\n", __func__); - status = op->status; - goto out; - } if (op->status == nfserr_replay_me) { op->replay = &cstate->replay_owner->so_replay; nfsd4_encode_replay(&resp->xdr, op); -- cgit v1.2.3 From f3c0eb05e258c6a48c2d1ef2fa71ffb6ff63cd18 Mon Sep 17 00:00:00 2001 From: Davide Caratti Date: Thu, 18 May 2017 18:01:43 +0200 Subject: netfilter: conntrack: fix false CRC32c mismatch using paged skb sctp_compute_cksum() implementation assumes that at least the SCTP header is in the linear part of skb: modify conntrack error callback to avoid false CRC32c mismatch, if the transport header is partially/entirely paged. Fixes: cf6e007eef83 ("netfilter: conntrack: validate SCTP crc32c in PREROUTING") Signed-off-by: Davide Caratti Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_conntrack_proto_sctp.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c index 13875d599a85..1c5b14a6cab3 100644 --- a/net/netfilter/nf_conntrack_proto_sctp.c +++ b/net/netfilter/nf_conntrack_proto_sctp.c @@ -512,16 +512,19 @@ static int sctp_error(struct net *net, struct nf_conn *tpl, struct sk_buff *skb, u8 pf, unsigned int hooknum) { const struct sctphdr *sh; - struct sctphdr _sctph; const char *logmsg; - sh = skb_header_pointer(skb, dataoff, sizeof(_sctph), &_sctph); - if (!sh) { + if (skb->len < dataoff + sizeof(struct sctphdr)) { logmsg = "nf_ct_sctp: short packet "; goto out_invalid; } if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING && skb->ip_summed == CHECKSUM_NONE) { + if (!skb_make_writable(skb, dataoff + sizeof(struct sctphdr))) { + logmsg = "nf_ct_sctp: failed to read header "; + goto out_invalid; + } + sh = (const struct sctphdr *)(skb->data + dataoff); if (sh->checksum != sctp_compute_cksum(skb, dataoff)) { logmsg = "nf_ct_sctp: bad CRC "; goto out_invalid; -- cgit v1.2.3 From d2df92e98a34a5619dadd29c6291113c009181e7 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Sun, 21 May 2017 00:37:10 +0200 Subject: netfilter: nft_set_rbtree: handle element re-addition after deletion The existing code selects no next branch to be inspected when re-inserting an inactive element into the rb-tree, looping endlessly. This patch restricts the check for active elements to the EEXIST case only. Fixes: e701001e7cbe ("netfilter: nft_rbtree: allow adjacent intervals with dynamic updates") Reported-by: Wolfgang Bumiller Tested-by: Wolfgang Bumiller Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nft_set_rbtree.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c index e97e2fb53f0a..fbdbaa00dd5f 100644 --- a/net/netfilter/nft_set_rbtree.c +++ b/net/netfilter/nft_set_rbtree.c @@ -116,17 +116,17 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set, else if (d > 0) p = &parent->rb_right; else { - if (nft_set_elem_active(&rbe->ext, genmask)) { - if (nft_rbtree_interval_end(rbe) && - !nft_rbtree_interval_end(new)) - p = &parent->rb_left; - else if (!nft_rbtree_interval_end(rbe) && - nft_rbtree_interval_end(new)) - p = &parent->rb_right; - else { - *ext = &rbe->ext; - return -EEXIST; - } + if (nft_rbtree_interval_end(rbe) && + !nft_rbtree_interval_end(new)) { + p = &parent->rb_left; + } else if (!nft_rbtree_interval_end(rbe) && + nft_rbtree_interval_end(new)) { + p = &parent->rb_right; + } else if (nft_set_elem_active(&rbe->ext, genmask)) { + *ext = &rbe->ext; + return -EEXIST; + } else { + p = &parent->rb_left; } } } -- cgit v1.2.3 From 124dffea9e8e372509e055aebd118e85518fd644 Mon Sep 17 00:00:00 2001 From: Liping Zhang Date: Sun, 21 May 2017 22:38:11 +0800 Subject: netfilter: nat: use atomic bit op to clear the _SRC_NAT_DONE_BIT We need to clear the IPS_SRC_NAT_DONE_BIT to indicate that the ct has been removed from nat_bysource table. But unfortunately, we use the non-atomic bit operation: "ct->status &= ~IPS_NAT_DONE_MASK". So there's a race condition that we may clear the _DYING_BIT set by another CPU unexpectedly. Since we don't care about the IPS_DST_NAT_DONE_BIT, so just using clear_bit to clear the IPS_SRC_NAT_DONE_BIT is enough. Also note, this is the last user which use the non-atomic bit operation to update the confirmed ct->status. Reported-by: Florian Westphal Signed-off-by: Liping Zhang Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_nat_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c index ef0be325a0c6..6c72922d20ca 100644 --- a/net/netfilter/nf_nat_core.c +++ b/net/netfilter/nf_nat_core.c @@ -566,7 +566,7 @@ static int nf_nat_proto_clean(struct nf_conn *ct, void *data) * Else, when the conntrack is destoyed, nf_nat_cleanup_conntrack() * will delete entry from already-freed table. */ - ct->status &= ~IPS_NAT_DONE_MASK; + clear_bit(IPS_SRC_NAT_DONE_BIT, &ct->status); rhltable_remove(&nf_nat_bysource_table, &ct->nat_bysource, nf_nat_bysource_params); -- cgit v1.2.3 From 43fe8b8eb81eee713400340716cf945f59d21496 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 23 May 2017 23:27:38 +0200 Subject: posix-timers: Make signal printks conditional A recent commit added extra printks for CPU/RT limits. This can result in excessive spam in dmesg. Make the printks conditional on print_fatal_signals. Fixes: e7ea7c9806a2 ("rlimits: Print more information when CPU/RT limits are exceeded") Reported-by: Dave Jones Signed-off-by: Thomas Gleixner Cc: Arun Raghavan --- kernel/time/posix-cpu-timers.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c index 1370f067fb51..d2a1e6dd0291 100644 --- a/kernel/time/posix-cpu-timers.c +++ b/kernel/time/posix-cpu-timers.c @@ -825,8 +825,10 @@ static void check_thread_timers(struct task_struct *tsk, * At the hard limit, we just die. * No need to calculate anything else now. */ - pr_info("CPU Watchdog Timeout (hard): %s[%d]\n", - tsk->comm, task_pid_nr(tsk)); + if (print_fatal_signals) { + pr_info("CPU Watchdog Timeout (hard): %s[%d]\n", + tsk->comm, task_pid_nr(tsk)); + } __group_send_sig_info(SIGKILL, SEND_SIG_PRIV, tsk); return; } @@ -838,8 +840,10 @@ static void check_thread_timers(struct task_struct *tsk, soft += USEC_PER_SEC; sig->rlim[RLIMIT_RTTIME].rlim_cur = soft; } - pr_info("RT Watchdog Timeout (soft): %s[%d]\n", - tsk->comm, task_pid_nr(tsk)); + if (print_fatal_signals) { + pr_info("RT Watchdog Timeout (soft): %s[%d]\n", + tsk->comm, task_pid_nr(tsk)); + } __group_send_sig_info(SIGXCPU, SEND_SIG_PRIV, tsk); } } @@ -936,8 +940,10 @@ static void check_process_timers(struct task_struct *tsk, * At the hard limit, we just die. * No need to calculate anything else now. */ - pr_info("RT Watchdog Timeout (hard): %s[%d]\n", - tsk->comm, task_pid_nr(tsk)); + if (print_fatal_signals) { + pr_info("RT Watchdog Timeout (hard): %s[%d]\n", + tsk->comm, task_pid_nr(tsk)); + } __group_send_sig_info(SIGKILL, SEND_SIG_PRIV, tsk); return; } @@ -945,8 +951,10 @@ static void check_process_timers(struct task_struct *tsk, /* * At the soft limit, send a SIGXCPU every second. */ - pr_info("CPU Watchdog Timeout (soft): %s[%d]\n", - tsk->comm, task_pid_nr(tsk)); + if (print_fatal_signals) { + pr_info("CPU Watchdog Timeout (soft): %s[%d]\n", + tsk->comm, task_pid_nr(tsk)); + } __group_send_sig_info(SIGXCPU, SEND_SIG_PRIV, tsk); if (soft < hard) { soft++; -- cgit v1.2.3 From 0648a07c9b22acc33ead0645cf8f607b0c9c7e32 Mon Sep 17 00:00:00 2001 From: Artem Savkov Date: Sat, 20 May 2017 09:58:10 +0200 Subject: scsi: scsi_dh_rdac: Use ctlr directly in rdac_failover_get() rdac_failover_get references struct rdac_controller as ctlr->ms_sdev->handler_data->ctlr for no apparent reason. Besides being inefficient this also introduces a null-pointer dereference as send_mode_select() sets ctlr->ms_sdev to NULL before calling rdac_failover_get(): [ 18.432550] device-mapper: multipath service-time: version 0.3.0 loaded [ 18.436124] BUG: unable to handle kernel NULL pointer dereference at 0000000000000790 [ 18.436129] IP: send_mode_select+0xca/0x560 [ 18.436129] PGD 0 [ 18.436130] P4D 0 [ 18.436130] [ 18.436132] Oops: 0000 [#1] SMP [ 18.436133] Modules linked in: dm_service_time sd_mod dm_multipath amdkfd amd_iommu_v2 radeon(+) i2c_algo_bit drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops ttm qla2xxx drm serio_raw scsi_transport_fc bnx2 i2c_core dm_mirror dm_region_hash dm_log dm_mod [ 18.436143] CPU: 4 PID: 443 Comm: kworker/u16:2 Not tainted 4.12.0-rc1.1.el7.test.x86_64 #1 [ 18.436144] Hardware name: IBM BladeCenter LS22 -[79013SG]-/Server Blade, BIOS -[L8E164AUS-1.07]- 05/25/2011 [ 18.436145] Workqueue: kmpath_rdacd send_mode_select [ 18.436146] task: ffff880225116a40 task.stack: ffffc90002bd8000 [ 18.436148] RIP: 0010:send_mode_select+0xca/0x560 [ 18.436148] RSP: 0018:ffffc90002bdbda8 EFLAGS: 00010246 [ 18.436149] RAX: 0000000000000000 RBX: ffffc90002bdbe08 RCX: ffff88017ef04a80 [ 18.436150] RDX: ffffc90002bdbe08 RSI: ffff88017ef04a80 RDI: ffff8802248e4388 [ 18.436151] RBP: ffffc90002bdbe48 R08: 0000000000000000 R09: ffffffff81c104c0 [ 18.436151] R10: 00000000000001ff R11: 000000000000035a R12: ffffc90002bdbdd8 [ 18.436152] R13: ffff8802248e4390 R14: ffff880225152800 R15: ffff8802248e4400 [ 18.436153] FS: 0000000000000000(0000) GS:ffff880227d00000(0000) knlGS:0000000000000000 [ 18.436154] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 18.436154] CR2: 0000000000000790 CR3: 000000042535b000 CR4: 00000000000006e0 [ 18.436155] Call Trace: [ 18.436159] ? rdac_activate+0x14e/0x150 [ 18.436161] ? refcount_dec_and_test+0x11/0x20 [ 18.436162] ? kobject_put+0x1c/0x50 [ 18.436165] ? scsi_dh_activate+0x6f/0xd0 [ 18.436168] process_one_work+0x149/0x360 [ 18.436170] worker_thread+0x4d/0x3c0 [ 18.436172] kthread+0x109/0x140 [ 18.436173] ? rescuer_thread+0x380/0x380 [ 18.436174] ? kthread_park+0x60/0x60 [ 18.436176] ret_from_fork+0x2c/0x40 [ 18.436177] Code: 49 c7 46 20 00 00 00 00 4c 89 ef c6 07 00 0f 1f 40 00 45 31 ed c7 45 b0 05 00 00 00 44 89 6d b4 4d 89 f5 4c 8b 75 a8 49 8b 45 20 <48> 8b b0 90 07 00 00 48 8b 56 10 8b 42 10 48 8d 7a 28 85 c0 0f [ 18.436192] RIP: send_mode_select+0xca/0x560 RSP: ffffc90002bdbda8 [ 18.436192] CR2: 0000000000000790 [ 18.436198] ---[ end trace 40f3e4dca1ffabdd ]--- [ 18.436199] Kernel panic - not syncing: Fatal exception [ 18.436222] Kernel Offset: disabled [-- MARK -- Thu May 18 11:45:00 2017] Fixes: 327825574132 scsi_dh_rdac: switch to scsi_execute_req_flags() Cc: stable@vger.kernel.org Signed-off-by: Artem Savkov Reviewed-by: Christoph Hellwig Signed-off-by: Martin K. Petersen --- drivers/scsi/device_handler/scsi_dh_rdac.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c index 3cbab8710e58..2ceff585f189 100644 --- a/drivers/scsi/device_handler/scsi_dh_rdac.c +++ b/drivers/scsi/device_handler/scsi_dh_rdac.c @@ -265,18 +265,16 @@ static unsigned int rdac_failover_get(struct rdac_controller *ctlr, struct list_head *list, unsigned char *cdb) { - struct scsi_device *sdev = ctlr->ms_sdev; - struct rdac_dh_data *h = sdev->handler_data; struct rdac_mode_common *common; unsigned data_size; struct rdac_queue_data *qdata; u8 *lun_table; - if (h->ctlr->use_ms10) { + if (ctlr->use_ms10) { struct rdac_pg_expanded *rdac_pg; data_size = sizeof(struct rdac_pg_expanded); - rdac_pg = &h->ctlr->mode_select.expanded; + rdac_pg = &ctlr->mode_select.expanded; memset(rdac_pg, 0, data_size); common = &rdac_pg->common; rdac_pg->page_code = RDAC_PAGE_CODE_REDUNDANT_CONTROLLER + 0x40; @@ -288,7 +286,7 @@ static unsigned int rdac_failover_get(struct rdac_controller *ctlr, struct rdac_pg_legacy *rdac_pg; data_size = sizeof(struct rdac_pg_legacy); - rdac_pg = &h->ctlr->mode_select.legacy; + rdac_pg = &ctlr->mode_select.legacy; memset(rdac_pg, 0, data_size); common = &rdac_pg->common; rdac_pg->page_code = RDAC_PAGE_CODE_REDUNDANT_CONTROLLER; @@ -304,7 +302,7 @@ static unsigned int rdac_failover_get(struct rdac_controller *ctlr, } /* Prepare the command. */ - if (h->ctlr->use_ms10) { + if (ctlr->use_ms10) { cdb[0] = MODE_SELECT_10; cdb[7] = data_size >> 8; cdb[8] = data_size & 0xff; -- cgit v1.2.3 From 5e901d0b15c0cba8c5ba55e4be46fc5a0e2f3cb9 Mon Sep 17 00:00:00 2001 From: Arun Easi Date: Fri, 19 May 2017 01:33:15 -0700 Subject: scsi: qedi: Fix bad pte call trace when iscsiuio is stopped. munmap done by iscsiuio during a stop of the service triggers a "bad pte" warning sometimes. munmap kernel path goes through the mmapped pages and has a validation check for mapcount (in struct page) to be zero or above. kzalloc, which we had used to allocate udev->ctrl, uses slab allocations, which re-uses mapcount (union) for other purposes that can make the mapcount look negative. Avoid all these trouble by invoking one of the __get_free_pages wrappers to be used instead of kzalloc for udev->ctrl. BUG: Bad page map in process iscsiuio pte:80000000aa624067 pmd:3e6777067 page:ffffea0002a98900 count:2 mapcount:-2143289280 mapping: (null) index:0xffff8800aa624e00 page flags: 0x10075d00000090(dirty|slab) page dumped because: bad pte addr:00007fcba70a3000 vm_flags:0c0400fb anon_vma: (null) mapping:ffff8803edf66e90 index:0 Call Trace: dump_stack+0x19/0x1b print_bad_pte+0x1af/0x250 unmap_page_range+0x7a7/0x8a0 unmap_single_vma+0x81/0xf0 unmap_vmas+0x49/0x90 unmap_region+0xbe/0x140 ? vma_rb_erase+0x121/0x220 do_munmap+0x245/0x420 vm_munmap+0x41/0x60 SyS_munmap+0x22/0x30 tracesys+0xdd/0xe2 Signed-off-by: Arun Easi Signed-off-by: Manish Rangankar Signed-off-by: Martin K. Petersen --- drivers/scsi/qedi/qedi_main.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/drivers/scsi/qedi/qedi_main.c b/drivers/scsi/qedi/qedi_main.c index 92775a8b74b1..997e3052a706 100644 --- a/drivers/scsi/qedi/qedi_main.c +++ b/drivers/scsi/qedi/qedi_main.c @@ -151,6 +151,11 @@ static int qedi_uio_close(struct uio_info *uinfo, struct inode *inode) static void __qedi_free_uio_rings(struct qedi_uio_dev *udev) { + if (udev->uctrl) { + free_page((unsigned long)udev->uctrl); + udev->uctrl = NULL; + } + if (udev->ll2_ring) { free_page((unsigned long)udev->ll2_ring); udev->ll2_ring = NULL; @@ -169,7 +174,6 @@ static void __qedi_free_uio(struct qedi_uio_dev *udev) __qedi_free_uio_rings(udev); pci_dev_put(udev->pdev); - kfree(udev->uctrl); kfree(udev); } @@ -208,6 +212,11 @@ static int __qedi_alloc_uio_rings(struct qedi_uio_dev *udev) if (udev->ll2_ring || udev->ll2_buf) return rc; + /* Memory for control area. */ + udev->uctrl = (void *)get_zeroed_page(GFP_KERNEL); + if (!udev->uctrl) + return -ENOMEM; + /* Allocating memory for LL2 ring */ udev->ll2_ring_size = QEDI_PAGE_SIZE; udev->ll2_ring = (void *)get_zeroed_page(GFP_KERNEL | __GFP_COMP); @@ -237,7 +246,6 @@ exit_alloc_ring: static int qedi_alloc_uio_rings(struct qedi_ctx *qedi) { struct qedi_uio_dev *udev = NULL; - struct qedi_uio_ctrl *uctrl = NULL; int rc = 0; list_for_each_entry(udev, &qedi_udev_list, list) { @@ -258,21 +266,14 @@ static int qedi_alloc_uio_rings(struct qedi_ctx *qedi) goto err_udev; } - uctrl = kzalloc(sizeof(*uctrl), GFP_KERNEL); - if (!uctrl) { - rc = -ENOMEM; - goto err_uctrl; - } - udev->uio_dev = -1; udev->qedi = qedi; udev->pdev = qedi->pdev; - udev->uctrl = uctrl; rc = __qedi_alloc_uio_rings(udev); if (rc) - goto err_uio_rings; + goto err_uctrl; list_add(&udev->list, &qedi_udev_list); @@ -283,8 +284,6 @@ static int qedi_alloc_uio_rings(struct qedi_ctx *qedi) udev->rx_pkt = udev->ll2_buf + LL2_SINGLE_BUF_SIZE; return 0; - err_uio_rings: - kfree(uctrl); err_uctrl: kfree(udev); err_udev: -- cgit v1.2.3 From fc2fbf0d422b54b487c5e7413acd54cbac6d4151 Mon Sep 17 00:00:00 2001 From: "manish.rangankar@cavium.com" Date: Fri, 19 May 2017 01:33:16 -0700 Subject: scsi: qedi: Correctly set firmware max supported BDs. Signed-off-by: Manish Rangankar Signed-off-by: Martin K. Petersen --- drivers/scsi/qedi/qedi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qedi/qedi.h b/drivers/scsi/qedi/qedi.h index 5ca3e8c28a3f..269dac620cf8 100644 --- a/drivers/scsi/qedi/qedi.h +++ b/drivers/scsi/qedi/qedi.h @@ -38,7 +38,7 @@ struct qedi_endpoint; #define QEDI_MAX_ISCSI_TASK 4096 #define QEDI_MAX_TASK_NUM 0x0FFF #define QEDI_MAX_ISCSI_CONNS_PER_HBA 1024 -#define QEDI_ISCSI_MAX_BDS_PER_CMD 256 /* Firmware max BDs is 256 */ +#define QEDI_ISCSI_MAX_BDS_PER_CMD 255 /* Firmware max BDs is 255 */ #define MAX_OUSTANDING_TASKS_PER_CON 1024 #define QEDI_MAX_BD_LEN 0xffff -- cgit v1.2.3 From d0788a528d9e09d7c17f05dd61c4cc492181f817 Mon Sep 17 00:00:00 2001 From: "manish.rangankar@cavium.com" Date: Fri, 19 May 2017 01:33:17 -0700 Subject: scsi: qedi: Set dma_boundary to 0xfff. Signed-off-by: Manish Rangankar Signed-off-by: Martin K. Petersen --- drivers/scsi/qedi/qedi.h | 1 + drivers/scsi/qedi/qedi_iscsi.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/scsi/qedi/qedi.h b/drivers/scsi/qedi/qedi.h index 269dac620cf8..32632c9b2276 100644 --- a/drivers/scsi/qedi/qedi.h +++ b/drivers/scsi/qedi/qedi.h @@ -63,6 +63,7 @@ struct qedi_endpoint; #define QEDI_PAGE_MASK (~((QEDI_PAGE_SIZE) - 1)) #define QEDI_PAGE_SIZE 4096 +#define QEDI_HW_DMA_BOUNDARY 0xfff #define QEDI_PATH_HANDLE 0xFE0000000UL struct qedi_uio_ctrl { diff --git a/drivers/scsi/qedi/qedi_iscsi.c b/drivers/scsi/qedi/qedi_iscsi.c index 3548d46f9b27..19177931b84c 100644 --- a/drivers/scsi/qedi/qedi_iscsi.c +++ b/drivers/scsi/qedi/qedi_iscsi.c @@ -59,6 +59,7 @@ struct scsi_host_template qedi_host_template = { .this_id = -1, .sg_tablesize = QEDI_ISCSI_MAX_BDS_PER_CMD, .max_sectors = 0xffff, + .dma_boundary = QEDI_HW_DMA_BOUNDARY, .cmd_per_lun = 128, .use_clustering = ENABLE_CLUSTERING, .shost_attrs = qedi_shost_attrs, -- cgit v1.2.3 From 0ea9314f4e6c69f8d732e0a9310114c2de35ada8 Mon Sep 17 00:00:00 2001 From: "manish.rangankar@cavium.com" Date: Fri, 19 May 2017 01:33:18 -0700 Subject: scsi: qedi: Fix endpoint NULL panic in qedi_set_path. RIP: 0010:qedi_set_path+0x114/0x570 [qedi] Call Trace: [] iscsi_if_recv_msg+0x623/0x14a0 [] ? rhashtable_lookup_compare+0x36/0x70 [] iscsi_if_rx+0x8e/0x1f0 [] netlink_unicast+0xed/0x1b0 [] netlink_sendmsg+0x330/0x770 [] sock_sendmsg+0xb0/0xf0 [] ? __switch_to+0x17b/0x4b0 [] ? __schedule+0x2d8/0x900 [] ___sys_sendmsg+0x3a9/0x3c0 [] ? get_futex_key+0x1c8/0x2b0 [] ? futex_wake+0x80/0x160 Signed-off-by: Manish Rangankar Signed-off-by: Martin K. Petersen --- drivers/scsi/qedi/qedi_iscsi.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/qedi/qedi_iscsi.c b/drivers/scsi/qedi/qedi_iscsi.c index 19177931b84c..87f0af358b33 100644 --- a/drivers/scsi/qedi/qedi_iscsi.c +++ b/drivers/scsi/qedi/qedi_iscsi.c @@ -1224,8 +1224,12 @@ static int qedi_set_path(struct Scsi_Host *shost, struct iscsi_path *path_data) iscsi_cid = (u32)path_data->handle; qedi_ep = qedi->ep_tbl[iscsi_cid]; - QEDI_INFO(&qedi->dbg_ctx, QEDI_LOG_CONN, + QEDI_INFO(&qedi->dbg_ctx, QEDI_LOG_INFO, "iscsi_cid=0x%x, qedi_ep=%p\n", iscsi_cid, qedi_ep); + if (!qedi_ep) { + ret = -EINVAL; + goto set_path_exit; + } if (!is_valid_ether_addr(&path_data->mac_addr[0])) { QEDI_NOTICE(&qedi->dbg_ctx, "dst mac NOT VALID\n"); -- cgit v1.2.3 From 962ea1c0df6c5a36f4477aa4a10f4acc0f5f56bd Mon Sep 17 00:00:00 2001 From: "manish.rangankar@cavium.com" Date: Fri, 19 May 2017 01:33:19 -0700 Subject: scsi: qedi: Set firmware tcp msl timer value. Signed-off-by: Manish Rangankar Signed-off-by: Martin K. Petersen --- drivers/scsi/qedi/qedi_main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/qedi/qedi_main.c b/drivers/scsi/qedi/qedi_main.c index 997e3052a706..62ba0550b68c 100644 --- a/drivers/scsi/qedi/qedi_main.c +++ b/drivers/scsi/qedi/qedi_main.c @@ -827,6 +827,7 @@ static int qedi_set_iscsi_pf_param(struct qedi_ctx *qedi) qedi->pf_params.iscsi_pf_params.num_uhq_pages_in_ring = num_sq_pages; qedi->pf_params.iscsi_pf_params.num_queues = qedi->num_queues; qedi->pf_params.iscsi_pf_params.debug_mode = qedi_fw_debug; + qedi->pf_params.iscsi_pf_params.two_msl_timer = 4000; for (log_page_size = 0 ; log_page_size < 32 ; log_page_size++) { if ((1 << log_page_size) == PAGE_SIZE) -- cgit v1.2.3 From 3d61a3132212d6b1c8c6914700d5f6456712ac08 Mon Sep 17 00:00:00 2001 From: Nilesh Javali Date: Fri, 19 May 2017 01:33:20 -0700 Subject: scsi: qedi: set max_fin_rt default value max_fin_rt is the maximum re-transmission of FIN packets as part of the termination flow. After reaching this value the FW will send a single RESET. Signed-off-by: Nilesh Javali Signed-off-by: Manish Rangankar Signed-off-by: Martin K. Petersen --- drivers/scsi/qedi/qedi_main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/qedi/qedi_main.c b/drivers/scsi/qedi/qedi_main.c index 62ba0550b68c..09a294634bc7 100644 --- a/drivers/scsi/qedi/qedi_main.c +++ b/drivers/scsi/qedi/qedi_main.c @@ -828,6 +828,7 @@ static int qedi_set_iscsi_pf_param(struct qedi_ctx *qedi) qedi->pf_params.iscsi_pf_params.num_queues = qedi->num_queues; qedi->pf_params.iscsi_pf_params.debug_mode = qedi_fw_debug; qedi->pf_params.iscsi_pf_params.two_msl_timer = 4000; + qedi->pf_params.iscsi_pf_params.max_fin_rt = 2; for (log_page_size = 0 ; log_page_size < 32 ; log_page_size++) { if ((1 << log_page_size) == PAGE_SIZE) -- cgit v1.2.3 From b19775e4785996503b106e59d9d3a8839e677afd Mon Sep 17 00:00:00 2001 From: "manish.rangankar@cavium.com" Date: Fri, 19 May 2017 01:33:21 -0700 Subject: scsi: qedi: Fix endpoint NULL panic during recovery. Signed-off-by: Manish Rangankar Signed-off-by: Martin K. Petersen --- drivers/scsi/qedi/qedi_fw.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/scsi/qedi/qedi_fw.c b/drivers/scsi/qedi/qedi_fw.c index d6978cbc56f0..8bc7ee1a8ca8 100644 --- a/drivers/scsi/qedi/qedi_fw.c +++ b/drivers/scsi/qedi/qedi_fw.c @@ -1494,6 +1494,8 @@ static int qedi_send_iscsi_tmf(struct qedi_conn *qedi_conn, tmf_hdr = (struct iscsi_tm *)mtask->hdr; qedi_cmd = (struct qedi_cmd *)mtask->dd_data; ep = qedi_conn->ep; + if (!ep) + return -ENODEV; tid = qedi_get_task_idx(qedi); if (tid == -1) -- cgit v1.2.3 From e274086e473c0cbea18051ae0a78a05f8d658f47 Mon Sep 17 00:00:00 2001 From: Changbin Du Date: Mon, 22 May 2017 17:46:58 +0800 Subject: drm/i915/gvt: clean up unsubmited workloads before destroying kmem cache MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is to fix a memory leak issue caused by unfreed gvtg workload objects. Walk through the workload list and free all of the remained workloads before destroying kmem cache. [179.885211] INFO: Object 0xffff9cef10003b80 @offset=7040 [179.885657] kmem_cache_destroy gvt-g_vgpu_workload: Slab cache still has objects [179.886146] CPU: 2 PID: 2318 Comm: win_lucas Tainted: G    B   W       4.11.0+ #1 [179.887223] Call Trace: [179.887394] dump_stack+0x63/0x90 [179.887617] kmem_cache_destroy+0x1cf/0x1e0 [179.887960] intel_vgpu_clean_execlist+0x15/0x20 [i915] [179.888365] intel_gvt_destroy_vgpu+0x4c/0xd0 [i915] [179.888688] intel_vgpu_remove+0x2a/0x30 [kvmgt] [179.888988] mdev_device_remove_ops+0x23/0x50 [mdev] [179.889309] mdev_device_remove+0xe4/0x190 [mdev] [179.889615] remove_store+0x7d/0xb0 [mdev] [179.889885] dev_attr_store+0x18/0x30 [179.890129] sysfs_kf_write+0x37/0x40 [179.890371] kernfs_fop_write+0x107/0x180 [179.890632] __vfs_write+0x37/0x160 [179.890865] ? kmem_cache_alloc+0xd7/0x1b0 [179.891116] ? apparmor_file_permission+0x1a/0x20 [179.891372] ? security_file_permission+0x3b/0xc0 [179.891628] vfs_write+0xb8/0x1b0 [179.891812] SyS_write+0x55/0xc0 [179.891992] entry_SYSCALL_64_fastpath+0x1e/0xad Signed-off-by: Changbin Du Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/execlist.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/gvt/execlist.c b/drivers/gpu/drm/i915/gvt/execlist.c index dca989eb2d42..24fe04d6307b 100644 --- a/drivers/gpu/drm/i915/gvt/execlist.c +++ b/drivers/gpu/drm/i915/gvt/execlist.c @@ -779,8 +779,26 @@ static void init_vgpu_execlist(struct intel_vgpu *vgpu, int ring_id) vgpu_vreg(vgpu, ctx_status_ptr_reg) = ctx_status_ptr.dw; } +static void clean_workloads(struct intel_vgpu *vgpu, unsigned long engine_mask) +{ + struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; + struct intel_engine_cs *engine; + struct intel_vgpu_workload *pos, *n; + unsigned int tmp; + + /* free the unsubmited workloads in the queues. */ + for_each_engine_masked(engine, dev_priv, engine_mask, tmp) { + list_for_each_entry_safe(pos, n, + &vgpu->workload_q_head[engine->id], list) { + list_del_init(&pos->list); + free_workload(pos); + } + } +} + void intel_vgpu_clean_execlist(struct intel_vgpu *vgpu) { + clean_workloads(vgpu, ALL_ENGINES); kmem_cache_destroy(vgpu->workloads); } @@ -811,17 +829,9 @@ void intel_vgpu_reset_execlist(struct intel_vgpu *vgpu, { struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; struct intel_engine_cs *engine; - struct intel_vgpu_workload *pos, *n; unsigned int tmp; - for_each_engine_masked(engine, dev_priv, engine_mask, tmp) { - /* free the unsubmited workload in the queue */ - list_for_each_entry_safe(pos, n, - &vgpu->workload_q_head[engine->id], list) { - list_del_init(&pos->list); - free_workload(pos); - } - + clean_workloads(vgpu, engine_mask); + for_each_engine_masked(engine, dev_priv, engine_mask, tmp) init_vgpu_execlist(vgpu, engine->id); - } } -- cgit v1.2.3 From 75b61250bf687c686ba6850c34eccc1303b0b827 Mon Sep 17 00:00:00 2001 From: Varun Prakash Date: Tue, 16 May 2017 19:23:44 +0530 Subject: scsi: libcxgbi: fix skb use after free skb->data is assigned to task->hdr in cxgbi_conn_alloc_pdu(), skb gets freed after tx but task->hdr is still dereferenced in iscsi_tcp_task_xmit() to avoid this call skb_get() after allocating skb and free the skb in cxgbi_cleanup_task() or before allocating new skb in cxgbi_conn_alloc_pdu(). Signed-off-by: Varun Prakash Signed-off-by: Martin K. Petersen --- drivers/scsi/cxgbi/libcxgbi.c | 25 ++++++++++++++++++------- drivers/scsi/cxgbi/libcxgbi.h | 16 ++++++++-------- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c index bd7d39ecbd24..fb06974c88c1 100644 --- a/drivers/scsi/cxgbi/libcxgbi.c +++ b/drivers/scsi/cxgbi/libcxgbi.c @@ -1873,6 +1873,11 @@ int cxgbi_conn_alloc_pdu(struct iscsi_task *task, u8 opcode) tcp_task->dd_data = tdata; task->hdr = NULL; + if (tdata->skb) { + kfree_skb(tdata->skb); + tdata->skb = NULL; + } + if (SKB_MAX_HEAD(cdev->skb_tx_rsvd) > (512 * MAX_SKB_FRAGS) && (opcode == ISCSI_OP_SCSI_DATA_OUT || (opcode == ISCSI_OP_SCSI_CMD && @@ -1890,6 +1895,7 @@ int cxgbi_conn_alloc_pdu(struct iscsi_task *task, u8 opcode) return -ENOMEM; } + skb_get(tdata->skb); skb_reserve(tdata->skb, cdev->skb_tx_rsvd); task->hdr = (struct iscsi_hdr *)tdata->skb->data; task->hdr_max = SKB_TX_ISCSI_PDU_HEADER_MAX; /* BHS + AHS */ @@ -2035,9 +2041,9 @@ int cxgbi_conn_xmit_pdu(struct iscsi_task *task) unsigned int datalen; int err; - if (!skb) { + if (!skb || cxgbi_skcb_test_flag(skb, SKCBF_TX_DONE)) { log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_PDU_TX, - "task 0x%p, skb NULL.\n", task); + "task 0x%p, skb 0x%p\n", task, skb); return 0; } @@ -2050,7 +2056,6 @@ int cxgbi_conn_xmit_pdu(struct iscsi_task *task) } datalen = skb->data_len; - tdata->skb = NULL; /* write ppod first if using ofldq to write ppod */ if (ttinfo->flags & CXGBI_PPOD_INFO_FLAG_VALID) { @@ -2078,6 +2083,7 @@ int cxgbi_conn_xmit_pdu(struct iscsi_task *task) pdulen += ISCSI_DIGEST_SIZE; task->conn->txdata_octets += pdulen; + cxgbi_skcb_set_flag(skb, SKCBF_TX_DONE); return 0; } @@ -2086,7 +2092,6 @@ int cxgbi_conn_xmit_pdu(struct iscsi_task *task) "task 0x%p, skb 0x%p, len %u/%u, %d EAGAIN.\n", task, skb, skb->len, skb->data_len, err); /* reset skb to send when we are called again */ - tdata->skb = skb; return err; } @@ -2094,7 +2099,8 @@ int cxgbi_conn_xmit_pdu(struct iscsi_task *task) "itt 0x%x, skb 0x%p, len %u/%u, xmit err %d.\n", task->itt, skb, skb->len, skb->data_len, err); - kfree_skb(skb); + __kfree_skb(tdata->skb); + tdata->skb = NULL; iscsi_conn_printk(KERN_ERR, task->conn, "xmit err %d.\n", err); iscsi_conn_failure(task->conn, ISCSI_ERR_XMIT_FAILED); @@ -2113,8 +2119,10 @@ void cxgbi_cleanup_task(struct iscsi_task *task) tcp_task->dd_data = NULL; /* never reached the xmit task callout */ - if (tdata->skb) - __kfree_skb(tdata->skb); + if (tdata->skb) { + kfree_skb(tdata->skb); + tdata->skb = NULL; + } task_release_itt(task, task->hdr_itt); memset(tdata, 0, sizeof(*tdata)); @@ -2714,6 +2722,9 @@ EXPORT_SYMBOL_GPL(cxgbi_attr_is_visible); static int __init libcxgbi_init_module(void) { pr_info("%s", version); + + BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, cb) < + sizeof(struct cxgbi_skb_cb)); return 0; } diff --git a/drivers/scsi/cxgbi/libcxgbi.h b/drivers/scsi/cxgbi/libcxgbi.h index 18e0ea83d361..239462a75760 100644 --- a/drivers/scsi/cxgbi/libcxgbi.h +++ b/drivers/scsi/cxgbi/libcxgbi.h @@ -195,7 +195,8 @@ struct cxgbi_skb_rx_cb { }; struct cxgbi_skb_tx_cb { - void *l2t; + void *handle; + void *arp_err_handler; struct sk_buff *wr_next; }; @@ -203,6 +204,7 @@ enum cxgbi_skcb_flags { SKCBF_TX_NEED_HDR, /* packet needs a header */ SKCBF_TX_MEM_WRITE, /* memory write */ SKCBF_TX_FLAG_COMPL, /* wr completion flag */ + SKCBF_TX_DONE, /* skb tx done */ SKCBF_RX_COALESCED, /* received whole pdu */ SKCBF_RX_HDR, /* received pdu header */ SKCBF_RX_DATA, /* received pdu payload */ @@ -215,13 +217,13 @@ enum cxgbi_skcb_flags { }; struct cxgbi_skb_cb { - unsigned char ulp_mode; - unsigned long flags; - unsigned int seq; union { struct cxgbi_skb_rx_cb rx; struct cxgbi_skb_tx_cb tx; }; + unsigned char ulp_mode; + unsigned long flags; + unsigned int seq; }; #define CXGBI_SKB_CB(skb) ((struct cxgbi_skb_cb *)&((skb)->cb[0])) @@ -374,11 +376,9 @@ static inline void cxgbi_sock_enqueue_wr(struct cxgbi_sock *csk, cxgbi_skcb_tx_wr_next(skb) = NULL; /* * We want to take an extra reference since both us and the driver - * need to free the packet before it's really freed. We know there's - * just one user currently so we use atomic_set rather than skb_get - * to avoid the atomic op. + * need to free the packet before it's really freed. */ - atomic_set(&skb->users, 2); + skb_get(skb); if (!csk->wr_pending_head) csk->wr_pending_head = skb; -- cgit v1.2.3 From f3cdbe39b2ab0636dec0d5d43b54f1061ce7566c Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Wed, 17 May 2017 04:34:37 -0500 Subject: tcmu: fix crash during device removal We currently do tcmu_free_device ->tcmu_netlink_event(TCMU_CMD_REMOVED_DEVICE) -> uio_unregister_device -> kfree(tcmu_dev). The problem is that the kernel does not wait for userspace to do the close() on the uio device before freeing the tcmu_dev. We can then hit a race where the kernel frees the tcmu_dev before userspace does close() and so when close() -> release -> tcmu_release is done, we try to access a freed tcmu_dev. This patch made over the target-pending master branch moves the freeing of the tcmu_dev to when the last reference has been dropped. This also fixes a leak where if tcmu_configure_device was not called on a device we did not free udev->name which was allocated at tcmu_alloc_device time. Signed-off-by: Mike Christie Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_user.c | 46 ++++++++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c index 9045837f748b..beb5f098f32d 100644 --- a/drivers/target/target_core_user.c +++ b/drivers/target/target_core_user.c @@ -97,7 +97,7 @@ struct tcmu_hba { struct tcmu_dev { struct list_head node; - + struct kref kref; struct se_device se_dev; char *name; @@ -969,6 +969,7 @@ static struct se_device *tcmu_alloc_device(struct se_hba *hba, const char *name) udev = kzalloc(sizeof(struct tcmu_dev), GFP_KERNEL); if (!udev) return NULL; + kref_init(&udev->kref); udev->name = kstrdup(name, GFP_KERNEL); if (!udev->name) { @@ -1145,6 +1146,24 @@ static int tcmu_open(struct uio_info *info, struct inode *inode) return 0; } +static void tcmu_dev_call_rcu(struct rcu_head *p) +{ + struct se_device *dev = container_of(p, struct se_device, rcu_head); + struct tcmu_dev *udev = TCMU_DEV(dev); + + kfree(udev->uio_info.name); + kfree(udev->name); + kfree(udev); +} + +static void tcmu_dev_kref_release(struct kref *kref) +{ + struct tcmu_dev *udev = container_of(kref, struct tcmu_dev, kref); + struct se_device *dev = &udev->se_dev; + + call_rcu(&dev->rcu_head, tcmu_dev_call_rcu); +} + static int tcmu_release(struct uio_info *info, struct inode *inode) { struct tcmu_dev *udev = container_of(info, struct tcmu_dev, uio_info); @@ -1152,7 +1171,8 @@ static int tcmu_release(struct uio_info *info, struct inode *inode) clear_bit(TCMU_DEV_BIT_OPEN, &udev->flags); pr_debug("close\n"); - + /* release ref from configure */ + kref_put(&udev->kref, tcmu_dev_kref_release); return 0; } @@ -1272,6 +1292,12 @@ static int tcmu_configure_device(struct se_device *dev) dev->dev_attrib.hw_max_sectors = 128; dev->dev_attrib.hw_queue_depth = 128; + /* + * Get a ref incase userspace does a close on the uio device before + * LIO has initiated tcmu_free_device. + */ + kref_get(&udev->kref); + ret = tcmu_netlink_event(TCMU_CMD_ADDED_DEVICE, udev->uio_info.name, udev->uio_info.uio_dev->minor); if (ret) @@ -1284,11 +1310,13 @@ static int tcmu_configure_device(struct se_device *dev) return 0; err_netlink: + kref_put(&udev->kref, tcmu_dev_kref_release); uio_unregister_device(&udev->uio_info); err_register: vfree(udev->mb_addr); err_vzalloc: kfree(info->name); + info->name = NULL; return ret; } @@ -1302,14 +1330,6 @@ static int tcmu_check_and_free_pending_cmd(struct tcmu_cmd *cmd) return -EINVAL; } -static void tcmu_dev_call_rcu(struct rcu_head *p) -{ - struct se_device *dev = container_of(p, struct se_device, rcu_head); - struct tcmu_dev *udev = TCMU_DEV(dev); - - kfree(udev); -} - static bool tcmu_dev_configured(struct tcmu_dev *udev) { return udev->uio_info.uio_dev ? true : false; @@ -1364,10 +1384,10 @@ static void tcmu_free_device(struct se_device *dev) udev->uio_info.uio_dev->minor); uio_unregister_device(&udev->uio_info); - kfree(udev->uio_info.name); - kfree(udev->name); } - call_rcu(&dev->rcu_head, tcmu_dev_call_rcu); + + /* release ref from init */ + kref_put(&udev->kref, tcmu_dev_kref_release); } enum { -- cgit v1.2.3 From 0e774888675d7ec693379a228490ce611135cbc2 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Wed, 26 Apr 2017 10:50:02 +0900 Subject: thermal: qoriq: remove useless call for of_thermal_get_trip_points() Building this driver with W=1 reports: warning: variable 'trip' set but not used [-Wunused-but-set-variable] The call for of_thermal_get_trip_points() is useless. Signed-off-by: Masahiro Yamada Signed-off-by: Eduardo Valentin --- drivers/thermal/qoriq_thermal.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/thermal/qoriq_thermal.c b/drivers/thermal/qoriq_thermal.c index 644ba526d9ea..4362a69ac88d 100644 --- a/drivers/thermal/qoriq_thermal.c +++ b/drivers/thermal/qoriq_thermal.c @@ -195,7 +195,6 @@ static struct thermal_zone_of_device_ops tmu_tz_ops = { static int qoriq_tmu_probe(struct platform_device *pdev) { int ret; - const struct thermal_trip *trip; struct qoriq_tmu_data *data; struct device_node *np = pdev->dev.of_node; u32 site = 0; @@ -243,8 +242,6 @@ static int qoriq_tmu_probe(struct platform_device *pdev) goto err_tmu; } - trip = of_thermal_get_trip_points(data->tz); - /* Enable monitoring */ site |= 0x1 << (15 - data->sensor_id); tmu_write(data, site | TMR_ME | TMR_ALPF, &data->regs->tmr); -- cgit v1.2.3 From c4b379d0640a35b6c87200c3bdac0df2e6137022 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 8 May 2017 11:36:43 +0100 Subject: thermal: core: make thermal_emergency_poweroff static Making thermal_emergency_poweroff static fixes sparse warning: drivers/thermal/thermal_core.c:6: warning: symbol 'thermal_emergency_poweroff' was not declared. Should it be static? Fixes: ef1d87e06ab4 ("thermal: core: Add a back up thermal shutdown mechanism") Acked-by: Keerthy Signed-off-by: Colin Ian King Signed-off-by: Eduardo Valentin --- drivers/thermal/thermal_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index b21b9cc2c8d6..5a51c740e372 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -359,7 +359,7 @@ static DECLARE_DELAYED_WORK(thermal_emergency_poweroff_work, * This may be called from any critical situation to trigger a system shutdown * after a known period of time. By default this is not scheduled. */ -void thermal_emergency_poweroff(void) +static void thermal_emergency_poweroff(void) { int poweroff_delay_ms = CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS; /* -- cgit v1.2.3 From 748c23d88610b5df378d86e7192e4bd1f58adb35 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Wed, 26 Apr 2017 16:45:25 +0200 Subject: ti-soc-thermal: Use devm_kcalloc() in ti_bandgap_build() A multiplication for the size determination of a memory allocation indicated that an array data structure should be processed. Thus use the corresponding function "devm_kcalloc". This issue was detected by using the Coccinelle software. Acked-by: Keerthy Tested-by: Keerthy Signed-off-by: Markus Elfring Signed-off-by: Eduardo Valentin --- drivers/thermal/ti-soc-thermal/ti-bandgap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/thermal/ti-soc-thermal/ti-bandgap.c b/drivers/thermal/ti-soc-thermal/ti-bandgap.c index ba9c302454fb..f19cb7612a65 100644 --- a/drivers/thermal/ti-soc-thermal/ti-bandgap.c +++ b/drivers/thermal/ti-soc-thermal/ti-bandgap.c @@ -1224,8 +1224,8 @@ static struct ti_bandgap *ti_bandgap_build(struct platform_device *pdev) bgp->conf = of_id->data; /* register shadow for context save and restore */ - bgp->regval = devm_kzalloc(&pdev->dev, sizeof(*bgp->regval) * - bgp->conf->sensor_count, GFP_KERNEL); + bgp->regval = devm_kcalloc(&pdev->dev, bgp->conf->sensor_count, + sizeof(*bgp->regval), GFP_KERNEL); if (!bgp->regval) { dev_err(&pdev->dev, "Unable to allocate mem for driver ref\n"); return ERR_PTR(-ENOMEM); -- cgit v1.2.3 From 57e521151b56ee0c5164c442b7928c66711bfbc4 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Wed, 26 Apr 2017 17:03:07 +0200 Subject: ti-soc-thermal: Delete error messages for failed memory allocations in ti_bandgap_build() The script "checkpatch.pl" pointed information out like the following. WARNING: Possible unnecessary 'out of memory' message Thus remove such statements here. Link: http://events.linuxfoundation.org/sites/events/files/slides/LCJ16-Refactor_Strings-WSang_0.pdf Acked-by: Keerthy Tested-by: Keerthy Signed-off-by: Markus Elfring Signed-off-by: Eduardo Valentin --- drivers/thermal/ti-soc-thermal/ti-bandgap.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/thermal/ti-soc-thermal/ti-bandgap.c b/drivers/thermal/ti-soc-thermal/ti-bandgap.c index f19cb7612a65..109fb0a5f19f 100644 --- a/drivers/thermal/ti-soc-thermal/ti-bandgap.c +++ b/drivers/thermal/ti-soc-thermal/ti-bandgap.c @@ -1214,10 +1214,8 @@ static struct ti_bandgap *ti_bandgap_build(struct platform_device *pdev) } bgp = devm_kzalloc(&pdev->dev, sizeof(*bgp), GFP_KERNEL); - if (!bgp) { - dev_err(&pdev->dev, "Unable to allocate mem for driver ref\n"); + if (!bgp) return ERR_PTR(-ENOMEM); - } of_id = of_match_device(of_ti_bandgap_match, &pdev->dev); if (of_id) @@ -1226,10 +1224,8 @@ static struct ti_bandgap *ti_bandgap_build(struct platform_device *pdev) /* register shadow for context save and restore */ bgp->regval = devm_kcalloc(&pdev->dev, bgp->conf->sensor_count, sizeof(*bgp->regval), GFP_KERNEL); - if (!bgp->regval) { - dev_err(&pdev->dev, "Unable to allocate mem for driver ref\n"); + if (!bgp->regval) return ERR_PTR(-ENOMEM); - } i = 0; do { -- cgit v1.2.3 From 8b8656d64c0cce9007e062273190d8e97096f0ac Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Wed, 26 Apr 2017 17:11:28 +0200 Subject: ti-soc-thermal: Fix a typo in a comment line Add a missing character in this description for a function. Acked-by: Keerthy Tested-by: Keerthy Signed-off-by: Markus Elfring Signed-off-by: Eduardo Valentin --- drivers/thermal/ti-soc-thermal/ti-bandgap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/thermal/ti-soc-thermal/ti-bandgap.c b/drivers/thermal/ti-soc-thermal/ti-bandgap.c index 109fb0a5f19f..696ab3046b87 100644 --- a/drivers/thermal/ti-soc-thermal/ti-bandgap.c +++ b/drivers/thermal/ti-soc-thermal/ti-bandgap.c @@ -1010,7 +1010,7 @@ ti_bandgap_force_single_read(struct ti_bandgap *bgp, int id) } /** - * ti_bandgap_set_continous_mode() - One time enabling of continuous mode + * ti_bandgap_set_continuous_mode() - One time enabling of continuous mode * @bgp: pointer to struct ti_bandgap * * Call this function only if HAS(MODE_CONFIG) is set. As this driver may -- cgit v1.2.3 From a54c51863ed1294078a435151e625313b4365ac5 Mon Sep 17 00:00:00 2001 From: Jon Mason Date: Fri, 28 Apr 2017 16:11:30 -0400 Subject: thermal: broadcom: ns-thermal: default on iProc SoCs Tweak the Kconfig description to mention support for NSP and make the default on for iProc based platforms. Signed-off-by: Jon Mason Signed-off-by: Eduardo Valentin --- drivers/thermal/broadcom/Kconfig | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/thermal/broadcom/Kconfig b/drivers/thermal/broadcom/Kconfig index ab08af4654ef..42c098e86f84 100644 --- a/drivers/thermal/broadcom/Kconfig +++ b/drivers/thermal/broadcom/Kconfig @@ -9,8 +9,9 @@ config BCM2835_THERMAL config BCM_NS_THERMAL tristate "Northstar thermal driver" depends on ARCH_BCM_IPROC || COMPILE_TEST + default y if ARCH_BCM_IPROC help - Northstar is a family of SoCs that includes e.g. BCM4708, BCM47081, - BCM4709 and BCM47094. It contains DMU (Device Management Unit) block - with a thermal sensor that allows checking CPU temperature. This - driver provides support for it. + Support for the Northstar and Northstar Plus family of SoCs (e.g. + BCM4708, BCM4709, BCM5301x, BCM95852X, etc). It contains DMU (Device + Management Unit) block with a thermal sensor that allows checking CPU + temperature. -- cgit v1.2.3 From 0037ae47812b1f431cc602100d1d51f37d77b61e Mon Sep 17 00:00:00 2001 From: Alexander Sverdlin Date: Mon, 22 May 2017 16:05:22 +0200 Subject: dmaengine: ep93xx: Always start from BASE0 The current buffer is being reset to zero on device_free_chan_resources() but not on device_terminate_all(). It could happen that HW is restarted and expects BASE0 to be used, but the driver is not synchronized and will start from BASE1. One solution is to reset the buffer explicitly in m2p_hw_setup(). Signed-off-by: Alexander Sverdlin Cc: stable@vger.kernel.org Signed-off-by: Vinod Koul --- drivers/dma/ep93xx_dma.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/dma/ep93xx_dma.c b/drivers/dma/ep93xx_dma.c index d37e8dda8079..deb009c3121f 100644 --- a/drivers/dma/ep93xx_dma.c +++ b/drivers/dma/ep93xx_dma.c @@ -323,6 +323,8 @@ static int m2p_hw_setup(struct ep93xx_dma_chan *edmac) | M2P_CONTROL_ENABLE; m2p_set_control(edmac, control); + edmac->buffer = 0; + return 0; } -- cgit v1.2.3 From 98f9de366fccee7572c646af226b2d4b4841e3b5 Mon Sep 17 00:00:00 2001 From: Alexander Sverdlin Date: Mon, 22 May 2017 16:05:23 +0200 Subject: dmaengine: ep93xx: Don't drain the transfers in terminate_all() Draining the transfers in terminate_all callback happens with IRQs disabled, therefore induces huge latency: irqsoff latency trace v1.1.5 on 4.11.0 -------------------------------------------------------------------- latency: 39770 us, #57/57, CPU#0 | (M:preempt VP:0, KP:0, SP:0 HP:0) ----------------- | task: process-129 (uid:0 nice:0 policy:2 rt_prio:50) ----------------- => started at: _snd_pcm_stream_lock_irqsave => ended at: snd_pcm_stream_unlock_irqrestore _------=> CPU# / _-----=> irqs-off | / _----=> need-resched || / _---=> hardirq/softirq ||| / _--=> preempt-depth |||| / delay cmd pid ||||| time | caller \ / ||||| \ | / process-129 0d.s. 3us : _snd_pcm_stream_lock_irqsave process-129 0d.s1 9us : snd_pcm_stream_lock <-_snd_pcm_stream_lock_irqsave process-129 0d.s1 15us : preempt_count_add <-snd_pcm_stream_lock process-129 0d.s2 22us : preempt_count_add <-snd_pcm_stream_lock process-129 0d.s3 32us : snd_pcm_update_hw_ptr0 <-snd_pcm_period_elapsed process-129 0d.s3 41us : soc_pcm_pointer <-snd_pcm_update_hw_ptr0 process-129 0d.s3 50us : dmaengine_pcm_pointer <-soc_pcm_pointer process-129 0d.s3 58us+: snd_dmaengine_pcm_pointer_no_residue <-dmaengine_pcm_pointer process-129 0d.s3 96us : update_audio_tstamp <-snd_pcm_update_hw_ptr0 process-129 0d.s3 103us : snd_pcm_update_state <-snd_pcm_update_hw_ptr0 process-129 0d.s3 112us : xrun <-snd_pcm_update_state process-129 0d.s3 119us : snd_pcm_stop <-xrun process-129 0d.s3 126us : snd_pcm_action <-snd_pcm_stop process-129 0d.s3 134us : snd_pcm_action_single <-snd_pcm_action process-129 0d.s3 141us : snd_pcm_pre_stop <-snd_pcm_action_single process-129 0d.s3 150us : snd_pcm_do_stop <-snd_pcm_action_single process-129 0d.s3 157us : soc_pcm_trigger <-snd_pcm_do_stop process-129 0d.s3 166us : snd_dmaengine_pcm_trigger <-soc_pcm_trigger process-129 0d.s3 175us : ep93xx_dma_terminate_all <-snd_dmaengine_pcm_trigger process-129 0d.s3 182us : preempt_count_add <-ep93xx_dma_terminate_all process-129 0d.s4 189us*: m2p_hw_shutdown <-ep93xx_dma_terminate_all process-129 0d.s4 39472us : m2p_hw_setup <-ep93xx_dma_terminate_all ... rest skipped... process-129 0d.s. 40080us : => ep93xx_dma_tasklet => tasklet_action => __do_softirq => irq_exit => __handle_domain_irq => vic_handle_irq => __irq_usr => 0xb66c6668 Just abort the transfers and warn if the HW state is not what we expect. Move draining into device_synchronize callback. Signed-off-by: Alexander Sverdlin Cc: stable@vger.kernel.org Signed-off-by: Vinod Koul --- drivers/dma/ep93xx_dma.c | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/drivers/dma/ep93xx_dma.c b/drivers/dma/ep93xx_dma.c index deb009c3121f..ec240592f5c8 100644 --- a/drivers/dma/ep93xx_dma.c +++ b/drivers/dma/ep93xx_dma.c @@ -201,6 +201,7 @@ struct ep93xx_dma_engine { struct dma_device dma_dev; bool m2m; int (*hw_setup)(struct ep93xx_dma_chan *); + void (*hw_synchronize)(struct ep93xx_dma_chan *); void (*hw_shutdown)(struct ep93xx_dma_chan *); void (*hw_submit)(struct ep93xx_dma_chan *); int (*hw_interrupt)(struct ep93xx_dma_chan *); @@ -333,21 +334,27 @@ static inline u32 m2p_channel_state(struct ep93xx_dma_chan *edmac) return (readl(edmac->regs + M2P_STATUS) >> 4) & 0x3; } -static void m2p_hw_shutdown(struct ep93xx_dma_chan *edmac) +static void m2p_hw_synchronize(struct ep93xx_dma_chan *edmac) { + unsigned long flags; u32 control; + spin_lock_irqsave(&edmac->lock, flags); control = readl(edmac->regs + M2P_CONTROL); control &= ~(M2P_CONTROL_STALLINT | M2P_CONTROL_NFBINT); m2p_set_control(edmac, control); + spin_unlock_irqrestore(&edmac->lock, flags); while (m2p_channel_state(edmac) >= M2P_STATE_ON) - cpu_relax(); + schedule(); +} +static void m2p_hw_shutdown(struct ep93xx_dma_chan *edmac) +{ m2p_set_control(edmac, 0); - while (m2p_channel_state(edmac) == M2P_STATE_STALL) - cpu_relax(); + while (m2p_channel_state(edmac) != M2P_STATE_IDLE) + dev_warn(chan2dev(edmac), "M2P: Not yet IDLE\n"); } static void m2p_fill_desc(struct ep93xx_dma_chan *edmac) @@ -1162,6 +1169,26 @@ fail: return NULL; } +/** + * ep93xx_dma_synchronize - Synchronizes the termination of transfers to the + * current context. + * @chan: channel + * + * Synchronizes the DMA channel termination to the current context. When this + * function returns it is guaranteed that all transfers for previously issued + * descriptors have stopped and and it is safe to free the memory associated + * with them. Furthermore it is guaranteed that all complete callback functions + * for a previously submitted descriptor have finished running and it is safe to + * free resources accessed from within the complete callbacks. + */ +static void ep93xx_dma_synchronize(struct dma_chan *chan) +{ + struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan); + + if (edmac->edma->hw_synchronize) + edmac->edma->hw_synchronize(edmac); +} + /** * ep93xx_dma_terminate_all - terminate all transactions * @chan: channel @@ -1325,6 +1352,7 @@ static int __init ep93xx_dma_probe(struct platform_device *pdev) dma_dev->device_prep_slave_sg = ep93xx_dma_prep_slave_sg; dma_dev->device_prep_dma_cyclic = ep93xx_dma_prep_dma_cyclic; dma_dev->device_config = ep93xx_dma_slave_config; + dma_dev->device_synchronize = ep93xx_dma_synchronize; dma_dev->device_terminate_all = ep93xx_dma_terminate_all; dma_dev->device_issue_pending = ep93xx_dma_issue_pending; dma_dev->device_tx_status = ep93xx_dma_tx_status; @@ -1342,6 +1370,7 @@ static int __init ep93xx_dma_probe(struct platform_device *pdev) } else { dma_cap_set(DMA_PRIVATE, dma_dev->cap_mask); + edma->hw_synchronize = m2p_hw_synchronize; edma->hw_setup = m2p_hw_setup; edma->hw_shutdown = m2p_hw_shutdown; edma->hw_submit = m2p_hw_submit; -- cgit v1.2.3 From 7d4df089d77306914426a604c890175f91a9a459 Mon Sep 17 00:00:00 2001 From: Milian Wolff Date: Wed, 24 May 2017 15:21:23 +0900 Subject: perf report: Don't crash on invalid maps in `-g srcline` mode I just hit a segfault when doing `perf report -g srcline`. Valgrind pointed me at this code as the culprit: ==8359== Invalid read of size 8 ==8359== at 0x3096D9: map__rip_2objdump (map.c:430) ==8359== by 0x2FC1A3: match_chain_srcline (callchain.c:645) ==8359== by 0x2FC1A3: match_chain (callchain.c:700) ==8359== by 0x2FC1A3: append_chain (callchain.c:895) ==8359== by 0x2FC1A3: append_chain_children (callchain.c:846) ==8359== by 0x2FF719: callchain_append (callchain.c:944) ==8359== by 0x2FF719: hist_entry__append_callchain (callchain.c:1058) ==8359== by 0x32FA06: iter_add_single_cumulative_entry (hist.c:908) ==8359== by 0x33195C: hist_entry_iter__add (hist.c:1050) ==8359== by 0x258F65: process_sample_event (builtin-report.c:204) ==8359== by 0x30D60C: perf_session__deliver_event (session.c:1310) ==8359== by 0x30D60C: ordered_events__deliver_event (session.c:119) ==8359== by 0x310D12: __ordered_events__flush (ordered-events.c:210) ==8359== by 0x310D12: ordered_events__flush.part.3 (ordered-events.c:277) ==8359== by 0x30DD3C: perf_session__process_user_event (session.c:1349) ==8359== by 0x30DD3C: perf_session__process_event (session.c:1475) ==8359== by 0x30FC3C: __perf_session__process_events (session.c:1867) ==8359== by 0x30FC3C: perf_session__process_events (session.c:1921) ==8359== by 0x25A985: __cmd_report (builtin-report.c:575) ==8359== by 0x25A985: cmd_report (builtin-report.c:1054) ==8359== by 0x2B9A80: run_builtin (perf.c:296) ==8359== Address 0x70 is not stack'd, malloc'd or (recently) free'd This patch fixes the issue. Signed-off-by: Milian Wolff [ Remove dependency from another change ] Signed-off-by: Namhyung Kim Cc: Arnaldo Carvalho de Melo Cc: Arnaldo Carvalho de Melo Cc: David Ahern Cc: Jiri Olsa Cc: Jiri Olsa Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Yao Jin Cc: kernel-team@lge.com Link: http://lkml.kernel.org/r/20170524062129.32529-2-namhyung@kernel.org Signed-off-by: Ingo Molnar --- tools/perf/util/callchain.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index 81fc29ac798f..b4204b43ed58 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c @@ -621,14 +621,19 @@ enum match_result { static enum match_result match_chain_srcline(struct callchain_cursor_node *node, struct callchain_list *cnode) { - char *left = get_srcline(cnode->ms.map->dso, + char *left = NULL; + char *right = NULL; + enum match_result ret = MATCH_EQ; + int cmp; + + if (cnode->ms.map) + left = get_srcline(cnode->ms.map->dso, map__rip_2objdump(cnode->ms.map, cnode->ip), cnode->ms.sym, true, false); - char *right = get_srcline(node->map->dso, + if (node->map) + right = get_srcline(node->map->dso, map__rip_2objdump(node->map, node->ip), node->sym, true, false); - enum match_result ret = MATCH_EQ; - int cmp; if (left && right) cmp = strcmp(left, right); -- cgit v1.2.3 From b21cc97810932a551f7aac46f0b89c469c828b3f Mon Sep 17 00:00:00 2001 From: Milian Wolff Date: Wed, 24 May 2017 15:21:24 +0900 Subject: perf report: Fix memory leak in addr2line when called by addr2inlines When a filename was found in addr2line it was duplicated via strdup() but never freed. Now we pass NULL and handle this gracefully in addr2line. Detected by Valgrind: ==16331== 1,680 bytes in 21 blocks are definitely lost in loss record 148 of 220 ==16331== at 0x4C2AF1F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==16331== by 0x672FA69: strdup (in /usr/lib/libc-2.25.so) ==16331== by 0x52769F: addr2line (srcline.c:256) ==16331== by 0x52769F: addr2inlines (srcline.c:294) ==16331== by 0x52769F: dso__parse_addr_inlines (srcline.c:502) ==16331== by 0x574D7A: inline__fprintf (hist.c:41) ==16331== by 0x574D7A: ipchain__fprintf_graph (hist.c:147) ==16331== by 0x57518A: __callchain__fprintf_graph (hist.c:212) ==16331== by 0x5753CF: callchain__fprintf_graph.constprop.6 (hist.c:337) ==16331== by 0x57738E: hist_entry__fprintf (hist.c:628) ==16331== by 0x57738E: hists__fprintf (hist.c:882) ==16331== by 0x44A20F: perf_evlist__tty_browse_hists (builtin-report.c:399) ==16331== by 0x44A20F: report__browse_hists (builtin-report.c:491) ==16331== by 0x44A20F: __cmd_report (builtin-report.c:624) ==16331== by 0x44A20F: cmd_report (builtin-report.c:1054) ==16331== by 0x4A49CE: run_builtin (perf.c:296) ==16331== by 0x4A4CC0: handle_internal_command (perf.c:348) ==16331== by 0x434371: run_argv (perf.c:392) ==16331== by 0x434371: main (perf.c:530) Signed-off-by: Milian Wolff Signed-off-by: Namhyung Kim Cc: Arnaldo Carvalho de Melo Cc: Arnaldo Carvalho de Melo Cc: David Ahern Cc: Jiri Olsa Cc: Jiri Olsa Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Yao Jin Cc: kernel-team@lge.com Link: http://lkml.kernel.org/r/20170524062129.32529-3-namhyung@kernel.org Signed-off-by: Ingo Molnar --- tools/perf/util/srcline.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/tools/perf/util/srcline.c b/tools/perf/util/srcline.c index df051a52393c..5e376d64d59e 100644 --- a/tools/perf/util/srcline.c +++ b/tools/perf/util/srcline.c @@ -230,7 +230,10 @@ static int addr2line(const char *dso_name, u64 addr, bfd_map_over_sections(a2l->abfd, find_address_in_section, a2l); - if (a2l->found && unwind_inlines) { + if (!a2l->found) + return 0; + + if (unwind_inlines) { int cnt = 0; while (bfd_find_inliner_info(a2l->abfd, &a2l->filename, @@ -243,6 +246,8 @@ static int addr2line(const char *dso_name, u64 addr, a2l->line, node, dso) != 0) return 0; + // found at least one inline frame + ret = 1; } } @@ -252,14 +257,14 @@ static int addr2line(const char *dso_name, u64 addr, } } - if (a2l->found && a2l->filename) { - *file = strdup(a2l->filename); - *line = a2l->line; - - if (*file) - ret = 1; + if (file) { + *file = a2l->filename ? strdup(a2l->filename) : NULL; + ret = *file ? 1 : 0; } + if (line) + *line = a2l->line; + return ret; } @@ -278,8 +283,6 @@ void dso__free_a2l(struct dso *dso) static struct inline_node *addr2inlines(const char *dso_name, u64 addr, struct dso *dso) { - char *file = NULL; - unsigned int line = 0; struct inline_node *node; node = zalloc(sizeof(*node)); @@ -291,7 +294,7 @@ static struct inline_node *addr2inlines(const char *dso_name, u64 addr, INIT_LIST_HEAD(&node->val); node->addr = addr; - if (!addr2line(dso_name, addr, &file, &line, dso, TRUE, node)) + if (!addr2line(dso_name, addr, NULL, NULL, dso, TRUE, node)) goto out_free_inline_node; if (list_empty(&node->val)) -- cgit v1.2.3 From 1982ad48fc82c284a5cc55697a012d3357e84d01 Mon Sep 17 00:00:00 2001 From: Milian Wolff Date: Wed, 24 May 2017 15:21:25 +0900 Subject: perf report: Fix off-by-one for non-activation frames As the documentation for dwfl_frame_pc says, frames that are no activation frames need to have their program counter decremented by one to properly find the function of the caller. This fixes many cases where perf report currently attributes the cost to the next line. I.e. I have code like this: ~~~~~~~~~~~~~~~ #include #include using namespace std; int main() { this_thread::sleep_for(chrono::milliseconds(1000)); this_thread::sleep_for(chrono::milliseconds(100)); this_thread::sleep_for(chrono::milliseconds(10)); return 0; } ~~~~~~~~~~~~~~~ Now compile and record it: ~~~~~~~~~~~~~~~ g++ -std=c++11 -g -O2 test.cpp echo 1 | sudo tee /proc/sys/kernel/sched_schedstats perf record \ --event sched:sched_stat_sleep \ --event sched:sched_process_exit \ --event sched:sched_switch --call-graph=dwarf \ --output perf.data.raw \ ./a.out echo 0 | sudo tee /proc/sys/kernel/sched_schedstats perf inject --sched-stat --input perf.data.raw --output perf.data ~~~~~~~~~~~~~~~ Before this patch, the report clearly shows the off-by-one issue. Most notably, the last sleep invocation is incorrectly attributed to the "return 0;" line: ~~~~~~~~~~~~~~~ Overhead Source:Line ........ ........... 100.00% core.c:0 | ---__schedule core.c:0 schedule do_nanosleep hrtimer.c:0 hrtimer_nanosleep sys_nanosleep entry_SYSCALL_64_fastpath .tmp_entry_64.o:0 __nanosleep_nocancel .:0 std::this_thread::sleep_for > thread:323 | |--90.08%--main test.cpp:9 | __libc_start_main | _start | |--9.01%--main test.cpp:10 | __libc_start_main | _start | --0.91%--main test.cpp:13 __libc_start_main _start ~~~~~~~~~~~~~~~ With this patch here applied, the issue is fixed. The report becomes much more usable: ~~~~~~~~~~~~~~~ Overhead Source:Line ........ ........... 100.00% core.c:0 | ---__schedule core.c:0 schedule do_nanosleep hrtimer.c:0 hrtimer_nanosleep sys_nanosleep entry_SYSCALL_64_fastpath .tmp_entry_64.o:0 __nanosleep_nocancel .:0 std::this_thread::sleep_for > thread:323 | |--90.08%--main test.cpp:8 | __libc_start_main | _start | |--9.01%--main test.cpp:9 | __libc_start_main | _start | --0.91%--main test.cpp:10 __libc_start_main _start ~~~~~~~~~~~~~~~ Similarly it works for signal frames: ~~~~~~~~~~~~~~~ __noinline void bar(void) { volatile long cnt = 0; for (cnt = 0; cnt < 100000000; cnt++); } __noinline void foo(void) { bar(); } void sig_handler(int sig) { foo(); } int main(void) { signal(SIGUSR1, sig_handler); raise(SIGUSR1); foo(); return 0; } ~~~~~~~~~~~~~~~~ Before, the report wrongly points to `signal.c:29` after raise(): ~~~~~~~~~~~~~~~~ $ perf report --stdio --no-children -g srcline -s srcline ... 100.00% signal.c:11 | ---bar signal.c:11 | |--50.49%--main signal.c:29 | __libc_start_main | _start | --49.51%--0x33a8f raise .:0 main signal.c:29 __libc_start_main _start ~~~~~~~~~~~~~~~~ With this patch in, the issue is fixed and we instead get: ~~~~~~~~~~~~~~~~ 100.00% signal signal [.] bar | ---bar signal.c:11 | |--50.49%--main signal.c:29 | __libc_start_main | _start | --49.51%--0x33a8f raise .:0 main signal.c:27 __libc_start_main _start ~~~~~~~~~~~~~~~~ Note how this patch fixes this issue for both unwinding methods, i.e. both dwfl and libunwind. The former case is straight-forward thanks to dwfl_frame_pc(). For libunwind, we replace the functionality via unw_is_signal_frame() for any but the very first frame. Signed-off-by: Milian Wolff Signed-off-by: Namhyung Kim Cc: Arnaldo Carvalho de Melo Cc: Arnaldo Carvalho de Melo Cc: David Ahern Cc: Jiri Olsa Cc: Jiri Olsa Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Yao Jin Cc: kernel-team@lge.com Link: http://lkml.kernel.org/r/20170524062129.32529-4-namhyung@kernel.org Signed-off-by: Ingo Molnar --- tools/perf/util/unwind-libdw.c | 6 +++++- tools/perf/util/unwind-libunwind-local.c | 11 +++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/unwind-libdw.c b/tools/perf/util/unwind-libdw.c index f90e11a555b2..943a06291587 100644 --- a/tools/perf/util/unwind-libdw.c +++ b/tools/perf/util/unwind-libdw.c @@ -168,12 +168,16 @@ frame_callback(Dwfl_Frame *state, void *arg) { struct unwind_info *ui = arg; Dwarf_Addr pc; + bool isactivation; - if (!dwfl_frame_pc(state, &pc, NULL)) { + if (!dwfl_frame_pc(state, &pc, &isactivation)) { pr_err("%s", dwfl_errmsg(-1)); return DWARF_CB_ABORT; } + if (!isactivation) + --pc; + return entry(pc, ui) || !(--ui->max_stack) ? DWARF_CB_ABORT : DWARF_CB_OK; } diff --git a/tools/perf/util/unwind-libunwind-local.c b/tools/perf/util/unwind-libunwind-local.c index f8455bed6e65..672c2ada9357 100644 --- a/tools/perf/util/unwind-libunwind-local.c +++ b/tools/perf/util/unwind-libunwind-local.c @@ -692,6 +692,17 @@ static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb, while (!ret && (unw_step(&c) > 0) && i < max_stack) { unw_get_reg(&c, UNW_REG_IP, &ips[i]); + + /* + * Decrement the IP for any non-activation frames. + * this is required to properly find the srcline + * for caller frames. + * See also the documentation for dwfl_frame_pc(), + * which this code tries to replicate. + */ + if (unw_is_signal_frame(&c) <= 0) + --ips[i]; + ++i; } -- cgit v1.2.3 From 325fbff51f961491adff4037d0e0a94d6132bd9b Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Wed, 24 May 2017 15:21:26 +0900 Subject: perf script: Add --inline option for debugging The --inline option is to show inlined functions in callchains. For example: $ perf script a.out 5644 11611.467597: 309961 cycles:u: 790 main (/home/namhyung/tmp/perf/a.out) 20511 __libc_start_main (/usr/lib/libc-2.25.so) 8ba _start (/home/namhyung/tmp/perf/a.out) ... $ perf script --inline a.out 5644 11611.467597: 309961 cycles:u: 790 main (/home/namhyung/tmp/perf/a.out) std::__detail::_Adaptor, double>::operator() std::uniform_real_distribution::operator() > std::uniform_real_distribution::operator() > main 20511 __libc_start_main (/usr/lib/libc-2.25.so) 8ba _start (/home/namhyung/tmp/perf/a.out) ... Reviewed-and-tested-by: Milian Wolff Signed-off-by: Namhyung Kim Cc: Arnaldo Carvalho de Melo Cc: Arnaldo Carvalho de Melo Cc: Jin Yao Cc: Jiri Olsa Cc: Jiri Olsa Cc: Linus Torvalds Cc: Milian Wolff Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: kernel-team@lge.com Link: http://lkml.kernel.org/r/20170524062129.32529-5-namhyung@kernel.org Signed-off-by: Ingo Molnar --- tools/perf/Documentation/perf-script.txt | 4 ++++ tools/perf/builtin-script.c | 2 ++ tools/perf/util/evsel_fprintf.c | 33 ++++++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+) diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt index cb0eda3925e6..3517e204a2b3 100644 --- a/tools/perf/Documentation/perf-script.txt +++ b/tools/perf/Documentation/perf-script.txt @@ -311,6 +311,10 @@ include::itrace.txt[] Set the maximum number of program blocks to print with brstackasm for each sample. +--inline:: + If a callgraph address belongs to an inlined function, the inline stack + will be printed. Each entry has function name and file/line. + SEE ALSO -------- linkperf:perf-record[1], linkperf:perf-script-perl[1], diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index d05aec491cff..4761b0d7fcb5 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -2494,6 +2494,8 @@ int cmd_script(int argc, const char **argv) "Enable kernel symbol demangling"), OPT_STRING(0, "time", &script.time_str, "str", "Time span of interest (start,stop)"), + OPT_BOOLEAN(0, "inline", &symbol_conf.inline_name, + "Show inline function"), OPT_END() }; const char * const script_subcommands[] = { "record", "report", NULL }; diff --git a/tools/perf/util/evsel_fprintf.c b/tools/perf/util/evsel_fprintf.c index e415aee6a245..583f3a602506 100644 --- a/tools/perf/util/evsel_fprintf.c +++ b/tools/perf/util/evsel_fprintf.c @@ -7,6 +7,7 @@ #include "map.h" #include "strlist.h" #include "symbol.h" +#include "srcline.h" static int comma_fprintf(FILE *fp, bool *first, const char *fmt, ...) { @@ -168,6 +169,38 @@ int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment, if (!print_oneline) printed += fprintf(fp, "\n"); + if (symbol_conf.inline_name && node->map) { + struct inline_node *inode; + + addr = map__rip_2objdump(node->map, node->ip), + inode = dso__parse_addr_inlines(node->map->dso, addr); + + if (inode) { + struct inline_list *ilist; + + list_for_each_entry(ilist, &inode->val, list) { + if (print_arrow) + printed += fprintf(fp, " <-"); + + /* IP is same, just skip it */ + if (print_ip) + printed += fprintf(fp, "%c%16s", + s, ""); + if (print_sym) + printed += fprintf(fp, " %s", + ilist->funcname); + if (print_srcline) + printed += fprintf(fp, "\n %s:%d", + ilist->filename, + ilist->line_nr); + if (!print_oneline) + printed += fprintf(fp, "\n"); + } + + inline_node__delete(inode); + } + } + if (symbol_conf.bt_stop_list && node->sym && strlist__has_entry(symbol_conf.bt_stop_list, -- cgit v1.2.3 From 28071f51839e393f697d0d1df0b223a4bc373606 Mon Sep 17 00:00:00 2001 From: Milian Wolff Date: Wed, 24 May 2017 15:21:27 +0900 Subject: perf report: Always honor callchain order for inlined nodes So far, the inlined nodes where only reversed when we built perf against libbfd. If that was not available, the addr2line fallback code path was missing the inline_list__reverse call. Now we always add the nodes in the correct order within inline_list__append. This removes the need to reverse the list and also ensures that all callers construct the list in the right order. Signed-off-by: Milian Wolff Signed-off-by: Namhyung Kim Cc: Arnaldo Carvalho de Melo Cc: Arnaldo Carvalho de Melo Cc: David Ahern Cc: Jiri Olsa Cc: Jiri Olsa Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Yao Jin Cc: kernel-team@lge.com Link: http://lkml.kernel.org/r/20170524062129.32529-6-namhyung@kernel.org Signed-off-by: Ingo Molnar --- tools/perf/util/srcline.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/tools/perf/util/srcline.c b/tools/perf/util/srcline.c index 5e376d64d59e..6af0364cad06 100644 --- a/tools/perf/util/srcline.c +++ b/tools/perf/util/srcline.c @@ -56,7 +56,10 @@ static int inline_list__append(char *filename, char *funcname, int line_nr, } } - list_add_tail(&ilist->list, &node->val); + if (callchain_param.order == ORDER_CALLEE) + list_add_tail(&ilist->list, &node->val); + else + list_add(&ilist->list, &node->val); return 0; } @@ -200,14 +203,6 @@ static void addr2line_cleanup(struct a2l_data *a2l) #define MAX_INLINE_NEST 1024 -static void inline_list__reverse(struct inline_node *node) -{ - struct inline_list *ilist, *n; - - list_for_each_entry_safe_reverse(ilist, n, &node->val, list) - list_move_tail(&ilist->list, &node->val); -} - static int addr2line(const char *dso_name, u64 addr, char **file, unsigned int *line, struct dso *dso, bool unwind_inlines, struct inline_node *node) @@ -250,11 +245,6 @@ static int addr2line(const char *dso_name, u64 addr, ret = 1; } } - - if ((node != NULL) && - (callchain_param.order != ORDER_CALLEE)) { - inline_list__reverse(node); - } } if (file) { -- cgit v1.2.3 From 4d53b9d546f9f4505e6e3d58c8eed894d6f684e7 Mon Sep 17 00:00:00 2001 From: Milian Wolff Date: Wed, 24 May 2017 15:21:28 +0900 Subject: perf report: Do not drop last inlined frame The very last inlined frame, i.e. the one furthest away from the non-inlined frame, was silently dropped. This is apparent when comparing the output of `perf script` and `addr2line`: ~~~~~~ $ perf script --inline ... a.out 26722 80836.309329: 72425 cycles: 21561 __hypot_finite (/usr/lib/libm-2.25.so) ace3 hypot (/usr/lib/libm-2.25.so) a4a main (a.out) std::abs std::_Norm_helper::_S_do_it std::norm main 20510 __libc_start_main (/usr/lib/libc-2.25.so) bd9 _start (a.out) $ addr2line -a -f -i -e /tmp/a.out a4a | c++filt 0x0000000000000a4a std::__complex_abs(doublecomplex ) /usr/include/c++/6.3.1/complex:589 double std::abs(std::complex const&) /usr/include/c++/6.3.1/complex:597 double std::_Norm_helper::_S_do_it(std::complex const&) /usr/include/c++/6.3.1/complex:654 double std::norm(std::complex const&) /usr/include/c++/6.3.1/complex:664 main /tmp/inlining.cpp:14 ~~~~~ Note how `std::__complex_abs` is missing from the `perf script` output. This is similarly showing up in `perf report`. The patch here fixes this issue, and the output becomes: ~~~~~ a.out 26722 80836.309329: 72425 cycles: 21561 __hypot_finite (/usr/lib/libm-2.25.so) ace3 hypot (/usr/lib/libm-2.25.so) a4a main (a.out) std::__complex_abs std::abs std::_Norm_helper::_S_do_it std::norm main 20510 __libc_start_main (/usr/lib/libc-2.25.so) bd9 _start (a.out) ~~~~~ Signed-off-by: Milian Wolff Signed-off-by: Namhyung Kim Cc: Arnaldo Carvalho de Melo Cc: Arnaldo Carvalho de Melo Cc: David Ahern Cc: Jiri Olsa Cc: Jiri Olsa Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Yao Jin Cc: kernel-team@lge.com Link: http://lkml.kernel.org/r/20170524062129.32529-7-namhyung@kernel.org Signed-off-by: Ingo Molnar --- tools/perf/util/srcline.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/tools/perf/util/srcline.c b/tools/perf/util/srcline.c index 6af0364cad06..ebc88a74e67b 100644 --- a/tools/perf/util/srcline.c +++ b/tools/perf/util/srcline.c @@ -203,6 +203,16 @@ static void addr2line_cleanup(struct a2l_data *a2l) #define MAX_INLINE_NEST 1024 +static int inline_list__append_dso_a2l(struct dso *dso, + struct inline_node *node) +{ + struct a2l_data *a2l = dso->a2l; + char *funcname = a2l->funcname ? strdup(a2l->funcname) : NULL; + char *filename = a2l->filename ? strdup(a2l->filename) : NULL; + + return inline_list__append(filename, funcname, a2l->line, node, dso); +} + static int addr2line(const char *dso_name, u64 addr, char **file, unsigned int *line, struct dso *dso, bool unwind_inlines, struct inline_node *node) @@ -231,15 +241,15 @@ static int addr2line(const char *dso_name, u64 addr, if (unwind_inlines) { int cnt = 0; + if (node && inline_list__append_dso_a2l(dso, node)) + return 0; + while (bfd_find_inliner_info(a2l->abfd, &a2l->filename, &a2l->funcname, &a2l->line) && cnt++ < MAX_INLINE_NEST) { if (node != NULL) { - if (inline_list__append(strdup(a2l->filename), - strdup(a2l->funcname), - a2l->line, node, - dso) != 0) + if (inline_list__append_dso_a2l(dso, node)) return 0; // found at least one inline frame ret = 1; -- cgit v1.2.3 From 7111ffff60a68f55d864200cd6c7677319e5c242 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Wed, 24 May 2017 15:21:29 +0900 Subject: perf tools: Put caller above callee in --children mode The __hpp__sort_acc() sorts entries using callchain depth in order to put callers above in children mode. But it assumed the callchain order was callee-first. Now default (for children) is caller-first so the order of entries is reverted. For example, consider following case: $ perf report --no-children ..l # Overhead Command Shared Object Symbol # ........ ....... ................... .......................... # 99.44% a.out a.out [.] main | ---main __libc_start_main _start Then children mode should show 'start' above '__libc_start_main' since it's the caller (parent) of the __libc_start_main. But it's reversed: # Children Self Command Shared Object Symbol # ........ ........ ....... ............... ..................... # 99.61% 0.00% a.out libc-2.25.so [.] __libc_start_main 99.61% 0.00% a.out a.out [.] _start 99.54% 99.44% a.out a.out [.] main This patch fixes it. # Children Self Command Shared Object Symbol # ........ ........ ....... ............... ..................... # 99.61% 0.00% a.out a.out [.] _start 99.61% 0.00% a.out libc-2.25.so [.] __libc_start_main 99.54% 99.44% a.out a.out [.] main Signed-off-by: Namhyung Kim Acked-by: Jiri Olsa Cc: Arnaldo Carvalho de Melo Cc: Arnaldo Carvalho de Melo Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Linus Torvalds Cc: Milian Wolff Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Yao Jin Cc: kernel-team@lge.com Link: http://lkml.kernel.org/r/20170524062129.32529-8-namhyung@kernel.org Signed-off-by: Ingo Molnar --- tools/perf/ui/hist.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index 59addd52d9cd..ddb2c6fbdf91 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -210,6 +210,8 @@ static int __hpp__sort_acc(struct hist_entry *a, struct hist_entry *b, return 0; ret = b->callchain->max_depth - a->callchain->max_depth; + if (callchain_param.order == ORDER_CALLER) + ret = -ret; } return ret; } -- cgit v1.2.3 From 6e30437bd42c4d4e9cfc4c40efda00eb83a11cde Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 24 May 2017 08:57:21 +0200 Subject: tools/include: Sync kernel ABI headers with tooling headers Sync (copy) the following v4.12 kernel headers to the tooling headers: arch/x86/include/asm/disabled-features.h: arch/x86/include/uapi/asm/kvm.h: arch/powerpc/include/uapi/asm/kvm.h: arch/s390/include/uapi/asm/kvm.h: arch/arm/include/uapi/asm/kvm.h: arch/arm64/include/uapi/asm/kvm.h: - 'struct kvm_sync_regs' got changed in an ABI-incompatible way, fortunately none of the (in-kernel) tooling relied on it - new KVM_DEV calls added arch/x86/include/asm/required-features.h: - 5-level paging hardware ABI detail added arch/x86/include/asm/cpufeatures.h: - new CPU feature added arch/x86/include/uapi/asm/vmx.h: - new VMX exit conditions None of the changes requires fixes in the tooling source code. This addresses the following warnings: Warning: include/uapi/linux/stat.h differs from kernel Warning: arch/x86/include/asm/disabled-features.h differs from kernel Warning: arch/x86/include/asm/required-features.h differs from kernel Warning: arch/x86/include/asm/cpufeatures.h differs from kernel Warning: arch/x86/include/uapi/asm/kvm.h differs from kernel Warning: arch/x86/include/uapi/asm/vmx.h differs from kernel Warning: arch/powerpc/include/uapi/asm/kvm.h differs from kernel Warning: arch/s390/include/uapi/asm/kvm.h differs from kernel Warning: arch/arm/include/uapi/asm/kvm.h differs from kernel Warning: arch/arm64/include/uapi/asm/kvm.h differs from kernel Cc: Arnaldo Carvalho de Melo Cc: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: Jiri Olsa Cc: Linus Torvalds Cc: Milian Wolff Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Yao Jin Cc: kernel-team@lge.com Link: http://lkml.kernel.org/r/20170524065721.j2mlch6bgk5klgbc@gmail.com Signed-off-by: Ingo Molnar --- tools/arch/arm/include/uapi/asm/kvm.h | 10 +++++++++- tools/arch/arm64/include/uapi/asm/kvm.h | 10 +++++++++- tools/arch/powerpc/include/uapi/asm/kvm.h | 3 +++ tools/arch/s390/include/uapi/asm/kvm.h | 26 ++++++++++++++++++++++++-- tools/arch/x86/include/asm/cpufeatures.h | 2 ++ tools/arch/x86/include/asm/disabled-features.h | 8 +++++++- tools/arch/x86/include/asm/required-features.h | 8 +++++++- tools/arch/x86/include/uapi/asm/kvm.h | 3 +++ tools/arch/x86/include/uapi/asm/vmx.h | 25 ++++++++++++++++++------- tools/include/uapi/linux/stat.h | 8 ++------ 10 files changed, 84 insertions(+), 19 deletions(-) diff --git a/tools/arch/arm/include/uapi/asm/kvm.h b/tools/arch/arm/include/uapi/asm/kvm.h index 6ebd3e6a1fd1..5e3c673fa3f4 100644 --- a/tools/arch/arm/include/uapi/asm/kvm.h +++ b/tools/arch/arm/include/uapi/asm/kvm.h @@ -27,6 +27,8 @@ #define __KVM_HAVE_IRQ_LINE #define __KVM_HAVE_READONLY_MEM +#define KVM_COALESCED_MMIO_PAGE_OFFSET 1 + #define KVM_REG_SIZE(id) \ (1U << (((id) & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT)) @@ -114,6 +116,8 @@ struct kvm_debug_exit_arch { }; struct kvm_sync_regs { + /* Used with KVM_CAP_ARM_USER_IRQ */ + __u64 device_irq_level; }; struct kvm_arch_memory_slot { @@ -192,13 +196,17 @@ struct kvm_arch_memory_slot { #define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5 #define KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS 6 #define KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO 7 +#define KVM_DEV_ARM_VGIC_GRP_ITS_REGS 8 #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT 10 #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK \ (0x3fffffULL << KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT) #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK 0x3ff #define VGIC_LEVEL_INFO_LINE_LEVEL 0 -#define KVM_DEV_ARM_VGIC_CTRL_INIT 0 +#define KVM_DEV_ARM_VGIC_CTRL_INIT 0 +#define KVM_DEV_ARM_ITS_SAVE_TABLES 1 +#define KVM_DEV_ARM_ITS_RESTORE_TABLES 2 +#define KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES 3 /* KVM_IRQ_LINE irq field index values */ #define KVM_ARM_IRQ_TYPE_SHIFT 24 diff --git a/tools/arch/arm64/include/uapi/asm/kvm.h b/tools/arch/arm64/include/uapi/asm/kvm.h index c2860358ae3e..70eea2ecc663 100644 --- a/tools/arch/arm64/include/uapi/asm/kvm.h +++ b/tools/arch/arm64/include/uapi/asm/kvm.h @@ -39,6 +39,8 @@ #define __KVM_HAVE_IRQ_LINE #define __KVM_HAVE_READONLY_MEM +#define KVM_COALESCED_MMIO_PAGE_OFFSET 1 + #define KVM_REG_SIZE(id) \ (1U << (((id) & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT)) @@ -143,6 +145,8 @@ struct kvm_debug_exit_arch { #define KVM_GUESTDBG_USE_HW (1 << 17) struct kvm_sync_regs { + /* Used with KVM_CAP_ARM_USER_IRQ */ + __u64 device_irq_level; }; struct kvm_arch_memory_slot { @@ -212,13 +216,17 @@ struct kvm_arch_memory_slot { #define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5 #define KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS 6 #define KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO 7 +#define KVM_DEV_ARM_VGIC_GRP_ITS_REGS 8 #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT 10 #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK \ (0x3fffffULL << KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT) #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK 0x3ff #define VGIC_LEVEL_INFO_LINE_LEVEL 0 -#define KVM_DEV_ARM_VGIC_CTRL_INIT 0 +#define KVM_DEV_ARM_VGIC_CTRL_INIT 0 +#define KVM_DEV_ARM_ITS_SAVE_TABLES 1 +#define KVM_DEV_ARM_ITS_RESTORE_TABLES 2 +#define KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES 3 /* Device Control API on vcpu fd */ #define KVM_ARM_VCPU_PMU_V3_CTRL 0 diff --git a/tools/arch/powerpc/include/uapi/asm/kvm.h b/tools/arch/powerpc/include/uapi/asm/kvm.h index 4edbe4bb0e8b..07fbeb927834 100644 --- a/tools/arch/powerpc/include/uapi/asm/kvm.h +++ b/tools/arch/powerpc/include/uapi/asm/kvm.h @@ -29,6 +29,9 @@ #define __KVM_HAVE_IRQ_LINE #define __KVM_HAVE_GUEST_DEBUG +/* Not always available, but if it is, this is the correct offset. */ +#define KVM_COALESCED_MMIO_PAGE_OFFSET 1 + struct kvm_regs { __u64 pc; __u64 cr; diff --git a/tools/arch/s390/include/uapi/asm/kvm.h b/tools/arch/s390/include/uapi/asm/kvm.h index 7f4fd65e9208..3dd2a1d308dd 100644 --- a/tools/arch/s390/include/uapi/asm/kvm.h +++ b/tools/arch/s390/include/uapi/asm/kvm.h @@ -26,6 +26,8 @@ #define KVM_DEV_FLIC_ADAPTER_REGISTER 6 #define KVM_DEV_FLIC_ADAPTER_MODIFY 7 #define KVM_DEV_FLIC_CLEAR_IO_IRQ 8 +#define KVM_DEV_FLIC_AISM 9 +#define KVM_DEV_FLIC_AIRQ_INJECT 10 /* * We can have up to 4*64k pending subchannels + 8 adapter interrupts, * as well as up to ASYNC_PF_PER_VCPU*KVM_MAX_VCPUS pfault done interrupts. @@ -41,7 +43,14 @@ struct kvm_s390_io_adapter { __u8 isc; __u8 maskable; __u8 swap; - __u8 pad; + __u8 flags; +}; + +#define KVM_S390_ADAPTER_SUPPRESSIBLE 0x01 + +struct kvm_s390_ais_req { + __u8 isc; + __u16 mode; }; #define KVM_S390_IO_ADAPTER_MASK 1 @@ -110,6 +119,7 @@ struct kvm_s390_vm_cpu_machine { #define KVM_S390_VM_CPU_FEAT_CMMA 10 #define KVM_S390_VM_CPU_FEAT_PFMFI 11 #define KVM_S390_VM_CPU_FEAT_SIGPIF 12 +#define KVM_S390_VM_CPU_FEAT_KSS 13 struct kvm_s390_vm_cpu_feat { __u64 feat[16]; }; @@ -198,6 +208,10 @@ struct kvm_guest_debug_arch { #define KVM_SYNC_VRS (1UL << 6) #define KVM_SYNC_RICCB (1UL << 7) #define KVM_SYNC_FPRS (1UL << 8) +#define KVM_SYNC_GSCB (1UL << 9) +/* length and alignment of the sdnx as a power of two */ +#define SDNXC 8 +#define SDNXL (1UL << SDNXC) /* definition of registers in kvm_run */ struct kvm_sync_regs { __u64 prefix; /* prefix register */ @@ -218,8 +232,16 @@ struct kvm_sync_regs { }; __u8 reserved[512]; /* for future vector expansion */ __u32 fpc; /* valid on KVM_SYNC_VRS or KVM_SYNC_FPRS */ - __u8 padding[52]; /* riccb needs to be 64byte aligned */ + __u8 padding1[52]; /* riccb needs to be 64byte aligned */ __u8 riccb[64]; /* runtime instrumentation controls block */ + __u8 padding2[192]; /* sdnx needs to be 256byte aligned */ + union { + __u8 sdnx[SDNXL]; /* state description annex */ + struct { + __u64 reserved1[2]; + __u64 gscb[4]; + }; + }; }; #define KVM_REG_S390_TODPR (KVM_REG_S390 | KVM_REG_SIZE_U32 | 0x1) diff --git a/tools/arch/x86/include/asm/cpufeatures.h b/tools/arch/x86/include/asm/cpufeatures.h index 0fe00446f9ca..2701e5f8145b 100644 --- a/tools/arch/x86/include/asm/cpufeatures.h +++ b/tools/arch/x86/include/asm/cpufeatures.h @@ -202,6 +202,8 @@ #define X86_FEATURE_AVX512_4VNNIW (7*32+16) /* AVX-512 Neural Network Instructions */ #define X86_FEATURE_AVX512_4FMAPS (7*32+17) /* AVX-512 Multiply Accumulation Single precision */ +#define X86_FEATURE_MBA ( 7*32+18) /* Memory Bandwidth Allocation */ + /* Virtualization flags: Linux defined, word 8 */ #define X86_FEATURE_TPR_SHADOW ( 8*32+ 0) /* Intel TPR Shadow */ #define X86_FEATURE_VNMI ( 8*32+ 1) /* Intel Virtual NMI */ diff --git a/tools/arch/x86/include/asm/disabled-features.h b/tools/arch/x86/include/asm/disabled-features.h index 85599ad4d024..5dff775af7cd 100644 --- a/tools/arch/x86/include/asm/disabled-features.h +++ b/tools/arch/x86/include/asm/disabled-features.h @@ -36,6 +36,12 @@ # define DISABLE_OSPKE (1<<(X86_FEATURE_OSPKE & 31)) #endif /* CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS */ +#ifdef CONFIG_X86_5LEVEL +# define DISABLE_LA57 0 +#else +# define DISABLE_LA57 (1<<(X86_FEATURE_LA57 & 31)) +#endif + /* * Make sure to add features to the correct mask */ @@ -55,7 +61,7 @@ #define DISABLED_MASK13 0 #define DISABLED_MASK14 0 #define DISABLED_MASK15 0 -#define DISABLED_MASK16 (DISABLE_PKU|DISABLE_OSPKE) +#define DISABLED_MASK16 (DISABLE_PKU|DISABLE_OSPKE|DISABLE_LA57) #define DISABLED_MASK17 0 #define DISABLED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 18) diff --git a/tools/arch/x86/include/asm/required-features.h b/tools/arch/x86/include/asm/required-features.h index fac9a5c0abe9..d91ba04dd007 100644 --- a/tools/arch/x86/include/asm/required-features.h +++ b/tools/arch/x86/include/asm/required-features.h @@ -53,6 +53,12 @@ # define NEED_MOVBE 0 #endif +#ifdef CONFIG_X86_5LEVEL +# define NEED_LA57 (1<<(X86_FEATURE_LA57 & 31)) +#else +# define NEED_LA57 0 +#endif + #ifdef CONFIG_X86_64 #ifdef CONFIG_PARAVIRT /* Paravirtualized systems may not have PSE or PGE available */ @@ -98,7 +104,7 @@ #define REQUIRED_MASK13 0 #define REQUIRED_MASK14 0 #define REQUIRED_MASK15 0 -#define REQUIRED_MASK16 0 +#define REQUIRED_MASK16 (NEED_LA57) #define REQUIRED_MASK17 0 #define REQUIRED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 18) diff --git a/tools/arch/x86/include/uapi/asm/kvm.h b/tools/arch/x86/include/uapi/asm/kvm.h index 739c0c594022..c2824d02ba37 100644 --- a/tools/arch/x86/include/uapi/asm/kvm.h +++ b/tools/arch/x86/include/uapi/asm/kvm.h @@ -9,6 +9,9 @@ #include #include +#define KVM_PIO_PAGE_OFFSET 1 +#define KVM_COALESCED_MMIO_PAGE_OFFSET 2 + #define DE_VECTOR 0 #define DB_VECTOR 1 #define BP_VECTOR 3 diff --git a/tools/arch/x86/include/uapi/asm/vmx.h b/tools/arch/x86/include/uapi/asm/vmx.h index 14458658e988..690a2dcf4078 100644 --- a/tools/arch/x86/include/uapi/asm/vmx.h +++ b/tools/arch/x86/include/uapi/asm/vmx.h @@ -76,7 +76,11 @@ #define EXIT_REASON_WBINVD 54 #define EXIT_REASON_XSETBV 55 #define EXIT_REASON_APIC_WRITE 56 +#define EXIT_REASON_RDRAND 57 #define EXIT_REASON_INVPCID 58 +#define EXIT_REASON_VMFUNC 59 +#define EXIT_REASON_ENCLS 60 +#define EXIT_REASON_RDSEED 61 #define EXIT_REASON_PML_FULL 62 #define EXIT_REASON_XSAVES 63 #define EXIT_REASON_XRSTORS 64 @@ -90,6 +94,7 @@ { EXIT_REASON_TASK_SWITCH, "TASK_SWITCH" }, \ { EXIT_REASON_CPUID, "CPUID" }, \ { EXIT_REASON_HLT, "HLT" }, \ + { EXIT_REASON_INVD, "INVD" }, \ { EXIT_REASON_INVLPG, "INVLPG" }, \ { EXIT_REASON_RDPMC, "RDPMC" }, \ { EXIT_REASON_RDTSC, "RDTSC" }, \ @@ -108,6 +113,8 @@ { EXIT_REASON_IO_INSTRUCTION, "IO_INSTRUCTION" }, \ { EXIT_REASON_MSR_READ, "MSR_READ" }, \ { EXIT_REASON_MSR_WRITE, "MSR_WRITE" }, \ + { EXIT_REASON_INVALID_STATE, "INVALID_STATE" }, \ + { EXIT_REASON_MSR_LOAD_FAIL, "MSR_LOAD_FAIL" }, \ { EXIT_REASON_MWAIT_INSTRUCTION, "MWAIT_INSTRUCTION" }, \ { EXIT_REASON_MONITOR_TRAP_FLAG, "MONITOR_TRAP_FLAG" }, \ { EXIT_REASON_MONITOR_INSTRUCTION, "MONITOR_INSTRUCTION" }, \ @@ -115,20 +122,24 @@ { EXIT_REASON_MCE_DURING_VMENTRY, "MCE_DURING_VMENTRY" }, \ { EXIT_REASON_TPR_BELOW_THRESHOLD, "TPR_BELOW_THRESHOLD" }, \ { EXIT_REASON_APIC_ACCESS, "APIC_ACCESS" }, \ - { EXIT_REASON_GDTR_IDTR, "GDTR_IDTR" }, \ - { EXIT_REASON_LDTR_TR, "LDTR_TR" }, \ + { EXIT_REASON_EOI_INDUCED, "EOI_INDUCED" }, \ + { EXIT_REASON_GDTR_IDTR, "GDTR_IDTR" }, \ + { EXIT_REASON_LDTR_TR, "LDTR_TR" }, \ { EXIT_REASON_EPT_VIOLATION, "EPT_VIOLATION" }, \ { EXIT_REASON_EPT_MISCONFIG, "EPT_MISCONFIG" }, \ { EXIT_REASON_INVEPT, "INVEPT" }, \ + { EXIT_REASON_RDTSCP, "RDTSCP" }, \ { EXIT_REASON_PREEMPTION_TIMER, "PREEMPTION_TIMER" }, \ + { EXIT_REASON_INVVPID, "INVVPID" }, \ { EXIT_REASON_WBINVD, "WBINVD" }, \ + { EXIT_REASON_XSETBV, "XSETBV" }, \ { EXIT_REASON_APIC_WRITE, "APIC_WRITE" }, \ - { EXIT_REASON_EOI_INDUCED, "EOI_INDUCED" }, \ - { EXIT_REASON_INVALID_STATE, "INVALID_STATE" }, \ - { EXIT_REASON_MSR_LOAD_FAIL, "MSR_LOAD_FAIL" }, \ - { EXIT_REASON_INVD, "INVD" }, \ - { EXIT_REASON_INVVPID, "INVVPID" }, \ + { EXIT_REASON_RDRAND, "RDRAND" }, \ { EXIT_REASON_INVPCID, "INVPCID" }, \ + { EXIT_REASON_VMFUNC, "VMFUNC" }, \ + { EXIT_REASON_ENCLS, "ENCLS" }, \ + { EXIT_REASON_RDSEED, "RDSEED" }, \ + { EXIT_REASON_PML_FULL, "PML_FULL" }, \ { EXIT_REASON_XSAVES, "XSAVES" }, \ { EXIT_REASON_XRSTORS, "XRSTORS" } diff --git a/tools/include/uapi/linux/stat.h b/tools/include/uapi/linux/stat.h index d538897b8e08..17b10304c393 100644 --- a/tools/include/uapi/linux/stat.h +++ b/tools/include/uapi/linux/stat.h @@ -48,17 +48,13 @@ * tv_sec holds the number of seconds before (negative) or after (positive) * 00:00:00 1st January 1970 UTC. * - * tv_nsec holds a number of nanoseconds before (0..-999,999,999 if tv_sec is - * negative) or after (0..999,999,999 if tv_sec is positive) the tv_sec time. - * - * Note that if both tv_sec and tv_nsec are non-zero, then the two values must - * either be both positive or both negative. + * tv_nsec holds a number of nanoseconds (0..999,999,999) after the tv_sec time. * * __reserved is held in case we need a yet finer resolution. */ struct statx_timestamp { __s64 tv_sec; - __s32 tv_nsec; + __u32 tv_nsec; __s32 __reserved; }; -- cgit v1.2.3 From ebd574994c63164d538a197172157318f58ac647 Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Tue, 23 May 2017 10:37:29 -0500 Subject: Revert "x86/entry: Fix the end of the stack for newly forked tasks" Petr Mladek reported the following warning when loading the livepatch sample module: WARNING: CPU: 1 PID: 3699 at arch/x86/kernel/stacktrace.c:132 save_stack_trace_tsk_reliable+0x133/0x1a0 ... Call Trace: __schedule+0x273/0x820 schedule+0x36/0x80 kthreadd+0x305/0x310 ? kthread_create_on_cpu+0x80/0x80 ? icmp_echo.part.32+0x50/0x50 ret_from_fork+0x2c/0x40 That warning means the end of the stack is no longer recognized as such for newly forked tasks. The problem was introduced with the following commit: ff3f7e2475bb ("x86/entry: Fix the end of the stack for newly forked tasks") ... which was completely misguided. It only partially fixed the reported issue, and it introduced another bug in the process. None of the other entry code saves the frame pointer before calling into C code, so it doesn't make sense for ret_from_fork to do so either. Contrary to what I originally thought, the original issue wasn't related to newly forked tasks. It was actually related to ftrace. When entry code calls into a function which then calls into an ftrace handler, the stack frame looks different than normal. The original issue will be fixed in the unwinder, in a subsequent patch. Reported-by: Petr Mladek Signed-off-by: Josh Poimboeuf Acked-by: Thomas Gleixner Cc: Dave Jones Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Steven Rostedt Cc: live-patching@vger.kernel.org Fixes: ff3f7e2475bb ("x86/entry: Fix the end of the stack for newly forked tasks") Link: http://lkml.kernel.org/r/f350760f7e82f0750c8d1dd093456eb212751caa.1495553739.git.jpoimboe@redhat.com Signed-off-by: Ingo Molnar --- arch/x86/entry/entry_32.S | 30 +++++++++++++++++++----------- arch/x86/entry/entry_64.S | 11 ++++------- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S index 50bc26949e9e..48ef7bb32c42 100644 --- a/arch/x86/entry/entry_32.S +++ b/arch/x86/entry/entry_32.S @@ -251,6 +251,23 @@ ENTRY(__switch_to_asm) jmp __switch_to END(__switch_to_asm) +/* + * The unwinder expects the last frame on the stack to always be at the same + * offset from the end of the page, which allows it to validate the stack. + * Calling schedule_tail() directly would break that convention because its an + * asmlinkage function so its argument has to be pushed on the stack. This + * wrapper creates a proper "end of stack" frame header before the call. + */ +ENTRY(schedule_tail_wrapper) + FRAME_BEGIN + + pushl %eax + call schedule_tail + popl %eax + + FRAME_END + ret +ENDPROC(schedule_tail_wrapper) /* * A newly forked process directly context switches into this address. * @@ -259,24 +276,15 @@ END(__switch_to_asm) * edi: kernel thread arg */ ENTRY(ret_from_fork) - FRAME_BEGIN /* help unwinder find end of stack */ - - /* - * schedule_tail() is asmlinkage so we have to put its 'prev' argument - * on the stack. - */ - pushl %eax - call schedule_tail - popl %eax + call schedule_tail_wrapper testl %ebx, %ebx jnz 1f /* kernel threads are uncommon */ 2: /* When we fork, we trace the syscall return in the child, too. */ - leal FRAME_OFFSET(%esp), %eax + movl %esp, %eax call syscall_return_slowpath - FRAME_END jmp restore_all /* kernel thread */ diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S index 607d72c4a485..4a4c0834f965 100644 --- a/arch/x86/entry/entry_64.S +++ b/arch/x86/entry/entry_64.S @@ -36,7 +36,6 @@ #include #include #include -#include #include .code64 @@ -406,19 +405,17 @@ END(__switch_to_asm) * r12: kernel thread arg */ ENTRY(ret_from_fork) - FRAME_BEGIN /* help unwinder find end of stack */ movq %rax, %rdi - call schedule_tail /* rdi: 'prev' task parameter */ + call schedule_tail /* rdi: 'prev' task parameter */ - testq %rbx, %rbx /* from kernel_thread? */ - jnz 1f /* kernel threads are uncommon */ + testq %rbx, %rbx /* from kernel_thread? */ + jnz 1f /* kernel threads are uncommon */ 2: - leaq FRAME_OFFSET(%rsp),%rdi /* pt_regs pointer */ + movq %rsp, %rdi call syscall_return_slowpath /* returns with IRQs disabled */ TRACE_IRQS_ON /* user mode is traced as IRQS on */ SWAPGS - FRAME_END jmp restore_regs_and_iret 1: -- cgit v1.2.3 From 519fb5c3350d1b5225b27b1cac55144f79351718 Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Tue, 23 May 2017 10:37:30 -0500 Subject: x86/unwind: Add end-of-stack check for ftrace handlers Dave Jones and Steven Rostedt reported unwinder warnings like the following: WARNING: kernel stack frame pointer at ffff8800bda0ff30 in sshd:1090 has bad value 000055b32abf1fa8 In both cases, the unwinder was attempting to unwind from an ftrace handler into entry code. The callchain was something like: syscall entry code C function ftrace handler save_stack_trace() The problem is that the unwinder's end-of-stack logic gets confused by the way ftrace lays out the stack frame (with fentry enabled). I was able to recreate this warning with: echo call_usermodehelper_exec_async:stacktrace > /sys/kernel/debug/tracing/set_ftrace_filter (exit login session) I considered fixing this by changing the ftrace code to rewrite the stack to make the unwinder happy. But that seemed too intrusive after I implemented it. Instead, just add another check to the unwinder's end-of-stack logic to detect this special case. Side note: We could probably get rid of these end-of-stack checks by encoding the frame pointer for syscall entry just like we do for interrupt entry. That would be simpler, but it would also be a lot more intrusive since it would slightly affect the performance of every syscall. Reported-by: Dave Jones Reported-by: Steven Rostedt Signed-off-by: Josh Poimboeuf Acked-by: Thomas Gleixner Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Petr Mladek Cc: live-patching@vger.kernel.org Fixes: c32c47c68a0a ("x86/unwind: Warn on bad frame pointer") Link: http://lkml.kernel.org/r/671ba22fbc0156b8f7e0cfa5ab2a795e08bc37e1.1495553739.git.jpoimboe@redhat.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/unwind_frame.c | 49 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/arch/x86/kernel/unwind_frame.c b/arch/x86/kernel/unwind_frame.c index 82c6d7f1fd73..b9389d72b2f7 100644 --- a/arch/x86/kernel/unwind_frame.c +++ b/arch/x86/kernel/unwind_frame.c @@ -104,6 +104,11 @@ static inline unsigned long *last_frame(struct unwind_state *state) return (unsigned long *)task_pt_regs(state->task) - 2; } +static bool is_last_frame(struct unwind_state *state) +{ + return state->bp == last_frame(state); +} + #ifdef CONFIG_X86_32 #define GCC_REALIGN_WORDS 3 #else @@ -115,16 +120,15 @@ static inline unsigned long *last_aligned_frame(struct unwind_state *state) return last_frame(state) - GCC_REALIGN_WORDS; } -static bool is_last_task_frame(struct unwind_state *state) +static bool is_last_aligned_frame(struct unwind_state *state) { unsigned long *last_bp = last_frame(state); unsigned long *aligned_bp = last_aligned_frame(state); /* - * We have to check for the last task frame at two different locations - * because gcc can occasionally decide to realign the stack pointer and - * change the offset of the stack frame in the prologue of a function - * called by head/entry code. Examples: + * GCC can occasionally decide to realign the stack pointer and change + * the offset of the stack frame in the prologue of a function called + * by head/entry code. Examples: * * : * push %edi @@ -141,11 +145,38 @@ static bool is_last_task_frame(struct unwind_state *state) * push %rbp * mov %rsp,%rbp * - * Note that after aligning the stack, it pushes a duplicate copy of - * the return address before pushing the frame pointer. + * After aligning the stack, it pushes a duplicate copy of the return + * address before pushing the frame pointer. + */ + return (state->bp == aligned_bp && *(aligned_bp + 1) == *(last_bp + 1)); +} + +static bool is_last_ftrace_frame(struct unwind_state *state) +{ + unsigned long *last_bp = last_frame(state); + unsigned long *last_ftrace_bp = last_bp - 3; + + /* + * When unwinding from an ftrace handler of a function called by entry + * code, the stack layout of the last frame is: + * + * bp + * parent ret addr + * bp + * function ret addr + * parent ret addr + * pt_regs + * ----------------- */ - return (state->bp == last_bp || - (state->bp == aligned_bp && *(aligned_bp+1) == *(last_bp+1))); + return (state->bp == last_ftrace_bp && + *state->bp == *(state->bp + 2) && + *(state->bp + 1) == *(state->bp + 4)); +} + +static bool is_last_task_frame(struct unwind_state *state) +{ + return is_last_frame(state) || is_last_aligned_frame(state) || + is_last_ftrace_frame(state); } /* -- cgit v1.2.3 From 7e6091209f7f73e2a81943020793b5ad26d645c6 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Tue, 23 May 2017 18:27:54 +0200 Subject: x86/build: Permit building with old make versions At least Make 3.82 dislikes the tab in front of the $(warning) function: arch/x86/Makefile:162: *** recipe commences before first target. Stop. Let's be gentle. Signed-off-by: Jan Kiszka Acked-by: Thomas Gleixner Cc: Josh Poimboeuf Cc: Linus Torvalds Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1944fcd8-e3df-d1f7-c0e4-60aeb1917a24@siemens.com Signed-off-by: Ingo Molnar --- arch/x86/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 5851411e60fb..bf240b920473 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -159,7 +159,7 @@ ifdef CONFIG_FUNCTION_GRAPH_TRACER # If '-Os' is enabled, disable it and print a warning. ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE undefine CONFIG_CC_OPTIMIZE_FOR_SIZE - $(warning Disabling CONFIG_CC_OPTIMIZE_FOR_SIZE. Your compiler does not have -mfentry so you cannot optimize for size with CONFIG_FUNCTION_GRAPH_TRACER.) + $(warning Disabling CONFIG_CC_OPTIMIZE_FOR_SIZE. Your compiler does not have -mfentry so you cannot optimize for size with CONFIG_FUNCTION_GRAPH_TRACER.) endif endif -- cgit v1.2.3 From c9525a3fab63fbe091007494f8b7a06438eea6a7 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sat, 20 May 2017 17:20:16 -0700 Subject: x86/watchdog: Fix Kconfig help text file path reference to lockup watchdog documentation Signed-off-by: Benjamin Peterson Acked-by: Thomas Gleixner Cc: Linus Torvalds Cc: Peter Zijlstra Fixes: 9919cba7ff71147803c988521cc1ceb80e7f0f6d ("watchdog: Update documentation") Link: http://lkml.kernel.org/r/20170521002016.13258-1-bp@benjamin.pe Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index cd18994a9555..4ccfacc7232a 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -360,7 +360,7 @@ config SMP Management" code will be disabled if you say Y here. See also , - and the SMP-HOWTO available at + and the SMP-HOWTO available at . If you don't know what to do here, say N. -- cgit v1.2.3 From 28232a4317be7ad615f0f1b69dc8583fd580a8e3 Mon Sep 17 00:00:00 2001 From: Christoffer Dall Date: Sat, 20 May 2017 14:12:34 +0200 Subject: KVM: arm/arm64: Fix isues with GICv2 on GICv3 migration We have been a little loose with our intermediate VMCR representation where we had a 'ctlr' field, but we failed to differentiate between the GICv2 GICC_CTLR and ICC_CTLR_EL1 layouts, and therefore ended up mapping the wrong bits into the individual fields of the ICH_VMCR_EL2 when emulating a GICv2 on a GICv3 system. Fix this by using explicit fields for the VMCR bits instead. Cc: Eric Auger Reported-by: wanghaibin Signed-off-by: Christoffer Dall Reviewed-by: Marc Zyngier Tested-by: Marc Zyngier --- arch/arm64/kvm/vgic-sys-reg-v3.c | 10 ++++---- include/linux/irqchip/arm-gic-v3.h | 4 ++++ include/linux/irqchip/arm-gic.h | 28 ++++++++++++++++++++--- virt/kvm/arm/vgic/vgic-mmio-v2.c | 16 +++++++++++-- virt/kvm/arm/vgic/vgic-v2.c | 28 ++++++++++++++++++++--- virt/kvm/arm/vgic/vgic-v3.c | 47 ++++++++++++++++++++++++++------------ virt/kvm/arm/vgic/vgic.h | 12 ++++++---- 7 files changed, 114 insertions(+), 31 deletions(-) diff --git a/arch/arm64/kvm/vgic-sys-reg-v3.c b/arch/arm64/kvm/vgic-sys-reg-v3.c index 79f37e37d367..6260b69e5622 100644 --- a/arch/arm64/kvm/vgic-sys-reg-v3.c +++ b/arch/arm64/kvm/vgic-sys-reg-v3.c @@ -65,8 +65,8 @@ static bool access_gic_ctlr(struct kvm_vcpu *vcpu, struct sys_reg_params *p, * Here set VMCR.CTLR in ICC_CTLR_EL1 layout. * The vgic_set_vmcr() will convert to ICH_VMCR layout. */ - vmcr.ctlr = val & ICC_CTLR_EL1_CBPR_MASK; - vmcr.ctlr |= val & ICC_CTLR_EL1_EOImode_MASK; + vmcr.cbpr = (val & ICC_CTLR_EL1_CBPR_MASK) >> ICC_CTLR_EL1_CBPR_SHIFT; + vmcr.eoim = (val & ICC_CTLR_EL1_EOImode_MASK) >> ICC_CTLR_EL1_EOImode_SHIFT; vgic_set_vmcr(vcpu, &vmcr); } else { val = 0; @@ -83,8 +83,8 @@ static bool access_gic_ctlr(struct kvm_vcpu *vcpu, struct sys_reg_params *p, * The VMCR.CTLR value is in ICC_CTLR_EL1 layout. * Extract it directly using ICC_CTLR_EL1 reg definitions. */ - val |= vmcr.ctlr & ICC_CTLR_EL1_CBPR_MASK; - val |= vmcr.ctlr & ICC_CTLR_EL1_EOImode_MASK; + val |= (vmcr.cbpr << ICC_CTLR_EL1_CBPR_SHIFT) & ICC_CTLR_EL1_CBPR_MASK; + val |= (vmcr.eoim << ICC_CTLR_EL1_EOImode_SHIFT) & ICC_CTLR_EL1_EOImode_MASK; p->regval = val; } @@ -135,7 +135,7 @@ static bool access_gic_bpr1(struct kvm_vcpu *vcpu, struct sys_reg_params *p, p->regval = 0; vgic_get_vmcr(vcpu, &vmcr); - if (!((vmcr.ctlr & ICH_VMCR_CBPR_MASK) >> ICH_VMCR_CBPR_SHIFT)) { + if (!vmcr.cbpr) { if (p->is_write) { vmcr.abpr = (p->regval & ICC_BPR1_EL1_MASK) >> ICC_BPR1_EL1_SHIFT; diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h index fffb91202bc9..1fa293a37f4a 100644 --- a/include/linux/irqchip/arm-gic-v3.h +++ b/include/linux/irqchip/arm-gic-v3.h @@ -417,6 +417,10 @@ #define ICH_HCR_EN (1 << 0) #define ICH_HCR_UIE (1 << 1) +#define ICH_VMCR_ACK_CTL_SHIFT 2 +#define ICH_VMCR_ACK_CTL_MASK (1 << ICH_VMCR_ACK_CTL_SHIFT) +#define ICH_VMCR_FIQ_EN_SHIFT 3 +#define ICH_VMCR_FIQ_EN_MASK (1 << ICH_VMCR_FIQ_EN_SHIFT) #define ICH_VMCR_CBPR_SHIFT 4 #define ICH_VMCR_CBPR_MASK (1 << ICH_VMCR_CBPR_SHIFT) #define ICH_VMCR_EOIM_SHIFT 9 diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h index dc30f3d057eb..d3453ee072fc 100644 --- a/include/linux/irqchip/arm-gic.h +++ b/include/linux/irqchip/arm-gic.h @@ -25,7 +25,18 @@ #define GICC_ENABLE 0x1 #define GICC_INT_PRI_THRESHOLD 0xf0 -#define GIC_CPU_CTRL_EOImodeNS (1 << 9) +#define GIC_CPU_CTRL_EnableGrp0_SHIFT 0 +#define GIC_CPU_CTRL_EnableGrp0 (1 << GIC_CPU_CTRL_EnableGrp0_SHIFT) +#define GIC_CPU_CTRL_EnableGrp1_SHIFT 1 +#define GIC_CPU_CTRL_EnableGrp1 (1 << GIC_CPU_CTRL_EnableGrp1_SHIFT) +#define GIC_CPU_CTRL_AckCtl_SHIFT 2 +#define GIC_CPU_CTRL_AckCtl (1 << GIC_CPU_CTRL_AckCtl_SHIFT) +#define GIC_CPU_CTRL_FIQEn_SHIFT 3 +#define GIC_CPU_CTRL_FIQEn (1 << GIC_CPU_CTRL_FIQEn_SHIFT) +#define GIC_CPU_CTRL_CBPR_SHIFT 4 +#define GIC_CPU_CTRL_CBPR (1 << GIC_CPU_CTRL_CBPR_SHIFT) +#define GIC_CPU_CTRL_EOImodeNS_SHIFT 9 +#define GIC_CPU_CTRL_EOImodeNS (1 << GIC_CPU_CTRL_EOImodeNS_SHIFT) #define GICC_IAR_INT_ID_MASK 0x3ff #define GICC_INT_SPURIOUS 1023 @@ -84,8 +95,19 @@ #define GICH_LR_EOI (1 << 19) #define GICH_LR_HW (1 << 31) -#define GICH_VMCR_CTRL_SHIFT 0 -#define GICH_VMCR_CTRL_MASK (0x21f << GICH_VMCR_CTRL_SHIFT) +#define GICH_VMCR_ENABLE_GRP0_SHIFT 0 +#define GICH_VMCR_ENABLE_GRP0_MASK (1 << GICH_VMCR_ENABLE_GRP0_SHIFT) +#define GICH_VMCR_ENABLE_GRP1_SHIFT 1 +#define GICH_VMCR_ENABLE_GRP1_MASK (1 << GICH_VMCR_ENABLE_GRP1_SHIFT) +#define GICH_VMCR_ACK_CTL_SHIFT 2 +#define GICH_VMCR_ACK_CTL_MASK (1 << GICH_VMCR_ACK_CTL_SHIFT) +#define GICH_VMCR_FIQ_EN_SHIFT 3 +#define GICH_VMCR_FIQ_EN_MASK (1 << GICH_VMCR_FIQ_EN_SHIFT) +#define GICH_VMCR_CBPR_SHIFT 4 +#define GICH_VMCR_CBPR_MASK (1 << GICH_VMCR_CBPR_SHIFT) +#define GICH_VMCR_EOI_MODE_SHIFT 9 +#define GICH_VMCR_EOI_MODE_MASK (1 << GICH_VMCR_EOI_MODE_SHIFT) + #define GICH_VMCR_PRIMASK_SHIFT 27 #define GICH_VMCR_PRIMASK_MASK (0x1f << GICH_VMCR_PRIMASK_SHIFT) #define GICH_VMCR_BINPOINT_SHIFT 21 diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c index 0a4283ed9aa7..63e0bbdcddcc 100644 --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c @@ -226,7 +226,13 @@ static unsigned long vgic_mmio_read_vcpuif(struct kvm_vcpu *vcpu, switch (addr & 0xff) { case GIC_CPU_CTRL: - val = vmcr.ctlr; + val = vmcr.grpen0 << GIC_CPU_CTRL_EnableGrp0_SHIFT; + val |= vmcr.grpen1 << GIC_CPU_CTRL_EnableGrp1_SHIFT; + val |= vmcr.ackctl << GIC_CPU_CTRL_AckCtl_SHIFT; + val |= vmcr.fiqen << GIC_CPU_CTRL_FIQEn_SHIFT; + val |= vmcr.cbpr << GIC_CPU_CTRL_CBPR_SHIFT; + val |= vmcr.eoim << GIC_CPU_CTRL_EOImodeNS_SHIFT; + break; case GIC_CPU_PRIMASK: /* @@ -267,7 +273,13 @@ static void vgic_mmio_write_vcpuif(struct kvm_vcpu *vcpu, switch (addr & 0xff) { case GIC_CPU_CTRL: - vmcr.ctlr = val; + vmcr.grpen0 = !!(val & GIC_CPU_CTRL_EnableGrp0); + vmcr.grpen1 = !!(val & GIC_CPU_CTRL_EnableGrp1); + vmcr.ackctl = !!(val & GIC_CPU_CTRL_AckCtl); + vmcr.fiqen = !!(val & GIC_CPU_CTRL_FIQEn); + vmcr.cbpr = !!(val & GIC_CPU_CTRL_CBPR); + vmcr.eoim = !!(val & GIC_CPU_CTRL_EOImodeNS); + break; case GIC_CPU_PRIMASK: /* diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c index 504b4bd0d651..e4187e52bb26 100644 --- a/virt/kvm/arm/vgic/vgic-v2.c +++ b/virt/kvm/arm/vgic/vgic-v2.c @@ -177,7 +177,18 @@ void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp) struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2; u32 vmcr; - vmcr = (vmcrp->ctlr << GICH_VMCR_CTRL_SHIFT) & GICH_VMCR_CTRL_MASK; + vmcr = (vmcrp->grpen0 << GICH_VMCR_ENABLE_GRP0_SHIFT) & + GICH_VMCR_ENABLE_GRP0_MASK; + vmcr |= (vmcrp->grpen1 << GICH_VMCR_ENABLE_GRP1_SHIFT) & + GICH_VMCR_ENABLE_GRP1_MASK; + vmcr |= (vmcrp->ackctl << GICH_VMCR_ACK_CTL_SHIFT) & + GICH_VMCR_ACK_CTL_MASK; + vmcr |= (vmcrp->fiqen << GICH_VMCR_FIQ_EN_SHIFT) & + GICH_VMCR_FIQ_EN_MASK; + vmcr |= (vmcrp->cbpr << GICH_VMCR_CBPR_SHIFT) & + GICH_VMCR_CBPR_MASK; + vmcr |= (vmcrp->eoim << GICH_VMCR_EOI_MODE_SHIFT) & + GICH_VMCR_EOI_MODE_MASK; vmcr |= (vmcrp->abpr << GICH_VMCR_ALIAS_BINPOINT_SHIFT) & GICH_VMCR_ALIAS_BINPOINT_MASK; vmcr |= (vmcrp->bpr << GICH_VMCR_BINPOINT_SHIFT) & @@ -195,8 +206,19 @@ void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp) vmcr = cpu_if->vgic_vmcr; - vmcrp->ctlr = (vmcr & GICH_VMCR_CTRL_MASK) >> - GICH_VMCR_CTRL_SHIFT; + vmcrp->grpen0 = (vmcr & GICH_VMCR_ENABLE_GRP0_MASK) >> + GICH_VMCR_ENABLE_GRP0_SHIFT; + vmcrp->grpen1 = (vmcr & GICH_VMCR_ENABLE_GRP1_MASK) >> + GICH_VMCR_ENABLE_GRP1_SHIFT; + vmcrp->ackctl = (vmcr & GICH_VMCR_ACK_CTL_MASK) >> + GICH_VMCR_ACK_CTL_SHIFT; + vmcrp->fiqen = (vmcr & GICH_VMCR_FIQ_EN_MASK) >> + GICH_VMCR_FIQ_EN_SHIFT; + vmcrp->cbpr = (vmcr & GICH_VMCR_CBPR_MASK) >> + GICH_VMCR_CBPR_SHIFT; + vmcrp->eoim = (vmcr & GICH_VMCR_EOI_MODE_MASK) >> + GICH_VMCR_EOI_MODE_SHIFT; + vmcrp->abpr = (vmcr & GICH_VMCR_ALIAS_BINPOINT_MASK) >> GICH_VMCR_ALIAS_BINPOINT_SHIFT; vmcrp->bpr = (vmcr & GICH_VMCR_BINPOINT_MASK) >> diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c index 6fe3f003636a..030248e669f6 100644 --- a/virt/kvm/arm/vgic/vgic-v3.c +++ b/virt/kvm/arm/vgic/vgic-v3.c @@ -159,15 +159,24 @@ void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr) void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp) { struct vgic_v3_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v3; + u32 model = vcpu->kvm->arch.vgic.vgic_model; u32 vmcr; - /* - * Ignore the FIQen bit, because GIC emulation always implies - * SRE=1 which means the vFIQEn bit is also RES1. - */ - vmcr = ((vmcrp->ctlr >> ICC_CTLR_EL1_EOImode_SHIFT) << - ICH_VMCR_EOIM_SHIFT) & ICH_VMCR_EOIM_MASK; - vmcr |= (vmcrp->ctlr << ICH_VMCR_CBPR_SHIFT) & ICH_VMCR_CBPR_MASK; + if (model == KVM_DEV_TYPE_ARM_VGIC_V2) { + vmcr = (vmcrp->ackctl << ICH_VMCR_ACK_CTL_SHIFT) & + ICH_VMCR_ACK_CTL_MASK; + vmcr |= (vmcrp->fiqen << ICH_VMCR_FIQ_EN_SHIFT) & + ICH_VMCR_FIQ_EN_MASK; + } else { + /* + * When emulating GICv3 on GICv3 with SRE=1 on the + * VFIQEn bit is RES1 and the VAckCtl bit is RES0. + */ + vmcr = ICH_VMCR_FIQ_EN_MASK; + } + + vmcr |= (vmcrp->cbpr << ICH_VMCR_CBPR_SHIFT) & ICH_VMCR_CBPR_MASK; + vmcr |= (vmcrp->eoim << ICH_VMCR_EOIM_SHIFT) & ICH_VMCR_EOIM_MASK; vmcr |= (vmcrp->abpr << ICH_VMCR_BPR1_SHIFT) & ICH_VMCR_BPR1_MASK; vmcr |= (vmcrp->bpr << ICH_VMCR_BPR0_SHIFT) & ICH_VMCR_BPR0_MASK; vmcr |= (vmcrp->pmr << ICH_VMCR_PMR_SHIFT) & ICH_VMCR_PMR_MASK; @@ -180,17 +189,27 @@ void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp) void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp) { struct vgic_v3_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v3; + u32 model = vcpu->kvm->arch.vgic.vgic_model; u32 vmcr; vmcr = cpu_if->vgic_vmcr; - /* - * Ignore the FIQen bit, because GIC emulation always implies - * SRE=1 which means the vFIQEn bit is also RES1. - */ - vmcrp->ctlr = ((vmcr >> ICH_VMCR_EOIM_SHIFT) << - ICC_CTLR_EL1_EOImode_SHIFT) & ICC_CTLR_EL1_EOImode_MASK; - vmcrp->ctlr |= (vmcr & ICH_VMCR_CBPR_MASK) >> ICH_VMCR_CBPR_SHIFT; + if (model == KVM_DEV_TYPE_ARM_VGIC_V2) { + vmcrp->ackctl = (vmcr & ICH_VMCR_ACK_CTL_MASK) >> + ICH_VMCR_ACK_CTL_SHIFT; + vmcrp->fiqen = (vmcr & ICH_VMCR_FIQ_EN_MASK) >> + ICH_VMCR_FIQ_EN_SHIFT; + } else { + /* + * When emulating GICv3 on GICv3 with SRE=1 on the + * VFIQEn bit is RES1 and the VAckCtl bit is RES0. + */ + vmcrp->fiqen = 1; + vmcrp->ackctl = 0; + } + + vmcrp->cbpr = (vmcr & ICH_VMCR_CBPR_MASK) >> ICH_VMCR_CBPR_SHIFT; + vmcrp->eoim = (vmcr & ICH_VMCR_EOIM_MASK) >> ICH_VMCR_EOIM_SHIFT; vmcrp->abpr = (vmcr & ICH_VMCR_BPR1_MASK) >> ICH_VMCR_BPR1_SHIFT; vmcrp->bpr = (vmcr & ICH_VMCR_BPR0_MASK) >> ICH_VMCR_BPR0_SHIFT; vmcrp->pmr = (vmcr & ICH_VMCR_PMR_MASK) >> ICH_VMCR_PMR_SHIFT; diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h index da83e4caa272..bba7fa22a7f7 100644 --- a/virt/kvm/arm/vgic/vgic.h +++ b/virt/kvm/arm/vgic/vgic.h @@ -111,14 +111,18 @@ static inline bool irq_is_pending(struct vgic_irq *irq) * registers regardless of the hardware backed GIC used. */ struct vgic_vmcr { - u32 ctlr; + u32 grpen0; + u32 grpen1; + + u32 ackctl; + u32 fiqen; + u32 cbpr; + u32 eoim; + u32 abpr; u32 bpr; u32 pmr; /* Priority mask field in the GICC_PMR and * ICC_PMR_EL1 priority field format */ - /* Below member variable are valid only for GICv3 */ - u32 grpen0; - u32 grpen1; }; struct vgic_reg_attr { -- cgit v1.2.3 From cbed27cdf0e3f7ea3b2259e86b9e34df02be3fe4 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Tue, 18 Apr 2017 15:07:11 -0400 Subject: x86/PAT: Fix Xorg regression on CPUs that don't support PAT In the file arch/x86/mm/pat.c, there's a '__pat_enabled' variable. The variable is set to 1 by default and the function pat_init() sets __pat_enabled to 0 if the CPU doesn't support PAT. However, on AMD K6-3 CPUs, the processor initialization code never calls pat_init() and so __pat_enabled stays 1 and the function pat_enabled() returns true, even though the K6-3 CPU doesn't support PAT. The result of this bug is that a kernel warning is produced when attempting to start the Xserver and the Xserver doesn't start (fork() returns ENOMEM). Another symptom of this bug is that the framebuffer driver doesn't set the K6-3 MTRR registers: x86/PAT: Xorg:3891 map pfn expected mapping type uncached-minus for [mem 0xe4000000-0xe5ffffff], got write-combining ------------[ cut here ]------------ WARNING: CPU: 0 PID: 3891 at arch/x86/mm/pat.c:1020 untrack_pfn+0x5c/0x9f ... x86/PAT: Xorg:3891 map pfn expected mapping type uncached-minus for [mem 0xe4000000-0xe5ffffff], got write-combining To fix the bug change pat_enabled() so that it returns true only if PAT initialization was actually done. Also, I changed boot_cpu_has(X86_FEATURE_PAT) to this_cpu_has(X86_FEATURE_PAT) in pat_ap_init(), so that we check the PAT feature on the processor that is being initialized. Signed-off-by: Mikulas Patocka Cc: Andrew Morton Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Josh Poimboeuf Cc: Linus Torvalds Cc: Luis R. Rodriguez Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Toshi Kani Cc: stable@vger.kernel.org # v4.2+ Link: http://lkml.kernel.org/r/alpine.LRH.2.02.1704181501450.26399@file01.intranet.prod.int.rdu2.redhat.com Signed-off-by: Ingo Molnar --- arch/x86/mm/pat.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c index 9b78685b66e6..83a59a67757a 100644 --- a/arch/x86/mm/pat.c +++ b/arch/x86/mm/pat.c @@ -65,9 +65,11 @@ static int __init nopat(char *str) } early_param("nopat", nopat); +static bool __read_mostly __pat_initialized = false; + bool pat_enabled(void) { - return !!__pat_enabled; + return __pat_initialized; } EXPORT_SYMBOL_GPL(pat_enabled); @@ -225,13 +227,14 @@ static void pat_bsp_init(u64 pat) } wrmsrl(MSR_IA32_CR_PAT, pat); + __pat_initialized = true; __init_cache_modes(pat); } static void pat_ap_init(u64 pat) { - if (!boot_cpu_has(X86_FEATURE_PAT)) { + if (!this_cpu_has(X86_FEATURE_PAT)) { /* * If this happens we are on a secondary CPU, but switched to * PAT on the boot CPU. We have no way to undo PAT. @@ -306,7 +309,7 @@ void pat_init(void) u64 pat; struct cpuinfo_x86 *c = &boot_cpu_data; - if (!pat_enabled()) { + if (!__pat_enabled) { init_cache_modes(); return; } -- cgit v1.2.3 From 4497a224f759cd8350e07382307b55f870ef0df2 Mon Sep 17 00:00:00 2001 From: Jeremy Linton Date: Sat, 8 Apr 2017 02:18:40 -0500 Subject: reset: hi6220: Set module license so that it can be loaded The hi6220_reset driver can be built as a standalone module yet it cannot be loaded because it depends on GPL exported symbols. Lets set the module license so that the module loads, and things like the on-board kirin drm starts working. Signed-off-by: Jeremy Linton Reviewed-by: Xinliang Liu Signed-off-by: Philipp Zabel --- drivers/reset/hisilicon/hi6220_reset.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/reset/hisilicon/hi6220_reset.c b/drivers/reset/hisilicon/hi6220_reset.c index 35ce53edabf9..d5e5229308f2 100644 --- a/drivers/reset/hisilicon/hi6220_reset.c +++ b/drivers/reset/hisilicon/hi6220_reset.c @@ -155,3 +155,5 @@ static int __init hi6220_reset_init(void) } postcore_initcall(hi6220_reset_init); + +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From fefa92679dbe0c613e62b6c27235dcfbe9640ad1 Mon Sep 17 00:00:00 2001 From: Liping Zhang Date: Sun, 21 May 2017 07:22:49 +0800 Subject: netfilter: ctnetlink: fix incorrect nf_ct_put during hash resize If nf_conntrack_htable_size was adjusted by the user during the ct dump operation, we may invoke nf_ct_put twice for the same ct, i.e. the "last" ct. This will cause the ct will be freed but still linked in hash buckets. It's very easy to reproduce the problem by the following commands: # while : ; do echo $RANDOM > /proc/sys/net/netfilter/nf_conntrack_buckets done # while : ; do conntrack -L done # iperf -s 127.0.0.1 & # iperf -c 127.0.0.1 -P 60 -t 36000 After a while, the system will hang like this: NMI watchdog: BUG: soft lockup - CPU#1 stuck for 22s! [bash:20184] NMI watchdog: BUG: soft lockup - CPU#0 stuck for 22s! [iperf:20382] ... So at last if we find cb->args[1] is equal to "last", this means hash resize happened, then we can set cb->args[1] to 0 to fix the above issue. Fixes: d205dc40798d ("[NETFILTER]: ctnetlink: fix deadlock in table dumping") Signed-off-by: Liping Zhang Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_conntrack_netlink.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 9799a50bc604..a8be9b72e6cd 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -890,8 +890,13 @@ restart: } out: local_bh_enable(); - if (last) + if (last) { + /* nf ct hash resize happened, now clear the leftover. */ + if ((struct nf_conn *)cb->args[1] == last) + cb->args[1] = 0; + nf_ct_put(last); + } while (i) { i--; -- cgit v1.2.3 From 0f0b9b63e14fc3f66e4d342df016c9b071c5abed Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 2 May 2017 13:14:13 +0200 Subject: gfs2: Make flush bios explicitely sync Commit b685d3d65ac7 "block: treat REQ_FUA and REQ_PREFLUSH as synchronous" removed REQ_SYNC flag from WRITE_{FUA|PREFLUSH|...} definitions. generic_make_request_checks() however strips REQ_FUA and REQ_PREFLUSH flags from a bio when the storage doesn't report volatile write cache and thus write effectively becomes asynchronous which can lead to performance regressions Fix the problem by making sure all bios which are synchronous are properly marked with REQ_SYNC. Fixes: b685d3d65ac791406e0dfd8779cc9b3707fea5a3 CC: Steven Whitehouse CC: cluster-devel@redhat.com CC: stable@vger.kernel.org Acked-by: Bob Peterson Signed-off-by: Jan Kara --- fs/gfs2/log.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c index f865b96374df..d2955daf17a4 100644 --- a/fs/gfs2/log.c +++ b/fs/gfs2/log.c @@ -659,7 +659,7 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags) struct gfs2_log_header *lh; unsigned int tail; u32 hash; - int op_flags = REQ_PREFLUSH | REQ_FUA | REQ_META; + int op_flags = REQ_PREFLUSH | REQ_FUA | REQ_META | REQ_SYNC; struct page *page = mempool_alloc(gfs2_page_pool, GFP_NOIO); enum gfs2_freeze_state state = atomic_read(&sdp->sd_freeze_state); lh = page_address(page); -- cgit v1.2.3 From d8747d642ec4ce96adf17ae35652a5e4015cfe02 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 2 May 2017 13:16:18 +0200 Subject: reiserfs: Make flush bios explicitely sync Commit b685d3d65ac7 "block: treat REQ_FUA and REQ_PREFLUSH as synchronous" removed REQ_SYNC flag from WRITE_{FUA|PREFLUSH|...} definitions. generic_make_request_checks() however strips REQ_FUA and REQ_PREFLUSH flags from a bio when the storage doesn't report volatile write cache and thus write effectively becomes asynchronous which can lead to performance regressions Fix the problem by making sure all bios which are synchronous are properly marked with REQ_SYNC. Fixes: b685d3d65ac791406e0dfd8779cc9b3707fea5a3 CC: reiserfs-devel@vger.kernel.org CC: stable@vger.kernel.org Signed-off-by: Jan Kara --- fs/reiserfs/journal.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index da01f497180a..39bb1e838d8d 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c @@ -1112,7 +1112,7 @@ static int flush_commit_list(struct super_block *s, depth = reiserfs_write_unlock_nested(s); if (reiserfs_barrier_flush(s)) __sync_dirty_buffer(jl->j_commit_bh, - REQ_PREFLUSH | REQ_FUA); + REQ_SYNC | REQ_PREFLUSH | REQ_FUA); else sync_dirty_buffer(jl->j_commit_bh); reiserfs_write_lock_nested(s, depth); @@ -1271,7 +1271,7 @@ static int _update_journal_header_block(struct super_block *sb, if (reiserfs_barrier_flush(sb)) __sync_dirty_buffer(journal->j_header_bh, - REQ_PREFLUSH | REQ_FUA); + REQ_SYNC | REQ_PREFLUSH | REQ_FUA); else sync_dirty_buffer(journal->j_header_bh); -- cgit v1.2.3 From 6d3b5d8d8dd1c14f991ccab84b40f8425f1ae91b Mon Sep 17 00:00:00 2001 From: Olga Kornievskaia Date: Tue, 16 May 2017 12:00:15 -0400 Subject: NFS fix COMMIT after COPY Fix a typo in the commit e092693443b995c8e3a565a73b5fdb05f1260f9b "NFS append COMMIT after synchronous COPY" Reported-by: Eryu Guan Fixes: e092693443b ("NFS append COMMIT after synchronous COPY") Signed-off-by: Olga Kornievskaia Tested-by: Eryu Guan Signed-off-by: Trond Myklebust --- fs/nfs/nfs42proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/nfs/nfs42proc.c b/fs/nfs/nfs42proc.c index 929d09a5310a..319a47db218d 100644 --- a/fs/nfs/nfs42proc.c +++ b/fs/nfs/nfs42proc.c @@ -177,7 +177,7 @@ static ssize_t _nfs42_proc_copy(struct file *src, if (status) goto out; - if (!nfs_write_verifier_cmp(&res->write_res.verifier.verifier, + if (nfs_write_verifier_cmp(&res->write_res.verifier.verifier, &res->commit_res.verf->verifier)) { status = -EAGAIN; goto out; -- cgit v1.2.3 From 662f9a105b4322b8559d448f86110e6ec24b8738 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 20 May 2017 00:31:12 +0300 Subject: pNFS/flexfiles: missing error code in ff_layout_alloc_lseg() If xdr_inline_decode() fails then we end up returning ERR_PTR(0). The caller treats NULL returns as -ENOMEM so it doesn't really hurt runtime, but obviously we intended to set an error code here. Fixes: d67ae825a59d ("pnfs/flexfiles: Add the FlexFile Layout Driver") Signed-off-by: Dan Carpenter Signed-off-by: Trond Myklebust --- fs/nfs/flexfilelayout/flexfilelayout.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c index f5714ee01000..23542dc44a25 100644 --- a/fs/nfs/flexfilelayout/flexfilelayout.c +++ b/fs/nfs/flexfilelayout/flexfilelayout.c @@ -454,6 +454,7 @@ ff_layout_alloc_lseg(struct pnfs_layout_hdr *lh, goto out_err_free; /* fh */ + rc = -EIO; p = xdr_inline_decode(&stream, 4); if (!p) goto out_err_free; -- cgit v1.2.3 From d2c23c0075d7091bf749411bd2ee757cf4ec356c Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Mon, 22 May 2017 22:18:28 +0200 Subject: xprtrdma: Delete an error message for a failed memory allocation in xprt_rdma_bc_setup() Omit an extra message for a memory allocation failure in this function. This issue was detected by using the Coccinelle software. Link: http://events.linuxfoundation.org/sites/events/files/slides/LCJ16-Refactor_Strings-WSang_0.pdf Signed-off-by: Markus Elfring Reviewed-by: Chuck Lever Signed-off-by: Trond Myklebust --- net/sunrpc/xprtrdma/backchannel.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/net/sunrpc/xprtrdma/backchannel.c b/net/sunrpc/xprtrdma/backchannel.c index 24fedd4b117e..03f6b5840764 100644 --- a/net/sunrpc/xprtrdma/backchannel.c +++ b/net/sunrpc/xprtrdma/backchannel.c @@ -119,11 +119,9 @@ int xprt_rdma_bc_setup(struct rpc_xprt *xprt, unsigned int reqs) for (i = 0; i < (reqs << 1); i++) { rqst = kzalloc(sizeof(*rqst), GFP_KERNEL); - if (!rqst) { - pr_err("RPC: %s: Failed to create bc rpc_rqst\n", - __func__); + if (!rqst) goto out_free; - } + dprintk("RPC: %s: new rqst %p\n", __func__, rqst); rqst->rq_xprt = &r_xprt->rx_xprt; -- cgit v1.2.3 From 08cb5b0f058a325fcb5305e33f572ff6d6dfa289 Mon Sep 17 00:00:00 2001 From: Benjamin Coddington Date: Mon, 22 May 2017 20:20:23 -0400 Subject: pnfs: Fix the check for requests in range of layout segment It's possible and acceptable for NFS to attempt to add requests beyond the range of the current pgio->pg_lseg, a case which should be caught and limited by the pg_test operation. However, the current handling of this case replaces pgio->pg_lseg with a new layout segment (after a WARN) within that pg_test operation. That will cause all the previously added requests to be submitted with this new layout segment, which may not be valid for those requests. Fix this problem by only returning zero for the number of bytes to coalesce from pg_test for this case which allows any previously added requests to complete on the current layout segment. The check for requests starting out of range of the layout segment moves to pg_init, so that the replacement of pgio->pg_lseg will be done when the next request is added. Signed-off-by: Benjamin Coddington Signed-off-by: Trond Myklebust --- fs/nfs/pnfs.c | 25 +++++++++++++++++-------- fs/nfs/pnfs.h | 10 ++++++++++ 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index adc6ec28d4b5..c383d0913b54 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c @@ -2094,12 +2094,26 @@ pnfs_generic_pg_check_layout(struct nfs_pageio_descriptor *pgio) } EXPORT_SYMBOL_GPL(pnfs_generic_pg_check_layout); +/* + * Check for any intersection between the request and the pgio->pg_lseg, + * and if none, put this pgio->pg_lseg away. + */ +static void +pnfs_generic_pg_check_range(struct nfs_pageio_descriptor *pgio, struct nfs_page *req) +{ + if (pgio->pg_lseg && !pnfs_lseg_request_intersecting(pgio->pg_lseg, req)) { + pnfs_put_lseg(pgio->pg_lseg); + pgio->pg_lseg = NULL; + } +} + void pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req) { u64 rd_size = req->wb_bytes; pnfs_generic_pg_check_layout(pgio); + pnfs_generic_pg_check_range(pgio, req); if (pgio->pg_lseg == NULL) { if (pgio->pg_dreq == NULL) rd_size = i_size_read(pgio->pg_inode) - req_offset(req); @@ -2131,6 +2145,7 @@ pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *req, u64 wb_size) { pnfs_generic_pg_check_layout(pgio); + pnfs_generic_pg_check_range(pgio, req); if (pgio->pg_lseg == NULL) { pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, req->wb_context, @@ -2191,16 +2206,10 @@ pnfs_generic_pg_test(struct nfs_pageio_descriptor *pgio, seg_end = pnfs_end_offset(pgio->pg_lseg->pls_range.offset, pgio->pg_lseg->pls_range.length); req_start = req_offset(req); - WARN_ON_ONCE(req_start >= seg_end); + /* start of request is past the last byte of this segment */ - if (req_start >= seg_end) { - /* reference the new lseg */ - if (pgio->pg_ops->pg_cleanup) - pgio->pg_ops->pg_cleanup(pgio); - if (pgio->pg_ops->pg_init) - pgio->pg_ops->pg_init(pgio, req); + if (req_start >= seg_end) return 0; - } /* adjust 'size' iff there are fewer bytes left in the * segment than what nfs_generic_pg_test returned */ diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index 2d05b756a8d6..99731e3e332f 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h @@ -593,6 +593,16 @@ pnfs_lseg_range_intersecting(const struct pnfs_layout_range *l1, return pnfs_is_range_intersecting(l1->offset, end1, l2->offset, end2); } +static inline bool +pnfs_lseg_request_intersecting(struct pnfs_layout_segment *lseg, struct nfs_page *req) +{ + u64 seg_last = pnfs_end_offset(lseg->pls_range.offset, lseg->pls_range.length); + u64 req_last = req_offset(req) + req->wb_bytes; + + return pnfs_is_range_intersecting(lseg->pls_range.offset, seg_last, + req_offset(req), req_last); +} + extern unsigned int layoutstats_timer; #ifdef NFS_DEBUG -- cgit v1.2.3 From b49c15f97c936ef5a536821f97e4dd8568369802 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Wed, 24 May 2017 07:55:44 -0400 Subject: NFSv4.0: Fix a lock leak in nfs40_walk_client_list Xiaolong Ye's kernel test robot detected the following Oops: [ 299.158991] BUG: scheduling while atomic: mount.nfs/9387/0x00000002 [ 299.169587] 2 locks held by mount.nfs/9387: [ 299.176165] #0: (nfs_clid_init_mutex){......}, at: [] nfs4_discover_server_trunking+0x47/0x1fc [ 299.201802] #1: (&(&nn->nfs_client_lock)->rlock){......}, at: [] nfs40_walk_client_list+0x2e9/0x338 [ 299.221979] CPU: 0 PID: 9387 Comm: mount.nfs Not tainted 4.11.0-rc7-00021-g14d1bbb #45 [ 299.235584] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.9.3-20161025_171302-gandalf 04/01/2014 [ 299.251176] Call Trace: [ 299.255192] dump_stack+0x61/0x7e [ 299.260416] __schedule_bug+0x65/0x74 [ 299.266208] __schedule+0x5d/0x87c [ 299.271883] schedule+0x89/0x9a [ 299.276937] schedule_timeout+0x232/0x289 [ 299.283223] ? detach_if_pending+0x10b/0x10b [ 299.289935] schedule_timeout_uninterruptible+0x2a/0x2c [ 299.298266] ? put_rpccred+0x3e/0x115 [ 299.304327] ? schedule_timeout_uninterruptible+0x2a/0x2c [ 299.312851] msleep+0x1e/0x22 [ 299.317612] nfs4_discover_server_trunking+0x102/0x1fc [ 299.325644] nfs4_init_client+0x13f/0x194 It looks as if we recently added a spin_lock() leak to nfs40_walk_client_list() when cleaning up the code. Reported-by: kernel test robot Fixes: 14d1bbb0ca42 ("NFS: Create a common nfs4_match_client() function") Cc: Anna Schumaker Signed-off-by: Trond Myklebust --- fs/nfs/nfs4client.c | 1 - 1 file changed, 1 deletion(-) diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c index 692a7a8bfc7a..66776f022111 100644 --- a/fs/nfs/nfs4client.c +++ b/fs/nfs/nfs4client.c @@ -582,7 +582,6 @@ int nfs40_walk_client_list(struct nfs_client *new, */ nfs4_schedule_path_down_recovery(pos); default: - spin_lock(&nn->nfs_client_lock); goto out; } -- cgit v1.2.3 From d38162e4b5c643733792f32be4ea107c831827b4 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 17 May 2017 15:15:57 +0200 Subject: Revert "drm/i915: Restore lost "Initialized i915" welcome message" This reverts commit bc5ca47c0af4f949ba889e666b7da65569e36093. Gabriel put this back into generic code with commit 75f6dfe3e652e1adef8cc1b073c89f3e22103a8f Author: Gabriel Krisman Bertazi Date: Wed Dec 28 12:32:11 2016 -0200 drm: Deduplicate driver initialization message but somehow he missed Chris' patch to add the message meanwhile. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=101025 Fixes: 75f6dfe3e652 ("drm: Deduplicate driver initialization message") Cc: Gabriel Krisman Bertazi Cc: Daniel Vetter Cc: Jani Nikula Cc: Chris Wilson Cc: # v4.11+ Reviewed-by: Gabriel Krisman Bertazi Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170517131557.7836-1-daniel.vetter@ffwll.ch (cherry picked from commit 6bdba81979b2c3c8fed0be62ca31c32c3129d85f) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_drv.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 3036d4835b0f..c994fe6e65b2 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1272,10 +1272,6 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent) dev_priv->ipc_enabled = false; - /* Everything is in place, we can now relax! */ - DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n", - driver.name, driver.major, driver.minor, driver.patchlevel, - driver.date, pci_name(pdev), dev_priv->drm.primary->index); if (IS_ENABLED(CONFIG_DRM_I915_DEBUG)) DRM_INFO("DRM_I915_DEBUG enabled\n"); if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)) -- cgit v1.2.3 From 2e0bb5b38f32eb21fe25e845721a205370adeffe Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 23 May 2017 20:44:12 +0100 Subject: drm/i915/selftests: Silence compiler warning in igt_ctx_exec The compiler doesn't always spot the guard that object is allocated on the first pass, leading to: drivers/gpu/drm/i915/selftests/i915_gem_context.c: warning: 'obj' may be used uninitialized in this function [-Wuninitialized]: => 370:8 v2: Make it more obvious by setting obj to NULL on the first pass and any later pass where we need to reallocate. Reported-by: Geert Uytterhoeven Fixes: 791ff39ae32a ("drm/i915: Live testing for context execution") Signed-off-by: Chris Wilson Cc: Joonas Lahtinen Cc: Tvrtko Ursulin Cc: Matthew Auld c: # v4.12-rc1+ Link: http://patchwork.freedesktop.org/patch/msgid/20170523194412.1195-1-chris@chris-wilson.co.uk Reviewed-by: Tvrtko Ursulin (cherry picked from commit ca83d5840cb641b2efb04db0b70fa56955dd1453) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/selftests/i915_gem_context.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/selftests/i915_gem_context.c index 1afb8b06e3e1..12b85b3278cd 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_context.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_context.c @@ -320,7 +320,7 @@ static unsigned long max_dwords(struct drm_i915_gem_object *obj) static int igt_ctx_exec(void *arg) { struct drm_i915_private *i915 = arg; - struct drm_i915_gem_object *obj; + struct drm_i915_gem_object *obj = NULL; struct drm_file *file; IGT_TIMEOUT(end_time); LIST_HEAD(objects); @@ -359,7 +359,7 @@ static int igt_ctx_exec(void *arg) } for_each_engine(engine, i915, id) { - if (dw == 0) { + if (!obj) { obj = create_test_object(ctx, file, &objects); if (IS_ERR(obj)) { err = PTR_ERR(obj); @@ -376,8 +376,10 @@ static int igt_ctx_exec(void *arg) goto out_unlock; } - if (++dw == max_dwords(obj)) + if (++dw == max_dwords(obj)) { + obj = NULL; dw = 0; + } ndwords++; } ncontexts++; -- cgit v1.2.3 From fc152d22d6e9fac95a9a990e6c29510bdf1b9425 Mon Sep 17 00:00:00 2001 From: Mateusz Jurczyk Date: Wed, 24 May 2017 15:55:00 +0200 Subject: x86/alternatives: Prevent uninitialized stack byte read in apply_alternatives() In the current form of the code, if a->replacementlen is 0, the reference to *insnbuf for comparison touches potentially garbage memory. While it doesn't affect the execution flow due to the subsequent a->replacementlen comparison, it is (rightly) detected as use of uninitialized memory by a runtime instrumentation currently under my development, and could be detected as such by other tools in the future, too (e.g. KMSAN). Fix the "false-positive" by reordering the conditions to first check the replacement instruction length before referencing specific opcode bytes. Signed-off-by: Mateusz Jurczyk Reviewed-by: Borislav Petkov Cc: Andy Lutomirski Link: http://lkml.kernel.org/r/20170524135500.27223-1-mjurczyk@google.com Signed-off-by: Thomas Gleixner --- arch/x86/kernel/alternative.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index c5b8f760473c..32e14d137416 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c @@ -409,8 +409,13 @@ void __init_or_module noinline apply_alternatives(struct alt_instr *start, memcpy(insnbuf, replacement, a->replacementlen); insnbuf_sz = a->replacementlen; - /* 0xe8 is a relative jump; fix the offset. */ - if (*insnbuf == 0xe8 && a->replacementlen == 5) { + /* + * 0xe8 is a relative jump; fix the offset. + * + * Instruction length is checked before the opcode to avoid + * accessing uninitialized bytes for zero-length replacements. + */ + if (a->replacementlen == 5 && *insnbuf == 0xe8) { *(s32 *)(insnbuf + 1) += replacement - instr; DPRINTK("Fix CALL offset: 0x%x, CALL 0x%lx", *(s32 *)(insnbuf + 1), -- cgit v1.2.3 From 3e4240da0e3673637c1c995bdd14cfdbc8f4dc4c Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Wed, 24 May 2017 01:39:35 +0200 Subject: Revert "ata: sata_mv: Convert to devm_ioremap_resource()" This reverts commit 368e5fbdfc60732643f34f538823ed4bc8829827. devm_ioremap_resource() enforces that there are no overlapping resources, where as devm_ioremap() does not. The sata phy driver needs a subset of the sata IO address space, so maps some of the sata address space. As a result, sata_mv now fails to probe, reporting it cannot get its resources, and so we don't have any SATA disks. Signed-off-by: Andrew Lunn Acked-by: Gregory CLEMENT Cc: stable@vger.kernel.org # v4.11+ Signed-off-by: Tejun Heo --- drivers/ata/sata_mv.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index b66bcda88320..3b2246dded74 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -4067,7 +4067,6 @@ static int mv_platform_probe(struct platform_device *pdev) struct ata_host *host; struct mv_host_priv *hpriv; struct resource *res; - void __iomem *mmio; int n_ports = 0, irq = 0; int rc; int port; @@ -4086,9 +4085,8 @@ static int mv_platform_probe(struct platform_device *pdev) * Get the register base first */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - mmio = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(mmio)) - return PTR_ERR(mmio); + if (res == NULL) + return -EINVAL; /* allocate host */ if (pdev->dev.of_node) { @@ -4132,7 +4130,12 @@ static int mv_platform_probe(struct platform_device *pdev) hpriv->board_idx = chip_soc; host->iomap = NULL; - hpriv->base = mmio - SATAHC0_REG_BASE; + hpriv->base = devm_ioremap(&pdev->dev, res->start, + resource_size(res)); + if (!hpriv->base) + return -ENOMEM; + + hpriv->base -= SATAHC0_REG_BASE; hpriv->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(hpriv->clk)) -- cgit v1.2.3 From 44f73dc42c11398d7b84e94365a485ebd6420798 Mon Sep 17 00:00:00 2001 From: Antoine Tenart Date: Wed, 24 May 2017 16:10:32 +0200 Subject: arm64: marvell: dts: fix interrupts in 7k/8k crypto nodes The cryptographic engine nodes have an interrupt which is configured as both edge and level, which makes no sense at all. Fix this by configuring it the right way (level). Signed-off-by: Antoine Tenart Signed-off-by: Gregory CLEMENT --- arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi | 3 +-- arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi b/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi index ac8df5201cd6..b4bc42ece754 100644 --- a/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi +++ b/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi @@ -231,8 +231,7 @@ cpm_crypto: crypto@800000 { compatible = "inside-secure,safexcel-eip197"; reg = <0x800000 0x200000>; - interrupts = , + interrupts = , , , , diff --git a/arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi b/arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi index 7740a75a8230..6e2058847ddc 100644 --- a/arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi +++ b/arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi @@ -221,8 +221,7 @@ cps_crypto: crypto@800000 { compatible = "inside-secure,safexcel-eip197"; reg = <0x800000 0x200000>; - interrupts = , + interrupts = , , , , -- cgit v1.2.3 From 46e3813d72abb018f0cd6e72389004db8728c738 Mon Sep 17 00:00:00 2001 From: "Guilherme G. Piccoli" Date: Thu, 18 May 2017 18:34:35 -0300 Subject: MAINTAINERS/serial: Change maintainer of jsm driver Gabriel will no longer maintain this driver, so I'm adding myself as maintainer. Thanks for all your work on jsm driver Gabriel. Signed-off-by: Guilherme G. Piccoli Acked-by: Gabriel Krisman Bertazi Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index f7d568b8f133..a3030d04ef41 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7136,7 +7136,7 @@ S: Maintained F: drivers/media/platform/rcar_jpu.c JSM Neo PCI based serial card -M: Gabriel Krisman Bertazi +M: Guilherme G. Piccoli L: linux-serial@vger.kernel.org S: Maintained F: drivers/tty/serial/jsm/ -- cgit v1.2.3 From 41c25707d21716826e3c1f60967f5550610ec1c9 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 24 May 2017 12:03:48 -0400 Subject: cpuset: consider dying css as offline In most cases, a cgroup controller don't care about the liftimes of cgroups. For the controller, a css becomes online when ->css_online() is called on it and offline when ->css_offline() is called. However, cpuset is special in that the user interface it exposes cares whether certain cgroups exist or not. Combined with the RCU delay between cgroup removal and css offlining, this can lead to user visible behavior oddities where operations which should succeed after cgroup removals fail for some time period. The effects of cgroup removals are delayed when seen from userland. This patch adds css_is_dying() which tests whether offline is pending and updates is_cpuset_online() so that the function returns false also while offline is pending. This gets rid of the userland visible delays. Signed-off-by: Tejun Heo Reported-by: Daniel Jordan Link: http://lkml.kernel.org/r/327ca1f5-7957-fbb9-9e5f-9ba149d40ba2@oracle.com Cc: stable@vger.kernel.org Signed-off-by: Tejun Heo --- include/linux/cgroup.h | 20 ++++++++++++++++++++ kernel/cgroup/cpuset.c | 4 ++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index ed2573e149fa..710a005c6b7a 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h @@ -343,6 +343,26 @@ static inline bool css_tryget_online(struct cgroup_subsys_state *css) return true; } +/** + * css_is_dying - test whether the specified css is dying + * @css: target css + * + * Test whether @css is in the process of offlining or already offline. In + * most cases, ->css_online() and ->css_offline() callbacks should be + * enough; however, the actual offline operations are RCU delayed and this + * test returns %true also when @css is scheduled to be offlined. + * + * This is useful, for example, when the use case requires synchronous + * behavior with respect to cgroup removal. cgroup removal schedules css + * offlining but the css can seem alive while the operation is being + * delayed. If the delay affects user visible semantics, this test can be + * used to resolve the situation. + */ +static inline bool css_is_dying(struct cgroup_subsys_state *css) +{ + return !(css->flags & CSS_NO_REF) && percpu_ref_is_dying(&css->refcnt); +} + /** * css_put - put a css reference * @css: target css diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c index f6501f4f6040..ae643412948a 100644 --- a/kernel/cgroup/cpuset.c +++ b/kernel/cgroup/cpuset.c @@ -176,9 +176,9 @@ typedef enum { } cpuset_flagbits_t; /* convenient tests for these bits */ -static inline bool is_cpuset_online(const struct cpuset *cs) +static inline bool is_cpuset_online(struct cpuset *cs) { - return test_bit(CS_ONLINE, &cs->flags); + return test_bit(CS_ONLINE, &cs->flags) && !css_is_dying(&cs->css); } static inline int is_cpu_exclusive(const struct cpuset *cs) -- cgit v1.2.3 From 4efda5f2130da033aeedc5b3205569893b910de2 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 24 May 2017 10:19:45 +0200 Subject: ASoC: Fix use-after-free at card unregistration soc_cleanup_card_resources() call snd_card_free() at the last of its procedure. This turned out to lead to a use-after-free. PCM runtimes have been already removed via soc_remove_pcm_runtimes(), while it's dereferenced later in soc_pcm_free() called via snd_card_free(). The fix is simple: just move the snd_card_free() call to the beginning of the whole procedure. This also gives another benefit: it guarantees that all operations have been shut down before actually releasing the resources, which was racy until now. Reported-and-tested-by: Robert Jarzmik Signed-off-by: Takashi Iwai Signed-off-by: Mark Brown Cc: --- sound/soc/soc-core.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index aae099c0e502..754e3ef8d7ae 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2286,6 +2286,9 @@ static int soc_cleanup_card_resources(struct snd_soc_card *card) list_for_each_entry(rtd, &card->rtd_list, list) flush_delayed_work(&rtd->delayed_work); + /* free the ALSA card at first; this syncs with pending operations */ + snd_card_free(card->snd_card); + /* remove and free each DAI */ soc_remove_dai_links(card); soc_remove_pcm_runtimes(card); @@ -2300,9 +2303,7 @@ static int soc_cleanup_card_resources(struct snd_soc_card *card) if (card->remove) card->remove(card); - snd_card_free(card->snd_card); return 0; - } /* removes a socdev */ -- cgit v1.2.3 From 3a1672bb0186e940fc8521d19069f57690e850c2 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Wed, 24 May 2017 11:01:32 +0100 Subject: MAINTAINERS: Update email address for patches to Wolfson parts A somewhat overdue update of the address for sending patches on Wolfson parts to since our acquision a couple of years ago by Cirrus Logic. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index f7d568b8f133..517829e3bd1d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13858,7 +13858,7 @@ S: Odd fixes F: drivers/net/wireless/wl3501* WOLFSON MICROELECTRONICS DRIVERS -L: patches@opensource.wolfsonmicro.com +L: patches@opensource.cirrus.com T: git https://github.com/CirrusLogic/linux-drivers.git W: https://github.com/CirrusLogic/linux-drivers/wiki S: Supported -- cgit v1.2.3 From 7819a942de7b993771bd9377babc80485fe7606b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 24 May 2017 01:17:10 +0000 Subject: ASoC: rsnd: SSI PIO adjust to 24bit mode commit 90431eb49bff ("ASoC: rsnd: don't use PDTA bit for 24bit on SSI") fixups 24bit mode data alignment, but PIO was not cared. This patch fixes PIO mode 24bit data alignment Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/ssi.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index c224695c1484..91e5c07911b4 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -550,6 +550,13 @@ static void __rsnd_ssi_interrupt(struct rsnd_mod *mod, struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); u32 *buf = (u32 *)(runtime->dma_area + rsnd_dai_pointer_offset(io, 0)); + int shift = 0; + + switch (runtime->sample_bits) { + case 32: + shift = 8; + break; + } /* * 8/16/32 data can be assesse to TDR/RDR register @@ -557,9 +564,9 @@ static void __rsnd_ssi_interrupt(struct rsnd_mod *mod, * see rsnd_ssi_init() */ if (rsnd_io_is_play(io)) - rsnd_mod_write(mod, SSITDR, *buf); + rsnd_mod_write(mod, SSITDR, (*buf) << shift); else - *buf = rsnd_mod_read(mod, SSIRDR); + *buf = (rsnd_mod_read(mod, SSIRDR) >> shift); elapsed = rsnd_dai_pointer_update(io, sizeof(*buf)); } -- cgit v1.2.3 From 5cd1f5c32132101955d7f0e1955249a84f9b6fd9 Mon Sep 17 00:00:00 2001 From: Pardha Saradhi K Date: Mon, 15 May 2017 19:44:29 +0530 Subject: ASoC: Intel: Skylake: Fix IPC rx_list corruption In SKL+ platforms, all IPC commands are serialised, i.e. the driver sends a new IPC to DSP, only after receiving a reply from the firmware for the current IPC. Hence it seems apparent that there is only a single modifier of the IPC RX List. However, during an IPC timeout case in a multithreaded environment, there is a possibility of the list element being deleted two times if not properly protected. So, use spin lock save/restore to prevent rx_list corruption. Signed-off-by: Pardha Saradhi K Signed-off-by: Subhransu S. Prusty Acked-by: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl-sst-ipc.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sound/soc/intel/skylake/skl-sst-ipc.c b/sound/soc/intel/skylake/skl-sst-ipc.c index 58c525096a7c..498b15345b1a 100644 --- a/sound/soc/intel/skylake/skl-sst-ipc.c +++ b/sound/soc/intel/skylake/skl-sst-ipc.c @@ -413,8 +413,11 @@ static void skl_ipc_process_reply(struct sst_generic_ipc *ipc, u32 reply = header.primary & IPC_GLB_REPLY_STATUS_MASK; u64 *ipc_header = (u64 *)(&header); struct skl_sst *skl = container_of(ipc, struct skl_sst, ipc); + unsigned long flags; + spin_lock_irqsave(&ipc->dsp->spinlock, flags); msg = skl_ipc_reply_get_msg(ipc, *ipc_header); + spin_unlock_irqrestore(&ipc->dsp->spinlock, flags); if (msg == NULL) { dev_dbg(ipc->dev, "ipc: rx list is empty\n"); return; @@ -456,8 +459,10 @@ static void skl_ipc_process_reply(struct sst_generic_ipc *ipc, } } + spin_lock_irqsave(&ipc->dsp->spinlock, flags); list_del(&msg->list); sst_ipc_tx_msg_reply_complete(ipc, msg); + spin_unlock_irqrestore(&ipc->dsp->spinlock, flags); } irqreturn_t skl_dsp_irq_thread_handler(int irq, void *context) -- cgit v1.2.3 From 0a716776914ed9d7ca90b48041e6767693bfb672 Mon Sep 17 00:00:00 2001 From: Shreyas NC Date: Mon, 15 May 2017 19:44:30 +0530 Subject: ASoC: Intel: Skylake: Fix to parse consecutive string tkns in manifest Element size in the manifest should be updated for each token, so that the loop can parse all the string elements in the manifest. This was not happening when more than two string elements appear consecutively, as it is not updated with correct string element size. Fixed with this patch. Signed-off-by: Shreyas NC Signed-off-by: Subhransu S. Prusty Acked-by: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl-topology.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index 3a99712e44a8..64a0f8ed33e1 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -2502,7 +2502,7 @@ static int skl_tplg_get_manifest_tkn(struct device *dev, if (ret < 0) return ret; - tkn_count += ret; + tkn_count = ret; tuple_size += tkn_count * sizeof(struct snd_soc_tplg_vendor_string_elem); -- cgit v1.2.3 From ddff7ed45edce4a4c92949d3c61cd25d229c4a14 Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Tue, 23 May 2017 16:50:47 +0200 Subject: scsi: qla2xxx: don't disable a not previously enabled PCI device When pci_enable_device() or pci_enable_device_mem() fail in qla2x00_probe_one() we bail out but do a call to pci_disable_device(). This causes the dev_WARN_ON() in pci_disable_device() to trigger, as the device wasn't enabled previously. So instead of taking the 'probe_out' error path we can directly return *iff* one of the pci_enable_device() calls fails. Additionally rename the 'probe_out' goto label's name to the more descriptive 'disable_device'. Signed-off-by: Johannes Thumshirn Fixes: e315cd28b9ef ("[SCSI] qla2xxx: Code changes for qla data structure refactoring") Cc: Reviewed-by: Bart Van Assche Reviewed-by: Giridhar Malavali Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_os.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 1c7957903283..af25d8afd42a 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -2623,10 +2623,10 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) if (mem_only) { if (pci_enable_device_mem(pdev)) - goto probe_out; + return ret; } else { if (pci_enable_device(pdev)) - goto probe_out; + return ret; } /* This may fail but that's ok */ @@ -2636,7 +2636,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) if (!ha) { ql_log_pci(ql_log_fatal, pdev, 0x0009, "Unable to allocate memory for ha.\n"); - goto probe_out; + goto disable_device; } ql_dbg_pci(ql_dbg_init, pdev, 0x000a, "Memory allocated for ha=%p.\n", ha); @@ -3254,7 +3254,7 @@ iospace_config_failed: pci_release_selected_regions(ha->pdev, ha->bars); kfree(ha); -probe_out: +disable_device: pci_disable_device(pdev); return ret; } -- cgit v1.2.3 From c2dd893a3b0772d1c680e109b9d5715d7f73022b Mon Sep 17 00:00:00 2001 From: Maurizio Lombardi Date: Wed, 24 May 2017 14:09:44 +0200 Subject: scsi: bnx2fc: fix race condition in bnx2fc_get_host_stats() If multiple tasks attempt to read the stats, it may happen that the start_req_done completion is re-initialized while still being used by another task, causing a list corruption. This patch fixes the bug by adding a mutex to serialize the calls to bnx2fc_get_host_stats(). WARNING: at lib/list_debug.c:48 list_del+0x6e/0xa0() (Not tainted) Hardware name: PowerEdge R820 list_del corruption. prev->next should be ffff882035627d90, but was ffff884069541588 Pid: 40267, comm: perl Not tainted 2.6.32-642.3.1.el6.x86_64 #1 Call Trace: [] ? warn_slowpath_common+0x91/0xe0 [] ? warn_slowpath_fmt+0x46/0x60 [] ? list_del+0x6e/0xa0 [] ? wait_for_common+0x14d/0x180 [] ? default_wake_function+0x0/0x20 [] ? wait_for_completion_timeout+0x13/0x20 [] ? bnx2fc_get_host_stats+0xa1/0x280 [bnx2fc] [] ? fc_stat_show+0x90/0xc0 [scsi_transport_fc] [] ? show_fcstat_tx_frames+0x16/0x20 [scsi_transport_fc] [] ? dev_attr_show+0x27/0x50 [] ? __get_free_pages+0xe/0x50 [] ? sysfs_read_file+0x111/0x200 [] ? vfs_read+0xb5/0x1a0 [] ? fget_light_pos+0x16/0x50 [] ? sys_read+0x51/0xb0 [] ? __audit_syscall_exit+0x25e/0x290 [] ? system_call_fastpath+0x16/0x1b Signed-off-by: Maurizio Lombardi Acked-by: Chad Dupuis Signed-off-by: Martin K. Petersen --- drivers/scsi/bnx2fc/bnx2fc.h | 1 + drivers/scsi/bnx2fc/bnx2fc_fcoe.c | 10 ++++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/bnx2fc/bnx2fc.h b/drivers/scsi/bnx2fc/bnx2fc.h index 4fc8ed5fe067..1f424e40afdf 100644 --- a/drivers/scsi/bnx2fc/bnx2fc.h +++ b/drivers/scsi/bnx2fc/bnx2fc.h @@ -191,6 +191,7 @@ struct bnx2fc_hba { struct bnx2fc_cmd_mgr *cmd_mgr; spinlock_t hba_lock; struct mutex hba_mutex; + struct mutex hba_stats_mutex; unsigned long adapter_state; #define ADAPTER_STATE_UP 0 #define ADAPTER_STATE_GOING_DOWN 1 diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index 93b5a0012417..902722dc4ce3 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -663,15 +663,17 @@ static struct fc_host_statistics *bnx2fc_get_host_stats(struct Scsi_Host *shost) if (!fw_stats) return NULL; + mutex_lock(&hba->hba_stats_mutex); + bnx2fc_stats = fc_get_host_stats(shost); init_completion(&hba->stat_req_done); if (bnx2fc_send_stat_req(hba)) - return bnx2fc_stats; + goto unlock_stats_mutex; rc = wait_for_completion_timeout(&hba->stat_req_done, (2 * HZ)); if (!rc) { BNX2FC_HBA_DBG(lport, "FW stat req timed out\n"); - return bnx2fc_stats; + goto unlock_stats_mutex; } BNX2FC_STATS(hba, rx_stat2, fc_crc_cnt); bnx2fc_stats->invalid_crc_count += hba->bfw_stats.fc_crc_cnt; @@ -693,6 +695,9 @@ static struct fc_host_statistics *bnx2fc_get_host_stats(struct Scsi_Host *shost) memcpy(&hba->prev_stats, hba->stats_buffer, sizeof(struct fcoe_statistics_params)); + +unlock_stats_mutex: + mutex_unlock(&hba->hba_stats_mutex); return bnx2fc_stats; } @@ -1340,6 +1345,7 @@ static struct bnx2fc_hba *bnx2fc_hba_create(struct cnic_dev *cnic) } spin_lock_init(&hba->hba_lock); mutex_init(&hba->hba_mutex); + mutex_init(&hba->hba_stats_mutex); hba->cnic = cnic; -- cgit v1.2.3 From 3ab2137915aea0ce7b3ec02e0f260ecc0f1c289d Mon Sep 17 00:00:00 2001 From: Xin Long Date: Tue, 23 May 2017 13:28:54 +0800 Subject: sctp: fix stream update when processing dupcookie Since commit 3dbcc105d556 ("sctp: alloc stream info when initializing asoc"), stream and stream.out info are always alloced when creating an asoc. So it's not correct to check !asoc->stream before updating stream info when processing dupcookie, but would be better to check asoc state instead. Fixes: 3dbcc105d556 ("sctp: alloc stream info when initializing asoc") Signed-off-by: Xin Long Acked-by: Neil Horman Acked-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/associola.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/sctp/associola.c b/net/sctp/associola.c index a9708da28eb5..95238284c422 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -1176,7 +1176,9 @@ void sctp_assoc_update(struct sctp_association *asoc, asoc->ctsn_ack_point = asoc->next_tsn - 1; asoc->adv_peer_ack_point = asoc->ctsn_ack_point; - if (!asoc->stream) { + + if (sctp_state(asoc, COOKIE_WAIT)) { + sctp_stream_free(asoc->stream); asoc->stream = new->stream; new->stream = NULL; } -- cgit v1.2.3 From 7e06297768886337707f5833942b3bd524a6d3d5 Mon Sep 17 00:00:00 2001 From: Xin Long Date: Tue, 23 May 2017 13:28:55 +0800 Subject: sctp: set new_asoc temp when processing dupcookie After sctp changed to use transport hashtable, a transport would be added into global hashtable when adding the peer to an asoc, then the asoc can be got by searching the transport in the hashtbale. The problem is when processing dupcookie in sctp_sf_do_5_2_4_dupcook, a new asoc would be created. A peer with the same addr and port as the one in the old asoc might be added into the new asoc, but fail to be added into the hashtable, as they also belong to the same sk. It causes that sctp's dupcookie processing can not really work. Since the new asoc will be freed after copying it's information to the old asoc, it's more like a temp asoc. So this patch is to fix it by setting it as a temp asoc to avoid adding it's any transport into the hashtable and also avoid allocing assoc_id. An extra thing it has to do is to also alloc stream info for any temp asoc, as sctp dupcookie process needs it to update old asoc. But I don't think it would hurt something, as a temp asoc would always be freed after finishing processing cookie echo packet. Reported-by: Jianwen Ji Signed-off-by: Xin Long Acked-by: Neil Horman Acked-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/sm_make_chunk.c | 13 ++++--------- net/sctp/sm_statefuns.c | 3 +++ 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 8a08f13469c4..92e332e17391 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -2454,16 +2454,11 @@ int sctp_process_init(struct sctp_association *asoc, struct sctp_chunk *chunk, * stream sequence number shall be set to 0. */ - /* Allocate storage for the negotiated streams if it is not a temporary - * association. - */ - if (!asoc->temp) { - if (sctp_stream_init(asoc, gfp)) - goto clean_up; + if (sctp_stream_init(asoc, gfp)) + goto clean_up; - if (sctp_assoc_set_id(asoc, gfp)) - goto clean_up; - } + if (!asoc->temp && sctp_assoc_set_id(asoc, gfp)) + goto clean_up; /* ADDIP Section 4.1 ASCONF Chunk Procedures * diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 4f5e6cfc7f60..f863b5573e42 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -2088,6 +2088,9 @@ sctp_disposition_t sctp_sf_do_5_2_4_dupcook(struct net *net, } } + /* Set temp so that it won't be added into hashtable */ + new_asoc->temp = 1; + /* Compare the tie_tag in cookie with the verification tag of * current association. */ -- cgit v1.2.3 From 159a07604a99bd01e7db112de08d53dc4fcad109 Mon Sep 17 00:00:00 2001 From: Quentin Schulz Date: Tue, 23 May 2017 11:48:08 +0200 Subject: net: fec: add post PHY reset delay DT property Some PHY require to wait for a bit after the reset GPIO has been toggled. This adds support for the DT property `phy-reset-post-delay` which gives the delay in milliseconds to wait after reset. If the DT property is not given, no delay is observed. Post reset delay greater than 1000ms are invalid. Signed-off-by: Quentin Schulz Reviewed-by: Andrew Lunn Acked-by: Fugang Duan Signed-off-by: David S. Miller --- Documentation/devicetree/bindings/net/fsl-fec.txt | 4 ++++ drivers/net/ethernet/freescale/fec_main.c | 16 +++++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/net/fsl-fec.txt b/Documentation/devicetree/bindings/net/fsl-fec.txt index a1e3693cca16..6f55bdd52f8a 100644 --- a/Documentation/devicetree/bindings/net/fsl-fec.txt +++ b/Documentation/devicetree/bindings/net/fsl-fec.txt @@ -15,6 +15,10 @@ Optional properties: - phy-reset-active-high : If present then the reset sequence using the GPIO specified in the "phy-reset-gpios" property is reversed (H=reset state, L=operation state). +- phy-reset-post-delay : Post reset delay in milliseconds. If present then + a delay of phy-reset-post-delay milliseconds will be observed after the + phy-reset-gpios has been toggled. Can be omitted thus no delay is + observed. Delay is in range of 1ms to 1000ms. Other delays are invalid. - phy-supply : regulator that powers the Ethernet PHY. - phy-handle : phandle to the PHY device connected to this device. - fixed-link : Assume a fixed link. See fixed-link.txt in the same directory. diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 56a563f90b0b..f7c8649fd28f 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -3192,7 +3192,7 @@ static int fec_reset_phy(struct platform_device *pdev) { int err, phy_reset; bool active_high = false; - int msec = 1; + int msec = 1, phy_post_delay = 0; struct device_node *np = pdev->dev.of_node; if (!np) @@ -3209,6 +3209,11 @@ static int fec_reset_phy(struct platform_device *pdev) else if (!gpio_is_valid(phy_reset)) return 0; + err = of_property_read_u32(np, "phy-reset-post-delay", &phy_post_delay); + /* valid reset duration should be less than 1s */ + if (!err && phy_post_delay > 1000) + return -EINVAL; + active_high = of_property_read_bool(np, "phy-reset-active-high"); err = devm_gpio_request_one(&pdev->dev, phy_reset, @@ -3226,6 +3231,15 @@ static int fec_reset_phy(struct platform_device *pdev) gpio_set_value_cansleep(phy_reset, !active_high); + if (!phy_post_delay) + return 0; + + if (phy_post_delay > 20) + msleep(phy_post_delay); + else + usleep_range(phy_post_delay * 1000, + phy_post_delay * 1000 + 1000); + return 0; } #else /* CONFIG_OF */ -- cgit v1.2.3 From 0ff50e83b5122e836ca492fefb11656b225ac29c Mon Sep 17 00:00:00 2001 From: Alexander Potapenko Date: Tue, 23 May 2017 13:20:28 +0200 Subject: net: rtnetlink: bail out from rtnl_fdb_dump() on parse error rtnl_fdb_dump() failed to check the result of nlmsg_parse(), which led to contents of |ifm| being uninitialized because nlh->nlmsglen was too small to accommodate |ifm|. The uninitialized data may affect some branches and result in unwanted effects, although kernel data doesn't seem to leak to the userspace directly. The bug has been detected with KMSAN and syzkaller. For the record, here is the KMSAN report: ================================================================== BUG: KMSAN: use of unitialized memory in rtnl_fdb_dump+0x5dc/0x1000 CPU: 0 PID: 1039 Comm: probe Not tainted 4.11.0-rc5+ #2727 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 Call Trace: __dump_stack lib/dump_stack.c:16 dump_stack+0x143/0x1b0 lib/dump_stack.c:52 kmsan_report+0x12a/0x180 mm/kmsan/kmsan.c:1007 __kmsan_warning_32+0x66/0xb0 mm/kmsan/kmsan_instr.c:491 rtnl_fdb_dump+0x5dc/0x1000 net/core/rtnetlink.c:3230 netlink_dump+0x84f/0x1190 net/netlink/af_netlink.c:2168 __netlink_dump_start+0xc97/0xe50 net/netlink/af_netlink.c:2258 netlink_dump_start ./include/linux/netlink.h:165 rtnetlink_rcv_msg+0xae9/0xb40 net/core/rtnetlink.c:4094 netlink_rcv_skb+0x339/0x5a0 net/netlink/af_netlink.c:2339 rtnetlink_rcv+0x83/0xa0 net/core/rtnetlink.c:4110 netlink_unicast_kernel net/netlink/af_netlink.c:1272 netlink_unicast+0x13b7/0x1480 net/netlink/af_netlink.c:1298 netlink_sendmsg+0x10b8/0x10f0 net/netlink/af_netlink.c:1844 sock_sendmsg_nosec net/socket.c:633 sock_sendmsg net/socket.c:643 ___sys_sendmsg+0xd4b/0x10f0 net/socket.c:1997 __sys_sendmsg net/socket.c:2031 SYSC_sendmsg+0x2c6/0x3f0 net/socket.c:2042 SyS_sendmsg+0x87/0xb0 net/socket.c:2038 do_syscall_64+0x102/0x150 arch/x86/entry/common.c:285 entry_SYSCALL64_slow_path+0x25/0x25 arch/x86/entry/entry_64.S:246 RIP: 0033:0x401300 RSP: 002b:00007ffc3b0e6d58 EFLAGS: 00000246 ORIG_RAX: 000000000000002e RAX: ffffffffffffffda RBX: 00000000004002b0 RCX: 0000000000401300 RDX: 0000000000000000 RSI: 00007ffc3b0e6d80 RDI: 0000000000000003 RBP: 00007ffc3b0e6e00 R08: 000000000000000b R09: 0000000000000004 R10: 000000000000000d R11: 0000000000000246 R12: 0000000000000000 R13: 00000000004065a0 R14: 0000000000406630 R15: 0000000000000000 origin: 000000008fe00056 save_stack_trace+0x59/0x60 arch/x86/kernel/stacktrace.c:59 kmsan_save_stack_with_flags mm/kmsan/kmsan.c:352 kmsan_internal_poison_shadow+0xb1/0x1a0 mm/kmsan/kmsan.c:247 kmsan_poison_shadow+0x6d/0xc0 mm/kmsan/kmsan.c:260 slab_alloc_node mm/slub.c:2743 __kmalloc_node_track_caller+0x1f4/0x390 mm/slub.c:4349 __kmalloc_reserve net/core/skbuff.c:138 __alloc_skb+0x2cd/0x740 net/core/skbuff.c:231 alloc_skb ./include/linux/skbuff.h:933 netlink_alloc_large_skb net/netlink/af_netlink.c:1144 netlink_sendmsg+0x934/0x10f0 net/netlink/af_netlink.c:1819 sock_sendmsg_nosec net/socket.c:633 sock_sendmsg net/socket.c:643 ___sys_sendmsg+0xd4b/0x10f0 net/socket.c:1997 __sys_sendmsg net/socket.c:2031 SYSC_sendmsg+0x2c6/0x3f0 net/socket.c:2042 SyS_sendmsg+0x87/0xb0 net/socket.c:2038 do_syscall_64+0x102/0x150 arch/x86/entry/common.c:285 return_from_SYSCALL_64+0x0/0x6a arch/x86/entry/entry_64.S:246 ================================================================== and the reproducer: ================================================================== #include #include #include #include int main() { int sock = socket(PF_NETLINK, SOCK_DGRAM | SOCK_NONBLOCK, 0); struct msghdr msg; memset(&msg, 0, sizeof(msg)); char nlmsg_buf[32]; memset(nlmsg_buf, 0, sizeof(nlmsg_buf)); struct nlmsghdr *nlmsg = nlmsg_buf; nlmsg->nlmsg_len = 0x11; nlmsg->nlmsg_type = 0x1e; // RTM_NEWROUTE = RTM_BASE + 0x0e // type = 0x0e = 1110b // kind = 2 nlmsg->nlmsg_flags = 0x101; // NLM_F_ROOT | NLM_F_REQUEST nlmsg->nlmsg_seq = 0; nlmsg->nlmsg_pid = 0; nlmsg_buf[16] = (char)7; struct iovec iov; iov.iov_base = nlmsg_buf; iov.iov_len = 17; msg.msg_iov = &iov; msg.msg_iovlen = 1; sendmsg(sock, &msg, 0); return 0; } ================================================================== Signed-off-by: Alexander Potapenko Signed-off-by: David S. Miller --- net/core/rtnetlink.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 49a279a7cc15..9e2c0a7cb325 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -3231,8 +3231,11 @@ static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb) int err = 0; int fidx = 0; - if (nlmsg_parse(cb->nlh, sizeof(struct ifinfomsg), tb, - IFLA_MAX, ifla_policy, NULL) == 0) { + err = nlmsg_parse(cb->nlh, sizeof(struct ifinfomsg), tb, + IFLA_MAX, ifla_policy, NULL); + if (err < 0) { + return -EINVAL; + } else if (err == 0) { if (tb[IFLA_MASTER]) br_idx = nla_get_u32(tb[IFLA_MASTER]); } -- cgit v1.2.3 From cd47512e51190efc34a6b90d5c6b54de036ea421 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 23 May 2017 08:19:49 -0700 Subject: net/phy: fix mdio-octeon dependency and build Fix build errors by making this driver depend on OF_MDIO, like several other similar drivers do. drivers/built-in.o: In function `octeon_mdiobus_remove': mdio-octeon.c:(.text+0x196ee0): undefined reference to `mdiobus_unregister' mdio-octeon.c:(.text+0x196ee8): undefined reference to `mdiobus_free' drivers/built-in.o: In function `octeon_mdiobus_probe': mdio-octeon.c:(.text+0x196f1d): undefined reference to `devm_mdiobus_alloc_size' mdio-octeon.c:(.text+0x196ffe): undefined reference to `of_mdiobus_register' mdio-octeon.c:(.text+0x197010): undefined reference to `mdiobus_free' Signed-off-by: Randy Dunlap Cc: Andrew Lunn Cc: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 60ffc9da6a28..c360dd6ead22 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -108,7 +108,7 @@ config MDIO_MOXART config MDIO_OCTEON tristate "Octeon and some ThunderX SOCs MDIO buses" depends on 64BIT - depends on HAS_IOMEM + depends on HAS_IOMEM && OF_MDIO select MDIO_CAVIUM help This module provides a driver for the Octeon and ThunderX MDIO -- cgit v1.2.3 From f2899788353c13891412b273fdff5f02d49aa40f Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Tue, 23 May 2017 17:49:13 +0200 Subject: net: phy: marvell: Limit errata to 88m1101 The 88m1101 has an errata when configuring autoneg. However, it was being applied to many other Marvell PHYs as well. Limit its scope to just the 88m1101. Fixes: 76884679c644 ("phylib: Add support for Marvell 88e1111S and 88e1145") Reported-by: Daniel Walker Signed-off-by: Andrew Lunn Acked-by: Harini Katakam Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/marvell.c | 66 ++++++++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 29 deletions(-) diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index 272b051a0199..9097e42bec2e 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -255,34 +255,6 @@ static int marvell_config_aneg(struct phy_device *phydev) { int err; - /* The Marvell PHY has an errata which requires - * that certain registers get written in order - * to restart autonegotiation */ - err = phy_write(phydev, MII_BMCR, BMCR_RESET); - - if (err < 0) - return err; - - err = phy_write(phydev, 0x1d, 0x1f); - if (err < 0) - return err; - - err = phy_write(phydev, 0x1e, 0x200c); - if (err < 0) - return err; - - err = phy_write(phydev, 0x1d, 0x5); - if (err < 0) - return err; - - err = phy_write(phydev, 0x1e, 0); - if (err < 0) - return err; - - err = phy_write(phydev, 0x1e, 0x100); - if (err < 0) - return err; - err = marvell_set_polarity(phydev, phydev->mdix_ctrl); if (err < 0) return err; @@ -316,6 +288,42 @@ static int marvell_config_aneg(struct phy_device *phydev) return 0; } +static int m88e1101_config_aneg(struct phy_device *phydev) +{ + int err; + + /* This Marvell PHY has an errata which requires + * that certain registers get written in order + * to restart autonegotiation + */ + err = phy_write(phydev, MII_BMCR, BMCR_RESET); + + if (err < 0) + return err; + + err = phy_write(phydev, 0x1d, 0x1f); + if (err < 0) + return err; + + err = phy_write(phydev, 0x1e, 0x200c); + if (err < 0) + return err; + + err = phy_write(phydev, 0x1d, 0x5); + if (err < 0) + return err; + + err = phy_write(phydev, 0x1e, 0); + if (err < 0) + return err; + + err = phy_write(phydev, 0x1e, 0x100); + if (err < 0) + return err; + + return marvell_config_aneg(phydev); +} + static int m88e1111_config_aneg(struct phy_device *phydev) { int err; @@ -1892,7 +1900,7 @@ static struct phy_driver marvell_drivers[] = { .flags = PHY_HAS_INTERRUPT, .probe = marvell_probe, .config_init = &marvell_config_init, - .config_aneg = &marvell_config_aneg, + .config_aneg = &m88e1101_config_aneg, .read_status = &genphy_read_status, .ack_interrupt = &marvell_ack_interrupt, .config_intr = &marvell_config_intr, -- cgit v1.2.3 From 35d2f80b07bbe03fb358afb0bdeff7437a7d67ff Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Tue, 23 May 2017 13:38:41 -0400 Subject: vlan: Fix tcp checksum offloads in Q-in-Q vlans It appears that TCP checksum offloading has been broken for Q-in-Q vlans. The behavior was execerbated by the series commit afb0bc972b52 ("Merge branch 'stacked_vlan_tso'") that that enabled accleleration features on stacked vlans. However, event without that series, it is possible to trigger this issue. It just requires a lot more specialized configuration. The root cause is the interaction between how netdev_intersect_features() works, the features actually set on the vlan devices and HW having the ability to run checksum with longer headers. The issue starts when netdev_interesect_features() replaces NETIF_F_HW_CSUM with a combination of NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM, if the HW advertises IP|IPV6 specific checksums. This happens for tagged and multi-tagged packets. However, HW that enables IP|IPV6 checksum offloading doesn't gurantee that packets with arbitrarily long headers can be checksummed. This patch disables IP|IPV6 checksums on the packet for multi-tagged packets. CC: Toshiaki Makita CC: Michal Kubecek Signed-off-by: Vladislav Yasevich Acked-by: Toshiaki Makita Signed-off-by: David S. Miller --- include/linux/if_vlan.h | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h index 8d5fcd6284ce..283dc2f5364d 100644 --- a/include/linux/if_vlan.h +++ b/include/linux/if_vlan.h @@ -614,14 +614,16 @@ static inline bool skb_vlan_tagged_multi(const struct sk_buff *skb) static inline netdev_features_t vlan_features_check(const struct sk_buff *skb, netdev_features_t features) { - if (skb_vlan_tagged_multi(skb)) - features = netdev_intersect_features(features, - NETIF_F_SG | - NETIF_F_HIGHDMA | - NETIF_F_FRAGLIST | - NETIF_F_HW_CSUM | - NETIF_F_HW_VLAN_CTAG_TX | - NETIF_F_HW_VLAN_STAG_TX); + if (skb_vlan_tagged_multi(skb)) { + /* In the case of multi-tagged packets, use a direct mask + * instead of using netdev_interesect_features(), to make + * sure that only devices supporting NETIF_F_HW_CSUM will + * have checksum offloading support. + */ + features &= NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_HW_CSUM | + NETIF_F_FRAGLIST | NETIF_F_HW_VLAN_CTAG_TX | + NETIF_F_HW_VLAN_STAG_TX; + } return features; } -- cgit v1.2.3 From cc6e9de62a7f84c9293a2ea41bc412b55bb46e85 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Tue, 23 May 2017 13:38:42 -0400 Subject: be2net: Fix offload features for Q-in-Q packets At least some of the be2net cards do not seem to be capabled of performing checksum offload computions on Q-in-Q packets. In these case, the recevied checksum on the remote is invalid and TCP syn packets are dropped. This patch adds a call to check disbled acceleration features on Q-in-Q tagged traffic. CC: Sathya Perla CC: Ajit Khaparde CC: Sriharsha Basavapatna CC: Somnath Kotur Signed-off-by: Vladislav Yasevich Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be_main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index f3a09ab55900..4eee18ce9be4 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -5078,9 +5078,11 @@ static netdev_features_t be_features_check(struct sk_buff *skb, struct be_adapter *adapter = netdev_priv(dev); u8 l4_hdr = 0; - /* The code below restricts offload features for some tunneled packets. + /* The code below restricts offload features for some tunneled and + * Q-in-Q packets. * Offload features for normal (non tunnel) packets are unchanged. */ + features = vlan_features_check(skb, features); if (!skb->encapsulation || !(adapter->flags & BE_FLAGS_VXLAN_OFFLOADS)) return features; -- cgit v1.2.3 From 2836b4f224d4fd7d1a2b23c3eecaf0f0ae199a74 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Tue, 23 May 2017 13:38:43 -0400 Subject: virtio-net: enable TSO/checksum offloads for Q-in-Q vlans Since virtio does not provide it's own ndo_features_check handler, TSO, and now checksum offload, are disabled for stacked vlans. Re-enable the support and let the host take care of it. This restores/improves Guest-to-Guest performance over Q-in-Q vlans. Acked-by: Jason Wang Acked-by: Michael S. Tsirkin Signed-off-by: Vladislav Yasevich Signed-off-by: David S. Miller --- drivers/net/virtio_net.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 9320d96a1632..3e9246cc49c3 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -1989,6 +1989,7 @@ static const struct net_device_ops virtnet_netdev = { .ndo_poll_controller = virtnet_netpoll, #endif .ndo_xdp = virtnet_xdp, + .ndo_features_check = passthru_features_check, }; static void virtnet_config_changed_work(struct work_struct *work) -- cgit v1.2.3 From 9dfa7bba35ac08a63565d58c454dccb7e1bb0a08 Mon Sep 17 00:00:00 2001 From: Michael Schmitz Date: Sun, 30 Apr 2017 19:49:21 +1200 Subject: fix race in drivers/char/random.c:get_reg() get_reg() can be reentered on architectures with prioritized interrupts (m68k in this case), causing f->reg_index to be incremented after the range check. Out of bounds memory access past the pt_regs struct results. This will go mostly undetected unless access is beyond end of memory. Prevent the race by disabling interrupts in get_reg(). Tested on m68k (Atari Falcon, and ARAnyM emulator). Kudos to Geert Uytterhoeven for helping to trace this race. Signed-off-by: Michael Schmitz Signed-off-by: Theodore Ts'o --- drivers/char/random.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/char/random.c b/drivers/char/random.c index 0ab024918907..a561f0c2f428 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1097,12 +1097,16 @@ static void add_interrupt_bench(cycles_t start) static __u32 get_reg(struct fast_pool *f, struct pt_regs *regs) { __u32 *ptr = (__u32 *) regs; + unsigned long flags; if (regs == NULL) return 0; + local_irq_save(flags); if (f->reg_idx >= sizeof(struct pt_regs) / sizeof(__u32)) f->reg_idx = 0; - return *(ptr + f->reg_idx++); + ptr += f->reg_idx++; + local_irq_restore(flags); + return *ptr; } void add_interrupt_randomness(int irq, int irq_flags) -- cgit v1.2.3 From 624327f8794704c5066b11a52f9da6a09dce7f9a Mon Sep 17 00:00:00 2001 From: Eryu Guan Date: Wed, 24 May 2017 18:02:20 -0400 Subject: ext4: fix off-by-one on max nr_pages in ext4_find_unwritten_pgoff() ext4_find_unwritten_pgoff() is used to search for offset of hole or data in page range [index, end] (both inclusive), and the max number of pages to search should be at least one, if end == index. Otherwise the only page is missed and no hole or data is found, which is not correct. When block size is smaller than page size, this can be demonstrated by preallocating a file with size smaller than page size and writing data to the last block. E.g. run this xfs_io command on a 1k block size ext4 on x86_64 host. # xfs_io -fc "falloc 0 3k" -c "pwrite 2k 1k" \ -c "seek -d 0" /mnt/ext4/testfile wrote 1024/1024 bytes at offset 2048 1 KiB, 1 ops; 0.0000 sec (42.459 MiB/sec and 43478.2609 ops/sec) Whence Result DATA EOF Data at offset 2k was missed, and lseek(2) returned ENXIO. This is unconvered by generic/285 subtest 07 and 08 on ppc64 host, where pagesize is 64k. Because a recent change to generic/285 reduced the preallocated file size to smaller than 64k. Signed-off-by: Eryu Guan Signed-off-by: Theodore Ts'o Reviewed-by: Jan Kara --- fs/ext4/file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ext4/file.c b/fs/ext4/file.c index 2b00bf84c05b..02ce7e7bbdf5 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c @@ -481,7 +481,7 @@ static int ext4_find_unwritten_pgoff(struct inode *inode, int i, num; unsigned long nr_pages; - num = min_t(pgoff_t, end - index, PAGEVEC_SIZE); + num = min_t(pgoff_t, end - index, PAGEVEC_SIZE - 1) + 1; nr_pages = pagevec_lookup(&pvec, inode->i_mapping, index, (pgoff_t)num); if (nr_pages == 0) -- cgit v1.2.3 From e5465795cac48233c9b606a7a419f4190a91851e Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Wed, 24 May 2017 18:05:29 -0400 Subject: ext4: fix off-by-one error when writing back pages before dio read The 'lend' argument of filemap_write_and_wait_range() is inclusive, so we need to subtract 1 from pos + count. Note that 'count' is guaranteed to be nonzero since ext4_file_read_iter() returns early when given a 0 count. Fixes: 16c54688592c ("ext4: Allow parallel DIO reads") Signed-off-by: Eric Biggers Signed-off-by: Theodore Ts'o Reviewed-by: Jan Kara --- fs/ext4/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 7cd99de8c4ba..90b264928742 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -3713,7 +3713,7 @@ static ssize_t ext4_direct_IO_read(struct kiocb *iocb, struct iov_iter *iter) */ inode_lock_shared(inode); ret = filemap_write_and_wait_range(mapping, iocb->ki_pos, - iocb->ki_pos + count); + iocb->ki_pos + count - 1); if (ret) goto out_unlock; ret = __blockdev_direct_IO(iocb, inode, inode->i_sb->s_bdev, -- cgit v1.2.3 From d6b975504e7e71fc29fcd14530433e816d7f5aac Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Wed, 24 May 2017 18:10:49 -0400 Subject: ext4: remove unused d_name argument from ext4_search_dir() et al. Now that we are passing a struct ext4_filename, we do not need to pass around the original struct qstr too. Signed-off-by: Eric Biggers Signed-off-by: Theodore Ts'o Reviewed-by: Jan Kara --- fs/ext4/ext4.h | 2 -- fs/ext4/inline.c | 5 ++--- fs/ext4/namei.c | 13 +++++-------- 3 files changed, 7 insertions(+), 13 deletions(-) diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 8e8046104f4d..32191548abed 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -2523,7 +2523,6 @@ extern int ext4_search_dir(struct buffer_head *bh, int buf_size, struct inode *dir, struct ext4_filename *fname, - const struct qstr *d_name, unsigned int offset, struct ext4_dir_entry_2 **res_dir); extern int ext4_generic_delete_entry(handle_t *handle, @@ -3007,7 +3006,6 @@ extern int htree_inlinedir_to_tree(struct file *dir_file, int *has_inline_data); extern struct buffer_head *ext4_find_inline_entry(struct inode *dir, struct ext4_filename *fname, - const struct qstr *d_name, struct ext4_dir_entry_2 **res_dir, int *has_inline_data); extern int ext4_delete_inline_entry(handle_t *handle, diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c index d5dea4c293ef..8d141c0c8ff9 100644 --- a/fs/ext4/inline.c +++ b/fs/ext4/inline.c @@ -1627,7 +1627,6 @@ out: struct buffer_head *ext4_find_inline_entry(struct inode *dir, struct ext4_filename *fname, - const struct qstr *d_name, struct ext4_dir_entry_2 **res_dir, int *has_inline_data) { @@ -1649,7 +1648,7 @@ struct buffer_head *ext4_find_inline_entry(struct inode *dir, EXT4_INLINE_DOTDOT_SIZE; inline_size = EXT4_MIN_INLINE_DATA_SIZE - EXT4_INLINE_DOTDOT_SIZE; ret = ext4_search_dir(iloc.bh, inline_start, inline_size, - dir, fname, d_name, 0, res_dir); + dir, fname, 0, res_dir); if (ret == 1) goto out_find; if (ret < 0) @@ -1662,7 +1661,7 @@ struct buffer_head *ext4_find_inline_entry(struct inode *dir, inline_size = ext4_get_inline_size(dir) - EXT4_MIN_INLINE_DATA_SIZE; ret = ext4_search_dir(iloc.bh, inline_start, inline_size, - dir, fname, d_name, 0, res_dir); + dir, fname, 0, res_dir); if (ret == 1) goto out_find; diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index b81f7d46f344..404256caf9cf 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -1155,12 +1155,11 @@ errout: static inline int search_dirblock(struct buffer_head *bh, struct inode *dir, struct ext4_filename *fname, - const struct qstr *d_name, unsigned int offset, struct ext4_dir_entry_2 **res_dir) { return ext4_search_dir(bh, bh->b_data, dir->i_sb->s_blocksize, dir, - fname, d_name, offset, res_dir); + fname, offset, res_dir); } /* @@ -1262,7 +1261,6 @@ static inline bool ext4_match(const struct ext4_filename *fname, */ int ext4_search_dir(struct buffer_head *bh, char *search_buf, int buf_size, struct inode *dir, struct ext4_filename *fname, - const struct qstr *d_name, unsigned int offset, struct ext4_dir_entry_2 **res_dir) { struct ext4_dir_entry_2 * de; @@ -1355,7 +1353,7 @@ static struct buffer_head * ext4_find_entry (struct inode *dir, if (ext4_has_inline_data(dir)) { int has_inline_data = 1; - ret = ext4_find_inline_entry(dir, &fname, d_name, res_dir, + ret = ext4_find_inline_entry(dir, &fname, res_dir, &has_inline_data); if (has_inline_data) { if (inlined) @@ -1447,7 +1445,7 @@ restart: goto next; } set_buffer_verified(bh); - i = search_dirblock(bh, dir, &fname, d_name, + i = search_dirblock(bh, dir, &fname, block << EXT4_BLOCK_SIZE_BITS(sb), res_dir); if (i == 1) { EXT4_I(dir)->i_dir_start_lookup = block; @@ -1488,7 +1486,6 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir, { struct super_block * sb = dir->i_sb; struct dx_frame frames[2], *frame; - const struct qstr *d_name = fname->usr_fname; struct buffer_head *bh; ext4_lblk_t block; int retval; @@ -1505,7 +1502,7 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir, if (IS_ERR(bh)) goto errout; - retval = search_dirblock(bh, dir, fname, d_name, + retval = search_dirblock(bh, dir, fname, block << EXT4_BLOCK_SIZE_BITS(sb), res_dir); if (retval == 1) @@ -1530,7 +1527,7 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir, bh = NULL; errout: - dxtrace(printk(KERN_DEBUG "%s not found\n", d_name->name)); + dxtrace(printk(KERN_DEBUG "%s not found\n", fname->usr_fname->name)); success: dx_release(frames); return bh; -- cgit v1.2.3 From c41d342b39f15acbdc61948bab0cb3c567ec992a Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Wed, 24 May 2017 18:20:31 -0400 Subject: ext4: remove redundant check for encrypted file on dio write path Currently we don't allow direct I/O on encrypted regular files, so in such cases we return 0 early in ext4_direct_IO(). There was also an additional BUG_ON() check in ext4_direct_IO_write(), but it can never be hit because of the earlier check for the exact same condition in ext4_direct_IO(). There was also no matching check on the read path, which made the write path specific check seem very ad-hoc. Just remove the unnecessary BUG_ON(). Signed-off-by: Eric Biggers Signed-off-by: Theodore Ts'o Reviewed-by: David Gstir Reviewed-by: Jan Kara --- fs/ext4/inode.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 90b264928742..074aeba78259 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -3629,9 +3629,6 @@ static ssize_t ext4_direct_IO_write(struct kiocb *iocb, struct iov_iter *iter) get_block_func = ext4_dio_get_block_unwritten_async; dio_flags = DIO_LOCKING; } -#ifdef CONFIG_EXT4_FS_ENCRYPTION - BUG_ON(ext4_encrypted_inode(inode) && S_ISREG(inode->i_mode)); -#endif ret = __blockdev_direct_IO(iocb, inode, inode->i_sb->s_bdev, iter, get_block_func, ext4_end_io_dio, NULL, dio_flags); -- cgit v1.2.3 From b8cb5a545c3dd8b975aad19ea020eabe0a888e8d Mon Sep 17 00:00:00 2001 From: Tahsin Erdogan Date: Wed, 24 May 2017 18:24:07 -0400 Subject: ext4: fix quota charging for shared xattr blocks ext4_xattr_block_set() calls dquot_alloc_block() to charge for an xattr block when new references are made. However if dquot_initialize() hasn't been called on an inode, request for charging is effectively ignored because ext4_inode_info->i_dquot is not initialized yet. Add dquot_initialize() to call paths that lead to ext4_xattr_block_set(). Signed-off-by: Tahsin Erdogan Signed-off-by: Theodore Ts'o Reviewed-by: Jan Kara --- fs/ext4/acl.c | 4 ++++ fs/ext4/super.c | 3 +++ fs/ext4/xattr.c | 8 ++++++++ fs/quota/dquot.c | 16 ++++++++++++++++ include/linux/quotaops.h | 6 ++++++ 5 files changed, 37 insertions(+) diff --git a/fs/ext4/acl.c b/fs/ext4/acl.c index fd389935ecd1..3ec0e46de95f 100644 --- a/fs/ext4/acl.c +++ b/fs/ext4/acl.c @@ -4,6 +4,7 @@ * Copyright (C) 2001-2003 Andreas Gruenbacher, */ +#include #include "ext4_jbd2.h" #include "ext4.h" #include "xattr.h" @@ -232,6 +233,9 @@ ext4_set_acl(struct inode *inode, struct posix_acl *acl, int type) handle_t *handle; int error, retries = 0; + error = dquot_initialize(inode); + if (error) + return error; retry: handle = ext4_journal_start(inode, EXT4_HT_XATTR, ext4_jbd2_credits_xattr(inode)); diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 8f05c72bc4ec..d37c81f327e7 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -1174,6 +1174,9 @@ static int ext4_set_context(struct inode *inode, const void *ctx, size_t len, return res; } + res = dquot_initialize(inode); + if (res) + return res; retry: handle = ext4_journal_start(inode, EXT4_HT_MISC, ext4_jbd2_credits_xattr(inode)); diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index 8fb7ce14e6eb..5d3c2536641c 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c @@ -888,6 +888,8 @@ inserted: else { u32 ref; + WARN_ON_ONCE(dquot_initialize_needed(inode)); + /* The old block is released after updating the inode. */ error = dquot_alloc_block(inode, @@ -954,6 +956,8 @@ inserted: /* We need to allocate a new block */ ext4_fsblk_t goal, block; + WARN_ON_ONCE(dquot_initialize_needed(inode)); + goal = ext4_group_first_block_no(sb, EXT4_I(inode)->i_block_group); @@ -1166,6 +1170,7 @@ ext4_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index, return -EINVAL; if (strlen(name) > 255) return -ERANGE; + ext4_write_lock_xattr(inode, &no_expand); error = ext4_reserve_inode_write(handle, inode, &is.iloc); @@ -1267,6 +1272,9 @@ ext4_xattr_set(struct inode *inode, int name_index, const char *name, int error, retries = 0; int credits = ext4_jbd2_credits_xattr(inode); + error = dquot_initialize(inode); + if (error) + return error; retry: handle = ext4_journal_start(inode, EXT4_HT_XATTR, credits); if (IS_ERR(handle)) { diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index ebf80c7739e1..48813aeaab80 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c @@ -1512,6 +1512,22 @@ int dquot_initialize(struct inode *inode) } EXPORT_SYMBOL(dquot_initialize); +bool dquot_initialize_needed(struct inode *inode) +{ + struct dquot **dquots; + int i; + + if (!dquot_active(inode)) + return false; + + dquots = i_dquot(inode); + for (i = 0; i < MAXQUOTAS; i++) + if (!dquots[i] && sb_has_quota_active(inode->i_sb, i)) + return true; + return false; +} +EXPORT_SYMBOL(dquot_initialize_needed); + /* * Release all quotas referenced by inode. * diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h index 9c6f768b7d32..dda22f45fc1b 100644 --- a/include/linux/quotaops.h +++ b/include/linux/quotaops.h @@ -44,6 +44,7 @@ void inode_sub_rsv_space(struct inode *inode, qsize_t number); void inode_reclaim_rsv_space(struct inode *inode, qsize_t number); int dquot_initialize(struct inode *inode); +bool dquot_initialize_needed(struct inode *inode); void dquot_drop(struct inode *inode); struct dquot *dqget(struct super_block *sb, struct kqid qid); static inline struct dquot *dqgrab(struct dquot *dquot) @@ -207,6 +208,11 @@ static inline int dquot_initialize(struct inode *inode) return 0; } +static inline bool dquot_initialize_needed(struct inode *inode) +{ + return false; +} + static inline void dquot_drop(struct inode *inode) { } -- cgit v1.2.3 From 4179bc30b2fe85f827d93e0ae7ae8f49ad3afc02 Mon Sep 17 00:00:00 2001 From: Kyungchan Koh Date: Wed, 24 May 2017 10:16:27 -0700 Subject: md: uuid debug statement now in processor byte order. Previously, the uuid debug statements were printed in little-endian format, which wasn't consistent in machines that might not be in little-endian byte order. With this change, the output will be consistent for all machines with different byte-ordering. Signed-off-by: Kyungchan Koh Signed-off-by: Shaohua Li --- drivers/md/bitmap.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index bf7419a56454..f4eace5ea184 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -485,10 +485,10 @@ void bitmap_print_sb(struct bitmap *bitmap) pr_debug(" magic: %08x\n", le32_to_cpu(sb->magic)); pr_debug(" version: %d\n", le32_to_cpu(sb->version)); pr_debug(" uuid: %08x.%08x.%08x.%08x\n", - *(__u32 *)(sb->uuid+0), - *(__u32 *)(sb->uuid+4), - *(__u32 *)(sb->uuid+8), - *(__u32 *)(sb->uuid+12)); + le32_to_cpu(*(__u32 *)(sb->uuid+0)), + le32_to_cpu(*(__u32 *)(sb->uuid+4)), + le32_to_cpu(*(__u32 *)(sb->uuid+8)), + le32_to_cpu(*(__u32 *)(sb->uuid+12))); pr_debug(" events: %llu\n", (unsigned long long) le64_to_cpu(sb->events)); pr_debug("events cleared: %llu\n", -- cgit v1.2.3 From e153903686deac9ea8c499b49516126f1a844fdb Mon Sep 17 00:00:00 2001 From: Nix Date: Tue, 16 May 2017 10:13:31 +0100 Subject: md: report sector of stripes with check mismatches This makes it possible, with appropriate filesystem support, for a sysadmin to tell what is affected by the mismatch, and whether it should be ignored (if it's inside a swap partition, for instance). We ratelimit to prevent log flooding: if there are so many mismatches that ratelimiting is necessary, the individual messages are relatively unlikely to be important (either the machine is swapping like crazy or something is very wrong with the disk). Signed-off-by: Nick Alcock Signed-off-by: Shaohua Li --- drivers/md/raid5.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 9c4f7659f8b1..722064689e82 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -4085,10 +4085,15 @@ static void handle_parity_checks5(struct r5conf *conf, struct stripe_head *sh, set_bit(STRIPE_INSYNC, &sh->state); else { atomic64_add(STRIPE_SECTORS, &conf->mddev->resync_mismatches); - if (test_bit(MD_RECOVERY_CHECK, &conf->mddev->recovery)) + if (test_bit(MD_RECOVERY_CHECK, &conf->mddev->recovery)) { /* don't try to repair!! */ set_bit(STRIPE_INSYNC, &sh->state); - else { + pr_warn_ratelimited("%s: mismatch sector in range " + "%llu-%llu\n", mdname(conf->mddev), + (unsigned long long) sh->sector, + (unsigned long long) sh->sector + + STRIPE_SECTORS); + } else { sh->check_state = check_state_compute_run; set_bit(STRIPE_COMPUTE_RUN, &sh->state); set_bit(STRIPE_OP_COMPUTE_BLK, &s->ops_request); @@ -4237,10 +4242,15 @@ static void handle_parity_checks6(struct r5conf *conf, struct stripe_head *sh, } } else { atomic64_add(STRIPE_SECTORS, &conf->mddev->resync_mismatches); - if (test_bit(MD_RECOVERY_CHECK, &conf->mddev->recovery)) + if (test_bit(MD_RECOVERY_CHECK, &conf->mddev->recovery)) { /* don't try to repair!! */ set_bit(STRIPE_INSYNC, &sh->state); - else { + pr_warn_ratelimited("%s: mismatch sector in range " + "%llu-%llu\n", mdname(conf->mddev), + (unsigned long long) sh->sector, + (unsigned long long) sh->sector + + STRIPE_SECTORS); + } else { int *target = &sh->ops.target; sh->ops.target = -1; -- cgit v1.2.3 From cb590700e04d4f59179c44f360217f5ad04ae262 Mon Sep 17 00:00:00 2001 From: "himanshu.madhani@cavium.com" Date: Wed, 24 May 2017 18:06:18 -0700 Subject: scsi: qla2xxx: Fix recursive loop during target mode configuration for ISP25XX leaving system unresponsive Following messages are seen into system logs qla2xxx [0000:09:00.0]-00af:9: Performing ISP error recovery - ha=ffff98315ee30000. qla2xxx [0000:09:00.0]-504b:9: RISC paused -- HCCR=40, Dumping firmware. qla2xxx [0000:09:00.0]-d009:9: Firmware has been previously dumped (ffffba488c001000) -- ignoring request. qla2xxx [0000:09:00.0]-504b:9: RISC paused -- HCCR=40, Dumping firmware. See Bugzilla for details https://bugzilla.kernel.org/show_bug.cgi?id=195285 Fixes: d74595278f4ab ("scsi: qla2xxx: Add multiple queue pair functionality.") Cc: # v4.10+ Reported-by: Laurence Oberman Reported-by: Anthony Bloodoff Tested-by: Laurence Oberman Tested-by: Anthony Bloodoff Signed-off-by: Himanshu Madhani Signed-off-by: Giridhar Malavali Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_isr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index aac03504d9a3..2572121b765b 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -3282,7 +3282,7 @@ msix_register_fail: } /* Enable MSI-X vector for response queue update for queue 0 */ - if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) { + if (IS_QLA25XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha)) { if (ha->msixbase && ha->mqiobase && (ha->max_rsp_queues > 1 || ha->max_req_queues > 1 || ql2xmqsupport)) -- cgit v1.2.3 From 0ea88662b5c6404a8f7af6b040b3cf1f0e8c3a66 Mon Sep 17 00:00:00 2001 From: Quinn Tran Date: Wed, 24 May 2017 18:06:19 -0700 Subject: scsi: qla2xxx: Fix NULL pointer access due to redundant fc_host_port_name call Remove redundant fc_host_port_name calls to prevent early access of scsi_host->shost_data buffer. This prevent null pointer access. Following stack trace is seen: BUG: unable to handle kernel NULL pointer dereference at 00000000000008 IP: qla24xx_report_id_acquisition+0x22d/0x3a0 [qla2xxx] Cc: # v4.11+ Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_mbx.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index a113ab3592a7..12fea77e31c6 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -3676,15 +3676,6 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha, qlt_update_host_map(vha, id); } - fc_host_port_name(vha->host) = - wwn_to_u64(vha->port_name); - - if (qla_ini_mode_enabled(vha)) - ql_dbg(ql_dbg_mbx, vha, 0x1018, - "FA-WWN portname %016llx (%x)\n", - fc_host_port_name(vha->host), - rptid_entry->vp_status); - set_bit(REGISTER_FC4_NEEDED, &vha->dpc_flags); set_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags); } else { -- cgit v1.2.3 From b95b9452aacf80659ea67bf0948cbfa7e28e5e0b Mon Sep 17 00:00:00 2001 From: Sawan Chandak Date: Wed, 24 May 2017 18:06:20 -0700 Subject: scsi: qla2xxx: Fix crash due to mismatch mumber of Q-pair creation for Multi queue when driver is loaded with Multi Queue enabled, it was noticed that there was one less queue pair created. Following message would indicate this: "No resources to create additional q pair." The result of one less queue pair means that system can crash, if the block mq layer thinks there is an extra hardware queue available, and the driver will use a NULL ptr qpair in that instance. Following stack trace is seen in one of the crash: irq_create_affinity_masks+0x98/0x530 irq_create_affinity_masks+0x98/0x530 __pci_enable_msix+0x321/0x4e0 mutex_lock+0x12/0x40 pci_alloc_irq_vectors_affinity+0xb5/0x140 qla24xx_enable_msix+0x79/0x530 [qla2xxx] qla2x00_request_irqs+0x61/0x2d0 [qla2xxx] qla2x00_probe_one+0xc73/0x2390 [qla2xxx] ida_simple_get+0x98/0x100 kernfs_next_descendant_post+0x40/0x50 local_pci_probe+0x45/0xa0 pci_device_probe+0xfc/0x140 driver_probe_device+0x2c5/0x470 __driver_attach+0xdd/0xe0 driver_probe_device+0x470/0x470 bus_for_each_dev+0x6c/0xc0 driver_attach+0x1e/0x20 bus_add_driver+0x45/0x270 driver_register+0x60/0xe0 __pci_register_driver+0x4c/0x50 qla2x00_module_init+0x1ce/0x21e [qla2xxx] Cc: # v4.10+ Signed-off-by: Sawan Chandak Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_def.h | 1 + drivers/scsi/qla2xxx/qla_init.c | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index ae119018dfaa..eddbc1218a39 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -3425,6 +3425,7 @@ struct qla_hw_data { uint8_t max_req_queues; uint8_t max_rsp_queues; uint8_t max_qpairs; + uint8_t num_qpairs; struct qla_qpair *base_qpair; struct qla_npiv_entry *npiv_info; uint16_t nvram_npiv_size; diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 034743309ada..0391fc317003 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -7543,12 +7543,13 @@ struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *vha, int qos, int v /* Assign available que pair id */ mutex_lock(&ha->mq_lock); qpair_id = find_first_zero_bit(ha->qpair_qid_map, ha->max_qpairs); - if (qpair_id >= ha->max_qpairs) { + if (ha->num_qpairs >= ha->max_qpairs) { mutex_unlock(&ha->mq_lock); ql_log(ql_log_warn, vha, 0x0183, "No resources to create additional q pair.\n"); goto fail_qid_map; } + ha->num_qpairs++; set_bit(qpair_id, ha->qpair_qid_map); ha->queue_pair_map[qpair_id] = qpair; qpair->id = qpair_id; @@ -7635,6 +7636,7 @@ fail_rsp: fail_msix: ha->queue_pair_map[qpair_id] = NULL; clear_bit(qpair_id, ha->qpair_qid_map); + ha->num_qpairs--; mutex_unlock(&ha->mq_lock); fail_qid_map: kfree(qpair); @@ -7660,6 +7662,7 @@ int qla2xxx_delete_qpair(struct scsi_qla_host *vha, struct qla_qpair *qpair) mutex_lock(&ha->mq_lock); ha->queue_pair_map[qpair->id] = NULL; clear_bit(qpair->id, ha->qpair_qid_map); + ha->num_qpairs--; list_del(&qpair->qp_list_elem); if (list_empty(&vha->qp_list)) vha->flags.qpairs_available = 0; -- cgit v1.2.3 From ce6c668b146cc4f4442111e2bcee4c3af94e1ddf Mon Sep 17 00:00:00 2001 From: Joe Carnuccio Date: Wed, 24 May 2017 18:06:21 -0700 Subject: scsi: qla2xxx: Modify T262 FW dump template to specify same start/end to debug customer issues Firmware dump allows for debugging customer issues. This patch fixes start/end pointer calculation to capture T262 template entry for dump tool. Cc: # v4.10+ Signed-off-by: Joe Carnuccio Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_tmpl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_tmpl.c b/drivers/scsi/qla2xxx/qla_tmpl.c index 8a58ef3adab4..c197972a3e2d 100644 --- a/drivers/scsi/qla2xxx/qla_tmpl.c +++ b/drivers/scsi/qla2xxx/qla_tmpl.c @@ -371,7 +371,7 @@ qla27xx_fwdt_entry_t262(struct scsi_qla_host *vha, goto done; } - if (end <= start || start == 0 || end == 0) { + if (end < start || start == 0 || end == 0) { ql_dbg(ql_dbg_misc, vha, 0xd023, "%s: unusable range (start=%x end=%x)\n", __func__, ent->t262.end_addr, ent->t262.start_addr); -- cgit v1.2.3 From 1d63496516c61e2e1351f10e6becbfc9ee511395 Mon Sep 17 00:00:00 2001 From: Joe Carnuccio Date: Wed, 24 May 2017 18:06:22 -0700 Subject: scsi: qla2xxx: Set bit 15 for DIAG_ECHO_TEST MBC Set bit (BIT_15) to send right ECHO payload information for Diagnostic Echo Test command. Cc: # v4.10+ Signed-off-by: Joe Carnuccio Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_bsg.c | 9 +++++---- drivers/scsi/qla2xxx/qla_mbx.c | 4 ++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index 16d1cd50feed..ca3420de5a01 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -730,6 +730,8 @@ qla2x00_process_loopback(struct bsg_job *bsg_job) return -EIO; } + memset(&elreq, 0, sizeof(elreq)); + elreq.req_sg_cnt = dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list, bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); @@ -795,10 +797,9 @@ qla2x00_process_loopback(struct bsg_job *bsg_job) if (atomic_read(&vha->loop_state) == LOOP_READY && (ha->current_topology == ISP_CFG_F || - ((IS_QLA81XX(ha) || IS_QLA8031(ha) || IS_QLA8044(ha)) && - le32_to_cpu(*(uint32_t *)req_data) == ELS_OPCODE_BYTE - && req_data_len == MAX_ELS_FRAME_PAYLOAD)) && - elreq.options == EXTERNAL_LOOPBACK) { + (le32_to_cpu(*(uint32_t *)req_data) == ELS_OPCODE_BYTE && + req_data_len == MAX_ELS_FRAME_PAYLOAD)) && + elreq.options == EXTERNAL_LOOPBACK) { type = "FC_BSG_HST_VENDOR_ECHO_DIAG"; ql_dbg(ql_dbg_user, vha, 0x701e, "BSG request type: %s.\n", type); diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 12fea77e31c6..cba1fc5e8be9 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -4812,9 +4812,9 @@ qla2x00_echo_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq, memset(mcp->mb, 0 , sizeof(mcp->mb)); mcp->mb[0] = MBC_DIAGNOSTIC_ECHO; - mcp->mb[1] = mreq->options | BIT_6; /* BIT_6 specifies 64bit address */ + /* BIT_6 specifies 64bit address */ + mcp->mb[1] = mreq->options | BIT_15 | BIT_6; if (IS_CNA_CAPABLE(ha)) { - mcp->mb[1] |= BIT_15; mcp->mb[2] = vha->fcoe_fcf_idx; } mcp->mb[16] = LSW(mreq->rcv_dma); -- cgit v1.2.3 From 74939a0bc772d642b1c12827966c4c3a3c90ea2c Mon Sep 17 00:00:00 2001 From: Joe Carnuccio Date: Wed, 24 May 2017 18:06:23 -0700 Subject: scsi: qla2xxx: Fix mailbox pointer error in fwdump capture Cc: # v4.10+ Signed-off-by: Joe Carnuccio Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_dbg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index 51b4179469d1..88748a6ab73f 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -1131,7 +1131,7 @@ qla24xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) /* Mailbox registers. */ mbx_reg = ®->mailbox0; - for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++, dmp_reg++) + for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++, mbx_reg++) fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg)); /* Transfer sequence registers. */ @@ -2090,7 +2090,7 @@ qla83xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) /* Mailbox registers. */ mbx_reg = ®->mailbox0; - for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++, dmp_reg++) + for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++, mbx_reg++) fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg)); /* Transfer sequence registers. */ -- cgit v1.2.3 From d5ff0eed3a6621f6fd6c14f042c30a6eacfa77f1 Mon Sep 17 00:00:00 2001 From: Joe Carnuccio Date: Wed, 24 May 2017 18:06:24 -0700 Subject: scsi: qla2xxx: Fix crash due to NULL pointer dereference of ctx Fixes following signature in the stack trace: BUG: unable to handle kernel NULL pointer dereference at 0000000000000374 IP: [] qla2x00_sp_free_dma+0xeb/0x2a0 [qla2xxx] Cc: # v4.10+ Signed-off-by: Joe Carnuccio Signed-off-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_inline.h | 26 +++++++------------------- drivers/scsi/qla2xxx/qla_os.c | 30 +++++++++++++++++++----------- drivers/scsi/qla2xxx/qla_target.c | 8 +++++--- 3 files changed, 31 insertions(+), 33 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h index 66df6cec59da..c61a6a871c8e 100644 --- a/drivers/scsi/qla2xxx/qla_inline.h +++ b/drivers/scsi/qla2xxx/qla_inline.h @@ -129,28 +129,16 @@ qla2x00_clear_loop_id(fc_port_t *fcport) { } static inline void -qla2x00_clean_dsd_pool(struct qla_hw_data *ha, srb_t *sp, - struct qla_tgt_cmd *tc) +qla2x00_clean_dsd_pool(struct qla_hw_data *ha, struct crc_context *ctx) { - struct dsd_dma *dsd_ptr, *tdsd_ptr; - struct crc_context *ctx; - - if (sp) - ctx = (struct crc_context *)GET_CMD_CTX_SP(sp); - else if (tc) - ctx = (struct crc_context *)tc->ctx; - else { - BUG(); - return; - } + struct dsd_dma *dsd, *tdsd; /* clean up allocated prev pool */ - list_for_each_entry_safe(dsd_ptr, tdsd_ptr, - &ctx->dsd_list, list) { - dma_pool_free(ha->dl_dma_pool, dsd_ptr->dsd_addr, - dsd_ptr->dsd_list_dma); - list_del(&dsd_ptr->list); - kfree(dsd_ptr); + list_for_each_entry_safe(dsd, tdsd, &ctx->dsd_list, list) { + dma_pool_free(ha->dl_dma_pool, dsd->dsd_addr, + dsd->dsd_list_dma); + list_del(&dsd->list); + kfree(dsd); } INIT_LIST_HEAD(&ctx->dsd_list); } diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index af25d8afd42a..2a2ce7476339 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -630,29 +630,34 @@ qla2x00_sp_free_dma(void *ptr) sp->flags &= ~SRB_CRC_PROT_DMA_VALID; } + if (!ctx) + goto end; + if (sp->flags & SRB_CRC_CTX_DSD_VALID) { /* List assured to be having elements */ - qla2x00_clean_dsd_pool(ha, sp, NULL); + qla2x00_clean_dsd_pool(ha, ctx); sp->flags &= ~SRB_CRC_CTX_DSD_VALID; } if (sp->flags & SRB_CRC_CTX_DMA_VALID) { - dma_pool_free(ha->dl_dma_pool, ctx, - ((struct crc_context *)ctx)->crc_ctx_dma); + struct crc_context *ctx0 = ctx; + + dma_pool_free(ha->dl_dma_pool, ctx0, ctx0->crc_ctx_dma); sp->flags &= ~SRB_CRC_CTX_DMA_VALID; } if (sp->flags & SRB_FCP_CMND_DMA_VALID) { - struct ct6_dsd *ctx1 = (struct ct6_dsd *)ctx; + struct ct6_dsd *ctx1 = ctx; dma_pool_free(ha->fcp_cmnd_dma_pool, ctx1->fcp_cmnd, - ctx1->fcp_cmnd_dma); + ctx1->fcp_cmnd_dma); list_splice(&ctx1->dsd_list, &ha->gbl_dsd_list); ha->gbl_dsd_inuse -= ctx1->dsd_use_cnt; ha->gbl_dsd_avail += ctx1->dsd_use_cnt; mempool_free(ctx1, ha->ctx_mempool); } +end: CMD_SP(cmd) = NULL; qla2x00_rel_sp(sp); } @@ -699,21 +704,24 @@ qla2xxx_qpair_sp_free_dma(void *ptr) sp->flags &= ~SRB_CRC_PROT_DMA_VALID; } + if (!ctx) + goto end; + if (sp->flags & SRB_CRC_CTX_DSD_VALID) { /* List assured to be having elements */ - qla2x00_clean_dsd_pool(ha, sp, NULL); + qla2x00_clean_dsd_pool(ha, ctx); sp->flags &= ~SRB_CRC_CTX_DSD_VALID; } if (sp->flags & SRB_CRC_CTX_DMA_VALID) { - dma_pool_free(ha->dl_dma_pool, ctx, - ((struct crc_context *)ctx)->crc_ctx_dma); + struct crc_context *ctx0 = ctx; + + dma_pool_free(ha->dl_dma_pool, ctx, ctx0->crc_ctx_dma); sp->flags &= ~SRB_CRC_CTX_DMA_VALID; } if (sp->flags & SRB_FCP_CMND_DMA_VALID) { - struct ct6_dsd *ctx1 = (struct ct6_dsd *)ctx; - + struct ct6_dsd *ctx1 = ctx; dma_pool_free(ha->fcp_cmnd_dma_pool, ctx1->fcp_cmnd, ctx1->fcp_cmnd_dma); list_splice(&ctx1->dsd_list, &ha->gbl_dsd_list); @@ -721,7 +729,7 @@ qla2xxx_qpair_sp_free_dma(void *ptr) ha->gbl_dsd_avail += ctx1->dsd_use_cnt; mempool_free(ctx1, ha->ctx_mempool); } - +end: CMD_SP(cmd) = NULL; qla2xxx_rel_qpair_sp(sp->qpair, sp); } diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 0e03ca2ab3e5..e766d8412384 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -2245,11 +2245,13 @@ static void qlt_unmap_sg(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd) pci_unmap_sg(ha->pdev, cmd->prot_sg, cmd->prot_sg_cnt, cmd->dma_data_direction); + if (!cmd->ctx) + return; + if (cmd->ctx_dsd_alloced) - qla2x00_clean_dsd_pool(ha, NULL, cmd); + qla2x00_clean_dsd_pool(ha, cmd->ctx); - if (cmd->ctx) - dma_pool_free(ha->dl_dma_pool, cmd->ctx, cmd->ctx->crc_ctx_dma); + dma_pool_free(ha->dl_dma_pool, cmd->ctx, cmd->ctx->crc_ctx_dma); } static int qlt_check_reserve_free_req(struct scsi_qla_host *vha, -- cgit v1.2.3 From 6df765dca378bddf994cfd2044acafa501bd800f Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 24 May 2017 21:38:46 +0200 Subject: serial: imx: ensure UCR3 and UFCR are setup correctly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit e61c38d85b73 ("serial: imx: setup DCEDTE early and ensure DCD and RI irqs to be off") has a flaw: While UCR3 and UFCR were modified using read-modify-write before it switched to write register values independent of the previous state. That's a good idea in principle (and that's why I did it) but needs more care. This patch reinstates read-modify-write for UFCR and for UCR3 ensures that RXDMUXSEL and ADNIMP are set for post imx1. Fixes: e61c38d85b73 ("serial: imx: setup DCEDTE early and ensure DCD and RI irqs to be off") Signed-off-by: Uwe Kleine-König Acked-by: Mika Penttilä Tested-by: Mika Penttilä Acked-by: Steve Twiss Tested-by: Steve Twiss Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/imx.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 33509b4beaec..bbefddd92bfe 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -2184,7 +2184,9 @@ static int serial_imx_probe(struct platform_device *pdev) * and DCD (when they are outputs) or enables the respective * irqs. So set this bit early, i.e. before requesting irqs. */ - writel(UFCR_DCEDTE, sport->port.membase + UFCR); + reg = readl(sport->port.membase + UFCR); + if (!(reg & UFCR_DCEDTE)) + writel(reg | UFCR_DCEDTE, sport->port.membase + UFCR); /* * Disable UCR3_RI and UCR3_DCD irqs. They are also not @@ -2195,7 +2197,15 @@ static int serial_imx_probe(struct platform_device *pdev) sport->port.membase + UCR3); } else { - writel(0, sport->port.membase + UFCR); + unsigned long ucr3 = UCR3_DSR; + + reg = readl(sport->port.membase + UFCR); + if (reg & UFCR_DCEDTE) + writel(reg & ~UFCR_DCEDTE, sport->port.membase + UFCR); + + if (!is_imx1_uart(sport)) + ucr3 |= IMX21_UCR3_RXDMUXSEL | UCR3_ADNIMP; + writel(ucr3, sport->port.membase + UCR3); } clk_disable_unprepare(sport->clk_ipg); -- cgit v1.2.3 From 59fe2cc8b1c32dd139da80fc8222b5b3290b7a09 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Fri, 19 May 2017 13:59:20 +0200 Subject: serial: altera_uart: call iounmap() at driver remove The driver calls ioremap() in the probe function but doesn't call iounmap() in the remove function correspondingly. Do so now. Follow commit 5c9d6abed9e0 ("serial: altera_jtaguart: adding iounmap()") Cc: Alexey Khoroshilov Signed-off-by: Tobias Klauser Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/altera_uart.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/tty/serial/altera_uart.c b/drivers/tty/serial/altera_uart.c index 46d3438a0d27..3e4b717670d7 100644 --- a/drivers/tty/serial/altera_uart.c +++ b/drivers/tty/serial/altera_uart.c @@ -615,6 +615,7 @@ static int altera_uart_remove(struct platform_device *pdev) if (port) { uart_remove_one_port(&altera_uart_driver, port); port->mapbase = 0; + iounmap(port->membase); } return 0; -- cgit v1.2.3 From 3d51b956267343a65498704ada854c33c0f5e946 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 19 May 2017 10:04:01 +0200 Subject: staging: ccree: add CRYPTO dependency A rare randconfig build error shows up when we have CONFIG_CRYPTO=m in combination with a built-in CCREE driver: crypto/hmac.o: In function `hmac_update': hmac.c:(.text.hmac_update+0x28): undefined reference to `crypto_shash_update' crypto/hmac.o: In function `hmac_setkey': hmac.c:(.text.hmac_setkey+0x90): undefined reference to `crypto_shash_digest' hmac.c:(.text.hmac_setkey+0x154): undefined reference to `crypto_shash_update' drivers/staging/ccree/ssi_cipher.o: In function `ssi_blkcipher_setkey': ssi_cipher.c:(.text.ssi_blkcipher_setkey+0x350): undefined reference to `crypto_shash_digest' drivers/staging/ccree/ssi_cipher.o: In function `ssi_blkcipher_exit': ssi_cipher.c:(.text.ssi_blkcipher_exit+0xd4): undefined reference to `crypto_destroy_tfm' drivers/staging/ccree/ssi_cipher.o: In function `ssi_blkcipher_init': ssi_cipher.c:(.text.ssi_blkcipher_init+0x1b0): undefined reference to `crypto_alloc_shash' drivers/staging/ccree/ssi_cipher.o: In function `ssi_ablkcipher_free': ssi_cipher.c:(.text.ssi_ablkcipher_free+0x48): undefined reference to `crypto_unregister_alg' drivers/staging/ccree/ssi_cipher.o: In function `ssi_ablkcipher_alloc': ssi_cipher.c:(.text.ssi_ablkcipher_alloc+0x138): undefined reference to `crypto_register_alg' ssi_cipher.c:(.text.ssi_ablkcipher_alloc+0x274): undefined reference to `crypto_blkcipher_type' We actually need to depend on both CRYPTO and CRYPTO_HW here to avoid the problem, since CRYPTO_HW is a bool symbol and by itself that does not force CCREE to be a loadable module when the core cryto support is modular. Fixes: 50cfbbb7e627 ("staging: ccree: add ahash support") Signed-off-by: Arnd Bergmann Acked-By: Gilad Ben-Yossef Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/ccree/Kconfig b/drivers/staging/ccree/Kconfig index ae627049c499..4be87f503e3b 100644 --- a/drivers/staging/ccree/Kconfig +++ b/drivers/staging/ccree/Kconfig @@ -1,6 +1,6 @@ config CRYPTO_DEV_CCREE tristate "Support for ARM TrustZone CryptoCell C7XX family of Crypto accelerators" - depends on CRYPTO_HW && OF && HAS_DMA + depends on CRYPTO && CRYPTO_HW && OF && HAS_DMA default n select CRYPTO_HASH select CRYPTO_BLKCIPHER -- cgit v1.2.3 From 415ba3c157b9de7edc59468d19d48c1d15972a75 Mon Sep 17 00:00:00 2001 From: Alistair Popple Date: Sat, 20 May 2017 06:56:35 +1000 Subject: powerpc/powernv/npu-dma.c: Fix opal_npu_destroy_context() call opal_npu_destroy_context() should be called with the NPU PHB, not the PCIe PHB. Fixes: 1ab66d1fbada ("powerpc/powernv: Introduce address translation services for Nvlink2") Signed-off-by: Alistair Popple Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/powernv/npu-dma.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/platforms/powernv/npu-dma.c b/arch/powerpc/platforms/powernv/npu-dma.c index 067defeea691..78fa9395b8c5 100644 --- a/arch/powerpc/platforms/powernv/npu-dma.c +++ b/arch/powerpc/platforms/powernv/npu-dma.c @@ -714,7 +714,7 @@ static void pnv_npu2_release_context(struct kref *kref) void pnv_npu2_destroy_context(struct npu_context *npu_context, struct pci_dev *gpdev) { - struct pnv_phb *nphb, *phb; + struct pnv_phb *nphb; struct npu *npu; struct pci_dev *npdev = pnv_pci_get_npu_dev(gpdev, 0); struct device_node *nvlink_dn; @@ -728,13 +728,12 @@ void pnv_npu2_destroy_context(struct npu_context *npu_context, nphb = pci_bus_to_host(npdev->bus)->private_data; npu = &nphb->npu; - phb = pci_bus_to_host(gpdev->bus)->private_data; nvlink_dn = of_parse_phandle(npdev->dev.of_node, "ibm,nvlink", 0); if (WARN_ON(of_property_read_u32(nvlink_dn, "ibm,npu-link-index", &nvlink_index))) return; npu_context->npdev[npu->index][nvlink_index] = NULL; - opal_npu_destroy_context(phb->opal_id, npu_context->mm->context.id, + opal_npu_destroy_context(nphb->opal_id, npu_context->mm->context.id, PCI_DEVID(gpdev->bus->number, gpdev->devfn)); kref_put(&npu_context->kref, pnv_npu2_release_context); } -- cgit v1.2.3 From d957fb4d173647640a2b83e7c7e56a580e7fc7e7 Mon Sep 17 00:00:00 2001 From: Michael Neuling Date: Wed, 24 May 2017 17:03:26 +1000 Subject: powerpc: Fix booting P9 hash with CONFIG_PPC_RADIX_MMU=N Currently if you disable CONFIG_PPC_RADIX_MMU you'll crash on boot on a P9. This is because we still set MMU_FTR_TYPE_RADIX via ibm,pa-features and MMU_FTR_TYPE_RADIX is what's used for code patching in much of the asm code (ie. slb_miss_realmode) This patch fixes the problem by stopping MMU_FTR_TYPE_RADIX from being set from ibm.pa-features. We may eventually end up removing the CONFIG_PPC_RADIX_MMU option completely but until then this fixes the issue. Fixes: 17a3dd2f5fc7 ("powerpc/mm/radix: Use firmware feature to enable Radix MMU") Cc: stable@vger.kernel.org # v4.7+ Signed-off-by: Michael Neuling Signed-off-by: Michael Ellerman --- arch/powerpc/kernel/prom.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 40c4887c27b6..f83056297441 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -161,7 +161,9 @@ static struct ibm_pa_feature { { .pabyte = 0, .pabit = 3, .cpu_features = CPU_FTR_CTRL }, { .pabyte = 0, .pabit = 6, .cpu_features = CPU_FTR_NOEXECUTE }, { .pabyte = 1, .pabit = 2, .mmu_features = MMU_FTR_CI_LARGE_PAGE }, +#ifdef CONFIG_PPC_RADIX_MMU { .pabyte = 40, .pabit = 0, .mmu_features = MMU_FTR_TYPE_RADIX }, +#endif { .pabyte = 1, .pabit = 1, .invert = 1, .cpu_features = CPU_FTR_NODSISRALIGN }, { .pabyte = 5, .pabit = 0, .cpu_features = CPU_FTR_REAL_LE, .cpu_user_ftrs = PPC_FEATURE_TRUE_LE }, -- cgit v1.2.3 From d75e4919cc0b6fbcbc8d6654ef66d87a9dbf1526 Mon Sep 17 00:00:00 2001 From: Jeremy Kerr Date: Wed, 24 May 2017 16:49:59 +1000 Subject: powerpc/spufs: Fix hash faults for kernel regions Commit ac29c64089b7 ("powerpc/mm: Replace _PAGE_USER with _PAGE_PRIVILEGED") swapped _PAGE_USER for _PAGE_PRIVILEGED, and introduced check_pte_access() which denied kernel access to non-_PAGE_PRIVILEGED pages. However, it didn't add _PAGE_PRIVILEGED to the hash fault handler for spufs' kernel accesses, so the DMAs required to establish SPE memory no longer work. This change adds _PAGE_PRIVILEGED to the hash fault handler for kernel accesses. Fixes: ac29c64089b7 ("powerpc/mm: Replace _PAGE_USER with _PAGE_PRIVILEGED") Cc: stable@vger.kernel.org # v4.7+ Signed-off-by: Jeremy Kerr Reported-by: Sombat Tragolgosol Reviewed-by: Aneesh Kumar K.V Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/cell/spu_base.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index 96c2b8a40630..0c45cdbac4cf 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -197,7 +197,9 @@ static int __spu_trap_data_map(struct spu *spu, unsigned long ea, u64 dsisr) (REGION_ID(ea) != USER_REGION_ID)) { spin_unlock(&spu->register_lock); - ret = hash_page(ea, _PAGE_PRESENT | _PAGE_READ, 0x300, dsisr); + ret = hash_page(ea, + _PAGE_PRESENT | _PAGE_READ | _PAGE_PRIVILEGED, + 0x300, dsisr); spin_lock(&spu->register_lock); if (!ret) { -- cgit v1.2.3 From a4700a26107241cc7b9ac8528b2c6714ff99983d Mon Sep 17 00:00:00 2001 From: Nicholas Piggin Date: Sat, 20 May 2017 14:29:49 +1000 Subject: powerpc: Add PPC_FEATURE userspace bits for SCV and DARN instructions Providing "scv" support to userspace requires kernel support, so it must be advertised as independently to the base ISA 3 instruction set. The darn instruction relies on firmware enablement, so it has been decided to split this out from the core ISA 3 feature as well. Signed-off-by: Nicholas Piggin Acked-by: Benjamin Herrenschmidt Signed-off-by: Michael Ellerman --- arch/powerpc/include/uapi/asm/cputable.h | 2 ++ arch/powerpc/kernel/cputable.c | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/include/uapi/asm/cputable.h b/arch/powerpc/include/uapi/asm/cputable.h index 3e7ce86d5c13..4d877144f377 100644 --- a/arch/powerpc/include/uapi/asm/cputable.h +++ b/arch/powerpc/include/uapi/asm/cputable.h @@ -46,6 +46,8 @@ #define PPC_FEATURE2_HTM_NOSC 0x01000000 #define PPC_FEATURE2_ARCH_3_00 0x00800000 /* ISA 3.00 */ #define PPC_FEATURE2_HAS_IEEE128 0x00400000 /* VSX IEEE Binary Float 128-bit */ +#define PPC_FEATURE2_DARN 0x00200000 /* darn random number insn */ +#define PPC_FEATURE2_SCV 0x00100000 /* scv syscall */ /* * IMPORTANT! diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 9b3e88b1a9c8..6f849832a669 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -124,7 +124,8 @@ extern void __restore_cpu_e6500(void); #define COMMON_USER_POWER9 COMMON_USER_POWER8 #define COMMON_USER2_POWER9 (COMMON_USER2_POWER8 | \ PPC_FEATURE2_ARCH_3_00 | \ - PPC_FEATURE2_HAS_IEEE128) + PPC_FEATURE2_HAS_IEEE128 | \ + PPC_FEATURE2_DARN ) #ifdef CONFIG_PPC_BOOK3E_64 #define COMMON_USER_BOOKE (COMMON_USER_PPC64 | PPC_FEATURE_BOOKE) -- cgit v1.2.3 From 7f53de2069c801776f0f5d1a1d665324967a4fab Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 23 May 2017 17:07:41 -0700 Subject: firmware: vpd: do not leave freed section attributes to the list We should only add section attribute to the list of section attributes if we successfully created corresponding sysfs attribute. Fixes: 049a59db34eb ("firmware: Google VPD sysfs driver") Signed-off-by: Dmitry Torokhov Reviewed-by: Guenter Roeck Signed-off-by: Greg Kroah-Hartman --- drivers/firmware/google/vpd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/firmware/google/vpd.c b/drivers/firmware/google/vpd.c index 1e7860f02f4f..23a24a6d02c2 100644 --- a/drivers/firmware/google/vpd.c +++ b/drivers/firmware/google/vpd.c @@ -136,12 +136,12 @@ static int vpd_section_attrib_add(const u8 *key, s32 key_len, info->value = value; INIT_LIST_HEAD(&info->list); - list_add_tail(&info->list, &sec->attribs); ret = sysfs_create_bin_file(sec->kobj, &info->bin_attr); if (ret) goto free_info_key; + list_add_tail(&info->list, &sec->attribs); return 0; free_info_key: -- cgit v1.2.3 From ce57cba37f3721c21e46adf21c61292dfd7a9c04 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 23 May 2017 17:07:43 -0700 Subject: firmware: vpd: avoid potential use-after-free when destroying section We should not free info->key before we remove sysfs attribute that uses this data as its name. Fixes: 049a59db34eb ("firmware: Google VPD sysfs driver") Signed-off-by: Dmitry Torokhov Reviewed-by: Guenter Roeck Signed-off-by: Greg Kroah-Hartman --- drivers/firmware/google/vpd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/firmware/google/vpd.c b/drivers/firmware/google/vpd.c index 23a24a6d02c2..db49c6f98153 100644 --- a/drivers/firmware/google/vpd.c +++ b/drivers/firmware/google/vpd.c @@ -158,8 +158,8 @@ static void vpd_section_attrib_destroy(struct vpd_section *sec) struct vpd_attrib_info *temp; list_for_each_entry_safe(info, temp, &sec->attribs, list) { - kfree(info->key); sysfs_remove_bin_file(sec->kobj, &info->bin_attr); + kfree(info->key); kfree(info); } } -- cgit v1.2.3 From 2ee1cc70552e5520a275254427c0c37fc81728d2 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 23 May 2017 17:07:44 -0700 Subject: firmware: vpd: do not leak kobjects kobject_del() only unlinks kobject, we need to use kobject_put() to make sure kobject will go away completely. Fixes: 049a59db34eb ("firmware: Google VPD sysfs driver") Signed-off-by: Dmitry Torokhov Reviewed-by: Guenter Roeck Signed-off-by: Greg Kroah-Hartman --- drivers/firmware/google/vpd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/firmware/google/vpd.c b/drivers/firmware/google/vpd.c index db49c6f98153..31058d400bda 100644 --- a/drivers/firmware/google/vpd.c +++ b/drivers/firmware/google/vpd.c @@ -244,7 +244,7 @@ static int vpd_section_destroy(struct vpd_section *sec) { if (sec->enabled) { vpd_section_attrib_destroy(sec); - kobject_del(sec->kobj); + kobject_put(sec->kobj); sysfs_remove_bin_file(vpd_kobj, &sec->bin_attr); kfree(sec->raw_name); iounmap(sec->baseaddr); @@ -331,7 +331,7 @@ static void __exit vpd_platform_exit(void) { vpd_section_destroy(&ro_vpd); vpd_section_destroy(&rw_vpd); - kobject_del(vpd_kobj); + kobject_put(vpd_kobj); } module_init(vpd_platform_init); -- cgit v1.2.3 From 717902cc93118119a6fce7765da6cf2786987418 Mon Sep 17 00:00:00 2001 From: Timmy Li Date: Mon, 22 May 2017 16:48:28 +0100 Subject: ARM64: PCI: Fix struct acpi_pci_root_ops allocation failure path Commit 093d24a20442 ("arm64: PCI: Manage controller-specific data on per-controller basis") added code to allocate ACPI PCI root_ops dynamically on a per host bridge basis but failed to update the corresponding memory allocation failure path in pci_acpi_scan_root() leading to a potential memory leakage. Fix it by adding the required kfree call. Fixes: 093d24a20442 ("arm64: PCI: Manage controller-specific data on per-controller basis") Reviewed-by: Tomasz Nowicki Signed-off-by: Timmy Li [lorenzo.pieralisi@arm.com: refactored code, rewrote commit log] Signed-off-by: Lorenzo Pieralisi CC: Will Deacon CC: Bjorn Helgaas Signed-off-by: Catalin Marinas --- arch/arm64/kernel/pci.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c index 4f0e3ebfea4b..c7e3e6387a49 100644 --- a/arch/arm64/kernel/pci.c +++ b/arch/arm64/kernel/pci.c @@ -191,8 +191,10 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root) return NULL; root_ops = kzalloc_node(sizeof(*root_ops), GFP_KERNEL, node); - if (!root_ops) + if (!root_ops) { + kfree(ri); return NULL; + } ri->cfg = pci_acpi_setup_ecam_mapping(root); if (!ri->cfg) { -- cgit v1.2.3 From 3eff8ecd271d941b2326dba7defd0ca7c4c0baf5 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sun, 21 May 2017 00:45:46 +0000 Subject: goldfish_pipe: use GFP_ATOMIC under spin lock The function get_free_pipe_id_locked() is called from goldfish_pipe_open() with a lock is held, so we should use GFP_ATOMIC instead of GFP_KERNEL. Signed-off-by: Wei Yongjun Signed-off-by: Greg Kroah-Hartman --- drivers/platform/goldfish/goldfish_pipe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/goldfish/goldfish_pipe.c b/drivers/platform/goldfish/goldfish_pipe.c index 2de1e603bd2b..5f3672153b12 100644 --- a/drivers/platform/goldfish/goldfish_pipe.c +++ b/drivers/platform/goldfish/goldfish_pipe.c @@ -704,7 +704,7 @@ static int get_free_pipe_id_locked(struct goldfish_pipe_dev *dev) /* Reallocate the array */ u32 new_capacity = 2 * dev->pipes_capacity; struct goldfish_pipe **pipes = - kcalloc(new_capacity, sizeof(*pipes), GFP_KERNEL); + kcalloc(new_capacity, sizeof(*pipes), GFP_ATOMIC); if (!pipes) return -ENOMEM; memcpy(pipes, dev->pipes, sizeof(*pipes) * dev->pipes_capacity); -- cgit v1.2.3 From cdc1daca1b9b9ea3809009af944ade641dc32e86 Mon Sep 17 00:00:00 2001 From: "Guilherme G. Piccoli" Date: Thu, 18 May 2017 16:53:20 -0300 Subject: MAINTAINERS: Change maintainer of genwqe driver Gabriel won't maintain this driver anymore. So, I'll maintain it with Frank. Thanks Gabriel for all your work on genwqe. Signed-off-by: Guilherme G. Piccoli Acked-by: Gabriel Krisman Bertazi Acked-by: Frank Haverkamp Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 9e984645c4b0..4ee8967a1e4a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5622,7 +5622,7 @@ F: scripts/get_maintainer.pl GENWQE (IBM Generic Workqueue Card) M: Frank Haverkamp -M: Gabriel Krisman Bertazi +M: Guilherme G. Piccoli S: Supported F: drivers/misc/genwqe/ -- cgit v1.2.3 From 11387fe4a98f75d1f4cdb3efe3b42b19205c9df5 Mon Sep 17 00:00:00 2001 From: Eric Garver Date: Tue, 23 May 2017 18:37:27 -0400 Subject: geneve: fix fill_info when using collect_metadata Since 9b4437a5b870 ("geneve: Unify LWT and netdev handling.") fill_info does not return UDP_ZERO_CSUM6_RX when using COLLECT_METADATA. This is because it uses ip_tunnel_info_af() with the device level info, which is not valid for COLLECT_METADATA. Fix by checking for the presence of the actual sockets. Fixes: 9b4437a5b870 ("geneve: Unify LWT and netdev handling.") Signed-off-by: Eric Garver Acked-by: Pravin B Shelar Signed-off-by: David S. Miller --- drivers/net/geneve.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c index dec5d563ab19..959fd12d2e67 100644 --- a/drivers/net/geneve.c +++ b/drivers/net/geneve.c @@ -1293,7 +1293,7 @@ static int geneve_fill_info(struct sk_buff *skb, const struct net_device *dev) if (nla_put_u32(skb, IFLA_GENEVE_ID, vni)) goto nla_put_failure; - if (ip_tunnel_info_af(info) == AF_INET) { + if (rtnl_dereference(geneve->sock4)) { if (nla_put_in_addr(skb, IFLA_GENEVE_REMOTE, info->key.u.ipv4.dst)) goto nla_put_failure; @@ -1302,8 +1302,10 @@ static int geneve_fill_info(struct sk_buff *skb, const struct net_device *dev) !!(info->key.tun_flags & TUNNEL_CSUM))) goto nla_put_failure; + } + #if IS_ENABLED(CONFIG_IPV6) - } else { + if (rtnl_dereference(geneve->sock6)) { if (nla_put_in6_addr(skb, IFLA_GENEVE_REMOTE6, &info->key.u.ipv6.dst)) goto nla_put_failure; @@ -1315,8 +1317,8 @@ static int geneve_fill_info(struct sk_buff *skb, const struct net_device *dev) if (nla_put_u8(skb, IFLA_GENEVE_UDP_ZERO_CSUM6_RX, !geneve->use_udp6_rx_checksums)) goto nla_put_failure; -#endif } +#endif if (nla_put_u8(skb, IFLA_GENEVE_TTL, info->key.ttl) || nla_put_u8(skb, IFLA_GENEVE_TOS, info->key.tos) || -- cgit v1.2.3 From 65d786c21bf8140dac83563306f46fe0b13a9aaa Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 23 May 2017 18:18:37 -0500 Subject: net: fix potential null pointer dereference Add null check to avoid a potential null pointer dereference. Addresses-Coverity-ID: 1408831 Signed-off-by: Gustavo A. R. Silva Acked-by: Pablo Neira Ayuso Signed-off-by: David S. Miller --- drivers/net/gtp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index 4fea1b3dfbb4..7b652bb7ebe4 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -873,7 +873,7 @@ static struct gtp_dev *gtp_find_dev(struct net *src_net, struct nlattr *nla[]) /* Check if there's an existing gtpX device to configure */ dev = dev_get_by_index_rcu(net, nla_get_u32(nla[GTPA_LINK])); - if (dev->netdev_ops == >p_netdev_ops) + if (dev && dev->netdev_ops == >p_netdev_ops) gtp = netdev_priv(dev); put_net(net); -- cgit v1.2.3 From 4b3c7dbbfff0673e8a89575414b864d8b001d3bb Mon Sep 17 00:00:00 2001 From: KT Liao Date: Thu, 25 May 2017 10:06:21 -0700 Subject: Input: elan_i2c - clear INT before resetting controller Some old touchpad FWs need to have interrupt cleared before issuing reset command after updating firmware. We clear interrupt by attempting to read full report from the controller, and discarding any data read. Signed-off-by: KT Liao Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/elan_i2c_i2c.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/input/mouse/elan_i2c_i2c.c b/drivers/input/mouse/elan_i2c_i2c.c index a679e56c44cd..765879dcaf85 100644 --- a/drivers/input/mouse/elan_i2c_i2c.c +++ b/drivers/input/mouse/elan_i2c_i2c.c @@ -557,7 +557,14 @@ static int elan_i2c_finish_fw_update(struct i2c_client *client, long ret; int error; int len; - u8 buffer[ETP_I2C_INF_LENGTH]; + u8 buffer[ETP_I2C_REPORT_LEN]; + + len = i2c_master_recv(client, buffer, ETP_I2C_REPORT_LEN); + if (len != ETP_I2C_REPORT_LEN) { + error = len < 0 ? len : -EIO; + dev_warn(dev, "failed to read I2C data after FW WDT reset: %d (%d)\n", + error, len); + } reinit_completion(completion); enable_irq(client->irq); -- cgit v1.2.3 From a04f144059ac09f2c3da50b5707df589044aad66 Mon Sep 17 00:00:00 2001 From: KT Liao Date: Tue, 23 May 2017 13:41:47 -0700 Subject: Input: elan_i2c - ignore signals when finishing updating firmware Use wait_for_completion_timeout() instead of wait_for_completion_interruptible_timeout() to avoid stray signals ruining firmware update. Our timeout is only 300 msec so we are fine simply letting it expire in case device misbehaves. Signed-off-by: KT Liao Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/elan_i2c_i2c.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/drivers/input/mouse/elan_i2c_i2c.c b/drivers/input/mouse/elan_i2c_i2c.c index 765879dcaf85..f431da07f861 100644 --- a/drivers/input/mouse/elan_i2c_i2c.c +++ b/drivers/input/mouse/elan_i2c_i2c.c @@ -554,7 +554,6 @@ static int elan_i2c_finish_fw_update(struct i2c_client *client, struct completion *completion) { struct device *dev = &client->dev; - long ret; int error; int len; u8 buffer[ETP_I2C_REPORT_LEN]; @@ -570,23 +569,19 @@ static int elan_i2c_finish_fw_update(struct i2c_client *client, enable_irq(client->irq); error = elan_i2c_write_cmd(client, ETP_I2C_STAND_CMD, ETP_I2C_RESET); - if (!error) - ret = wait_for_completion_interruptible_timeout(completion, - msecs_to_jiffies(300)); - disable_irq(client->irq); - if (error) { dev_err(dev, "device reset failed: %d\n", error); - return error; - } else if (ret == 0) { + } else if (!wait_for_completion_timeout(completion, + msecs_to_jiffies(300))) { dev_err(dev, "timeout waiting for device reset\n"); - return -ETIMEDOUT; - } else if (ret < 0) { - error = ret; - dev_err(dev, "error waiting for device reset: %d\n", error); - return error; + error = -ETIMEDOUT; } + disable_irq(client->irq); + + if (error) + return error; + len = i2c_master_recv(client, buffer, ETP_I2C_INF_LENGTH); if (len != ETP_I2C_INF_LENGTH) { error = len < 0 ? len : -EIO; -- cgit v1.2.3 From 7c3f1875c66fbc19762760097cabc91849ea0bbb Mon Sep 17 00:00:00 2001 From: Roman Kapl Date: Wed, 24 May 2017 10:22:22 +0200 Subject: net: move somaxconn init from sysctl code The default value for somaxconn is set in sysctl_core_net_init(), but this function is not called when kernel is configured without CONFIG_SYSCTL. This results in the kernel not being able to accept TCP connections, because the backlog has zero size. Usually, the user ends up with: "TCP: request_sock_TCP: Possible SYN flooding on port 7. Dropping request. Check SNMP counters." If SYN cookies are not enabled the connection is rejected. Before ef547f2ac16 (tcp: remove max_qlen_log), the effects were less severe, because the backlog was always at least eight slots long. Signed-off-by: Roman Kapl Signed-off-by: David S. Miller --- net/core/net_namespace.c | 19 +++++++++++++++++++ net/core/sysctl_net_core.c | 2 -- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index 1934efd4a9d4..26bbfababff2 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -315,6 +315,25 @@ out_undo: goto out; } +static int __net_init net_defaults_init_net(struct net *net) +{ + net->core.sysctl_somaxconn = SOMAXCONN; + return 0; +} + +static struct pernet_operations net_defaults_ops = { + .init = net_defaults_init_net, +}; + +static __init int net_defaults_init(void) +{ + if (register_pernet_subsys(&net_defaults_ops)) + panic("Cannot initialize net default settings"); + + return 0; +} + +core_initcall(net_defaults_init); #ifdef CONFIG_NET_NS static struct ucounts *inc_net_namespaces(struct user_namespace *ns) diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c index ea23254b2457..b7cd9aafe99e 100644 --- a/net/core/sysctl_net_core.c +++ b/net/core/sysctl_net_core.c @@ -479,8 +479,6 @@ static __net_init int sysctl_core_net_init(struct net *net) { struct ctl_table *tbl; - net->core.sysctl_somaxconn = SOMAXCONN; - tbl = netns_core_table; if (!net_eq(net, &init_net)) { tbl = kmemdup(tbl, sizeof(netns_core_table), GFP_KERNEL); -- cgit v1.2.3 From ba615f675281d76fd19aa03558777f81fb6b6084 Mon Sep 17 00:00:00 2001 From: Wei Wang Date: Wed, 24 May 2017 09:59:31 -0700 Subject: tcp: avoid fastopen API to be used on AF_UNSPEC Fastopen API should be used to perform fastopen operations on the TCP socket. It does not make sense to use fastopen API to perform disconnect by calling it with AF_UNSPEC. The fastopen data path is also prone to race conditions and bugs when using with AF_UNSPEC. One issue reported and analyzed by Vegard Nossum is as follows: +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Thread A: Thread B: ------------------------------------------------------------------------ sendto() - tcp_sendmsg() - sk_stream_memory_free() = 0 - goto wait_for_sndbuf - sk_stream_wait_memory() - sk_wait_event() // sleep | sendto(flags=MSG_FASTOPEN, dest_addr=AF_UNSPEC) | - tcp_sendmsg() | - tcp_sendmsg_fastopen() | - __inet_stream_connect() | - tcp_disconnect() //because of AF_UNSPEC | - tcp_transmit_skb()// send RST | - return 0; // no reconnect! | - sk_stream_wait_connect() | - sock_error() | - xchg(&sk->sk_err, 0) | - return -ECONNRESET - ... // wake up, see sk->sk_err == 0 - skb_entail() on TCP_CLOSE socket If the connection is reopened then we will send a brand new SYN packet after thread A has already queued a buffer. At this point I think the socket internal state (sequence numbers etc.) becomes messed up. When the new connection is closed, the FIN-ACK is rejected because the sequence number is outside the window. The other side tries to retransmit, but __tcp_retransmit_skb() calls tcp_trim_head() on an empty skb which corrupts the skb data length and hits a BUG() in copy_and_csum_bits(). +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Hence, this patch adds a check for AF_UNSPEC in the fastopen data path and return EOPNOTSUPP to user if such case happens. Fixes: cf60af03ca4e7 ("tcp: Fast Open client - sendmsg(MSG_FASTOPEN)") Reported-by: Vegard Nossum Signed-off-by: Wei Wang Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/tcp.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 842b575f8fdd..59792d283ff8 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -1084,9 +1084,12 @@ static int tcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg, { struct tcp_sock *tp = tcp_sk(sk); struct inet_sock *inet = inet_sk(sk); + struct sockaddr *uaddr = msg->msg_name; int err, flags; - if (!(sysctl_tcp_fastopen & TFO_CLIENT_ENABLE)) + if (!(sysctl_tcp_fastopen & TFO_CLIENT_ENABLE) || + (uaddr && msg->msg_namelen >= sizeof(uaddr->sa_family) && + uaddr->sa_family == AF_UNSPEC)) return -EOPNOTSUPP; if (tp->fastopen_req) return -EALREADY; /* Another Fast Open is in progress */ @@ -1108,7 +1111,7 @@ static int tcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg, } } flags = (msg->msg_flags & MSG_DONTWAIT) ? O_NONBLOCK : 0; - err = __inet_stream_connect(sk->sk_socket, msg->msg_name, + err = __inet_stream_connect(sk->sk_socket, uaddr, msg->msg_namelen, flags, 1); /* fastopen_req could already be freed in __inet_stream_connect * if the connection times out or gets rst -- cgit v1.2.3 From 5990baaa6d7b437dfcf58b7021ca56b1d6b35869 Mon Sep 17 00:00:00 2001 From: Ihar Hrachyshka Date: Wed, 24 May 2017 15:19:35 -0700 Subject: arp: fixed -Wuninitialized compiler warning Commit 7d472a59c0e5ec117220a05de6b370447fb6cb66 ("arp: always override existing neigh entries with gratuitous ARP") introduced a compiler warning: net/ipv4/arp.c:880:35: warning: 'addr_type' may be used uninitialized in this function [-Wmaybe-uninitialized] While the code logic seems to be correct and doesn't allow the variable to be used uninitialized, and the warning is not consistently reproducible, it's still worth fixing it for other people not to waste time looking at the warning in case it pops up in the build environment. Yes, compiler is probably at fault, but we will need to accommodate. Fixes: 7d472a59c0e5 ("arp: always override existing neigh entries with gratuitous ARP") Signed-off-by: Ihar Hrachyshka Signed-off-by: David S. Miller --- net/ipv4/arp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index ae96e6f3e0cb..e9f3386a528b 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -863,8 +863,8 @@ static int arp_process(struct net *net, struct sock *sk, struct sk_buff *skb) n = __neigh_lookup(&arp_tbl, &sip, dev, 0); + addr_type = -1; if (n || IN_DEV_ARP_ACCEPT(in_dev)) { - addr_type = -1; is_garp = arp_is_garp(net, dev, &addr_type, arp->ar_op, sip, tip, sha, tha); } -- cgit v1.2.3 From 1ad2f5838d345e1c102bd1cd27c4f4c1349b0dc8 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Thu, 25 May 2017 01:05:05 +0200 Subject: bpf: fix incorrect pruning decision when alignment must be tracked Currently, when we enforce alignment tracking on direct packet access, the verifier lets the following program pass despite doing a packet write with unaligned access: 0: (61) r2 = *(u32 *)(r1 +76) 1: (61) r3 = *(u32 *)(r1 +80) 2: (61) r7 = *(u32 *)(r1 +8) 3: (bf) r0 = r2 4: (07) r0 += 14 5: (25) if r7 > 0x1 goto pc+4 R0=pkt(id=0,off=14,r=0) R1=ctx R2=pkt(id=0,off=0,r=0) R3=pkt_end R7=inv,min_value=0,max_value=1 R10=fp 6: (2d) if r0 > r3 goto pc+1 R0=pkt(id=0,off=14,r=14) R1=ctx R2=pkt(id=0,off=0,r=14) R3=pkt_end R7=inv,min_value=0,max_value=1 R10=fp 7: (63) *(u32 *)(r0 -4) = r0 8: (b7) r0 = 0 9: (95) exit from 6 to 8: R0=pkt(id=0,off=14,r=0) R1=ctx R2=pkt(id=0,off=0,r=0) R3=pkt_end R7=inv,min_value=0,max_value=1 R10=fp 8: (b7) r0 = 0 9: (95) exit from 5 to 10: R0=pkt(id=0,off=14,r=0) R1=ctx R2=pkt(id=0,off=0,r=0) R3=pkt_end R7=inv,min_value=2 R10=fp 10: (07) r0 += 1 11: (05) goto pc-6 6: safe <----- here, wrongly found safe processed 15 insns However, if we enforce a pruning mismatch by adding state into r8 which is then being mismatched in states_equal(), we find that for the otherwise same program, the verifier detects a misaligned packet access when actually walking that path: 0: (61) r2 = *(u32 *)(r1 +76) 1: (61) r3 = *(u32 *)(r1 +80) 2: (61) r7 = *(u32 *)(r1 +8) 3: (b7) r8 = 1 4: (bf) r0 = r2 5: (07) r0 += 14 6: (25) if r7 > 0x1 goto pc+4 R0=pkt(id=0,off=14,r=0) R1=ctx R2=pkt(id=0,off=0,r=0) R3=pkt_end R7=inv,min_value=0,max_value=1 R8=imm1,min_value=1,max_value=1,min_align=1 R10=fp 7: (2d) if r0 > r3 goto pc+1 R0=pkt(id=0,off=14,r=14) R1=ctx R2=pkt(id=0,off=0,r=14) R3=pkt_end R7=inv,min_value=0,max_value=1 R8=imm1,min_value=1,max_value=1,min_align=1 R10=fp 8: (63) *(u32 *)(r0 -4) = r0 9: (b7) r0 = 0 10: (95) exit from 7 to 9: R0=pkt(id=0,off=14,r=0) R1=ctx R2=pkt(id=0,off=0,r=0) R3=pkt_end R7=inv,min_value=0,max_value=1 R8=imm1,min_value=1,max_value=1,min_align=1 R10=fp 9: (b7) r0 = 0 10: (95) exit from 6 to 11: R0=pkt(id=0,off=14,r=0) R1=ctx R2=pkt(id=0,off=0,r=0) R3=pkt_end R7=inv,min_value=2 R8=imm1,min_value=1,max_value=1,min_align=1 R10=fp 11: (07) r0 += 1 12: (b7) r8 = 0 13: (05) goto pc-7 <----- mismatch due to r8 7: (2d) if r0 > r3 goto pc+1 R0=pkt(id=0,off=15,r=15) R1=ctx R2=pkt(id=0,off=0,r=15) R3=pkt_end R7=inv,min_value=2 R8=imm0,min_value=0,max_value=0,min_align=2147483648 R10=fp 8: (63) *(u32 *)(r0 -4) = r0 misaligned packet access off 2+15+-4 size 4 The reason why we fail to see it in states_equal() is that the third test in compare_ptrs_to_packet() ... if (old->off <= cur->off && old->off >= old->range && cur->off >= cur->range) return true; ... will let the above pass. The situation we run into is that old->off <= cur->off (14 <= 15), meaning that prior walked paths went with smaller offset, which was later used in the packet access after successful packet range check and found to be safe already. For example: Given is R0=pkt(id=0,off=0,r=0). Adding offset 14 as in above program to it, results in R0=pkt(id=0,off=14,r=0) before the packet range test. Now, testing this against R3=pkt_end with 'if r0 > r3 goto out' will transform R0 into R0=pkt(id=0,off=14,r=14) for the case when we're within bounds. A write into the packet at offset *(u32 *)(r0 -4), that is, 2 + 14 -4, is valid and aligned (2 is for NET_IP_ALIGN). After processing this with all fall-through paths, we later on check paths from branches. When the above skb->mark test is true, then we jump near the end of the program, perform r0 += 1, and jump back to the 'if r0 > r3 goto out' test we've visited earlier already. This time, R0 is of type R0=pkt(id=0,off=15,r=0), and we'll prune that part because this time we'll have a larger safe packet range, and we already found that with off=14 all further insn were already safe, so it's safe as well with a larger off. However, the problem is that the subsequent write into the packet with 2 + 15 -4 is then unaligned, and not caught by the alignment tracking. Note that min_align, aux_off, and aux_off_align were all 0 in this example. Since we cannot tell at this time what kind of packet access was performed in the prior walk and what minimal requirements it has (we might do so in the future, but that requires more complexity), fix it to disable this pruning case for strict alignment for now, and let the verifier do check such paths instead. With that applied, the test cases pass and reject the program due to misalignment. Fixes: d1174416747d ("bpf: Track alignment of register values in the verifier.") Reference: http://patchwork.ozlabs.org/patch/761909/ Signed-off-by: Daniel Borkmann Acked-by: Alexei Starovoitov Signed-off-by: David S. Miller --- kernel/bpf/verifier.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index c72cd41f5b8b..e37e06b1229d 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -843,9 +843,6 @@ static int check_ptr_alignment(struct bpf_verifier_env *env, { bool strict = env->strict_alignment; - if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)) - strict = true; - switch (reg->type) { case PTR_TO_PACKET: return check_pkt_ptr_alignment(reg, off, size, strict); @@ -2696,7 +2693,8 @@ err_free: /* the following conditions reduce the number of explored insns * from ~140k to ~80k for ultra large programs that use a lot of ptr_to_packet */ -static bool compare_ptrs_to_packet(struct bpf_reg_state *old, +static bool compare_ptrs_to_packet(struct bpf_verifier_env *env, + struct bpf_reg_state *old, struct bpf_reg_state *cur) { if (old->id != cur->id) @@ -2739,7 +2737,7 @@ static bool compare_ptrs_to_packet(struct bpf_reg_state *old, * 'if (R4 > data_end)' and all further insn were already good with r=20, * so they will be good with r=30 and we can prune the search. */ - if (old->off <= cur->off && + if (!env->strict_alignment && old->off <= cur->off && old->off >= old->range && cur->off >= cur->range) return true; @@ -2810,7 +2808,7 @@ static bool states_equal(struct bpf_verifier_env *env, continue; if (rold->type == PTR_TO_PACKET && rcur->type == PTR_TO_PACKET && - compare_ptrs_to_packet(rold, rcur)) + compare_ptrs_to_packet(env, rold, rcur)) continue; return false; @@ -3588,10 +3586,10 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr) } else { log_level = 0; } - if (attr->prog_flags & BPF_F_STRICT_ALIGNMENT) + + env->strict_alignment = !!(attr->prog_flags & BPF_F_STRICT_ALIGNMENT); + if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)) env->strict_alignment = true; - else - env->strict_alignment = false; ret = replace_map_fd_with_map_ptr(env); if (ret < 0) @@ -3697,7 +3695,10 @@ int bpf_analyzer(struct bpf_prog *prog, const struct bpf_ext_analyzer_ops *ops, mutex_lock(&bpf_verifier_lock); log_level = 0; + env->strict_alignment = false; + if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)) + env->strict_alignment = true; env->explored_states = kcalloc(env->prog->len, sizeof(struct bpf_verifier_state_list *), -- cgit v1.2.3 From a9789ef9afcb4fb0193f8dd94f2665ba3ad71e79 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Thu, 25 May 2017 01:05:06 +0200 Subject: bpf: properly reset caller saved regs after helper call and ld_abs/ind Currently, after performing helper calls, we clear all caller saved registers, that is r0 - r5 and fill r0 depending on struct bpf_func_proto specification. The way we reset these regs can affect pruning decisions in later paths, since we only reset register's imm to 0 and type to NOT_INIT. However, we leave out clearing of other variables such as id, min_value, max_value, etc, which can later on lead to pruning mismatches due to stale data. Signed-off-by: Daniel Borkmann Acked-by: Alexei Starovoitov Signed-off-by: David S. Miller --- kernel/bpf/verifier.c | 37 ++++++++++++++++--------------------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index e37e06b1229d..339c8a1371de 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -463,19 +463,22 @@ static const int caller_saved[CALLER_SAVED_REGS] = { BPF_REG_0, BPF_REG_1, BPF_REG_2, BPF_REG_3, BPF_REG_4, BPF_REG_5 }; +static void mark_reg_not_init(struct bpf_reg_state *regs, u32 regno) +{ + BUG_ON(regno >= MAX_BPF_REG); + + memset(®s[regno], 0, sizeof(regs[regno])); + regs[regno].type = NOT_INIT; + regs[regno].min_value = BPF_REGISTER_MIN_RANGE; + regs[regno].max_value = BPF_REGISTER_MAX_RANGE; +} + static void init_reg_state(struct bpf_reg_state *regs) { int i; - for (i = 0; i < MAX_BPF_REG; i++) { - regs[i].type = NOT_INIT; - regs[i].imm = 0; - regs[i].min_value = BPF_REGISTER_MIN_RANGE; - regs[i].max_value = BPF_REGISTER_MAX_RANGE; - regs[i].min_align = 0; - regs[i].aux_off = 0; - regs[i].aux_off_align = 0; - } + for (i = 0; i < MAX_BPF_REG; i++) + mark_reg_not_init(regs, i); /* frame pointer */ regs[BPF_REG_FP].type = FRAME_PTR; @@ -1346,7 +1349,6 @@ static int check_call(struct bpf_verifier_env *env, int func_id, int insn_idx) struct bpf_verifier_state *state = &env->cur_state; const struct bpf_func_proto *fn = NULL; struct bpf_reg_state *regs = state->regs; - struct bpf_reg_state *reg; struct bpf_call_arg_meta meta; bool changes_data; int i, err; @@ -1413,11 +1415,8 @@ static int check_call(struct bpf_verifier_env *env, int func_id, int insn_idx) } /* reset caller saved regs */ - for (i = 0; i < CALLER_SAVED_REGS; i++) { - reg = regs + caller_saved[i]; - reg->type = NOT_INIT; - reg->imm = 0; - } + for (i = 0; i < CALLER_SAVED_REGS; i++) + mark_reg_not_init(regs, caller_saved[i]); /* update return register */ if (fn->ret_type == RET_INTEGER) { @@ -2445,7 +2444,6 @@ static int check_ld_abs(struct bpf_verifier_env *env, struct bpf_insn *insn) { struct bpf_reg_state *regs = env->cur_state.regs; u8 mode = BPF_MODE(insn->code); - struct bpf_reg_state *reg; int i, err; if (!may_access_skb(env->prog->type)) { @@ -2478,11 +2476,8 @@ static int check_ld_abs(struct bpf_verifier_env *env, struct bpf_insn *insn) } /* reset caller saved regs to unreadable */ - for (i = 0; i < CALLER_SAVED_REGS; i++) { - reg = regs + caller_saved[i]; - reg->type = NOT_INIT; - reg->imm = 0; - } + for (i = 0; i < CALLER_SAVED_REGS; i++) + mark_reg_not_init(regs, caller_saved[i]); /* mark destination R0 register as readable, since it contains * the value fetched from the packet -- cgit v1.2.3 From 41703a731066fde79c3e5ccf3391cf77a98aeda5 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Thu, 25 May 2017 01:05:07 +0200 Subject: bpf: add bpf_clone_redirect to bpf_helper_changes_pkt_data The bpf_clone_redirect() still needs to be listed in bpf_helper_changes_pkt_data() since we call into bpf_try_make_head_writable() from there, thus we need to invalidate prior pkt regs as well. Fixes: 36bbef52c7eb ("bpf: direct packet write and access for helpers for clsact progs") Signed-off-by: Daniel Borkmann Acked-by: Alexei Starovoitov Signed-off-by: David S. Miller --- net/core/filter.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/core/filter.c b/net/core/filter.c index a253a6197e6b..a6bb95fa87b2 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -2281,6 +2281,7 @@ bool bpf_helper_changes_pkt_data(void *func) func == bpf_skb_change_head || func == bpf_skb_change_tail || func == bpf_skb_pull_data || + func == bpf_clone_redirect || func == bpf_l3_csum_replace || func == bpf_l4_csum_replace || func == bpf_xdp_adjust_head) -- cgit v1.2.3 From a316338cb71a3260201490e615f2f6d5c0d8fb2c Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Thu, 25 May 2017 01:05:08 +0200 Subject: bpf: fix wrong exposure of map_flags into fdinfo for lpm trie_alloc() always needs to have BPF_F_NO_PREALLOC passed in via attr->map_flags, since it does not support preallocation yet. We check the flag, but we never copy the flag into trie->map.map_flags, which is later on exposed into fdinfo and used by loaders such as iproute2. Latter uses this in bpf_map_selfcheck_pinned() to test whether a pinned map has the same spec as the one from the BPF obj file and if not, bails out, which is currently the case for lpm since it exposes always 0 as flags. Also copy over flags in array_map_alloc() and stack_map_alloc(). They always have to be 0 right now, but we should make sure to not miss to copy them over at a later point in time when we add actual flags for them to use. Fixes: b95a5c4db09b ("bpf: add a longest prefix match trie map implementation") Reported-by: Jarno Rajahalme Signed-off-by: Daniel Borkmann Acked-by: Alexei Starovoitov Signed-off-by: David S. Miller --- kernel/bpf/arraymap.c | 1 + kernel/bpf/lpm_trie.c | 1 + kernel/bpf/stackmap.c | 1 + 3 files changed, 3 insertions(+) diff --git a/kernel/bpf/arraymap.c b/kernel/bpf/arraymap.c index 5e00b2333c26..172dc8ee0e3b 100644 --- a/kernel/bpf/arraymap.c +++ b/kernel/bpf/arraymap.c @@ -86,6 +86,7 @@ static struct bpf_map *array_map_alloc(union bpf_attr *attr) array->map.key_size = attr->key_size; array->map.value_size = attr->value_size; array->map.max_entries = attr->max_entries; + array->map.map_flags = attr->map_flags; array->elem_size = elem_size; if (!percpu) diff --git a/kernel/bpf/lpm_trie.c b/kernel/bpf/lpm_trie.c index 39cfafd895b8..b09185f0f17d 100644 --- a/kernel/bpf/lpm_trie.c +++ b/kernel/bpf/lpm_trie.c @@ -432,6 +432,7 @@ static struct bpf_map *trie_alloc(union bpf_attr *attr) trie->map.key_size = attr->key_size; trie->map.value_size = attr->value_size; trie->map.max_entries = attr->max_entries; + trie->map.map_flags = attr->map_flags; trie->data_size = attr->key_size - offsetof(struct bpf_lpm_trie_key, data); trie->max_prefixlen = trie->data_size * 8; diff --git a/kernel/bpf/stackmap.c b/kernel/bpf/stackmap.c index 4dfd6f2ec2f9..31147d730abf 100644 --- a/kernel/bpf/stackmap.c +++ b/kernel/bpf/stackmap.c @@ -88,6 +88,7 @@ static struct bpf_map *stack_map_alloc(union bpf_attr *attr) smap->map.key_size = attr->key_size; smap->map.value_size = value_size; smap->map.max_entries = attr->max_entries; + smap->map.map_flags = attr->map_flags; smap->n_buckets = n_buckets; smap->map.pages = round_up(cost, PAGE_SIZE) >> PAGE_SHIFT; -- cgit v1.2.3 From 614d0d77b49a9b131e58b77473698ab5b2c525b7 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Thu, 25 May 2017 01:05:09 +0200 Subject: bpf: add various verifier test cases This patch adds various verifier test cases: 1) A test case for the pruning issue when tracking alignment is used. 2) Various PTR_TO_MAP_VALUE_OR_NULL tests to make sure pointer arithmetic turns such register into UNKNOWN_VALUE type. 3) Test cases for the special treatment of LD_ABS/LD_IND to make sure verifier doesn't break calling convention here. Latter is needed, since f.e. arm64 JIT uses r1 - r5 for storing temporary data, so they really must be marked as NOT_INIT. Signed-off-by: Daniel Borkmann Acked-by: Alexei Starovoitov Signed-off-by: David S. Miller --- include/linux/filter.h | 10 ++ tools/include/linux/filter.h | 10 ++ tools/testing/selftests/bpf/test_verifier.c | 239 +++++++++++++++++++++++++++- 3 files changed, 255 insertions(+), 4 deletions(-) diff --git a/include/linux/filter.h b/include/linux/filter.h index 56197f82af45..62d948f80730 100644 --- a/include/linux/filter.h +++ b/include/linux/filter.h @@ -272,6 +272,16 @@ struct bpf_prog_aux; .off = OFF, \ .imm = IMM }) +/* Unconditional jumps, goto pc + off16 */ + +#define BPF_JMP_A(OFF) \ + ((struct bpf_insn) { \ + .code = BPF_JMP | BPF_JA, \ + .dst_reg = 0, \ + .src_reg = 0, \ + .off = OFF, \ + .imm = 0 }) + /* Function call */ #define BPF_EMIT_CALL(FUNC) \ diff --git a/tools/include/linux/filter.h b/tools/include/linux/filter.h index 390d7c9685fd..4ce25d43e8e3 100644 --- a/tools/include/linux/filter.h +++ b/tools/include/linux/filter.h @@ -208,6 +208,16 @@ .off = OFF, \ .imm = IMM }) +/* Unconditional jumps, goto pc + off16 */ + +#define BPF_JMP_A(OFF) \ + ((struct bpf_insn) { \ + .code = BPF_JMP | BPF_JA, \ + .dst_reg = 0, \ + .src_reg = 0, \ + .off = OFF, \ + .imm = 0 }) + /* Function call */ #define BPF_EMIT_CALL(FUNC) \ diff --git a/tools/testing/selftests/bpf/test_verifier.c b/tools/testing/selftests/bpf/test_verifier.c index 3773562056da..cabb19b1e371 100644 --- a/tools/testing/selftests/bpf/test_verifier.c +++ b/tools/testing/selftests/bpf/test_verifier.c @@ -49,6 +49,7 @@ #define MAX_NR_MAPS 4 #define F_NEEDS_EFFICIENT_UNALIGNED_ACCESS (1 << 0) +#define F_LOAD_WITH_STRICT_ALIGNMENT (1 << 1) struct bpf_test { const char *descr; @@ -2614,6 +2615,30 @@ static struct bpf_test tests[] = { .result = REJECT, .prog_type = BPF_PROG_TYPE_SCHED_CLS, }, + { + "direct packet access: test17 (pruning, alignment)", + .insns = { + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, + offsetof(struct __sk_buff, data)), + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, + offsetof(struct __sk_buff, data_end)), + BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1, + offsetof(struct __sk_buff, mark)), + BPF_MOV64_REG(BPF_REG_0, BPF_REG_2), + BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 14), + BPF_JMP_IMM(BPF_JGT, BPF_REG_7, 1, 4), + BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 1), + BPF_STX_MEM(BPF_W, BPF_REG_0, BPF_REG_0, -4), + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_EXIT_INSN(), + BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 1), + BPF_JMP_A(-6), + }, + .errstr = "misaligned packet access off 2+15+-4 size 4", + .result = REJECT, + .prog_type = BPF_PROG_TYPE_SCHED_CLS, + .flags = F_LOAD_WITH_STRICT_ALIGNMENT, + }, { "helper access to packet: test1, valid packet_ptr range", .insns = { @@ -3340,6 +3365,70 @@ static struct bpf_test tests[] = { .result = ACCEPT, .prog_type = BPF_PROG_TYPE_SCHED_CLS }, + { + "alu ops on ptr_to_map_value_or_null, 1", + .insns = { + BPF_MOV64_IMM(BPF_REG_1, 10), + BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8), + BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), + BPF_LD_MAP_FD(BPF_REG_1, 0), + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, + BPF_FUNC_map_lookup_elem), + BPF_MOV64_REG(BPF_REG_4, BPF_REG_0), + BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, -2), + BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 2), + BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1), + BPF_ST_MEM(BPF_DW, BPF_REG_4, 0, 0), + BPF_EXIT_INSN(), + }, + .fixup_map1 = { 4 }, + .errstr = "R4 invalid mem access", + .result = REJECT, + .prog_type = BPF_PROG_TYPE_SCHED_CLS + }, + { + "alu ops on ptr_to_map_value_or_null, 2", + .insns = { + BPF_MOV64_IMM(BPF_REG_1, 10), + BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8), + BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), + BPF_LD_MAP_FD(BPF_REG_1, 0), + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, + BPF_FUNC_map_lookup_elem), + BPF_MOV64_REG(BPF_REG_4, BPF_REG_0), + BPF_ALU64_IMM(BPF_AND, BPF_REG_4, -1), + BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1), + BPF_ST_MEM(BPF_DW, BPF_REG_4, 0, 0), + BPF_EXIT_INSN(), + }, + .fixup_map1 = { 4 }, + .errstr = "R4 invalid mem access", + .result = REJECT, + .prog_type = BPF_PROG_TYPE_SCHED_CLS + }, + { + "alu ops on ptr_to_map_value_or_null, 3", + .insns = { + BPF_MOV64_IMM(BPF_REG_1, 10), + BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8), + BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), + BPF_LD_MAP_FD(BPF_REG_1, 0), + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, + BPF_FUNC_map_lookup_elem), + BPF_MOV64_REG(BPF_REG_4, BPF_REG_0), + BPF_ALU64_IMM(BPF_LSH, BPF_REG_4, 1), + BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1), + BPF_ST_MEM(BPF_DW, BPF_REG_4, 0, 0), + BPF_EXIT_INSN(), + }, + .fixup_map1 = { 4 }, + .errstr = "R4 invalid mem access", + .result = REJECT, + .prog_type = BPF_PROG_TYPE_SCHED_CLS + }, { "invalid memory access with multiple map_lookup_elem calls", .insns = { @@ -4937,7 +5026,149 @@ static struct bpf_test tests[] = { .fixup_map_in_map = { 3 }, .errstr = "R1 type=map_value_or_null expected=map_ptr", .result = REJECT, - } + }, + { + "ld_abs: check calling conv, r1", + .insns = { + BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), + BPF_MOV64_IMM(BPF_REG_1, 0), + BPF_LD_ABS(BPF_W, -0x200000), + BPF_MOV64_REG(BPF_REG_0, BPF_REG_1), + BPF_EXIT_INSN(), + }, + .errstr = "R1 !read_ok", + .result = REJECT, + }, + { + "ld_abs: check calling conv, r2", + .insns = { + BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), + BPF_MOV64_IMM(BPF_REG_2, 0), + BPF_LD_ABS(BPF_W, -0x200000), + BPF_MOV64_REG(BPF_REG_0, BPF_REG_2), + BPF_EXIT_INSN(), + }, + .errstr = "R2 !read_ok", + .result = REJECT, + }, + { + "ld_abs: check calling conv, r3", + .insns = { + BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), + BPF_MOV64_IMM(BPF_REG_3, 0), + BPF_LD_ABS(BPF_W, -0x200000), + BPF_MOV64_REG(BPF_REG_0, BPF_REG_3), + BPF_EXIT_INSN(), + }, + .errstr = "R3 !read_ok", + .result = REJECT, + }, + { + "ld_abs: check calling conv, r4", + .insns = { + BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), + BPF_MOV64_IMM(BPF_REG_4, 0), + BPF_LD_ABS(BPF_W, -0x200000), + BPF_MOV64_REG(BPF_REG_0, BPF_REG_4), + BPF_EXIT_INSN(), + }, + .errstr = "R4 !read_ok", + .result = REJECT, + }, + { + "ld_abs: check calling conv, r5", + .insns = { + BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), + BPF_MOV64_IMM(BPF_REG_5, 0), + BPF_LD_ABS(BPF_W, -0x200000), + BPF_MOV64_REG(BPF_REG_0, BPF_REG_5), + BPF_EXIT_INSN(), + }, + .errstr = "R5 !read_ok", + .result = REJECT, + }, + { + "ld_abs: check calling conv, r7", + .insns = { + BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), + BPF_MOV64_IMM(BPF_REG_7, 0), + BPF_LD_ABS(BPF_W, -0x200000), + BPF_MOV64_REG(BPF_REG_0, BPF_REG_7), + BPF_EXIT_INSN(), + }, + .result = ACCEPT, + }, + { + "ld_ind: check calling conv, r1", + .insns = { + BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), + BPF_MOV64_IMM(BPF_REG_1, 1), + BPF_LD_IND(BPF_W, BPF_REG_1, -0x200000), + BPF_MOV64_REG(BPF_REG_0, BPF_REG_1), + BPF_EXIT_INSN(), + }, + .errstr = "R1 !read_ok", + .result = REJECT, + }, + { + "ld_ind: check calling conv, r2", + .insns = { + BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), + BPF_MOV64_IMM(BPF_REG_2, 1), + BPF_LD_IND(BPF_W, BPF_REG_2, -0x200000), + BPF_MOV64_REG(BPF_REG_0, BPF_REG_2), + BPF_EXIT_INSN(), + }, + .errstr = "R2 !read_ok", + .result = REJECT, + }, + { + "ld_ind: check calling conv, r3", + .insns = { + BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), + BPF_MOV64_IMM(BPF_REG_3, 1), + BPF_LD_IND(BPF_W, BPF_REG_3, -0x200000), + BPF_MOV64_REG(BPF_REG_0, BPF_REG_3), + BPF_EXIT_INSN(), + }, + .errstr = "R3 !read_ok", + .result = REJECT, + }, + { + "ld_ind: check calling conv, r4", + .insns = { + BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), + BPF_MOV64_IMM(BPF_REG_4, 1), + BPF_LD_IND(BPF_W, BPF_REG_4, -0x200000), + BPF_MOV64_REG(BPF_REG_0, BPF_REG_4), + BPF_EXIT_INSN(), + }, + .errstr = "R4 !read_ok", + .result = REJECT, + }, + { + "ld_ind: check calling conv, r5", + .insns = { + BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), + BPF_MOV64_IMM(BPF_REG_5, 1), + BPF_LD_IND(BPF_W, BPF_REG_5, -0x200000), + BPF_MOV64_REG(BPF_REG_0, BPF_REG_5), + BPF_EXIT_INSN(), + }, + .errstr = "R5 !read_ok", + .result = REJECT, + }, + { + "ld_ind: check calling conv, r7", + .insns = { + BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), + BPF_MOV64_IMM(BPF_REG_7, 1), + BPF_LD_IND(BPF_W, BPF_REG_7, -0x200000), + BPF_MOV64_REG(BPF_REG_0, BPF_REG_7), + BPF_EXIT_INSN(), + }, + .result = ACCEPT, + }, }; static int probe_filter_length(const struct bpf_insn *fp) @@ -5059,9 +5290,9 @@ static void do_test_single(struct bpf_test *test, bool unpriv, do_test_fixup(test, prog, map_fds); - fd_prog = bpf_load_program(prog_type ? : BPF_PROG_TYPE_SOCKET_FILTER, - prog, prog_len, "GPL", 0, bpf_vlog, - sizeof(bpf_vlog)); + fd_prog = bpf_verify_program(prog_type ? : BPF_PROG_TYPE_SOCKET_FILTER, + prog, prog_len, test->flags & F_LOAD_WITH_STRICT_ALIGNMENT, + "GPL", 0, bpf_vlog, sizeof(bpf_vlog)); expected_ret = unpriv && test->result_unpriv != UNDEF ? test->result_unpriv : test->result; -- cgit v1.2.3 From 791caeb084c57e3a4d648cf1ee799d1f70c0ef4e Mon Sep 17 00:00:00 2001 From: David Daney Date: Wed, 24 May 2017 16:35:49 -0700 Subject: test_bpf: Add a couple of tests for BPF_JSGE. Some JITs can optimize comparisons with zero. Add a couple of BPF_JSGE tests against immediate zero. Signed-off-by: David Daney Acked-by: Daniel Borkmann Signed-off-by: David S. Miller --- lib/test_bpf.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/lib/test_bpf.c b/lib/test_bpf.c index 889bc31785be..be88cbaadde3 100644 --- a/lib/test_bpf.c +++ b/lib/test_bpf.c @@ -4504,6 +4504,44 @@ static struct bpf_test tests[] = { { }, { { 0, 1 } }, }, + { + "JMP_JSGE_K: Signed jump: value walk 1", + .u.insns_int = { + BPF_ALU32_IMM(BPF_MOV, R0, 0), + BPF_LD_IMM64(R1, -3), + BPF_JMP_IMM(BPF_JSGE, R1, 0, 6), + BPF_ALU64_IMM(BPF_ADD, R1, 1), + BPF_JMP_IMM(BPF_JSGE, R1, 0, 4), + BPF_ALU64_IMM(BPF_ADD, R1, 1), + BPF_JMP_IMM(BPF_JSGE, R1, 0, 2), + BPF_ALU64_IMM(BPF_ADD, R1, 1), + BPF_JMP_IMM(BPF_JSGE, R1, 0, 1), + BPF_EXIT_INSN(), /* bad exit */ + BPF_ALU32_IMM(BPF_MOV, R0, 1), /* good exit */ + BPF_EXIT_INSN(), + }, + INTERNAL, + { }, + { { 0, 1 } }, + }, + { + "JMP_JSGE_K: Signed jump: value walk 2", + .u.insns_int = { + BPF_ALU32_IMM(BPF_MOV, R0, 0), + BPF_LD_IMM64(R1, -3), + BPF_JMP_IMM(BPF_JSGE, R1, 0, 4), + BPF_ALU64_IMM(BPF_ADD, R1, 2), + BPF_JMP_IMM(BPF_JSGE, R1, 0, 2), + BPF_ALU64_IMM(BPF_ADD, R1, 2), + BPF_JMP_IMM(BPF_JSGE, R1, 0, 1), + BPF_EXIT_INSN(), /* bad exit */ + BPF_ALU32_IMM(BPF_MOV, R0, 1), /* good exit */ + BPF_EXIT_INSN(), + }, + INTERNAL, + { }, + { { 0, 1 } }, + }, /* BPF_JMP | BPF_JGT | BPF_K */ { "JMP_JGT_K: if (3 > 2) return 1", -- cgit v1.2.3 From 797a93647a48d6cb8a20641a86a71713a947f786 Mon Sep 17 00:00:00 2001 From: Nithin Sujir Date: Wed, 24 May 2017 19:45:17 -0700 Subject: bonding: Don't update slave->link until ready to commit In the loadbalance arp monitoring scheme, when a slave link change is detected, the slave->link is immediately updated and slave_state_changed is set. Later down the function, the rtnl_lock is acquired and the changes are committed, updating the bond link state. However, the acquisition of the rtnl_lock can fail. The next time the monitor runs, since slave->link is already updated, it determines that link is unchanged. This results in the bond link state permanently out of sync with the slave link. This patch modifies bond_loadbalance_arp_mon() to handle link changes identical to bond_ab_arp_{inspect/commit}(). The new link state is maintained in slave->new_link until we're ready to commit at which point it's copied into slave->link. NOTE: miimon_{inspect/commit}() has a more complex state machine requiring the use of the bond_{propose,commit}_link_state() functions which maintains the intermediate state in slave->link_new_state. The arp monitors don't require that. Testing: This bug is very easy to reproduce with the following steps. 1. In a loop, toggle a slave link of a bond slave interface. 2. In a separate loop, do ifconfig up/down of an unrelated interface to create contention for rtnl_lock. Within a few iterations, the bond link goes out of sync with the slave link. Signed-off-by: Nithin Nayak Sujir Cc: Mahesh Bandewar Cc: Jay Vosburgh Acked-by: Mahesh Bandewar Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 73313318399c..2359478b977f 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -2612,11 +2612,13 @@ static void bond_loadbalance_arp_mon(struct bonding *bond) bond_for_each_slave_rcu(bond, slave, iter) { unsigned long trans_start = dev_trans_start(slave->dev); + slave->new_link = BOND_LINK_NOCHANGE; + if (slave->link != BOND_LINK_UP) { if (bond_time_in_interval(bond, trans_start, 1) && bond_time_in_interval(bond, slave->last_rx, 1)) { - slave->link = BOND_LINK_UP; + slave->new_link = BOND_LINK_UP; slave_state_changed = 1; /* primary_slave has no meaning in round-robin @@ -2643,7 +2645,7 @@ static void bond_loadbalance_arp_mon(struct bonding *bond) if (!bond_time_in_interval(bond, trans_start, 2) || !bond_time_in_interval(bond, slave->last_rx, 2)) { - slave->link = BOND_LINK_DOWN; + slave->new_link = BOND_LINK_DOWN; slave_state_changed = 1; if (slave->link_failure_count < UINT_MAX) @@ -2674,6 +2676,11 @@ static void bond_loadbalance_arp_mon(struct bonding *bond) if (!rtnl_trylock()) goto re_arm; + bond_for_each_slave(bond, slave, iter) { + if (slave->new_link != BOND_LINK_NOCHANGE) + slave->link = slave->new_link; + } + if (slave_state_changed) { bond_slave_state_change(bond); if (BOND_MODE(bond) == BOND_MODE_XOR) -- cgit v1.2.3 From 5711ea1b5421cbc3f0e35162e3d9611b1a57544c Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Thu, 25 May 2017 01:06:50 +0200 Subject: arm64: defconfig: enable some core options for 64bit Rockchip socs Enable some very core config options used on 64bit Rockchip socs. As built-in driver enable the Rockchip spi driver as well as the cros-ec-spi and cros-ec keyboard driver, as this may be helpful in case an initrd does not work as expected and drops the user into a shell. Another built-in is the fan53555 regulator driver, as it and its register-compatible cousins Silergy syr827 and syr828 are often used on Rockchip socs as cpu-supply next to regular pmic. The rest can be enabled as modules and contains the pcie host controller and its phy, the sucessive approximation adc (saradc) that gets often used for additional buttons on Rockchip boards as well as the adc-keys Keyboard driver for these keys. The cros-ec-pwm also can be a module, as it is normally only used to drive display backlights as well as the Rockchip thermal controller that allows to read the cpu and gpu temperatures and affect frequency scaling if necessary. Signed-off-by: Heiko Stuebner Signed-off-by: Olof Johansson --- arch/arm64/configs/defconfig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 65cdd878cfbd..97c123e09e45 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -68,6 +68,7 @@ CONFIG_PCIE_QCOM=y CONFIG_PCIE_ARMADA_8K=y CONFIG_PCI_AARDVARK=y CONFIG_PCIE_RCAR=y +CONFIG_PCIE_ROCKCHIP=m CONFIG_PCI_HOST_GENERIC=y CONFIG_PCI_XGENE=y CONFIG_ARM64_VA_BITS_48=y @@ -208,6 +209,8 @@ CONFIG_BRCMFMAC=m CONFIG_WL18XX=m CONFIG_WLCORE_SDIO=m CONFIG_INPUT_EVDEV=y +CONFIG_KEYBOARD_ADC=m +CONFIG_KEYBOARD_CROS_EC=y CONFIG_KEYBOARD_GPIO=y CONFIG_INPUT_MISC=y CONFIG_INPUT_PM8941_PWRKEY=y @@ -263,6 +266,7 @@ CONFIG_SPI_MESON_SPIFC=m CONFIG_SPI_ORION=y CONFIG_SPI_PL022=y CONFIG_SPI_QUP=y +CONFIG_SPI_ROCKCHIP=y CONFIG_SPI_S3C64XX=y CONFIG_SPI_SPIDEV=m CONFIG_SPMI=y @@ -292,6 +296,7 @@ CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y CONFIG_CPU_THERMAL=y CONFIG_THERMAL_EMULATION=y CONFIG_EXYNOS_THERMAL=y +CONFIG_ROCKCHIP_THERMAL=m CONFIG_WATCHDOG=y CONFIG_S3C2410_WATCHDOG=y CONFIG_MESON_GXBB_WATCHDOG=m @@ -300,12 +305,14 @@ CONFIG_RENESAS_WDT=y CONFIG_BCM2835_WDT=y CONFIG_MFD_CROS_EC=y CONFIG_MFD_CROS_EC_I2C=y +CONFIG_MFD_CROS_EC_SPI=y CONFIG_MFD_EXYNOS_LPASS=m CONFIG_MFD_HI655X_PMIC=y CONFIG_MFD_MAX77620=y CONFIG_MFD_SPMI_PMIC=y CONFIG_MFD_RK808=y CONFIG_MFD_SEC_CORE=y +CONFIG_REGULATOR_FAN53555=y CONFIG_REGULATOR_FIXED_VOLTAGE=y CONFIG_REGULATOR_GPIO=y CONFIG_REGULATOR_HI655X=y @@ -473,8 +480,10 @@ CONFIG_ARCH_TEGRA_186_SOC=y CONFIG_EXTCON_USB_GPIO=y CONFIG_IIO=y CONFIG_EXYNOS_ADC=y +CONFIG_ROCKCHIP_SARADC=m CONFIG_PWM=y CONFIG_PWM_BCM2835=m +CONFIG_PWM_CROS_EC=m CONFIG_PWM_MESON=m CONFIG_PWM_ROCKCHIP=y CONFIG_PWM_SAMSUNG=y @@ -484,6 +493,7 @@ CONFIG_PHY_HI6220_USB=y CONFIG_PHY_SUN4I_USB=y CONFIG_PHY_ROCKCHIP_INNO_USB2=y CONFIG_PHY_ROCKCHIP_EMMC=y +CONFIG_PHY_ROCKCHIP_PCIE=m CONFIG_PHY_XGENE=y CONFIG_PHY_TEGRA_XUSB=y CONFIG_ARM_SCPI_PROTOCOL=y -- cgit v1.2.3 From 791229f1d530a0f0a680a4c09f98199792485f33 Mon Sep 17 00:00:00 2001 From: Murali Karicheri Date: Wed, 29 Mar 2017 16:02:18 +0530 Subject: ARM: dts: keystone-k2l: fix broken Ethernet due to disabled OSR Ethernet networking on K2L has been broken since v4.11-rc1. This was caused by commit 32a34441a9bd ("ARM: keystone: dts: fix netcp clocks and add names"). This commit inadvertently moves on-chip static RAM clock to the end of list of clocks provided for netcp. Since keystone PM domain support does not have a list of recognized con_ids, only the first clock in the list comes under runtime PM management. This means the OSR (On-chip Static RAM) clock remains disabled and that broke networking on K2L. The OSR is used by QMSS on K2L as an external linking RAM. However this is a standalone RAM that can be used for non-QMSS usage (as well as from DSP side). So add a SRAM device node for the same and add the OSR clock to the node. Remove the now redundant OSR clock node from netcp. To manage all clocks defined for netCP's use by runtime PM needs keystone generic power domain (genpd) driver support which is under works. Meanwhile, this patch restores K2L networking and is correct irrespective of any future genpd work since OSR is an independent module and not part of NetCP anyway. Signed-off-by: Murali Karicheri Acked-by: Tero Kristo [nsekhar@ti.com: commit message updates, port to latest mainline] Signed-off-by: Sekhar Nori Cc: stable@vger.kernel.org # for 4.11 Acked-by: Santosh Shilimkar Signed-off-by: Arnd Bergmann --- arch/arm/boot/dts/keystone-k2l-netcp.dtsi | 4 ++-- arch/arm/boot/dts/keystone-k2l.dtsi | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/keystone-k2l-netcp.dtsi b/arch/arm/boot/dts/keystone-k2l-netcp.dtsi index b6f26824e83a..66f615a74118 100644 --- a/arch/arm/boot/dts/keystone-k2l-netcp.dtsi +++ b/arch/arm/boot/dts/keystone-k2l-netcp.dtsi @@ -137,8 +137,8 @@ netcp: netcp@26000000 { /* NetCP address range */ ranges = <0 0x26000000 0x1000000>; - clocks = <&clkpa>, <&clkcpgmac>, <&chipclk12>, <&clkosr>; - clock-names = "pa_clk", "ethss_clk", "cpts", "osr_clk"; + clocks = <&clkpa>, <&clkcpgmac>, <&chipclk12>; + clock-names = "pa_clk", "ethss_clk", "cpts"; dma-coherent; ti,navigator-dmas = <&dma_gbe 0>, diff --git a/arch/arm/boot/dts/keystone-k2l.dtsi b/arch/arm/boot/dts/keystone-k2l.dtsi index b58e7ebc0919..148650406cf7 100644 --- a/arch/arm/boot/dts/keystone-k2l.dtsi +++ b/arch/arm/boot/dts/keystone-k2l.dtsi @@ -232,6 +232,14 @@ }; }; + osr: sram@70000000 { + compatible = "mmio-sram"; + reg = <0x70000000 0x10000>; + #address-cells = <1>; + #size-cells = <1>; + clocks = <&clkosr>; + }; + dspgpio0: keystone_dsp_gpio@02620240 { compatible = "ti,keystone-dsp-gpio"; gpio-controller; -- cgit v1.2.3 From 9bd9590997b92fbd79fd028f704f6c584b4439d7 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 27 Apr 2017 19:02:22 +0300 Subject: drm/i915: Stop pretending to mask/unmask LPE audio interrupts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit vlv_display_irq_postinstall() enables the LPE audio interrupts regardless of whether the LPE audio irq chip has masked/unmasked them. Also the irqchip masking/unmasking doesn't consider the state of the display power well or the device, and hence just leads to dmesg spew when it tries to access the hardware while it's powered down. If the current way works, then we don't need to do anything in the mask/unmask hooks. If it doesn't work, well, then we'd need to properly track whether the irqchip has masked/unmasked the interrupts when we enable display interrupts. And the mask/unmask hooks would need to check whether display interrupts are even enabled before frobbing with he registers. So let's just assume the current way works and neuter the mask/unmask hooks. Also clean up vlv_display_irq_postinstall() a bit and stop it from trying to unmask/enable the LPE C interrupt on VLV since it doesn't exist. Cc: Takashi Iwai Cc: Pierre-Louis Bossart Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/20170427160231.13337-4-ville.syrjala@linux.intel.com Reviewed-by: Takashi Iwai (cherry picked from commit ebf5f921478b9b55ed4e634b994571dd23a8fca3) Reference: http://mid.mail-archive.com/874cf6d3-4e45-d4cf-e662-eb972490d2ce@redhat.com Tested-by: Hans de Goede Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_irq.c | 15 ++++++-------- drivers/gpu/drm/i915/intel_lpe_audio.c | 36 ---------------------------------- 2 files changed, 6 insertions(+), 45 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index fd97fe00cd0d..190f6aa5d15e 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2953,7 +2953,6 @@ static void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv) u32 pipestat_mask; u32 enable_mask; enum pipe pipe; - u32 val; pipestat_mask = PLANE_FLIP_DONE_INT_STATUS_VLV | PIPE_CRC_DONE_INTERRUPT_STATUS; @@ -2964,18 +2963,16 @@ static void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv) enable_mask = I915_DISPLAY_PORT_INTERRUPT | I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | - I915_DISPLAY_PIPE_B_EVENT_INTERRUPT; + I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | + I915_LPE_PIPE_A_INTERRUPT | + I915_LPE_PIPE_B_INTERRUPT; + if (IS_CHERRYVIEW(dev_priv)) - enable_mask |= I915_DISPLAY_PIPE_C_EVENT_INTERRUPT; + enable_mask |= I915_DISPLAY_PIPE_C_EVENT_INTERRUPT | + I915_LPE_PIPE_C_INTERRUPT; WARN_ON(dev_priv->irq_mask != ~0); - val = (I915_LPE_PIPE_A_INTERRUPT | - I915_LPE_PIPE_B_INTERRUPT | - I915_LPE_PIPE_C_INTERRUPT); - - enable_mask |= val; - dev_priv->irq_mask = ~enable_mask; GEN5_IRQ_INIT(VLV_, dev_priv->irq_mask, enable_mask); diff --git a/drivers/gpu/drm/i915/intel_lpe_audio.c b/drivers/gpu/drm/i915/intel_lpe_audio.c index 668f00480d97..292fedf30b00 100644 --- a/drivers/gpu/drm/i915/intel_lpe_audio.c +++ b/drivers/gpu/drm/i915/intel_lpe_audio.c @@ -149,44 +149,10 @@ static void lpe_audio_platdev_destroy(struct drm_i915_private *dev_priv) static void lpe_audio_irq_unmask(struct irq_data *d) { - struct drm_i915_private *dev_priv = d->chip_data; - unsigned long irqflags; - u32 val = (I915_LPE_PIPE_A_INTERRUPT | - I915_LPE_PIPE_B_INTERRUPT); - - if (IS_CHERRYVIEW(dev_priv)) - val |= I915_LPE_PIPE_C_INTERRUPT; - - spin_lock_irqsave(&dev_priv->irq_lock, irqflags); - - dev_priv->irq_mask &= ~val; - I915_WRITE(VLV_IIR, val); - I915_WRITE(VLV_IIR, val); - I915_WRITE(VLV_IMR, dev_priv->irq_mask); - POSTING_READ(VLV_IMR); - - spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); } static void lpe_audio_irq_mask(struct irq_data *d) { - struct drm_i915_private *dev_priv = d->chip_data; - unsigned long irqflags; - u32 val = (I915_LPE_PIPE_A_INTERRUPT | - I915_LPE_PIPE_B_INTERRUPT); - - if (IS_CHERRYVIEW(dev_priv)) - val |= I915_LPE_PIPE_C_INTERRUPT; - - spin_lock_irqsave(&dev_priv->irq_lock, irqflags); - - dev_priv->irq_mask |= val; - I915_WRITE(VLV_IMR, dev_priv->irq_mask); - I915_WRITE(VLV_IIR, val); - I915_WRITE(VLV_IIR, val); - POSTING_READ(VLV_IIR); - - spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); } static struct irq_chip lpe_audio_irqchip = { @@ -330,8 +296,6 @@ void intel_lpe_audio_teardown(struct drm_i915_private *dev_priv) desc = irq_to_desc(dev_priv->lpe_audio.irq); - lpe_audio_irq_mask(&desc->irq_data); - lpe_audio_platdev_destroy(dev_priv); irq_free_desc(dev_priv->lpe_audio.irq); -- cgit v1.2.3 From 702644ec1cab10ffefcebb4060d4da46d4ef2c7f Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Wed, 24 May 2017 20:04:41 +0200 Subject: x86/timers: Move simple_udelay_calibration past init_hypervisor_platform This ensures that adjustments to x86_platform done by the hypervisor setup is already respected by this simple calibration. The current user of this, introduced by 1b5aeebf3a92 ("x86/earlyprintk: Add support for earlyprintk via USB3 debug port"), comes much later into play. Fixes: dd759d93f4dd ("x86/timers: Add simple udelay calibration") Signed-off-by: Jan Kiszka Signed-off-by: Thomas Gleixner Acked-by: Lu Baolu Link: http://lkml.kernel.org/r/5e89fe60-aab3-2c1c-aba8-32f8ad376189@siemens.com --- arch/x86/kernel/setup.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 0b4d3c686b1e..f81823695014 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -980,8 +980,6 @@ void __init setup_arch(char **cmdline_p) */ x86_configure_nx(); - simple_udelay_calibration(); - parse_early_param(); #ifdef CONFIG_MEMORY_HOTPLUG @@ -1041,6 +1039,8 @@ void __init setup_arch(char **cmdline_p) */ init_hypervisor_platform(); + simple_udelay_calibration(); + x86_init.resources.probe_roms(); /* after parse_early_param, so could debug it */ -- cgit v1.2.3 From e8a3ce1130134046e9da132aa4d043566df8237d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 26 May 2017 01:44:19 +0000 Subject: ASoC: rsnd: fixup parent_clk_name of AUDIO_CLKOUTx commit 25165f79adc7 ("ASoC: rsnd: enable clock-frequency for both 44.1kHz/48kHz") supported both 44.1kHz/48kHz for AUDIO_CLKOUTx, but it didn't care its parent clock name. This patch fixes it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/adg.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index 66203d107a11..d3b0dc145a56 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -507,7 +507,8 @@ static void rsnd_adg_get_clkout(struct rsnd_priv *priv, rbga = rbgx; adg->rbga_rate_for_441khz = rate / div; ckr |= brg_table[i] << 20; - if (req_441kHz_rate) + if (req_441kHz_rate && + !(adg_mode_flags(adg) & AUDIO_OUT_48)) parent_clk_name = __clk_get_name(clk); } } @@ -522,7 +523,8 @@ static void rsnd_adg_get_clkout(struct rsnd_priv *priv, rbgb = rbgx; adg->rbgb_rate_for_48khz = rate / div; ckr |= brg_table[i] << 16; - if (req_48kHz_rate) + if (req_48kHz_rate && + (adg_mode_flags(adg) & AUDIO_OUT_48)) parent_clk_name = __clk_get_name(clk); } } -- cgit v1.2.3 From 5acc1ca4fb15f00bfa3d4046e35ca381bc25d580 Mon Sep 17 00:00:00 2001 From: Wanpeng Li Date: Sat, 20 May 2017 20:32:32 -0700 Subject: KVM: X86: Fix preempt the preemption timer cancel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Preemption can occur during cancel preemption timer, and there will be inconsistent status in lapic, vmx and vmcs field. CPU0 CPU1 preemption timer vmexit handle_preemption_timer(vCPU0) kvm_lapic_expired_hv_timer vmx_cancel_hv_timer vmx->hv_deadline_tsc = -1 vmcs_clear_bits /* hv_timer_in_use still true */ sched_out sched_in kvm_arch_vcpu_load vmx_set_hv_timer write vmx->hv_deadline_tsc vmcs_set_bits /* back in kvm_lapic_expired_hv_timer */ hv_timer_in_use = false ... vmx_vcpu_run vmx_arm_hv_run write preemption timer deadline spurious preemption timer vmexit handle_preemption_timer(vCPU0) kvm_lapic_expired_hv_timer WARN_ON(!apic->lapic_timer.hv_timer_in_use); This can be reproduced sporadically during boot of L2 on a preemptible L1, causing a splat on L1. WARNING: CPU: 3 PID: 1952 at arch/x86/kvm/lapic.c:1529 kvm_lapic_expired_hv_timer+0xb5/0xd0 [kvm] CPU: 3 PID: 1952 Comm: qemu-system-x86 Not tainted 4.12.0-rc1+ #24 RIP: 0010:kvm_lapic_expired_hv_timer+0xb5/0xd0 [kvm] Call Trace: handle_preemption_timer+0xe/0x20 [kvm_intel] vmx_handle_exit+0xc9/0x15f0 [kvm_intel] ? lock_acquire+0xdb/0x250 ? lock_acquire+0xdb/0x250 ? kvm_arch_vcpu_ioctl_run+0xdf3/0x1ce0 [kvm] kvm_arch_vcpu_ioctl_run+0xe55/0x1ce0 [kvm] kvm_vcpu_ioctl+0x384/0x7b0 [kvm] ? kvm_vcpu_ioctl+0x384/0x7b0 [kvm] ? __fget+0xf3/0x210 do_vfs_ioctl+0xa4/0x700 ? __fget+0x114/0x210 SyS_ioctl+0x79/0x90 do_syscall_64+0x8f/0x750 ? trace_hardirqs_on_thunk+0x1a/0x1c entry_SYSCALL64_slow_path+0x25/0x25 This patch fixes it by disabling preemption while cancelling preemption timer. This way cancel_hv_timer is atomic with respect to kvm_arch_vcpu_load. Cc: Paolo Bonzini Cc: Radim Krčmář Signed-off-by: Wanpeng Li Signed-off-by: Paolo Bonzini --- arch/x86/kvm/lapic.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index c329d2894905..6e6f345adfe6 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -1495,8 +1495,10 @@ EXPORT_SYMBOL_GPL(kvm_lapic_hv_timer_in_use); static void cancel_hv_timer(struct kvm_lapic *apic) { + preempt_disable(); kvm_x86_ops->cancel_hv_timer(apic->vcpu); apic->lapic_timer.hv_timer_in_use = false; + preempt_enable(); } static bool start_hv_timer(struct kvm_lapic *apic) -- cgit v1.2.3 From e1d39b17e044e8ae819827810d87d809ba5f58c0 Mon Sep 17 00:00:00 2001 From: "Jan H. Schönherr" Date: Sat, 20 May 2017 13:22:56 +0200 Subject: KVM: nVMX: Fix handling of lmsw instruction MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The decision whether or not to exit from L2 to L1 on an lmsw instruction is based on bogus values: instead of using the information encoded within the exit qualification, it uses the data also used for the mov-to-cr instruction, which boils down to using whatever is in %eax at that point. Use the correct values instead. Without this fix, an L1 may not get notified when a 32-bit Linux L2 switches its secondary CPUs to protected mode; the L1 is only notified on the next modification of CR0. This short time window poses a problem, when there is some other reason to exit to L1 in between. Then, L2 will be resumed in real mode and chaos ensues. Signed-off-by: Jan H. Schönherr Reviewed-by: Wanpeng Li Signed-off-by: Paolo Bonzini --- arch/x86/kvm/vmx.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 72f78396bc09..880f371705bc 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -7913,11 +7913,13 @@ static bool nested_vmx_exit_handled_cr(struct kvm_vcpu *vcpu, { unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION); int cr = exit_qualification & 15; - int reg = (exit_qualification >> 8) & 15; - unsigned long val = kvm_register_readl(vcpu, reg); + int reg; + unsigned long val; switch ((exit_qualification >> 4) & 3) { case 0: /* mov to cr */ + reg = (exit_qualification >> 8) & 15; + val = kvm_register_readl(vcpu, reg); switch (cr) { case 0: if (vmcs12->cr0_guest_host_mask & @@ -7972,6 +7974,7 @@ static bool nested_vmx_exit_handled_cr(struct kvm_vcpu *vcpu, * lmsw can change bits 1..3 of cr0, and only set bit 0 of * cr0. Other attempted changes are ignored, with no exit. */ + val = (exit_qualification >> LMSW_SOURCE_DATA_SHIFT) & 0x0f; if (vmcs12->cr0_guest_host_mask & 0xe & (val ^ vmcs12->cr0_read_shadow)) return true; -- cgit v1.2.3 From 52b5419016997f2960e9c8b6584c4acb3875d126 Mon Sep 17 00:00:00 2001 From: "Jan H. Schönherr" Date: Sat, 20 May 2017 13:24:32 +0200 Subject: KVM: x86: Fix virtual wire mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Intel SDM says, that at most one LAPIC should be configured with ExtINT delivery. KVM configures all LAPICs this way. This causes pic_unlock() to kick the first available vCPU from the internal KVM data structures. If this vCPU is not the BSP, but some not-yet-booted AP, the BSP may never realize that there is an interrupt. Fix that by enabling ExtINT delivery only for the BSP. This allows booting a Linux guest without a TSC in the above situation. Otherwise the BSP gets stuck in calibrate_delay_converge(). Signed-off-by: Jan H. Schönherr Reviewed-by: Wanpeng Li Signed-off-by: Paolo Bonzini --- arch/x86/kvm/lapic.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 6e6f345adfe6..d24c8742d9b0 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -1936,7 +1936,8 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu, bool init_event) for (i = 0; i < KVM_APIC_LVT_NUM; i++) kvm_lapic_set_reg(apic, APIC_LVTT + 0x10 * i, APIC_LVT_MASKED); apic_update_lvtt(apic); - if (kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_LINT0_REENABLED)) + if (kvm_vcpu_is_reset_bsp(vcpu) && + kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_LINT0_REENABLED)) kvm_lapic_set_reg(apic, APIC_LVT0, SET_APIC_DELIVERY_MODE(0, APIC_MODE_EXTINT)); apic_manage_nmi_watchdog(apic, kvm_lapic_get_reg(apic, APIC_LVT0)); -- cgit v1.2.3 From 0908cf4dfef35fc6ac12329007052ebe93ff1081 Mon Sep 17 00:00:00 2001 From: linzhang Date: Thu, 25 May 2017 14:07:18 +0800 Subject: net: llc: add lock_sock in llc_ui_bind to avoid a race condition There is a race condition in llc_ui_bind if two or more processes/threads try to bind a same socket. If more processes/threads bind a same socket success that will lead to two problems, one is this action is not what we expected, another is will lead to kernel in unstable status or oops(in my simple test case, cause llc2.ko can't unload). The current code is test SOCK_ZAPPED bit to avoid a process to bind a same socket twice but that is can't avoid more processes/threads try to bind a same socket at the same time. So, add lock_sock in llc_ui_bind like others, such as llc_ui_connect. Signed-off-by: Lin Zhang Signed-off-by: David S. Miller --- net/llc/af_llc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index 8364fe5b59e4..c38d16f22d2a 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -311,6 +311,8 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen) int rc = -EINVAL; dprintk("%s: binding %02X\n", __func__, addr->sllc_sap); + + lock_sock(sk); if (unlikely(!sock_flag(sk, SOCK_ZAPPED) || addrlen != sizeof(*addr))) goto out; rc = -EAFNOSUPPORT; @@ -382,6 +384,7 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen) out_put: llc_sap_put(sap); out: + release_sock(sk); return rc; } -- cgit v1.2.3 From 804ec7ebe8ea003999ca8d1bfc499edc6a9e07df Mon Sep 17 00:00:00 2001 From: Davide Caratti Date: Thu, 25 May 2017 19:14:56 +0200 Subject: sctp: fix ICMP processing if skb is non-linear sometimes ICMP replies to INIT chunks are ignored by the client, even if the encapsulated SCTP headers match an open socket. This happens when the ICMP packet is carried by a paged skb: use skb_header_pointer() to read packet contents beyond the SCTP header, so that chunk header and initiate tag are validated correctly. v2: - don't use skb_header_pointer() to read the transport header, since icmp_socket_deliver() already puts these 8 bytes in the linear area. - change commit message to make specific reference to INIT chunks. Signed-off-by: Davide Caratti Acked-by: Marcelo Ricardo Leitner Acked-by: Vlad Yasevich Reviewed-by: Xin Long Signed-off-by: David S. Miller --- net/sctp/input.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/net/sctp/input.c b/net/sctp/input.c index 0e06a278d2a9..ba9ad32fc447 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -473,15 +473,14 @@ struct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *skb, struct sctp_association **app, struct sctp_transport **tpp) { + struct sctp_init_chunk *chunkhdr, _chunkhdr; union sctp_addr saddr; union sctp_addr daddr; struct sctp_af *af; struct sock *sk = NULL; struct sctp_association *asoc; struct sctp_transport *transport = NULL; - struct sctp_init_chunk *chunkhdr; __u32 vtag = ntohl(sctphdr->vtag); - int len = skb->len - ((void *)sctphdr - (void *)skb->data); *app = NULL; *tpp = NULL; @@ -516,13 +515,16 @@ struct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *skb, * discard the packet. */ if (vtag == 0) { - chunkhdr = (void *)sctphdr + sizeof(struct sctphdr); - if (len < sizeof(struct sctphdr) + sizeof(sctp_chunkhdr_t) - + sizeof(__be32) || + /* chunk header + first 4 octects of init header */ + chunkhdr = skb_header_pointer(skb, skb_transport_offset(skb) + + sizeof(struct sctphdr), + sizeof(struct sctp_chunkhdr) + + sizeof(__be32), &_chunkhdr); + if (!chunkhdr || chunkhdr->chunk_hdr.type != SCTP_CID_INIT || - ntohl(chunkhdr->init_hdr.init_tag) != asoc->c.my_vtag) { + ntohl(chunkhdr->init_hdr.init_tag) != asoc->c.my_vtag) goto out; - } + } else if (vtag != asoc->c.peer_vtag) { goto out; } -- cgit v1.2.3 From 7485af89a6fd48f7e6fab2505d2364d1817723e6 Mon Sep 17 00:00:00 2001 From: Jane Chu Date: Thu, 25 May 2017 13:51:20 -0600 Subject: arch/sparc: increase CONFIG_NODES_SHIFT on SPARC64 to 5 SPARC M6-32 platform has (2^5) NUMA nodes, so need to bump up the CONFIG_NODES_SHIFT to 5. Orabug: 25577754 Signed-off-by: Jane Chu Reviewed-by: Bob Picco Reviewed-by: Atish Patra Signed-off-by: David S. Miller --- arch/sparc/Kconfig | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 58243b0d21c0..e544ac12737e 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -295,9 +295,13 @@ config NUMA depends on SPARC64 && SMP config NODES_SHIFT - int - default "4" + int "Maximum NUMA Nodes (as a power of 2)" + range 4 5 if SPARC64 + default "5" depends on NEED_MULTIPLE_NODES + help + Specify the maximum number of NUMA Nodes available on the target + system. Increases memory reserved to accommodate various tables. # Some NUMA nodes have memory ranges that span # other nodes. Even though a pfn is valid and -- cgit v1.2.3 From 0e9a709560dbcfbace8bf4019dc5298619235891 Mon Sep 17 00:00:00 2001 From: Peter Dawson Date: Fri, 26 May 2017 06:35:18 +1000 Subject: ip6_tunnel, ip6_gre: fix setting of DSCP on encapsulated packets This fix addresses two problems in the way the DSCP field is formulated on the encapsulating header of IPv6 tunnels. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=195661 1) The IPv6 tunneling code was manipulating the DSCP field of the encapsulating packet using the 32b flowlabel. Since the flowlabel is only the lower 20b it was incorrect to assume that the upper 12b containing the DSCP and ECN fields would remain intact when formulating the encapsulating header. This fix handles the 'inherit' and 'fixed-value' DSCP cases explicitly using the extant dsfield u8 variable. 2) The use of INET_ECN_encapsulate(0, dsfield) in ip6_tnl_xmit was incorrect and resulted in the DSCP value always being set to 0. Commit 90427ef5d2a4 ("ipv6: fix flow labels when the traffic class is non-0") caused the regression by masking out the flowlabel which exposed the incorrect handling of the DSCP portion of the flowlabel in ip6_tunnel and ip6_gre. Fixes: 90427ef5d2a4 ("ipv6: fix flow labels when the traffic class is non-0") Signed-off-by: Peter Dawson Signed-off-by: David S. Miller --- net/ipv6/ip6_gre.c | 13 +++++++------ net/ipv6/ip6_tunnel.c | 21 +++++++++++++-------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index 8d128ba79b66..0c5b4caa1949 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c @@ -537,11 +537,10 @@ static inline int ip6gre_xmit_ipv4(struct sk_buff *skb, struct net_device *dev) memcpy(&fl6, &t->fl.u.ip6, sizeof(fl6)); - dsfield = ipv4_get_dsfield(iph); - if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS) - fl6.flowlabel |= htonl((__u32)iph->tos << IPV6_TCLASS_SHIFT) - & IPV6_TCLASS_MASK; + dsfield = ipv4_get_dsfield(iph); + else + dsfield = ip6_tclass(t->parms.flowinfo); if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK) fl6.flowi6_mark = skb->mark; else @@ -598,9 +597,11 @@ static inline int ip6gre_xmit_ipv6(struct sk_buff *skb, struct net_device *dev) memcpy(&fl6, &t->fl.u.ip6, sizeof(fl6)); - dsfield = ipv6_get_dsfield(ipv6h); if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS) - fl6.flowlabel |= (*(__be32 *) ipv6h & IPV6_TCLASS_MASK); + dsfield = ipv6_get_dsfield(ipv6h); + else + dsfield = ip6_tclass(t->parms.flowinfo); + if (t->parms.flags & IP6_TNL_F_USE_ORIG_FLOWLABEL) fl6.flowlabel |= ip6_flowlabel(ipv6h); if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK) diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 6eb2ae507500..7ae6c503f1ca 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -1196,7 +1196,7 @@ route_lookup: skb_push(skb, sizeof(struct ipv6hdr)); skb_reset_network_header(skb); ipv6h = ipv6_hdr(skb); - ip6_flow_hdr(ipv6h, INET_ECN_encapsulate(0, dsfield), + ip6_flow_hdr(ipv6h, dsfield, ip6_make_flowlabel(net, skb, fl6->flowlabel, true, fl6)); ipv6h->hop_limit = hop_limit; ipv6h->nexthdr = proto; @@ -1231,8 +1231,6 @@ ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) if (tproto != IPPROTO_IPIP && tproto != 0) return -1; - dsfield = ipv4_get_dsfield(iph); - if (t->parms.collect_md) { struct ip_tunnel_info *tun_info; const struct ip_tunnel_key *key; @@ -1246,6 +1244,7 @@ ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) fl6.flowi6_proto = IPPROTO_IPIP; fl6.daddr = key->u.ipv6.dst; fl6.flowlabel = key->label; + dsfield = ip6_tclass(key->label); } else { if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) encap_limit = t->parms.encap_limit; @@ -1254,8 +1253,9 @@ ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) fl6.flowi6_proto = IPPROTO_IPIP; if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS) - fl6.flowlabel |= htonl((__u32)iph->tos << IPV6_TCLASS_SHIFT) - & IPV6_TCLASS_MASK; + dsfield = ipv4_get_dsfield(iph); + else + dsfield = ip6_tclass(t->parms.flowinfo); if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK) fl6.flowi6_mark = skb->mark; else @@ -1267,6 +1267,8 @@ ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6)) return -1; + dsfield = INET_ECN_encapsulate(dsfield, ipv4_get_dsfield(iph)); + skb_set_inner_ipproto(skb, IPPROTO_IPIP); err = ip6_tnl_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu, @@ -1300,8 +1302,6 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) ip6_tnl_addr_conflict(t, ipv6h)) return -1; - dsfield = ipv6_get_dsfield(ipv6h); - if (t->parms.collect_md) { struct ip_tunnel_info *tun_info; const struct ip_tunnel_key *key; @@ -1315,6 +1315,7 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) fl6.flowi6_proto = IPPROTO_IPV6; fl6.daddr = key->u.ipv6.dst; fl6.flowlabel = key->label; + dsfield = ip6_tclass(key->label); } else { offset = ip6_tnl_parse_tlv_enc_lim(skb, skb_network_header(skb)); /* ip6_tnl_parse_tlv_enc_lim() might have reallocated skb->head */ @@ -1337,7 +1338,9 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) fl6.flowi6_proto = IPPROTO_IPV6; if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS) - fl6.flowlabel |= (*(__be32 *)ipv6h & IPV6_TCLASS_MASK); + dsfield = ipv6_get_dsfield(ipv6h); + else + dsfield = ip6_tclass(t->parms.flowinfo); if (t->parms.flags & IP6_TNL_F_USE_ORIG_FLOWLABEL) fl6.flowlabel |= ip6_flowlabel(ipv6h); if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK) @@ -1351,6 +1354,8 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6)) return -1; + dsfield = INET_ECN_encapsulate(dsfield, ipv6_get_dsfield(ipv6h)); + skb_set_inner_ipproto(skb, IPPROTO_IPV6); err = ip6_tnl_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu, -- cgit v1.2.3 From 82533ad9a1ce3a7a6863849a552c2cc041b55e0d Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Thu, 25 May 2017 22:54:53 +0200 Subject: net: ethernet: ax88796: don't call free_irq without request_irq first MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The function ax_init_dev (which is called only from the driver's .probe function) calls free_irq in the error path without having requested the irq in the first place. So drop the free_irq call in the error path. Fixes: 825a2ff1896e ("AX88796 network driver") Signed-off-by: Uwe Kleine-König Signed-off-by: David S. Miller --- drivers/net/ethernet/8390/ax88796.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/8390/ax88796.c b/drivers/net/ethernet/8390/ax88796.c index b0a3b85fc6f8..db02bc2fb4b2 100644 --- a/drivers/net/ethernet/8390/ax88796.c +++ b/drivers/net/ethernet/8390/ax88796.c @@ -748,13 +748,13 @@ static int ax_init_dev(struct net_device *dev) ret = ax_mii_init(dev); if (ret) - goto out_irq; + goto err_out; ax_NS8390_init(dev, 0); ret = register_netdev(dev); if (ret) - goto out_irq; + goto err_out; netdev_info(dev, "%dbit, irq %d, %lx, MAC: %pM\n", ei_local->word16 ? 16 : 8, dev->irq, dev->base_addr, @@ -762,9 +762,6 @@ static int ax_init_dev(struct net_device *dev) return 0; - out_irq: - /* cleanup irq */ - free_irq(dev->irq, dev); err_out: return ret; } -- cgit v1.2.3 From 3fb07daff8e99243366a081e5129560734de4ada Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 25 May 2017 14:27:35 -0700 Subject: ipv4: add reference counting to metrics Andrey Konovalov reported crashes in ipv4_mtu() I could reproduce the issue with KASAN kernels, between 10.246.7.151 and 10.246.7.152 : 1) 20 concurrent netperf -t TCP_RR -H 10.246.7.152 -l 1000 & 2) At the same time run following loop : while : do ip ro add 10.246.7.152 dev eth0 src 10.246.7.151 mtu 1500 ip ro del 10.246.7.152 dev eth0 src 10.246.7.151 mtu 1500 done Cong Wang attempted to add back rt->fi in commit 82486aa6f1b9 ("ipv4: restore rt->fi for reference counting") but this proved to add some issues that were complex to solve. Instead, I suggested to add a refcount to the metrics themselves, being a standalone object (in particular, no reference to other objects) I tried to make this patch as small as possible to ease its backport, instead of being super clean. Note that we believe that only ipv4 dst need to take care of the metric refcount. But if this is wrong, this patch adds the basic infrastructure to extend this to other families. Many thanks to Julian Anastasov for reviewing this patch, and Cong Wang for his efforts on this problem. Fixes: 2860583fe840 ("ipv4: Kill rt->fi") Signed-off-by: Eric Dumazet Reported-by: Andrey Konovalov Reviewed-by: Julian Anastasov Acked-by: Cong Wang Signed-off-by: David S. Miller --- include/net/dst.h | 8 +++++++- include/net/ip_fib.h | 10 +++++----- net/core/dst.c | 23 ++++++++++++++--------- net/ipv4/fib_semantics.c | 17 ++++++++++------- net/ipv4/route.c | 10 +++++++++- 5 files changed, 45 insertions(+), 23 deletions(-) diff --git a/include/net/dst.h b/include/net/dst.h index 049af33da3b6..cfc043784166 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -107,10 +107,16 @@ struct dst_entry { }; }; +struct dst_metrics { + u32 metrics[RTAX_MAX]; + atomic_t refcnt; +}; +extern const struct dst_metrics dst_default_metrics; + u32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old); -extern const u32 dst_default_metrics[]; #define DST_METRICS_READ_ONLY 0x1UL +#define DST_METRICS_REFCOUNTED 0x2UL #define DST_METRICS_FLAGS 0x3UL #define __DST_METRICS_PTR(Y) \ ((u32 *)((Y) & ~DST_METRICS_FLAGS)) diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h index 6692c5758b33..f7f6aa789c61 100644 --- a/include/net/ip_fib.h +++ b/include/net/ip_fib.h @@ -114,11 +114,11 @@ struct fib_info { __be32 fib_prefsrc; u32 fib_tb_id; u32 fib_priority; - u32 *fib_metrics; -#define fib_mtu fib_metrics[RTAX_MTU-1] -#define fib_window fib_metrics[RTAX_WINDOW-1] -#define fib_rtt fib_metrics[RTAX_RTT-1] -#define fib_advmss fib_metrics[RTAX_ADVMSS-1] + struct dst_metrics *fib_metrics; +#define fib_mtu fib_metrics->metrics[RTAX_MTU-1] +#define fib_window fib_metrics->metrics[RTAX_WINDOW-1] +#define fib_rtt fib_metrics->metrics[RTAX_RTT-1] +#define fib_advmss fib_metrics->metrics[RTAX_ADVMSS-1] int fib_nhs; #ifdef CONFIG_IP_ROUTE_MULTIPATH int fib_weight; diff --git a/net/core/dst.c b/net/core/dst.c index 960e503b5a52..6192f11beec9 100644 --- a/net/core/dst.c +++ b/net/core/dst.c @@ -151,13 +151,13 @@ int dst_discard_out(struct net *net, struct sock *sk, struct sk_buff *skb) } EXPORT_SYMBOL(dst_discard_out); -const u32 dst_default_metrics[RTAX_MAX + 1] = { +const struct dst_metrics dst_default_metrics = { /* This initializer is needed to force linker to place this variable * into const section. Otherwise it might end into bss section. * We really want to avoid false sharing on this variable, and catch * any writes on it. */ - [RTAX_MAX] = 0xdeadbeef, + .refcnt = ATOMIC_INIT(1), }; void dst_init(struct dst_entry *dst, struct dst_ops *ops, @@ -169,7 +169,7 @@ void dst_init(struct dst_entry *dst, struct dst_ops *ops, if (dev) dev_hold(dev); dst->ops = ops; - dst_init_metrics(dst, dst_default_metrics, true); + dst_init_metrics(dst, dst_default_metrics.metrics, true); dst->expires = 0UL; dst->path = dst; dst->from = NULL; @@ -314,25 +314,30 @@ EXPORT_SYMBOL(dst_release); u32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old) { - u32 *p = kmalloc(sizeof(u32) * RTAX_MAX, GFP_ATOMIC); + struct dst_metrics *p = kmalloc(sizeof(*p), GFP_ATOMIC); if (p) { - u32 *old_p = __DST_METRICS_PTR(old); + struct dst_metrics *old_p = (struct dst_metrics *)__DST_METRICS_PTR(old); unsigned long prev, new; - memcpy(p, old_p, sizeof(u32) * RTAX_MAX); + atomic_set(&p->refcnt, 1); + memcpy(p->metrics, old_p->metrics, sizeof(p->metrics)); new = (unsigned long) p; prev = cmpxchg(&dst->_metrics, old, new); if (prev != old) { kfree(p); - p = __DST_METRICS_PTR(prev); + p = (struct dst_metrics *)__DST_METRICS_PTR(prev); if (prev & DST_METRICS_READ_ONLY) p = NULL; + } else if (prev & DST_METRICS_REFCOUNTED) { + if (atomic_dec_and_test(&old_p->refcnt)) + kfree(old_p); } } - return p; + BUILD_BUG_ON(offsetof(struct dst_metrics, metrics) != 0); + return (u32 *)p; } EXPORT_SYMBOL(dst_cow_metrics_generic); @@ -341,7 +346,7 @@ void __dst_destroy_metrics_generic(struct dst_entry *dst, unsigned long old) { unsigned long prev, new; - new = ((unsigned long) dst_default_metrics) | DST_METRICS_READ_ONLY; + new = ((unsigned long) &dst_default_metrics) | DST_METRICS_READ_ONLY; prev = cmpxchg(&dst->_metrics, old, new); if (prev == old) kfree(__DST_METRICS_PTR(old)); diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index da449ddb8cc1..ad9ad4aab5da 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c @@ -203,6 +203,7 @@ static void rt_fibinfo_free_cpus(struct rtable __rcu * __percpu *rtp) static void free_fib_info_rcu(struct rcu_head *head) { struct fib_info *fi = container_of(head, struct fib_info, rcu); + struct dst_metrics *m; change_nexthops(fi) { if (nexthop_nh->nh_dev) @@ -213,8 +214,9 @@ static void free_fib_info_rcu(struct rcu_head *head) rt_fibinfo_free(&nexthop_nh->nh_rth_input); } endfor_nexthops(fi); - if (fi->fib_metrics != (u32 *) dst_default_metrics) - kfree(fi->fib_metrics); + m = fi->fib_metrics; + if (m != &dst_default_metrics && atomic_dec_and_test(&m->refcnt)) + kfree(m); kfree(fi); } @@ -971,11 +973,11 @@ fib_convert_metrics(struct fib_info *fi, const struct fib_config *cfg) val = 255; if (type == RTAX_FEATURES && (val & ~RTAX_FEATURE_MASK)) return -EINVAL; - fi->fib_metrics[type - 1] = val; + fi->fib_metrics->metrics[type - 1] = val; } if (ecn_ca) - fi->fib_metrics[RTAX_FEATURES - 1] |= DST_FEATURE_ECN_CA; + fi->fib_metrics->metrics[RTAX_FEATURES - 1] |= DST_FEATURE_ECN_CA; return 0; } @@ -1033,11 +1035,12 @@ struct fib_info *fib_create_info(struct fib_config *cfg) goto failure; fib_info_cnt++; if (cfg->fc_mx) { - fi->fib_metrics = kzalloc(sizeof(u32) * RTAX_MAX, GFP_KERNEL); + fi->fib_metrics = kzalloc(sizeof(*fi->fib_metrics), GFP_KERNEL); if (!fi->fib_metrics) goto failure; + atomic_set(&fi->fib_metrics->refcnt, 1); } else - fi->fib_metrics = (u32 *) dst_default_metrics; + fi->fib_metrics = (struct dst_metrics *)&dst_default_metrics; fi->fib_net = net; fi->fib_protocol = cfg->fc_protocol; @@ -1238,7 +1241,7 @@ int fib_dump_info(struct sk_buff *skb, u32 portid, u32 seq, int event, if (fi->fib_priority && nla_put_u32(skb, RTA_PRIORITY, fi->fib_priority)) goto nla_put_failure; - if (rtnetlink_put_metrics(skb, fi->fib_metrics) < 0) + if (rtnetlink_put_metrics(skb, fi->fib_metrics->metrics) < 0) goto nla_put_failure; if (fi->fib_prefsrc && diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 655d9eebe43e..6883b3d4ba8f 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1385,8 +1385,12 @@ static void rt_add_uncached_list(struct rtable *rt) static void ipv4_dst_destroy(struct dst_entry *dst) { + struct dst_metrics *p = (struct dst_metrics *)DST_METRICS_PTR(dst); struct rtable *rt = (struct rtable *) dst; + if (p != &dst_default_metrics && atomic_dec_and_test(&p->refcnt)) + kfree(p); + if (!list_empty(&rt->rt_uncached)) { struct uncached_list *ul = rt->rt_uncached_list; @@ -1438,7 +1442,11 @@ static void rt_set_nexthop(struct rtable *rt, __be32 daddr, rt->rt_gateway = nh->nh_gw; rt->rt_uses_gateway = 1; } - dst_init_metrics(&rt->dst, fi->fib_metrics, true); + dst_init_metrics(&rt->dst, fi->fib_metrics->metrics, true); + if (fi->fib_metrics != &dst_default_metrics) { + rt->dst._metrics |= DST_METRICS_REFCOUNTED; + atomic_inc(&fi->fib_metrics->refcnt); + } #ifdef CONFIG_IP_ROUTE_CLASSID rt->dst.tclassid = nh->nh_tclassid; #endif -- cgit v1.2.3 From 4f8caa60a5a13a78f26198618f21774bd6aa6498 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Fri, 26 May 2017 17:40:52 -0400 Subject: ext4: fix data corruption with EXT4_GET_BLOCKS_ZERO When ext4_map_blocks() is called with EXT4_GET_BLOCKS_ZERO to zero-out allocated blocks and these blocks are actually converted from unwritten extent the following race can happen: CPU0 CPU1 page fault page fault ... ... ext4_map_blocks() ext4_ext_map_blocks() ext4_ext_handle_unwritten_extents() ext4_ext_convert_to_initialized() - zero out converted extent ext4_zeroout_es() - inserts extent as initialized in status tree ext4_map_blocks() ext4_es_lookup_extent() - finds initialized extent write data ext4_issue_zeroout() - zeroes out new extent overwriting data This problem can be reproduced by generic/340 for the fallocated case for the last block in the file. Fix the problem by avoiding zeroing out the area we are mapping with ext4_map_blocks() in ext4_ext_convert_to_initialized(). It is pointless to zero out this area in the first place as the caller asked us to convert the area to initialized because he is just going to write data there before the transaction finishes. To achieve this we delete the special case of zeroing out full extent as that will be handled by the cases below zeroing only the part of the extent that needs it. We also instruct ext4_split_extent() that the middle of extent being split contains data so that ext4_split_extent_at() cannot zero out full extent in case of ENOSPC. CC: stable@vger.kernel.org Fixes: 12735f881952c32b31bc4e433768f18489f79ec9 Signed-off-by: Jan Kara Signed-off-by: Theodore Ts'o --- fs/ext4/extents.c | 80 +++++++++++++++++++++++++------------------------------ 1 file changed, 37 insertions(+), 43 deletions(-) diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 2a97dff87b96..83a513efc824 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -3413,13 +3413,13 @@ static int ext4_ext_convert_to_initialized(handle_t *handle, struct ext4_sb_info *sbi; struct ext4_extent_header *eh; struct ext4_map_blocks split_map; - struct ext4_extent zero_ex; + struct ext4_extent zero_ex1, zero_ex2; struct ext4_extent *ex, *abut_ex; ext4_lblk_t ee_block, eof_block; unsigned int ee_len, depth, map_len = map->m_len; int allocated = 0, max_zeroout = 0; int err = 0; - int split_flag = 0; + int split_flag = EXT4_EXT_DATA_VALID2; ext_debug("ext4_ext_convert_to_initialized: inode %lu, logical" "block %llu, max_blocks %u\n", inode->i_ino, @@ -3436,7 +3436,8 @@ static int ext4_ext_convert_to_initialized(handle_t *handle, ex = path[depth].p_ext; ee_block = le32_to_cpu(ex->ee_block); ee_len = ext4_ext_get_actual_len(ex); - zero_ex.ee_len = 0; + zero_ex1.ee_len = 0; + zero_ex2.ee_len = 0; trace_ext4_ext_convert_to_initialized_enter(inode, map, ex); @@ -3576,62 +3577,52 @@ static int ext4_ext_convert_to_initialized(handle_t *handle, if (ext4_encrypted_inode(inode)) max_zeroout = 0; - /* If extent is less than s_max_zeroout_kb, zeroout directly */ - if (max_zeroout && (ee_len <= max_zeroout)) { - err = ext4_ext_zeroout(inode, ex); - if (err) - goto out; - zero_ex.ee_block = ex->ee_block; - zero_ex.ee_len = cpu_to_le16(ext4_ext_get_actual_len(ex)); - ext4_ext_store_pblock(&zero_ex, ext4_ext_pblock(ex)); - - err = ext4_ext_get_access(handle, inode, path + depth); - if (err) - goto out; - ext4_ext_mark_initialized(ex); - ext4_ext_try_to_merge(handle, inode, path, ex); - err = ext4_ext_dirty(handle, inode, path + path->p_depth); - goto out; - } - /* - * four cases: + * five cases: * 1. split the extent into three extents. - * 2. split the extent into two extents, zeroout the first half. - * 3. split the extent into two extents, zeroout the second half. + * 2. split the extent into two extents, zeroout the head of the first + * extent. + * 3. split the extent into two extents, zeroout the tail of the second + * extent. * 4. split the extent into two extents with out zeroout. + * 5. no splitting needed, just possibly zeroout the head and / or the + * tail of the extent. */ split_map.m_lblk = map->m_lblk; split_map.m_len = map->m_len; - if (max_zeroout && (allocated > map->m_len)) { + if (max_zeroout && (allocated > split_map.m_len)) { if (allocated <= max_zeroout) { - /* case 3 */ - zero_ex.ee_block = - cpu_to_le32(map->m_lblk); - zero_ex.ee_len = cpu_to_le16(allocated); - ext4_ext_store_pblock(&zero_ex, - ext4_ext_pblock(ex) + map->m_lblk - ee_block); - err = ext4_ext_zeroout(inode, &zero_ex); + /* case 3 or 5 */ + zero_ex1.ee_block = + cpu_to_le32(split_map.m_lblk + + split_map.m_len); + zero_ex1.ee_len = + cpu_to_le16(allocated - split_map.m_len); + ext4_ext_store_pblock(&zero_ex1, + ext4_ext_pblock(ex) + split_map.m_lblk + + split_map.m_len - ee_block); + err = ext4_ext_zeroout(inode, &zero_ex1); if (err) goto out; - split_map.m_lblk = map->m_lblk; split_map.m_len = allocated; - } else if (map->m_lblk - ee_block + map->m_len < max_zeroout) { - /* case 2 */ - if (map->m_lblk != ee_block) { - zero_ex.ee_block = ex->ee_block; - zero_ex.ee_len = cpu_to_le16(map->m_lblk - + } + if (split_map.m_lblk - ee_block + split_map.m_len < + max_zeroout) { + /* case 2 or 5 */ + if (split_map.m_lblk != ee_block) { + zero_ex2.ee_block = ex->ee_block; + zero_ex2.ee_len = cpu_to_le16(split_map.m_lblk - ee_block); - ext4_ext_store_pblock(&zero_ex, + ext4_ext_store_pblock(&zero_ex2, ext4_ext_pblock(ex)); - err = ext4_ext_zeroout(inode, &zero_ex); + err = ext4_ext_zeroout(inode, &zero_ex2); if (err) goto out; } + split_map.m_len += split_map.m_lblk - ee_block; split_map.m_lblk = ee_block; - split_map.m_len = map->m_lblk - ee_block + map->m_len; allocated = map->m_len; } } @@ -3642,8 +3633,11 @@ static int ext4_ext_convert_to_initialized(handle_t *handle, err = 0; out: /* If we have gotten a failure, don't zero out status tree */ - if (!err) - err = ext4_zeroout_es(inode, &zero_ex); + if (!err) { + err = ext4_zeroout_es(inode, &zero_ex1); + if (!err) + err = ext4_zeroout_es(inode, &zero_ex2); + } return err ? err : allocated; } -- cgit v1.2.3 From a056bdaae7a181f7dcc876cfab2f94538e508709 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Fri, 26 May 2017 17:45:45 -0400 Subject: ext4: fix data corruption for mmap writes mpage_submit_page() can race with another process growing i_size and writing data via mmap to the written-back page. As mpage_submit_page() samples i_size too early, it may happen that ext4_bio_write_page() zeroes out too large tail of the page and thus corrupts user data. Fix the problem by sampling i_size only after the page has been write-protected in page tables by clear_page_dirty_for_io() call. Reported-by: Michael Zimmer CC: stable@vger.kernel.org Fixes: cb20d5188366f04d96d2e07b1240cc92170ade40 Signed-off-by: Jan Kara Signed-off-by: Theodore Ts'o --- fs/ext4/inode.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 074aeba78259..657a98fa80b6 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -2124,15 +2124,29 @@ static int ext4_writepage(struct page *page, static int mpage_submit_page(struct mpage_da_data *mpd, struct page *page) { int len; - loff_t size = i_size_read(mpd->inode); + loff_t size; int err; BUG_ON(page->index != mpd->first_page); + clear_page_dirty_for_io(page); + /* + * We have to be very careful here! Nothing protects writeback path + * against i_size changes and the page can be writeably mapped into + * page tables. So an application can be growing i_size and writing + * data through mmap while writeback runs. clear_page_dirty_for_io() + * write-protects our page in page tables and the page cannot get + * written to again until we release page lock. So only after + * clear_page_dirty_for_io() we are safe to sample i_size for + * ext4_bio_write_page() to zero-out tail of the written page. We rely + * on the barrier provided by TestClearPageDirty in + * clear_page_dirty_for_io() to make sure i_size is really sampled only + * after page tables are updated. + */ + size = i_size_read(mpd->inode); if (page->index == size >> PAGE_SHIFT) len = size & ~PAGE_MASK; else len = PAGE_SIZE; - clear_page_dirty_for_io(page); err = ext4_bio_write_page(&mpd->io_submit, page, len, mpd->wbc, false); if (!err) mpd->wbc->nr_to_write--; -- cgit v1.2.3 From 5720acf4bfc142ba568d5b6782fceaf62ed15e0b Mon Sep 17 00:00:00 2001 From: Miroslav Benes Date: Fri, 26 May 2017 14:45:21 +0200 Subject: livepatch: Make livepatch dependent on !TRIM_UNUSED_KSYMS If TRIM_UNUSED_KSYMS is enabled, all unneeded exported symbols are made unexported. Two-pass build of the kernel is done to find out which symbols are needed based on a configuration. This effectively complicates things for out-of-tree modules. Livepatch exports functions to (un)register and enable/disable a live patch. The only in-tree module which uses these functions is a sample in samples/livepatch/. If the sample is disabled, the functions are trimmed and out-of-tree live patches cannot be built. Note that live patches are intended to be built out-of-tree. Suggested-by: Michal Marek Acked-by: Josh Poimboeuf Acked-by: Jessica Yu Signed-off-by: Miroslav Benes Signed-off-by: Jiri Kosina --- kernel/livepatch/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/livepatch/Kconfig b/kernel/livepatch/Kconfig index 045022557936..ec4565122e65 100644 --- a/kernel/livepatch/Kconfig +++ b/kernel/livepatch/Kconfig @@ -10,6 +10,7 @@ config LIVEPATCH depends on SYSFS depends on KALLSYMS_ALL depends on HAVE_LIVEPATCH + depends on !TRIM_UNUSED_KSYMS help Say Y here if you want to support kernel live patching. This option has no runtime impact until a kernel "patch" -- cgit v1.2.3 From f9797c2f20c0160edd718aa467101f3301e57e59 Mon Sep 17 00:00:00 2001 From: Luis Henriques Date: Thu, 25 May 2017 16:20:38 +0100 Subject: ftrace: Fix memory leak in ftrace_graph_release() ftrace_hash is being kfree'ed in ftrace_graph_release(), however the ->buckets field is not. This results in a memory leak that is easily captured by kmemleak: unreferenced object 0xffff880038afe000 (size 8192): comm "trace-cmd", pid 238, jiffies 4294916898 (age 9.736s) hex dump (first 32 bytes): 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ backtrace: [] kmemleak_alloc+0x4e/0xb0 [] __kmalloc+0x12d/0x1a0 [] alloc_ftrace_hash+0x51/0x80 [] __ftrace_graph_open.isra.39.constprop.46+0xa3/0x100 [] ftrace_graph_open+0x68/0xa0 [] do_dentry_open.isra.1+0x1bd/0x2d0 [] vfs_open+0x47/0x60 [] path_openat+0x2a5/0x1020 [] do_filp_open+0x8a/0xf0 [] do_sys_open+0x12f/0x200 [] SyS_open+0x1e/0x20 [] entry_SYSCALL_64_fastpath+0x13/0x94 [] 0xffffffffffffffff Link: http://lkml.kernel.org/r/20170525152038.7661-1-lhenriques@suse.com Cc: stable@vger.kernel.org Fixes: b9b0c831bed2 ("ftrace: Convert graph filter to use hash tables") Signed-off-by: Luis Henriques Signed-off-by: Steven Rostedt (VMware) --- kernel/trace/ftrace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 74fdfe9ed3db..9e5841dc14b5 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -5063,7 +5063,7 @@ ftrace_graph_release(struct inode *inode, struct file *file) } out: - kfree(fgd->new_hash); + free_ftrace_hash(fgd->new_hash); kfree(fgd); return ret; -- cgit v1.2.3 From c93f5cf571e7795f97d49ef51b766cf25e328545 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Thu, 25 May 2017 19:38:17 +0900 Subject: kprobes/x86: Fix to set RWX bits correctly before releasing trampoline Fix kprobes to set(recover) RWX bits correctly on trampoline buffer before releasing it. Releasing readonly page to module_memfree() crash the kernel. Without this fix, if kprobes user register a bunch of kprobes in function body (since kprobes on function entry usually use ftrace) and unregister it, kernel hits a BUG and crash. Link: http://lkml.kernel.org/r/149570868652.3518.14120169373590420503.stgit@devbox Signed-off-by: Masami Hiramatsu Fixes: d0381c81c2f7 ("kprobes/x86: Set kprobes pages read-only") Signed-off-by: Steven Rostedt (VMware) --- arch/x86/kernel/kprobes/core.c | 9 +++++++++ kernel/kprobes.c | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c index 5b2bbfbb3712..6b877807598b 100644 --- a/arch/x86/kernel/kprobes/core.c +++ b/arch/x86/kernel/kprobes/core.c @@ -52,6 +52,7 @@ #include #include #include +#include #include #include @@ -417,6 +418,14 @@ static void prepare_boost(struct kprobe *p, struct insn *insn) } } +/* Recover page to RW mode before releasing it */ +void free_insn_page(void *page) +{ + set_memory_nx((unsigned long)page & PAGE_MASK, 1); + set_memory_rw((unsigned long)page & PAGE_MASK, 1); + module_memfree(page); +} + static int arch_copy_kprobe(struct kprobe *p) { struct insn insn; diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 2d2d3a568e4e..adfe3b4cfe05 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -122,7 +122,7 @@ static void *alloc_insn_page(void) return module_alloc(PAGE_SIZE); } -static void free_insn_page(void *page) +void __weak free_insn_page(void *page) { module_memfree(page); } -- cgit v1.2.3 From bdd7e3d68492bfb7ade574f8c64b87bea499ca2e Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Fri, 26 May 2017 13:44:54 +0900 Subject: selftests/ftrace: Add a testcase for many kprobe events Add a testcase to test kprobes via ftrace interface with many concurrent kprobe events. This tries to add many kprobe events (up to 256) on kernel functions. To avoid making ftrace-based kprobes (kprobes on fentry), it skips first N bytes (on x86 N=5, on ppc or arm N=4) of function entry. After that, it enables all those events, disable it, and remove it. Since the unoptimization buffer reclaiming will be delayed, after removing events, it will wait enough time. Link: http://lkml.kernel.org/r/149577388470.11702.11832460851769204511.stgit@devbox Signed-off-by: Masami Hiramatsu Suggested-by: Steven Rostedt Signed-off-by: Steven Rostedt (VMware) --- .../ftrace/test.d/kprobe/multiple_kprobes.tc | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 tools/testing/selftests/ftrace/test.d/kprobe/multiple_kprobes.tc diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/multiple_kprobes.tc b/tools/testing/selftests/ftrace/test.d/kprobe/multiple_kprobes.tc new file mode 100644 index 000000000000..f4d1ff785d67 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/kprobe/multiple_kprobes.tc @@ -0,0 +1,21 @@ +#!/bin/sh +# description: Register/unregister many kprobe events + +# ftrace fentry skip size depends on the machine architecture. +# Currently HAVE_KPROBES_ON_FTRACE defined on x86 and powerpc +case `uname -m` in + x86_64|i[3456]86) OFFS=5;; + ppc*) OFFS=4;; + *) OFFS=0;; +esac + +echo "Setup up to 256 kprobes" +grep t /proc/kallsyms | cut -f3 -d" " | grep -v .*\\..* | \ +head -n 256 | while read i; do echo p ${i}+${OFFS} ; done > kprobe_events ||: + +echo 1 > events/kprobes/enable +echo 0 > events/kprobes/enable +echo > kprobe_events +echo "Waiting for unoptimizing & freeing" +sleep 5 +echo "Done" -- cgit v1.2.3 From a53276e2826010338478ed94310874001a8097fa Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Fri, 26 May 2017 10:14:11 -0400 Subject: x86/mm/ftrace: Do not bug in early boot on irqs_disabled in cpu_flush_range() With function tracing starting in early bootup and having its trampoline pages being read only, a bug triggered with the following: kernel BUG at arch/x86/mm/pageattr.c:189! invalid opcode: 0000 [#1] SMP Modules linked in: CPU: 0 PID: 0 Comm: swapper Not tainted 4.12.0-rc2-test+ #3 Hardware name: MSI MS-7823/CSM-H87M-G43 (MS-7823), BIOS V1.6 02/22/2014 task: ffffffffb4222500 task.stack: ffffffffb4200000 RIP: 0010:change_page_attr_set_clr+0x269/0x302 RSP: 0000:ffffffffb4203c88 EFLAGS: 00010046 RAX: 0000000000000046 RBX: 0000000000000000 RCX: 00000001b6000000 RDX: ffffffffb4203d40 RSI: 0000000000000000 RDI: ffffffffb4240d60 RBP: ffffffffb4203d18 R08: 00000001b6000000 R09: 0000000000000001 R10: ffffffffb4203aa8 R11: 0000000000000003 R12: ffffffffc029b000 R13: ffffffffb4203d40 R14: 0000000000000001 R15: 0000000000000000 FS: 0000000000000000(0000) GS:ffff9a639ea00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: ffff9a636b384000 CR3: 00000001ea21d000 CR4: 00000000000406b0 Call Trace: change_page_attr_clear+0x1f/0x21 set_memory_ro+0x1e/0x20 arch_ftrace_update_trampoline+0x207/0x21c ? ftrace_caller+0x64/0x64 ? 0xffffffffc029b000 ftrace_startup+0xf4/0x198 register_ftrace_function+0x26/0x3c function_trace_init+0x5e/0x73 tracer_init+0x1e/0x23 tracing_set_tracer+0x127/0x15a register_tracer+0x19b/0x1bc init_function_trace+0x90/0x92 early_trace_init+0x236/0x2b3 start_kernel+0x200/0x3f5 x86_64_start_reservations+0x29/0x2b x86_64_start_kernel+0x17c/0x18f secondary_startup_64+0x9f/0x9f ? secondary_startup_64+0x9f/0x9f Interrupts should not be enabled at this early in the boot process. It is also fine to leave interrupts enabled during this time as there's only one CPU running, and on_each_cpu() means to only run on the current CPU. If early_boot_irqs_disabled is set, it is safe to run cpu_flush_range() with interrupts disabled. Don't trigger a BUG_ON() in that case. Link: http://lkml.kernel.org/r/20170526093717.0be3b849@gandalf.local.home Suggested-by: Thomas Gleixner Signed-off-by: Steven Rostedt (VMware) --- arch/x86/mm/pageattr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 1dcd2be4cce4..c8520b2c62d2 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c @@ -186,7 +186,7 @@ static void cpa_flush_range(unsigned long start, int numpages, int cache) unsigned int i, level; unsigned long addr; - BUG_ON(irqs_disabled()); + BUG_ON(irqs_disabled() && !early_boot_irqs_disabled); WARN_ON(PAGE_ALIGN(start) != start); on_each_cpu(__cpa_flush_range, NULL, 1); -- cgit v1.2.3 From 6ee98ffeea0bc9e072e419497d78697d8afcdd6d Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 25 May 2017 10:57:51 +0200 Subject: x86/ftrace: Make sure that ftrace trampolines are not RWX ftrace use module_alloc() to allocate trampoline pages. The mapping of module_alloc() is RWX, which makes sense as the memory is written to right after allocation. But nothing makes these pages RO after writing to them. Add proper set_memory_rw/ro() calls to protect the trampolines after modification. Link: http://lkml.kernel.org/r/alpine.DEB.2.20.1705251056410.1862@nanos Signed-off-by: Thomas Gleixner Signed-off-by: Steven Rostedt (VMware) --- arch/x86/kernel/ftrace.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c index 0651e974dcb3..9bef1bbeba63 100644 --- a/arch/x86/kernel/ftrace.c +++ b/arch/x86/kernel/ftrace.c @@ -689,8 +689,12 @@ static inline void *alloc_tramp(unsigned long size) { return module_alloc(size); } -static inline void tramp_free(void *tramp) +static inline void tramp_free(void *tramp, int size) { + int npages = PAGE_ALIGN(size) >> PAGE_SHIFT; + + set_memory_nx((unsigned long)tramp, npages); + set_memory_rw((unsigned long)tramp, npages); module_memfree(tramp); } #else @@ -699,7 +703,7 @@ static inline void *alloc_tramp(unsigned long size) { return NULL; } -static inline void tramp_free(void *tramp) { } +static inline void tramp_free(void *tramp, int size) { } #endif /* Defined as markers to the end of the ftrace default trampolines */ @@ -771,7 +775,7 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size) /* Copy ftrace_caller onto the trampoline memory */ ret = probe_kernel_read(trampoline, (void *)start_offset, size); if (WARN_ON(ret < 0)) { - tramp_free(trampoline); + tramp_free(trampoline, *tramp_size); return 0; } @@ -797,7 +801,7 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size) /* Are we pointing to the reference? */ if (WARN_ON(memcmp(op_ptr.op, op_ref, 3) != 0)) { - tramp_free(trampoline); + tramp_free(trampoline, *tramp_size); return 0; } @@ -839,7 +843,7 @@ void arch_ftrace_update_trampoline(struct ftrace_ops *ops) unsigned long offset; unsigned long ip; unsigned int size; - int ret; + int ret, npages; if (ops->trampoline) { /* @@ -848,11 +852,14 @@ void arch_ftrace_update_trampoline(struct ftrace_ops *ops) */ if (!(ops->flags & FTRACE_OPS_FL_ALLOC_TRAMP)) return; + npages = PAGE_ALIGN(ops->trampoline_size) >> PAGE_SHIFT; + set_memory_rw(ops->trampoline, npages); } else { ops->trampoline = create_trampoline(ops, &size); if (!ops->trampoline) return; ops->trampoline_size = size; + npages = PAGE_ALIGN(size) >> PAGE_SHIFT; } offset = calc_trampoline_call_offset(ops->flags & FTRACE_OPS_FL_SAVE_REGS); @@ -863,6 +870,7 @@ void arch_ftrace_update_trampoline(struct ftrace_ops *ops) /* Do a safe modify in case the trampoline is executing */ new = ftrace_call_replace(ip, (unsigned long)func); ret = update_ftrace_func(ip, new); + set_memory_ro(ops->trampoline, npages); /* The update should never fail */ WARN_ON(ret); @@ -939,7 +947,7 @@ void arch_ftrace_trampoline_free(struct ftrace_ops *ops) if (!ops || !(ops->flags & FTRACE_OPS_FL_ALLOC_TRAMP)) return; - tramp_free((void *)ops->trampoline); + tramp_free((void *)ops->trampoline, ops->trampoline_size); ops->trampoline = 0; } -- cgit v1.2.3 From b3addcf0d1f04f53fcc302577d5a5e964c18531a Mon Sep 17 00:00:00 2001 From: Bin Liu Date: Thu, 25 May 2017 13:42:39 -0500 Subject: usb: musb: dsps: keep VBUS on for host-only mode Currently VBUS is turned off while a usb device is detached, and turned on again by the polling routine. This short period VBUS loss prevents usb modem to switch mode. VBUS should be constantly on for host-only mode, so this changes the driver to not turn off VBUS for host-only mode. Fixes: 2f3fd2c5bde1 ("usb: musb: Prepare dsps glue layer for PM runtime support") Cc: stable@vger.kernel.org #v4.11 Reported-by: Moreno Bartalucci Acked-by: Tony Lindgren Signed-off-by: Bin Liu Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_dsps.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 9c7ee26ef388..bc6a9be2ccc5 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -245,6 +245,11 @@ static int dsps_check_status(struct musb *musb, void *unused) dsps_mod_timer_optional(glue); break; case OTG_STATE_A_WAIT_BCON: + /* keep VBUS on for host-only mode */ + if (musb->port_mode == MUSB_PORT_MODE_HOST) { + dsps_mod_timer_optional(glue); + break; + } musb_writeb(musb->mregs, MUSB_DEVCTL, 0); skip_session = 1; /* fall */ -- cgit v1.2.3 From 7b4500bc519686712471924972022df88b12ff93 Mon Sep 17 00:00:00 2001 From: Ravi Bangoria Date: Fri, 5 May 2017 15:44:17 +0530 Subject: perf annotate: Fix failure when filename has special chars When filename contains special chars, perf annotate fails with an error: $ perf annotate --vmlinux ./vmlinux\(test\) --stdio native_safe_halt sh: -c: line 0: syntax error near unexpected token `(' sh: -c: line 0: `objdump --start-address=0xffffffff8184e840 --stop-address=0xffffffff8184e848 -l -d --no-show-raw -S -C ./vmlinux(test) 2>/dev/null|grep -v ./vmlinux(test):|expand' Fix it by surrounding filename in double quotes. Signed-off-by: Ravi Bangoria Cc: Adam Stylinski Cc: Alexander Shishkin Cc: Christian Borntraeger Cc: Peter Zijlstra Cc: Taeung Song Link: http://lkml.kernel.org/r/20170505101417.2117-1-ravi.bangoria@linux.vnet.ibm.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/annotate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 683f8340460c..07d5608a675f 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -1429,7 +1429,7 @@ int symbol__disassemble(struct symbol *sym, struct map *map, const char *arch_na snprintf(command, sizeof(command), "%s %s%s --start-address=0x%016" PRIx64 " --stop-address=0x%016" PRIx64 - " -l -d %s %s -C %s 2>/dev/null|grep -v %s:|expand", + " -l -d %s %s -C \"%s\" 2>/dev/null|grep -v \"%s:\"|expand", objdump_path ? objdump_path : "objdump", disassembler_style ? "-M " : "", disassembler_style ? disassembler_style : "", -- cgit v1.2.3 From ac20fa0a96c32ff40c8a127dfd58140f1df44a9b Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Tue, 2 May 2017 12:39:53 -0400 Subject: drm/msm: select PM_OPP Otherwise, if nothing else enabled selects it, dev_pm_opp_of_add_table() will return -ENOTSUPP. Fixes: e2af8b6 ("drm/msm: gpu: Use OPP tables if we can") Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig index 5b8e23d051f2..0a31cd6d01ce 100644 --- a/drivers/gpu/drm/msm/Kconfig +++ b/drivers/gpu/drm/msm/Kconfig @@ -13,6 +13,7 @@ config DRM_MSM select QCOM_SCM select SND_SOC_HDMI_CODEC if SND_SOC select SYNC_FILE + select PM_OPP default y help DRM/KMS driver for MSM/snapdragon. -- cgit v1.2.3 From 786813c343cb619d23cb0990e152e350b826d810 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Wed, 3 May 2017 10:04:48 -0400 Subject: drm/msm/mdp5: use __drm_atomic_helper_plane_duplicate_state() Somehow the helper was never retrofitted for mdp5. Which meant when plane_state->fence was added, it could get copied into new state in mdp5_plane_duplicate_state(). If an update to disable the plane (for example on rmfb) managed to sneak in after an nonblock update had swapped state, but before it was committed, we'd get a splat: WARNING: CPU: 1 PID: 69 at ../drivers/gpu/drm/drm_atomic_helper.c:1061 drm_atomic_helper_wait_for_fences+0xe0/0xf8 Modules linked in: CPU: 1 PID: 69 Comm: kworker/1:1 Tainted: G W 4.11.0-rc8+ #1187 Hardware name: Qualcomm Technologies, Inc. APQ 8016 SBC (DT) Workqueue: events drm_mode_rmfb_work_fn task: ffffffc036560d00 task.stack: ffffffc036550000 PC is at drm_atomic_helper_wait_for_fences+0xe0/0xf8 LR is at complete_commit.isra.1+0x44/0x1c0 pc : [] lr : [] pstate: 20000145 sp : ffffffc036553b60 x29: ffffffc036553b60 x28: ffffffc0264e6a00 x27: ffffffc035659000 x26: 0000000000000000 x25: ffffffc0240e8000 x24: 0000000000000038 x23: 0000000000000000 x22: ffffff800858f200 x21: ffffffc0240e8000 x20: ffffffc02f56a800 x19: 0000000000000000 x18: 0000000000000000 x17: 0000000000000000 x16: 0000000000000000 x15: 0000000000000000 x14: ffffffc00a192700 x13: 0000000000000004 x12: 0000000000000000 x11: ffffff80089a1690 x10: 00000000000008f0 x9 : ffffffc036553b20 x8 : ffffffc036561650 x7 : ffffffc03fe6cb40 x6 : 0000000000000000 x5 : 0000000000000001 x4 : 0000000000000002 x3 : ffffffc035659000 x2 : ffffffc0240e8c80 x1 : 0000000000000000 x0 : ffffffc02adbe588 ---[ end trace 13aeec77c3fb55e2 ]--- Call trace: Exception stack(0xffffffc036553990 to 0xffffffc036553ac0) 3980: 0000000000000000 0000008000000000 39a0: ffffffc036553b60 ffffff80084f6040 0000000000004ff0 0000000000000038 39c0: ffffffc0365539d0 ffffff800857e098 ffffffc036553a00 ffffff800857e1b0 39e0: ffffffc036553a10 ffffff800857c554 ffffffc0365e8400 ffffffc0365e8400 3a00: ffffffc036553a20 ffffff8008103358 000000000001aad7 ffffff800851b72c 3a20: ffffffc036553a50 ffffff80080e9228 ffffffc02adbe588 0000000000000000 3a40: ffffffc0240e8c80 ffffffc035659000 0000000000000002 0000000000000001 3a60: 0000000000000000 ffffffc03fe6cb40 ffffffc036561650 ffffffc036553b20 3a80: 00000000000008f0 ffffff80089a1690 0000000000000000 0000000000000004 3aa0: ffffffc00a192700 0000000000000000 0000000000000000 0000000000000000 [] drm_atomic_helper_wait_for_fences+0xe0/0xf8 [] complete_commit.isra.1+0x44/0x1c0 [] msm_atomic_commit+0x32c/0x350 [] drm_atomic_commit+0x50/0x60 [] drm_atomic_remove_fb+0x158/0x250 [] drm_framebuffer_remove+0x50/0x158 [] drm_mode_rmfb_work_fn+0x40/0x58 [] process_one_work+0x1d0/0x378 [] worker_thread+0x244/0x488 [] kthread+0xfc/0x128 [] ret_from_fork+0x10/0x50 Fixes: 9626014 ("drm/fence: add in-fences support") Cc: stable@vger.kernel.org Reviewed-by: Daniel Vetter Reported-by: Stanimir Varbanov Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c index a38c5fe6cc19..30b4691f7b0d 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c @@ -225,9 +225,10 @@ mdp5_plane_duplicate_state(struct drm_plane *plane) mdp5_state = kmemdup(to_mdp5_plane_state(plane->state), sizeof(*mdp5_state), GFP_KERNEL); + if (!mdp5_state) + return NULL; - if (mdp5_state && mdp5_state->base.fb) - drm_framebuffer_reference(mdp5_state->base.fb); + __drm_atomic_helper_plane_duplicate_state(plane, &mdp5_state->base); return &mdp5_state->base; } -- cgit v1.2.3 From 134ccada7ac59156761ce05afd1c0b1d02ebd928 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Wed, 3 May 2017 10:43:14 -0400 Subject: drm/msm/gpu: check legacy clk names in get_clocks() Otherwise if someone was using old bindings with "core_clk" instead of "core" as the clock name, we'd never find it and gpu would be stuck at 27MHz (or whatever it's slowest rate is). Fixes: 98db803 ("msm/drm: gpu: Dynamically locate the clocks from the device tree") Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/msm_gpu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index 97b9c38c6b3f..0fdc88d79ca8 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -549,9 +549,9 @@ static int get_clocks(struct platform_device *pdev, struct msm_gpu *gpu) gpu->grp_clks[i] = get_clock(dev, name); /* Remember the key clocks that we need to control later */ - if (!strcmp(name, "core")) + if (!strcmp(name, "core") || !strcmp(name, "core_clk")) gpu->core_clk = gpu->grp_clks[i]; - else if (!strcmp(name, "rbbmtimer")) + else if (!strcmp(name, "rbbmtimer") || !strcmp(name, "rbbmtimer_clk")) gpu->rbbmtimer_clk = gpu->grp_clks[i]; ++i; -- cgit v1.2.3 From 43523eba79bda8f5b4c27f8ffe20ea078d20113a Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 12 Apr 2017 12:11:58 -0700 Subject: drm/msm: Expose our reservation object when exporting a dmabuf. Without this, polling on the dma-buf (and presumably other devices synchronizing against our rendering) would return immediately, even while the BO was busy. Signed-off-by: Eric Anholt Reviewed-by: Daniel Vetter Cc: stable@vger.kernel.org Cc: Rob Clark Cc: linux-arm-msm@vger.kernel.org Cc: freedreno@lists.freedesktop.org Reviewed-by: Rob Clark Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/msm_drv.c | 1 + drivers/gpu/drm/msm/msm_drv.h | 1 + drivers/gpu/drm/msm/msm_gem_prime.c | 7 +++++++ 3 files changed, 9 insertions(+) diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 87b5695d4034..9d498eb81906 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -830,6 +830,7 @@ static struct drm_driver msm_driver = { .prime_fd_to_handle = drm_gem_prime_fd_to_handle, .gem_prime_export = drm_gem_prime_export, .gem_prime_import = drm_gem_prime_import, + .gem_prime_res_obj = msm_gem_prime_res_obj, .gem_prime_pin = msm_gem_prime_pin, .gem_prime_unpin = msm_gem_prime_unpin, .gem_prime_get_sg_table = msm_gem_prime_get_sg_table, diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 28b6f9ba5066..1b26ca626528 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -224,6 +224,7 @@ struct sg_table *msm_gem_prime_get_sg_table(struct drm_gem_object *obj); void *msm_gem_prime_vmap(struct drm_gem_object *obj); void msm_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr); int msm_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma); +struct reservation_object *msm_gem_prime_res_obj(struct drm_gem_object *obj); struct drm_gem_object *msm_gem_prime_import_sg_table(struct drm_device *dev, struct dma_buf_attachment *attach, struct sg_table *sg); int msm_gem_prime_pin(struct drm_gem_object *obj); diff --git a/drivers/gpu/drm/msm/msm_gem_prime.c b/drivers/gpu/drm/msm/msm_gem_prime.c index 60bb290700ce..13403c6da6c7 100644 --- a/drivers/gpu/drm/msm/msm_gem_prime.c +++ b/drivers/gpu/drm/msm/msm_gem_prime.c @@ -70,3 +70,10 @@ void msm_gem_prime_unpin(struct drm_gem_object *obj) if (!obj->import_attach) msm_gem_put_pages(obj); } + +struct reservation_object *msm_gem_prime_res_obj(struct drm_gem_object *obj) +{ + struct msm_gem_object *msm_obj = to_msm_bo(obj); + + return msm_obj->resv; +} -- cgit v1.2.3 From 3c30cc41a87880db86c343b8c9cc8bc2d3d36055 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 12 Apr 2017 12:12:00 -0700 Subject: drm/msm: Reuse dma_fence_release. If we follow the typical pattern of the base class being the first member, we can use the default dma_fence_free function. Signed-off-by: Eric Anholt Cc: Rob Clark Cc: linux-arm-msm@vger.kernel.org Cc: freedreno@lists.freedesktop.org Reviewed-by: Rob Clark Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/msm_fence.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_fence.c b/drivers/gpu/drm/msm/msm_fence.c index 3f299c537b77..a2f89bac9c16 100644 --- a/drivers/gpu/drm/msm/msm_fence.c +++ b/drivers/gpu/drm/msm/msm_fence.c @@ -99,8 +99,8 @@ void msm_update_fence(struct msm_fence_context *fctx, uint32_t fence) } struct msm_fence { - struct msm_fence_context *fctx; struct dma_fence base; + struct msm_fence_context *fctx; }; static inline struct msm_fence *to_msm_fence(struct dma_fence *fence) @@ -130,19 +130,13 @@ static bool msm_fence_signaled(struct dma_fence *fence) return fence_completed(f->fctx, f->base.seqno); } -static void msm_fence_release(struct dma_fence *fence) -{ - struct msm_fence *f = to_msm_fence(fence); - kfree_rcu(f, base.rcu); -} - static const struct dma_fence_ops msm_fence_ops = { .get_driver_name = msm_fence_get_driver_name, .get_timeline_name = msm_fence_get_timeline_name, .enable_signaling = msm_fence_enable_signaling, .signaled = msm_fence_signaled, .wait = dma_fence_default_wait, - .release = msm_fence_release, + .release = dma_fence_free, }; struct dma_fence * -- cgit v1.2.3 From adcbae310f9ed84ef139e3fa6d7a7743d96c44c8 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Sun, 21 May 2017 12:05:07 -0400 Subject: drm/msm/mdp5: release hwpipe(s) for unused planes Otherwise, if userspace doesn't re-use a given plane, it's hwpipe(s) could stay permanently assigned. Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c index 30b4691f7b0d..7d3741215387 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c @@ -445,6 +445,10 @@ static int mdp5_plane_atomic_check_with_state(struct drm_crtc_state *crtc_state, mdp5_pipe_release(state->state, old_hwpipe); mdp5_pipe_release(state->state, old_right_hwpipe); } + } else { + mdp5_pipe_release(state->state, mdp5_state->hwpipe); + mdp5_pipe_release(state->state, mdp5_state->r_hwpipe); + mdp5_state->hwpipe = mdp5_state->r_hwpipe = NULL; } return 0; -- cgit v1.2.3 From c43dd227f411359802427da7aebe5da5b0e48e0e Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Wed, 24 May 2017 18:12:19 +0200 Subject: drm/msm: constify irq_domain_ops struct irq_domain_ops is not modified, so it can be made const. Signed-off-by: Tobias Klauser Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/mdp/mdp5/mdp5_mdss.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_mdss.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_mdss.c index f8f48d014978..9c34d7824988 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_mdss.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_mdss.c @@ -116,7 +116,7 @@ static int mdss_hw_irqdomain_map(struct irq_domain *d, unsigned int irq, return 0; } -static struct irq_domain_ops mdss_hw_irqdomain_ops = { +static const struct irq_domain_ops mdss_hw_irqdomain_ops = { .map = mdss_hw_irqdomain_map, .xlate = irq_domain_xlate_onecell, }; -- cgit v1.2.3 From 3cfac69cbd56e1a57a70bfbdb07560b788030404 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Fri, 17 Mar 2017 19:38:40 +0100 Subject: drm/msm: for array in-fences, check if all backing fences are from our own context before waiting Use the dma_fence_match_context helper to check if all backing fences are from our own context, in which case we don't have to wait. Signed-off-by: Philipp Zabel Cc: Rob Clark Cc: Gustavo Padovan [rebased on code-motion] Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/msm_gem_submit.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c index 1c545ebe6a5a..8ac4ca443914 100644 --- a/drivers/gpu/drm/msm/msm_gem_submit.c +++ b/drivers/gpu/drm/msm/msm_gem_submit.c @@ -410,12 +410,11 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, if (!in_fence) return -EINVAL; - /* TODO if we get an array-fence due to userspace merging multiple - * fences, we need a way to determine if all the backing fences - * are from our own context.. + /* + * Wait if the fence is from a foreign context, or if the fence + * array contains any fence from a foreign context. */ - - if (in_fence->context != gpu->fctx->context) { + if (!dma_fence_match_context(in_fence, gpu->fctx->context)) { ret = dma_fence_wait(in_fence, true); if (ret) return ret; -- cgit v1.2.3 From 90dd57de4a043f642179b1323a31ca3ced826611 Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Mon, 8 May 2017 14:34:57 -0600 Subject: drm/msm: Take the mutex before calling msm_gem_new_impl Amongst its other duties, msm_gem_new_impl adds the newly created GEM object to the shared inactive list which may also be actively modifiying the list during submission. All the paths to modify the list are protected by the mutex except for the one through msm_gem_import which can end up causing list corruption. Signed-off-by: Jordan Crouse [add extra WARN_ON(!mutex_is_locked(&dev->struct_mutex))] Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/msm_gem.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index 68e509b3b9e4..50289a23baf8 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -758,6 +758,8 @@ static int msm_gem_new_impl(struct drm_device *dev, struct msm_gem_object *msm_obj; bool use_vram = false; + WARN_ON(!mutex_is_locked(&dev->struct_mutex)); + switch (flags & MSM_BO_CACHE_MASK) { case MSM_BO_UNCACHED: case MSM_BO_CACHED: @@ -853,7 +855,11 @@ struct drm_gem_object *msm_gem_import(struct drm_device *dev, size = PAGE_ALIGN(dmabuf->size); + /* Take mutex so we can modify the inactive list in msm_gem_new_impl */ + mutex_lock(&dev->struct_mutex); ret = msm_gem_new_impl(dev, size, MSM_BO_WC, dmabuf->resv, &obj); + mutex_unlock(&dev->struct_mutex); + if (ret) goto fail; -- cgit v1.2.3 From d72fea538fe6d783c1e63a2fc304019abf4be93a Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Mon, 8 May 2017 14:34:58 -0600 Subject: drm/msm: Fix the check for the command size The overrun check for the size of submitted commands is off by one. It should allow the offset plus the size to be equal to the size of the memory object when the command stream is very tightly constructed. Signed-off-by: Jordan Crouse Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/msm_gem_submit.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c index 8ac4ca443914..7832e6421d25 100644 --- a/drivers/gpu/drm/msm/msm_gem_submit.c +++ b/drivers/gpu/drm/msm/msm_gem_submit.c @@ -495,8 +495,9 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, goto out; } - if ((submit_cmd.size + submit_cmd.submit_offset) >= - msm_obj->base.size) { + if (!submit_cmd.size || + ((submit_cmd.size + submit_cmd.submit_offset) > + msm_obj->base.size)) { DRM_ERROR("invalid cmdstream size: %u\n", submit_cmd.size); ret = -EINVAL; goto out; -- cgit v1.2.3 From 6c713a3a23154f4f0c2217ea39811ebe443dafaa Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Fri, 26 May 2017 01:44:43 +0200 Subject: net: dsa: mv88e6xxx: Add eeprom-length to binding The binding documentation for the mv88e6xxx switch is missing the eeprom-length property, which has been implemented since May 2016, commit f8cd8753def0 ("dsa: mv88e6xxx: Handle eeprom-length property") Signed-off-by: Andrew Lunn Signed-off-by: David S. Miller --- Documentation/devicetree/bindings/net/dsa/marvell.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/net/dsa/marvell.txt b/Documentation/devicetree/bindings/net/dsa/marvell.txt index 7ef9dbb08957..1d4d0f49c9d0 100644 --- a/Documentation/devicetree/bindings/net/dsa/marvell.txt +++ b/Documentation/devicetree/bindings/net/dsa/marvell.txt @@ -26,6 +26,10 @@ Optional properties: - interrupt-controller : Indicates the switch is itself an interrupt controller. This is used for the PHY interrupts. #interrupt-cells = <2> : Controller uses two cells, number and flag +- eeprom-length : Set to the length of an EEPROM connected to the + switch. Must be set if the switch can not detect + the presence and/or size of a connected EEPROM, + otherwise optional. - mdio : Container of PHY and devices on the switches MDIO bus. - mdio? : Container of PHYs and devices on the external MDIO -- cgit v1.2.3 From fb3ce90b7d7761b6f7f28f0ff5c456ef6b5229a1 Mon Sep 17 00:00:00 2001 From: Firo Yang Date: Fri, 26 May 2017 22:37:38 +0800 Subject: hdlcdrv: Fix divide by zero in hdlcdrv_ioctl syszkaller fuzzer triggered a divide by zero, when set calibration through ioctl(). To fix it, test 'bitrate' if it is negative or 0, just return -EINVAL. Reported-by: Andrey Konovalov Signed-off-by: Firo Yang Signed-off-by: David S. Miller --- drivers/net/hamradio/hdlcdrv.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/hamradio/hdlcdrv.c b/drivers/net/hamradio/hdlcdrv.c index 8c3633c1d078..97e3bc60c3e7 100644 --- a/drivers/net/hamradio/hdlcdrv.c +++ b/drivers/net/hamradio/hdlcdrv.c @@ -576,6 +576,8 @@ static int hdlcdrv_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) case HDLCDRVCTL_CALIBRATE: if(!capable(CAP_SYS_RAWIO)) return -EPERM; + if (s->par.bitrate <= 0) + return -EINVAL; if (bi.data.calibrate > INT_MAX / s->par.bitrate) return -EINVAL; s->hdlctx.calibrate = bi.data.calibrate * s->par.bitrate / 16; -- cgit v1.2.3 From 1ea34adb87c969b89dfd83f1905a79161e9ada26 Mon Sep 17 00:00:00 2001 From: Juergen Gross Date: Fri, 26 May 2017 12:36:47 +0100 Subject: efi: Don't issue error message when booted under Xen When booted as Xen dom0 there won't be an EFI memmap allocated. Avoid issuing an error message in this case: [ 0.144079] efi: Failed to allocate new EFI memmap Signed-off-by: Juergen Gross Signed-off-by: Matt Fleming Cc: # v4.9+ Cc: Ard Biesheuvel Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: linux-efi@vger.kernel.org Link: http://lkml.kernel.org/r/20170526113652.21339-2-matt@codeblueprint.co.uk Signed-off-by: Ingo Molnar --- arch/x86/platform/efi/quirks.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c index 26615991d69c..e0cf95a83f3f 100644 --- a/arch/x86/platform/efi/quirks.c +++ b/arch/x86/platform/efi/quirks.c @@ -360,6 +360,9 @@ void __init efi_free_boot_services(void) free_bootmem_late(start, size); } + if (!num_entries) + return; + new_size = efi.memmap.desc_size * num_entries; new_phys = efi_memmap_alloc(num_entries); if (!new_phys) { -- cgit v1.2.3 From 684e3f965d0be8c26fedefe94f637374242aba08 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 26 May 2017 12:36:48 +0100 Subject: efi: Remove duplicate 'const' specifiers gcc-7 shows these harmless warnings: drivers/firmware/efi/libstub/secureboot.c:19:27: error: duplicate 'const' declaration specifier [-Werror=duplicate-decl-specifier] static const efi_char16_t const efi_SecureBoot_name[] = { drivers/firmware/efi/libstub/secureboot.c:22:27: error: duplicate 'const' declaration specifier [-Werror=duplicate-decl-specifier] Removing one of the specifiers gives us the expected behavior. Signed-off-by: Arnd Bergmann Signed-off-by: Matt Fleming Reviewed-by: David Howells Acked-by: Ard Biesheuvel Cc: Josh Boyer Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: linux-efi@vger.kernel.org Fixes: de8cb458625c ("efi: Get and store the secure boot status") Link: http://lkml.kernel.org/r/20170526113652.21339-3-matt@codeblueprint.co.uk Signed-off-by: Ingo Molnar --- drivers/firmware/efi/libstub/secureboot.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/firmware/efi/libstub/secureboot.c b/drivers/firmware/efi/libstub/secureboot.c index 8c34d50a4d80..959777ec8a77 100644 --- a/drivers/firmware/efi/libstub/secureboot.c +++ b/drivers/firmware/efi/libstub/secureboot.c @@ -16,10 +16,10 @@ /* BIOS variables */ static const efi_guid_t efi_variable_guid = EFI_GLOBAL_VARIABLE_GUID; -static const efi_char16_t const efi_SecureBoot_name[] = { +static const efi_char16_t efi_SecureBoot_name[] = { 'S', 'e', 'c', 'u', 'r', 'e', 'B', 'o', 'o', 't', 0 }; -static const efi_char16_t const efi_SetupMode_name[] = { +static const efi_char16_t efi_SetupMode_name[] = { 'S', 'e', 't', 'u', 'p', 'M', 'o', 'd', 'e', 0 }; -- cgit v1.2.3 From 4e52797d2efefac3271abdc54439a3435abd77b9 Mon Sep 17 00:00:00 2001 From: Sai Praneeth Date: Fri, 26 May 2017 12:36:49 +0100 Subject: x86/efi: Disable runtime services on kexec kernel if booted with efi=old_map Booting kexec kernel with "efi=old_map" in kernel command line hits kernel panic as shown below. BUG: unable to handle kernel paging request at ffff88007fe78070 IP: virt_efi_set_variable.part.7+0x63/0x1b0 PGD 7ea28067 PUD 7ea2b067 PMD 7ea2d067 PTE 0 [...] Call Trace: virt_efi_set_variable() efi_delete_dummy_variable() efi_enter_virtual_mode() start_kernel() x86_64_start_reservations() x86_64_start_kernel() start_cpu() [ efi=old_map was never intended to work with kexec. The problem with using efi=old_map is that the virtual addresses are assigned from the memory region used by other kernel mappings; vmalloc() space. Potentially there could be collisions when booting kexec if something else is mapped at the virtual address we allocated for runtime service regions in the initial boot - Matt Fleming ] Since kexec was never intended to work with efi=old_map, disable runtime services in kexec if booted with efi=old_map, so that we don't panic. Tested-by: Lee Chun-Yi Signed-off-by: Sai Praneeth Prakhya Signed-off-by: Matt Fleming Acked-by: Dave Young Cc: Ard Biesheuvel Cc: Borislav Petkov Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Ravi Shankar Cc: Ricardo Neri Cc: Thomas Gleixner Cc: linux-efi@vger.kernel.org Link: http://lkml.kernel.org/r/20170526113652.21339-4-matt@codeblueprint.co.uk Signed-off-by: Ingo Molnar --- arch/x86/platform/efi/efi.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 7e76a4d8304b..43b96f5f78ba 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -828,9 +828,11 @@ static void __init kexec_enter_virtual_mode(void) /* * We don't do virtual mode, since we don't do runtime services, on - * non-native EFI + * non-native EFI. With efi=old_map, we don't do runtime services in + * kexec kernel because in the initial boot something else might + * have been mapped at these virtual addresses. */ - if (!efi_is_native()) { + if (!efi_is_native() || efi_enabled(EFI_OLD_MEMMAP)) { efi_memmap_unmap(); clear_bit(EFI_RUNTIME_SERVICES, &efi.flags); return; -- cgit v1.2.3 From 94133e46a0f5ca3f138479806104ab4a8cb0455e Mon Sep 17 00:00:00 2001 From: Baoquan He Date: Fri, 26 May 2017 12:36:50 +0100 Subject: x86/efi: Correct EFI identity mapping under 'efi=old_map' when KASLR is enabled For EFI with the 'efi=old_map' kernel option specified, the kernel will panic when KASLR is enabled: BUG: unable to handle kernel paging request at 000000007febd57e IP: 0x7febd57e PGD 1025a067 PUD 0 Oops: 0010 [#1] SMP Call Trace: efi_enter_virtual_mode() start_kernel() x86_64_start_reservations() x86_64_start_kernel() start_cpu() The root cause is that the identity mapping is not built correctly in the 'efi=old_map' case. On 'nokaslr' kernels, PAGE_OFFSET is 0xffff880000000000 which is PGDIR_SIZE aligned. We can borrow the PUD table from the direct mappings safely. Given a physical address X, we have pud_index(X) == pud_index(__va(X)). However, on KASLR kernels, PAGE_OFFSET is PUD_SIZE aligned. For a given physical address X, pud_index(X) != pud_index(__va(X)). We can't just copy the PGD entry from direct mapping to build identity mapping, instead we need to copy the PUD entries one by one from the direct mapping. Fix it. Signed-off-by: Baoquan He Signed-off-by: Matt Fleming Cc: Ard Biesheuvel Cc: Bhupesh Sharma Cc: Borislav Petkov Cc: Dave Young Cc: Frank Ramsay Cc: Kees Cook Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Russ Anderson Cc: Thomas Garnier Cc: Thomas Gleixner Cc: linux-efi@vger.kernel.org Link: http://lkml.kernel.org/r/20170526113652.21339-5-matt@codeblueprint.co.uk [ Fixed and reworded the changelog and code comments to be more readable. ] Signed-off-by: Ingo Molnar --- arch/x86/platform/efi/efi_64.c | 79 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 71 insertions(+), 8 deletions(-) diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c index c488625c9712..eb8dff15a7f6 100644 --- a/arch/x86/platform/efi/efi_64.c +++ b/arch/x86/platform/efi/efi_64.c @@ -71,11 +71,13 @@ static void __init early_code_mapping_set_exec(int executable) pgd_t * __init efi_call_phys_prolog(void) { - unsigned long vaddress; - pgd_t *save_pgd; + unsigned long vaddr, addr_pgd, addr_p4d, addr_pud; + pgd_t *save_pgd, *pgd_k, *pgd_efi; + p4d_t *p4d, *p4d_k, *p4d_efi; + pud_t *pud; int pgd; - int n_pgds; + int n_pgds, i, j; if (!efi_enabled(EFI_OLD_MEMMAP)) { save_pgd = (pgd_t *)read_cr3(); @@ -88,10 +90,49 @@ pgd_t * __init efi_call_phys_prolog(void) n_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT), PGDIR_SIZE); save_pgd = kmalloc_array(n_pgds, sizeof(*save_pgd), GFP_KERNEL); + /* + * Build 1:1 identity mapping for efi=old_map usage. Note that + * PAGE_OFFSET is PGDIR_SIZE aligned when KASLR is disabled, while + * it is PUD_SIZE ALIGNED with KASLR enabled. So for a given physical + * address X, the pud_index(X) != pud_index(__va(X)), we can only copy + * PUD entry of __va(X) to fill in pud entry of X to build 1:1 mapping. + * This means here we can only reuse the PMD tables of the direct mapping. + */ for (pgd = 0; pgd < n_pgds; pgd++) { - save_pgd[pgd] = *pgd_offset_k(pgd * PGDIR_SIZE); - vaddress = (unsigned long)__va(pgd * PGDIR_SIZE); - set_pgd(pgd_offset_k(pgd * PGDIR_SIZE), *pgd_offset_k(vaddress)); + addr_pgd = (unsigned long)(pgd * PGDIR_SIZE); + vaddr = (unsigned long)__va(pgd * PGDIR_SIZE); + pgd_efi = pgd_offset_k(addr_pgd); + save_pgd[pgd] = *pgd_efi; + + p4d = p4d_alloc(&init_mm, pgd_efi, addr_pgd); + if (!p4d) { + pr_err("Failed to allocate p4d table!\n"); + goto out; + } + + for (i = 0; i < PTRS_PER_P4D; i++) { + addr_p4d = addr_pgd + i * P4D_SIZE; + p4d_efi = p4d + p4d_index(addr_p4d); + + pud = pud_alloc(&init_mm, p4d_efi, addr_p4d); + if (!pud) { + pr_err("Failed to allocate pud table!\n"); + goto out; + } + + for (j = 0; j < PTRS_PER_PUD; j++) { + addr_pud = addr_p4d + j * PUD_SIZE; + + if (addr_pud > (max_pfn << PAGE_SHIFT)) + break; + + vaddr = (unsigned long)__va(addr_pud); + + pgd_k = pgd_offset_k(vaddr); + p4d_k = p4d_offset(pgd_k, vaddr); + pud[j] = *pud_offset(p4d_k, vaddr); + } + } } out: __flush_tlb_all(); @@ -104,8 +145,11 @@ void __init efi_call_phys_epilog(pgd_t *save_pgd) /* * After the lock is released, the original page table is restored. */ - int pgd_idx; + int pgd_idx, i; int nr_pgds; + pgd_t *pgd; + p4d_t *p4d; + pud_t *pud; if (!efi_enabled(EFI_OLD_MEMMAP)) { write_cr3((unsigned long)save_pgd); @@ -115,9 +159,28 @@ void __init efi_call_phys_epilog(pgd_t *save_pgd) nr_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT) , PGDIR_SIZE); - for (pgd_idx = 0; pgd_idx < nr_pgds; pgd_idx++) + for (pgd_idx = 0; pgd_idx < nr_pgds; pgd_idx++) { + pgd = pgd_offset_k(pgd_idx * PGDIR_SIZE); set_pgd(pgd_offset_k(pgd_idx * PGDIR_SIZE), save_pgd[pgd_idx]); + if (!(pgd_val(*pgd) & _PAGE_PRESENT)) + continue; + + for (i = 0; i < PTRS_PER_P4D; i++) { + p4d = p4d_offset(pgd, + pgd_idx * PGDIR_SIZE + i * P4D_SIZE); + + if (!(p4d_val(*p4d) & _PAGE_PRESENT)) + continue; + + pud = (pud_t *)p4d_page_vaddr(*p4d); + pud_free(&init_mm, pud); + } + + p4d = (p4d_t *)pgd_page_vaddr(*pgd); + p4d_free(&init_mm, p4d); + } + kfree(save_pgd); __flush_tlb_all(); -- cgit v1.2.3 From 7425826f4f7ac60f2538b06a7f0a5d1006405159 Mon Sep 17 00:00:00 2001 From: Dave Young Date: Fri, 26 May 2017 12:36:51 +0100 Subject: efi/bgrt: Skip efi_bgrt_init() in case of non-EFI boot Sabrina Dubroca reported an early panic: BUG: unable to handle kernel paging request at ffffffffff240001 IP: efi_bgrt_init+0xdc/0x134 [...] ---[ end Kernel panic - not syncing: Attempted to kill the idle task! ... which was introduced by: 7b0a911478c7 ("efi/x86: Move the EFI BGRT init code to early init code") The cause is that on this machine the firmware provides the EFI ACPI BGRT table even on legacy non-EFI bootups - which table should be EFI only. The garbage BGRT data causes the efi_bgrt_init() panic. Add a check to skip efi_bgrt_init() in case non-EFI bootup to work around this firmware bug. Tested-by: Sabrina Dubroca Signed-off-by: Dave Young Signed-off-by: Ard Biesheuvel Signed-off-by: Matt Fleming Cc: # v4.11+ Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: linux-efi@vger.kernel.org Fixes: 7b0a911478c7 ("efi/x86: Move the EFI BGRT init code to early init code") Link: http://lkml.kernel.org/r/20170526113652.21339-6-matt@codeblueprint.co.uk [ Rewrote the changelog to be more readable. ] Signed-off-by: Ingo Molnar --- drivers/firmware/efi/efi-bgrt.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/firmware/efi/efi-bgrt.c b/drivers/firmware/efi/efi-bgrt.c index 04ca8764f0c0..8bf27323f7a3 100644 --- a/drivers/firmware/efi/efi-bgrt.c +++ b/drivers/firmware/efi/efi-bgrt.c @@ -36,6 +36,9 @@ void __init efi_bgrt_init(struct acpi_table_header *table) if (acpi_disabled) return; + if (!efi_enabled(EFI_BOOT)) + return; + if (table->length < sizeof(bgrt_tab)) { pr_notice("Ignoring BGRT: invalid length %u (expected %zu)\n", table->length, sizeof(bgrt_tab)); -- cgit v1.2.3 From c21fbe29f8588991b4fbf209ad4f6ecd4b550cdb Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sun, 28 May 2017 17:25:14 +0200 Subject: net: dsa: mv88e6xxx: Add missing static to stub functions Stub functions in header files need to be static, or we can have multiple definitions errors. Reported-by: kbuild test robot Fixes: 6335e9f2446b ("net: dsa: mv88e6xxx: mv88e6390X SERDES support") Signed-off-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/global2.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/global2.h b/drivers/net/dsa/mv88e6xxx/global2.h index 96046bb12ca1..d8d3c5abb2a1 100644 --- a/drivers/net/dsa/mv88e6xxx/global2.h +++ b/drivers/net/dsa/mv88e6xxx/global2.h @@ -114,13 +114,13 @@ static inline int mv88e6xxx_g2_set_eeprom16(struct mv88e6xxx_chip *chip, return -EOPNOTSUPP; } -int mv88e6xxx_g2_pvt_write(struct mv88e6xxx_chip *chip, int src_dev, - int src_port, u16 data) +static int mv88e6xxx_g2_pvt_write(struct mv88e6xxx_chip *chip, int src_dev, + int src_port, u16 data) { return -EOPNOTSUPP; } -int mv88e6xxx_g2_misc_4_bit_port(struct mv88e6xxx_chip *chip) +static int mv88e6xxx_g2_misc_4_bit_port(struct mv88e6xxx_chip *chip) { return -EOPNOTSUPP; } -- cgit v1.2.3 From fe3b81b446d4ecb954f1b9dd191164a78fd278ad Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 4 Apr 2017 17:08:42 -0700 Subject: NFS: Use ERR_CAST() to avoid cross-structure cast When the call to nfs_devname() fails, the error path attempts to retain the error via the mnt variable, but this requires a cast across very different types (char * to struct vfsmount *), which the upcoming structure layout randomization plugin flags as being potentially dangerous in the face of randomization. This is a false positive, but what this code actually wants to do is retain the error value, so this patch explicitly sets it, instead of using what seems to be an unexpected cast. Signed-off-by: Kees Cook Acked-by: Trond Myklebust Reviewed-by: Christoph Hellwig --- fs/nfs/namespace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c index 1a224a33a6c2..e5686be67be8 100644 --- a/fs/nfs/namespace.c +++ b/fs/nfs/namespace.c @@ -246,7 +246,7 @@ struct vfsmount *nfs_do_submount(struct dentry *dentry, struct nfs_fh *fh, devname = nfs_devname(dentry, page, PAGE_SIZE); if (IS_ERR(devname)) - mnt = (struct vfsmount *)devname; + mnt = ERR_CAST(devname); else mnt = nfs_do_clone_mount(NFS_SB(dentry->d_sb), devname, &mountdata); -- cgit v1.2.3 From fee2aa753823860f2b8dfe58d98cafe8e4840855 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Mon, 8 May 2017 14:45:26 -0700 Subject: ntfs: Use ERR_CAST() to avoid cross-structure cast When trying to propagate an error result, the error return path attempts to retain the error, but does this with an open cast across very different types, which the upcoming structure layout randomization plugin flags as being potentially dangerous in the face of randomization. This is a false positive, but what this code actually wants to do is use ERR_CAST() to retain the error value. Cc: Anton Altaparmakov Cc: Andrew Morton Signed-off-by: Kees Cook --- fs/ntfs/namei.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ntfs/namei.c b/fs/ntfs/namei.c index 358258364616..4690cd75d8d7 100644 --- a/fs/ntfs/namei.c +++ b/fs/ntfs/namei.c @@ -159,7 +159,7 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent, PTR_ERR(dent_inode)); kfree(name); /* Return the error code. */ - return (struct dentry *)dent_inode; + return ERR_CAST(dent_inode); } /* It is guaranteed that @name is no longer allocated at this point. */ if (MREF_ERR(mref) == -ENOENT) { -- cgit v1.2.3 From 7585d12f6555fdf4faaefec34ac58b28555b27d0 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Mon, 8 May 2017 14:49:27 -0700 Subject: ocfs2: Use ERR_CAST() to avoid cross-structure cast When trying to propagate an error result, the error return path attempts to retain the error, but does this with an open cast across very different types, which the upcoming structure layout randomization plugin flags as being potentially dangerous in the face of randomization. This is a false positive, but what this code actually wants to do is use ERR_CAST() to retain the error value. Cc: Mark Fasheh Cc: Joel Becker Signed-off-by: Kees Cook --- fs/ocfs2/export.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ocfs2/export.c b/fs/ocfs2/export.c index 827fc9809bc2..9f88188060db 100644 --- a/fs/ocfs2/export.c +++ b/fs/ocfs2/export.c @@ -119,7 +119,7 @@ check_err: if (IS_ERR(inode)) { mlog_errno(PTR_ERR(inode)); - result = (void *)inode; + result = ERR_CAST(inode); goto bail; } -- cgit v1.2.3 From 234041dfe5ca83d5c8122ec1999eaf3f00335d7b Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 4 Apr 2017 22:07:10 -0700 Subject: sgi-xp: Use designated initializers Prepare to mark sensitive kernel structures for randomization by making sure they're using designated initializers. In this case, no initializers are needed (they can be NULL initialized and callers adjusted to check for NULL, which is more efficient than an indirect call). Cc: Robin Holt Signed-off-by: Kees Cook Reviewed-by: Christoph Hellwig --- drivers/misc/sgi-xp/xp.h | 12 +++++++++++- drivers/misc/sgi-xp/xp_main.c | 36 +++++++----------------------------- 2 files changed, 18 insertions(+), 30 deletions(-) diff --git a/drivers/misc/sgi-xp/xp.h b/drivers/misc/sgi-xp/xp.h index c862cd4583cc..b8069eec18cb 100644 --- a/drivers/misc/sgi-xp/xp.h +++ b/drivers/misc/sgi-xp/xp.h @@ -309,6 +309,9 @@ static inline enum xp_retval xpc_send(short partid, int ch_number, u32 flags, void *payload, u16 payload_size) { + if (!xpc_interface.send) + return xpNotLoaded; + return xpc_interface.send(partid, ch_number, flags, payload, payload_size); } @@ -317,6 +320,9 @@ static inline enum xp_retval xpc_send_notify(short partid, int ch_number, u32 flags, void *payload, u16 payload_size, xpc_notify_func func, void *key) { + if (!xpc_interface.send_notify) + return xpNotLoaded; + return xpc_interface.send_notify(partid, ch_number, flags, payload, payload_size, func, key); } @@ -324,12 +330,16 @@ xpc_send_notify(short partid, int ch_number, u32 flags, void *payload, static inline void xpc_received(short partid, int ch_number, void *payload) { - return xpc_interface.received(partid, ch_number, payload); + if (xpc_interface.received) + xpc_interface.received(partid, ch_number, payload); } static inline enum xp_retval xpc_partid_to_nasids(short partid, void *nasids) { + if (!xpc_interface.partid_to_nasids) + return xpNotLoaded; + return xpc_interface.partid_to_nasids(partid, nasids); } diff --git a/drivers/misc/sgi-xp/xp_main.c b/drivers/misc/sgi-xp/xp_main.c index 01be66d02ca8..6d7f557fd1c1 100644 --- a/drivers/misc/sgi-xp/xp_main.c +++ b/drivers/misc/sgi-xp/xp_main.c @@ -69,23 +69,9 @@ struct xpc_registration xpc_registrations[XPC_MAX_NCHANNELS]; EXPORT_SYMBOL_GPL(xpc_registrations); /* - * Initialize the XPC interface to indicate that XPC isn't loaded. + * Initialize the XPC interface to NULL to indicate that XPC isn't loaded. */ -static enum xp_retval -xpc_notloaded(void) -{ - return xpNotLoaded; -} - -struct xpc_interface xpc_interface = { - (void (*)(int))xpc_notloaded, - (void (*)(int))xpc_notloaded, - (enum xp_retval(*)(short, int, u32, void *, u16))xpc_notloaded, - (enum xp_retval(*)(short, int, u32, void *, u16, xpc_notify_func, - void *))xpc_notloaded, - (void (*)(short, int, void *))xpc_notloaded, - (enum xp_retval(*)(short, void *))xpc_notloaded -}; +struct xpc_interface xpc_interface = { }; EXPORT_SYMBOL_GPL(xpc_interface); /* @@ -115,17 +101,7 @@ EXPORT_SYMBOL_GPL(xpc_set_interface); void xpc_clear_interface(void) { - xpc_interface.connect = (void (*)(int))xpc_notloaded; - xpc_interface.disconnect = (void (*)(int))xpc_notloaded; - xpc_interface.send = (enum xp_retval(*)(short, int, u32, void *, u16)) - xpc_notloaded; - xpc_interface.send_notify = (enum xp_retval(*)(short, int, u32, void *, - u16, xpc_notify_func, - void *))xpc_notloaded; - xpc_interface.received = (void (*)(short, int, void *)) - xpc_notloaded; - xpc_interface.partid_to_nasids = (enum xp_retval(*)(short, void *)) - xpc_notloaded; + memset(&xpc_interface, 0, sizeof(xpc_interface)); } EXPORT_SYMBOL_GPL(xpc_clear_interface); @@ -188,7 +164,8 @@ xpc_connect(int ch_number, xpc_channel_func func, void *key, u16 payload_size, mutex_unlock(®istration->mutex); - xpc_interface.connect(ch_number); + if (xpc_interface.connect) + xpc_interface.connect(ch_number); return xpSuccess; } @@ -237,7 +214,8 @@ xpc_disconnect(int ch_number) registration->assigned_limit = 0; registration->idle_limit = 0; - xpc_interface.disconnect(ch_number); + if (xpc_interface.disconnect) + xpc_interface.disconnect(ch_number); mutex_unlock(®istration->mutex); -- cgit v1.2.3 From 2a9d6d26e2b76eee1064d221b49f3ec527546c53 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Sat, 6 May 2017 00:54:07 -0700 Subject: drm/amdgpu: Use designated initializers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The randstruct plugin requires structures that are entirely function pointers be initialized using designated initializers. Cc: Alex Deucher Cc: Christian König Signed-off-by: Kees Cook --- drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c index a4831fe0223b..a2c59a08b2bd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c @@ -220,9 +220,9 @@ static void amdgpu_vram_mgr_debug(struct ttm_mem_type_manager *man, } const struct ttm_mem_type_manager_func amdgpu_vram_mgr_func = { - amdgpu_vram_mgr_init, - amdgpu_vram_mgr_fini, - amdgpu_vram_mgr_new, - amdgpu_vram_mgr_del, - amdgpu_vram_mgr_debug + .init = amdgpu_vram_mgr_init, + .takedown = amdgpu_vram_mgr_fini, + .get_node = amdgpu_vram_mgr_new, + .put_node = amdgpu_vram_mgr_del, + .debug = amdgpu_vram_mgr_debug }; -- cgit v1.2.3 From 3ddd396f6b57cbd5cb034498b5c4cd3dd920cf15 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Sat, 6 May 2017 01:09:00 -0700 Subject: drm/amd/powerplay: Use designated initializers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The randstruct plugin requires designated initializers for structures that are entirely function pointers. Cc: Christian König Cc: Eric Huang Cc: Alex Deucher Signed-off-by: Kees Cook --- drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c index d5f53d04fa08..83e40fe51b62 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c @@ -709,17 +709,17 @@ static int tf_vega10_thermal_disable_alert(struct pp_hwmgr *hwmgr, static struct phm_master_table_item vega10_thermal_start_thermal_controller_master_list[] = { - {NULL, tf_vega10_thermal_initialize}, - {NULL, tf_vega10_thermal_set_temperature_range}, - {NULL, tf_vega10_thermal_enable_alert}, + { .tableFunction = tf_vega10_thermal_initialize }, + { .tableFunction = tf_vega10_thermal_set_temperature_range }, + { .tableFunction = tf_vega10_thermal_enable_alert }, /* We should restrict performance levels to low before we halt the SMC. * On the other hand we are still in boot state when we do this * so it would be pointless. * If this assumption changes we have to revisit this table. */ - {NULL, tf_vega10_thermal_setup_fan_table}, - {NULL, tf_vega10_thermal_start_smc_fan_control}, - {NULL, NULL} + { .tableFunction = tf_vega10_thermal_setup_fan_table }, + { .tableFunction = tf_vega10_thermal_start_smc_fan_control }, + { } }; static struct phm_master_table_header @@ -731,10 +731,10 @@ vega10_thermal_start_thermal_controller_master = { static struct phm_master_table_item vega10_thermal_set_temperature_range_master_list[] = { - {NULL, tf_vega10_thermal_disable_alert}, - {NULL, tf_vega10_thermal_set_temperature_range}, - {NULL, tf_vega10_thermal_enable_alert}, - {NULL, NULL} + { .tableFunction = tf_vega10_thermal_disable_alert }, + { .tableFunction = tf_vega10_thermal_set_temperature_range }, + { .tableFunction = tf_vega10_thermal_enable_alert }, + { } }; struct phm_master_table_header -- cgit v1.2.3 From 243dd05d39aa14fac2ffde75cc66dee3270896f8 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Sat, 6 May 2017 01:10:06 -0700 Subject: mtk-vcodec: Use designated initializers The randstruct plugin requires designated initializers for structures that are entirely function pointers. Cc: Wu-Cheng Li Cc: Tiffany Lin Cc: Hans Verkuil Cc: Mauro Carvalho Chehab Signed-off-by: Kees Cook --- drivers/media/platform/mtk-vcodec/vdec/vdec_h264_if.c | 8 ++++---- drivers/media/platform/mtk-vcodec/vdec/vdec_vp8_if.c | 8 ++++---- drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/media/platform/mtk-vcodec/vdec/vdec_h264_if.c b/drivers/media/platform/mtk-vcodec/vdec/vdec_h264_if.c index 57a842ff3097..b7731b18ecae 100644 --- a/drivers/media/platform/mtk-vcodec/vdec/vdec_h264_if.c +++ b/drivers/media/platform/mtk-vcodec/vdec/vdec_h264_if.c @@ -493,10 +493,10 @@ static int vdec_h264_get_param(unsigned long h_vdec, } static struct vdec_common_if vdec_h264_if = { - vdec_h264_init, - vdec_h264_decode, - vdec_h264_get_param, - vdec_h264_deinit, + .init = vdec_h264_init, + .decode = vdec_h264_decode, + .get_param = vdec_h264_get_param, + .deinit = vdec_h264_deinit, }; struct vdec_common_if *get_h264_dec_comm_if(void); diff --git a/drivers/media/platform/mtk-vcodec/vdec/vdec_vp8_if.c b/drivers/media/platform/mtk-vcodec/vdec/vdec_vp8_if.c index 6e7a62ae0842..b9fad6a48879 100644 --- a/drivers/media/platform/mtk-vcodec/vdec/vdec_vp8_if.c +++ b/drivers/media/platform/mtk-vcodec/vdec/vdec_vp8_if.c @@ -620,10 +620,10 @@ static void vdec_vp8_deinit(unsigned long h_vdec) } static struct vdec_common_if vdec_vp8_if = { - vdec_vp8_init, - vdec_vp8_decode, - vdec_vp8_get_param, - vdec_vp8_deinit, + .init = vdec_vp8_init, + .decode = vdec_vp8_decode, + .get_param = vdec_vp8_get_param, + .deinit = vdec_vp8_deinit, }; struct vdec_common_if *get_vp8_dec_comm_if(void); diff --git a/drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c b/drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c index 5539b1853f16..1daee1207469 100644 --- a/drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c +++ b/drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c @@ -979,10 +979,10 @@ static int vdec_vp9_get_param(unsigned long h_vdec, } static struct vdec_common_if vdec_vp9_if = { - vdec_vp9_init, - vdec_vp9_decode, - vdec_vp9_get_param, - vdec_vp9_deinit, + .init = vdec_vp9_init, + .decode = vdec_vp9_decode, + .get_param = vdec_vp9_get_param, + .deinit = vdec_vp9_deinit, }; struct vdec_common_if *get_vp9_dec_comm_if(void); -- cgit v1.2.3 From 5ed02dbb497422bf225783f46e6eadd237d23d6b Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 28 May 2017 17:20:53 -0700 Subject: Linux 4.12-rc3 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 63e10bd4f14a..470bd4d9513a 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 4 PATCHLEVEL = 12 SUBLEVEL = 0 -EXTRAVERSION = -rc2 +EXTRAVERSION = -rc3 NAME = Fearless Coyote # *DOCUMENTATION* -- cgit v1.2.3 From 4013ef48798ae954530bdb8971d3794333e46526 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 8 Mar 2017 15:12:53 +0100 Subject: drm/exynos: Merge pre/postclose hooks Again no apparent explanation for the split except hysterical raisins. Cc: Inki Dae Cc: Joonyoung Shim Cc: Seung-Woo Kim Cc: Kyungmin Park Signed-off-by: Daniel Vetter Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos_drm_drv.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index 09d3c4c3c858..50294a7bd29d 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -82,14 +82,9 @@ err_file_priv_free: return ret; } -static void exynos_drm_preclose(struct drm_device *dev, - struct drm_file *file) -{ - exynos_drm_subdrv_close(dev, file); -} - static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file) { + exynos_drm_subdrv_close(dev, file); kfree(file->driver_priv); file->driver_priv = NULL; } @@ -145,7 +140,6 @@ static struct drm_driver exynos_drm_driver = { .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | DRIVER_ATOMIC | DRIVER_RENDER, .open = exynos_drm_open, - .preclose = exynos_drm_preclose, .lastclose = exynos_drm_lastclose, .postclose = exynos_drm_postclose, .gem_free_object_unlocked = exynos_drm_gem_free_object, -- cgit v1.2.3 From f2921d8c4899a3d9d7c6326315c24efea2c9efd9 Mon Sep 17 00:00:00 2001 From: Hoegeun Kwon Date: Thu, 13 Apr 2017 15:05:26 +0900 Subject: drm/exynos: dsi: Fix the parse_dt function The dsi + panel is a parental relationship, so OF grpah is not needed. Therefore, the current dsi_parse_dt function will throw an error, because there is no linked OF graph for the case fimd + dsi + panel. Parse the Pll burst and esc clock frequency properties in dsi_parse_dt() and create a bridge_node only if there is an OF graph associated with dsi. Signed-off-by: Hoegeun Kwon Reviewed-by: Andrzej Hajda Reviewed-by: Andi Shyti Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos_drm_dsi.c | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index fc4fda738906..24ab77c674ec 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -1633,7 +1633,6 @@ static int exynos_dsi_parse_dt(struct exynos_dsi *dsi) { struct device *dev = dsi->dev; struct device_node *node = dev->of_node; - struct device_node *ep; int ret; ret = exynos_dsi_of_read_u32(node, "samsung,pll-clock-frequency", @@ -1641,32 +1640,21 @@ static int exynos_dsi_parse_dt(struct exynos_dsi *dsi) if (ret < 0) return ret; - ep = of_graph_get_endpoint_by_regs(node, DSI_PORT_OUT, 0); - if (!ep) { - dev_err(dev, "no output port with endpoint specified\n"); - return -EINVAL; - } - - ret = exynos_dsi_of_read_u32(ep, "samsung,burst-clock-frequency", + ret = exynos_dsi_of_read_u32(node, "samsung,burst-clock-frequency", &dsi->burst_clk_rate); if (ret < 0) - goto end; + return ret; - ret = exynos_dsi_of_read_u32(ep, "samsung,esc-clock-frequency", + ret = exynos_dsi_of_read_u32(node, "samsung,esc-clock-frequency", &dsi->esc_clk_rate); if (ret < 0) - goto end; - - of_node_put(ep); + return ret; dsi->bridge_node = of_graph_get_remote_node(node, DSI_PORT_OUT, 0); if (!dsi->bridge_node) return -EINVAL; -end: - of_node_put(ep); - - return ret; + return 0; } static int exynos_dsi_bind(struct device *dev, struct device *master, -- cgit v1.2.3 From 70505c2ef94b7584dc24d6eaaeb0fc335b99813a Mon Sep 17 00:00:00 2001 From: Hoegeun Kwon Date: Fri, 26 May 2017 10:02:01 +0900 Subject: drm/exynos: dsi: Remove bridge node reference in removal Since bridge node is referenced during in the probe, it should be released on removal. Suggested-by: Andrzej Hajda Signed-off-by: Hoegeun Kwon Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos_drm_dsi.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index 24ab77c674ec..d404de86d5f9 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -1805,6 +1805,10 @@ static int exynos_dsi_probe(struct platform_device *pdev) static int exynos_dsi_remove(struct platform_device *pdev) { + struct exynos_dsi *dsi = platform_get_drvdata(pdev); + + of_node_put(dsi->bridge_node); + pm_runtime_disable(&pdev->dev); component_del(&pdev->dev, &exynos_dsi_component_ops); -- cgit v1.2.3 From e379cbee79a8abb8e9b4da63187884939852ddb4 Mon Sep 17 00:00:00 2001 From: Inki Dae Date: Mon, 29 May 2017 09:59:05 +0900 Subject: drm/exynos: clean up description of exynos_drm_crtc This patch removes unnecessary descriptions on exynos_drm_crtc structure and adds one description which specifies what pipe_clk member does. pipe_clk support had been added by below patch without any description, drm/exynos: add support for pipeline clock to the framework Commit-id : f26b9343f582f44ec920474d71b4b2220b1ed9a8 Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos_drm_drv.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index cb3176930596..39c740572034 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -160,12 +160,9 @@ struct exynos_drm_clk { * drm framework doesn't support multiple irq yet. * we can refer to the crtc to current hardware interrupt occurred through * this pipe value. - * @enabled: if the crtc is enabled or not - * @event: vblank event that is currently queued for flip - * @wait_update: wait all pending planes updates to finish - * @pending_update: number of pending plane updates in this crtc * @ops: pointer to callbacks for exynos drm specific functionality * @ctx: A pointer to the crtc's implementation specific context + * @pipe_clk: A pointer to the crtc's pipeline clock. */ struct exynos_drm_crtc { struct drm_crtc base; -- cgit v1.2.3 From dac6ca243c4c49a9ca7507d3d66140ebfac8b04b Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Sun, 28 May 2017 22:04:14 +0200 Subject: x86/microcode/AMD: Change load_microcode_amd()'s param to bool to fix preemptibility bug With CONFIG_DEBUG_PREEMPT enabled, I get: BUG: using smp_processor_id() in preemptible [00000000] code: swapper/0/1 caller is debug_smp_processor_id CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.12.0-rc2+ #2 Call Trace: dump_stack check_preemption_disabled debug_smp_processor_id save_microcode_in_initrd_amd ? microcode_init save_microcode_in_initrd ... because, well, it says it above, we're using smp_processor_id() in preemptible code. But passing the CPU number is not really needed. It is only used to determine whether we're on the BSP, and, if so, to save the microcode patch for early loading. [ We don't absolutely need to do it on the BSP but we do that customarily there. ] Instead, convert that function parameter to a boolean which denotes whether the patch should be saved or not, thereby avoiding the use of smp_processor_id() in preemptible code. Signed-off-by: Borislav Petkov Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/20170528200414.31305-1-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/microcode/amd.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c index 45db4d2ebd01..e9f4d762aa5b 100644 --- a/arch/x86/kernel/cpu/microcode/amd.c +++ b/arch/x86/kernel/cpu/microcode/amd.c @@ -320,7 +320,7 @@ void load_ucode_amd_ap(unsigned int cpuid_1_eax) } static enum ucode_state -load_microcode_amd(int cpu, u8 family, const u8 *data, size_t size); +load_microcode_amd(bool save, u8 family, const u8 *data, size_t size); int __init save_microcode_in_initrd_amd(unsigned int cpuid_1_eax) { @@ -338,8 +338,7 @@ int __init save_microcode_in_initrd_amd(unsigned int cpuid_1_eax) if (!desc.mc) return -EINVAL; - ret = load_microcode_amd(smp_processor_id(), x86_family(cpuid_1_eax), - desc.data, desc.size); + ret = load_microcode_amd(true, x86_family(cpuid_1_eax), desc.data, desc.size); if (ret != UCODE_OK) return -EINVAL; @@ -675,7 +674,7 @@ static enum ucode_state __load_microcode_amd(u8 family, const u8 *data, } static enum ucode_state -load_microcode_amd(int cpu, u8 family, const u8 *data, size_t size) +load_microcode_amd(bool save, u8 family, const u8 *data, size_t size) { enum ucode_state ret; @@ -689,8 +688,8 @@ load_microcode_amd(int cpu, u8 family, const u8 *data, size_t size) #ifdef CONFIG_X86_32 /* save BSP's matching patch for early load */ - if (cpu_data(cpu).cpu_index == boot_cpu_data.cpu_index) { - struct ucode_patch *p = find_patch(cpu); + if (save) { + struct ucode_patch *p = find_patch(0); if (p) { memset(amd_ucode_patch, 0, PATCH_MAX_SIZE); memcpy(amd_ucode_patch, p->data, min_t(u32, ksize(p->data), @@ -722,11 +721,12 @@ static enum ucode_state request_microcode_amd(int cpu, struct device *device, { char fw_name[36] = "amd-ucode/microcode_amd.bin"; struct cpuinfo_x86 *c = &cpu_data(cpu); + bool bsp = c->cpu_index == boot_cpu_data.cpu_index; enum ucode_state ret = UCODE_NFOUND; const struct firmware *fw; /* reload ucode container only on the boot cpu */ - if (!refresh_fw || c->cpu_index != boot_cpu_data.cpu_index) + if (!refresh_fw || !bsp) return UCODE_OK; if (c->x86 >= 0x15) @@ -743,7 +743,7 @@ static enum ucode_state request_microcode_amd(int cpu, struct device *device, goto fw_release; } - ret = load_microcode_amd(cpu, c->x86, fw->data, fw->size); + ret = load_microcode_amd(bsp, c->x86, fw->data, fw->size); fw_release: release_firmware(fw); -- cgit v1.2.3 From 5d9070b1f0fc9a159a9a3240c43004828408444b Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Sun, 28 May 2017 11:03:42 +0200 Subject: x86/debug/32: Convert a smp_processor_id() call to raw to avoid DEBUG_PREEMPT warning ... to raw_smp_processor_id() to not trip the BUG: using smp_processor_id() in preemptible [00000000] code: swapper/0/1 check. The reasoning behind it is that __warn() already uses the raw_ variants but the show_regs() path on 32-bit doesn't. Signed-off-by: Borislav Petkov Cc: Josh Poimboeuf Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/20170528092212.fiod7kygpjm23m3o@pd.tnic Signed-off-by: Ingo Molnar --- arch/x86/kernel/process_32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index ff40e74c9181..ffeae818aa7a 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c @@ -78,7 +78,7 @@ void __show_regs(struct pt_regs *regs, int all) printk(KERN_DEFAULT "EIP: %pS\n", (void *)regs->ip); printk(KERN_DEFAULT "EFLAGS: %08lx CPU: %d\n", regs->flags, - smp_processor_id()); + raw_smp_processor_id()); printk(KERN_DEFAULT "EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n", regs->ax, regs->bx, regs->cx, regs->dx); -- cgit v1.2.3 From cc7a938f5f308eeb6f8fe3cec28e1800aa81facb Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 24 May 2017 17:39:03 +0200 Subject: ARM: at91: select CONFIG_ARM_CPU_SUSPEND The reference to cpu_resume requires the corresponding generic code to be enabled when CONFIG_PM is set: arch/arm/mach-at91/pm.o: In function `sama5d2_pm_init': pm.c:(.init.text+0x5e8): undefined reference to `cpu_resume' Fixes: 24a0f5c539f9 ("ARM: at91: pm: Add sama5d2 backup mode") Signed-off-by: Arnd Bergmann Signed-off-by: Alexandre Belloni --- arch/arm/mach-at91/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 841e924143f9..cbd959b73654 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -1,6 +1,7 @@ menuconfig ARCH_AT91 bool "Atmel SoCs" depends on ARCH_MULTI_V4T || ARCH_MULTI_V5 || ARCH_MULTI_V7 + select ARM_CPU_SUSPEND if PM select COMMON_CLK_AT91 select GPIOLIB select PINCTRL -- cgit v1.2.3 From 6ac56951dc10232e24419f6972fc8131dd0166e0 Mon Sep 17 00:00:00 2001 From: Ilya Dryomov Date: Mon, 22 May 2017 19:59:24 +0200 Subject: rbd: implement REQ_OP_WRITE_ZEROES Commit 93c1defedcae ("rbd: remove the discard_zeroes_data flag") explicitly didn't implement REQ_OP_WRITE_ZEROES for rbd, while the following commit 48920ff2a5a9 ("block: remove the discard_zeroes_data flag") dropped ->discard_zeroes_data in favor of REQ_OP_WRITE_ZEROES. rbd does support efficient zeroing via CEPH_OSD_OP_ZERO opcode and will release either some or all blocks depending on whether the zeroing request is rbd_obj_bytes() aligned. This is how we currently implement discards, so REQ_OP_WRITE_ZEROES can be identical to REQ_OP_DISCARD for now. Caveats: - REQ_NOUNMAP is ignored, but AFAICT that's true of at least two other current implementations - nvme and loop - there is no ->write_zeroes_alignment and blk_bio_write_zeroes_split() is hence less helpful than blk_bio_discard_split(), but this can (and should) be fixed on the rbd side In the future we will split these into two code paths to respect REQ_NOUNMAP on zeroout and save on zeroing blocks that couldn't be released on discard. Fixes: 93c1defedcae ("rbd: remove the discard_zeroes_data flag") Signed-off-by: Ilya Dryomov Reviewed-by: Jason Dillaman Reviewed-by: Christoph Hellwig --- drivers/block/rbd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 454bf9c34882..c16f74547804 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -4023,6 +4023,7 @@ static void rbd_queue_workfn(struct work_struct *work) switch (req_op(rq)) { case REQ_OP_DISCARD: + case REQ_OP_WRITE_ZEROES: op_type = OBJ_OP_DISCARD; break; case REQ_OP_WRITE: @@ -4420,6 +4421,7 @@ static int rbd_init_disk(struct rbd_device *rbd_dev) q->limits.discard_granularity = segment_size; q->limits.discard_alignment = segment_size; blk_queue_max_discard_sectors(q, segment_size / SECTOR_SIZE); + blk_queue_max_write_zeroes_sectors(q, segment_size / SECTOR_SIZE); if (!ceph_test_opt(rbd_dev->rbd_client->client, NOCRC)) q->backing_dev_info->capabilities |= BDI_CAP_STABLE_WRITES; -- cgit v1.2.3 From f3a1568582cc207663a4d5e37da790334372855b Mon Sep 17 00:00:00 2001 From: Amir Goldstein Date: Wed, 24 May 2017 15:29:33 +0300 Subject: ovl: mark upper merge dir with type origin entries "impure" An upper dir is marked "impure" to let ovl_iterate() know that this directory may contain non pure upper entries whose d_ino may need to be read from the origin inode. We already mark a non-merge dir "impure" when moving a non-pure child entry inside it, to let ovl_iterate() know not to iterate the non-merge dir directly. Mark also a merge dir "impure" when moving a non-pure child entry inside it and when copying up a child entry inside it. This can be used to optimize ovl_iterate() to perform a "pure merge" of upper and lower directories, merging the content of the directories, without having to read d_ino from origin inodes. Signed-off-by: Amir Goldstein Signed-off-by: Miklos Szeredi --- fs/overlayfs/copy_up.c | 5 +++++ fs/overlayfs/dir.c | 31 +++++-------------------------- fs/overlayfs/namei.c | 20 -------------------- fs/overlayfs/overlayfs.h | 15 +++++++++++---- fs/overlayfs/super.c | 5 ++++- fs/overlayfs/util.c | 42 +++++++++++++++++++++++++++++++++++------- 6 files changed, 60 insertions(+), 58 deletions(-) diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c index 843ed2a2d7db..7a44533f4bbf 100644 --- a/fs/overlayfs/copy_up.c +++ b/fs/overlayfs/copy_up.c @@ -459,6 +459,11 @@ static int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry, ovl_path_upper(parent, &parentpath); upperdir = parentpath.dentry; + /* Mark parent "impure" because it may now contain non-pure upper */ + err = ovl_set_impure(parent, upperdir); + if (err) + return err; + err = vfs_getattr(&parentpath, &pstat, STATX_ATIME | STATX_MTIME, AT_STATX_SYNC_AS_STAT); if (err) diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c index f2a118ba00e4..a63a71656e9b 100644 --- a/fs/overlayfs/dir.c +++ b/fs/overlayfs/dir.c @@ -149,22 +149,6 @@ static int ovl_set_opaque(struct dentry *dentry, struct dentry *upperdentry) return ovl_set_opaque_xerr(dentry, upperdentry, -EIO); } -static int ovl_set_impure(struct dentry *dentry, struct dentry *upperdentry) -{ - int err; - - /* - * Do not fail when upper doesn't support xattrs. - * Upper inodes won't have origin nor redirect xattr anyway. - */ - err = ovl_check_setxattr(dentry, upperdentry, OVL_XATTR_IMPURE, - "y", 1, 0); - if (!err) - ovl_dentry_set_impure(dentry); - - return err; -} - /* Common operations required to be done after creation of file on upper */ static void ovl_instantiate(struct dentry *dentry, struct inode *inode, struct dentry *newdentry, bool hardlink) @@ -976,21 +960,16 @@ static int ovl_rename(struct inode *olddir, struct dentry *old, if (!samedir) { /* * When moving a merge dir or non-dir with copy up origin into - * a non-merge upper dir (a.k.a pure upper dir), we are making - * the target parent dir "impure". ovl_iterate() iterates pure - * upper dirs directly, because there is no need to filter out - * whiteouts and merge dir content with lower dir. But for the - * case of an "impure" upper dir, ovl_iterate() cannot iterate - * the real directory directly, because it looks for the inode - * numbers to fill d_ino in the entries origin inode. + * a new parent, we are marking the new parent dir "impure". + * When ovl_iterate() iterates an "impure" upper dir, it will + * lookup the origin inodes of the entries to fill d_ino. */ - if (ovl_type_origin(old) && !ovl_type_merge(new->d_parent)) { + if (ovl_type_origin(old)) { err = ovl_set_impure(new->d_parent, new_upperdir); if (err) goto out_revert_creds; } - if (!overwrite && ovl_type_origin(new) && - !ovl_type_merge(old->d_parent)) { + if (!overwrite && ovl_type_origin(new)) { err = ovl_set_impure(old->d_parent, old_upperdir); if (err) goto out_revert_creds; diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c index 0c72a5909db2..f3136c31e72a 100644 --- a/fs/overlayfs/namei.c +++ b/fs/overlayfs/namei.c @@ -167,31 +167,11 @@ invalid: goto out; } -static bool ovl_check_dir_xattr(struct dentry *dentry, const char *name) -{ - int res; - char val; - - if (!d_is_dir(dentry)) - return false; - - res = vfs_getxattr(dentry, name, &val, 1); - if (res == 1 && val == 'y') - return true; - - return false; -} - static bool ovl_is_opaquedir(struct dentry *dentry) { return ovl_check_dir_xattr(dentry, OVL_XATTR_OPAQUE); } -static bool ovl_is_impuredir(struct dentry *dentry) -{ - return ovl_check_dir_xattr(dentry, OVL_XATTR_IMPURE); -} - static int ovl_lookup_single(struct dentry *base, struct ovl_lookup_data *d, const char *name, unsigned int namelen, size_t prelen, const char *post, diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index a9fb958fd5d4..0623cebeefff 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h @@ -207,7 +207,6 @@ bool ovl_dentry_is_opaque(struct dentry *dentry); bool ovl_dentry_is_impure(struct dentry *dentry); bool ovl_dentry_is_whiteout(struct dentry *dentry); void ovl_dentry_set_opaque(struct dentry *dentry); -void ovl_dentry_set_impure(struct dentry *dentry); bool ovl_redirect_dir(struct super_block *sb); const char *ovl_dentry_get_redirect(struct dentry *dentry); void ovl_dentry_set_redirect(struct dentry *dentry, const char *redirect); @@ -221,6 +220,17 @@ bool ovl_is_whiteout(struct dentry *dentry); struct file *ovl_path_open(struct path *path, int flags); int ovl_copy_up_start(struct dentry *dentry); void ovl_copy_up_end(struct dentry *dentry); +bool ovl_check_dir_xattr(struct dentry *dentry, const char *name); +int ovl_check_setxattr(struct dentry *dentry, struct dentry *upperdentry, + const char *name, const void *value, size_t size, + int xerr); +int ovl_set_impure(struct dentry *dentry, struct dentry *upperdentry); + +static inline bool ovl_is_impuredir(struct dentry *dentry) +{ + return ovl_check_dir_xattr(dentry, OVL_XATTR_IMPURE); +} + /* namei.c */ int ovl_path_next(int idx, struct dentry *dentry, struct path *path); @@ -281,6 +291,3 @@ int ovl_copy_up(struct dentry *dentry); int ovl_copy_up_flags(struct dentry *dentry, int flags); int ovl_copy_xattr(struct dentry *old, struct dentry *new); int ovl_set_attr(struct dentry *upper, struct kstat *stat); -int ovl_check_setxattr(struct dentry *dentry, struct dentry *upperdentry, - const char *name, const void *value, size_t size, - int xerr); diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index f1647626a882..4882ffb37bae 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -974,7 +974,10 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) path_put(&workpath); kfree(lowertmp); - oe->__upperdentry = upperpath.dentry; + if (upperpath.dentry) { + oe->__upperdentry = upperpath.dentry; + oe->impure = ovl_is_impuredir(upperpath.dentry); + } for (i = 0; i < numlower; i++) { oe->lowerstack[i].dentry = stack[i].dentry; oe->lowerstack[i].mnt = ufs->lower_mnt[i]; diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c index e0dfb07d5457..809048913889 100644 --- a/fs/overlayfs/util.c +++ b/fs/overlayfs/util.c @@ -194,13 +194,6 @@ void ovl_dentry_set_opaque(struct dentry *dentry) oe->opaque = true; } -void ovl_dentry_set_impure(struct dentry *dentry) -{ - struct ovl_entry *oe = dentry->d_fsdata; - - oe->impure = true; -} - bool ovl_redirect_dir(struct super_block *sb) { struct ovl_fs *ofs = sb->s_fs_info; @@ -311,6 +304,21 @@ void ovl_copy_up_end(struct dentry *dentry) spin_unlock(&ofs->copyup_wq.lock); } +bool ovl_check_dir_xattr(struct dentry *dentry, const char *name) +{ + int res; + char val; + + if (!d_is_dir(dentry)) + return false; + + res = vfs_getxattr(dentry, name, &val, 1); + if (res == 1 && val == 'y') + return true; + + return false; +} + int ovl_check_setxattr(struct dentry *dentry, struct dentry *upperdentry, const char *name, const void *value, size_t size, int xerr) @@ -331,3 +339,23 @@ int ovl_check_setxattr(struct dentry *dentry, struct dentry *upperdentry, return err; } + +int ovl_set_impure(struct dentry *dentry, struct dentry *upperdentry) +{ + int err; + struct ovl_entry *oe = dentry->d_fsdata; + + if (oe->impure) + return 0; + + /* + * Do not fail when upper doesn't support xattrs. + * Upper inodes won't have origin nor redirect xattr anyway. + */ + err = ovl_check_setxattr(dentry, upperdentry, OVL_XATTR_IMPURE, + "y", 1, 0); + if (!err) + oe->impure = true; + + return err; +} -- cgit v1.2.3 From 118b90f3f18e733c99f0e8b98ea31a815ffc4d14 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 18 May 2017 14:10:22 +0300 Subject: drm/dp: add helper for reading DP sink/branch device desc from DPCD Reviewed-by: Daniel Vetter Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/acba54da7d80eafea9e59a893e27e3c31028c0ba.1495105635.git.jani.nikula@intel.com --- drivers/gpu/drm/drm_dp_helper.c | 35 +++++++++++++++++++++++++++++++++++ include/drm/drm_dp_helper.h | 19 +++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 3e5f52110ea1..52e0ca9a5bb1 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -1208,3 +1208,38 @@ int drm_dp_stop_crc(struct drm_dp_aux *aux) return 0; } EXPORT_SYMBOL(drm_dp_stop_crc); + +/** + * drm_dp_read_desc - read sink/branch descriptor from DPCD + * @aux: DisplayPort AUX channel + * @desc: Device decriptor to fill from DPCD + * @is_branch: true for branch devices, false for sink devices + * + * Read DPCD 0x400 (sink) or 0x500 (branch) into @desc. Also debug log the + * identification. + * + * Returns 0 on success or a negative error code on failure. + */ +int drm_dp_read_desc(struct drm_dp_aux *aux, struct drm_dp_desc *desc, + bool is_branch) +{ + struct drm_dp_dpcd_ident *ident = &desc->ident; + unsigned int offset = is_branch ? DP_BRANCH_OUI : DP_SINK_OUI; + int ret, dev_id_len; + + ret = drm_dp_dpcd_read(aux, offset, ident, sizeof(*ident)); + if (ret < 0) + return ret; + + dev_id_len = strnlen(ident->device_id, sizeof(ident->device_id)); + + DRM_DEBUG_KMS("DP %s: OUI %*phD dev-ID %*pE HW-rev %d.%d SW-rev %d.%d\n", + is_branch ? "branch" : "sink", + (int)sizeof(ident->oui), ident->oui, + dev_id_len, ident->device_id, + ident->hw_rev >> 4, ident->hw_rev & 0xf, + ident->sw_major_rev, ident->sw_minor_rev); + + return 0; +} +EXPORT_SYMBOL(drm_dp_read_desc); diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index c0bd0d7651a9..84502da177a1 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -913,4 +913,23 @@ void drm_dp_aux_unregister(struct drm_dp_aux *aux); int drm_dp_start_crc(struct drm_dp_aux *aux, struct drm_crtc *crtc); int drm_dp_stop_crc(struct drm_dp_aux *aux); +struct drm_dp_dpcd_ident { + u8 oui[3]; + u8 device_id[6]; + u8 hw_rev; + u8 sw_major_rev; + u8 sw_minor_rev; +} __packed; + +/** + * struct drm_dp_desc - DP branch/sink device descriptor + * @ident: DP device identification from DPCD 0x400 (sink) or 0x500 (branch). + */ +struct drm_dp_desc { + struct drm_dp_dpcd_ident ident; +}; + +int drm_dp_read_desc(struct drm_dp_aux *aux, struct drm_dp_desc *desc, + bool is_branch); + #endif /* _DRM_DP_HELPER_H_ */ -- cgit v1.2.3 From 84c367533bd24108e5392b355280647a4a2893ac Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 18 May 2017 14:10:23 +0300 Subject: drm/i915: use drm DP helper to read DPCD desc Switch to using the common DP helpers instead of using our own. v2: also remove leftover struct intel_dp_desc (Daniel) Reviewed-by: Daniel Vetter Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_dp.c | 37 ++++--------------------------------- drivers/gpu/drm/i915/intel_drv.h | 13 +------------ drivers/gpu/drm/i915/intel_lspcon.c | 2 +- 3 files changed, 6 insertions(+), 46 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index ee77b519835c..5ce45d98da78 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1507,37 +1507,6 @@ static void intel_dp_print_rates(struct intel_dp *intel_dp) DRM_DEBUG_KMS("common rates: %s\n", str); } -bool -__intel_dp_read_desc(struct intel_dp *intel_dp, struct intel_dp_desc *desc) -{ - u32 base = drm_dp_is_branch(intel_dp->dpcd) ? DP_BRANCH_OUI : - DP_SINK_OUI; - - return drm_dp_dpcd_read(&intel_dp->aux, base, desc, sizeof(*desc)) == - sizeof(*desc); -} - -bool intel_dp_read_desc(struct intel_dp *intel_dp) -{ - struct intel_dp_desc *desc = &intel_dp->desc; - bool oui_sup = intel_dp->dpcd[DP_DOWN_STREAM_PORT_COUNT] & - DP_OUI_SUPPORT; - int dev_id_len; - - if (!__intel_dp_read_desc(intel_dp, desc)) - return false; - - dev_id_len = strnlen(desc->device_id, sizeof(desc->device_id)); - DRM_DEBUG_KMS("DP %s: OUI %*phD%s dev-ID %*pE HW-rev %d.%d SW-rev %d.%d\n", - drm_dp_is_branch(intel_dp->dpcd) ? "branch" : "sink", - (int)sizeof(desc->oui), desc->oui, oui_sup ? "" : "(NS)", - dev_id_len, desc->device_id, - desc->hw_rev >> 4, desc->hw_rev & 0xf, - desc->sw_major_rev, desc->sw_minor_rev); - - return true; -} - static int rate_to_index(int find, const int *rates) { int i = 0; @@ -3622,7 +3591,8 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp) if (!intel_dp_read_dpcd(intel_dp)) return false; - intel_dp_read_desc(intel_dp); + drm_dp_read_desc(&intel_dp->aux, &intel_dp->desc, + drm_dp_is_branch(intel_dp->dpcd)); if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11) dev_priv->no_aux_handshake = intel_dp->dpcd[DP_MAX_DOWNSPREAD] & @@ -4624,7 +4594,8 @@ intel_dp_long_pulse(struct intel_connector *intel_connector) intel_dp_print_rates(intel_dp); - intel_dp_read_desc(intel_dp); + drm_dp_read_desc(&intel_dp->aux, &intel_dp->desc, + drm_dp_is_branch(intel_dp->dpcd)); intel_dp_configure_mst(intel_dp); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index aaee3949a422..f630c7af5020 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -906,14 +906,6 @@ enum link_m_n_set { M2_N2 }; -struct intel_dp_desc { - u8 oui[3]; - u8 device_id[6]; - u8 hw_rev; - u8 sw_major_rev; - u8 sw_minor_rev; -} __packed; - struct intel_dp_compliance_data { unsigned long edid; uint8_t video_pattern; @@ -957,7 +949,7 @@ struct intel_dp { /* Max link BW for the sink as per DPCD registers */ int max_sink_link_bw; /* sink or branch descriptor */ - struct intel_dp_desc desc; + struct drm_dp_desc desc; struct drm_dp_aux aux; enum intel_display_power_domain aux_power_domain; uint8_t train_set[4]; @@ -1532,9 +1524,6 @@ static inline unsigned int intel_dp_unused_lane_mask(int lane_count) } bool intel_dp_read_dpcd(struct intel_dp *intel_dp); -bool __intel_dp_read_desc(struct intel_dp *intel_dp, - struct intel_dp_desc *desc); -bool intel_dp_read_desc(struct intel_dp *intel_dp); int intel_dp_link_required(int pixel_clock, int bpp); int intel_dp_max_data_rate(int max_link_clock, int max_lanes); bool intel_digital_port_connected(struct drm_i915_private *dev_priv, diff --git a/drivers/gpu/drm/i915/intel_lspcon.c b/drivers/gpu/drm/i915/intel_lspcon.c index 71cbe9c08932..5abef482eacf 100644 --- a/drivers/gpu/drm/i915/intel_lspcon.c +++ b/drivers/gpu/drm/i915/intel_lspcon.c @@ -240,7 +240,7 @@ bool lspcon_init(struct intel_digital_port *intel_dig_port) return false; } - intel_dp_read_desc(dp); + drm_dp_read_desc(&dp->aux, &dp->desc, drm_dp_is_branch(dp->dpcd)); DRM_DEBUG_KMS("Success: LSPCON init\n"); return true; -- cgit v1.2.3 From 76fa998acd86b6b40d0217e12af39c2406bdcd2b Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 18 May 2017 14:10:24 +0300 Subject: drm/dp: start a DPCD based DP sink/branch device quirk database MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Face the fact, there are Display Port sink and branch devices out there in the wild that don't follow the Display Port specifications, or they have bugs, or just otherwise require special treatment. Start a common quirk database the drivers can query based on the DP device identification. At least for now, we leave the workarounds for the drivers to implement as they see fit. For starters, add a branch device that can't handle full 24-bit main link Mdiv and Ndiv main link attributes properly. Naturally, the workaround of reducing main link attributes for all devices ended up in regressions for other devices. So here we are. v2: Rebase on DRM DP desc read helpers v3: Fix the OUI memcmp blunder (Clint) Cc: Ville Syrjälä Cc: Dhinakaran Pandiyan Cc: Clint Taylor Cc: Adam Jackson Cc: Harry Wentland Tested-by: Clinton Taylor Reviewed-by: Clinton Taylor Reviewed-by: Daniel Vetter # v2 Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/91ec198dd95258dbf3bee2f6be739e0da73b4fdd.1495105635.git.jani.nikula@intel.com --- drivers/gpu/drm/drm_dp_helper.c | 52 +++++++++++++++++++++++++++++++++++++++-- include/drm/drm_dp_helper.h | 32 +++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 52e0ca9a5bb1..213fb837e1c4 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -1209,6 +1209,51 @@ int drm_dp_stop_crc(struct drm_dp_aux *aux) } EXPORT_SYMBOL(drm_dp_stop_crc); +struct dpcd_quirk { + u8 oui[3]; + bool is_branch; + u32 quirks; +}; + +#define OUI(first, second, third) { (first), (second), (third) } + +static const struct dpcd_quirk dpcd_quirk_list[] = { + /* Analogix 7737 needs reduced M and N at HBR2 link rates */ + { OUI(0x00, 0x22, 0xb9), true, BIT(DP_DPCD_QUIRK_LIMITED_M_N) }, +}; + +#undef OUI + +/* + * Get a bit mask of DPCD quirks for the sink/branch device identified by + * ident. The quirk data is shared but it's up to the drivers to act on the + * data. + * + * For now, only the OUI (first three bytes) is used, but this may be extended + * to device identification string and hardware/firmware revisions later. + */ +static u32 +drm_dp_get_quirks(const struct drm_dp_dpcd_ident *ident, bool is_branch) +{ + const struct dpcd_quirk *quirk; + u32 quirks = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(dpcd_quirk_list); i++) { + quirk = &dpcd_quirk_list[i]; + + if (quirk->is_branch != is_branch) + continue; + + if (memcmp(quirk->oui, ident->oui, sizeof(ident->oui)) != 0) + continue; + + quirks |= quirk->quirks; + } + + return quirks; +} + /** * drm_dp_read_desc - read sink/branch descriptor from DPCD * @aux: DisplayPort AUX channel @@ -1231,14 +1276,17 @@ int drm_dp_read_desc(struct drm_dp_aux *aux, struct drm_dp_desc *desc, if (ret < 0) return ret; + desc->quirks = drm_dp_get_quirks(ident, is_branch); + dev_id_len = strnlen(ident->device_id, sizeof(ident->device_id)); - DRM_DEBUG_KMS("DP %s: OUI %*phD dev-ID %*pE HW-rev %d.%d SW-rev %d.%d\n", + DRM_DEBUG_KMS("DP %s: OUI %*phD dev-ID %*pE HW-rev %d.%d SW-rev %d.%d quirks 0x%04x\n", is_branch ? "branch" : "sink", (int)sizeof(ident->oui), ident->oui, dev_id_len, ident->device_id, ident->hw_rev >> 4, ident->hw_rev & 0xf, - ident->sw_major_rev, ident->sw_minor_rev); + ident->sw_major_rev, ident->sw_minor_rev, + desc->quirks); return 0; } diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 84502da177a1..bb837310c07e 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -924,12 +924,44 @@ struct drm_dp_dpcd_ident { /** * struct drm_dp_desc - DP branch/sink device descriptor * @ident: DP device identification from DPCD 0x400 (sink) or 0x500 (branch). + * @quirks: Quirks; use drm_dp_has_quirk() to query for the quirks. */ struct drm_dp_desc { struct drm_dp_dpcd_ident ident; + u32 quirks; }; int drm_dp_read_desc(struct drm_dp_aux *aux, struct drm_dp_desc *desc, bool is_branch); +/** + * enum drm_dp_quirk - Display Port sink/branch device specific quirks + * + * Display Port sink and branch devices in the wild have a variety of bugs, try + * to collect them here. The quirks are shared, but it's up to the drivers to + * implement workarounds for them. + */ +enum drm_dp_quirk { + /** + * @DP_DPCD_QUIRK_LIMITED_M_N: + * + * The device requires main link attributes Mvid and Nvid to be limited + * to 16 bits. + */ + DP_DPCD_QUIRK_LIMITED_M_N, +}; + +/** + * drm_dp_has_quirk() - does the DP device have a specific quirk + * @desc: Device decriptor filled by drm_dp_read_desc() + * @quirk: Quirk to query for + * + * Return true if DP device identified by @desc has @quirk. + */ +static inline bool +drm_dp_has_quirk(const struct drm_dp_desc *desc, enum drm_dp_quirk quirk) +{ + return desc->quirks & BIT(quirk); +} + #endif /* _DRM_DP_HELPER_H_ */ -- cgit v1.2.3 From b31e85eda38c58cae986162ae2c462b53b0a2065 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 18 May 2017 14:10:25 +0300 Subject: drm/i915: Detect USB-C specific dongles before reducing M and N MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Analogix 7737 DP to HDMI converter requires reduced M and N values when to operate correctly at HBR2. We tried to reduce the M/N values for all devices in commit 9a86cda07af2 ("drm/i915/dp: reduce link M/N parameters"), but that regressed some other sinks. Detect this IC by its OUI value of 0x0022B9 via the DPCD quirk list, and only reduce the M/N values for that. v2 by Jani: Rebased on the DP quirk database v3 by Jani: Rebased on the reworked DP quirk database v4 by Jani: Improve commit message (Daniel) Fixes: 9a86cda07af2 ("drm/i915/dp: reduce link M/N parameters") Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=93578 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=100755 Cc: Jani Nikula Cc: Dhinakaran Pandiyan Cc: Ville Syrjälä Reviewed-by: Daniel Vetter Signed-off-by: Clint Taylor Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/2d2e30f8f47d3f28c9b74ca2612336a54585c3ec.1495105635.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 3 ++- drivers/gpu/drm/i915/intel_display.c | 22 ++++++++++++++-------- drivers/gpu/drm/i915/intel_dp.c | 8 ++++++-- drivers/gpu/drm/i915/intel_dp_mst.c | 5 ++++- 4 files changed, 26 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index c9b0949f6c1a..963f6d4481f7 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -562,7 +562,8 @@ struct intel_link_m_n { void intel_link_compute_m_n(int bpp, int nlanes, int pixel_clock, int link_clock, - struct intel_link_m_n *m_n); + struct intel_link_m_n *m_n, + bool reduce_m_n); /* Interface history: * diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 3617927af269..3cabe52a4e3b 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6101,7 +6101,7 @@ retry: pipe_config->fdi_lanes = lane; intel_link_compute_m_n(pipe_config->pipe_bpp, lane, fdi_dotclock, - link_bw, &pipe_config->fdi_m_n); + link_bw, &pipe_config->fdi_m_n, false); ret = ironlake_check_fdi_lanes(dev, intel_crtc->pipe, pipe_config); if (ret == -EINVAL && pipe_config->pipe_bpp > 6*3) { @@ -6277,7 +6277,8 @@ intel_reduce_m_n_ratio(uint32_t *num, uint32_t *den) } static void compute_m_n(unsigned int m, unsigned int n, - uint32_t *ret_m, uint32_t *ret_n) + uint32_t *ret_m, uint32_t *ret_n, + bool reduce_m_n) { /* * Reduce M/N as much as possible without loss in precision. Several DP @@ -6285,9 +6286,11 @@ static void compute_m_n(unsigned int m, unsigned int n, * values. The passed in values are more likely to have the least * significant bits zero than M after rounding below, so do this first. */ - while ((m & 1) == 0 && (n & 1) == 0) { - m >>= 1; - n >>= 1; + if (reduce_m_n) { + while ((m & 1) == 0 && (n & 1) == 0) { + m >>= 1; + n >>= 1; + } } *ret_n = min_t(unsigned int, roundup_pow_of_two(n), DATA_LINK_N_MAX); @@ -6298,16 +6301,19 @@ static void compute_m_n(unsigned int m, unsigned int n, void intel_link_compute_m_n(int bits_per_pixel, int nlanes, int pixel_clock, int link_clock, - struct intel_link_m_n *m_n) + struct intel_link_m_n *m_n, + bool reduce_m_n) { m_n->tu = 64; compute_m_n(bits_per_pixel * pixel_clock, link_clock * nlanes * 8, - &m_n->gmch_m, &m_n->gmch_n); + &m_n->gmch_m, &m_n->gmch_n, + reduce_m_n); compute_m_n(pixel_clock, link_clock, - &m_n->link_m, &m_n->link_n); + &m_n->link_m, &m_n->link_n, + reduce_m_n); } static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 5ce45d98da78..fc691b8b317c 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1593,6 +1593,8 @@ intel_dp_compute_config(struct intel_encoder *encoder, int common_rates[DP_MAX_SUPPORTED_RATES] = {}; int common_len; uint8_t link_bw, rate_select; + bool reduce_m_n = drm_dp_has_quirk(&intel_dp->desc, + DP_DPCD_QUIRK_LIMITED_M_N); common_len = intel_dp_common_rates(intel_dp, common_rates); @@ -1722,7 +1724,8 @@ found: intel_link_compute_m_n(bpp, lane_count, adjusted_mode->crtc_clock, pipe_config->port_clock, - &pipe_config->dp_m_n); + &pipe_config->dp_m_n, + reduce_m_n); if (intel_connector->panel.downclock_mode != NULL && dev_priv->drrs.type == SEAMLESS_DRRS_SUPPORT) { @@ -1730,7 +1733,8 @@ found: intel_link_compute_m_n(bpp, lane_count, intel_connector->panel.downclock_mode->clock, pipe_config->port_clock, - &pipe_config->dp_m2_n2); + &pipe_config->dp_m2_n2, + reduce_m_n); } /* diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index c1f62eb07c07..989e25577ac0 100644 --- a/drivers/gpu/drm/i915/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/intel_dp_mst.c @@ -44,6 +44,8 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder, int lane_count, slots; const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; int mst_pbn; + bool reduce_m_n = drm_dp_has_quirk(&intel_dp->desc, + DP_DPCD_QUIRK_LIMITED_M_N); pipe_config->has_pch_encoder = false; bpp = 24; @@ -75,7 +77,8 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder, intel_link_compute_m_n(bpp, lane_count, adjusted_mode->crtc_clock, pipe_config->port_clock, - &pipe_config->dp_m_n); + &pipe_config->dp_m_n, + reduce_m_n); pipe_config->dp_m_n.tu = slots; -- cgit v1.2.3 From f3d3eab667de62572376abb1aa26316191c39929 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 9 May 2017 10:04:36 +0200 Subject: HID: i2c: Call acpi_device_fix_up_power for ACPI-enumerated devices For ACPI devices which do not have a _PSC method, the ACPI subsys cannot query their initial state at boot, so these devices are assumed to have been put in D0 by the BIOS, but for touchscreens that is not always true. This commit adds a call to acpi_device_fix_up_power to explicitly put devices without a _PSC method into D0 state (for devices with a _PSC method it is a nop). Note we only need to do this on probe, after a resume the ACPI subsys knows the device is in D3 and will properly put it in D0. This fixes the SIS0817 i2c-hid touchscreen on a Peaq C1010 2-in-1 device failing to probe with a "hid_descr_cmd failed" error. Acked-by: Benjamin Tissoires Signed-off-by: Hans de Goede Signed-off-by: Jiri Kosina --- drivers/hid/i2c-hid/i2c-hid.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c index 8daa8ce64ebb..fb55fb4c39fc 100644 --- a/drivers/hid/i2c-hid/i2c-hid.c +++ b/drivers/hid/i2c-hid/i2c-hid.c @@ -897,6 +897,15 @@ static int i2c_hid_acpi_pdata(struct i2c_client *client, return 0; } +static void i2c_hid_acpi_fix_up_power(struct device *dev) +{ + acpi_handle handle = ACPI_HANDLE(dev); + struct acpi_device *adev; + + if (handle && acpi_bus_get_device(handle, &adev) == 0) + acpi_device_fix_up_power(adev); +} + static const struct acpi_device_id i2c_hid_acpi_match[] = { {"ACPI0C50", 0 }, {"PNP0C50", 0 }, @@ -909,6 +918,8 @@ static inline int i2c_hid_acpi_pdata(struct i2c_client *client, { return -ENODEV; } + +static inline void i2c_hid_acpi_fix_up_power(struct device *dev) {} #endif #ifdef CONFIG_OF @@ -1030,6 +1041,8 @@ static int i2c_hid_probe(struct i2c_client *client, if (ret < 0) goto err_regulator; + i2c_hid_acpi_fix_up_power(&client->dev); + pm_runtime_get_noresume(&client->dev); pm_runtime_set_active(&client->dev); pm_runtime_enable(&client->dev); -- cgit v1.2.3 From a082c6f680da298cf075886ff032f32ccb7c5e1a Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 29 May 2017 15:15:27 +0200 Subject: ovl: filter trusted xattr for non-admin Filesystems filter out extended attributes in the "trusted." domain for unprivlieged callers. Overlay calls underlying filesystem's method with elevated privs, so need to do the filtering in overlayfs too. Signed-off-by: Miklos Szeredi --- fs/overlayfs/inode.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index ad9547f82da5..d613e2c41242 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c @@ -240,6 +240,16 @@ int ovl_xattr_get(struct dentry *dentry, const char *name, return res; } +static bool ovl_can_list(const char *s) +{ + /* List all non-trusted xatts */ + if (strncmp(s, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) != 0) + return true; + + /* Never list trusted.overlay, list other trusted for superuser only */ + return !ovl_is_private_xattr(s) && capable(CAP_SYS_ADMIN); +} + ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size) { struct dentry *realdentry = ovl_dentry_real(dentry); @@ -263,7 +273,7 @@ ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size) return -EIO; len -= slen; - if (ovl_is_private_xattr(s)) { + if (!ovl_can_list(s)) { res -= slen; memmove(s, s + slen, len); } else { -- cgit v1.2.3 From b0f5a8f32e8bbdaae1abb8abe2d3cbafaba57e08 Mon Sep 17 00:00:00 2001 From: Vegard Nossum Date: Mon, 29 May 2017 09:22:07 +0200 Subject: kthread: fix boot hang (regression) on MIPS/OpenRISC This fixes a regression in commit 4d6501dce079 where I didn't notice that MIPS and OpenRISC were reinitialising p->{set,clear}_child_tid to NULL after our initialisation in copy_process(). We can simply get rid of the arch-specific initialisation here since it is now always done in copy_process() before hitting copy_thread{,_tls}(). Review notes: - As far as I can tell, copy_process() is the only user of copy_thread_tls(), which is the only caller of copy_thread() for architectures that don't implement copy_thread_tls(). - After this patch, there is no arch-specific code touching p->set_child_tid or p->clear_child_tid whatsoever. - It may look like MIPS/OpenRISC wanted to always have these fields be NULL, but that's not true, as copy_process() would unconditionally set them again _after_ calling copy_thread_tls() before commit 4d6501dce079. Fixes: 4d6501dce079c1eb6bf0b1d8f528a5e81770109e ("kthread: Fix use-after-free if kthread fork fails") Reported-by: Guenter Roeck Tested-by: Guenter Roeck # MIPS only Acked-by: Stafford Horne Acked-by: Oleg Nesterov Cc: Ralf Baechle Cc: linux-mips@linux-mips.org Cc: Jonas Bonn Cc: Stefan Kristiansson Cc: openrisc@lists.librecores.org Cc: Jamie Iles Cc: Thomas Gleixner Signed-off-by: Vegard Nossum Signed-off-by: Linus Torvalds --- arch/mips/kernel/process.c | 1 - arch/openrisc/kernel/process.c | 2 -- 2 files changed, 3 deletions(-) diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index 918d4c73e951..5351e1f3950d 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -120,7 +120,6 @@ int copy_thread_tls(unsigned long clone_flags, unsigned long usp, struct thread_info *ti = task_thread_info(p); struct pt_regs *childregs, *regs = current_pt_regs(); unsigned long childksp; - p->set_child_tid = p->clear_child_tid = NULL; childksp = (unsigned long)task_stack_page(p) + THREAD_SIZE - 32; diff --git a/arch/openrisc/kernel/process.c b/arch/openrisc/kernel/process.c index f8da545854f9..106859ae27ff 100644 --- a/arch/openrisc/kernel/process.c +++ b/arch/openrisc/kernel/process.c @@ -167,8 +167,6 @@ copy_thread(unsigned long clone_flags, unsigned long usp, top_of_kernel_stack = sp; - p->set_child_tid = p->clear_child_tid = NULL; - /* Locate userspace context on stack... */ sp -= STACK_FRAME_OVERHEAD; /* redzone */ sp -= sizeof(struct pt_regs); -- cgit v1.2.3 From 67a7d5f561f469ad2fa5154d2888258ab8e6df7c Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 29 May 2017 13:24:55 -0400 Subject: ext4: fix fdatasync(2) after extent manipulation operations Currently, extent manipulation operations such as hole punch, range zeroing, or extent shifting do not record the fact that file data has changed and thus fdatasync(2) has a work to do. As a result if we crash e.g. after a punch hole and fdatasync, user can still possibly see the punched out data after journal replay. Test generic/392 fails due to these problems. Fix the problem by properly marking that file data has changed in these operations. CC: stable@vger.kernel.org Fixes: a4bb6b64e39abc0e41ca077725f2a72c868e7622 Signed-off-by: Jan Kara Signed-off-by: Theodore Ts'o --- fs/ext4/extents.c | 5 +++++ fs/ext4/inode.c | 2 ++ 2 files changed, 7 insertions(+) diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 83a513efc824..3e36508610b7 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -4877,6 +4877,8 @@ static long ext4_zero_range(struct file *file, loff_t offset, /* Zero out partial block at the edges of the range */ ret = ext4_zero_partial_blocks(handle, inode, offset, len); + if (ret >= 0) + ext4_update_inode_fsync_trans(handle, inode, 1); if (file->f_flags & O_SYNC) ext4_handle_sync(handle); @@ -5563,6 +5565,7 @@ int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len) ext4_handle_sync(handle); inode->i_mtime = inode->i_ctime = current_time(inode); ext4_mark_inode_dirty(handle, inode); + ext4_update_inode_fsync_trans(handle, inode, 1); out_stop: ext4_journal_stop(handle); @@ -5736,6 +5739,8 @@ int ext4_insert_range(struct inode *inode, loff_t offset, loff_t len) up_write(&EXT4_I(inode)->i_data_sem); if (IS_SYNC(inode)) ext4_handle_sync(handle); + if (ret >= 0) + ext4_update_inode_fsync_trans(handle, inode, 1); out_stop: ext4_journal_stop(handle); diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 657a98fa80b6..5cf82d03968c 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -4218,6 +4218,8 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length) inode->i_mtime = inode->i_ctime = current_time(inode); ext4_mark_inode_dirty(handle, inode); + if (ret >= 0) + ext4_update_inode_fsync_trans(handle, inode, 1); out_stop: ext4_journal_stop(handle); out_dio: -- cgit v1.2.3 From 878d8db039daac0938238e9a40a5bd6e50ee3c9b Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Wed, 10 May 2017 18:12:40 +0200 Subject: Revert "ACPI / button: Change default behavior to lid_init_state=open" Revert commit 77e9a4aa9de1 (ACPI / button: Change default behavior to lid_init_state=open) which changed the kernel's behavior on laptops that boot with closed lids and expect the lid switch state to be reported accurately by the kernel. If you boot or resume your laptop with the lid closed on a docking station while using an external monitor connected to it, both internal and external displays will light on, while only the external should. There is a design choice in gdm to only provide the greeter on the internal display when lit on, so users only see a gray area on the external monitor. Also, the cursor will not show up as it's by default on the internal display too. To "fix" that, users have to open the laptop once and close it once again to sync the state of the switch with the hardware state. Even if the "method" operation mode implementation can be buggy on some platforms, the "open" choice is worse. It breaks docking stations basically and there is no way to have a user-space hwdb to fix that. On the contrary, it's rather easy in user-space to have a hwdb with the problematic platforms. Then, libinput (1.7.0+) can fix the state of the lid switch for us: you need to set the udev property LIBINPUT_ATTR_LID_SWITCH_RELIABILITY to 'write_open'. When libinput detects internal keyboard events, it will overwrite the state of the switch to open, making it reliable again. Given that logind only checks the lid switch value after a timeout, we can assume the user will use the internal keyboard before this timeout expires. For example, such a hwdb entry is: libinput:name:*Lid Switch*:dmi:*svnMicrosoftCorporation:pnSurface3:* LIBINPUT_ATTR_LID_SWITCH_RELIABILITY=write_open Link: https://bugzilla.gnome.org/show_bug.cgi?id=782380 Cc: 4.11+ # 4.11+ Signed-off-by: Benjamin Tissoires Signed-off-by: Rafael J. Wysocki --- drivers/acpi/button.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index 6d5a8c1d3132..e19f530f1083 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -113,7 +113,7 @@ struct acpi_button { static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier); static struct acpi_device *lid_device; -static u8 lid_init_state = ACPI_BUTTON_LID_INIT_OPEN; +static u8 lid_init_state = ACPI_BUTTON_LID_INIT_METHOD; static unsigned long lid_report_interval __read_mostly = 500; module_param(lid_report_interval, ulong, 0644); -- cgit v1.2.3 From 2ea65321b83539afc1d45c1bea39c55ab42af62b Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Tue, 9 May 2017 13:57:31 +0800 Subject: ACPICA: Tables: Fix regression introduced by a too early mechanism enabling In the Linux kernel, acpi_get_table() "clones" haven't been fully balanced by acpi_put_table() invocations. In upstream ACPICA, due to the design change, there are also unbalanced acpi_get_table_by_index() invocations requiring special care. acpi_get_table() reference counting mismatches may occor due to that and printing error messages related to them is not useful at this point. The strict balanced validation count check should only be enabled after confirming that all invocations are safe and aligned with their designed purposes. Thus this patch removes the error value returned by acpi_tb_get_table() in that case along with the accompanying error message to fix the issue. Fixes: 174cc7187e6f (ACPICA: Tables: Back port acpi_get_table_with_size() and early_acpi_os_unmap_memory() from Linux kernel) Cc: 4.10+ # 4.10+ Reported-by: Anush Seetharaman Reported-by: Dan Williams Signed-off-by: Lv Zheng [ rjw: Changelog ] Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/tbutils.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c index 5a968a78652b..7abe66505739 100644 --- a/drivers/acpi/acpica/tbutils.c +++ b/drivers/acpi/acpica/tbutils.c @@ -418,11 +418,7 @@ acpi_tb_get_table(struct acpi_table_desc *table_desc, table_desc->validation_count++; if (table_desc->validation_count == 0) { - ACPI_ERROR((AE_INFO, - "Table %p, Validation count is zero after increment\n", - table_desc)); table_desc->validation_count--; - return_ACPI_STATUS(AE_LIMIT); } *out_table = table_desc->pointer; -- cgit v1.2.3 From 6c77003677d5f1ce15f26d24360cb66c0bc07bb3 Mon Sep 17 00:00:00 2001 From: David Arcari Date: Fri, 26 May 2017 11:37:31 -0400 Subject: cpufreq: cpufreq_register_driver() should return -ENODEV if init fails For a driver that does not set the CPUFREQ_STICKY flag, if all of the ->init() calls fail, cpufreq_register_driver() should return an error. This will prevent the driver from loading. Fixes: ce1bcfe94db8 (cpufreq: check cpufreq_policy_list instead of scanning policies for all CPUs) Cc: 4.0+ # 4.0+ Signed-off-by: David Arcari Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 0e3f6496524d..26b643d57847 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -2468,6 +2468,7 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data) if (!(cpufreq_driver->flags & CPUFREQ_STICKY) && list_empty(&cpufreq_policy_list)) { /* if all ->init() calls failed, unregister */ + ret = -ENODEV; pr_debug("%s: No CPU initialized for driver %s\n", __func__, driver_data->name); goto err_if_unreg; -- cgit v1.2.3 From 7575f8257279f9dd24b3fc950aa2c7e98564a103 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Wed, 17 May 2017 12:20:35 +0530 Subject: cpufreq: kirkwood-cpufreq:- Handle return value of clk_prepare_enable() clk_prepare_enable() can fail here and we must check its return value. Signed-off-by: Arvind Yadav Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/kirkwood-cpufreq.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/cpufreq/kirkwood-cpufreq.c b/drivers/cpufreq/kirkwood-cpufreq.c index 1b9bcd76c60e..c2dd43f3f5d8 100644 --- a/drivers/cpufreq/kirkwood-cpufreq.c +++ b/drivers/cpufreq/kirkwood-cpufreq.c @@ -127,7 +127,12 @@ static int kirkwood_cpufreq_probe(struct platform_device *pdev) return PTR_ERR(priv.cpu_clk); } - clk_prepare_enable(priv.cpu_clk); + err = clk_prepare_enable(priv.cpu_clk); + if (err) { + dev_err(priv.dev, "Unable to prepare cpuclk\n"); + return err; + } + kirkwood_freq_table[0].frequency = clk_get_rate(priv.cpu_clk) / 1000; priv.ddr_clk = of_clk_get_by_name(np, "ddrclk"); @@ -137,7 +142,11 @@ static int kirkwood_cpufreq_probe(struct platform_device *pdev) goto out_cpu; } - clk_prepare_enable(priv.ddr_clk); + err = clk_prepare_enable(priv.ddr_clk); + if (err) { + dev_err(priv.dev, "Unable to prepare ddrclk\n"); + goto out_cpu; + } kirkwood_freq_table[1].frequency = clk_get_rate(priv.ddr_clk) / 1000; priv.powersave_clk = of_clk_get_by_name(np, "powersave"); @@ -146,7 +155,11 @@ static int kirkwood_cpufreq_probe(struct platform_device *pdev) err = PTR_ERR(priv.powersave_clk); goto out_ddr; } - clk_prepare_enable(priv.powersave_clk); + err = clk_prepare_enable(priv.powersave_clk); + if (err) { + dev_err(priv.dev, "Unable to prepare powersave clk\n"); + goto out_ddr; + } of_node_put(np); np = NULL; -- cgit v1.2.3 From 1943d1723e7a7ee1a7b9b0ba4878dde0dc100671 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 26 May 2017 16:09:48 -0700 Subject: Input: silead - disable interrupt during suspend When we put the touchscreen controller in low-power mode the irq pin may trigger (float) and if we then try to read a data packet we get the following error in dmesg: [ 478.801017] silead_ts i2c-MSSL1680:00: Data read error -121 This commit disables the irq during suspend/resume fixing this error. Signed-off-by: Hans de Goede Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/silead.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/input/touchscreen/silead.c b/drivers/input/touchscreen/silead.c index 813dd68a5c82..0dbcf105f7db 100644 --- a/drivers/input/touchscreen/silead.c +++ b/drivers/input/touchscreen/silead.c @@ -526,6 +526,7 @@ static int __maybe_unused silead_ts_suspend(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); + disable_irq(client->irq); silead_ts_set_power(client, SILEAD_POWER_OFF); return 0; } @@ -551,6 +552,8 @@ static int __maybe_unused silead_ts_resume(struct device *dev) return -ENODEV; } + enable_irq(client->irq); + return 0; } -- cgit v1.2.3 From 2755551188d240f0098cdc6f1a2984f8a1785689 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 29 May 2017 19:57:19 -0700 Subject: Input: synaptics - clear device info before filling in synaptics_query_hardware() was being passed a 'struct synaptics_device_info' in uninitialized stack memory, then not always initializing all fields. This caused garbage to show up in certain fields, making the touchpad unusable. Fix by zeroing the device info, so all fields default to 0. Fixes: 6c53694fb222 ("Input: synaptics - split device info into a separate structure") Signed-off-by: Eric Biggers Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/synaptics.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 131df9d3660f..4f97970abc94 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -397,6 +397,8 @@ static int synaptics_query_hardware(struct psmouse *psmouse, { int error; + memset(info, 0, sizeof(*info)); + error = synaptics_identify(psmouse, info); if (error) return error; -- cgit v1.2.3 From f4947d79a7080b25829997eeee38d4d65137c161 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Tue, 23 May 2017 14:15:24 -0700 Subject: Input: synaptics - keep PS/2 around when RMI4_SMB is not enabled Or the user might have the touchpad unbound from PS/2 but never picked up by rmi-smbus.ko Signed-off-by: Benjamin Tissoires Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/synaptics.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 4f97970abc94..9b27a6c710b2 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -1689,7 +1689,8 @@ enum { SYNAPTICS_INTERTOUCH_ON, }; -static int synaptics_intertouch = SYNAPTICS_INTERTOUCH_NOT_SET; +static int synaptics_intertouch = IS_ENABLED(CONFIG_RMI4_SMB) ? + SYNAPTICS_INTERTOUCH_NOT_SET : SYNAPTICS_INTERTOUCH_OFF; module_param_named(synaptics_intertouch, synaptics_intertouch, int, 0644); MODULE_PARM_DESC(synaptics_intertouch, "Use a secondary bus for the Synaptics device."); -- cgit v1.2.3 From f4101ff87dafd22fbcc3547fd3a3a3717d3d72d3 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Fri, 26 May 2017 16:21:36 -0700 Subject: Input: synaptics - warn the users when there is a better mode The Synaptics touchpads are now either using i2c-hid or rmi-smbus. Warn the users if they are missing the rmi-smbus modules and have no chance of reporting correct data. Signed-off-by: Benjamin Tissoires Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/synaptics.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 9b27a6c710b2..604aa3aa7284 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -176,6 +176,12 @@ static const char * const smbus_pnp_ids[] = { NULL }; +static const char * const forcepad_pnp_ids[] = { + "SYN300D", + "SYN3014", + NULL +}; + /* * Send a command to the synpatics touchpad by special commands */ @@ -482,13 +488,6 @@ static const struct min_max_quirk min_max_pnpid_table[] = { { } }; -/* This list has been kindly provided by Synaptics. */ -static const char * const forcepad_pnp_ids[] = { - "SYN300D", - "SYN3014", - NULL -}; - /***************************************************************************** * Synaptics communications functions ****************************************************************************/ @@ -1813,6 +1812,15 @@ int synaptics_init(struct psmouse *psmouse) } if (SYN_CAP_INTERTOUCH(info.ext_cap_0c)) { + if ((!IS_ENABLED(CONFIG_RMI4_SMB) || + !IS_ENABLED(CONFIG_MOUSE_PS2_SYNAPTICS_SMBUS)) && + /* Forcepads need F21, which is not ready */ + !psmouse_matches_pnp_id(psmouse, forcepad_pnp_ids)) { + psmouse_warn(psmouse, + "The touchpad can support a better bus than the too old PS/2 protocol. " + "Make sure MOUSE_PS2_SYNAPTICS_SMBUS and RMI4_SMB are enabled to get a better touchpad experience.\n"); + } + error = synaptics_setup_intertouch(psmouse, &info, true); if (!error) return PSMOUSE_SYNAPTICS_SMBUS; -- cgit v1.2.3 From 2fef826e45c6a1e63f55ab72546f7d795300d9a8 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Fri, 26 May 2017 16:51:19 -0700 Subject: Input: synaptics - tell users to report when they should be using rmi-smbus Users should really consider switching to rmi-smbus instead of plain PS/2. Notify them that they should report a missing pnpID in the file. Signed-off-by: Benjamin Tissoires Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/synaptics.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 604aa3aa7284..16c30460ef04 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -1739,8 +1739,16 @@ static int synaptics_setup_intertouch(struct psmouse *psmouse, if (synaptics_intertouch == SYNAPTICS_INTERTOUCH_NOT_SET) { if (!psmouse_matches_pnp_id(psmouse, topbuttonpad_pnp_ids) && - !psmouse_matches_pnp_id(psmouse, smbus_pnp_ids)) + !psmouse_matches_pnp_id(psmouse, smbus_pnp_ids)) { + + if (!psmouse_matches_pnp_id(psmouse, forcepad_pnp_ids)) + psmouse_info(psmouse, + "Your touchpad (%s) says it can support a different bus. " + "If i2c-hid and hid-rmi are not used, you might want to try setting psmouse.synaptics_intertouch to 1 and report this to linux-input@vger.kernel.org.\n", + psmouse->ps2dev.serio->firmware_id); + return -ENXIO; + } } psmouse_info(psmouse, "Trying to set up SMBus access\n"); -- cgit v1.2.3 From 56b177055adb246cdeca174331dbf92fc49bfccd Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 23 May 2017 07:08:43 +0000 Subject: rcar-dmac: fixup descriptor pointer for descriptor mode In descriptor mode, the descriptor running pointer is not maintained by the interrupt handler, thus, driver finds the running descriptor from the descriptor pointer field in the CHCRB register. But, CHCRB::DPTR indicates *next* descriptor pointer, not current. Thus, The residue calculation will be missed. This patch fixup it. Signed-off-by: Kuninori Morimoto Signed-off-by: Vinod Koul --- drivers/dma/sh/rcar-dmac.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c index db41795fe42a..bd261c9e9664 100644 --- a/drivers/dma/sh/rcar-dmac.c +++ b/drivers/dma/sh/rcar-dmac.c @@ -1287,6 +1287,9 @@ static unsigned int rcar_dmac_chan_get_residue(struct rcar_dmac_chan *chan, if (desc->hwdescs.use) { dptr = (rcar_dmac_chan_read(chan, RCAR_DMACHCRB) & RCAR_DMACHCRB_DPTR_MASK) >> RCAR_DMACHCRB_DPTR_SHIFT; + if (dptr == 0) + dptr = desc->nchunks; + dptr--; WARN_ON(dptr >= desc->nchunks); } else { running = desc->running; -- cgit v1.2.3 From 7a7c0a6438b8e7636d5a22e572892cc234f68297 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sat, 27 May 2017 00:27:25 +0200 Subject: mac80211: fix TX aggregation start/stop callback race When starting or stopping an aggregation session, one of the steps is that the driver calls back to mac80211 that the start/stop can proceed. This is handled by queueing up a fake SKB and processing it from the normal iface/sdata work. Since this isn't flushed when disassociating, the following race is possible: * associate * start aggregation session * driver callback * disassociate * associate again to the same AP * callback processing runs, leading to a WARN_ON() that the TID hadn't requested aggregation If the second association isn't to the same AP, there would only be a message printed ("Could not find station: "), but the same race could happen. Fix this by not going the whole detour with a fake SKB etc. but simply looking up the aggregation session in the driver callback, marking it with a START_CB/STOP_CB bit and then scheduling the regular aggregation work that will now process these bits as well. This also simplifies the code and gets rid of the whole problem with allocation failures of said skb, which could have left the session in limbo. Reported-by: Jouni Malinen Signed-off-by: Johannes Berg --- net/mac80211/agg-tx.c | 128 ++++++++++++++++++--------------------------- net/mac80211/ht.c | 16 ++++-- net/mac80211/ieee80211_i.h | 14 ++--- net/mac80211/iface.c | 11 +--- net/mac80211/sta_info.h | 2 + 5 files changed, 71 insertions(+), 100 deletions(-) diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 60e2a62f7bef..cf2392b2ac71 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c @@ -7,7 +7,7 @@ * Copyright 2006-2007 Jiri Benc * Copyright 2007, Michael Wu * Copyright 2007-2010, Intel Corporation - * Copyright(c) 2015 Intel Deutschland GmbH + * Copyright(c) 2015-2017 Intel Deutschland GmbH * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -741,46 +741,43 @@ static void ieee80211_agg_tx_operational(struct ieee80211_local *local, ieee80211_agg_start_txq(sta, tid, true); } -void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid) +void ieee80211_start_tx_ba_cb(struct sta_info *sta, int tid, + struct tid_ampdu_tx *tid_tx) { - struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); + struct ieee80211_sub_if_data *sdata = sta->sdata; struct ieee80211_local *local = sdata->local; - struct sta_info *sta; - struct tid_ampdu_tx *tid_tx; - trace_api_start_tx_ba_cb(sdata, ra, tid); + if (WARN_ON(test_and_set_bit(HT_AGG_STATE_DRV_READY, &tid_tx->state))) + return; + + if (test_bit(HT_AGG_STATE_RESPONSE_RECEIVED, &tid_tx->state)) + ieee80211_agg_tx_operational(local, sta, tid); +} + +static struct tid_ampdu_tx * +ieee80211_lookup_tid_tx(struct ieee80211_sub_if_data *sdata, + const u8 *ra, u16 tid, struct sta_info **sta) +{ + struct tid_ampdu_tx *tid_tx; if (tid >= IEEE80211_NUM_TIDS) { ht_dbg(sdata, "Bad TID value: tid = %d (>= %d)\n", tid, IEEE80211_NUM_TIDS); - return; + return NULL; } - mutex_lock(&local->sta_mtx); - sta = sta_info_get_bss(sdata, ra); - if (!sta) { - mutex_unlock(&local->sta_mtx); + *sta = sta_info_get_bss(sdata, ra); + if (!*sta) { ht_dbg(sdata, "Could not find station: %pM\n", ra); - return; + return NULL; } - mutex_lock(&sta->ampdu_mlme.mtx); - tid_tx = rcu_dereference_protected_tid_tx(sta, tid); + tid_tx = rcu_dereference((*sta)->ampdu_mlme.tid_tx[tid]); - if (WARN_ON(!tid_tx)) { + if (WARN_ON(!tid_tx)) ht_dbg(sdata, "addBA was not requested!\n"); - goto unlock; - } - if (WARN_ON(test_and_set_bit(HT_AGG_STATE_DRV_READY, &tid_tx->state))) - goto unlock; - - if (test_bit(HT_AGG_STATE_RESPONSE_RECEIVED, &tid_tx->state)) - ieee80211_agg_tx_operational(local, sta, tid); - - unlock: - mutex_unlock(&sta->ampdu_mlme.mtx); - mutex_unlock(&local->sta_mtx); + return tid_tx; } void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, @@ -788,19 +785,20 @@ void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, { struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); struct ieee80211_local *local = sdata->local; - struct ieee80211_ra_tid *ra_tid; - struct sk_buff *skb = dev_alloc_skb(0); + struct sta_info *sta; + struct tid_ampdu_tx *tid_tx; - if (unlikely(!skb)) - return; + trace_api_start_tx_ba_cb(sdata, ra, tid); - ra_tid = (struct ieee80211_ra_tid *) &skb->cb; - memcpy(&ra_tid->ra, ra, ETH_ALEN); - ra_tid->tid = tid; + rcu_read_lock(); + tid_tx = ieee80211_lookup_tid_tx(sdata, ra, tid, &sta); + if (!tid_tx) + goto out; - skb->pkt_type = IEEE80211_SDATA_QUEUE_AGG_START; - skb_queue_tail(&sdata->skb_queue, skb); - ieee80211_queue_work(&local->hw, &sdata->work); + set_bit(HT_AGG_STATE_START_CB, &tid_tx->state); + ieee80211_queue_work(&local->hw, &sta->ampdu_mlme.work); + out: + rcu_read_unlock(); } EXPORT_SYMBOL(ieee80211_start_tx_ba_cb_irqsafe); @@ -860,37 +858,18 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid) } EXPORT_SYMBOL(ieee80211_stop_tx_ba_session); -void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid) +void ieee80211_stop_tx_ba_cb(struct sta_info *sta, int tid, + struct tid_ampdu_tx *tid_tx) { - struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); - struct ieee80211_local *local = sdata->local; - struct sta_info *sta; - struct tid_ampdu_tx *tid_tx; + struct ieee80211_sub_if_data *sdata = sta->sdata; bool send_delba = false; - trace_api_stop_tx_ba_cb(sdata, ra, tid); - - if (tid >= IEEE80211_NUM_TIDS) { - ht_dbg(sdata, "Bad TID value: tid = %d (>= %d)\n", - tid, IEEE80211_NUM_TIDS); - return; - } - - ht_dbg(sdata, "Stopping Tx BA session for %pM tid %d\n", ra, tid); - - mutex_lock(&local->sta_mtx); - - sta = sta_info_get_bss(sdata, ra); - if (!sta) { - ht_dbg(sdata, "Could not find station: %pM\n", ra); - goto unlock; - } + ht_dbg(sdata, "Stopping Tx BA session for %pM tid %d\n", + sta->sta.addr, tid); - mutex_lock(&sta->ampdu_mlme.mtx); spin_lock_bh(&sta->lock); - tid_tx = rcu_dereference_protected_tid_tx(sta, tid); - if (!tid_tx || !test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) { + if (!test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) { ht_dbg(sdata, "unexpected callback to A-MPDU stop for %pM tid %d\n", sta->sta.addr, tid); @@ -906,12 +885,8 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid) spin_unlock_bh(&sta->lock); if (send_delba) - ieee80211_send_delba(sdata, ra, tid, + ieee80211_send_delba(sdata, sta->sta.addr, tid, WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE); - - mutex_unlock(&sta->ampdu_mlme.mtx); - unlock: - mutex_unlock(&local->sta_mtx); } void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, @@ -919,19 +894,20 @@ void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, { struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); struct ieee80211_local *local = sdata->local; - struct ieee80211_ra_tid *ra_tid; - struct sk_buff *skb = dev_alloc_skb(0); + struct sta_info *sta; + struct tid_ampdu_tx *tid_tx; - if (unlikely(!skb)) - return; + trace_api_stop_tx_ba_cb(sdata, ra, tid); - ra_tid = (struct ieee80211_ra_tid *) &skb->cb; - memcpy(&ra_tid->ra, ra, ETH_ALEN); - ra_tid->tid = tid; + rcu_read_lock(); + tid_tx = ieee80211_lookup_tid_tx(sdata, ra, tid, &sta); + if (!tid_tx) + goto out; - skb->pkt_type = IEEE80211_SDATA_QUEUE_AGG_STOP; - skb_queue_tail(&sdata->skb_queue, skb); - ieee80211_queue_work(&local->hw, &sdata->work); + set_bit(HT_AGG_STATE_STOP_CB, &tid_tx->state); + ieee80211_queue_work(&local->hw, &sta->ampdu_mlme.work); + out: + rcu_read_unlock(); } EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb_irqsafe); diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index f4a528773563..6ca5442b1e03 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c @@ -7,6 +7,7 @@ * Copyright 2006-2007 Jiri Benc * Copyright 2007, Michael Wu * Copyright 2007-2010, Intel Corporation + * Copyright 2017 Intel Deutschland GmbH * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -289,8 +290,6 @@ void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta, { int i; - cancel_work_sync(&sta->ampdu_mlme.work); - for (i = 0; i < IEEE80211_NUM_TIDS; i++) { __ieee80211_stop_tx_ba_session(sta, i, reason); __ieee80211_stop_rx_ba_session(sta, i, WLAN_BACK_RECIPIENT, @@ -298,6 +297,9 @@ void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta, reason != AGG_STOP_DESTROY_STA && reason != AGG_STOP_PEER_REQUEST); } + + /* stopping might queue the work again - so cancel only afterwards */ + cancel_work_sync(&sta->ampdu_mlme.work); } void ieee80211_ba_session_work(struct work_struct *work) @@ -352,10 +354,16 @@ void ieee80211_ba_session_work(struct work_struct *work) spin_unlock_bh(&sta->lock); tid_tx = rcu_dereference_protected_tid_tx(sta, tid); - if (tid_tx && test_and_clear_bit(HT_AGG_STATE_WANT_STOP, - &tid_tx->state)) + if (!tid_tx) + continue; + + if (test_and_clear_bit(HT_AGG_STATE_START_CB, &tid_tx->state)) + ieee80211_start_tx_ba_cb(sta, tid, tid_tx); + if (test_and_clear_bit(HT_AGG_STATE_WANT_STOP, &tid_tx->state)) ___ieee80211_stop_tx_ba_session(sta, tid, AGG_STOP_LOCAL_REQUEST); + if (test_and_clear_bit(HT_AGG_STATE_STOP_CB, &tid_tx->state)) + ieee80211_stop_tx_ba_cb(sta, tid, tid_tx); } mutex_unlock(&sta->ampdu_mlme.mtx); } diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index f8f6c148f554..665501ac358f 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1036,8 +1036,6 @@ struct ieee80211_rx_agg { enum sdata_queue_type { IEEE80211_SDATA_QUEUE_TYPE_FRAME = 0, - IEEE80211_SDATA_QUEUE_AGG_START = 1, - IEEE80211_SDATA_QUEUE_AGG_STOP = 2, IEEE80211_SDATA_QUEUE_RX_AGG_START = 3, IEEE80211_SDATA_QUEUE_RX_AGG_STOP = 4, }; @@ -1427,12 +1425,6 @@ ieee80211_get_sband(struct ieee80211_sub_if_data *sdata) return local->hw.wiphy->bands[band]; } -/* this struct represents 802.11n's RA/TID combination */ -struct ieee80211_ra_tid { - u8 ra[ETH_ALEN]; - u16 tid; -}; - /* this struct holds the value parsing from channel switch IE */ struct ieee80211_csa_ie { struct cfg80211_chan_def chandef; @@ -1794,8 +1786,10 @@ int __ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, enum ieee80211_agg_stop_reason reason); int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, enum ieee80211_agg_stop_reason reason); -void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid); -void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid); +void ieee80211_start_tx_ba_cb(struct sta_info *sta, int tid, + struct tid_ampdu_tx *tid_tx); +void ieee80211_stop_tx_ba_cb(struct sta_info *sta, int tid, + struct tid_ampdu_tx *tid_tx); void ieee80211_ba_session_work(struct work_struct *work); void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid); void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid); diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 3bd5b81f5d81..8fae1a72e6a7 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -1237,7 +1237,6 @@ static void ieee80211_iface_work(struct work_struct *work) struct ieee80211_local *local = sdata->local; struct sk_buff *skb; struct sta_info *sta; - struct ieee80211_ra_tid *ra_tid; struct ieee80211_rx_agg *rx_agg; if (!ieee80211_sdata_running(sdata)) @@ -1253,15 +1252,7 @@ static void ieee80211_iface_work(struct work_struct *work) while ((skb = skb_dequeue(&sdata->skb_queue))) { struct ieee80211_mgmt *mgmt = (void *)skb->data; - if (skb->pkt_type == IEEE80211_SDATA_QUEUE_AGG_START) { - ra_tid = (void *)&skb->cb; - ieee80211_start_tx_ba_cb(&sdata->vif, ra_tid->ra, - ra_tid->tid); - } else if (skb->pkt_type == IEEE80211_SDATA_QUEUE_AGG_STOP) { - ra_tid = (void *)&skb->cb; - ieee80211_stop_tx_ba_cb(&sdata->vif, ra_tid->ra, - ra_tid->tid); - } else if (skb->pkt_type == IEEE80211_SDATA_QUEUE_RX_AGG_START) { + if (skb->pkt_type == IEEE80211_SDATA_QUEUE_RX_AGG_START) { rx_agg = (void *)&skb->cb; mutex_lock(&local->sta_mtx); sta = sta_info_get_bss(sdata, rx_agg->addr); diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 5609cacb20d5..ea0747d6a6da 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -116,6 +116,8 @@ enum ieee80211_sta_info_flags { #define HT_AGG_STATE_STOPPING 3 #define HT_AGG_STATE_WANT_START 4 #define HT_AGG_STATE_WANT_STOP 5 +#define HT_AGG_STATE_START_CB 6 +#define HT_AGG_STATE_STOP_CB 7 enum ieee80211_agg_stop_reason { AGG_STOP_DECLINED, -- cgit v1.2.3 From 4b1c88984c8ac894c2c411570757bed7fa5f3226 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 18 May 2017 15:13:57 +0200 Subject: iommu/dma: Fix function declaration Newly added code in the ipmmu-vmsa driver showed a small mistake in a header file that can't be included by itself without CONFIG_IOMMU_DMA enabled: In file included from drivers/iommu/ipmmu-vmsa.c:13:0: include/linux/dma-iommu.h:105:94: error: 'struct device' declared inside parameter list will not be visible outside of this definition or declaration [-Werror] This adds a forward declaration for 'struct device', similar to how we treat the other struct types in this case. Fixes: 3ae47292024f ("iommu/ipmmu-vmsa: Add new IOMMU_DOMAIN_DMA ops") Fixes: 273df9635385 ("iommu/dma: Make PCI window reservation generic") Signed-off-by: Arnd Bergmann Acked-by: Robin Murphy Signed-off-by: Joerg Roedel --- include/linux/dma-iommu.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/dma-iommu.h b/include/linux/dma-iommu.h index 4eac2670bfa1..92f20832fd28 100644 --- a/include/linux/dma-iommu.h +++ b/include/linux/dma-iommu.h @@ -78,6 +78,7 @@ void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list); struct iommu_domain; struct msi_msg; +struct device; static inline int iommu_dma_init(void) { -- cgit v1.2.3 From 573d41757c47cb71cd572236685d4c9e6cacc06c Mon Sep 17 00:00:00 2001 From: Sricharan R Date: Sat, 27 May 2017 19:17:40 +0530 Subject: iommu/of: Fix check for returning EPROBE_DEFER Now with IOMMU probe deferral, we return -EPROBE_DEFER for masters that are connected to an IOMMU which is not probed yet, but going to get probed, so that we can attach the correct dma_ops. So while trying to defer the probe of the master, check if the of_iommu node that it is connected to is marked in DT as 'status=disabled', then the IOMMU is never is going to get probed. So simply return NULL and let the master work without an IOMMU. Fixes: 7b07cbefb68d ("iommu: of: Handle IOMMU lookup failure with deferred probing or error") Reported-by: Geert Uytterhoeven Reviewed-by: Laurent Pinchart Tested-by: Will Deacon Tested-by: Magnus Damn Acked-by: Will Deacon Signed-off-by: Sricharan R Signed-off-by: Joerg Roedel --- drivers/iommu/of_iommu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c index 9f44ee8ea1bc..e6e9bec42e5f 100644 --- a/drivers/iommu/of_iommu.c +++ b/drivers/iommu/of_iommu.c @@ -118,6 +118,7 @@ static const struct iommu_ops ops = iommu_ops_from_fwnode(fwnode); if ((ops && !ops->of_xlate) || + !of_device_is_available(iommu_spec->np) || (!ops && !of_iommu_driver_present(iommu_spec->np))) return NULL; -- cgit v1.2.3 From a37b19a384914c60b7e1264a6c21e7bf96b637e8 Mon Sep 17 00:00:00 2001 From: Sricharan R Date: Sat, 27 May 2017 19:17:41 +0530 Subject: iommu/of: Ignore all errors except EPROBE_DEFER While deferring the probe of IOMMU masters, xlate and add_device callbacks called from of_iommu_configure can pass back error values like -ENODEV, which means the IOMMU cannot be connected with that master for real reasons. Before the IOMMU probe deferral, all such errors were ignored. Now all those errors are propagated back, killing the master's probe for such errors. Instead ignore all the errors except EPROBE_DEFER, which is the only one of concern and let the master work without IOMMU, thus restoring the old behavior. Also make explicit that of_dma_configure handles only -EPROBE_DEFER from of_iommu_configure. Fixes: 7b07cbefb68d ("iommu: of: Handle IOMMU lookup failure with deferred probing or error") Reported-by: Geert Uytterhoeven Tested-by: Magnus Damn Signed-off-by: Sricharan R Signed-off-by: Joerg Roedel --- drivers/iommu/of_iommu.c | 6 ++++++ drivers/of/device.c | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c index e6e9bec42e5f..19779b88a479 100644 --- a/drivers/iommu/of_iommu.c +++ b/drivers/iommu/of_iommu.c @@ -237,6 +237,12 @@ const struct iommu_ops *of_iommu_configure(struct device *dev, ops = ERR_PTR(err); } + /* Ignore all other errors apart from EPROBE_DEFER */ + if (IS_ERR(ops) && (PTR_ERR(ops) != -EPROBE_DEFER)) { + dev_dbg(dev, "Adding to IOMMU failed: %ld\n", PTR_ERR(ops)); + ops = NULL; + } + return ops; } diff --git a/drivers/of/device.c b/drivers/of/device.c index 9416d052cb89..28c38c756f92 100644 --- a/drivers/of/device.c +++ b/drivers/of/device.c @@ -144,8 +144,8 @@ int of_dma_configure(struct device *dev, struct device_node *np) coherent ? " " : " not "); iommu = of_iommu_configure(dev, np); - if (IS_ERR(iommu)) - return PTR_ERR(iommu); + if (IS_ERR(iommu) && PTR_ERR(iommu) == -EPROBE_DEFER) + return -EPROBE_DEFER; dev_dbg(dev, "device is%sbehind an iommu\n", iommu ? " " : " not "); -- cgit v1.2.3 From 058f8c3fb44d028ba44c2e3635d8bee9787018d6 Mon Sep 17 00:00:00 2001 From: Sricharan R Date: Sat, 27 May 2017 19:17:42 +0530 Subject: ACPI/IORT: Ignore all errors except EPROBE_DEFER While deferring the probe of IOMMU masters, xlate and add_device callbacks called from iort_iommu_configure can pass back error values like -ENODEV, which means the IOMMU cannot be connected with that master for real reasons. Before the IOMMU probe deferral, all such errors were ignored. Now all those errors are propagated back, killing the master's probe for such errors. Instead ignore all the errors except EPROBE_DEFER, which is the only one of concern and let the master work without IOMMU, thus restoring the old behavior. Also make explicit that acpi_dma_configure handles only -EPROBE_DEFER from iort_iommu_configure. Fixes: 5a1bb638d567 ("drivers: acpi: Handle IOMMU lookup failure with deferred probing or error") Signed-off-by: Sricharan R Signed-off-by: Joerg Roedel --- drivers/acpi/arm64/iort.c | 6 ++++++ drivers/acpi/scan.c | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c index c5fecf97ee2f..16e101f1f69d 100644 --- a/drivers/acpi/arm64/iort.c +++ b/drivers/acpi/arm64/iort.c @@ -782,6 +782,12 @@ const struct iommu_ops *iort_iommu_configure(struct device *dev) if (err) ops = ERR_PTR(err); + /* Ignore all other errors apart from EPROBE_DEFER */ + if (IS_ERR(ops) && (PTR_ERR(ops) != -EPROBE_DEFER)) { + dev_dbg(dev, "Adding to IOMMU failed: %ld\n", PTR_ERR(ops)); + ops = NULL; + } + return ops; } diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index e39ec7b7cb67..3a10d7573477 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1371,8 +1371,8 @@ int acpi_dma_configure(struct device *dev, enum dev_dma_attr attr) iort_set_dma_mask(dev); iommu = iort_iommu_configure(dev); - if (IS_ERR(iommu)) - return PTR_ERR(iommu); + if (IS_ERR(iommu) && PTR_ERR(iommu) == -EPROBE_DEFER) + return -EPROBE_DEFER; size = max(dev->coherent_dma_mask, dev->coherent_dma_mask + 1); /* -- cgit v1.2.3 From a93a121a96531b99d6feb8db96417b49e1bb28e8 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sat, 27 May 2017 19:17:43 +0530 Subject: ARM: dma-mapping: Don't tear down third-party mappings arch_setup_dma_ops() is used in device probe code paths to create an IOMMU mapping and attach it to the device. The function assumes that the device is attached to a device-specific IOMMU instance (or at least a device-specific TLB in a shared IOMMU instance) and thus creates a separate mapping for every device. On several systems (Renesas R-Car Gen2 being one of them), that assumption is not true, and IOMMU mappings must be shared between multiple devices. In those cases the IOMMU driver knows better than the generic ARM dma-mapping layer and attaches mapping to devices manually with arm_iommu_attach_device(), which sets the DMA ops for the device. The arch_setup_dma_ops() function takes this into account and bails out immediately if the device already has DMA ops assigned. However, the corresponding arch_teardown_dma_ops() function, called from driver unbind code paths (including probe deferral), will tear the mapping down regardless of who created it. When the device is reprobed arch_setup_dma_ops() will be called again but won't perform any operation as the DMA ops will still be set. We need to reset the DMA ops in arch_teardown_dma_ops() to fix this. However, we can't do so unconditionally, as then a new mapping would be created by arch_setup_dma_ops() when the device is reprobed, regardless of whether the device needs to share a mapping or not. We must thus keep track of whether arch_setup_dma_ops() created the mapping, and only in that case tear it down in arch_teardown_dma_ops(). Keep track of that information in the dev_archdata structure. As the structure is embedded in all instances of struct device let's not grow it, but turn the existing dma_coherent bool field into a bitfield that can be used for other purposes. Fixes: 09515ef5ddad ("of/acpi: Configure dma operations at probe time for platform/amba/pci bus devices") Reviewed-by: Robin Murphy Signed-off-by: Laurent Pinchart Signed-off-by: Joerg Roedel --- arch/arm/include/asm/device.h | 3 ++- arch/arm/mm/dma-mapping.c | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/arm/include/asm/device.h b/arch/arm/include/asm/device.h index 36ec9c8f6e16..3234fe9bba6e 100644 --- a/arch/arm/include/asm/device.h +++ b/arch/arm/include/asm/device.h @@ -19,7 +19,8 @@ struct dev_archdata { #ifdef CONFIG_XEN const struct dma_map_ops *dev_dma_ops; #endif - bool dma_coherent; + unsigned int dma_coherent:1; + unsigned int dma_ops_setup:1; }; struct omap_device; diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index c742dfd2967b..b48998f90bfb 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -2430,9 +2430,13 @@ void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size, dev->dma_ops = xen_dma_ops; } #endif + dev->archdata.dma_ops_setup = true; } void arch_teardown_dma_ops(struct device *dev) { + if (!dev->archdata.dma_ops_setup) + return; + arm_teardown_iommu_dma_ops(dev); } -- cgit v1.2.3 From 4dac3210c54a04be9c187dd31b4debb46e3d792b Mon Sep 17 00:00:00 2001 From: Lorenzo Pieralisi Date: Sat, 27 May 2017 19:17:44 +0530 Subject: ACPI/IORT: Move the check to get iommu_ops from translated fwspec With IOMMU probe deferral, iort_iommu_configure can be called multiple times for the same device. Hence we have a check to see if the device's fwspec is already translated and return the iommu_ops from that directly. But the check is wrongly placed in iort_iommu_xlate, which breaks devices with multiple sids. Move the check to iort_iommu_configure. Fixes: 5a1bb638d567 ("drivers: acpi: Handle IOMMU lookup failure with deferred probing or error") Tested-by: Nate Watterson Signed-off-by: Lorenzo Pieralisi Signed-off-by: Joerg Roedel --- drivers/acpi/arm64/iort.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c index 16e101f1f69d..797b28dc7b34 100644 --- a/drivers/acpi/arm64/iort.c +++ b/drivers/acpi/arm64/iort.c @@ -666,14 +666,6 @@ static const struct iommu_ops *iort_iommu_xlate(struct device *dev, int ret = -ENODEV; struct fwnode_handle *iort_fwnode; - /* - * If we already translated the fwspec there - * is nothing left to do, return the iommu_ops. - */ - ops = iort_fwspec_iommu_ops(dev->iommu_fwspec); - if (ops) - return ops; - if (node) { iort_fwnode = iort_get_fwnode(node); if (!iort_fwnode) @@ -735,6 +727,14 @@ const struct iommu_ops *iort_iommu_configure(struct device *dev) u32 streamid = 0; int err; + /* + * If we already translated the fwspec there + * is nothing left to do, return the iommu_ops. + */ + ops = iort_fwspec_iommu_ops(dev->iommu_fwspec); + if (ops) + return ops; + if (dev_is_pci(dev)) { struct pci_bus *bus = to_pci_dev(dev)->bus; u32 rid; -- cgit v1.2.3 From d3e01c51598b2639a4830549058500e5f2ace86f Mon Sep 17 00:00:00 2001 From: Sricharan R Date: Sat, 27 May 2017 19:17:45 +0530 Subject: arm: dma-mapping: Reset the device's dma_ops arch_teardown_dma_ops() being the inverse of arch_setup_dma_ops() ,dma_ops should be cleared in the teardown path. Currently, only the device's iommu mapping structures are cleared in arch_teardown_dma_ops, but not the dma_ops. So on the next reprobe, dma_ops left in place is stale from the first IOMMU setup, but iommu mappings has been disposed of. This is a problem when the probe of the device is deferred and recalled with the IOMMU probe deferral. So for fixing this, slightly refactor by moving the code from __arm_iommu_detach_device to arm_iommu_detach_device and cleanup the former. This takes care of resetting the dma_ops in the teardown path. Fixes: 09515ef5ddad ("of/acpi: Configure dma operations at probe time for platform/amba/pci bus devices") Reviewed-by: Laurent Pinchart Signed-off-by: Sricharan R Signed-off-by: Joerg Roedel --- arch/arm/mm/dma-mapping.c | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index b48998f90bfb..bd83c531828a 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -2311,7 +2311,14 @@ int arm_iommu_attach_device(struct device *dev, } EXPORT_SYMBOL_GPL(arm_iommu_attach_device); -static void __arm_iommu_detach_device(struct device *dev) +/** + * arm_iommu_detach_device + * @dev: valid struct device pointer + * + * Detaches the provided device from a previously attached map. + * This voids the dma operations (dma_map_ops pointer) + */ +void arm_iommu_detach_device(struct device *dev) { struct dma_iommu_mapping *mapping; @@ -2324,22 +2331,10 @@ static void __arm_iommu_detach_device(struct device *dev) iommu_detach_device(mapping->domain, dev); kref_put(&mapping->kref, release_iommu_mapping); to_dma_iommu_mapping(dev) = NULL; + set_dma_ops(dev, NULL); pr_debug("Detached IOMMU controller from %s device.\n", dev_name(dev)); } - -/** - * arm_iommu_detach_device - * @dev: valid struct device pointer - * - * Detaches the provided device from a previously attached map. - * This voids the dma operations (dma_map_ops pointer) - */ -void arm_iommu_detach_device(struct device *dev) -{ - __arm_iommu_detach_device(dev); - set_dma_ops(dev, NULL); -} EXPORT_SYMBOL_GPL(arm_iommu_detach_device); static const struct dma_map_ops *arm_get_iommu_dma_map_ops(bool coherent) @@ -2379,7 +2374,7 @@ static void arm_teardown_iommu_dma_ops(struct device *dev) if (!mapping) return; - __arm_iommu_detach_device(dev); + arm_iommu_detach_device(dev); arm_iommu_release_mapping(mapping); } -- cgit v1.2.3 From f434b1c4aba5cc4e5bae4399a965b5fd14011d69 Mon Sep 17 00:00:00 2001 From: Sekhar Nori Date: Thu, 25 May 2017 15:08:07 +0530 Subject: MAINTAINERS: add device-tree files to TI DaVinci entry Add device-tree files relevant to TI DaVinci platform to its entry so mach-davinci sub-arch maintainers get copied on patches with device-tree file updates. Signed-off-by: Sekhar Nori --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index f7d568b8f133..a3e559bdb452 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11775,6 +11775,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/nsekhar/linux-davinci.git S: Supported F: arch/arm/mach-davinci/ F: drivers/i2c/busses/i2c-davinci.c +F: arch/arm/boot/dts/da850* TI DAVINCI SERIES MEDIA DRIVER M: "Lad, Prabhakar" -- cgit v1.2.3 From 477c50e8dc1c7b5004e099b8b74ca8b70be2f4fd Mon Sep 17 00:00:00 2001 From: Wei Huang Date: Tue, 30 May 2017 11:56:22 +0100 Subject: drivers/perf: arm_pmu_acpi: avoid perf IRQ init when guest PMU is off We saw perf IRQ init failures when running Linux kernel in an ACPI guest without PMU (i.e. pmu=off). This is because perf IRQ is not present when pmu=off, but arm_pmu_acpi still tries to register or unregister GSI. This patch addresses the problem by checking gicc->performance_interrupt. If it is 0, which is the value set by qemu when pmu=off, we skip the IRQ register/unregister process. [ 4.069470] bc00: 0000000000040b00 ffff0000089db190 [ 4.070267] [] enable_percpu_irq+0xdc/0xe4 [ 4.071192] [] arm_perf_starting_cpu+0x108/0x10c [ 4.072200] [] cpuhp_invoke_callback+0x14c/0x4ac [ 4.073210] [] cpuhp_thread_fun+0xd4/0x11c [ 4.074132] [] smpboot_thread_fn+0x1b4/0x1c4 [ 4.075081] [] kthread+0x10c/0x138 [ 4.075921] [] ret_from_fork+0x10/0x50 [ 4.076947] genirq: Setting trigger mode 4 for irq 43 failed (gic_set_type+0x0/0x74) Signed-off-by: Wei Huang [will: add comment justifying deviation from ACPI spec, removed redundant hunk] Signed-off-by: Will Deacon Signed-off-by: Catalin Marinas --- drivers/perf/arm_pmu_acpi.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/perf/arm_pmu_acpi.c b/drivers/perf/arm_pmu_acpi.c index 34c862f213c7..0a9b78705ee8 100644 --- a/drivers/perf/arm_pmu_acpi.c +++ b/drivers/perf/arm_pmu_acpi.c @@ -29,6 +29,17 @@ static int arm_pmu_acpi_register_irq(int cpu) return -EINVAL; gsi = gicc->performance_interrupt; + + /* + * Per the ACPI spec, the MADT cannot describe a PMU that doesn't + * have an interrupt. QEMU advertises this by using a GSI of zero, + * which is not known to be valid on any hardware despite being + * valid per the spec. Take the pragmatic approach and reject a + * GSI of zero for now. + */ + if (!gsi) + return 0; + if (gicc->flags & ACPI_MADT_PERFORMANCE_IRQ_MODE) trigger = ACPI_EDGE_SENSITIVE; else -- cgit v1.2.3 From af622b86665881ffa96bc77fb89c94fae02cfa6b Mon Sep 17 00:00:00 2001 From: Ilya Dryomov Date: Tue, 23 May 2017 17:49:54 +0200 Subject: nbd: nbd_reset() call in nbd_dev_add() is redundant There is nothing to clear -- nbd_device has just been allocated. Fold nbd_reset() into its other caller, nbd_config_put(). Signed-off-by: Ilya Dryomov Reviewed-by: Josef Bacik Signed-off-by: Jens Axboe --- drivers/block/nbd.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 9a7bb2c29447..e725d8d5ab0b 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -937,14 +937,6 @@ static int nbd_reconnect_socket(struct nbd_device *nbd, unsigned long arg) return -ENOSPC; } -/* Reset all properties of an NBD device */ -static void nbd_reset(struct nbd_device *nbd) -{ - nbd->config = NULL; - nbd->tag_set.timeout = 0; - queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, nbd->disk->queue); -} - static void nbd_bdev_reset(struct block_device *bdev) { if (bdev->bd_openers > 1) @@ -1029,7 +1021,10 @@ static void nbd_config_put(struct nbd_device *nbd) } kfree(config->socks); } - nbd_reset(nbd); + nbd->config = NULL; + + nbd->tag_set.timeout = 0; + queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, nbd->disk->queue); mutex_unlock(&nbd->config_lock); nbd_put(nbd); @@ -1483,7 +1478,6 @@ static int nbd_dev_add(int index) disk->fops = &nbd_fops; disk->private_data = nbd; sprintf(disk->disk_name, "nbd%d", index); - nbd_reset(nbd); add_disk(disk); nbd_total_devices++; return index; -- cgit v1.2.3 From fa9765323a93473d3853d04c9903958453c92ad4 Mon Sep 17 00:00:00 2001 From: Ilya Dryomov Date: Tue, 23 May 2017 17:49:55 +0200 Subject: nbd: don't leak nbd_config nbd_config is allocated in nbd_alloc_config(), but never freed. Fixes: 5ea8d10802ec ("nbd: separate out the config information") Signed-off-by: Ilya Dryomov Reviewed-by: Josef Bacik Signed-off-by: Jens Axboe --- drivers/block/nbd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index e725d8d5ab0b..f3f191ba8ca4 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -1021,6 +1021,7 @@ static void nbd_config_put(struct nbd_device *nbd) } kfree(config->socks); } + kfree(nbd->config); nbd->config = NULL; nbd->tag_set.timeout = 0; -- cgit v1.2.3 From cbf712792b6e61317b93dd56dd5c0784363c9ac9 Mon Sep 17 00:00:00 2001 From: Radim Krčmář Date: Fri, 19 May 2017 15:48:51 +0200 Subject: KVM: nVMX: fix nested_vmx_check_vmptr failure paths under debugging MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit kvm_skip_emulated_instruction() will return 0 if userspace is single-stepping the guest. kvm_skip_emulated_instruction() uses return status convention of exit handler: 0 means "exit to userspace" and 1 means "continue vm entries". The problem is that nested_vmx_check_vmptr() return status means something else: 0 is ok, 1 is error. This means we would continue executing after a failure. Static checker noticed it because vmptr was not initialized. Reported-by: Dan Carpenter Fixes: 6affcbedcac7 ("KVM: x86: Add kvm_skip_emulated_instruction and use it.") Signed-off-by: Radim Krčmář Signed-off-by: Paolo Bonzini --- arch/x86/kvm/vmx.c | 140 ++++++++++++++++++++++------------------------------- 1 file changed, 57 insertions(+), 83 deletions(-) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 880f371705bc..9b4b5d6dcd34 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -6914,97 +6914,21 @@ static int get_vmx_mem_address(struct kvm_vcpu *vcpu, return 0; } -/* - * This function performs the various checks including - * - if it's 4KB aligned - * - No bits beyond the physical address width are set - * - Returns 0 on success or else 1 - * (Intel SDM Section 30.3) - */ -static int nested_vmx_check_vmptr(struct kvm_vcpu *vcpu, int exit_reason, - gpa_t *vmpointer) +static int nested_vmx_get_vmptr(struct kvm_vcpu *vcpu, gpa_t *vmpointer) { gva_t gva; - gpa_t vmptr; struct x86_exception e; - struct page *page; - struct vcpu_vmx *vmx = to_vmx(vcpu); - int maxphyaddr = cpuid_maxphyaddr(vcpu); if (get_vmx_mem_address(vcpu, vmcs_readl(EXIT_QUALIFICATION), vmcs_read32(VMX_INSTRUCTION_INFO), false, &gva)) return 1; - if (kvm_read_guest_virt(&vcpu->arch.emulate_ctxt, gva, &vmptr, - sizeof(vmptr), &e)) { + if (kvm_read_guest_virt(&vcpu->arch.emulate_ctxt, gva, vmpointer, + sizeof(*vmpointer), &e)) { kvm_inject_page_fault(vcpu, &e); return 1; } - switch (exit_reason) { - case EXIT_REASON_VMON: - /* - * SDM 3: 24.11.5 - * The first 4 bytes of VMXON region contain the supported - * VMCS revision identifier - * - * Note - IA32_VMX_BASIC[48] will never be 1 - * for the nested case; - * which replaces physical address width with 32 - * - */ - if (!PAGE_ALIGNED(vmptr) || (vmptr >> maxphyaddr)) { - nested_vmx_failInvalid(vcpu); - return kvm_skip_emulated_instruction(vcpu); - } - - page = nested_get_page(vcpu, vmptr); - if (page == NULL) { - nested_vmx_failInvalid(vcpu); - return kvm_skip_emulated_instruction(vcpu); - } - if (*(u32 *)kmap(page) != VMCS12_REVISION) { - kunmap(page); - nested_release_page_clean(page); - nested_vmx_failInvalid(vcpu); - return kvm_skip_emulated_instruction(vcpu); - } - kunmap(page); - nested_release_page_clean(page); - vmx->nested.vmxon_ptr = vmptr; - break; - case EXIT_REASON_VMCLEAR: - if (!PAGE_ALIGNED(vmptr) || (vmptr >> maxphyaddr)) { - nested_vmx_failValid(vcpu, - VMXERR_VMCLEAR_INVALID_ADDRESS); - return kvm_skip_emulated_instruction(vcpu); - } - - if (vmptr == vmx->nested.vmxon_ptr) { - nested_vmx_failValid(vcpu, - VMXERR_VMCLEAR_VMXON_POINTER); - return kvm_skip_emulated_instruction(vcpu); - } - break; - case EXIT_REASON_VMPTRLD: - if (!PAGE_ALIGNED(vmptr) || (vmptr >> maxphyaddr)) { - nested_vmx_failValid(vcpu, - VMXERR_VMPTRLD_INVALID_ADDRESS); - return kvm_skip_emulated_instruction(vcpu); - } - - if (vmptr == vmx->nested.vmxon_ptr) { - nested_vmx_failValid(vcpu, - VMXERR_VMPTRLD_VMXON_POINTER); - return kvm_skip_emulated_instruction(vcpu); - } - break; - default: - return 1; /* shouldn't happen */ - } - - if (vmpointer) - *vmpointer = vmptr; return 0; } @@ -7066,6 +6990,8 @@ out_msr_bitmap: static int handle_vmon(struct kvm_vcpu *vcpu) { int ret; + gpa_t vmptr; + struct page *page; struct vcpu_vmx *vmx = to_vmx(vcpu); const u64 VMXON_NEEDED_FEATURES = FEATURE_CONTROL_LOCKED | FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX; @@ -7095,9 +7021,37 @@ static int handle_vmon(struct kvm_vcpu *vcpu) return 1; } - if (nested_vmx_check_vmptr(vcpu, EXIT_REASON_VMON, NULL)) + if (nested_vmx_get_vmptr(vcpu, &vmptr)) return 1; - + + /* + * SDM 3: 24.11.5 + * The first 4 bytes of VMXON region contain the supported + * VMCS revision identifier + * + * Note - IA32_VMX_BASIC[48] will never be 1 for the nested case; + * which replaces physical address width with 32 + */ + if (!PAGE_ALIGNED(vmptr) || (vmptr >> cpuid_maxphyaddr(vcpu))) { + nested_vmx_failInvalid(vcpu); + return kvm_skip_emulated_instruction(vcpu); + } + + page = nested_get_page(vcpu, vmptr); + if (page == NULL) { + nested_vmx_failInvalid(vcpu); + return kvm_skip_emulated_instruction(vcpu); + } + if (*(u32 *)kmap(page) != VMCS12_REVISION) { + kunmap(page); + nested_release_page_clean(page); + nested_vmx_failInvalid(vcpu); + return kvm_skip_emulated_instruction(vcpu); + } + kunmap(page); + nested_release_page_clean(page); + + vmx->nested.vmxon_ptr = vmptr; ret = enter_vmx_operation(vcpu); if (ret) return ret; @@ -7213,9 +7167,19 @@ static int handle_vmclear(struct kvm_vcpu *vcpu) if (!nested_vmx_check_permission(vcpu)) return 1; - if (nested_vmx_check_vmptr(vcpu, EXIT_REASON_VMCLEAR, &vmptr)) + if (nested_vmx_get_vmptr(vcpu, &vmptr)) return 1; + if (!PAGE_ALIGNED(vmptr) || (vmptr >> cpuid_maxphyaddr(vcpu))) { + nested_vmx_failValid(vcpu, VMXERR_VMCLEAR_INVALID_ADDRESS); + return kvm_skip_emulated_instruction(vcpu); + } + + if (vmptr == vmx->nested.vmxon_ptr) { + nested_vmx_failValid(vcpu, VMXERR_VMCLEAR_VMXON_POINTER); + return kvm_skip_emulated_instruction(vcpu); + } + if (vmptr == vmx->nested.current_vmptr) nested_release_vmcs12(vmx); @@ -7545,9 +7509,19 @@ static int handle_vmptrld(struct kvm_vcpu *vcpu) if (!nested_vmx_check_permission(vcpu)) return 1; - if (nested_vmx_check_vmptr(vcpu, EXIT_REASON_VMPTRLD, &vmptr)) + if (nested_vmx_get_vmptr(vcpu, &vmptr)) return 1; + if (!PAGE_ALIGNED(vmptr) || (vmptr >> cpuid_maxphyaddr(vcpu))) { + nested_vmx_failValid(vcpu, VMXERR_VMPTRLD_INVALID_ADDRESS); + return kvm_skip_emulated_instruction(vcpu); + } + + if (vmptr == vmx->nested.vmxon_ptr) { + nested_vmx_failValid(vcpu, VMXERR_VMPTRLD_VMXON_POINTER); + return kvm_skip_emulated_instruction(vcpu); + } + if (vmx->nested.current_vmptr != vmptr) { struct vmcs12 *new_vmcs12; struct page *page; -- cgit v1.2.3 From 8eae9570d1d3887487be0b355d12656b46fac226 Mon Sep 17 00:00:00 2001 From: Gioh Kim Date: Tue, 30 May 2017 15:24:45 +0200 Subject: KVM: SVM: ignore type when setting segment registers Commit 19bca6ab75d8 ("KVM: SVM: Fix cross vendor migration issue with unusable bit") added checking type when setting unusable. So unusable can be set if present is 0 OR type is 0. According to the AMD processor manual, long mode ignores the type value in segment descriptor. And type can be 0 if it is read-only data segment. Therefore type value is not related to unusable flag. This patch is based on linux-next v4.12.0-rc3. Signed-off-by: Gioh Kim Signed-off-by: Paolo Bonzini --- arch/x86/kvm/svm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 183ddb235fb4..a654372efea1 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -1807,7 +1807,7 @@ static void svm_get_segment(struct kvm_vcpu *vcpu, * AMD's VMCB does not have an explicit unusable field, so emulate it * for cross vendor migration purposes by "not present" */ - var->unusable = !var->present || (var->type == 0); + var->unusable = !var->present; switch (seg) { case VCPU_SREG_TR: -- cgit v1.2.3 From 025d0973a0ec2121c6fd0da59e8cc3829fbb221e Mon Sep 17 00:00:00 2001 From: "Guilherme G. Piccoli" Date: Sun, 28 May 2017 23:07:01 -0300 Subject: cxgb4: avoid crash on PCI error recovery path During PCI error recovery process, specifically on eeh_err_detected() we might have a NULL netdev struct, hence a direct dereference will lead to a kernel oops. This was observed with latest upstream kernel (v4.12-rc2) on Chelsio adapter T422-CR in PowerPC machines. This patch checks for NULL pointer and avoids the crash, both in eeh_err_detected() and eeh_resume(). Also, we avoid to trigger a fatal error or to try disabling interrupts on FW during PCI error recovery, because: (a) driver might not be able to accurately access PCI regions in this case, and (b) trigger a fatal error _during_ the recovery steps is a mistake that could prevent the recovery path to complete successfully. Reported-by: Harsha Thyagaraja Signed-off-by: Guilherme G. Piccoli Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 21 +++++++++++++-------- drivers/net/ethernet/chelsio/cxgb4/t4_hw.c | 9 +++++++-- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index 38a5c6764bb5..b512149684fd 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -2771,6 +2771,9 @@ void t4_fatal_err(struct adapter *adap) { int port; + if (pci_channel_offline(adap->pdev)) + return; + /* Disable the SGE since ULDs are going to free resources that * could be exposed to the adapter. RDMA MWs for example... */ @@ -3882,9 +3885,10 @@ static pci_ers_result_t eeh_err_detected(struct pci_dev *pdev, spin_lock(&adap->stats_lock); for_each_port(adap, i) { struct net_device *dev = adap->port[i]; - - netif_device_detach(dev); - netif_carrier_off(dev); + if (dev) { + netif_device_detach(dev); + netif_carrier_off(dev); + } } spin_unlock(&adap->stats_lock); disable_interrupts(adap); @@ -3963,12 +3967,13 @@ static void eeh_resume(struct pci_dev *pdev) rtnl_lock(); for_each_port(adap, i) { struct net_device *dev = adap->port[i]; - - if (netif_running(dev)) { - link_start(dev); - cxgb_set_rxmode(dev); + if (dev) { + if (netif_running(dev)) { + link_start(dev); + cxgb_set_rxmode(dev); + } + netif_device_attach(dev); } - netif_device_attach(dev); } rtnl_unlock(); } diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c index aded42b96f6d..3a34aa629f7d 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c @@ -4557,8 +4557,13 @@ void t4_intr_enable(struct adapter *adapter) */ void t4_intr_disable(struct adapter *adapter) { - u32 whoami = t4_read_reg(adapter, PL_WHOAMI_A); - u32 pf = CHELSIO_CHIP_VERSION(adapter->params.chip) <= CHELSIO_T5 ? + u32 whoami, pf; + + if (pci_channel_offline(adapter->pdev)) + return; + + whoami = t4_read_reg(adapter, PL_WHOAMI_A); + pf = CHELSIO_CHIP_VERSION(adapter->params.chip) <= CHELSIO_T5 ? SOURCEPF_G(whoami) : T6_SOURCEPF_G(whoami); t4_write_reg(adapter, MYPF_REG(PL_PF_INT_ENABLE_A), 0); -- cgit v1.2.3 From 5ee6842cd8aff517701549463927cb1e5eb50b01 Mon Sep 17 00:00:00 2001 From: Madalin Bucur Date: Mon, 29 May 2017 09:22:06 +0300 Subject: Documentation: networking: add DPAA Ethernet document Signed-off-by: Madalin Bucur Signed-off-by: Camelia Groza Signed-off-by: David S. Miller --- Documentation/networking/dpaa.txt | 194 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 194 insertions(+) create mode 100644 Documentation/networking/dpaa.txt diff --git a/Documentation/networking/dpaa.txt b/Documentation/networking/dpaa.txt new file mode 100644 index 000000000000..76e016d4d344 --- /dev/null +++ b/Documentation/networking/dpaa.txt @@ -0,0 +1,194 @@ +The QorIQ DPAA Ethernet Driver +============================== + +Authors: +Madalin Bucur +Camelia Groza + +Contents +======== + + - DPAA Ethernet Overview + - DPAA Ethernet Supported SoCs + - Configuring DPAA Ethernet in your kernel + - DPAA Ethernet Frame Processing + - DPAA Ethernet Features + - Debugging + +DPAA Ethernet Overview +====================== + +DPAA stands for Data Path Acceleration Architecture and it is a +set of networking acceleration IPs that are available on several +generations of SoCs, both on PowerPC and ARM64. + +The Freescale DPAA architecture consists of a series of hardware blocks +that support Ethernet connectivity. The Ethernet driver depends upon the +following drivers in the Linux kernel: + + - Peripheral Access Memory Unit (PAMU) (* needed only for PPC platforms) + drivers/iommu/fsl_* + - Frame Manager (FMan) + drivers/net/ethernet/freescale/fman + - Queue Manager (QMan), Buffer Manager (BMan) + drivers/soc/fsl/qbman + +A simplified view of the dpaa_eth interfaces mapped to FMan MACs: + + dpaa_eth /eth0\ ... /ethN\ + driver | | | | + ------------- ---- ----------- ---- ------------- + -Ports / Tx Rx \ ... / Tx Rx \ + FMan | | | | + -MACs | MAC0 | | MACN | + / dtsec0 \ ... / dtsecN \ (or tgec) + / \ / \(or memac) + --------- -------------- --- -------------- --------- + FMan, FMan Port, FMan SP, FMan MURAM drivers + --------------------------------------------------------- + FMan HW blocks: MURAM, MACs, Ports, SP + --------------------------------------------------------- + +The dpaa_eth relation to the QMan, BMan and FMan: + ________________________________ + dpaa_eth / eth0 \ + driver / \ + --------- -^- -^- -^- --- --------- + QMan driver / \ / \ / \ \ / | BMan | + |Rx | |Rx | |Tx | |Tx | | driver | + --------- |Dfl| |Err| |Cnf| |FQs| | | + QMan HW |FQ | |FQ | |FQs| | | | | + / \ / \ / \ \ / | | + --------- --- --- --- -v- --------- + | FMan QMI | | + | FMan HW FMan BMI | BMan HW | + ----------------------- -------- + +where the acronyms used above (and in the code) are: +DPAA = Data Path Acceleration Architecture +FMan = DPAA Frame Manager +QMan = DPAA Queue Manager +BMan = DPAA Buffers Manager +QMI = QMan interface in FMan +BMI = BMan interface in FMan +FMan SP = FMan Storage Profiles +MURAM = Multi-user RAM in FMan +FQ = QMan Frame Queue +Rx Dfl FQ = default reception FQ +Rx Err FQ = Rx error frames FQ +Tx Cnf FQ = Tx confirmation FQs +Tx FQs = transmission frame queues +dtsec = datapath three speed Ethernet controller (10/100/1000 Mbps) +tgec = ten gigabit Ethernet controller (10 Gbps) +memac = multirate Ethernet MAC (10/100/1000/10000) + +DPAA Ethernet Supported SoCs +============================ + +The DPAA drivers enable the Ethernet controllers present on the following SoCs: + +# PPC +P1023 +P2041 +P3041 +P4080 +P5020 +P5040 +T1023 +T1024 +T1040 +T1042 +T2080 +T4240 +B4860 + +# ARM +LS1043A +LS1046A + +Configuring DPAA Ethernet in your kernel +======================================== + +To enable the DPAA Ethernet driver, the following Kconfig options are required: + +# common for arch/arm64 and arch/powerpc platforms +CONFIG_FSL_DPAA=y +CONFIG_FSL_FMAN=y +CONFIG_FSL_DPAA_ETH=y +CONFIG_FSL_XGMAC_MDIO=y + +# for arch/powerpc only +CONFIG_FSL_PAMU=y + +# common options needed for the PHYs used on the RDBs +CONFIG_VITESSE_PHY=y +CONFIG_REALTEK_PHY=y +CONFIG_AQUANTIA_PHY=y + +DPAA Ethernet Frame Processing +============================== + +On Rx, buffers for the incoming frames are retrieved from one of the three +existing buffers pools. The driver initializes and seeds these, each with +buffers of different sizes: 1KB, 2KB and 4KB. + +On Tx, all transmitted frames are returned to the driver through Tx +confirmation frame queues. The driver is then responsible for freeing the +buffers. In order to do this properly, a backpointer is added to the buffer +before transmission that points to the skb. When the buffer returns to the +driver on a confirmation FQ, the skb can be correctly consumed. + +DPAA Ethernet Features +====================== + +Currently the DPAA Ethernet driver enables the basic features required for +a Linux Ethernet driver. The support for advanced features will be added +gradually. + +The driver has Rx and Tx checksum offloading for UDP and TCP. Currently the Rx +checksum offload feature is enabled by default and cannot be controlled through +ethtool. + +The driver has support for multiple prioritized Tx traffic classes. Priorities +range from 0 (lowest) to 3 (highest). These are mapped to HW workqueues with +strict priority levels. Each traffic class contains NR_CPU TX queues. By +default, only one traffic class is enabled and the lowest priority Tx queues +are used. Higher priority traffic classes can be enabled with the mqprio +qdisc. For example, all four traffic classes are enabled on an interface with +the following command. Furthermore, skb priority levels are mapped to traffic +classes as follows: + + * priorities 0 to 3 - traffic class 0 (low priority) + * priorities 4 to 7 - traffic class 1 (medium-low priority) + * priorities 8 to 11 - traffic class 2 (medium-high priority) + * priorities 12 to 15 - traffic class 3 (high priority) + +tc qdisc add dev root handle 1: \ + mqprio num_tc 4 map 0 0 0 0 1 1 1 1 2 2 2 2 3 3 3 3 hw 1 + +Debugging +========= + +The following statistics are exported for each interface through ethtool: + + - interrupt count per CPU + - Rx packets count per CPU + - Tx packets count per CPU + - Tx confirmed packets count per CPU + - Tx S/G frames count per CPU + - Tx error count per CPU + - Rx error count per CPU + - Rx error count per type + - congestion related statistics: + - congestion status + - time spent in congestion + - number of time the device entered congestion + - dropped packets count per cause + +The driver also exports the following information in sysfs: + + - the FQ IDs for each FQ type + /sys/devices/platform/dpaa-ethernet.0/net//fqids + + - the IDs of the buffer pools in use + /sys/devices/platform/dpaa-ethernet.0/net//bpids -- cgit v1.2.3 From 512c7840cd692fdac0333684249753ebf3c819f9 Mon Sep 17 00:00:00 2001 From: "Mintz, Yuval" Date: Mon, 29 May 2017 11:24:49 +0300 Subject: qed: Don't log missing periodic stats by default Current implementation lacks the logic for providing management firmware with RDMA-related statistics; [much] worse than that - it logs such events by default to system logs. Since the statistics' gathering is done periodically, using sufficiently new management firmware the system logs would get filled with these unnecessary prints. For now, reduce the verbosity of the log so that it would not be logged by default. Fixes: 6c75424612a7 ("qed: Add support for NCSI statistics") Signed-off-by: Yuval Mintz Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c index 537d1236a4fe..715b3aaf83ac 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_main.c +++ b/drivers/net/ethernet/qlogic/qed/qed_main.c @@ -1730,7 +1730,8 @@ void qed_get_protocol_stats(struct qed_dev *cdev, qed_get_protocol_stats_iscsi(cdev, &stats->iscsi_stats); break; default: - DP_ERR(cdev, "Invalid protocol type = %d\n", type); + DP_VERBOSE(cdev, QED_MSG_SP, + "Invalid protocol type = %d\n", type); return; } } -- cgit v1.2.3 From 59b2c3140f329e5817197f84860f3fa61a742fdf Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 29 May 2017 14:56:01 +0200 Subject: net: dsa: mv88e6xxx: Add missing static to stub functions 'static' was not enough, the helpers must be 'static inline' net/dsa/mv88e6xxx/global2.h:123:12: error: 'mv88e6xxx_g2_misc_4_bit_port' defined but not used [-Werror=unused-function] net/dsa/mv88e6xxx/global2.h:117:12: error: 'mv88e6xxx_g2_pvt_write' defined but not used [-Werror=unused-function] Fixes: c21fbe29f858 ("net: dsa: mv88e6xxx: Add missing static to stub functions") Signed-off-by: Arnd Bergmann Reviewed-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/global2.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/global2.h b/drivers/net/dsa/mv88e6xxx/global2.h index d8d3c5abb2a1..14c0be98e0a4 100644 --- a/drivers/net/dsa/mv88e6xxx/global2.h +++ b/drivers/net/dsa/mv88e6xxx/global2.h @@ -114,13 +114,13 @@ static inline int mv88e6xxx_g2_set_eeprom16(struct mv88e6xxx_chip *chip, return -EOPNOTSUPP; } -static int mv88e6xxx_g2_pvt_write(struct mv88e6xxx_chip *chip, int src_dev, - int src_port, u16 data) +static inline int mv88e6xxx_g2_pvt_write(struct mv88e6xxx_chip *chip, + int src_dev, int src_port, u16 data) { return -EOPNOTSUPP; } -static int mv88e6xxx_g2_misc_4_bit_port(struct mv88e6xxx_chip *chip) +static inline int mv88e6xxx_g2_misc_4_bit_port(struct mv88e6xxx_chip *chip) { return -EOPNOTSUPP; } -- cgit v1.2.3 From f0d7ae95fff4ab444b8433f07afc4b077ef1a285 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 29 May 2017 15:00:17 +0200 Subject: net/mlx5: avoid build warning for uniprocessor Building the driver with CONFIG_SMP disabled results in a harmless warning: ethernet/mellanox/mlx5/core/main.c: In function 'mlx5_irq_set_affinity_hint': ethernet/mellanox/mlx5/core/main.c:615:6: error: unused variable 'irq' [-Werror=unused-variable] It's better to express the conditional compilation using IS_ENABLED() here, as that lets the compiler see what the intented use for the variable is, and that it can be silently discarded. Fixes: b665d98edc9a ("net/mlx5: Tolerate irq_set_affinity_hint() failures") Signed-off-by: Arnd Bergmann Acked-by: Saeed Mahameed Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/main.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index fe5546bb4153..af945edfee19 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -621,10 +621,9 @@ static int mlx5_irq_set_affinity_hint(struct mlx5_core_dev *mdev, int i) cpumask_set_cpu(cpumask_local_spread(i, priv->numa_node), priv->irq_info[i].mask); -#ifdef CONFIG_SMP - if (irq_set_affinity_hint(irq, priv->irq_info[i].mask)) + if (IS_ENABLED(CONFIG_SMP) && + irq_set_affinity_hint(irq, priv->irq_info[i].mask)) mlx5_core_warn(mdev, "irq_set_affinity_hint failed, irq 0x%.4x", irq); -#endif return 0; } -- cgit v1.2.3 From 5a1d08726230ead4817e9c22f2736b9ff21bf6af Mon Sep 17 00:00:00 2001 From: Tariq Toukan Date: Tue, 30 May 2017 11:44:04 +0300 Subject: MAINTAINERS: Update MELLANOX MLX4 core VPI driver maintainer Add myself as a maintainer for mlx4 core driver, replacing Yishai Hadas. Signed-off-by: Tariq Toukan Signed-off-by: David S. Miller --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 9e984645c4b0..d9d5398d0a49 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8508,7 +8508,7 @@ S: Odd Fixes F: drivers/media/radio/radio-miropcm20* MELLANOX MLX4 core VPI driver -M: Yishai Hadas +M: Tariq Toukan L: netdev@vger.kernel.org L: linux-rdma@vger.kernel.org W: http://www.mellanox.com -- cgit v1.2.3 From 39acf4e242621bd2b5d992a7ef2fd3358065d576 Mon Sep 17 00:00:00 2001 From: Tariq Toukan Date: Tue, 30 May 2017 11:44:05 +0300 Subject: MAINTAINERS: Move mlx4 rdma header file to IB driver charge It belongs there, should not be under mlx4 Core driver. Signed-off-by: Tariq Toukan Signed-off-by: David S. Miller --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index d9d5398d0a49..0dbc20c963c4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8516,7 +8516,6 @@ Q: http://patchwork.ozlabs.org/project/netdev/list/ S: Supported F: drivers/net/ethernet/mellanox/mlx4/ F: include/linux/mlx4/ -F: include/uapi/rdma/mlx4-abi.h MELLANOX MLX4 IB driver M: Yishai Hadas @@ -8526,6 +8525,7 @@ Q: http://patchwork.kernel.org/project/linux-rdma/list/ S: Supported F: drivers/infiniband/hw/mlx4/ F: include/linux/mlx4/ +F: include/uapi/rdma/mlx4-abi.h MELLANOX MLX5 core VPI driver M: Saeed Mahameed -- cgit v1.2.3 From 177567580aa1c3ec6e900b25280a52f02f93469f Mon Sep 17 00:00:00 2001 From: Tariq Toukan Date: Tue, 30 May 2017 11:44:06 +0300 Subject: MAINTAINERS: Move mlx5 rdma header file to IB driver charge It belongs there, should not be under mlx5 Core driver. Signed-off-by: Tariq Toukan Signed-off-by: David S. Miller --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 0dbc20c963c4..0f92a2ff4b12 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8538,7 +8538,6 @@ Q: http://patchwork.ozlabs.org/project/netdev/list/ S: Supported F: drivers/net/ethernet/mellanox/mlx5/core/ F: include/linux/mlx5/ -F: include/uapi/rdma/mlx5-abi.h MELLANOX MLX5 IB driver M: Matan Barak @@ -8549,6 +8548,7 @@ Q: http://patchwork.kernel.org/project/linux-rdma/list/ S: Supported F: drivers/infiniband/hw/mlx5/ F: include/linux/mlx5/ +F: include/uapi/rdma/mlx5-abi.h MELEXIS MLX90614 DRIVER M: Crt Mori -- cgit v1.2.3 From e4dc2b32df5573b077f6723e01cf761d236d5113 Mon Sep 17 00:00:00 2001 From: Keith Busch Date: Tue, 30 May 2017 14:39:11 -0400 Subject: blk-mq: Take tagset lock when updating hw queues The tagset lock needs to be held when iterating the tag_list, so a lockdep assert was added when updating number of hardware queues. The drivers calling this API, however, were unaware of the new requirement, so are failing the assertion. This patch takes the lock within the blk-mq function so the drivers do not have to be modified in order to be safe. Fixes: 705cda97e ("blk-mq: Make it safe to use RCU to iterate over blk_mq_tag_set.tag_list") Reported-by: Gabriel Krisman Bertazi Reviewed-by: Bart Van Assche Signed-off-by: Keith Busch Signed-off-by: Jens Axboe --- block/blk-mq.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/block/blk-mq.c b/block/blk-mq.c index f2224ffd225d..1bcccedcc74f 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -2641,7 +2641,8 @@ int blk_mq_update_nr_requests(struct request_queue *q, unsigned int nr) return ret; } -void blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set, int nr_hw_queues) +static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set, + int nr_hw_queues) { struct request_queue *q; @@ -2665,6 +2666,13 @@ void blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set, int nr_hw_queues) list_for_each_entry(q, &set->tag_list, tag_set_list) blk_mq_unfreeze_queue(q); } + +void blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set, int nr_hw_queues) +{ + mutex_lock(&set->tag_list_lock); + __blk_mq_update_nr_hw_queues(set, nr_hw_queues); + mutex_unlock(&set->tag_list_lock); +} EXPORT_SYMBOL_GPL(blk_mq_update_nr_hw_queues); /* Enable polling stats and return whether they were already enabled. */ -- cgit v1.2.3 From f511c0b17b081562dca8ac5061dfa86db4c66cc2 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 30 May 2017 12:38:59 -0700 Subject: "Yes, people use FOLL_FORCE ;)" This effectively reverts commit 8ee74a91ac30 ("proc: try to remove use of FOLL_FORCE entirely") It turns out that people do depend on FOLL_FORCE for the /proc//mem case, and we're talking not just debuggers. Talking to the affected people, the use-cases are: Keno Fischer: "We used these semantics as a hardening mechanism in the julia JIT. By opening /proc/self/mem and using these semantics, we could avoid needing RWX pages, or a dual mapping approach. We do have fallbacks to these other methods (though getting EIO here actually causes an assert in released versions - we'll updated that to make sure to take the fall back in that case). Nevertheless the /proc/self/mem approach was our favored approach because it a) Required an attacker to be able to execute syscalls which is a taller order than getting memory write and b) didn't double the virtual address space requirements (as a dual mapping approach would). I think in general this feature is very useful for anybody who needs to precisely control the execution of some other process. Various debuggers (gdb/lldb/rr) certainly fall into that category, but there's another class of such processes (wine, various emulators) which may want to do that kind of thing. Now, I suspect most of these will have the other process under ptrace control, so maybe allowing (same_mm || ptraced) would be ok, but at least for the sandbox/remote-jit use case, it would be perfectly reasonable to not have the jit server be a ptracer" Robert O'Callahan: "We write to readonly code and data mappings via /proc/.../mem in lots of different situations, particularly when we're adjusting program state during replay to match the recorded execution. Like Julia, we can add workarounds, but they could be expensive." so not only do people use FOLL_FORCE for both reads and writes, but they use it for both the local mm and remote mm. With these comments in mind, we likely also cannot add the "are we actively ptracing" check either, so this keeps the new code organization and does not do a real revert that would add back the original comment about "Maybe we should limit FOLL_FORCE to actual ptrace users?" Reported-by: Keno Fischer Reported-by: Robert O'Callahan Cc: Kees Cook Cc: Andy Lutomirski Cc: Eric Biederman Signed-off-by: Linus Torvalds --- fs/proc/base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/proc/base.c b/fs/proc/base.c index 45f6bf68fff3..f1e1927ccd48 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -821,7 +821,7 @@ static ssize_t mem_rw(struct file *file, char __user *buf, if (!mmget_not_zero(mm)) goto free; - flags = write ? FOLL_WRITE : 0; + flags = FOLL_FORCE | (write ? FOLL_WRITE : 0); while (count > 0) { int this_len = min_t(int, count, PAGE_SIZE); -- cgit v1.2.3 From 08fd5e76c268b7a5353302825b6b63a6027ddd0a Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Sat, 27 May 2017 06:50:05 -0700 Subject: hwmon: (aspeed-pwm-tacho) Select REGMAP The driver uses regmap and thus has to select it to avoid build errors such as the following. drivers/hwmon/aspeed-pwm-tacho.c:337:21: error: variable 'aspeed_pwm_tacho_regmap_config' has initializer but incomplete type Reported-by: kbuild test robot Acked-by: Joel Stanley Fixes: 2d7a548a3eff ("drivers: hwmon: Support for ASPEED PWM/Fan tach") Signed-off-by: Guenter Roeck --- drivers/hwmon/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 22d5eafd6815..5ef2814345ef 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -343,6 +343,7 @@ config SENSORS_ASB100 config SENSORS_ASPEED tristate "ASPEED AST2400/AST2500 PWM and Fan tach driver" + select REGMAP help This driver provides support for ASPEED AST2400/AST2500 PWM and Fan Tacho controllers. -- cgit v1.2.3 From 7ed1c5e5ddbb87aef9df7f8a8a714bcffe90f0eb Mon Sep 17 00:00:00 2001 From: Patrick Venture Date: Tue, 30 May 2017 12:42:01 -0700 Subject: hwmon: (aspeed-pwm-tacho) On read failure return -ETIMEDOUT When the controller fails to provide an RPM reading within the alloted time; the driver returns -ETIMEDOUT and no file contents. Signed-off-by: Patrick Venture Fixes: 2d7a548a3eff ("drivers: hwmon: Support for ASPEED PWM/Fan tach") Signed-off-by: Guenter Roeck --- drivers/hwmon/aspeed-pwm-tacho.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/hwmon/aspeed-pwm-tacho.c b/drivers/hwmon/aspeed-pwm-tacho.c index 48403a2115be..12b716b70ead 100644 --- a/drivers/hwmon/aspeed-pwm-tacho.c +++ b/drivers/hwmon/aspeed-pwm-tacho.c @@ -7,6 +7,7 @@ */ #include +#include #include #include #include @@ -494,7 +495,7 @@ static u32 aspeed_get_fan_tach_ch_measure_period(struct aspeed_pwm_tacho_data return clk / (clk_unit * div_h * div_l * tacho_div * tacho_unit); } -static u32 aspeed_get_fan_tach_ch_rpm(struct aspeed_pwm_tacho_data *priv, +static int aspeed_get_fan_tach_ch_rpm(struct aspeed_pwm_tacho_data *priv, u8 fan_tach_ch) { u32 raw_data, tach_div, clk_source, sec, val; @@ -510,6 +511,9 @@ static u32 aspeed_get_fan_tach_ch_rpm(struct aspeed_pwm_tacho_data *priv, msleep(sec); regmap_read(priv->regmap, ASPEED_PTCR_RESULT, &val); + if (!(val & RESULT_STATUS_MASK)) + return -ETIMEDOUT; + raw_data = val & RESULT_VALUE_MASK; tach_div = priv->type_fan_tach_clock_division[type]; tach_div = 0x4 << (tach_div * 2); @@ -561,12 +565,14 @@ static ssize_t show_rpm(struct device *dev, struct device_attribute *attr, { struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int index = sensor_attr->index; - u32 rpm; + int rpm; struct aspeed_pwm_tacho_data *priv = dev_get_drvdata(dev); rpm = aspeed_get_fan_tach_ch_rpm(priv, index); + if (rpm < 0) + return rpm; - return sprintf(buf, "%u\n", rpm); + return sprintf(buf, "%d\n", rpm); } static umode_t pwm_is_visible(struct kobject *kobj, -- cgit v1.2.3 From efd11cc8fa1a6d8aba16bd6aaa774ecc3d02145f Mon Sep 17 00:00:00 2001 From: Mark yao Date: Sat, 27 May 2017 19:43:36 +0800 Subject: drm/rockchip: Correct vop out_mode configure Force vop output mode on encoder driver seem not a good idea, EDP, HDMI, DisplayPort all have 10bit input on rk3399, On non-10bit vop, vop 8bit output bit[0-7] connect to the encoder high 8bit [2-9]. So force RGB10 to RGB888 on vop driver would be better. And another problem, EDP check crtc id on atomic_check, but encoder maybe NULL, so out_mode configure would fail, it cause edp no display. Signed-off-by: Mark Yao Reviewed-by: Jeffy Chen Link: http://patchwork.freedesktop.org/patch/msgid/1495885416-22216-1-git-send-email-mark.yao@rock-chips.com --- drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 12 ------------ drivers/gpu/drm/rockchip/cdn-dp-core.c | 9 ++------- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 8 ++++++++ drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 3 +++ drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 2 ++ 5 files changed, 15 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index d8fa7a9c9240..ce5f2d1f9994 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c @@ -245,8 +245,6 @@ rockchip_dp_drm_encoder_atomic_check(struct drm_encoder *encoder, struct drm_connector_state *conn_state) { struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state); - struct rockchip_dp_device *dp = to_dp(encoder); - int ret; /* * The hardware IC designed that VOP must output the RGB10 video @@ -258,16 +256,6 @@ rockchip_dp_drm_encoder_atomic_check(struct drm_encoder *encoder, s->output_mode = ROCKCHIP_OUT_MODE_AAAA; s->output_type = DRM_MODE_CONNECTOR_eDP; - if (dp->data->chip_type == RK3399_EDP) { - /* - * For RK3399, VOP Lit must code the out mode to RGB888, - * VOP Big must code the out mode to RGB10. - */ - ret = drm_of_encoder_active_endpoint_id(dp->dev->of_node, - encoder); - if (ret > 0) - s->output_mode = ROCKCHIP_OUT_MODE_P888; - } return 0; } diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockchip/cdn-dp-core.c index a2169dd3d26b..14fa1f8351e8 100644 --- a/drivers/gpu/drm/rockchip/cdn-dp-core.c +++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c @@ -615,7 +615,6 @@ static void cdn_dp_encoder_enable(struct drm_encoder *encoder) { struct cdn_dp_device *dp = encoder_to_dp(encoder); int ret, val; - struct rockchip_crtc_state *state; ret = drm_of_encoder_active_endpoint_id(dp->dev->of_node, encoder); if (ret < 0) { @@ -625,14 +624,10 @@ static void cdn_dp_encoder_enable(struct drm_encoder *encoder) DRM_DEV_DEBUG_KMS(dp->dev, "vop %s output to cdn-dp\n", (ret) ? "LIT" : "BIG"); - state = to_rockchip_crtc_state(encoder->crtc->state); - if (ret) { + if (ret) val = DP_SEL_VOP_LIT | (DP_SEL_VOP_LIT << 16); - state->output_mode = ROCKCHIP_OUT_MODE_P888; - } else { + else val = DP_SEL_VOP_LIT << 16; - state->output_mode = ROCKCHIP_OUT_MODE_AAAA; - } ret = cdn_dp_grf_write(dp, GRF_SOC_CON9, val); if (ret) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 3f7a82d1e095..45589d6ce65e 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -875,6 +875,7 @@ static bool vop_crtc_mode_fixup(struct drm_crtc *crtc, static void vop_crtc_enable(struct drm_crtc *crtc) { struct vop *vop = to_vop(crtc); + const struct vop_data *vop_data = vop->data; struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state); struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode; u16 hsync_len = adjusted_mode->hsync_end - adjusted_mode->hsync_start; @@ -967,6 +968,13 @@ static void vop_crtc_enable(struct drm_crtc *crtc) DRM_DEV_ERROR(vop->dev, "unsupported connector_type [%d]\n", s->output_type); } + + /* + * if vop is not support RGB10 output, need force RGB10 to RGB888. + */ + if (s->output_mode == ROCKCHIP_OUT_MODE_AAAA && + !(vop_data->feature & VOP_FEATURE_OUTPUT_RGB10)) + s->output_mode = ROCKCHIP_OUT_MODE_P888; VOP_CTRL_SET(vop, out_mode, s->output_mode); VOP_CTRL_SET(vop, htotal_pw, (htotal << 16) | hsync_len); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h index 5a4faa85dbd2..9979fd0c2282 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h @@ -142,6 +142,9 @@ struct vop_data { const struct vop_intr *intr; const struct vop_win_data *win; unsigned int win_size; + +#define VOP_FEATURE_OUTPUT_RGB10 BIT(0) + u64 feature; }; /* interrupt define */ diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c index 0da44442aab0..bafd698a28b1 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c @@ -275,6 +275,7 @@ static const struct vop_intr rk3288_vop_intr = { static const struct vop_data rk3288_vop = { .init_table = rk3288_init_reg_table, .table_size = ARRAY_SIZE(rk3288_init_reg_table), + .feature = VOP_FEATURE_OUTPUT_RGB10, .intr = &rk3288_vop_intr, .ctrl = &rk3288_ctrl_data, .win = rk3288_vop_win_data, @@ -343,6 +344,7 @@ static const struct vop_reg_data rk3399_init_reg_table[] = { static const struct vop_data rk3399_vop_big = { .init_table = rk3399_init_reg_table, .table_size = ARRAY_SIZE(rk3399_init_reg_table), + .feature = VOP_FEATURE_OUTPUT_RGB10, .intr = &rk3399_vop_intr, .ctrl = &rk3399_ctrl_data, /* -- cgit v1.2.3 From 64188cfbe5245d412de2139a3864e4e00b4136f0 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 30 May 2017 09:23:41 +0200 Subject: Revert "ALSA: usb-audio: purge needless variable length array" This reverts commit 89b593c30e83 ("ALSA: usb-audio: purge needless variable length array"). The patch turned out to cause a severe regression, triggering an Oops at snd_usb_ctl_msg(). It was overseen that snd_usb_ctl_msg() writes back the response to the given buffer, while the patch changed it to a read-only const buffer. (One should always double-check when an extra pointer cast is present...) As a simple fix, just revert the affected commit. It was merely a cleanup. Although it brings VLA again, it's clearer as a fix. We'll address the VLA later in another patch. Fixes: 89b593c30e83 ("ALSA: usb-audio: purge needless variable length array") Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=195875 Cc: # v4.11+ Signed-off-by: Takashi Iwai --- sound/usb/mixer_us16x08.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/usb/mixer_us16x08.c b/sound/usb/mixer_us16x08.c index dc48eedea92e..29d2c9282987 100644 --- a/sound/usb/mixer_us16x08.c +++ b/sound/usb/mixer_us16x08.c @@ -698,12 +698,12 @@ static int snd_us16x08_meter_get(struct snd_kcontrol *kcontrol, struct snd_usb_audio *chip = elem->head.mixer->chip; struct snd_us16x08_meter_store *store = elem->private_data; u8 meter_urb[64]; - char tmp[sizeof(mix_init_msg2)] = {0}; + char tmp[max(sizeof(mix_init_msg1), sizeof(mix_init_msg2))]; switch (kcontrol->private_value) { case 0: - snd_us16x08_send_urb(chip, (char *)mix_init_msg1, - sizeof(mix_init_msg1)); + memcpy(tmp, mix_init_msg1, sizeof(mix_init_msg1)); + snd_us16x08_send_urb(chip, tmp, 4); snd_us16x08_recv_urb(chip, meter_urb, sizeof(meter_urb)); kcontrol->private_value++; @@ -721,7 +721,7 @@ static int snd_us16x08_meter_get(struct snd_kcontrol *kcontrol, case 3: memcpy(tmp, mix_init_msg2, sizeof(mix_init_msg2)); tmp[2] = snd_get_meter_comp_index(store); - snd_us16x08_send_urb(chip, tmp, sizeof(mix_init_msg2)); + snd_us16x08_send_urb(chip, tmp, 10); snd_us16x08_recv_urb(chip, meter_urb, sizeof(meter_urb)); kcontrol->private_value = 0; -- cgit v1.2.3 From 617163fc2580da3d489b6c1bacb6312e0e2aac02 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 30 May 2017 23:21:07 +0200 Subject: ALSA: usb: Fix a typo in Tascam US-16x08 mixer element A mixer element created in a quirk for Tascam US-16x08 contains a typo: it should be "EQ MidLow Q" instead of "EQ MidQLow Q". Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=195875 Fixes: d2bb390a2081 ("ALSA: usb-audio: Tascam US-16x08 DSP mixer quirk") Cc: # v4.11+ Signed-off-by: Takashi Iwai --- sound/usb/mixer_us16x08.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/usb/mixer_us16x08.c b/sound/usb/mixer_us16x08.c index 29d2c9282987..442d8f7998e3 100644 --- a/sound/usb/mixer_us16x08.c +++ b/sound/usb/mixer_us16x08.c @@ -1135,7 +1135,7 @@ static const struct snd_us16x08_control_params eq_controls[] = { .control_id = SND_US16X08_ID_EQLOWMIDWIDTH, .type = USB_MIXER_U8, .num_channels = 16, - .name = "EQ MidQLow Q", + .name = "EQ MidLow Q", }, { /* EQ mid high gain */ .kcontrol_new = &snd_us16x08_eq_gain_ctl, -- cgit v1.2.3 From e49a14fa36aeb72476e038fcde96c151b7e4ecc8 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 30 May 2017 23:24:45 +0200 Subject: ALSA: usb: Avoid VLA in mixer_us16x08.c This is another attempt to work around the VLA used in mixer_us16x08.c. Basically the temporary array is used individually for two cases, and we can declare locally in each block, instead of hackish max() usage. Signed-off-by: Takashi Iwai --- sound/usb/mixer_us16x08.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/sound/usb/mixer_us16x08.c b/sound/usb/mixer_us16x08.c index 442d8f7998e3..26ed23b18b77 100644 --- a/sound/usb/mixer_us16x08.c +++ b/sound/usb/mixer_us16x08.c @@ -698,16 +698,18 @@ static int snd_us16x08_meter_get(struct snd_kcontrol *kcontrol, struct snd_usb_audio *chip = elem->head.mixer->chip; struct snd_us16x08_meter_store *store = elem->private_data; u8 meter_urb[64]; - char tmp[max(sizeof(mix_init_msg1), sizeof(mix_init_msg2))]; switch (kcontrol->private_value) { - case 0: + case 0: { + char tmp[sizeof(mix_init_msg1)]; + memcpy(tmp, mix_init_msg1, sizeof(mix_init_msg1)); snd_us16x08_send_urb(chip, tmp, 4); snd_us16x08_recv_urb(chip, meter_urb, sizeof(meter_urb)); kcontrol->private_value++; break; + } case 1: snd_us16x08_recv_urb(chip, meter_urb, sizeof(meter_urb)); @@ -718,7 +720,9 @@ static int snd_us16x08_meter_get(struct snd_kcontrol *kcontrol, sizeof(meter_urb)); kcontrol->private_value++; break; - case 3: + case 3: { + char tmp[sizeof(mix_init_msg2)]; + memcpy(tmp, mix_init_msg2, sizeof(mix_init_msg2)); tmp[2] = snd_get_meter_comp_index(store); snd_us16x08_send_urb(chip, tmp, 10); @@ -727,6 +731,7 @@ static int snd_us16x08_meter_get(struct snd_kcontrol *kcontrol, kcontrol->private_value = 0; break; } + } for (set = 0; set < 6; set++) get_meter_levels_from_urb(set, store, meter_urb); -- cgit v1.2.3 From 869e188a35c93f1bad7bf16c32f34a6feb5f79f1 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 31 May 2017 10:38:13 +0200 Subject: drm: Fix locking in drm_atomic_helper_resume In the conversion to drop drm_modeset_lock_all and the magic implicit context I failed to realize that _resume starts out with a pile of state copies, but not with the locks. And hence drm_atomic_commit won't grab these for us. v2: Add locking checks in helpers to make sure we catch this in the future. Note we can only require the locks in the atomic_check phase, not in the commit phase. But since any commit is guaranteed to first run the checks (even for the resume stuff where we use stored duplicated old state) this should give us full coverage. Requested by Maarten. Cc: Jyri Sarha Fixes: a5b8444e289c ("drm/atomic-helper: remove modeset_lock_all from helper_resume") Cc: Maarten Lankhorst Reviewed-by: Maarten Lankhorst Cc: Daniel Vetter Cc: Jani Nikula Cc: Sean Paul Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170531083813.1390-1-daniel.vetter@ffwll.ch --- drivers/gpu/drm/drm_atomic_helper.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 8be9719284b0..aa885a614e27 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -508,6 +508,8 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, bool has_connectors = !!new_crtc_state->connector_mask; + WARN_ON(!drm_modeset_is_locked(&crtc->mutex)); + if (!drm_mode_equal(&old_crtc_state->mode, &new_crtc_state->mode)) { DRM_DEBUG_ATOMIC("[CRTC:%d:%s] mode changed\n", crtc->base.id, crtc->name); @@ -551,6 +553,8 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, for_each_oldnew_connector_in_state(state, connector, old_connector_state, new_connector_state, i) { const struct drm_connector_helper_funcs *funcs = connector->helper_private; + WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex)); + /* * This only sets crtc->connectors_changed for routing changes, * drivers must set crtc->connectors_changed themselves when @@ -650,6 +654,8 @@ drm_atomic_helper_check_planes(struct drm_device *dev, for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) { const struct drm_plane_helper_funcs *funcs; + WARN_ON(!drm_modeset_is_locked(&plane->mutex)); + funcs = plane->helper_private; drm_atomic_helper_plane_changed(state, old_plane_state, new_plane_state, plane); @@ -2663,7 +2669,12 @@ int drm_atomic_helper_resume(struct drm_device *dev, drm_modeset_acquire_init(&ctx, 0); while (1) { + err = drm_modeset_lock_all_ctx(dev, &ctx); + if (err) + goto out; + err = drm_atomic_helper_commit_duplicated_state(state, &ctx); +out: if (err != -EDEADLK) break; -- cgit v1.2.3 From ff0361b34ac63ef80c785c32d62e0e9d89a2cf89 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 31 May 2017 09:44:32 +0200 Subject: dm: make flush bios explicitly sync Commit b685d3d65ac7 ("block: treat REQ_FUA and REQ_PREFLUSH as synchronous") removed REQ_SYNC flag from WRITE_{FUA|PREFLUSH|...} definitions. generic_make_request_checks() however strips REQ_FUA and REQ_PREFLUSH flags from a bio when the storage doesn't report volatile write cache and thus write effectively becomes asynchronous which can lead to performance regressions. Fix the problem by making sure all bios which are synchronous are properly marked with REQ_SYNC. Fixes: b685d3d65ac7 ("block: treat REQ_FUA and REQ_PREFLUSH as synchronous") Cc: stable@vger.kernel.org Signed-off-by: Jan Kara Signed-off-by: Mike Snitzer --- drivers/md/dm-bufio.c | 2 +- drivers/md/dm-integrity.c | 3 ++- drivers/md/dm-raid1.c | 2 +- drivers/md/dm-snap-persistent.c | 3 ++- drivers/md/dm.c | 2 +- 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c index cd8139593ccd..840c1496b2b1 100644 --- a/drivers/md/dm-bufio.c +++ b/drivers/md/dm-bufio.c @@ -1334,7 +1334,7 @@ int dm_bufio_issue_flush(struct dm_bufio_client *c) { struct dm_io_request io_req = { .bi_op = REQ_OP_WRITE, - .bi_op_flags = REQ_PREFLUSH, + .bi_op_flags = REQ_PREFLUSH | REQ_SYNC, .mem.type = DM_IO_KMEM, .mem.ptr.addr = NULL, .client = c->dm_io, diff --git a/drivers/md/dm-integrity.c b/drivers/md/dm-integrity.c index 1feeb2ccf5a1..7910bfe50da4 100644 --- a/drivers/md/dm-integrity.c +++ b/drivers/md/dm-integrity.c @@ -783,7 +783,8 @@ static void write_journal(struct dm_integrity_c *ic, unsigned commit_start, unsi for (i = 0; i < commit_sections; i++) rw_section_mac(ic, commit_start + i, true); } - rw_journal(ic, REQ_OP_WRITE, REQ_FUA, commit_start, commit_sections, &io_comp); + rw_journal(ic, REQ_OP_WRITE, REQ_FUA | REQ_SYNC, commit_start, + commit_sections, &io_comp); } else { unsigned to_end; io_comp.in_flight = (atomic_t)ATOMIC_INIT(2); diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index a95cbb80fb34..e61c45047c25 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c @@ -260,7 +260,7 @@ static int mirror_flush(struct dm_target *ti) struct mirror *m; struct dm_io_request io_req = { .bi_op = REQ_OP_WRITE, - .bi_op_flags = REQ_PREFLUSH, + .bi_op_flags = REQ_PREFLUSH | REQ_SYNC, .mem.type = DM_IO_KMEM, .mem.ptr.addr = NULL, .client = ms->io_client, diff --git a/drivers/md/dm-snap-persistent.c b/drivers/md/dm-snap-persistent.c index b93476c3ba3f..c5534d294773 100644 --- a/drivers/md/dm-snap-persistent.c +++ b/drivers/md/dm-snap-persistent.c @@ -741,7 +741,8 @@ static void persistent_commit_exception(struct dm_exception_store *store, /* * Commit exceptions to disk. */ - if (ps->valid && area_io(ps, REQ_OP_WRITE, REQ_PREFLUSH | REQ_FUA)) + if (ps->valid && area_io(ps, REQ_OP_WRITE, + REQ_PREFLUSH | REQ_FUA | REQ_SYNC)) ps->valid = 0; /* diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 6ef9500226c0..37ccd73c79ec 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -1657,7 +1657,7 @@ static struct mapped_device *alloc_dev(int minor) bio_init(&md->flush_bio, NULL, 0); md->flush_bio.bi_bdev = md->bdev; - md->flush_bio.bi_opf = REQ_OP_WRITE | REQ_PREFLUSH; + md->flush_bio.bi_opf = REQ_OP_WRITE | REQ_PREFLUSH | REQ_SYNC; dm_stats_init(&md->stats); -- cgit v1.2.3 From 63db7c815bc0997c29e484d2409684fdd9fcd93b Mon Sep 17 00:00:00 2001 From: Brian Foster Date: Wed, 31 May 2017 08:22:52 -0700 Subject: xfs: use ->b_state to fix buffer I/O accounting release race We've had user reports of unmount hangs in xfs_wait_buftarg() that analysis shows is due to btp->bt_io_count == -1. bt_io_count represents the count of in-flight asynchronous buffers and thus should always be >= 0. xfs_wait_buftarg() waits for this value to stabilize to zero in order to ensure that all untracked (with respect to the lru) buffers have completed I/O processing before unmount proceeds to tear down in-core data structures. The value of -1 implies an I/O accounting decrement race. Indeed, the fact that xfs_buf_ioacct_dec() is called from xfs_buf_rele() (where the buffer lock is no longer held) means that bp->b_flags can be updated from an unsafe context. While a user-level reproducer is currently not available, some intrusive hacks to run racing buffer lookups/ioacct/releases from multiple threads was used to successfully manufacture this problem. Existing callers do not expect to acquire the buffer lock from xfs_buf_rele(). Therefore, we can not safely update ->b_flags from this context. It turns out that we already have separate buffer state bits and associated serialization for dealing with buffer LRU state in the form of ->b_state and ->b_lock. Therefore, replace the _XBF_IN_FLIGHT flag with a ->b_state variant, update the I/O accounting wrappers appropriately and make sure they are used with the correct locking. This ensures that buffer in-flight state can be modified at buffer release time without racing with modifications from a buffer lock holder. Fixes: 9c7504aa72b6 ("xfs: track and serialize in-flight async buffers against unmount") Cc: # v4.8+ Signed-off-by: Brian Foster Reviewed-by: Nikolay Borisov Tested-by: Libor Pechacek Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/xfs_buf.c | 38 ++++++++++++++++++++++++++------------ fs/xfs/xfs_buf.h | 5 ++--- 2 files changed, 28 insertions(+), 15 deletions(-) diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c index 62fa39276a24..07b77b73b024 100644 --- a/fs/xfs/xfs_buf.c +++ b/fs/xfs/xfs_buf.c @@ -97,12 +97,16 @@ static inline void xfs_buf_ioacct_inc( struct xfs_buf *bp) { - if (bp->b_flags & (XBF_NO_IOACCT|_XBF_IN_FLIGHT)) + if (bp->b_flags & XBF_NO_IOACCT) return; ASSERT(bp->b_flags & XBF_ASYNC); - bp->b_flags |= _XBF_IN_FLIGHT; - percpu_counter_inc(&bp->b_target->bt_io_count); + spin_lock(&bp->b_lock); + if (!(bp->b_state & XFS_BSTATE_IN_FLIGHT)) { + bp->b_state |= XFS_BSTATE_IN_FLIGHT; + percpu_counter_inc(&bp->b_target->bt_io_count); + } + spin_unlock(&bp->b_lock); } /* @@ -110,14 +114,24 @@ xfs_buf_ioacct_inc( * freed and unaccount from the buftarg. */ static inline void -xfs_buf_ioacct_dec( +__xfs_buf_ioacct_dec( struct xfs_buf *bp) { - if (!(bp->b_flags & _XBF_IN_FLIGHT)) - return; + ASSERT(spin_is_locked(&bp->b_lock)); - bp->b_flags &= ~_XBF_IN_FLIGHT; - percpu_counter_dec(&bp->b_target->bt_io_count); + if (bp->b_state & XFS_BSTATE_IN_FLIGHT) { + bp->b_state &= ~XFS_BSTATE_IN_FLIGHT; + percpu_counter_dec(&bp->b_target->bt_io_count); + } +} + +static inline void +xfs_buf_ioacct_dec( + struct xfs_buf *bp) +{ + spin_lock(&bp->b_lock); + __xfs_buf_ioacct_dec(bp); + spin_unlock(&bp->b_lock); } /* @@ -149,9 +163,9 @@ xfs_buf_stale( * unaccounted (released to LRU) before that occurs. Drop in-flight * status now to preserve accounting consistency. */ - xfs_buf_ioacct_dec(bp); - spin_lock(&bp->b_lock); + __xfs_buf_ioacct_dec(bp); + atomic_set(&bp->b_lru_ref, 0); if (!(bp->b_state & XFS_BSTATE_DISPOSE) && (list_lru_del(&bp->b_target->bt_lru, &bp->b_lru))) @@ -979,12 +993,12 @@ xfs_buf_rele( * ensures the decrement occurs only once per-buf. */ if ((atomic_read(&bp->b_hold) == 1) && !list_empty(&bp->b_lru)) - xfs_buf_ioacct_dec(bp); + __xfs_buf_ioacct_dec(bp); goto out_unlock; } /* the last reference has been dropped ... */ - xfs_buf_ioacct_dec(bp); + __xfs_buf_ioacct_dec(bp); if (!(bp->b_flags & XBF_STALE) && atomic_read(&bp->b_lru_ref)) { /* * If the buffer is added to the LRU take a new reference to the diff --git a/fs/xfs/xfs_buf.h b/fs/xfs/xfs_buf.h index 8d1d44f87ce9..1508121f29f2 100644 --- a/fs/xfs/xfs_buf.h +++ b/fs/xfs/xfs_buf.h @@ -63,7 +63,6 @@ typedef enum { #define _XBF_KMEM (1 << 21)/* backed by heap memory */ #define _XBF_DELWRI_Q (1 << 22)/* buffer on a delwri queue */ #define _XBF_COMPOUND (1 << 23)/* compound buffer */ -#define _XBF_IN_FLIGHT (1 << 25) /* I/O in flight, for accounting purposes */ typedef unsigned int xfs_buf_flags_t; @@ -84,14 +83,14 @@ typedef unsigned int xfs_buf_flags_t; { _XBF_PAGES, "PAGES" }, \ { _XBF_KMEM, "KMEM" }, \ { _XBF_DELWRI_Q, "DELWRI_Q" }, \ - { _XBF_COMPOUND, "COMPOUND" }, \ - { _XBF_IN_FLIGHT, "IN_FLIGHT" } + { _XBF_COMPOUND, "COMPOUND" } /* * Internal state flags. */ #define XFS_BSTATE_DISPOSE (1 << 0) /* buffer being discarded */ +#define XFS_BSTATE_IN_FLIGHT (1 << 1) /* I/O in flight */ /* * The xfs_buftarg contains 2 notions of "sector size" - -- cgit v1.2.3 From 5be6b75610cefd1e21b98a218211922c2feb6e08 Mon Sep 17 00:00:00 2001 From: Hou Tao Date: Wed, 1 Mar 2017 09:02:33 +0800 Subject: cfq-iosched: fix the delay of cfq_group's vdisktime under iops mode When adding a cfq_group into the cfq service tree, we use CFQ_IDLE_DELAY as the delay of cfq_group's vdisktime if there have been other cfq_groups already. When cfq is under iops mode, commit 9a7f38c42c2b ("cfq-iosched: Convert from jiffies to nanoseconds") could result in a large iops delay and lead to an abnormal io schedule delay for the added cfq_group. To fix it, we just need to revert to the old CFQ_IDLE_DELAY value: HZ / 5 when iops mode is enabled. Despite having the same value, the delay of a cfq_queue in idle class and the delay of cfq_group are different things, so I define two new macros for the delay of a cfq_group under time-slice mode and iops mode. Fixes: 9a7f38c42c2b ("cfq-iosched: Convert from jiffies to nanoseconds") Cc: # 4.8+ Signed-off-by: Hou Tao Acked-by: Jan Kara Signed-off-by: Jens Axboe --- block/cfq-iosched.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index da69b079725f..b7e9c7feeab2 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -38,9 +38,13 @@ static const u64 cfq_target_latency = (u64)NSEC_PER_SEC * 3/10; /* 300 ms */ static const int cfq_hist_divisor = 4; /* - * offset from end of service tree + * offset from end of queue service tree for idle class */ #define CFQ_IDLE_DELAY (NSEC_PER_SEC / 5) +/* offset from end of group service tree under time slice mode */ +#define CFQ_SLICE_MODE_GROUP_DELAY (NSEC_PER_SEC / 5) +/* offset from end of group service under IOPS mode */ +#define CFQ_IOPS_MODE_GROUP_DELAY (HZ / 5) /* * below this threshold, we consider thinktime immediate @@ -1362,6 +1366,14 @@ cfq_group_service_tree_add(struct cfq_rb_root *st, struct cfq_group *cfqg) cfqg->vfraction = max_t(unsigned, vfr, 1); } +static inline u64 cfq_get_cfqg_vdisktime_delay(struct cfq_data *cfqd) +{ + if (!iops_mode(cfqd)) + return CFQ_SLICE_MODE_GROUP_DELAY; + else + return CFQ_IOPS_MODE_GROUP_DELAY; +} + static void cfq_group_notify_queue_add(struct cfq_data *cfqd, struct cfq_group *cfqg) { @@ -1381,7 +1393,8 @@ cfq_group_notify_queue_add(struct cfq_data *cfqd, struct cfq_group *cfqg) n = rb_last(&st->rb); if (n) { __cfqg = rb_entry_cfqg(n); - cfqg->vdisktime = __cfqg->vdisktime + CFQ_IDLE_DELAY; + cfqg->vdisktime = __cfqg->vdisktime + + cfq_get_cfqg_vdisktime_delay(cfqd); } else cfqg->vdisktime = st->min_vdisktime; cfq_group_service_tree_add(st, cfqg); -- cgit v1.2.3 From 5a8948f8a32ba56c17b3fb75d318ac98157f3ba5 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 31 May 2017 09:44:33 +0200 Subject: md: Make flush bios explicitely sync Commit b685d3d65ac7 "block: treat REQ_FUA and REQ_PREFLUSH as synchronous" removed REQ_SYNC flag from WRITE_{FUA|PREFLUSH|...} definitions. generic_make_request_checks() however strips REQ_FUA and REQ_PREFLUSH flags from a bio when the storage doesn't report volatile write cache and thus write effectively becomes asynchronous which can lead to performance regressions Fix the problem by making sure all bios which are synchronous are properly marked with REQ_SYNC. CC: linux-raid@vger.kernel.org CC: Shaohua Li Fixes: b685d3d65ac791406e0dfd8779cc9b3707fea5a3 CC: stable@vger.kernel.org Signed-off-by: Jan Kara Signed-off-by: Shaohua Li --- drivers/md/md.c | 2 +- drivers/md/raid5-cache.c | 4 ++-- drivers/md/raid5-ppl.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index 10367ffe92e3..212a6777ff31 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -765,7 +765,7 @@ void md_super_write(struct mddev *mddev, struct md_rdev *rdev, test_bit(FailFast, &rdev->flags) && !test_bit(LastDev, &rdev->flags)) ff = MD_FAILFAST; - bio->bi_opf = REQ_OP_WRITE | REQ_PREFLUSH | REQ_FUA | ff; + bio->bi_opf = REQ_OP_WRITE | REQ_SYNC | REQ_PREFLUSH | REQ_FUA | ff; atomic_inc(&mddev->pending_writes); submit_bio(bio); diff --git a/drivers/md/raid5-cache.c b/drivers/md/raid5-cache.c index 4c00bc248287..0a7af8b0a80a 100644 --- a/drivers/md/raid5-cache.c +++ b/drivers/md/raid5-cache.c @@ -1782,7 +1782,7 @@ static int r5l_log_write_empty_meta_block(struct r5l_log *log, sector_t pos, mb->checksum = cpu_to_le32(crc32c_le(log->uuid_checksum, mb, PAGE_SIZE)); if (!sync_page_io(log->rdev, pos, PAGE_SIZE, page, REQ_OP_WRITE, - REQ_FUA, false)) { + REQ_SYNC | REQ_FUA, false)) { __free_page(page); return -EIO; } @@ -2388,7 +2388,7 @@ r5c_recovery_rewrite_data_only_stripes(struct r5l_log *log, mb->checksum = cpu_to_le32(crc32c_le(log->uuid_checksum, mb, PAGE_SIZE)); sync_page_io(log->rdev, ctx->pos, PAGE_SIZE, page, - REQ_OP_WRITE, REQ_FUA, false); + REQ_OP_WRITE, REQ_SYNC | REQ_FUA, false); sh->log_start = ctx->pos; list_add_tail(&sh->r5c, &log->stripe_in_journal_list); atomic_inc(&log->stripe_in_journal_count); diff --git a/drivers/md/raid5-ppl.c b/drivers/md/raid5-ppl.c index 5d25bebf3328..ccce92e68d7f 100644 --- a/drivers/md/raid5-ppl.c +++ b/drivers/md/raid5-ppl.c @@ -907,8 +907,8 @@ static int ppl_write_empty_header(struct ppl_log *log) pplhdr->checksum = cpu_to_le32(~crc32c_le(~0, pplhdr, PAGE_SIZE)); if (!sync_page_io(rdev, rdev->ppl.sector - rdev->data_offset, - PPL_HEADER_SIZE, page, REQ_OP_WRITE | REQ_FUA, 0, - false)) { + PPL_HEADER_SIZE, page, REQ_OP_WRITE | REQ_SYNC | + REQ_FUA, 0, false)) { md_error(rdev->mddev, rdev); ret = -EIO; } -- cgit v1.2.3 From 6ea44adce91526700535b3150f77f8639ae8c82d Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 25 May 2017 17:00:32 +1000 Subject: SUNRPC: ensure correct error is reported by xs_tcp_setup_socket() If you attempt a TCP mount from an host that is unreachable in a way that triggers an immediate error from kernel_connect(), that error does not propagate up, instead EAGAIN is reported. This results in call_connect_status receiving the wrong error. A case that it easy to demonstrate is to attempt to mount from an address that results in ENETUNREACH, but first deleting any default route. Without this patch, the mount.nfs process is persistently runnable and is hard to kill. With this patch it exits as it should. The problem is caused by the fact that xs_tcp_force_close() eventually calls xprt_wake_pending_tasks(xprt, -EAGAIN); which causes an error return of -EAGAIN. so when xs_tcp_setup_sock() calls xprt_wake_pending_tasks(xprt, status); the status is ignored. Fixes: 4efdd92c9211 ("SUNRPC: Remove TCP client connection reset hack") Signed-off-by: NeilBrown Signed-off-by: Trond Myklebust --- net/sunrpc/xprtsock.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 16aff8ddc16f..d5b54c020dec 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -2432,7 +2432,12 @@ static void xs_tcp_setup_socket(struct work_struct *work) case -ENETUNREACH: case -EADDRINUSE: case -ENOBUFS: - /* retry with existing socket, after a delay */ + /* + * xs_tcp_force_close() wakes tasks with -EIO. + * We need to wake them first to ensure the + * correct error code. + */ + xprt_wake_pending_tasks(xprt, status); xs_tcp_force_close(xprt); goto out; } -- cgit v1.2.3 From 15e5651525c2e580a523568ed207e4a3fb11cc33 Mon Sep 17 00:00:00 2001 From: Douglas Caetano dos Santos Date: Fri, 26 May 2017 14:28:00 -0300 Subject: tcp: reinitialize MTU probing when setting MSS in a TCP repair MTU probing initialization occurred only at connect() and at SYN or SYN-ACK reception, but the former sets MSS to either the default or the user set value (through TCP_MAXSEG sockopt) and the latter never happens with repaired sockets. The result was that, with MTU probing enabled and unless TCP_MAXSEG sockopt was used before connect(), probing would be stuck at tcp_base_mss value until tcp_probe_interval seconds have passed. Signed-off-by: Douglas Caetano dos Santos Signed-off-by: David S. Miller --- net/ipv4/tcp.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 59792d283ff8..b5ea036ca781 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2381,9 +2381,10 @@ static int tcp_repair_set_window(struct tcp_sock *tp, char __user *optbuf, int l return 0; } -static int tcp_repair_options_est(struct tcp_sock *tp, +static int tcp_repair_options_est(struct sock *sk, struct tcp_repair_opt __user *optbuf, unsigned int len) { + struct tcp_sock *tp = tcp_sk(sk); struct tcp_repair_opt opt; while (len >= sizeof(opt)) { @@ -2396,6 +2397,7 @@ static int tcp_repair_options_est(struct tcp_sock *tp, switch (opt.opt_code) { case TCPOPT_MSS: tp->rx_opt.mss_clamp = opt.opt_val; + tcp_mtup_init(sk); break; case TCPOPT_WINDOW: { @@ -2555,7 +2557,7 @@ static int do_tcp_setsockopt(struct sock *sk, int level, if (!tp->repair) err = -EINVAL; else if (sk->sk_state == TCP_ESTABLISHED) - err = tcp_repair_options_est(tp, + err = tcp_repair_options_est(sk, (struct tcp_repair_opt __user *)optval, optlen); else -- cgit v1.2.3 From 45cc6586b7a73e84a8806881122b6ec306cdc9e7 Mon Sep 17 00:00:00 2001 From: Leo Liu Date: Mon, 29 May 2017 13:13:59 -0400 Subject: drm/amdgpu: Program ring for vce instance 1 at its register space We need program ring buffer on instance 1 register space domain, when only if instance 1 available, with two instances or instance 0, and we need only program instance 0 regsiter space domain for ring. Signed-off-by: Leo Liu Reviewed-by: Alex Deucher Cc: stable@vger.kernel.org Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vce_v3_0.c | 95 +++++++++++++++++++++++++---------- 1 file changed, 68 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c index fb0819359909..90332f55cfba 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c @@ -77,13 +77,26 @@ static int vce_v3_0_set_clockgating_state(void *handle, static uint64_t vce_v3_0_ring_get_rptr(struct amdgpu_ring *ring) { struct amdgpu_device *adev = ring->adev; + u32 v; + + mutex_lock(&adev->grbm_idx_mutex); + if (adev->vce.harvest_config == 0 || + adev->vce.harvest_config == AMDGPU_VCE_HARVEST_VCE1) + WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(0)); + else if (adev->vce.harvest_config == AMDGPU_VCE_HARVEST_VCE0) + WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(1)); if (ring == &adev->vce.ring[0]) - return RREG32(mmVCE_RB_RPTR); + v = RREG32(mmVCE_RB_RPTR); else if (ring == &adev->vce.ring[1]) - return RREG32(mmVCE_RB_RPTR2); + v = RREG32(mmVCE_RB_RPTR2); else - return RREG32(mmVCE_RB_RPTR3); + v = RREG32(mmVCE_RB_RPTR3); + + WREG32(mmGRBM_GFX_INDEX, mmGRBM_GFX_INDEX_DEFAULT); + mutex_unlock(&adev->grbm_idx_mutex); + + return v; } /** @@ -96,13 +109,26 @@ static uint64_t vce_v3_0_ring_get_rptr(struct amdgpu_ring *ring) static uint64_t vce_v3_0_ring_get_wptr(struct amdgpu_ring *ring) { struct amdgpu_device *adev = ring->adev; + u32 v; + + mutex_lock(&adev->grbm_idx_mutex); + if (adev->vce.harvest_config == 0 || + adev->vce.harvest_config == AMDGPU_VCE_HARVEST_VCE1) + WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(0)); + else if (adev->vce.harvest_config == AMDGPU_VCE_HARVEST_VCE0) + WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(1)); if (ring == &adev->vce.ring[0]) - return RREG32(mmVCE_RB_WPTR); + v = RREG32(mmVCE_RB_WPTR); else if (ring == &adev->vce.ring[1]) - return RREG32(mmVCE_RB_WPTR2); + v = RREG32(mmVCE_RB_WPTR2); else - return RREG32(mmVCE_RB_WPTR3); + v = RREG32(mmVCE_RB_WPTR3); + + WREG32(mmGRBM_GFX_INDEX, mmGRBM_GFX_INDEX_DEFAULT); + mutex_unlock(&adev->grbm_idx_mutex); + + return v; } /** @@ -116,12 +142,22 @@ static void vce_v3_0_ring_set_wptr(struct amdgpu_ring *ring) { struct amdgpu_device *adev = ring->adev; + mutex_lock(&adev->grbm_idx_mutex); + if (adev->vce.harvest_config == 0 || + adev->vce.harvest_config == AMDGPU_VCE_HARVEST_VCE1) + WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(0)); + else if (adev->vce.harvest_config == AMDGPU_VCE_HARVEST_VCE0) + WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(1)); + if (ring == &adev->vce.ring[0]) WREG32(mmVCE_RB_WPTR, lower_32_bits(ring->wptr)); else if (ring == &adev->vce.ring[1]) WREG32(mmVCE_RB_WPTR2, lower_32_bits(ring->wptr)); else WREG32(mmVCE_RB_WPTR3, lower_32_bits(ring->wptr)); + + WREG32(mmGRBM_GFX_INDEX, mmGRBM_GFX_INDEX_DEFAULT); + mutex_unlock(&adev->grbm_idx_mutex); } static void vce_v3_0_override_vce_clock_gating(struct amdgpu_device *adev, bool override) @@ -231,33 +267,38 @@ static int vce_v3_0_start(struct amdgpu_device *adev) struct amdgpu_ring *ring; int idx, r; - ring = &adev->vce.ring[0]; - WREG32(mmVCE_RB_RPTR, lower_32_bits(ring->wptr)); - WREG32(mmVCE_RB_WPTR, lower_32_bits(ring->wptr)); - WREG32(mmVCE_RB_BASE_LO, ring->gpu_addr); - WREG32(mmVCE_RB_BASE_HI, upper_32_bits(ring->gpu_addr)); - WREG32(mmVCE_RB_SIZE, ring->ring_size / 4); - - ring = &adev->vce.ring[1]; - WREG32(mmVCE_RB_RPTR2, lower_32_bits(ring->wptr)); - WREG32(mmVCE_RB_WPTR2, lower_32_bits(ring->wptr)); - WREG32(mmVCE_RB_BASE_LO2, ring->gpu_addr); - WREG32(mmVCE_RB_BASE_HI2, upper_32_bits(ring->gpu_addr)); - WREG32(mmVCE_RB_SIZE2, ring->ring_size / 4); - - ring = &adev->vce.ring[2]; - WREG32(mmVCE_RB_RPTR3, lower_32_bits(ring->wptr)); - WREG32(mmVCE_RB_WPTR3, lower_32_bits(ring->wptr)); - WREG32(mmVCE_RB_BASE_LO3, ring->gpu_addr); - WREG32(mmVCE_RB_BASE_HI3, upper_32_bits(ring->gpu_addr)); - WREG32(mmVCE_RB_SIZE3, ring->ring_size / 4); - mutex_lock(&adev->grbm_idx_mutex); for (idx = 0; idx < 2; ++idx) { if (adev->vce.harvest_config & (1 << idx)) continue; WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(idx)); + + /* Program instance 0 reg space for two instances or instance 0 case + program instance 1 reg space for only instance 1 available case */ + if (idx != 1 || adev->vce.harvest_config == AMDGPU_VCE_HARVEST_VCE0) { + ring = &adev->vce.ring[0]; + WREG32(mmVCE_RB_RPTR, lower_32_bits(ring->wptr)); + WREG32(mmVCE_RB_WPTR, lower_32_bits(ring->wptr)); + WREG32(mmVCE_RB_BASE_LO, ring->gpu_addr); + WREG32(mmVCE_RB_BASE_HI, upper_32_bits(ring->gpu_addr)); + WREG32(mmVCE_RB_SIZE, ring->ring_size / 4); + + ring = &adev->vce.ring[1]; + WREG32(mmVCE_RB_RPTR2, lower_32_bits(ring->wptr)); + WREG32(mmVCE_RB_WPTR2, lower_32_bits(ring->wptr)); + WREG32(mmVCE_RB_BASE_LO2, ring->gpu_addr); + WREG32(mmVCE_RB_BASE_HI2, upper_32_bits(ring->gpu_addr)); + WREG32(mmVCE_RB_SIZE2, ring->ring_size / 4); + + ring = &adev->vce.ring[2]; + WREG32(mmVCE_RB_RPTR3, lower_32_bits(ring->wptr)); + WREG32(mmVCE_RB_WPTR3, lower_32_bits(ring->wptr)); + WREG32(mmVCE_RB_BASE_LO3, ring->gpu_addr); + WREG32(mmVCE_RB_BASE_HI3, upper_32_bits(ring->gpu_addr)); + WREG32(mmVCE_RB_SIZE3, ring->ring_size / 4); + } + vce_v3_0_mc_resume(adev, idx); WREG32_FIELD(VCE_STATUS, JOB_BUSY, 1); -- cgit v1.2.3 From 898805e0cdf7fd860ec21bf661d3a0285a3defbd Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 30 May 2017 16:21:51 +0100 Subject: net: phy: fix marvell phy status reading The Marvell driver incorrectly provides phydev->lp_advertising as the logical and of the link partner's advert and our advert. This is incorrect - this field is supposed to store the link parter's unmodified advertisment. This allows ethtool to report the correct link partner auto-negotiation status. Fixes: be937f1f89ca ("Marvell PHY m88e1111 driver fix") Signed-off-by: Russell King Reviewed-by: Andrew Lunn Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/marvell.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index 9097e42bec2e..57297ba23987 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -1127,8 +1127,6 @@ static int marvell_read_status_page(struct phy_device *phydev, int page) if (adv < 0) return adv; - lpa &= adv; - if (status & MII_M1011_PHY_STATUS_FULLDUPLEX) phydev->duplex = DUPLEX_FULL; else -- cgit v1.2.3 From 1ba15b24f07c44f68067959522639226c963e212 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Wed, 31 May 2017 10:18:55 +0200 Subject: KVM: s390: fix ais handling vs cpu model If ais is disabled via cpumodel, we must act accordingly, even if KVM_CAP_S390_AIS was enabled. Signed-off-by: Christian Borntraeger Reviewed-by: Pierre Morel Reviewed-by: Yi Min Zhao Reviewed-by: Halil Pasic Reviewed-by: Eric Farman --- arch/s390/include/asm/kvm_host.h | 1 - arch/s390/kvm/interrupt.c | 4 ++-- arch/s390/kvm/kvm-s390.c | 2 -- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h index 426614a882a9..65d07ac34647 100644 --- a/arch/s390/include/asm/kvm_host.h +++ b/arch/s390/include/asm/kvm_host.h @@ -541,7 +541,6 @@ struct kvm_s390_float_interrupt { struct mutex ais_lock; u8 simm; u8 nimm; - int ais_enabled; }; struct kvm_hw_wp_info_arch { diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c index caf15c8a8948..2d120fef7d90 100644 --- a/arch/s390/kvm/interrupt.c +++ b/arch/s390/kvm/interrupt.c @@ -2160,7 +2160,7 @@ static int modify_ais_mode(struct kvm *kvm, struct kvm_device_attr *attr) struct kvm_s390_ais_req req; int ret = 0; - if (!fi->ais_enabled) + if (!test_kvm_facility(kvm, 72)) return -ENOTSUPP; if (copy_from_user(&req, (void __user *)attr->addr, sizeof(req))) @@ -2204,7 +2204,7 @@ static int kvm_s390_inject_airq(struct kvm *kvm, }; int ret = 0; - if (!fi->ais_enabled || !adapter->suppressible) + if (!test_kvm_facility(kvm, 72) || !adapter->suppressible) return kvm_s390_inject_vm(kvm, &s390int); mutex_lock(&fi->ais_lock); diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 689ac48361c6..f28e2e776931 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -558,7 +558,6 @@ static int kvm_vm_ioctl_enable_cap(struct kvm *kvm, struct kvm_enable_cap *cap) } else { set_kvm_facility(kvm->arch.model.fac_mask, 72); set_kvm_facility(kvm->arch.model.fac_list, 72); - kvm->arch.float_int.ais_enabled = 1; r = 0; } mutex_unlock(&kvm->lock); @@ -1533,7 +1532,6 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) mutex_init(&kvm->arch.float_int.ais_lock); kvm->arch.float_int.simm = 0; kvm->arch.float_int.nimm = 0; - kvm->arch.float_int.ais_enabled = 0; spin_lock_init(&kvm->arch.float_int.lock); for (i = 0; i < FIRQ_LIST_COUNT; i++) INIT_LIST_HEAD(&kvm->arch.float_int.lists[i]); -- cgit v1.2.3 From 1b8f8694bb4992135dac150bf44a6c139e573970 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 30 May 2017 21:38:18 +0100 Subject: net: fix auto-loading of Marvell DSA driver Auto-loading of the Marvell DSA driver has stopped working with recent kernels. This seems to be due to the change of binding for DSA devices, moving them from the platform bus to the MDIO bus. In order for module auto-loading to work, we need to provide a MODALIAS string in the uevent file for the device. However, the device core does not automatically provide this, and needs each bus_type to implement a uevent method to generate these strings. The MDIO bus does not provide such a method, so no MODALIAS string is provided: .# cat /sys/bus/mdio_bus/devices/f1072004.mdio-mii\:04/uevent DRIVER=mv88e6085 OF_NAME=switch OF_FULLNAME=/soc/internal-regs/mdio@72004/switch@4 OF_COMPATIBLE_0=marvell,mv88e6085 OF_COMPATIBLE_N=1 In the case of OF-based devices, the solution is easy - of_device_uevent_modalias() does the work for us. After this is done, the uevent file looks like this: .# cat /sys/bus/mdio_bus/devices/f1072004.mdio-mii\:04/uevent DRIVER=mv88e6085 OF_NAME=switch OF_FULLNAME=/soc/internal-regs/mdio@72004/switch@4 OF_COMPATIBLE_0=marvell,mv88e6085 OF_COMPATIBLE_N=1 MODALIAS=of:NswitchTCmarvell,mv88e6085 which results in auto-loading of the Marvell DSA driver on Clearfog platforms. Fixes: c0405563a613 ("ARM: dts: armada-388-clearfog: Utilize new DSA binding") Signed-off-by: Russell King Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/mdio_bus.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 8e73f5f36e71..f99c21f78b63 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -658,6 +658,18 @@ static int mdio_bus_match(struct device *dev, struct device_driver *drv) return 0; } +static int mdio_uevent(struct device *dev, struct kobj_uevent_env *env) +{ + int rc; + + /* Some devices have extra OF data and an OF-style MODALIAS */ + rc = of_device_uevent_modalias(dev, env); + if (rc != -ENODEV) + return rc; + + return 0; +} + #ifdef CONFIG_PM static int mdio_bus_suspend(struct device *dev) { @@ -708,6 +720,7 @@ static const struct dev_pm_ops mdio_bus_pm_ops = { struct bus_type mdio_bus_type = { .name = "mdio_bus", .match = mdio_bus_match, + .uevent = mdio_uevent, .pm = MDIO_BUS_PM_OPS, }; EXPORT_SYMBOL(mdio_bus_type); -- cgit v1.2.3 From 06d2d6431bc8d41ef5ffd8bd4b52cea9f72aed22 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 30 May 2017 17:38:43 -0500 Subject: net: freescale: fix potential null pointer dereference Add NULL check before dereferencing pointer _id_ in order to avoid a potential NULL pointer dereference. Addresses-Coverity-ID: 1397995 Signed-off-by: Gustavo A. R. Silva Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fsl_pq_mdio.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/freescale/fsl_pq_mdio.c b/drivers/net/ethernet/freescale/fsl_pq_mdio.c index 446c7b374ff5..a10de1e9c157 100644 --- a/drivers/net/ethernet/freescale/fsl_pq_mdio.c +++ b/drivers/net/ethernet/freescale/fsl_pq_mdio.c @@ -381,7 +381,7 @@ static int fsl_pq_mdio_probe(struct platform_device *pdev) { const struct of_device_id *id = of_match_device(fsl_pq_mdio_match, &pdev->dev); - const struct fsl_pq_mdio_data *data = id->data; + const struct fsl_pq_mdio_data *data; struct device_node *np = pdev->dev.of_node; struct resource res; struct device_node *tbi; @@ -389,6 +389,13 @@ static int fsl_pq_mdio_probe(struct platform_device *pdev) struct mii_bus *new_bus; int err; + if (!id) { + dev_err(&pdev->dev, "Failed to match device\n"); + return -ENODEV; + } + + data = id->data; + dev_dbg(&pdev->dev, "found %s compatible node\n", id->compatible); new_bus = mdiobus_alloc_size(sizeof(*priv)); -- cgit v1.2.3 From f7cf69ae171592d133c69b9adaa5de7cfb6038ea Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 31 May 2017 14:26:26 -0400 Subject: libata: fix error checking in in ata_parse_force_one() ata_parse_force_one() was incorrectly comparing @p to @endp when it should have been comparing @id. The only consequence is that it may end up using an invalid port number in "libata.force" module param instead of rejecting it. Signed-off-by: Tejun Heo Reported-by: Petru-Florin Mihancea Link: https://bugzilla.kernel.org/show_bug.cgi?id=195785 --- 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 2d83b8c75965..e157a0e44419 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -6800,7 +6800,7 @@ static int __init ata_parse_force_one(char **cur, } force_ent->port = simple_strtoul(id, &endp, 10); - if (p == endp || *endp != '\0') { + if (id == endp || *endp != '\0') { *reason = "invalid port/link"; return -EINVAL; } -- cgit v1.2.3 From e8f4ae85439f34bec3b0ab69223a41809dab28c9 Mon Sep 17 00:00:00 2001 From: Jia-Ju Bai Date: Wed, 31 May 2017 09:40:11 +0800 Subject: isdn: Fix a sleep-in-atomic bug The driver may sleep under a spin lock, the function call path is: isdn_ppp_mp_receive (acquire the lock) isdn_ppp_mp_reassembly isdn_ppp_push_higher isdn_ppp_decompress isdn_ppp_ccp_reset_trans isdn_ppp_ccp_reset_alloc_state kzalloc(GFP_KERNEL) --> may sleep To fixed it, the "GFP_KERNEL" is replaced with "GFP_ATOMIC". Signed-off-by: Jia-Ju Bai Signed-off-by: David S. Miller --- drivers/isdn/i4l/isdn_ppp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c index d07dd5196ffc..8aa158a09180 100644 --- a/drivers/isdn/i4l/isdn_ppp.c +++ b/drivers/isdn/i4l/isdn_ppp.c @@ -2364,7 +2364,7 @@ static struct ippp_ccp_reset_state *isdn_ppp_ccp_reset_alloc_state(struct ippp_s id); return NULL; } else { - rs = kzalloc(sizeof(struct ippp_ccp_reset_state), GFP_KERNEL); + rs = kzalloc(sizeof(struct ippp_ccp_reset_state), GFP_ATOMIC); if (!rs) return NULL; rs->state = CCPResetIdle; -- cgit v1.2.3 From c2e8471d98f072f0f18acdd7df5b401ed0d29a2c Mon Sep 17 00:00:00 2001 From: Roopa Prabhu Date: Tue, 30 May 2017 23:50:36 -0700 Subject: mpls: fix clearing of dead nh_flags on link up recent fixes to use WRITE_ONCE for nh_flags on link up, accidently ended up leaving the deadflags on a nh. This patch fixes the WRITE_ONCE to use freshly evaluated nh_flags. Fixes: 39eb8cd17588 ("net: mpls: rt_nhn_alive and nh_flags should be accessed using READ_ONCE") Reported-by: Satish Ashok Signed-off-by: Roopa Prabhu Acked-by: David Ahern Signed-off-by: David S. Miller --- net/mpls/af_mpls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c index 257ec66009da..7b05fd1497ce 100644 --- a/net/mpls/af_mpls.c +++ b/net/mpls/af_mpls.c @@ -1418,7 +1418,7 @@ static void mpls_ifup(struct net_device *dev, unsigned int flags) continue; alive++; nh_flags &= ~flags; - WRITE_ONCE(nh->nh_flags, flags); + WRITE_ONCE(nh->nh_flags, nh_flags); } endfor_nexthops(rt); WRITE_ONCE(rt->rt_nhn_alive, alive); -- cgit v1.2.3 From 25cdda95fda78d22d44157da15aa7ea34be3c804 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Wed, 24 May 2017 21:47:09 -0700 Subject: iscsi-target: Fix initial login PDU asynchronous socket close OOPs This patch fixes a OOPs originally introduced by: commit bb048357dad6d604520c91586334c9c230366a14 Author: Nicholas Bellinger Date: Thu Sep 5 14:54:04 2013 -0700 iscsi-target: Add sk->sk_state_change to cleanup after TCP failure which would trigger a NULL pointer dereference when a TCP connection was closed asynchronously via iscsi_target_sk_state_change(), but only when the initial PDU processing in iscsi_target_do_login() from iscsi_np process context was blocked waiting for backend I/O to complete. To address this issue, this patch makes the following changes. First, it introduces some common helper functions used for checking socket closing state, checking login_flags, and atomically checking socket closing state + setting login_flags. Second, it introduces a LOGIN_FLAGS_INITIAL_PDU bit to know when a TCP connection has dropped via iscsi_target_sk_state_change(), but the initial PDU processing within iscsi_target_do_login() in iscsi_np context is still running. For this case, it sets LOGIN_FLAGS_CLOSED, but doesn't invoke schedule_delayed_work(). The original NULL pointer dereference case reported by MNC is now handled by iscsi_target_do_login() doing a iscsi_target_sk_check_close() before transitioning to FFP to determine when the socket has already closed, or iscsi_target_start_negotiation() if the login needs to exchange more PDUs (eg: iscsi_target_do_login returned 0) but the socket has closed. For both of these cases, the cleanup up of remaining connection resources will occur in iscsi_target_start_negotiation() from iscsi_np process context once the failure is detected. Finally, to handle to case where iscsi_target_sk_state_change() is called after the initial PDU procesing is complete, it now invokes conn->login_work -> iscsi_target_do_login_rx() to perform cleanup once existing iscsi_target_sk_check_close() checks detect connection failure. For this case, the cleanup of remaining connection resources will occur in iscsi_target_do_login_rx() from delayed workqueue process context once the failure is detected. Reported-by: Mike Christie Reviewed-by: Mike Christie Tested-by: Mike Christie Cc: Mike Christie Reported-by: Hannes Reinecke Cc: Hannes Reinecke Cc: Sagi Grimberg Cc: Varun Prakash Cc: # v3.12+ Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target_nego.c | 194 +++++++++++++++++++++---------- include/target/iscsi/iscsi_target_core.h | 1 + 2 files changed, 133 insertions(+), 62 deletions(-) diff --git a/drivers/target/iscsi/iscsi_target_nego.c b/drivers/target/iscsi/iscsi_target_nego.c index 7ccc9c1cbfd1..6f88b31242b0 100644 --- a/drivers/target/iscsi/iscsi_target_nego.c +++ b/drivers/target/iscsi/iscsi_target_nego.c @@ -493,14 +493,60 @@ static void iscsi_target_restore_sock_callbacks(struct iscsi_conn *conn) static int iscsi_target_do_login(struct iscsi_conn *, struct iscsi_login *); -static bool iscsi_target_sk_state_check(struct sock *sk) +static bool __iscsi_target_sk_check_close(struct sock *sk) { if (sk->sk_state == TCP_CLOSE_WAIT || sk->sk_state == TCP_CLOSE) { - pr_debug("iscsi_target_sk_state_check: TCP_CLOSE_WAIT|TCP_CLOSE," + pr_debug("__iscsi_target_sk_check_close: TCP_CLOSE_WAIT|TCP_CLOSE," "returning FALSE\n"); - return false; + return true; } - return true; + return false; +} + +static bool iscsi_target_sk_check_close(struct iscsi_conn *conn) +{ + bool state = false; + + if (conn->sock) { + struct sock *sk = conn->sock->sk; + + read_lock_bh(&sk->sk_callback_lock); + state = (__iscsi_target_sk_check_close(sk) || + test_bit(LOGIN_FLAGS_CLOSED, &conn->login_flags)); + read_unlock_bh(&sk->sk_callback_lock); + } + return state; +} + +static bool iscsi_target_sk_check_flag(struct iscsi_conn *conn, unsigned int flag) +{ + bool state = false; + + if (conn->sock) { + struct sock *sk = conn->sock->sk; + + read_lock_bh(&sk->sk_callback_lock); + state = test_bit(flag, &conn->login_flags); + read_unlock_bh(&sk->sk_callback_lock); + } + return state; +} + +static bool iscsi_target_sk_check_and_clear(struct iscsi_conn *conn, unsigned int flag) +{ + bool state = false; + + if (conn->sock) { + struct sock *sk = conn->sock->sk; + + write_lock_bh(&sk->sk_callback_lock); + state = (__iscsi_target_sk_check_close(sk) || + test_bit(LOGIN_FLAGS_CLOSED, &conn->login_flags)); + if (!state) + clear_bit(flag, &conn->login_flags); + write_unlock_bh(&sk->sk_callback_lock); + } + return state; } static void iscsi_target_login_drop(struct iscsi_conn *conn, struct iscsi_login *login) @@ -540,6 +586,20 @@ static void iscsi_target_do_login_rx(struct work_struct *work) pr_debug("entering iscsi_target_do_login_rx, conn: %p, %s:%d\n", conn, current->comm, current->pid); + /* + * If iscsi_target_do_login_rx() has been invoked by ->sk_data_ready() + * before initial PDU processing in iscsi_target_start_negotiation() + * has completed, go ahead and retry until it's cleared. + * + * Otherwise if the TCP connection drops while this is occuring, + * iscsi_target_start_negotiation() will detect the failure, call + * cancel_delayed_work_sync(&conn->login_work), and cleanup the + * remaining iscsi connection resources from iscsi_np process context. + */ + if (iscsi_target_sk_check_flag(conn, LOGIN_FLAGS_INITIAL_PDU)) { + schedule_delayed_work(&conn->login_work, msecs_to_jiffies(10)); + return; + } spin_lock(&tpg->tpg_state_lock); state = (tpg->tpg_state == TPG_STATE_ACTIVE); @@ -547,26 +607,12 @@ static void iscsi_target_do_login_rx(struct work_struct *work) if (!state) { pr_debug("iscsi_target_do_login_rx: tpg_state != TPG_STATE_ACTIVE\n"); - iscsi_target_restore_sock_callbacks(conn); - iscsi_target_login_drop(conn, login); - iscsit_deaccess_np(np, tpg, tpg_np); - return; + goto err; } - if (conn->sock) { - struct sock *sk = conn->sock->sk; - - read_lock_bh(&sk->sk_callback_lock); - state = iscsi_target_sk_state_check(sk); - read_unlock_bh(&sk->sk_callback_lock); - - if (!state) { - pr_debug("iscsi_target_do_login_rx, TCP state CLOSE\n"); - iscsi_target_restore_sock_callbacks(conn); - iscsi_target_login_drop(conn, login); - iscsit_deaccess_np(np, tpg, tpg_np); - return; - } + if (iscsi_target_sk_check_close(conn)) { + pr_debug("iscsi_target_do_login_rx, TCP state CLOSE\n"); + goto err; } conn->login_kworker = current; @@ -584,34 +630,29 @@ static void iscsi_target_do_login_rx(struct work_struct *work) flush_signals(current); conn->login_kworker = NULL; - if (rc < 0) { - iscsi_target_restore_sock_callbacks(conn); - iscsi_target_login_drop(conn, login); - iscsit_deaccess_np(np, tpg, tpg_np); - return; - } + if (rc < 0) + goto err; pr_debug("iscsi_target_do_login_rx after rx_login_io, %p, %s:%d\n", conn, current->comm, current->pid); rc = iscsi_target_do_login(conn, login); if (rc < 0) { - iscsi_target_restore_sock_callbacks(conn); - iscsi_target_login_drop(conn, login); - iscsit_deaccess_np(np, tpg, tpg_np); + goto err; } else if (!rc) { - if (conn->sock) { - struct sock *sk = conn->sock->sk; - - write_lock_bh(&sk->sk_callback_lock); - clear_bit(LOGIN_FLAGS_READ_ACTIVE, &conn->login_flags); - write_unlock_bh(&sk->sk_callback_lock); - } + if (iscsi_target_sk_check_and_clear(conn, LOGIN_FLAGS_READ_ACTIVE)) + goto err; } else if (rc == 1) { iscsi_target_nego_release(conn); iscsi_post_login_handler(np, conn, zero_tsih); iscsit_deaccess_np(np, tpg, tpg_np); } + return; + +err: + iscsi_target_restore_sock_callbacks(conn); + iscsi_target_login_drop(conn, login); + iscsit_deaccess_np(np, tpg, tpg_np); } static void iscsi_target_do_cleanup(struct work_struct *work) @@ -659,31 +700,54 @@ static void iscsi_target_sk_state_change(struct sock *sk) orig_state_change(sk); return; } + state = __iscsi_target_sk_check_close(sk); + pr_debug("__iscsi_target_sk_close_change: state: %d\n", state); + if (test_bit(LOGIN_FLAGS_READ_ACTIVE, &conn->login_flags)) { pr_debug("Got LOGIN_FLAGS_READ_ACTIVE=1 sk_state_change" " conn: %p\n", conn); + if (state) + set_bit(LOGIN_FLAGS_CLOSED, &conn->login_flags); write_unlock_bh(&sk->sk_callback_lock); orig_state_change(sk); return; } - if (test_and_set_bit(LOGIN_FLAGS_CLOSED, &conn->login_flags)) { + if (test_bit(LOGIN_FLAGS_CLOSED, &conn->login_flags)) { pr_debug("Got LOGIN_FLAGS_CLOSED=1 sk_state_change conn: %p\n", conn); write_unlock_bh(&sk->sk_callback_lock); orig_state_change(sk); return; } + /* + * If the TCP connection has dropped, go ahead and set LOGIN_FLAGS_CLOSED, + * but only queue conn->login_work -> iscsi_target_do_login_rx() + * processing if LOGIN_FLAGS_INITIAL_PDU has already been cleared. + * + * When iscsi_target_do_login_rx() runs, iscsi_target_sk_check_close() + * will detect the dropped TCP connection from delayed workqueue context. + * + * If LOGIN_FLAGS_INITIAL_PDU is still set, which means the initial + * iscsi_target_start_negotiation() is running, iscsi_target_do_login() + * via iscsi_target_sk_check_close() or iscsi_target_start_negotiation() + * via iscsi_target_sk_check_and_clear() is responsible for detecting the + * dropped TCP connection in iscsi_np process context, and cleaning up + * the remaining iscsi connection resources. + */ + if (state) { + pr_debug("iscsi_target_sk_state_change got failed state\n"); + set_bit(LOGIN_FLAGS_CLOSED, &conn->login_flags); + state = test_bit(LOGIN_FLAGS_INITIAL_PDU, &conn->login_flags); + write_unlock_bh(&sk->sk_callback_lock); - state = iscsi_target_sk_state_check(sk); - write_unlock_bh(&sk->sk_callback_lock); - - pr_debug("iscsi_target_sk_state_change: state: %d\n", state); + orig_state_change(sk); - if (!state) { - pr_debug("iscsi_target_sk_state_change got failed state\n"); - schedule_delayed_work(&conn->login_cleanup_work, 0); + if (!state) + schedule_delayed_work(&conn->login_work, 0); return; } + write_unlock_bh(&sk->sk_callback_lock); + orig_state_change(sk); } @@ -946,6 +1010,15 @@ static int iscsi_target_do_login(struct iscsi_conn *conn, struct iscsi_login *lo if (iscsi_target_handle_csg_one(conn, login) < 0) return -1; if (login_rsp->flags & ISCSI_FLAG_LOGIN_TRANSIT) { + /* + * Check to make sure the TCP connection has not + * dropped asynchronously while session reinstatement + * was occuring in this kthread context, before + * transitioning to full feature phase operation. + */ + if (iscsi_target_sk_check_close(conn)) + return -1; + login->tsih = conn->sess->tsih; login->login_complete = 1; iscsi_target_restore_sock_callbacks(conn); @@ -972,21 +1045,6 @@ static int iscsi_target_do_login(struct iscsi_conn *conn, struct iscsi_login *lo break; } - if (conn->sock) { - struct sock *sk = conn->sock->sk; - bool state; - - read_lock_bh(&sk->sk_callback_lock); - state = iscsi_target_sk_state_check(sk); - read_unlock_bh(&sk->sk_callback_lock); - - if (!state) { - pr_debug("iscsi_target_do_login() failed state for" - " conn: %p\n", conn); - return -1; - } - } - return 0; } @@ -1255,10 +1313,22 @@ int iscsi_target_start_negotiation( write_lock_bh(&sk->sk_callback_lock); set_bit(LOGIN_FLAGS_READY, &conn->login_flags); + set_bit(LOGIN_FLAGS_INITIAL_PDU, &conn->login_flags); write_unlock_bh(&sk->sk_callback_lock); } - + /* + * If iscsi_target_do_login returns zero to signal more PDU + * exchanges are required to complete the login, go ahead and + * clear LOGIN_FLAGS_INITIAL_PDU but only if the TCP connection + * is still active. + * + * Otherwise if TCP connection dropped asynchronously, go ahead + * and perform connection cleanup now. + */ ret = iscsi_target_do_login(conn, login); + if (!ret && iscsi_target_sk_check_and_clear(conn, LOGIN_FLAGS_INITIAL_PDU)) + ret = -1; + if (ret < 0) { cancel_delayed_work_sync(&conn->login_work); cancel_delayed_work_sync(&conn->login_cleanup_work); diff --git a/include/target/iscsi/iscsi_target_core.h b/include/target/iscsi/iscsi_target_core.h index 275581d483dd..5f17fb770477 100644 --- a/include/target/iscsi/iscsi_target_core.h +++ b/include/target/iscsi/iscsi_target_core.h @@ -557,6 +557,7 @@ struct iscsi_conn { #define LOGIN_FLAGS_READ_ACTIVE 1 #define LOGIN_FLAGS_CLOSED 2 #define LOGIN_FLAGS_READY 4 +#define LOGIN_FLAGS_INITIAL_PDU 8 unsigned long login_flags; struct delayed_work login_work; struct delayed_work login_cleanup_work; -- cgit v1.2.3 From 5e0cf5e6c43b9e19fc0284f69e5cd2b4a47523b0 Mon Sep 17 00:00:00 2001 From: Jiang Yi Date: Tue, 16 May 2017 17:57:55 +0800 Subject: iscsi-target: Always wait for kthread_should_stop() before kthread exit There are three timing problems in the kthread usages of iscsi_target_mod: - np_thread of struct iscsi_np - rx_thread and tx_thread of struct iscsi_conn In iscsit_close_connection(), it calls send_sig(SIGINT, conn->tx_thread, 1); kthread_stop(conn->tx_thread); In conn->tx_thread, which is iscsi_target_tx_thread(), when it receive SIGINT the kthread will exit without checking the return value of kthread_should_stop(). So if iscsi_target_tx_thread() exit right between send_sig(SIGINT...) and kthread_stop(...), the kthread_stop() will try to stop an already stopped kthread. This is invalid according to the documentation of kthread_stop(). (Fix -ECONNRESET logout handling in iscsi_target_tx_thread and early iscsi_target_rx_thread failure case - nab) Signed-off-by: Jiang Yi Cc: # v3.12+ Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target.c | 30 ++++++++++++++++++++++++------ drivers/target/iscsi/iscsi_target_erl0.c | 6 +++++- drivers/target/iscsi/iscsi_target_erl0.h | 2 +- drivers/target/iscsi/iscsi_target_login.c | 4 ++++ 4 files changed, 34 insertions(+), 8 deletions(-) diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 26a9bcd5ee6a..0d8f81591bed 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -3790,6 +3790,8 @@ int iscsi_target_tx_thread(void *arg) { int ret = 0; struct iscsi_conn *conn = arg; + bool conn_freed = false; + /* * Allow ourselves to be interrupted by SIGINT so that a * connection recovery / failure event can be triggered externally. @@ -3815,12 +3817,14 @@ get_immediate: goto transport_err; ret = iscsit_handle_response_queue(conn); - if (ret == 1) + if (ret == 1) { goto get_immediate; - else if (ret == -ECONNRESET) + } else if (ret == -ECONNRESET) { + conn_freed = true; goto out; - else if (ret < 0) + } else if (ret < 0) { goto transport_err; + } } transport_err: @@ -3830,8 +3834,13 @@ transport_err: * responsible for cleaning up the early connection failure. */ if (conn->conn_state != TARG_CONN_STATE_IN_LOGIN) - iscsit_take_action_for_connection_exit(conn); + iscsit_take_action_for_connection_exit(conn, &conn_freed); out: + if (!conn_freed) { + while (!kthread_should_stop()) { + msleep(100); + } + } return 0; } @@ -4004,6 +4013,7 @@ int iscsi_target_rx_thread(void *arg) { int rc; struct iscsi_conn *conn = arg; + bool conn_freed = false; /* * Allow ourselves to be interrupted by SIGINT so that a @@ -4016,7 +4026,7 @@ int iscsi_target_rx_thread(void *arg) */ rc = wait_for_completion_interruptible(&conn->rx_login_comp); if (rc < 0 || iscsi_target_check_conn_state(conn)) - return 0; + goto out; if (!conn->conn_transport->iscsit_get_rx_pdu) return 0; @@ -4025,7 +4035,15 @@ int iscsi_target_rx_thread(void *arg) if (!signal_pending(current)) atomic_set(&conn->transport_failed, 1); - iscsit_take_action_for_connection_exit(conn); + iscsit_take_action_for_connection_exit(conn, &conn_freed); + +out: + if (!conn_freed) { + while (!kthread_should_stop()) { + msleep(100); + } + } + return 0; } diff --git a/drivers/target/iscsi/iscsi_target_erl0.c b/drivers/target/iscsi/iscsi_target_erl0.c index 9a96e17bf7cd..7fe2aa73cff6 100644 --- a/drivers/target/iscsi/iscsi_target_erl0.c +++ b/drivers/target/iscsi/iscsi_target_erl0.c @@ -930,8 +930,10 @@ static void iscsit_handle_connection_cleanup(struct iscsi_conn *conn) } } -void iscsit_take_action_for_connection_exit(struct iscsi_conn *conn) +void iscsit_take_action_for_connection_exit(struct iscsi_conn *conn, bool *conn_freed) { + *conn_freed = false; + spin_lock_bh(&conn->state_lock); if (atomic_read(&conn->connection_exit)) { spin_unlock_bh(&conn->state_lock); @@ -942,6 +944,7 @@ void iscsit_take_action_for_connection_exit(struct iscsi_conn *conn) if (conn->conn_state == TARG_CONN_STATE_IN_LOGOUT) { spin_unlock_bh(&conn->state_lock); iscsit_close_connection(conn); + *conn_freed = true; return; } @@ -955,4 +958,5 @@ void iscsit_take_action_for_connection_exit(struct iscsi_conn *conn) spin_unlock_bh(&conn->state_lock); iscsit_handle_connection_cleanup(conn); + *conn_freed = true; } diff --git a/drivers/target/iscsi/iscsi_target_erl0.h b/drivers/target/iscsi/iscsi_target_erl0.h index 60e69e2af6ed..3822d9cd1230 100644 --- a/drivers/target/iscsi/iscsi_target_erl0.h +++ b/drivers/target/iscsi/iscsi_target_erl0.h @@ -15,6 +15,6 @@ extern int iscsit_stop_time2retain_timer(struct iscsi_session *); extern void iscsit_connection_reinstatement_rcfr(struct iscsi_conn *); extern void iscsit_cause_connection_reinstatement(struct iscsi_conn *, int); extern void iscsit_fall_back_to_erl0(struct iscsi_session *); -extern void iscsit_take_action_for_connection_exit(struct iscsi_conn *); +extern void iscsit_take_action_for_connection_exit(struct iscsi_conn *, bool *); #endif /*** ISCSI_TARGET_ERL0_H ***/ diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index 66238477137b..92b96b51d506 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c @@ -1464,5 +1464,9 @@ int iscsi_target_login_thread(void *arg) break; } + while (!kthread_should_stop()) { + msleep(100); + } + return 0; } -- cgit v1.2.3 From 9094367a9161858004eacb7373aa2bf48c51c16d Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 19 May 2017 10:04:31 +0200 Subject: scsi: lpfc: nvmet_fc: fix format string The lpfc_nvmeio_data() tracing helper always takes a format string and three additional arguments. The latest caller has a format string with only two integer arguments, causing this harmless warning: drivers/scsi/lpfc/lpfc_nvmet.c: In function 'lpfc_nvmet_xmt_fcp_release': drivers/scsi/lpfc/lpfc_nvmet.c:802:25: error: too many arguments for format [-Werror=format-extra-args] lpfc_nvmeio_data(phba, "NVMET FCP FREE: xri x%x ste %d\n", ctxp->oxid, We could add a dummy argument here, but it seems reasonable to print the 'abort' flag as the third argument. Fixes: 19b58d9473e8 ("nvmet_fc: add req_release to lldd api") Signed-off-by: Arnd Bergmann Acked-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_nvmet.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c index f94294b77b7b..24d54dd016d4 100644 --- a/drivers/scsi/lpfc/lpfc_nvmet.c +++ b/drivers/scsi/lpfc/lpfc_nvmet.c @@ -799,8 +799,8 @@ lpfc_nvmet_xmt_fcp_release(struct nvmet_fc_target_port *tgtport, } spin_unlock_irqrestore(&ctxp->ctxlock, flags); - lpfc_nvmeio_data(phba, "NVMET FCP FREE: xri x%x ste %d\n", ctxp->oxid, - ctxp->state, 0); + lpfc_nvmeio_data(phba, "NVMET FCP FREE: xri x%x ste %d abt %d\n", ctxp->oxid, + ctxp->state, aborting); atomic_inc(&lpfc_nvmep->xmt_fcp_release); -- cgit v1.2.3 From 7c9fdfb7000715df2d187df251d11e4850ce94c8 Mon Sep 17 00:00:00 2001 From: "Guilherme G. Piccoli" Date: Wed, 24 May 2017 18:48:51 -0300 Subject: scsi: lpfc: Avoid NULL pointer dereference in lpfc_els_abort() We might have a NULL pring in lpfc_els_abort(), for example on error recovery path, since queues are destroyed during error recovery mechanism. In this case, we should just drop the abort since the queues will be recreated anyway. This patch just verifies for NULL pointer and stop the abortion of the queue in case of a NULL pring. Also, this patch converts return type of lpfc_els_abort() from int to void, since it's not checked anywhere. Reported-by: Harsha Thyagaraja Reported-by: Naresh Bannoth Tested-by: Raphael Silva Signed-off-by: Guilherme G. Piccoli Reviewed-by: Johannes Thumshirn Acked-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_crtn.h | 2 +- drivers/scsi/lpfc/lpfc_nportdisc.c | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 8912767e7bc8..da669dce12fe 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -127,7 +127,7 @@ int lpfc_disc_state_machine(struct lpfc_vport *, struct lpfc_nodelist *, void *, void lpfc_do_scr_ns_plogi(struct lpfc_hba *, struct lpfc_vport *); int lpfc_check_sparm(struct lpfc_vport *, struct lpfc_nodelist *, struct serv_parm *, uint32_t, int); -int lpfc_els_abort(struct lpfc_hba *, struct lpfc_nodelist *); +void lpfc_els_abort(struct lpfc_hba *, struct lpfc_nodelist *); void lpfc_more_plogi(struct lpfc_vport *); void lpfc_more_adisc(struct lpfc_vport *); void lpfc_end_rscn(struct lpfc_vport *); diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index bff3de053df4..f74cb0142fd4 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c @@ -206,7 +206,7 @@ lpfc_check_elscmpl_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, * associated with a LPFC_NODELIST entry. This * routine effectively results in a "software abort". */ -int +void lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) { LIST_HEAD(abort_list); @@ -215,6 +215,10 @@ lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) pring = lpfc_phba_elsring(phba); + /* In case of error recovery path, we might have a NULL pring here */ + if (!pring) + return; + /* Abort outstanding I/O on NPort */ lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_DISCOVERY, "2819 Abort outstanding I/O on NPort x%x " @@ -273,7 +277,6 @@ lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) IOSTAT_LOCAL_REJECT, IOERR_SLI_ABORTED); lpfc_cancel_retry_delay_tmo(phba->pport, ndlp); - return 0; } static int -- cgit v1.2.3 From e6ef6a77f51e403a1400241b9d029ecaba45a834 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 23 May 2017 10:09:28 -0500 Subject: scsi: lpfc: prevent potential null pointer dereference Null check at line 966: if (ndlp) {, implies that ndlp might be NULL. Functions lpfc_nlp_set_state() and lpfc_issue_els_prli() dereference pointer ndlp. Include these function calls inside the IF block that tests pointer ndlp. Addresses-Coverity-ID: 1401856 Signed-off-by: Gustavo A. R. Silva Acked-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_ct.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index f2cd19c6c2df..24ce96dcc94d 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -978,9 +978,10 @@ lpfc_cmpl_ct_cmd_gft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, ndlp, did, ndlp->nlp_fc4_type, FC_TYPE_FCP, FC_TYPE_NVME); ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE; + + lpfc_nlp_set_state(vport, ndlp, NLP_STE_PRLI_ISSUE); + lpfc_issue_els_prli(vport, ndlp, 0); } - lpfc_nlp_set_state(vport, ndlp, NLP_STE_PRLI_ISSUE); - lpfc_issue_els_prli(vport, ndlp, 0); } else lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, "3065 GFT_ID failed x%08x\n", irsp->ulpStatus); -- cgit v1.2.3 From 4cd3b6ebff8510b2139d64024411207090cfe0a9 Mon Sep 17 00:00:00 2001 From: Bill Kuzeja Date: Thu, 25 May 2017 15:26:31 -0400 Subject: scsi: qla2xxx: Fix extraneous ref on sp's after adapter break Hung task timeouts can result if a qlogic board breaks unexpectedly while running I/O. These tasks become hung because command srb reference counts are not going to zero, hence the affected srbs and commands do not get freed. This fix accounts for this extra reference in the srbs in the case of a board failure. Fixes: a465537ad1a4 ("qla2xxx: Disable the adapter and skip error recovery in case of register disconnect") Signed-off-by: Bill Kuzeja Acked-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_os.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 2a2ce7476339..79f050256c55 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -1640,7 +1640,7 @@ qla2x00_loop_reset(scsi_qla_host_t *vha) void qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res) { - int que, cnt; + int que, cnt, status; unsigned long flags; srb_t *sp; struct qla_hw_data *ha = vha->hw; @@ -1670,8 +1670,12 @@ qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res) */ sp_get(sp); spin_unlock_irqrestore(&ha->hardware_lock, flags); - qla2xxx_eh_abort(GET_CMD_SP(sp)); + status = qla2xxx_eh_abort(GET_CMD_SP(sp)); spin_lock_irqsave(&ha->hardware_lock, flags); + /* Get rid of extra reference if immediate exit + * from ql2xxx_eh_abort */ + if (status == FAILED && (qla2x00_isp_reg_stat(ha))) + atomic_dec(&sp->ref_count); } req->outstanding_cmds[cnt] = NULL; sp->done(sp, res); -- cgit v1.2.3 From 70bdf2026d905b8bfa0a455d35018df3e9777a6c Mon Sep 17 00:00:00 2001 From: "Martin K. Petersen" Date: Fri, 19 May 2017 12:39:36 -0400 Subject: scsi: scsi_debug: Avoid PI being disabled when TPGS is enabled It was not possible to enable both T10 PI and TPGS because they share the same byte in the INQUIRY response. Logically OR the TPGS value instead of using assignment. Reported-by: Ritika Srivastava Reviewed-by: Bart Van Assche Reviewed-by: Ewan D. Milne Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 17249c3650fe..dc095a292c61 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -1404,7 +1404,7 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) arr[4] = SDEBUG_LONG_INQ_SZ - 5; arr[5] = (int)have_dif_prot; /* PROTECT bit */ if (sdebug_vpd_use_hostno == 0) - arr[5] = 0x10; /* claim: implicit TGPS */ + arr[5] |= 0x10; /* claim: implicit TPGS */ arr[6] = 0x10; /* claim: MultiP */ /* arr[6] |= 0x40; ... claim: EncServ (enclosure services) */ arr[7] = 0xa; /* claim: LINKED + CMDQUE */ -- cgit v1.2.3 From d2c3b14e1f0dcebdb695617c0c1342a36b914a47 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 1 Jun 2017 09:35:30 +0200 Subject: ALSA: hda - Fix applying MSI dual-codec mobo quirk The previous commit [63691587f7b0: ALSA: hda - Apply dual-codec quirk for MSI Z270-Gaming mobo] attempted to apply the existing dual-codec quirk for a MSI mobo. But it turned out that this isn't applied properly due to the MSI-vendor quirk before this entry. I overlooked such two MSI entries just because they were put in the wrong position, although we have a list ordered by PCI SSID numbers. This patch fixes it by rearranging the unordered entries. Fixes: 63691587f7b0 ("ALSA: hda - Apply dual-codec quirk for MSI Z270-Gaming mobo") Reported-by: Rudolf Schmidt Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 918e45268915..a57988d617e9 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -2324,11 +2324,11 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC889_FIXUP_MBA11_VREF), SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD), - SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD), - SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3), SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3/Z87X-UD3H", ALC889_FIXUP_FRONT_HP_NO_PRESENCE), SND_PCI_QUIRK(0x1458, 0xa0b8, "Gigabyte AZ370-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS), + SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD), SND_PCI_QUIRK(0x1462, 0xda57, "MSI Z270-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS), + SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3), SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", ALC882_FIXUP_ABIT_AW9D_MAX), SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC882_FIXUP_EAPD), SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_FIXUP_EAPD), -- cgit v1.2.3 From 1dbf647f31751a4e94fa0435c34f0f5ad5ce0adc Mon Sep 17 00:00:00 2001 From: Arend Van Spriel Date: Fri, 26 May 2017 13:02:55 +0200 Subject: brcmfmac: fix alignment configuration on host using 64-bit DMA For SDIO the alignment requirement for transfers from device to host is configured in firmware. This configuration is limited to minimum of 4-byte alignment. However, this is not correct for platforms using 64-bit DMA when the minimum alignment should be 8 bytes. This issue appeared when the ALIGNMENT definition was set according the DMA configuration. The configuration in firmware was not using that macro defintion, but a hardcoded value of 4. Hence the driver reported alignment failures for data coming from the device and causing transfers to fail. Fixes: 6e84ab604bde ("brcmfmac: properly align buffers on certain platforms Reported-by: Hans de Goede Tested-by: Hans de Goede Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Franky Lin Signed-off-by: Arend van Spriel Signed-off-by: Hans de Goede Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c index fc64b8913aa6..e03450059b06 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c @@ -3422,7 +3422,7 @@ static int brcmf_sdio_bus_preinit(struct device *dev) /* otherwise, set txglomalign */ value = sdiodev->settings->bus.sdio.sd_sgentry_align; /* SDIO ADMA requires at least 32 bit alignment */ - value = max_t(u32, value, 4); + value = max_t(u32, value, ALIGNMENT); err = brcmf_iovar_data_set(dev, "bus:txglomalign", &value, sizeof(u32)); } -- cgit v1.2.3 From d9c1b5431d5f0e07575db785a022bce91051ac1d Mon Sep 17 00:00:00 2001 From: Roman Pen Date: Thu, 1 Jun 2017 10:55:03 +0200 Subject: KVM: SVM: do not zero out segment attributes if segment is unusable or not present MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a fix for the problem [1], where VMCB.CPL was set to 0 and interrupt was taken on userspace stack. The root cause lies in the specific AMD CPU behaviour which manifests itself as unusable segment attributes on SYSRET. The corresponding work around for the kernel is the following: 61f01dd941ba ("x86_64, asm: Work around AMD SYSRET SS descriptor attribute issue") In other turn virtualization side treated unusable segment incorrectly and restored CPL from SS attributes, which were zeroed out few lines above. In current patch it is assured only that P bit is cleared in VMCB.save state and segment attributes are not zeroed out if segment is not presented or is unusable, therefore CPL can be safely restored from DPL field. This is only one part of the fix, since QEMU side should be fixed accordingly not to zero out attributes on its side. Corresponding patch will follow. [1] Message id: CAJrWOzD6Xq==b-zYCDdFLgSRMPM-NkNuTSDFEtX=7MreT45i7Q@mail.gmail.com Signed-off-by: Roman Pen Signed-off-by: Mikhail Sennikovskii Cc: Paolo Bonzini Cc: Radim KrÄmář Cc: kvm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Paolo Bonzini --- arch/x86/kvm/svm.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index a654372efea1..ba9891ac5c56 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -1840,6 +1840,7 @@ static void svm_get_segment(struct kvm_vcpu *vcpu, */ if (var->unusable) var->db = 0; + /* This is symmetric with svm_set_segment() */ var->dpl = to_svm(vcpu)->vmcb->save.cpl; break; } @@ -1980,18 +1981,14 @@ static void svm_set_segment(struct kvm_vcpu *vcpu, s->base = var->base; s->limit = var->limit; s->selector = var->selector; - if (var->unusable) - s->attrib = 0; - else { - s->attrib = (var->type & SVM_SELECTOR_TYPE_MASK); - s->attrib |= (var->s & 1) << SVM_SELECTOR_S_SHIFT; - s->attrib |= (var->dpl & 3) << SVM_SELECTOR_DPL_SHIFT; - s->attrib |= (var->present & 1) << SVM_SELECTOR_P_SHIFT; - s->attrib |= (var->avl & 1) << SVM_SELECTOR_AVL_SHIFT; - s->attrib |= (var->l & 1) << SVM_SELECTOR_L_SHIFT; - s->attrib |= (var->db & 1) << SVM_SELECTOR_DB_SHIFT; - s->attrib |= (var->g & 1) << SVM_SELECTOR_G_SHIFT; - } + s->attrib = (var->type & SVM_SELECTOR_TYPE_MASK); + s->attrib |= (var->s & 1) << SVM_SELECTOR_S_SHIFT; + s->attrib |= (var->dpl & 3) << SVM_SELECTOR_DPL_SHIFT; + s->attrib |= ((var->present & 1) && !var->unusable) << SVM_SELECTOR_P_SHIFT; + s->attrib |= (var->avl & 1) << SVM_SELECTOR_AVL_SHIFT; + s->attrib |= (var->l & 1) << SVM_SELECTOR_L_SHIFT; + s->attrib |= (var->db & 1) << SVM_SELECTOR_DB_SHIFT; + s->attrib |= (var->g & 1) << SVM_SELECTOR_G_SHIFT; /* * This is always accurate, except if SYSRET returned to a segment @@ -2000,7 +1997,8 @@ static void svm_set_segment(struct kvm_vcpu *vcpu, * would entail passing the CPL to userspace and back. */ if (seg == VCPU_SREG_SS) - svm->vmcb->save.cpl = (s->attrib >> SVM_SELECTOR_DPL_SHIFT) & 3; + /* This is symmetric with svm_get_segment() */ + svm->vmcb->save.cpl = (var->dpl & 3); mark_dirty(svm->vmcb, VMCB_SEG); } -- cgit v1.2.3 From 47a66eed99e6f231f4a1d261a9d493f4eee94829 Mon Sep 17 00:00:00 2001 From: ZhuangYanying Date: Fri, 26 May 2017 13:16:48 +0800 Subject: KVM: x86: Fix nmi injection failure when vcpu got blocked When spin_lock_irqsave() deadlock occurs inside the guest, vcpu threads, other than the lock-holding one, would enter into S state because of pvspinlock. Then inject NMI via libvirt API "inject-nmi", the NMI could not be injected into vm. The reason is: 1 It sets nmi_queued to 1 when calling ioctl KVM_NMI in qemu, and sets cpu->kvm_vcpu_dirty to true in do_inject_external_nmi() meanwhile. 2 It sets nmi_queued to 0 in process_nmi(), before entering guest, because cpu->kvm_vcpu_dirty is true. It's not enough just to check nmi_queued to decide whether to stay in vcpu_block() or not. NMI should be injected immediately at any situation. Add checking nmi_pending, and testing KVM_REQ_NMI replaces nmi_queued in vm_vcpu_has_events(). Do the same change for SMIs. Signed-off-by: Zhuang Yanying Signed-off-by: Paolo Bonzini --- arch/x86/kvm/x86.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 02363e37d4a6..a2cd0997343c 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -8394,10 +8394,13 @@ static inline bool kvm_vcpu_has_events(struct kvm_vcpu *vcpu) if (vcpu->arch.pv.pv_unhalted) return true; - if (atomic_read(&vcpu->arch.nmi_queued)) + if (kvm_test_request(KVM_REQ_NMI, vcpu) || + (vcpu->arch.nmi_pending && + kvm_x86_ops->nmi_allowed(vcpu))) return true; - if (kvm_test_request(KVM_REQ_SMI, vcpu)) + if (kvm_test_request(KVM_REQ_SMI, vcpu) || + (vcpu->arch.smi_pending && !is_smm(vcpu))) return true; if (kvm_arch_interrupt_allowed(vcpu) && -- cgit v1.2.3 From 9605bc46433d54f89b12d443a3d9aabf8070824b Mon Sep 17 00:00:00 2001 From: Fengguang Wu Date: Tue, 16 May 2017 20:41:45 +0800 Subject: phy: qualcomm: phy-qcom-qmp: fix application of sizeof to pointer drivers/phy/qualcomm/phy-qcom-qmp.c:847:37-43: ERROR: application of sizeof to pointer sizeof when applied to a pointer typed expression gives the size of the pointer Generated by: scripts/coccinelle/misc/noderef.cocci CC: Vivek Gautam Signed-off-by: Fengguang Wu Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/phy-qcom-qmp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/phy/phy-qcom-qmp.c b/drivers/phy/phy-qcom-qmp.c index a25c29d5fdf6..78ca62897784 100644 --- a/drivers/phy/phy-qcom-qmp.c +++ b/drivers/phy/phy-qcom-qmp.c @@ -844,7 +844,7 @@ static int qcom_qmp_phy_vreg_init(struct device *dev) int num = qmp->cfg->num_vregs; int i; - qmp->vregs = devm_kcalloc(dev, num, sizeof(qmp->vregs), GFP_KERNEL); + qmp->vregs = devm_kcalloc(dev, num, sizeof(*qmp->vregs), GFP_KERNEL); if (!qmp->vregs) return -ENOMEM; -- cgit v1.2.3 From a2b05b7aa60e1e9b60faf01dfb1cca35638d1ab1 Mon Sep 17 00:00:00 2001 From: Nicholas Piggin Date: Thu, 11 May 2017 21:24:41 +1000 Subject: powerpc/64s: Add dt_cpu_ftrs boot time setup option Provide a dt_cpu_ftrs= cmdline option to disable the dt_cpu_ftrs CPU feature discovery, and fall back to the "cputable" based version. Also allow control of advertising unknown features to userspace and with this parameter, and remove the clunky CONFIG option. Signed-off-by: Nicholas Piggin [mpe: Add explicit early check of bootargs in dt_cpu_ftrs_init()] Signed-off-by: Michael Ellerman --- Documentation/admin-guide/kernel-parameters.txt | 9 ++++ arch/powerpc/Kconfig | 5 --- arch/powerpc/kernel/dt_cpu_ftrs.c | 57 +++++++++++++++++++++---- 3 files changed, 57 insertions(+), 14 deletions(-) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 15f79c27748d..0f5c3b4347c6 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -866,6 +866,15 @@ dscc4.setup= [NET] + dt_cpu_ftrs= [PPC] + Format: {"off" | "known"} + Control how the dt_cpu_ftrs device-tree binding is + used for CPU feature discovery and setup (if it + exists). + off: Do not use it, fall back to legacy cpu table. + known: Do not pass through unknown features to guests + or userspace, only those that the kernel is aware of. + dump_apple_properties [X86] Dump name and content of EFI device properties on x86 Macs. Useful for driver authors to determine diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index f7c8f9972f61..4a4a05afcaf7 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -391,11 +391,6 @@ config PPC_DT_CPU_FTRS firmware provides this binding. If you're not sure say Y. -config PPC_CPUFEATURES_ENABLE_UNKNOWN - bool "cpufeatures pass through unknown features to guest/userspace" - depends on PPC_DT_CPU_FTRS - default y - config HIGHMEM bool "High memory support" depends on PPC32 diff --git a/arch/powerpc/kernel/dt_cpu_ftrs.c b/arch/powerpc/kernel/dt_cpu_ftrs.c index fcc7588a96d6..76eebba13a1d 100644 --- a/arch/powerpc/kernel/dt_cpu_ftrs.c +++ b/arch/powerpc/kernel/dt_cpu_ftrs.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -671,12 +672,24 @@ static struct dt_cpu_feature_match __initdata {"wait-v3", feat_enable, 0}, }; -/* XXX: how to configure this? Default + boot time? */ -#ifdef CONFIG_PPC_CPUFEATURES_ENABLE_UNKNOWN -#define CPU_FEATURE_ENABLE_UNKNOWN 1 -#else -#define CPU_FEATURE_ENABLE_UNKNOWN 0 -#endif +static bool __initdata using_dt_cpu_ftrs; +static bool __initdata enable_unknown = true; + +static int __init dt_cpu_ftrs_parse(char *str) +{ + if (!str) + return 0; + + if (!strcmp(str, "off")) + using_dt_cpu_ftrs = false; + else if (!strcmp(str, "known")) + enable_unknown = false; + else + return 1; + + return 0; +} +early_param("dt_cpu_ftrs", dt_cpu_ftrs_parse); static void __init cpufeatures_setup_start(u32 isa) { @@ -707,7 +720,7 @@ static bool __init cpufeatures_process_feature(struct dt_cpu_feature *f) } } - if (!known && CPU_FEATURE_ENABLE_UNKNOWN) { + if (!known && enable_unknown) { if (!feat_try_enable_unknown(f)) { pr_info("not enabling: %s (unknown and unsupported by kernel)\n", f->name); @@ -756,6 +769,26 @@ static void __init cpufeatures_setup_finished(void) cur_cpu_spec->cpu_features, cur_cpu_spec->mmu_features); } +static int __init disabled_on_cmdline(void) +{ + unsigned long root, chosen; + const char *p; + + root = of_get_flat_dt_root(); + chosen = of_get_flat_dt_subnode_by_name(root, "chosen"); + if (chosen == -FDT_ERR_NOTFOUND) + return false; + + p = of_get_flat_dt_prop(chosen, "bootargs", NULL); + if (!p) + return false; + + if (strstr(p, "dt_cpu_ftrs=off")) + return true; + + return false; +} + static int __init fdt_find_cpu_features(unsigned long node, const char *uname, int depth, void *data) { @@ -766,8 +799,6 @@ static int __init fdt_find_cpu_features(unsigned long node, const char *uname, return 0; } -static bool __initdata using_dt_cpu_ftrs = false; - bool __init dt_cpu_ftrs_in_use(void) { return using_dt_cpu_ftrs; @@ -775,6 +806,8 @@ bool __init dt_cpu_ftrs_in_use(void) bool __init dt_cpu_ftrs_init(void *fdt) { + using_dt_cpu_ftrs = false; + /* Setup and verify the FDT, if it fails we just bail */ if (!early_init_dt_verify(fdt)) return false; @@ -782,6 +815,9 @@ bool __init dt_cpu_ftrs_init(void *fdt) if (!of_scan_flat_dt(fdt_find_cpu_features, NULL)) return false; + if (disabled_on_cmdline()) + return false; + cpufeatures_setup_cpu(); using_dt_cpu_ftrs = true; @@ -1027,5 +1063,8 @@ static int __init dt_cpu_ftrs_scan_callback(unsigned long node, const char void __init dt_cpu_ftrs_scan(void) { + if (!using_dt_cpu_ftrs) + return; + of_scan_flat_dt(dt_cpu_ftrs_scan_callback, NULL); } -- cgit v1.2.3 From 99acc9bede06bbb2662aafff51f5b9e529fa845e Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Mon, 29 May 2017 20:26:07 +1000 Subject: powerpc/spufs: Fix coredump of SPU contexts If a process dumps core while it has SPU contexts active then we have code to also dump information about the SPU contexts. Unfortunately it's been broken for 3 1/2 years, and we didn't notice. In commit 7b1f4020d0d1 ("spufs: get rid of dump_emit() wrappers") the nread variable was removed and rc used instead. That means when the loop exits successfully, rc has the number of bytes read, but it's then used as the return value for the function, which should return 0 on success. So fix it by setting rc = 0 before returning in the success case. Fixes: 7b1f4020d0d1 ("spufs: get rid of dump_emit() wrappers") Signed-off-by: Michael Ellerman Acked-by: Jeremy Kerr Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/cell/spufs/coredump.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/powerpc/platforms/cell/spufs/coredump.c b/arch/powerpc/platforms/cell/spufs/coredump.c index e5a891ae80ee..84b7ac926ce6 100644 --- a/arch/powerpc/platforms/cell/spufs/coredump.c +++ b/arch/powerpc/platforms/cell/spufs/coredump.c @@ -175,6 +175,8 @@ static int spufs_arch_write_note(struct spu_context *ctx, int i, skip = roundup(cprm->pos - total + sz, 4) - cprm->pos; if (!dump_skip(cprm, skip)) goto Eio; + + rc = 0; out: free_page((unsigned long)buf); return rc; -- cgit v1.2.3 From 6f553912eedafae13ff20b322a65e471fe7f5236 Mon Sep 17 00:00:00 2001 From: Christophe Leroy Date: Wed, 24 May 2017 10:01:55 +0200 Subject: powerpc/sysdev/simple_gpio: Fix oops in gpio save_regs function of_mm_gpiochip_add_data() generates an oops for NULL pointer dereference. of_mm_gpiochip_add_data() calls mm_gc->save_regs() before setting the data, therefore ->save_regs() cannot use gpiochip_get_data() Fixes: 937daafca774 ("powerpc: simple-gpio: use gpiochip data pointer") Cc: stable@vger.kernel.org # v4.7+ Signed-off-by: Christophe Leroy Reviewed-by: Linus Walleij Signed-off-by: Michael Ellerman --- arch/powerpc/sysdev/simple_gpio.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/sysdev/simple_gpio.c b/arch/powerpc/sysdev/simple_gpio.c index ef470b470b04..6afddae2fb47 100644 --- a/arch/powerpc/sysdev/simple_gpio.c +++ b/arch/powerpc/sysdev/simple_gpio.c @@ -75,7 +75,8 @@ static int u8_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) static void u8_gpio_save_regs(struct of_mm_gpio_chip *mm_gc) { - struct u8_gpio_chip *u8_gc = gpiochip_get_data(&mm_gc->gc); + struct u8_gpio_chip *u8_gc = + container_of(mm_gc, struct u8_gpio_chip, mm_gc); u8_gc->data = in_8(mm_gc->regs); } -- cgit v1.2.3 From dc421b200f91930c9c6a9586810ff8c232cf10fc Mon Sep 17 00:00:00 2001 From: Michael Bringmann Date: Mon, 22 May 2017 15:44:37 -0500 Subject: powerpc/hotplug-mem: Fix missing endian conversion of aa_index When adding or removing memory, the aa_index (affinity value) for the memblock must also be converted to match the endianness of the rest of the 'ibm,dynamic-memory' property. Otherwise, subsequent retrieval of the attribute will likely lead to non-existent nodes, followed by using the default node in the code inappropriately. Fixes: 5f97b2a0d176 ("powerpc/pseries: Implement memory hotplug add in the kernel") Cc: stable@vger.kernel.org # v4.1+ Signed-off-by: Michael Bringmann Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/pseries/hotplug-memory.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c index e104c71ea44a..1fb162ba9d1c 100644 --- a/arch/powerpc/platforms/pseries/hotplug-memory.c +++ b/arch/powerpc/platforms/pseries/hotplug-memory.c @@ -124,6 +124,7 @@ static struct property *dlpar_clone_drconf_property(struct device_node *dn) for (i = 0; i < num_lmbs; i++) { lmbs[i].base_addr = be64_to_cpu(lmbs[i].base_addr); lmbs[i].drc_index = be32_to_cpu(lmbs[i].drc_index); + lmbs[i].aa_index = be32_to_cpu(lmbs[i].aa_index); lmbs[i].flags = be32_to_cpu(lmbs[i].flags); } @@ -147,6 +148,7 @@ static void dlpar_update_drconf_property(struct device_node *dn, for (i = 0; i < num_lmbs; i++) { lmbs[i].base_addr = cpu_to_be64(lmbs[i].base_addr); lmbs[i].drc_index = cpu_to_be32(lmbs[i].drc_index); + lmbs[i].aa_index = cpu_to_be32(lmbs[i].aa_index); lmbs[i].flags = cpu_to_be32(lmbs[i].flags); } -- cgit v1.2.3 From 0e5e7f5e9700661c3ddd95501743fb52fec1ab07 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 25 May 2017 16:33:52 +1000 Subject: powerpc/64: Reclaim CPU_FTR_SUBCORE We are running low on CPU feature bits, so we only want to use them when it's really necessary. CPU_FTR_SUBCORE is only used in one place, and only in C, so we don't need it in order to make asm patching work. It can only be set on "Power8" CPUs, which in practice means POWER8, POWER8E and POWER8NVL. There are no plans to implement it on future CPUs, but if there ever were we could retrofit it then. Although KVM uses subcores, it never looks at the CPU feature, it either looks at the ISA level or the threads_per_subcore value. So drop the CPU feature and do a PVR check instead. Drop the device tree "subcore" feature as we no longer support doing anything with it, and we will drop it from skiboot too. Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/cputable.h | 3 +-- arch/powerpc/kernel/dt_cpu_ftrs.c | 1 - arch/powerpc/platforms/powernv/subcore.c | 8 +++++++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h index c2d509584a98..d02ad93bf708 100644 --- a/arch/powerpc/include/asm/cputable.h +++ b/arch/powerpc/include/asm/cputable.h @@ -214,7 +214,6 @@ enum { #define CPU_FTR_DAWR LONG_ASM_CONST(0x0400000000000000) #define CPU_FTR_DABRX LONG_ASM_CONST(0x0800000000000000) #define CPU_FTR_PMAO_BUG LONG_ASM_CONST(0x1000000000000000) -#define CPU_FTR_SUBCORE LONG_ASM_CONST(0x2000000000000000) #define CPU_FTR_POWER9_DD1 LONG_ASM_CONST(0x4000000000000000) #ifndef __ASSEMBLY__ @@ -463,7 +462,7 @@ enum { CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \ CPU_FTR_ICSWX | CPU_FTR_CFAR | CPU_FTR_HVMODE | CPU_FTR_VMX_COPY | \ CPU_FTR_DBELL | CPU_FTR_HAS_PPR | CPU_FTR_DAWR | \ - CPU_FTR_ARCH_207S | CPU_FTR_TM_COMP | CPU_FTR_SUBCORE) + CPU_FTR_ARCH_207S | CPU_FTR_TM_COMP) #define CPU_FTRS_POWER8E (CPU_FTRS_POWER8 | CPU_FTR_PMAO_BUG) #define CPU_FTRS_POWER8_DD1 (CPU_FTRS_POWER8 & ~CPU_FTR_DBELL) #define CPU_FTRS_POWER9 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \ diff --git a/arch/powerpc/kernel/dt_cpu_ftrs.c b/arch/powerpc/kernel/dt_cpu_ftrs.c index 76eebba13a1d..4c7656dc4e04 100644 --- a/arch/powerpc/kernel/dt_cpu_ftrs.c +++ b/arch/powerpc/kernel/dt_cpu_ftrs.c @@ -643,7 +643,6 @@ static struct dt_cpu_feature_match __initdata {"processor-control-facility", feat_enable_dbell, CPU_FTR_DBELL}, {"processor-control-facility-v3", feat_enable_dbell, CPU_FTR_DBELL}, {"processor-utilization-of-resources-register", feat_enable_purr, 0}, - {"subcore", feat_enable, CPU_FTR_SUBCORE}, {"no-execute", feat_enable, 0}, {"strong-access-ordering", feat_enable, CPU_FTR_SAO}, {"cache-inhibited-large-page", feat_enable_large_ci, 0}, diff --git a/arch/powerpc/platforms/powernv/subcore.c b/arch/powerpc/platforms/powernv/subcore.c index 0babef11136f..8c6119280c13 100644 --- a/arch/powerpc/platforms/powernv/subcore.c +++ b/arch/powerpc/platforms/powernv/subcore.c @@ -407,7 +407,13 @@ static DEVICE_ATTR(subcores_per_core, 0644, static int subcore_init(void) { - if (!cpu_has_feature(CPU_FTR_SUBCORE)) + unsigned pvr_ver; + + pvr_ver = PVR_VER(mfspr(SPRN_PVR)); + + if (pvr_ver != PVR_POWER8 && + pvr_ver != PVR_POWER8E && + pvr_ver != PVR_POWER8NVL) return 0; /* -- cgit v1.2.3 From 54265664c15a68905d8d67d19205e9a767636434 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Wed, 31 May 2017 13:35:57 +0200 Subject: perf trace: Add mmap alias for s390 The s390 architecture maps sys_mmap (nr 90) into sys_old_mmap. For this reason perf trace can't find the proper syscall event to get args format from and displays it wrongly as 'continued'. To fix that fill the "alias" field with "old_mmap" for trace's mmap record to get the correct translation. Before: 0.042 ( 0.011 ms): vest/43052 fstat(statbuf: 0x3ffff89fd90 ) = 0 0.042 ( 0.028 ms): vest/43052 ... [continued]: mmap()) = 0x3fffd6e2000 0.072 ( 0.025 ms): vest/43052 read(buf: 0x3fffd6e2000, count: 4096 ) = 6 After: 0.045 ( 0.011 ms): fstat(statbuf: 0x3ffff8a0930 ) = 0 0.057 ( 0.018 ms): mmap(arg: 0x3ffff8a0858 ) = 0x3fffd14a000 0.076 ( 0.025 ms): read(buf: 0x3fffd14a000, count: 4096 ) = 6 Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20170531113557.19175-1-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index d014350adc52..4b2a5d298197 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -681,6 +681,10 @@ static struct syscall_fmt { { .name = "mlockall", .errmsg = true, .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, }, { .name = "mmap", .hexret = true, +/* The standard mmap maps to old_mmap on s390x */ +#if defined(__s390x__) + .alias = "old_mmap", +#endif .arg_scnprintf = { [0] = SCA_HEX, /* addr */ [2] = SCA_MMAP_PROT, /* prot */ [3] = SCA_MMAP_FLAGS, /* flags */ }, }, -- cgit v1.2.3 From c08d517480ea342cc43acdacc5cf4a795e18151d Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 1 Jun 2017 15:52:23 +0200 Subject: Revert "x86/PAT: Fix Xorg regression on CPUs that don't support PAT" This reverts commit cbed27cdf0e3f7ea3b2259e86b9e34df02be3fe4. As Andy Lutomirski observed: "I think this patch is bogus. pat_enabled() sure looks like it's supposed to return true if PAT is *enabled*, and these days PAT is 'enabled' even if there's no HW PAT support." Reported-by: Bernhard Held Reported-by: Chris Wilson Acked-by: Andy Lutomirski Cc: Andrew Morton Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Josh Poimboeuf Cc: Linus Torvalds Cc: Luis R. Rodriguez Cc: Mikulas Patocka Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Toshi Kani Cc: stable@vger.kernel.org # v4.2+ Cc: linux-kernel@vger.kernel.org Signed-off-by: Ingo Molnar --- arch/x86/mm/pat.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c index 83a59a67757a..9b78685b66e6 100644 --- a/arch/x86/mm/pat.c +++ b/arch/x86/mm/pat.c @@ -65,11 +65,9 @@ static int __init nopat(char *str) } early_param("nopat", nopat); -static bool __read_mostly __pat_initialized = false; - bool pat_enabled(void) { - return __pat_initialized; + return !!__pat_enabled; } EXPORT_SYMBOL_GPL(pat_enabled); @@ -227,14 +225,13 @@ static void pat_bsp_init(u64 pat) } wrmsrl(MSR_IA32_CR_PAT, pat); - __pat_initialized = true; __init_cache_modes(pat); } static void pat_ap_init(u64 pat) { - if (!this_cpu_has(X86_FEATURE_PAT)) { + if (!boot_cpu_has(X86_FEATURE_PAT)) { /* * If this happens we are on a secondary CPU, but switched to * PAT on the boot CPU. We have no way to undo PAT. @@ -309,7 +306,7 @@ void pat_init(void) u64 pat; struct cpuinfo_x86 *c = &boot_cpu_data; - if (!__pat_enabled) { + if (!pat_enabled()) { init_cache_modes(); return; } -- cgit v1.2.3 From cc2b702c52094b637a351d7491ac5200331d0445 Mon Sep 17 00:00:00 2001 From: David Sterba Date: Fri, 12 May 2017 01:03:52 +0200 Subject: btrfs: use correct types for page indices in btrfs_page_exists_in_range Variables start_idx and end_idx are supposed to hold a page index derived from the file offsets. The int type is not the right one though, offsets larger than 1 << 44 will get silently trimmed off the high bits. (1 << 44 is 16TiB) What can go wrong, if start is below the boundary and end gets trimmed: - if there's a page after start, we'll find it (radix_tree_gang_lookup_slot) - the final check "if (page->index <= end_idx)" will unexpectedly fail The function will return false, ie. "there's no page in the range", although there is at least one. btrfs_page_exists_in_range is used to prevent races in: * in hole punching, where we make sure there are not pages in the truncated range, otherwise we'll wait for them to finish and redo truncation, but we're going to replace the pages with holes anyway so the only problem is the intermediate state * lock_extent_direct: we want to make sure there are no pages before we lock and start DIO, to prevent stale data reads For practical occurence of the bug, there are several constaints. The file must be quite large, the affected range must cross the 16TiB boundary and the internal state of the file pages and pending operations must match. Also, we must not have started any ordered data in the range, otherwise we don't even reach the buggy function check. DIO locking tries hard in several places to avoid deadlocks with buffered IO and avoids waiting for ranges. The worst consequence seems to be stale data read. CC: Liu Bo CC: stable@vger.kernel.org # 3.16+ Fixes: fc4adbff823f7 ("btrfs: Drop EXTENT_UPTODATE check in hole punching and direct locking") Reviewed-by: Liu Bo Signed-off-by: David Sterba --- fs/btrfs/inode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 17cbe9306faf..3fc3e10594a4 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -7483,8 +7483,8 @@ bool btrfs_page_exists_in_range(struct inode *inode, loff_t start, loff_t end) int found = false; void **pagep = NULL; struct page *page = NULL; - int start_idx; - int end_idx; + unsigned long start_idx; + unsigned long end_idx; start_idx = start >> PAGE_SHIFT; -- cgit v1.2.3 From 896533a7da929136d0432713f02a3edffece2826 Mon Sep 17 00:00:00 2001 From: Jeff Mahoney Date: Wed, 17 May 2017 09:49:37 -0400 Subject: btrfs: fix memory leak in update_space_info failure path If we fail to add the space_info kobject, we'll leak the memory for the percpu counter. Fixes: 6ab0a2029c (btrfs: publish allocation data in sysfs) Cc: # v3.14+ Signed-off-by: Jeff Mahoney Reviewed-by: Liu Bo Signed-off-by: David Sterba --- fs/btrfs/extent-tree.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index e390451c72e6..27ca5b81ed22 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -3993,6 +3993,7 @@ static int update_space_info(struct btrfs_fs_info *info, u64 flags, info->space_info_kobj, "%s", alloc_name(found->flags)); if (ret) { + percpu_counter_destroy(&found->total_bytes_pinned); kfree(found); return ret; } -- cgit v1.2.3 From a9b3311ef36b670909ea4443f306c8318082c8f0 Mon Sep 17 00:00:00 2001 From: Jeff Mahoney Date: Wed, 17 May 2017 11:38:34 -0400 Subject: btrfs: fix race with relocation recovery and fs_root setup If we have to recover relocation during mount, we'll ultimately have to evict the orphan inode. That goes through the reservation dance, where priority_reclaim_metadata_space and flush_space expect fs_info->fs_root to be valid. That's the next thing to be set up during mount, so we crash, almost always in flush_space trying to join the transaction but priority_reclaim_metadata_space is possible as well. This call path has been problematic in the past WRT whether ->fs_root is valid yet. Commit 957780eb278 (Btrfs: introduce ticketed enospc infrastructure) added new users that are called in the direct path instead of the async path that had already been worked around. The thing is that we don't actually need the fs_root, specifically, for anything. We either use it to determine whether the root is the chunk_root for use in choosing an allocation profile or as a root to pass btrfs_join_transaction before immediately committing it. Anything that isn't the chunk root works in the former case and any root works in the latter. A simple fix is to use a root we know will always be there: the extent_root. Cc: # v4.8+ Fixes: 957780eb278 (Btrfs: introduce ticketed enospc infrastructure) Signed-off-by: Jeff Mahoney Reviewed-by: Liu Bo Signed-off-by: David Sterba --- fs/btrfs/extent-tree.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 27ca5b81ed22..33d979e9ea2a 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -4845,7 +4845,7 @@ static int may_commit_transaction(struct btrfs_fs_info *fs_info, spin_unlock(&delayed_rsv->lock); commit: - trans = btrfs_join_transaction(fs_info->fs_root); + trans = btrfs_join_transaction(fs_info->extent_root); if (IS_ERR(trans)) return -ENOSPC; @@ -4863,7 +4863,7 @@ static int flush_space(struct btrfs_fs_info *fs_info, struct btrfs_space_info *space_info, u64 num_bytes, u64 orig_bytes, int state) { - struct btrfs_root *root = fs_info->fs_root; + struct btrfs_root *root = fs_info->extent_root; struct btrfs_trans_handle *trans; int nr; int ret = 0; @@ -5063,7 +5063,7 @@ static void priority_reclaim_metadata_space(struct btrfs_fs_info *fs_info, int flush_state = FLUSH_DELAYED_ITEMS_NR; spin_lock(&space_info->lock); - to_reclaim = btrfs_calc_reclaim_metadata_size(fs_info->fs_root, + to_reclaim = btrfs_calc_reclaim_metadata_size(fs_info->extent_root, space_info); if (!to_reclaim) { spin_unlock(&space_info->lock); -- cgit v1.2.3 From 5ea6d691aac6c93b790f0905e3460d44cc4c449b Mon Sep 17 00:00:00 2001 From: Jia-Ju Bai Date: Thu, 1 Jun 2017 16:18:10 +0800 Subject: qlcnic: Fix a sleep-in-atomic bug in qlcnic_82xx_hw_write_wx_2M and qlcnic_82xx_hw_read_wx_2M The driver may sleep under a write spin lock, and the function call path is: qlcnic_82xx_hw_write_wx_2M (acquire the lock by write_lock_irqsave) crb_win_lock qlcnic_pcie_sem_lock usleep_range qlcnic_82xx_hw_read_wx_2M (acquire the lock by write_lock_irqsave) crb_win_lock qlcnic_pcie_sem_lock usleep_range To fix it, the usleep_range is replaced with udelay. Signed-off-by: Jia-Ju Bai Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c index 838cc0ceafd8..7848cf04b29a 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c @@ -341,7 +341,7 @@ qlcnic_pcie_sem_lock(struct qlcnic_adapter *adapter, int sem, u32 id_reg) } return -EIO; } - usleep_range(1000, 1500); + udelay(1200); } if (id_reg) -- cgit v1.2.3 From 7212462fa6fdae61f7f40a4ead048def45bb23cb Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Thu, 1 Jun 2017 10:00:07 +0200 Subject: netlink: don't send unknown nsid The NETLINK_F_LISTEN_ALL_NSID otion enables to listen all netns that have a nsid assigned into the netns where the netlink socket is opened. The nsid is sent as metadata to userland, but the existence of this nsid is checked only for netns that are different from the socket netns. Thus, if no nsid is assigned to the socket netns, NETNSA_NSID_NOT_ASSIGNED is reported to the userland. This value is confusing and useless. After this patch, only valid nsid are sent to userland. Reported-by: Flavio Leitner Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- net/netlink/af_netlink.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index ee841f00a6ec..7586d446d7dc 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -62,6 +62,7 @@ #include #include #include +#include #include #include @@ -1415,7 +1416,8 @@ static void do_one_broadcast(struct sock *sk, goto out; } NETLINK_CB(p->skb2).nsid = peernet2id(sock_net(sk), p->net); - NETLINK_CB(p->skb2).nsid_is_set = true; + if (NETLINK_CB(p->skb2).nsid != NETNSA_NSID_NOT_ASSIGNED) + NETLINK_CB(p->skb2).nsid_is_set = true; val = netlink_broadcast_deliver(sk, p->skb2); if (val < 0) { netlink_overrun(sk); -- cgit v1.2.3 From 2b7ea64f94347b72235e563fedd6ef1ead4d11ec Mon Sep 17 00:00:00 2001 From: Ganesh Goudar Date: Thu, 1 Jun 2017 17:11:30 +0530 Subject: cxgb4: update latest firmware version supported Change t4fw_version.h to update latest firmware version number to 1.16.45.0. Signed-off-by: Ganesh Goudar Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/t4fw_version.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4fw_version.h b/drivers/net/ethernet/chelsio/cxgb4/t4fw_version.h index 3549d3876278..f2d623a7aee0 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4fw_version.h +++ b/drivers/net/ethernet/chelsio/cxgb4/t4fw_version.h @@ -37,7 +37,7 @@ #define T4FW_VERSION_MAJOR 0x01 #define T4FW_VERSION_MINOR 0x10 -#define T4FW_VERSION_MICRO 0x2B +#define T4FW_VERSION_MICRO 0x2D #define T4FW_VERSION_BUILD 0x00 #define T4FW_MIN_VERSION_MAJOR 0x01 @@ -46,7 +46,7 @@ #define T5FW_VERSION_MAJOR 0x01 #define T5FW_VERSION_MINOR 0x10 -#define T5FW_VERSION_MICRO 0x2B +#define T5FW_VERSION_MICRO 0x2D #define T5FW_VERSION_BUILD 0x00 #define T5FW_MIN_VERSION_MAJOR 0x00 @@ -55,7 +55,7 @@ #define T6FW_VERSION_MAJOR 0x01 #define T6FW_VERSION_MINOR 0x10 -#define T6FW_VERSION_MICRO 0x2B +#define T6FW_VERSION_MICRO 0x2D #define T6FW_VERSION_BUILD 0x00 #define T6FW_MIN_VERSION_MAJOR 0x00 -- cgit v1.2.3 From 3968d38917eb9bd0cd391265f6c9c538d9b33ffa Mon Sep 17 00:00:00 2001 From: "Mintz, Yuval" Date: Thu, 1 Jun 2017 15:57:56 +0300 Subject: bnx2x: Fix Multi-Cos Apparently multi-cos isn't working for bnx2x quite some time - driver implements ndo_select_queue() to allow queue-selection for FCoE, but the regular L2 flow would cause it to modulo the fallback's result by the number of queues. The fallback would return a queue matching the needed tc [via __skb_tx_hash()], but since the modulo is by the number of TSS queues where number of TCs is not accounted, transmission would always be done by a queue configured into using TC0. Fixes: ada7c19e6d27 ("bnx2x: use XPS if possible for bnx2x_select_queue instead of pure hash") Signed-off-by: Yuval Mintz Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index eccb3d1b6abb..5f49334dcad5 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -1926,7 +1926,7 @@ u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb, } /* select a non-FCoE queue */ - return fallback(dev, skb) % BNX2X_NUM_ETH_QUEUES(bp); + return fallback(dev, skb) % (BNX2X_NUM_ETH_QUEUES(bp) * bp->max_cos); } void bnx2x_set_num_queues(struct bnx2x *bp) -- cgit v1.2.3 From aeb073241fe7a2b932e04e20c60e47718332877f Mon Sep 17 00:00:00 2001 From: Nikolay Aleksandrov Date: Thu, 1 Jun 2017 18:07:55 +0300 Subject: net: bridge: start hello timer only if device is up When the transition of NO_STP -> KERNEL_STP was fixed by always calling mod_timer in br_stp_start, it introduced a new regression which causes the timer to be armed even when the bridge is down, and since we stop the timers in its ndo_stop() function, they never get disabled if the device is destroyed before it's upped. To reproduce: $ while :; do ip l add br0 type bridge hello_time 100; brctl stp br0 on; ip l del br0; done; CC: Xin Long CC: Ivan Vecera CC: Sebastian Ott Reported-by: Sebastian Ott Fixes: 6d18c732b95c ("bridge: start hello_timer when enabling KERNEL_STP in br_stp_start") Signed-off-by: Nikolay Aleksandrov Signed-off-by: David S. Miller --- net/bridge/br_stp_if.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c index 0db8102995a5..6f12a5271219 100644 --- a/net/bridge/br_stp_if.c +++ b/net/bridge/br_stp_if.c @@ -179,7 +179,8 @@ static void br_stp_start(struct net_bridge *br) br_debug(br, "using kernel STP\n"); /* To start timers on any ports left in blocking */ - mod_timer(&br->hello_timer, jiffies + br->hello_time); + if (br->dev->flags & IFF_UP) + mod_timer(&br->hello_timer, jiffies + br->hello_time); br_port_state_selection(br); } -- cgit v1.2.3 From 0fde7ad71ee371ede73b3f326e58f9e8d102feb6 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 1 Jun 2017 09:42:46 -0700 Subject: sparc64: Fix build warnings with gcc 7. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit arch/sparc/kernel/ds.c: In function ‘register_services’: arch/sparc/kernel/ds.c:912:3: error: ‘strcpy’: writing at least 1 byte into a region of size 0 overflows the destination Reported-by: Anatoly Pugachev Signed-off-by: David S. Miller --- arch/sparc/kernel/ds.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sparc/kernel/ds.c b/arch/sparc/kernel/ds.c index b542cc7c8d94..f87265afb175 100644 --- a/arch/sparc/kernel/ds.c +++ b/arch/sparc/kernel/ds.c @@ -909,7 +909,7 @@ static int register_services(struct ds_info *dp) pbuf.req.handle = cp->handle; pbuf.req.major = 1; pbuf.req.minor = 0; - strcpy(pbuf.req.svc_id, cp->service_id); + strcpy(pbuf.id_buf, cp->service_id); err = __ds_send(lp, &pbuf, msg_len); if (err > 0) -- cgit v1.2.3 From b13bbeee5ee606cfb57ddcf47e66802f9aa7273e Mon Sep 17 00:00:00 2001 From: Kim Phillips Date: Thu, 1 Jun 2017 09:29:59 -0500 Subject: perf annotate: Fix branch instruction with multiple operands MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 'perf annotate' is dropping the cr* fields from branch instructions. Fix it by adding support to display branch instructions having multiple operands. Power Arch objdump of int_sqrt: 20.36 | c0000000004d2694: subf r10,r10,r3 | c0000000004d2698: v bgt cr6,c0000000004d26a0 1.82 | c0000000004d269c: mr r3,r10 29.18 | c0000000004d26a0: mr r10,r8 | c0000000004d26a4: v bgt cr7,c0000000004d26ac | c0000000004d26a8: mr r10,r7 Power Arch Before Patch: 20.36 | subf r10,r10,r3 | v bgt 40 1.82 | mr r3,r10 29.18 | 40: mr r10,r8 | v bgt 4c | mr r10,r7 Power Arch After patch: 20.36 | subf r10,r10,r3 | v bgt cr6,40 1.82 | mr r3,r10 29.18 | 40: mr r10,r8 | v bgt cr7,4c | mr r10,r7 Also support AArch64 conditional branch instructions, which can have up to three operands: Aarch64 Non-simplified (raw objdump) view: │ffff0000083cd11c: ↑ cbz w0, ffff0000083cd100 Tested-by: Ravi Bangoria Reported-by: Anton Blanchard Reported-by: Robin Murphy Signed-off-by: Kim Phillips Cc: Alexander Shishkin Cc: Christian Borntraeger Cc: Mark Rutland Cc: Peter Zijlstra Cc: Taeung Song Link: http://lkml.kernel.org/r/20170601092959.f60d98912e8a1b66fd1e4c0e@arm.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/annotate.c | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 07d5608a675f..1367d7e35242 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -239,10 +239,20 @@ static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *op const char *s = strchr(ops->raw, '+'); const char *c = strchr(ops->raw, ','); - if (c++ != NULL) + /* + * skip over possible up to 2 operands to get to address, e.g.: + * tbnz w0, #26, ffff0000083cd190 + */ + if (c++ != NULL) { ops->target.addr = strtoull(c, NULL, 16); - else + if (!ops->target.addr) { + c = strchr(c, ','); + if (c++ != NULL) + ops->target.addr = strtoull(c, NULL, 16); + } + } else { ops->target.addr = strtoull(ops->raw, NULL, 16); + } if (s++ != NULL) { ops->target.offset = strtoull(s, NULL, 16); @@ -257,10 +267,27 @@ static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *op static int jump__scnprintf(struct ins *ins, char *bf, size_t size, struct ins_operands *ops) { + const char *c = strchr(ops->raw, ','); + if (!ops->target.addr || ops->target.offset < 0) return ins__raw_scnprintf(ins, bf, size, ops); - return scnprintf(bf, size, "%-6.6s %" PRIx64, ins->name, ops->target.offset); + if (c != NULL) { + const char *c2 = strchr(c + 1, ','); + + /* check for 3-op insn */ + if (c2 != NULL) + c = c2; + c++; + + /* mirror arch objdump's space-after-comma style */ + if (*c == ' ') + c++; + } + + return scnprintf(bf, size, "%-6.6s %.*s%" PRIx64, + ins->name, c ? c - ops->raw : 0, ops->raw, + ops->target.offset); } static struct ins_ops jump_ops = { -- cgit v1.2.3 From 35cf2845563c1aaa01d27bd34d64795c4ae72700 Mon Sep 17 00:00:00 2001 From: Lance Richardson Date: Mon, 29 May 2017 13:25:57 -0400 Subject: vxlan: eliminate cached dst leak After commit 0c1d70af924b ("net: use dst_cache for vxlan device"), cached dst entries could be leaked when more than one remote was present for a given vxlan_fdb entry, causing subsequent netns operations to block indefinitely and "unregister_netdevice: waiting for lo to become free." messages to appear in the kernel log. Fix by properly releasing cached dst and freeing resources in this case. Fixes: 0c1d70af924b ("net: use dst_cache for vxlan device") Signed-off-by: Lance Richardson Acked-by: Paolo Abeni Signed-off-by: David S. Miller --- drivers/net/vxlan.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 328b4712683c..5c1d69e37870 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -740,6 +740,22 @@ static void vxlan_fdb_destroy(struct vxlan_dev *vxlan, struct vxlan_fdb *f) call_rcu(&f->rcu, vxlan_fdb_free); } +static void vxlan_dst_free(struct rcu_head *head) +{ + struct vxlan_rdst *rd = container_of(head, struct vxlan_rdst, rcu); + + dst_cache_destroy(&rd->dst_cache); + kfree(rd); +} + +static void vxlan_fdb_dst_destroy(struct vxlan_dev *vxlan, struct vxlan_fdb *f, + struct vxlan_rdst *rd) +{ + list_del_rcu(&rd->list); + vxlan_fdb_notify(vxlan, f, rd, RTM_DELNEIGH); + call_rcu(&rd->rcu, vxlan_dst_free); +} + static int vxlan_fdb_parse(struct nlattr *tb[], struct vxlan_dev *vxlan, union vxlan_addr *ip, __be16 *port, __be32 *src_vni, __be32 *vni, u32 *ifindex) @@ -864,9 +880,7 @@ static int __vxlan_fdb_delete(struct vxlan_dev *vxlan, * otherwise destroy the fdb entry */ if (rd && !list_is_singular(&f->remotes)) { - list_del_rcu(&rd->list); - vxlan_fdb_notify(vxlan, f, rd, RTM_DELNEIGH); - kfree_rcu(rd, rcu); + vxlan_fdb_dst_destroy(vxlan, f, rd); goto out; } -- cgit v1.2.3 From 93818da5eed63fbc17b64080406ea53b86b23309 Mon Sep 17 00:00:00 2001 From: Jia-Ju Bai Date: Wed, 31 May 2017 15:08:25 +0800 Subject: mISDN: Fix a sleep-in-atomic bug The driver may sleep under a read spin lock, and the function call path is: send_socklist (acquire the lock by read_lock) skb_copy(GFP_KERNEL) --> may sleep To fix it, the "GFP_KERNEL" is replaced with "GFP_ATOMIC". Signed-off-by: Jia-Ju Bai Signed-off-by: David S. Miller --- drivers/isdn/mISDN/stack.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/isdn/mISDN/stack.c b/drivers/isdn/mISDN/stack.c index 8b7faea2ddf8..422dced7c90a 100644 --- a/drivers/isdn/mISDN/stack.c +++ b/drivers/isdn/mISDN/stack.c @@ -75,7 +75,7 @@ send_socklist(struct mISDN_sock_list *sl, struct sk_buff *skb) if (sk->sk_state != MISDN_BOUND) continue; if (!cskb) - cskb = skb_copy(skb, GFP_KERNEL); + cskb = skb_copy(skb, GFP_ATOMIC); if (!cskb) { printk(KERN_WARNING "%s no skb\n", __func__); break; -- cgit v1.2.3 From e6f4292ae0a1e73fae26ced57de13a48f71ad1fa Mon Sep 17 00:00:00 2001 From: Leonard Crestez Date: Wed, 31 May 2017 13:29:29 +0300 Subject: ARM: dts: imx6ul-14x14-evk: Add ksz8081 phy properties Right now mach-imx6ul registers a fixup for the ksz8081 phy. The same register values can be set through the micrel phy driver by using dts properties. This seems preferable and allows cleanly fixing suspend/resume. Signed-off-by: Leonard Crestez Reviewed-by: Fabio Estevam Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- arch/arm/boot/dts/imx6ul-14x14-evk.dts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/boot/dts/imx6ul-14x14-evk.dts b/arch/arm/boot/dts/imx6ul-14x14-evk.dts index f18e1f1d0ce2..d2be8aa3370b 100644 --- a/arch/arm/boot/dts/imx6ul-14x14-evk.dts +++ b/arch/arm/boot/dts/imx6ul-14x14-evk.dts @@ -120,10 +120,16 @@ ethphy0: ethernet-phy@2 { reg = <2>; + micrel,led-mode = <1>; + clocks = <&clks IMX6UL_CLK_ENET_REF>; + clock-names = "rmii-ref"; }; ethphy1: ethernet-phy@1 { reg = <1>; + micrel,led-mode = <1>; + clocks = <&clks IMX6UL_CLK_ENET2_REF>; + clock-names = "rmii-ref"; }; }; }; -- cgit v1.2.3 From 79e498a9c7da0737829ff864aae44df434105676 Mon Sep 17 00:00:00 2001 From: Leonard Crestez Date: Wed, 31 May 2017 13:29:30 +0300 Subject: net: phy: micrel: Restore led_mode and clk_sel on resume These bits seem to be lost after a suspend/resume cycle so just set them again. Do this by splitting the handling of these bits into a function that is also called on resume. This patch fixes ethernet suspend/resume on imx6ul-14x14-evk boards. Signed-off-by: Leonard Crestez Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/micrel.c | 42 ++++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c index 6a5fd18f062c..b9252b8d81ff 100644 --- a/drivers/net/phy/micrel.c +++ b/drivers/net/phy/micrel.c @@ -268,23 +268,12 @@ out: return ret; } -static int kszphy_config_init(struct phy_device *phydev) +/* Some config bits need to be set again on resume, handle them here. */ +static int kszphy_config_reset(struct phy_device *phydev) { struct kszphy_priv *priv = phydev->priv; - const struct kszphy_type *type; int ret; - if (!priv) - return 0; - - type = priv->type; - - if (type->has_broadcast_disable) - kszphy_broadcast_disable(phydev); - - if (type->has_nand_tree_disable) - kszphy_nand_tree_disable(phydev); - if (priv->rmii_ref_clk_sel) { ret = kszphy_rmii_clk_sel(phydev, priv->rmii_ref_clk_sel_val); if (ret) { @@ -295,11 +284,30 @@ static int kszphy_config_init(struct phy_device *phydev) } if (priv->led_mode >= 0) - kszphy_setup_led(phydev, type->led_mode_reg, priv->led_mode); + kszphy_setup_led(phydev, priv->type->led_mode_reg, priv->led_mode); return 0; } +static int kszphy_config_init(struct phy_device *phydev) +{ + struct kszphy_priv *priv = phydev->priv; + const struct kszphy_type *type; + + if (!priv) + return 0; + + type = priv->type; + + if (type->has_broadcast_disable) + kszphy_broadcast_disable(phydev); + + if (type->has_nand_tree_disable) + kszphy_nand_tree_disable(phydev); + + return kszphy_config_reset(phydev); +} + static int ksz8041_config_init(struct phy_device *phydev) { struct device_node *of_node = phydev->mdio.dev.of_node; @@ -700,8 +708,14 @@ static int kszphy_suspend(struct phy_device *phydev) static int kszphy_resume(struct phy_device *phydev) { + int ret; + genphy_resume(phydev); + ret = kszphy_config_reset(phydev); + if (ret) + return ret; + /* Enable PHY Interrupts */ if (phy_interrupt_is_valid(phydev)) { phydev->interrupts = PHY_INTERRUPT_ENABLED; -- cgit v1.2.3 From b425e50492583b10cceb388af36ef0bd3bdf842a Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Wed, 31 May 2017 14:43:45 -0700 Subject: block: Avoid that blk_exit_rl() triggers a use-after-free Since the introduction of .init_rq_fn() and .exit_rq_fn() it is essential that the memory allocated for struct request_queue stays around until all blk_exit_rl() calls have finished. Hence make blk_init_rl() take a reference on struct request_queue. This patch fixes the following crash: general protection fault: 0000 [#2] SMP CPU: 3 PID: 28 Comm: ksoftirqd/3 Tainted: G D 4.12.0-rc2-dbg+ #2 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.0.0-prebuilt.qemu-project.org 04/01/2014 task: ffff88013a108040 task.stack: ffffc9000071c000 RIP: 0010:free_request_size+0x1a/0x30 RSP: 0018:ffffc9000071fd38 EFLAGS: 00010202 RAX: 6b6b6b6b6b6b6b6b RBX: ffff880067362a88 RCX: 0000000000000003 RDX: ffff880067464178 RSI: ffff880067362a88 RDI: ffff880135ea4418 RBP: ffffc9000071fd40 R08: 0000000000000000 R09: 0000000100180009 R10: ffffc9000071fd38 R11: ffffffff81110800 R12: ffff88006752d3d8 R13: ffff88006752d3d8 R14: ffff88013a108040 R15: 000000000000000a FS: 0000000000000000(0000) GS:ffff88013fd80000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007fa8ec1edb00 CR3: 0000000138ee8000 CR4: 00000000001406e0 Call Trace: mempool_destroy.part.10+0x21/0x40 mempool_destroy+0xe/0x10 blk_exit_rl+0x12/0x20 blkg_free+0x4d/0xa0 __blkg_release_rcu+0x59/0x170 rcu_process_callbacks+0x260/0x4e0 __do_softirq+0x116/0x250 smpboot_thread_fn+0x123/0x1e0 kthread+0x109/0x140 ret_from_fork+0x31/0x40 Fixes: commit e9c787e65c0c ("scsi: allocate scsi_cmnd structures as part of struct request") Signed-off-by: Bart Van Assche Acked-by: Tejun Heo Reviewed-by: Hannes Reinecke Reviewed-by: Christoph Hellwig Cc: Jan Kara Cc: # v4.11+ Signed-off-by: Jens Axboe --- block/blk-cgroup.c | 2 +- block/blk-core.c | 10 ++++++++-- block/blk-sysfs.c | 2 +- block/blk.h | 2 +- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c index 7c2947128f58..0480892e97e5 100644 --- a/block/blk-cgroup.c +++ b/block/blk-cgroup.c @@ -74,7 +74,7 @@ static void blkg_free(struct blkcg_gq *blkg) blkcg_policy[i]->pd_free_fn(blkg->pd[i]); if (blkg->blkcg != &blkcg_root) - blk_exit_rl(&blkg->rl); + blk_exit_rl(blkg->q, &blkg->rl); blkg_rwstat_exit(&blkg->stat_ios); blkg_rwstat_exit(&blkg->stat_bytes); diff --git a/block/blk-core.c b/block/blk-core.c index c7068520794b..a7421b772d0e 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -648,13 +648,19 @@ int blk_init_rl(struct request_list *rl, struct request_queue *q, if (!rl->rq_pool) return -ENOMEM; + if (rl != &q->root_rl) + WARN_ON_ONCE(!blk_get_queue(q)); + return 0; } -void blk_exit_rl(struct request_list *rl) +void blk_exit_rl(struct request_queue *q, struct request_list *rl) { - if (rl->rq_pool) + if (rl->rq_pool) { mempool_destroy(rl->rq_pool); + if (rl != &q->root_rl) + blk_put_queue(q); + } } struct request_queue *blk_alloc_queue(gfp_t gfp_mask) diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c index 712b018e9f54..283da7fbe034 100644 --- a/block/blk-sysfs.c +++ b/block/blk-sysfs.c @@ -809,7 +809,7 @@ static void blk_release_queue(struct kobject *kobj) blk_free_queue_stats(q->stats); - blk_exit_rl(&q->root_rl); + blk_exit_rl(q, &q->root_rl); if (q->queue_tags) __blk_queue_free_tags(q); diff --git a/block/blk.h b/block/blk.h index 2ed70228e44f..83c8e1100525 100644 --- a/block/blk.h +++ b/block/blk.h @@ -59,7 +59,7 @@ void blk_free_flush_queue(struct blk_flush_queue *q); int blk_init_rl(struct request_list *rl, struct request_queue *q, gfp_t gfp_mask); -void blk_exit_rl(struct request_list *rl); +void blk_exit_rl(struct request_queue *q, struct request_list *rl); void blk_rq_bio_prep(struct request_queue *q, struct request *rq, struct bio *bio); void blk_queue_bypass_start(struct request_queue *q); -- cgit v1.2.3 From e165bc02a02c70e40d5c811c705ba269aeca0497 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 1 Jun 2017 21:26:03 +0200 Subject: mac80211: fix dropped counter in multiqueue RX In the commit enabling per-CPU station statistics, I inadvertedly copy-pasted some code to update rx_packets and forgot to change it to update rx_dropped_misc. Fix that. This addresses https://bugzilla.kernel.org/show_bug.cgi?id=195953. Fixes: c9c5962b56c1 ("mac80211: enable collecting station statistics per-CPU") Reported-by: Petru-Florin Mihancea Signed-off-by: Johannes Berg --- net/mac80211/sta_info.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 7cdf7a835bb0..403e3cc58b57 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -2155,7 +2155,7 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) struct ieee80211_sta_rx_stats *cpurxs; cpurxs = per_cpu_ptr(sta->pcpu_rx_stats, cpu); - sinfo->rx_packets += cpurxs->dropped; + sinfo->rx_dropped_misc += cpurxs->dropped; } } -- cgit v1.2.3 From 5a27fec21b70c2c41efbfe30a0fbb0f005b9f7e5 Mon Sep 17 00:00:00 2001 From: Tatyana Nikolova Date: Fri, 5 May 2017 12:05:16 -0500 Subject: RDMA/i40iw: Don't set 0-length FULPDU RTR indication control flag Don't set control flag for 0-length FULPDU (Send) RTR indication in the enhanced MPA Request/Reply frames, because it isn't supported. Signed-off-by: Tatyana Nikolova Signed-off-by: Henry Orosco Signed-off-by: Doug Ledford --- drivers/infiniband/hw/i40iw/i40iw_cm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/infiniband/hw/i40iw/i40iw_cm.c b/drivers/infiniband/hw/i40iw/i40iw_cm.c index f3bc01bce483..e8e864fc1883 100644 --- a/drivers/infiniband/hw/i40iw/i40iw_cm.c +++ b/drivers/infiniband/hw/i40iw/i40iw_cm.c @@ -784,7 +784,6 @@ static void i40iw_build_mpa_v2(struct i40iw_cm_node *cm_node, } ctrl_ird |= IETF_PEER_TO_PEER; - ctrl_ird |= IETF_FLPDU_ZERO_LEN; switch (mpa_key) { case MPA_KEY_REQUEST: -- cgit v1.2.3 From b117f4796306a750ec1ffb928acc5f55bdb1fc7b Mon Sep 17 00:00:00 2001 From: Tatyana Nikolova Date: Fri, 5 May 2017 12:05:17 -0500 Subject: RDMA/i40iw: ACK MPA Reject frame Explicitly ACK the MPA Reject frame so the peer does not retransmit the frame. Signed-off-by: Tatyana Nikolova Signed-off-by: Henry Orosco Signed-off-by: Doug Ledford --- drivers/infiniband/hw/i40iw/i40iw_cm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/i40iw/i40iw_cm.c b/drivers/infiniband/hw/i40iw/i40iw_cm.c index e8e864fc1883..6ae98aa7f74e 100644 --- a/drivers/infiniband/hw/i40iw/i40iw_cm.c +++ b/drivers/infiniband/hw/i40iw/i40iw_cm.c @@ -2445,8 +2445,8 @@ static void i40iw_handle_rcv_mpa(struct i40iw_cm_node *cm_node, } else { type = I40IW_CM_EVENT_CONNECTED; cm_node->state = I40IW_CM_STATE_OFFLOADED; - i40iw_send_ack(cm_node); } + i40iw_send_ack(cm_node); break; default: pr_err("%s wrong cm_node state =%d\n", __func__, cm_node->state); -- cgit v1.2.3 From c0c643e16f9b00332cbbf3954556652dfa4ed5a3 Mon Sep 17 00:00:00 2001 From: Mustafa Ismail Date: Wed, 10 May 2017 23:32:14 -0500 Subject: RDMA/i40iw: Fix device initialization error path Some error paths in i40iw_initialize_dev are doing additional and unnecessary work before exiting. Correctly free resources allocated prior to error and return with correct status code. Signed-off-by: Mustafa Ismail Signed-off-by: Henry Orosco Signed-off-by: Doug Ledford --- drivers/infiniband/hw/i40iw/i40iw_main.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/infiniband/hw/i40iw/i40iw_main.c b/drivers/infiniband/hw/i40iw/i40iw_main.c index 2728af3103ce..a3f18a22f5ed 100644 --- a/drivers/infiniband/hw/i40iw/i40iw_main.c +++ b/drivers/infiniband/hw/i40iw/i40iw_main.c @@ -1319,13 +1319,13 @@ static enum i40iw_status_code i40iw_initialize_dev(struct i40iw_device *iwdev, status = i40iw_obj_aligned_mem(iwdev, &mem, I40IW_QUERY_FPM_BUF_SIZE, I40IW_FPM_QUERY_BUF_ALIGNMENT_MASK); if (status) - goto exit; + goto error; info.fpm_query_buf_pa = mem.pa; info.fpm_query_buf = mem.va; status = i40iw_obj_aligned_mem(iwdev, &mem, I40IW_COMMIT_FPM_BUF_SIZE, I40IW_FPM_COMMIT_BUF_ALIGNMENT_MASK); if (status) - goto exit; + goto error; info.fpm_commit_buf_pa = mem.pa; info.fpm_commit_buf = mem.va; info.hmc_fn_id = ldev->fid; @@ -1347,11 +1347,9 @@ static enum i40iw_status_code i40iw_initialize_dev(struct i40iw_device *iwdev, info.exception_lan_queue = 1; info.vchnl_send = i40iw_virtchnl_send; status = i40iw_device_init(&iwdev->sc_dev, &info); -exit: - if (status) { - kfree(iwdev->hmc_info_mem); - iwdev->hmc_info_mem = NULL; - } + + if (status) + goto error; memset(&vsi_info, 0, sizeof(vsi_info)); vsi_info.dev = &iwdev->sc_dev; vsi_info.back_vsi = (void *)iwdev; @@ -1362,11 +1360,19 @@ exit: memset(&stats_info, 0, sizeof(stats_info)); stats_info.fcn_id = ldev->fid; stats_info.pestat = kzalloc(sizeof(*stats_info.pestat), GFP_KERNEL); + if (!stats_info.pestat) { + status = I40IW_ERR_NO_MEMORY; + goto error; + } stats_info.stats_initialize = true; if (stats_info.pestat) i40iw_vsi_stats_init(&iwdev->vsi, &stats_info); } return status; +error: + kfree(iwdev->hmc_info_mem); + iwdev->hmc_info_mem = NULL; + return status; } /** -- cgit v1.2.3 From f300ba2d1ef1cb8411daa5e1ae44acfa7b88236c Mon Sep 17 00:00:00 2001 From: Shiraz Saleem Date: Fri, 19 May 2017 16:14:02 -0500 Subject: RDMA/i40iw: Remove MSS change support MSS change on active QPs is not supported. Store new MSS value for new QPs only. Remove code to modify MSS on the fly. This also resolves a crash on QP modify to QP 0. BUG: unable to handle kernel NULL pointer dereference at 0000000000000008 IP: i40iw_sc_qp_modify+0x22/0x280 [i40iw] Oops: 0000 [#1] SMP KASAN CPU: 2 PID: 1236 Comm: kworker/u16:4 Not tainted 4.12.0-rc1 #5 Hardware name: Gigabyte Technology Co., Ltd. To be filled by O.E.M./Q87M-D2H, BIOS F7 01/17/2014 Workqueue: l2params i40iw_l2params_worker [i40iw] task: ffff88070f5a9b40 task.stack: ffff88070f5a0000 RIP: 0010:i40iw_sc_qp_modify+0x22/0x280 [i40iw] ... Call Trace: i40iw_exec_cqp_cmd+0x2ce/0x410 [i40iw] ? _raw_spin_lock_irqsave+0x6f/0x80 ? i40iw_process_cqp_cmd+0x1d/0x80 [i40iw] i40iw_process_cqp_cmd+0x7c/0x80 [i40iw] i40iw_handle_cqp_op+0x2f/0x200 [i40iw] ? trace_hardirqs_off+0xd/0x10 ? _raw_spin_unlock_irqrestore+0x46/0x50 i40iw_hw_modify_qp+0x5e/0x90 [i40iw] i40iw_qp_mss_modify+0x52/0x60 [i40iw] i40iw_change_l2params+0x145/0x160 [i40iw] i40iw_l2params_worker+0x1f/0x40 [i40iw] process_one_work+0x1f5/0x650 ? process_one_work+0x161/0x650 worker_thread+0x48/0x3b0 kthread+0x112/0x150 ? process_one_work+0x650/0x650 ? kthread_create_on_node+0x40/0x40 ret_from_fork+0x2e/0x40 Code: 2e 0f 1f 84 00 00 00 00 00 55 48 89 e5 41 56 41 55 41 89 cd 41 54 49 89 fc 53 48 89 f3 48 89 d6 48 83 ec 08 48 8b 87 10 01 00 00 <48> 8b 40 08 4c 8b b0 40 04 00 00 4c 89 f7 e8 1b e5 ff ff 48 85 RIP: i40iw_sc_qp_modify+0x22/0x280 [i40iw] RSP: ffff88070f5a7c28 CR2: 0000000000000008 ---[ end trace 77a405931e296060 ]--- Reported-by: Stefan Assmann Signed-off-by: Shiraz Saleem Signed-off-by: Doug Ledford --- drivers/infiniband/hw/i40iw/i40iw_ctrl.c | 12 +----------- drivers/infiniband/hw/i40iw/i40iw_osdep.h | 1 - drivers/infiniband/hw/i40iw/i40iw_type.h | 2 -- drivers/infiniband/hw/i40iw/i40iw_utils.c | 17 ----------------- 4 files changed, 1 insertion(+), 31 deletions(-) diff --git a/drivers/infiniband/hw/i40iw/i40iw_ctrl.c b/drivers/infiniband/hw/i40iw/i40iw_ctrl.c index f82483b3d1e7..a027e2072477 100644 --- a/drivers/infiniband/hw/i40iw/i40iw_ctrl.c +++ b/drivers/infiniband/hw/i40iw/i40iw_ctrl.c @@ -285,28 +285,20 @@ void i40iw_change_l2params(struct i40iw_sc_vsi *vsi, struct i40iw_l2params *l2pa struct i40iw_sc_dev *dev = vsi->dev; struct i40iw_sc_qp *qp = NULL; bool qs_handle_change = false; - bool mss_change = false; unsigned long flags; u16 qs_handle; int i; - if (vsi->mss != l2params->mss) { - mss_change = true; - vsi->mss = l2params->mss; - } + vsi->mss = l2params->mss; i40iw_fill_qos_list(l2params->qs_handle_list); for (i = 0; i < I40IW_MAX_USER_PRIORITY; i++) { qs_handle = l2params->qs_handle_list[i]; if (vsi->qos[i].qs_handle != qs_handle) qs_handle_change = true; - else if (!mss_change) - continue; /* no MSS nor qs handle change */ spin_lock_irqsave(&vsi->qos[i].lock, flags); qp = i40iw_get_qp(&vsi->qos[i].qplist, qp); while (qp) { - if (mss_change) - i40iw_qp_mss_modify(dev, qp); if (qs_handle_change) { qp->qs_handle = qs_handle; /* issue cqp suspend command */ @@ -2395,7 +2387,6 @@ static enum i40iw_status_code i40iw_sc_qp_modify( set_64bit_val(wqe, 8, - LS_64(info->new_mss, I40IW_CQPSQ_QP_NEWMSS) | LS_64(term_len, I40IW_CQPSQ_QP_TERMLEN)); set_64bit_val(wqe, 16, qp->hw_host_ctx_pa); @@ -2410,7 +2401,6 @@ static enum i40iw_status_code i40iw_sc_qp_modify( LS_64(info->cq_num_valid, I40IW_CQPSQ_QP_CQNUMVALID) | LS_64(info->force_loopback, I40IW_CQPSQ_QP_FORCELOOPBACK) | LS_64(qp->qp_type, I40IW_CQPSQ_QP_QPTYPE) | - LS_64(info->mss_change, I40IW_CQPSQ_QP_MSSCHANGE) | LS_64(info->static_rsrc, I40IW_CQPSQ_QP_STATRSRC) | LS_64(info->remove_hash_idx, I40IW_CQPSQ_QP_REMOVEHASHENTRY) | LS_64(term_actions, I40IW_CQPSQ_QP_TERMACT) | diff --git a/drivers/infiniband/hw/i40iw/i40iw_osdep.h b/drivers/infiniband/hw/i40iw/i40iw_osdep.h index aa66c1c63dfa..f27be3e7830b 100644 --- a/drivers/infiniband/hw/i40iw/i40iw_osdep.h +++ b/drivers/infiniband/hw/i40iw/i40iw_osdep.h @@ -199,7 +199,6 @@ void i40iw_cqp_spawn_worker(struct i40iw_sc_dev *dev, struct i40iw_virtchnl_work_info *work_info, u32 iw_vf_idx); void *i40iw_remove_head(struct list_head *list); void i40iw_qp_suspend_resume(struct i40iw_sc_dev *dev, struct i40iw_sc_qp *qp, bool suspend); -void i40iw_qp_mss_modify(struct i40iw_sc_dev *dev, struct i40iw_sc_qp *qp); void i40iw_term_modify_qp(struct i40iw_sc_qp *qp, u8 next_state, u8 term, u8 term_len); void i40iw_terminate_done(struct i40iw_sc_qp *qp, int timeout_occurred); diff --git a/drivers/infiniband/hw/i40iw/i40iw_type.h b/drivers/infiniband/hw/i40iw/i40iw_type.h index 7b76259752b0..959ec81fba99 100644 --- a/drivers/infiniband/hw/i40iw/i40iw_type.h +++ b/drivers/infiniband/hw/i40iw/i40iw_type.h @@ -541,7 +541,6 @@ struct i40iw_create_qp_info { struct i40iw_modify_qp_info { u64 rx_win0; u64 rx_win1; - u16 new_mss; u8 next_iwarp_state; u8 termlen; bool ord_valid; @@ -554,7 +553,6 @@ struct i40iw_modify_qp_info { bool dont_send_term; bool dont_send_fin; bool cached_var_valid; - bool mss_change; bool force_loopback; }; diff --git a/drivers/infiniband/hw/i40iw/i40iw_utils.c b/drivers/infiniband/hw/i40iw/i40iw_utils.c index 409a3781e735..56d986924a4c 100644 --- a/drivers/infiniband/hw/i40iw/i40iw_utils.c +++ b/drivers/infiniband/hw/i40iw/i40iw_utils.c @@ -756,23 +756,6 @@ void i40iw_qp_suspend_resume(struct i40iw_sc_dev *dev, struct i40iw_sc_qp *qp, b i40iw_pr_err("CQP-OP QP Suspend/Resume fail"); } -/** - * i40iw_qp_mss_modify - modify mss for qp - * @dev: hardware control device structure - * @qp: hardware control qp - */ -void i40iw_qp_mss_modify(struct i40iw_sc_dev *dev, struct i40iw_sc_qp *qp) -{ - struct i40iw_device *iwdev = (struct i40iw_device *)dev->back_dev; - struct i40iw_qp *iwqp = (struct i40iw_qp *)qp->back_qp; - struct i40iw_modify_qp_info info; - - memset(&info, 0, sizeof(info)); - info.mss_change = true; - info.new_mss = qp->vsi->mss; - i40iw_hw_modify_qp(iwdev, iwqp, &info, false); -} - /** * i40iw_term_modify_qp - modify qp for term message * @qp: hardware control qp -- cgit v1.2.3 From e80bd98d1ff011beec872a8ebbb73930507d6a13 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 18 May 2017 13:11:17 -0500 Subject: RDMA/i40iw: fix duplicated code for different branches Refactor code to avoid identical code for different branches. Addresses-Coverity-ID: 1357356 Reviewed-by: Yuval Shaia Signed-off-by: Gustavo A. R. Silva Acked-by: Shiraz Saleem Signed-off-by: Doug Ledford --- drivers/infiniband/hw/i40iw/i40iw_virtchnl.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/infiniband/hw/i40iw/i40iw_virtchnl.c b/drivers/infiniband/hw/i40iw/i40iw_virtchnl.c index f4d13683a403..48fd327f876b 100644 --- a/drivers/infiniband/hw/i40iw/i40iw_virtchnl.c +++ b/drivers/infiniband/hw/i40iw/i40iw_virtchnl.c @@ -443,10 +443,7 @@ enum i40iw_status_code i40iw_vchnl_recv_pf(struct i40iw_sc_dev *dev, if (!dev->vchnl_up) return I40IW_ERR_NOT_READY; if (vchnl_msg->iw_op_code == I40IW_VCHNL_OP_GET_VER) { - if (vchnl_msg->iw_op_ver != I40IW_VCHNL_OP_GET_VER_V0) - vchnl_pf_send_get_ver_resp(dev, vf_id, vchnl_msg); - else - vchnl_pf_send_get_ver_resp(dev, vf_id, vchnl_msg); + vchnl_pf_send_get_ver_resp(dev, vf_id, vchnl_msg); return I40IW_SUCCESS; } for (iw_vf_idx = 0; iw_vf_idx < I40IW_MAX_PE_ENABLED_VF_COUNT; iw_vf_idx++) { -- cgit v1.2.3 From 0e5fc903513a652a2cf890a3d3b91c1779e16e97 Mon Sep 17 00:00:00 2001 From: Tatyana Nikolova Date: Wed, 10 May 2017 16:46:39 -0500 Subject: RDMA/nes: Don't set 0-length FULPDU RTR indication control flag Don't set control flag for 0-length FULPDU (Send) RTR indication in the enhanced MPA Request/Reply frames, because it isn't supported. Signed-off-by: Tatyana Nikolova Signed-off-by: Doug Ledford --- drivers/infiniband/hw/nes/nes_cm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c index fb983df7c157..06a55f6fb708 100644 --- a/drivers/infiniband/hw/nes/nes_cm.c +++ b/drivers/infiniband/hw/nes/nes_cm.c @@ -610,7 +610,6 @@ static void build_mpa_v2(struct nes_cm_node *cm_node, ctrl_ord = cm_node->ord_size & IETF_NO_IRD_ORD; } ctrl_ird |= IETF_PEER_TO_PEER; - ctrl_ird |= IETF_FLPDU_ZERO_LEN; switch (mpa_key) { case MPA_KEY_REQUEST: -- cgit v1.2.3 From f863de7de34025ee536cb3cc382bfc3cafaa9f0a Mon Sep 17 00:00:00 2001 From: Tatyana Nikolova Date: Wed, 10 May 2017 16:46:40 -0500 Subject: RDMA/nes: ACK MPA Reply frame Explicitly ACK the MPA Reply frame so the peer does not retransmit the frame. Signed-off-by: Tatyana Nikolova Signed-off-by: Doug Ledford --- drivers/infiniband/hw/nes/nes_cm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c index 06a55f6fb708..30b256a2c54e 100644 --- a/drivers/infiniband/hw/nes/nes_cm.c +++ b/drivers/infiniband/hw/nes/nes_cm.c @@ -1825,7 +1825,7 @@ static void handle_rcv_mpa(struct nes_cm_node *cm_node, struct sk_buff *skb) type = NES_CM_EVENT_CONNECTED; cm_node->state = NES_CM_STATE_TSA; } - + send_ack(cm_node, NULL); break; default: WARN_ON(1); -- cgit v1.2.3 From 1dad0ebeea1cd890b8892523f736916e245b0aef Mon Sep 17 00:00:00 2001 From: Raju Rangoju Date: Mon, 15 May 2017 06:40:39 +0000 Subject: RDMA/iw_cxgb4: Avoid touch after free error in ARP failure handlers The patch 761e19a504af (RDMA/iw_cxgb4: Handle return value of c4iw_ofld_send() in abort_arp_failure()) from May 6, 2016 leads to the following static checker warning: drivers/infiniband/hw/cxgb4/cm.c:575 abort_arp_failure() warn: passing freed memory 'skb' Also fixes skb leak when l2t resolution fails Fixes: 761e19a504afa55 (RDMA/iw_cxgb4: Handle return value of c4iw_ofld_send() in abort_arp_failure()) Reported-by: Dan Carpenter Cc: Dan Carpenter Signed-off-by: Raju Rangoju Reviewed-by: Steve Wise Signed-off-by: Doug Ledford --- drivers/infiniband/hw/cxgb4/cm.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c index b6fe45924c6e..06b110213e92 100644 --- a/drivers/infiniband/hw/cxgb4/cm.c +++ b/drivers/infiniband/hw/cxgb4/cm.c @@ -488,6 +488,7 @@ static int _put_ep_safe(struct c4iw_dev *dev, struct sk_buff *skb) ep = *((struct c4iw_ep **)(skb->cb + 2 * sizeof(void *))); release_ep_resources(ep); + kfree_skb(skb); return 0; } @@ -498,6 +499,7 @@ static int _put_pass_ep_safe(struct c4iw_dev *dev, struct sk_buff *skb) ep = *((struct c4iw_ep **)(skb->cb + 2 * sizeof(void *))); c4iw_put_ep(&ep->parent_ep->com); release_ep_resources(ep); + kfree_skb(skb); return 0; } @@ -569,11 +571,13 @@ static void abort_arp_failure(void *handle, struct sk_buff *skb) pr_debug("%s rdev %p\n", __func__, rdev); req->cmd = CPL_ABORT_NO_RST; + skb_get(skb); ret = c4iw_ofld_send(rdev, skb); if (ret) { __state_set(&ep->com, DEAD); queue_arp_failure_cpl(ep, skb, FAKE_CPL_PUT_EP_SAFE); - } + } else + kfree_skb(skb); } static int send_flowc(struct c4iw_ep *ep) -- cgit v1.2.3 From 4bbfabede50849f87b913a1fc07c02ecc96b6c57 Mon Sep 17 00:00:00 2001 From: Ganesh Goudar Date: Fri, 19 May 2017 14:48:42 +0530 Subject: RDMA/iw_cxgb4: calculate t4_eq_status_entries properly use egrstatuspagesize to calculate t4_eq_status_entries. Fixes: bb58d07964f2 ("cxgb4: Update IngPad and IngPack values") Reported-by: Logan Gunthorpe Signed-off-by: Potnuri Bharat Teja Signed-off-by: Ganesh Goudar Acked-by: Steve Wise Signed-off-by: Doug Ledford --- drivers/infiniband/hw/cxgb4/device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/cxgb4/device.c b/drivers/infiniband/hw/cxgb4/device.c index 329fb65e8fb0..f96a96dbcf1f 100644 --- a/drivers/infiniband/hw/cxgb4/device.c +++ b/drivers/infiniband/hw/cxgb4/device.c @@ -971,7 +971,7 @@ static struct c4iw_dev *c4iw_alloc(const struct cxgb4_lld_info *infop) devp->rdev.lldi.sge_egrstatuspagesize); devp->rdev.hw_queue.t4_eq_status_entries = - devp->rdev.lldi.sge_ingpadboundary > 64 ? 2 : 1; + devp->rdev.lldi.sge_egrstatuspagesize / 64; devp->rdev.hw_queue.t4_max_eq_size = 65520; devp->rdev.hw_queue.t4_max_iq_size = 65520; devp->rdev.hw_queue.t4_max_rq_size = 8192 - -- cgit v1.2.3 From 98b80a2a73a26f0e259632da519ccedb0cf37617 Mon Sep 17 00:00:00 2001 From: Raju Rangoju Date: Wed, 31 May 2017 12:06:58 +0530 Subject: RDMA/iw_cxgb4: fix the calculation of ipv6 header size Take care of ipv6 checks while computing header length for deducing mtu size of ipv6 servers. Due to the incorrect header length computation for ipv6 servers, wrong mss is reported to the peer (client). Signed-off-by: Raju Rangoju Signed-off-by: Ganesh Goudar Acked-by: Steve Wise Signed-off-by: Doug Ledford --- drivers/infiniband/hw/cxgb4/cm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c index 06b110213e92..0910faf3587b 100644 --- a/drivers/infiniband/hw/cxgb4/cm.c +++ b/drivers/infiniband/hw/cxgb4/cm.c @@ -2521,7 +2521,8 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb) goto reject; } - hdrs = sizeof(struct iphdr) + sizeof(struct tcphdr) + + hdrs = ((iptype == 4) ? sizeof(struct iphdr) : sizeof(struct ipv6hdr)) + + sizeof(struct tcphdr) + ((enable_tcp_timestamps && req->tcpopt.tstamp) ? 12 : 0); if (peer_mss && child_ep->mtu > (peer_mss + hdrs)) child_ep->mtu = peer_mss + hdrs; -- cgit v1.2.3 From c4dd4b69f55abcc8dd079f8de55d9d8c2ddbefce Mon Sep 17 00:00:00 2001 From: "Steven L. Roberts" Date: Wed, 10 May 2017 10:54:12 -0500 Subject: RDMA/hfi1: fix array termination by appending NULL to attr array This fixes a kernel panic when loading the hfi driver as a dynamic module. Signed-off-by: Steven L Roberts Reviewed-by: Leon Romanovsky Acked-by: Dennis Dalessandro Signed-off-by: Doug Ledford --- drivers/infiniband/hw/hfi1/sysfs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/hfi1/sysfs.c b/drivers/infiniband/hw/hfi1/sysfs.c index 50d140d25e38..2f3bbcac1e34 100644 --- a/drivers/infiniband/hw/hfi1/sysfs.c +++ b/drivers/infiniband/hw/hfi1/sysfs.c @@ -196,7 +196,8 @@ static const struct sysfs_ops port_cc_sysfs_ops = { }; static struct attribute *port_cc_default_attributes[] = { - &cc_prescan_attr.attr + &cc_prescan_attr.attr, + NULL }; static struct kobj_type port_cc_ktype = { -- cgit v1.2.3 From e4785b0633574a607daaa04bf2fe43550055194f Mon Sep 17 00:00:00 2001 From: "Steven L. Roberts" Date: Wed, 10 May 2017 14:58:13 -0500 Subject: RDMA/hfi1: change PCI bar addr assignments to Linux API functions The Omni-Path adapter driver fails to load on the ppc64le platform due to invalid PCI setup. This patch makes the PCI configuration more robust and will fix 64 bit addressing for ppc64le. Signed-off-by: Steven L Roberts Acked-by: Dennis Dalessandro Signed-off-by: Doug Ledford --- drivers/infiniband/hw/hfi1/pcie.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/infiniband/hw/hfi1/pcie.c b/drivers/infiniband/hw/hfi1/pcie.c index 93faf86d54b6..6a9f6f9819e1 100644 --- a/drivers/infiniband/hw/hfi1/pcie.c +++ b/drivers/infiniband/hw/hfi1/pcie.c @@ -207,8 +207,8 @@ int hfi1_pcie_ddinit(struct hfi1_devdata *dd, struct pci_dev *pdev) /* * Save BARs and command to rewrite after device reset. */ - dd->pcibar0 = addr; - dd->pcibar1 = addr >> 32; + pci_read_config_dword(dd->pcidev, PCI_BASE_ADDRESS_0, &dd->pcibar0); + pci_read_config_dword(dd->pcidev, PCI_BASE_ADDRESS_1, &dd->pcibar1); pci_read_config_dword(dd->pcidev, PCI_ROM_ADDRESS, &dd->pci_rom); pci_read_config_word(dd->pcidev, PCI_COMMAND, &dd->pci_command); pcie_capability_read_word(dd->pcidev, PCI_EXP_DEVCTL, &dd->pcie_devctl); -- cgit v1.2.3 From b3e6b4bdbb609762d8401ac4a959d590b4e4e3b8 Mon Sep 17 00:00:00 2001 From: "Byczkowski, Jakub" Date: Fri, 12 May 2017 09:01:37 -0700 Subject: RDMA/hfi1: Defer setting VL15 credits to link-up interrupt Keep VL15 credits at 0 during LNI, before link-up. Store VL15 credits value during verify cap interrupt and set in after link-up. This addresses an issue where VL15 MAD packets could be sent by one side of the link before the other side is ready to receive them. Reviewed-by: Mike Marciniszyn Reviewed-by: Dean Luick Reviewed-by: Dennis Dalessandro Signed-off-by: Jakub Byczkowski Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford --- drivers/infiniband/hw/hfi1/chip.c | 67 +++++++++++++++++++++-------- drivers/infiniband/hw/hfi1/chip_registers.h | 2 + drivers/infiniband/hw/hfi1/hfi.h | 11 ++++- drivers/infiniband/hw/hfi1/intr.c | 3 +- 4 files changed, 64 insertions(+), 19 deletions(-) diff --git a/drivers/infiniband/hw/hfi1/chip.c b/drivers/infiniband/hw/hfi1/chip.c index 5d6b1eeaa9a0..2ba00b89df6a 100644 --- a/drivers/infiniband/hw/hfi1/chip.c +++ b/drivers/infiniband/hw/hfi1/chip.c @@ -6312,25 +6312,38 @@ static void handle_8051_request(struct hfi1_pportdata *ppd) } } -static void write_global_credit(struct hfi1_devdata *dd, - u8 vau, u16 total, u16 shared) +/* + * Set up allocation unit vaulue. + */ +void set_up_vau(struct hfi1_devdata *dd, u8 vau) { - write_csr(dd, SEND_CM_GLOBAL_CREDIT, - ((u64)total << - SEND_CM_GLOBAL_CREDIT_TOTAL_CREDIT_LIMIT_SHIFT) | - ((u64)shared << - SEND_CM_GLOBAL_CREDIT_SHARED_LIMIT_SHIFT) | - ((u64)vau << SEND_CM_GLOBAL_CREDIT_AU_SHIFT)); + u64 reg = read_csr(dd, SEND_CM_GLOBAL_CREDIT); + + /* do not modify other values in the register */ + reg &= ~SEND_CM_GLOBAL_CREDIT_AU_SMASK; + reg |= (u64)vau << SEND_CM_GLOBAL_CREDIT_AU_SHIFT; + write_csr(dd, SEND_CM_GLOBAL_CREDIT, reg); } /* * Set up initial VL15 credits of the remote. Assumes the rest of - * the CM credit registers are zero from a previous global or credit reset . + * the CM credit registers are zero from a previous global or credit reset. + * Shared limit for VL15 will always be 0. */ -void set_up_vl15(struct hfi1_devdata *dd, u8 vau, u16 vl15buf) +void set_up_vl15(struct hfi1_devdata *dd, u16 vl15buf) { - /* leave shared count at zero for both global and VL15 */ - write_global_credit(dd, vau, vl15buf, 0); + u64 reg = read_csr(dd, SEND_CM_GLOBAL_CREDIT); + + /* set initial values for total and shared credit limit */ + reg &= ~(SEND_CM_GLOBAL_CREDIT_TOTAL_CREDIT_LIMIT_SMASK | + SEND_CM_GLOBAL_CREDIT_SHARED_LIMIT_SMASK); + + /* + * Set total limit to be equal to VL15 credits. + * Leave shared limit at 0. + */ + reg |= (u64)vl15buf << SEND_CM_GLOBAL_CREDIT_TOTAL_CREDIT_LIMIT_SHIFT; + write_csr(dd, SEND_CM_GLOBAL_CREDIT, reg); write_csr(dd, SEND_CM_CREDIT_VL15, (u64)vl15buf << SEND_CM_CREDIT_VL15_DEDICATED_LIMIT_VL_SHIFT); @@ -6348,9 +6361,11 @@ void reset_link_credits(struct hfi1_devdata *dd) for (i = 0; i < TXE_NUM_DATA_VL; i++) write_csr(dd, SEND_CM_CREDIT_VL + (8 * i), 0); write_csr(dd, SEND_CM_CREDIT_VL15, 0); - write_global_credit(dd, 0, 0, 0); + write_csr(dd, SEND_CM_GLOBAL_CREDIT, 0); /* reset the CM block */ pio_send_control(dd, PSC_CM_RESET); + /* reset cached value */ + dd->vl15buf_cached = 0; } /* convert a vCU to a CU */ @@ -6839,24 +6854,35 @@ void handle_link_up(struct work_struct *work) { struct hfi1_pportdata *ppd = container_of(work, struct hfi1_pportdata, link_up_work); + struct hfi1_devdata *dd = ppd->dd; + set_link_state(ppd, HLS_UP_INIT); /* cache the read of DC_LCB_STS_ROUND_TRIP_LTP_CNT */ - read_ltp_rtt(ppd->dd); + read_ltp_rtt(dd); /* * OPA specifies that certain counters are cleared on a transition * to link up, so do that. */ - clear_linkup_counters(ppd->dd); + clear_linkup_counters(dd); /* * And (re)set link up default values. */ set_linkup_defaults(ppd); + /* + * Set VL15 credits. Use cached value from verify cap interrupt. + * In case of quick linkup or simulator, vl15 value will be set by + * handle_linkup_change. VerifyCap interrupt handler will not be + * called in those scenarios. + */ + if (!(quick_linkup || dd->icode == ICODE_FUNCTIONAL_SIMULATOR)) + set_up_vl15(dd, dd->vl15buf_cached); + /* enforce link speed enabled */ if ((ppd->link_speed_active & ppd->link_speed_enabled) == 0) { /* oops - current speed is not enabled, bounce */ - dd_dev_err(ppd->dd, + dd_dev_err(dd, "Link speed active 0x%x is outside enabled 0x%x, downing link\n", ppd->link_speed_active, ppd->link_speed_enabled); set_link_down_reason(ppd, OPA_LINKDOWN_REASON_SPEED_POLICY, 0, @@ -7357,7 +7383,14 @@ void handle_verify_cap(struct work_struct *work) */ if (vau == 0) vau = 1; - set_up_vl15(dd, vau, vl15buf); + set_up_vau(dd, vau); + + /* + * Set VL15 credits to 0 in global credit register. Cache remote VL15 + * credits value and wait for link-up interrupt ot set it. + */ + set_up_vl15(dd, 0); + dd->vl15buf_cached = vl15buf; /* set up the LCB CRC mode */ crc_mask = ppd->port_crc_mode_enabled & partner_supported_crc; diff --git a/drivers/infiniband/hw/hfi1/chip_registers.h b/drivers/infiniband/hw/hfi1/chip_registers.h index 5bfa839d1c48..793514f1d15f 100644 --- a/drivers/infiniband/hw/hfi1/chip_registers.h +++ b/drivers/infiniband/hw/hfi1/chip_registers.h @@ -839,7 +839,9 @@ #define SEND_CM_CTRL_FORCE_CREDIT_MODE_SMASK 0x8ull #define SEND_CM_CTRL_RESETCSR 0x0000000000000020ull #define SEND_CM_GLOBAL_CREDIT (TXE + 0x000000000508) +#define SEND_CM_GLOBAL_CREDIT_AU_MASK 0x7ull #define SEND_CM_GLOBAL_CREDIT_AU_SHIFT 16 +#define SEND_CM_GLOBAL_CREDIT_AU_SMASK 0x70000ull #define SEND_CM_GLOBAL_CREDIT_RESETCSR 0x0000094000030000ull #define SEND_CM_GLOBAL_CREDIT_SHARED_LIMIT_MASK 0xFFFFull #define SEND_CM_GLOBAL_CREDIT_SHARED_LIMIT_SHIFT 0 diff --git a/drivers/infiniband/hw/hfi1/hfi.h b/drivers/infiniband/hw/hfi1/hfi.h index da322e6668cc..414a04a481c2 100644 --- a/drivers/infiniband/hw/hfi1/hfi.h +++ b/drivers/infiniband/hw/hfi1/hfi.h @@ -1045,6 +1045,14 @@ struct hfi1_devdata { /* initial vl15 credits to use */ u16 vl15_init; + /* + * Cached value for vl15buf, read during verify cap interrupt. VL15 + * credits are to be kept at 0 and set when handling the link-up + * interrupt. This removes the possibility of receiving VL15 MAD + * packets before this HFI is ready. + */ + u16 vl15buf_cached; + /* Misc small ints */ u8 n_krcv_queues; u8 qos_shift; @@ -1598,7 +1606,8 @@ int hfi1_rcvbuf_validate(u32 size, u8 type, u16 *encode); int fm_get_table(struct hfi1_pportdata *ppd, int which, void *t); int fm_set_table(struct hfi1_pportdata *ppd, int which, void *t); -void set_up_vl15(struct hfi1_devdata *dd, u8 vau, u16 vl15buf); +void set_up_vau(struct hfi1_devdata *dd, u8 vau); +void set_up_vl15(struct hfi1_devdata *dd, u16 vl15buf); void reset_link_credits(struct hfi1_devdata *dd); void assign_remote_cm_au_table(struct hfi1_devdata *dd, u8 vcu); diff --git a/drivers/infiniband/hw/hfi1/intr.c b/drivers/infiniband/hw/hfi1/intr.c index ba265d0ae93b..04a5082d5ac5 100644 --- a/drivers/infiniband/hw/hfi1/intr.c +++ b/drivers/infiniband/hw/hfi1/intr.c @@ -130,7 +130,8 @@ void handle_linkup_change(struct hfi1_devdata *dd, u32 linkup) * the remote values. Both sides must be using the values. */ if (quick_linkup || dd->icode == ICODE_FUNCTIONAL_SIMULATOR) { - set_up_vl15(dd, dd->vau, dd->vl15_init); + set_up_vau(dd, dd->vau); + set_up_vl15(dd, dd->vl15_init); assign_remote_cm_au_table(dd, dd->vcu); } -- cgit v1.2.3 From 1feb40067cf04ae48d65f728d62ca255c9449178 Mon Sep 17 00:00:00 2001 From: Mike Marciniszyn Date: Fri, 12 May 2017 09:02:00 -0700 Subject: RDMA/qib,hfi1: Fix MR reference count leak on write with immediate The handling of IB_RDMA_WRITE_ONLY_WITH_IMMEDIATE will leak a memory reference when a buffer cannot be allocated for returning the immediate data. The issue is that the rkey validation has already occurred and the RNR nak fails to release the reference that was fruitlessly gotten. The the peer will send the identical single packet request when its RNR timer pops. The fix is to release the held reference prior to the rnr nak exit. This is the only sequence the requires both rkey validation and the buffer allocation on the same packet. Cc: Stable # 4.7+ Tested-by: Tadeusz Struk Reviewed-by: Dennis Dalessandro Signed-off-by: Mike Marciniszyn Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford --- drivers/infiniband/hw/hfi1/rc.c | 5 ++++- drivers/infiniband/hw/qib/qib_rc.c | 4 +++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/infiniband/hw/hfi1/rc.c b/drivers/infiniband/hw/hfi1/rc.c index 069bdaf061ab..1080778a1f7c 100644 --- a/drivers/infiniband/hw/hfi1/rc.c +++ b/drivers/infiniband/hw/hfi1/rc.c @@ -2159,8 +2159,11 @@ send_last: ret = hfi1_rvt_get_rwqe(qp, 1); if (ret < 0) goto nack_op_err; - if (!ret) + if (!ret) { + /* peer will send again */ + rvt_put_ss(&qp->r_sge); goto rnr_nak; + } wc.ex.imm_data = ohdr->u.rc.imm_data; wc.wc_flags = IB_WC_WITH_IMM; goto send_last; diff --git a/drivers/infiniband/hw/qib/qib_rc.c b/drivers/infiniband/hw/qib/qib_rc.c index fc8b88514da5..4ddbcac5eabe 100644 --- a/drivers/infiniband/hw/qib/qib_rc.c +++ b/drivers/infiniband/hw/qib/qib_rc.c @@ -1956,8 +1956,10 @@ send_last: ret = qib_get_rwqe(qp, 1); if (ret < 0) goto nack_op_err; - if (!ret) + if (!ret) { + rvt_put_ss(&qp->r_sge); goto rnr_nak; + } wc.ex.imm_data = ohdr->u.rc.imm_data; hdrsize += 4; wc.wc_flags = IB_WC_WITH_IMM; -- cgit v1.2.3 From eed7624552ca55c346a4e9ccaa9ab0723841aee6 Mon Sep 17 00:00:00 2001 From: Jack Morgenstein Date: Sun, 21 May 2017 19:11:13 +0300 Subject: RDMA/mlx4: Fix MAD tunneling when SRIOV is enabled The cited patch added a type field to structures ib_ah and rdma_ah_attr. Function mlx4_ib_query_ah() builds an rdma_ah_attr structure from the data in an mlx4_ib_ah structure (which contains both an ib_ah structure and an address vector). For mlx4_ib_query_ah() to work properly, the type field in the contained ib_ah structure must be set correctly. In the outgoing MAD tunneling flow, procedure mlx4_ib_multiplex_mad() paravirtualizes a MAD received from a slave and sends the processed mad out over the wire. During this processing, it populates an mlx4_ib_ah structure and calls mlx4_ib_query_ah(). The cited commit overlooked setting the type field in the contained ib_ah structure before invoking mlx4_ib_query_ah(). As a result, the type field remained uninitialized, and the rdma_ah_attr structure was incorrectly built. This resulted in improperly built MADs being sent out over the wire. This patch properly initializes the type field in the contained ib_ah structure before calling mlx4_ib_query_ah(). The rdma_ah_attr structure is then generated correctly. Fixes: 44c58487d51a ("IB/core: Define 'ib' and 'roce' rdma_ah_attr types") Signed-off-by: Jack Morgenstein Signed-off-by: Leon Romanovsky Signed-off-by: Doug Ledford --- drivers/infiniband/hw/mlx4/mad.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c index b4694717f6f3..21d31cb1325f 100644 --- a/drivers/infiniband/hw/mlx4/mad.c +++ b/drivers/infiniband/hw/mlx4/mad.c @@ -1578,6 +1578,7 @@ static void mlx4_ib_multiplex_mad(struct mlx4_ib_demux_pv_ctx *ctx, struct ib_wc if (port < 0) return; ah.av.ib.port_pd = cpu_to_be32(port << 24 | (be32_to_cpu(ah.av.ib.port_pd) & 0xffffff)); + ah.ibah.type = rdma_ah_find_type(&dev->ib_dev, port); mlx4_ib_query_ah(&ah.ibah, &ah_attr); if (rdma_ah_get_ah_flags(&ah_attr) & IB_AH_GRH) -- cgit v1.2.3 From 1410a90ae449061b7e1ae19d275148f36948801b Mon Sep 17 00:00:00 2001 From: Max Gurtovoy Date: Sun, 28 May 2017 10:53:10 +0300 Subject: net/mlx5: Define interface bits for fencing UMR wqe HW can implement UMR wqe re-transmission in various ways. Thus, add HCA cap to distinguish the needed fence for UMR to make sure that the wqe wouldn't fail on mkey checks. Signed-off-by: Max Gurtovoy Acked-by: Leon Romanovsky Reviewed-by: Christoph Hellwig Signed-off-by: Doug Ledford --- include/linux/mlx5/mlx5_ifc.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h index 32de0724b400..edafedb7b509 100644 --- a/include/linux/mlx5/mlx5_ifc.h +++ b/include/linux/mlx5/mlx5_ifc.h @@ -766,6 +766,12 @@ enum { MLX5_CAP_PORT_TYPE_ETH = 0x1, }; +enum { + MLX5_CAP_UMR_FENCE_STRONG = 0x0, + MLX5_CAP_UMR_FENCE_SMALL = 0x1, + MLX5_CAP_UMR_FENCE_NONE = 0x2, +}; + struct mlx5_ifc_cmd_hca_cap_bits { u8 reserved_at_0[0x80]; @@ -875,7 +881,9 @@ struct mlx5_ifc_cmd_hca_cap_bits { u8 reserved_at_202[0x1]; u8 ipoib_enhanced_offloads[0x1]; u8 ipoib_basic_offloads[0x1]; - u8 reserved_at_205[0xa]; + u8 reserved_at_205[0x5]; + u8 umr_fence[0x2]; + u8 reserved_at_20c[0x3]; u8 drain_sigerr[0x1]; u8 cmdif_checksum[0x2]; u8 sigerr_cqe[0x1]; -- cgit v1.2.3 From 6e8484c5cf07c7ee632587e98c1a12d319dacb7c Mon Sep 17 00:00:00 2001 From: Max Gurtovoy Date: Sun, 28 May 2017 10:53:11 +0300 Subject: RDMA/mlx5: set UMR wqe fence according to HCA cap Cache the needed umr_fence and set the wqe ctrl segmennt accordingly. Signed-off-by: Max Gurtovoy Acked-by: Leon Romanovsky Reviewed-by: Sagi Grimberg Signed-off-by: Doug Ledford --- drivers/infiniband/hw/mlx5/main.c | 14 +++++++++ drivers/infiniband/hw/mlx5/mlx5_ib.h | 3 +- drivers/infiniband/hw/mlx5/qp.c | 59 ++++++++++++++---------------------- 3 files changed, 39 insertions(+), 37 deletions(-) diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c index d45772da0963..0c79983c8b1a 100644 --- a/drivers/infiniband/hw/mlx5/main.c +++ b/drivers/infiniband/hw/mlx5/main.c @@ -2979,6 +2979,18 @@ error_0: return ret; } +static u8 mlx5_get_umr_fence(u8 umr_fence_cap) +{ + switch (umr_fence_cap) { + case MLX5_CAP_UMR_FENCE_NONE: + return MLX5_FENCE_MODE_NONE; + case MLX5_CAP_UMR_FENCE_SMALL: + return MLX5_FENCE_MODE_INITIATOR_SMALL; + default: + return MLX5_FENCE_MODE_STRONG_ORDERING; + } +} + static int create_dev_resources(struct mlx5_ib_resources *devr) { struct ib_srq_init_attr attr; @@ -3693,6 +3705,8 @@ static void *mlx5_ib_add(struct mlx5_core_dev *mdev) mlx5_ib_internal_fill_odp_caps(dev); + dev->umr_fence = mlx5_get_umr_fence(MLX5_CAP_GEN(mdev, umr_fence)); + if (MLX5_CAP_GEN(mdev, imaicl)) { dev->ib_dev.alloc_mw = mlx5_ib_alloc_mw; dev->ib_dev.dealloc_mw = mlx5_ib_dealloc_mw; diff --git a/drivers/infiniband/hw/mlx5/mlx5_ib.h b/drivers/infiniband/hw/mlx5/mlx5_ib.h index 38c877bc45e5..bdcf25410c99 100644 --- a/drivers/infiniband/hw/mlx5/mlx5_ib.h +++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h @@ -349,7 +349,7 @@ struct mlx5_ib_qp { struct mlx5_ib_wq rq; u8 sq_signal_bits; - u8 fm_cache; + u8 next_fence; struct mlx5_ib_wq sq; /* serialize qp state modifications @@ -654,6 +654,7 @@ struct mlx5_ib_dev { struct mlx5_ib_port *port; struct mlx5_sq_bfreg bfreg; struct mlx5_sq_bfreg fp_bfreg; + u8 umr_fence; }; static inline struct mlx5_ib_cq *to_mibcq(struct mlx5_core_cq *mcq) diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c index 93959e1e43a3..ebb6768684de 100644 --- a/drivers/infiniband/hw/mlx5/qp.c +++ b/drivers/infiniband/hw/mlx5/qp.c @@ -3738,24 +3738,6 @@ static void dump_wqe(struct mlx5_ib_qp *qp, int idx, int size_16) } } -static u8 get_fence(u8 fence, struct ib_send_wr *wr) -{ - if (unlikely(wr->opcode == IB_WR_LOCAL_INV && - wr->send_flags & IB_SEND_FENCE)) - return MLX5_FENCE_MODE_STRONG_ORDERING; - - if (unlikely(fence)) { - if (wr->send_flags & IB_SEND_FENCE) - return MLX5_FENCE_MODE_SMALL_AND_FENCE; - else - return fence; - } else if (unlikely(wr->send_flags & IB_SEND_FENCE)) { - return MLX5_FENCE_MODE_FENCE; - } - - return 0; -} - static int begin_wqe(struct mlx5_ib_qp *qp, void **seg, struct mlx5_wqe_ctrl_seg **ctrl, struct ib_send_wr *wr, unsigned *idx, @@ -3784,8 +3766,7 @@ static int begin_wqe(struct mlx5_ib_qp *qp, void **seg, static void finish_wqe(struct mlx5_ib_qp *qp, struct mlx5_wqe_ctrl_seg *ctrl, u8 size, unsigned idx, u64 wr_id, - int nreq, u8 fence, u8 next_fence, - u32 mlx5_opcode) + int nreq, u8 fence, u32 mlx5_opcode) { u8 opmod = 0; @@ -3793,7 +3774,6 @@ static void finish_wqe(struct mlx5_ib_qp *qp, mlx5_opcode | ((u32)opmod << 24)); ctrl->qpn_ds = cpu_to_be32(size | (qp->trans_qp.base.mqp.qpn << 8)); ctrl->fm_ce_se |= fence; - qp->fm_cache = next_fence; if (unlikely(qp->wq_sig)) ctrl->signature = wq_sig(ctrl); @@ -3853,7 +3833,6 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, goto out; } - fence = qp->fm_cache; num_sge = wr->num_sge; if (unlikely(num_sge > qp->sq.max_gs)) { mlx5_ib_warn(dev, "\n"); @@ -3870,6 +3849,19 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, goto out; } + if (wr->opcode == IB_WR_LOCAL_INV || + wr->opcode == IB_WR_REG_MR) { + fence = dev->umr_fence; + next_fence = MLX5_FENCE_MODE_INITIATOR_SMALL; + } else if (wr->send_flags & IB_SEND_FENCE) { + if (qp->next_fence) + fence = MLX5_FENCE_MODE_SMALL_AND_FENCE; + else + fence = MLX5_FENCE_MODE_FENCE; + } else { + fence = qp->next_fence; + } + switch (ibqp->qp_type) { case IB_QPT_XRC_INI: xrc = seg; @@ -3896,7 +3888,6 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, goto out; case IB_WR_LOCAL_INV: - next_fence = MLX5_FENCE_MODE_INITIATOR_SMALL; qp->sq.wr_data[idx] = IB_WR_LOCAL_INV; ctrl->imm = cpu_to_be32(wr->ex.invalidate_rkey); set_linv_wr(qp, &seg, &size); @@ -3904,7 +3895,6 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, break; case IB_WR_REG_MR: - next_fence = MLX5_FENCE_MODE_INITIATOR_SMALL; qp->sq.wr_data[idx] = IB_WR_REG_MR; ctrl->imm = cpu_to_be32(reg_wr(wr)->key); err = set_reg_wr(qp, reg_wr(wr), &seg, &size); @@ -3927,9 +3917,8 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, goto out; } - finish_wqe(qp, ctrl, size, idx, wr->wr_id, - nreq, get_fence(fence, wr), - next_fence, MLX5_OPCODE_UMR); + finish_wqe(qp, ctrl, size, idx, wr->wr_id, nreq, + fence, MLX5_OPCODE_UMR); /* * SET_PSV WQEs are not signaled and solicited * on error @@ -3954,9 +3943,8 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, goto out; } - finish_wqe(qp, ctrl, size, idx, wr->wr_id, - nreq, get_fence(fence, wr), - next_fence, MLX5_OPCODE_SET_PSV); + finish_wqe(qp, ctrl, size, idx, wr->wr_id, nreq, + fence, MLX5_OPCODE_SET_PSV); err = begin_wqe(qp, &seg, &ctrl, wr, &idx, &size, nreq); if (err) { @@ -3966,7 +3954,6 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, goto out; } - next_fence = MLX5_FENCE_MODE_INITIATOR_SMALL; err = set_psv_wr(&sig_handover_wr(wr)->sig_attrs->wire, mr->sig->psv_wire.psv_idx, &seg, &size); @@ -3976,9 +3963,9 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, goto out; } - finish_wqe(qp, ctrl, size, idx, wr->wr_id, - nreq, get_fence(fence, wr), - next_fence, MLX5_OPCODE_SET_PSV); + finish_wqe(qp, ctrl, size, idx, wr->wr_id, nreq, + fence, MLX5_OPCODE_SET_PSV); + qp->next_fence = MLX5_FENCE_MODE_INITIATOR_SMALL; num_sge = 0; goto skip_psv; @@ -4089,8 +4076,8 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, } } - finish_wqe(qp, ctrl, size, idx, wr->wr_id, nreq, - get_fence(fence, wr), next_fence, + qp->next_fence = next_fence; + finish_wqe(qp, ctrl, size, idx, wr->wr_id, nreq, fence, mlx5_ib_opcode[wr->opcode]); skip_psv: if (0) -- cgit v1.2.3 From d38d7fdafaf89d1756f27e9b4054dd19a1d2f545 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Mon, 22 May 2017 13:30:15 -0500 Subject: RDMA/qedr: add null check before pointer dereference Add null check before dereferencing pointer sgid_attr.ndev inside function rdma_vlan_dev_vlan_id(). Addresses-Coverity-ID: 1373979 Signed-off-by: Gustavo A. R. Silva Acked-by: Ram Amrani Signed-off-by: Doug Ledford --- drivers/infiniband/hw/qedr/qedr_cm.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/infiniband/hw/qedr/qedr_cm.c b/drivers/infiniband/hw/qedr/qedr_cm.c index 3d7705cec770..d86dbe814d98 100644 --- a/drivers/infiniband/hw/qedr/qedr_cm.c +++ b/drivers/infiniband/hw/qedr/qedr_cm.c @@ -270,11 +270,13 @@ static inline int qedr_gsi_build_header(struct qedr_dev *dev, return rc; } - vlan_id = rdma_vlan_dev_vlan_id(sgid_attr.ndev); - if (vlan_id < VLAN_CFI_MASK) - has_vlan = true; - if (sgid_attr.ndev) + if (sgid_attr.ndev) { + vlan_id = rdma_vlan_dev_vlan_id(sgid_attr.ndev); + if (vlan_id < VLAN_CFI_MASK) + has_vlan = true; + dev_put(sgid_attr.ndev); + } if (!memcmp(&sgid, &zgid, sizeof(sgid))) { DP_ERR(dev, "gsi post send: GID not found GID index %d\n", -- cgit v1.2.3 From 8c490669deb0133dfb6bfe7a80d7cfef3bbbd92f Mon Sep 17 00:00:00 2001 From: Honggang Li Date: Thu, 11 May 2017 20:14:28 +0800 Subject: RDMA/IPoIB: Replace netdev_priv with ipoib_priv for ipoib_get_link_ksettings ipoib_dev_init accesses the wrong private data for the IPoIB device. Commit cd565b4b51e5 (IB/IPoIB: Support acceleration options callbacks) changed ipoib_priv from being identical to netdev_priv to being an area inside of, but not the same pointer as, the netdev_priv pointer. As such, the struct we want is the ipoib_priv area, not the netdev_priv area, so use the right accessor, otherwise we kernel panic. [ 27.271938] IPv6: ADDRCONF(NETDEV_CHANGE): mlx5_ib0.8006: link becomes ready [ 28.156790] BUG: unable to handle kernel NULL pointer dereference at 000000000000067c [ 28.166309] IP: ib_query_port+0x30/0x180 [ib_core] ... [ 28.306282] RIP: 0010:ib_query_port+0x30/0x180 [ib_core] ... [ 28.393337] Call Trace: [ 28.397594] ipoib_get_link_ksettings+0x66/0xe0 [ib_ipoib] [ 28.405274] __ethtool_get_link_ksettings+0xa0/0x1c0 [ 28.412353] speed_show+0x74/0xa0 [ 28.417503] dev_attr_show+0x20/0x50 [ 28.422922] ? mutex_lock+0x12/0x40 [ 28.428179] sysfs_kf_seq_show+0xbf/0x1a0 [ 28.434002] kernfs_seq_show+0x21/0x30 [ 28.439470] seq_read+0x116/0x3b0 [ 28.444445] ? do_filp_open+0xa5/0x100 [ 28.449774] kernfs_fop_read+0xff/0x180 [ 28.455220] __vfs_read+0x37/0x150 [ 28.460167] ? security_file_permission+0x9d/0xc0 [ 28.466560] vfs_read+0x8c/0x130 [ 28.471318] SyS_read+0x55/0xc0 [ 28.475950] do_syscall_64+0x67/0x150 [ 28.481163] entry_SYSCALL64_slow_path+0x25/0x25 ... [ 28.584493] ---[ end trace 3549968a4bf0aa5d ]--- Fixes: cd565b4b51e5 (IB/IPoIB: Support acceleration options callbacks) Fixes: 0d7e2d2166f6 (IB/ipoib: add get_link_ksettings in ethtool) Signed-off-by: Honggang Li Reviewed-by: Yuval Shaia Reviewed-by: Leon Romanovsky Signed-off-by: Doug Ledford --- drivers/infiniband/ulp/ipoib/ipoib_ethtool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c b/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c index 874b24366e4d..7871379342f4 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c @@ -178,7 +178,7 @@ static inline int ib_speed_enum_to_int(int speed) static int ipoib_get_link_ksettings(struct net_device *netdev, struct ethtool_link_ksettings *cmd) { - struct ipoib_dev_priv *priv = netdev_priv(netdev); + struct ipoib_dev_priv *priv = ipoib_priv(netdev); struct ib_port_attr attr; int ret, speed, width; -- cgit v1.2.3 From 0a1a972630c77edb39adf310699e404b8bf9176e Mon Sep 17 00:00:00 2001 From: Leon Romanovsky Date: Sun, 14 May 2017 13:32:06 +0300 Subject: RDMA/IPoIB: Limit the ipoib_dev_uninit_default scope ipoib_dev_uninit_default() call is used in ipoib_main.c file only and it generates the following warning from smatch tool: drivers/infiniband/ulp/ipoib/ipoib_main.c:1593:6: warning: symbol 'ipoib_dev_uninit_default' was not declared. Should it be static? so let's declare that function as static. Signed-off-by: Leon Romanovsky Reviewed-by: Yuval Shaia Signed-off-by: Doug Ledford --- drivers/infiniband/ulp/ipoib/ipoib_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 2869d1adb1de..a115c0b7a310 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -1590,7 +1590,7 @@ static void ipoib_neigh_hash_uninit(struct net_device *dev) wait_for_completion(&priv->ntbl.deleted); } -void ipoib_dev_uninit_default(struct net_device *dev) +static void ipoib_dev_uninit_default(struct net_device *dev) { struct ipoib_dev_priv *priv = ipoib_priv(dev); -- cgit v1.2.3 From 95c2ef50c726a51d580c35ae8dccd383abaa8701 Mon Sep 17 00:00:00 2001 From: Israel Rukshin Date: Thu, 11 May 2017 18:52:36 +0300 Subject: RDMA/srp: Fix NULL deref at srp_destroy_qp() If srp_init_qp() fails at srp_create_ch_ib() then ch->send_cq may be NULL. Calling directly to ib_destroy_qp() is sufficient because no work requests were posted on the created qp. Fixes: 9294000d6d89 ("IB/srp: Drain the send queue before destroying a QP") Cc: Signed-off-by: Israel Rukshin Reviewed-by: Max Gurtovoy Reviewed-by: Bart van Assche -- Signed-off-by: Doug Ledford --- drivers/infiniband/ulp/srp/ib_srp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index def723a5df29..4306285fb155 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -575,7 +575,7 @@ static int srp_create_ch_ib(struct srp_rdma_ch *ch) return 0; err_qp: - srp_destroy_qp(ch, qp); + ib_destroy_qp(qp); err_send_cq: ib_free_cq(send_cq); -- cgit v1.2.3 From 233c1955835bd8649003be9bb3d8e79788b08be1 Mon Sep 17 00:00:00 2001 From: Leon Romanovsky Date: Sun, 14 May 2017 15:49:57 +0300 Subject: RDMA/netlink: Reduce exposure of RDMA netlink functions RDMA netlink is part of ib_core, hence ibnl_chk_listeners(), ibnl_init() and ibnl_cleanup() don't need to be published in public header file. Let's remove EXPORT_SYMBOL from ibnl_chk_listeners() and move all these functions to private header file. CC: Yuval Shaia Signed-off-by: Leon Romanovsky Reviewed-by: Yuval Shaia Signed-off-by: Doug Ledford --- drivers/infiniband/core/core_priv.h | 10 ++++++++++ drivers/infiniband/core/netlink.c | 2 +- include/rdma/rdma_netlink.h | 10 ---------- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/infiniband/core/core_priv.h b/drivers/infiniband/core/core_priv.h index cb7d372e4bdf..d92ab4eaa8f3 100644 --- a/drivers/infiniband/core/core_priv.h +++ b/drivers/infiniband/core/core_priv.h @@ -169,6 +169,16 @@ void ib_mad_cleanup(void); int ib_sa_init(void); void ib_sa_cleanup(void); +int ibnl_init(void); +void ibnl_cleanup(void); + +/** + * Check if there are any listeners to the netlink group + * @group: the netlink group ID + * Returns 0 on success or a negative for no listeners. + */ +int ibnl_chk_listeners(unsigned int group); + int ib_nl_handle_resolve_resp(struct sk_buff *skb, struct netlink_callback *cb); int ib_nl_handle_set_timeout(struct sk_buff *skb, diff --git a/drivers/infiniband/core/netlink.c b/drivers/infiniband/core/netlink.c index b784055423c8..94931c474d41 100644 --- a/drivers/infiniband/core/netlink.c +++ b/drivers/infiniband/core/netlink.c @@ -37,6 +37,7 @@ #include #include #include +#include "core_priv.h" struct ibnl_client { struct list_head list; @@ -55,7 +56,6 @@ int ibnl_chk_listeners(unsigned int group) return -1; return 0; } -EXPORT_SYMBOL(ibnl_chk_listeners); int ibnl_add_client(int index, int nops, const struct ibnl_client_cbs cb_table[]) diff --git a/include/rdma/rdma_netlink.h b/include/rdma/rdma_netlink.h index 585266144329..348c102cb5f6 100644 --- a/include/rdma/rdma_netlink.h +++ b/include/rdma/rdma_netlink.h @@ -10,9 +10,6 @@ struct ibnl_client_cbs { struct module *module; }; -int ibnl_init(void); -void ibnl_cleanup(void); - /** * Add a a client to the list of IB netlink exporters. * @index: Index of the added client @@ -77,11 +74,4 @@ int ibnl_unicast(struct sk_buff *skb, struct nlmsghdr *nlh, int ibnl_multicast(struct sk_buff *skb, struct nlmsghdr *nlh, unsigned int group, gfp_t flags); -/** - * Check if there are any listeners to the netlink group - * @group: the netlink group ID - * Returns 0 on success or a negative for no listeners. - */ -int ibnl_chk_listeners(unsigned int group); - #endif /* _RDMA_NETLINK_H */ -- cgit v1.2.3 From f937d93a9122d1510ca6e4bb8d860aedcf9408c3 Mon Sep 17 00:00:00 2001 From: Leon Romanovsky Date: Thu, 18 May 2017 07:40:33 +0300 Subject: RDMA/uverbs: Declare local function static and add brackets to sizeof Commit 57520751445b ("IB/SA: Add OPA path record type") introduced new local function __ib_copy_path_rec_to_user, but didn't limit its scope. This produces the following sparse warning: drivers/infiniband/core/uverbs_marshall.c:99:6: warning: symbol '__ib_copy_path_rec_to_user' was not declared. Should it be static? In addition, it used sizeof ... notations instead of sizeof(...), which is correct in C, but a little bit misleading. Let's change it too. Fixes: 57520751445b ("IB/SA: Add OPA path record type") Reviewed-by: Yuval Shaia Signed-off-by: Leon Romanovsky Signed-off-by: Doug Ledford --- drivers/infiniband/core/uverbs_marshall.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/infiniband/core/uverbs_marshall.c b/drivers/infiniband/core/uverbs_marshall.c index 8b9587fe2303..94fd989c9060 100644 --- a/drivers/infiniband/core/uverbs_marshall.c +++ b/drivers/infiniband/core/uverbs_marshall.c @@ -96,11 +96,11 @@ void ib_copy_qp_attr_to_user(struct ib_uverbs_qp_attr *dst, } EXPORT_SYMBOL(ib_copy_qp_attr_to_user); -void __ib_copy_path_rec_to_user(struct ib_user_path_rec *dst, - struct sa_path_rec *src) +static void __ib_copy_path_rec_to_user(struct ib_user_path_rec *dst, + struct sa_path_rec *src) { - memcpy(dst->dgid, src->dgid.raw, sizeof src->dgid); - memcpy(dst->sgid, src->sgid.raw, sizeof src->sgid); + memcpy(dst->dgid, src->dgid.raw, sizeof(src->dgid)); + memcpy(dst->sgid, src->sgid.raw, sizeof(src->sgid)); dst->dlid = htons(ntohl(sa_path_get_dlid(src))); dst->slid = htons(ntohl(sa_path_get_slid(src))); -- cgit v1.2.3 From 53376fedb9da54c0d3b0bd3a6edcbeb681692909 Mon Sep 17 00:00:00 2001 From: Qing Huang Date: Thu, 18 May 2017 16:33:53 -0700 Subject: RDMA/core: not to set page dirty bit if it's already set. This change will optimize kernel memory deregistration operations. __ib_umem_release() used to call set_page_dirty_lock() against every writable page in its memory region. Its purpose is to keep data synced between CPU and DMA device when swapping happens after mem deregistration ops. Now we choose not to set page dirty bit if it's already set by kernel prior to calling __ib_umem_release(). This reduces memory deregistration time by half or even more when we ran application simulation test program. Signed-off-by: Qing Huang Signed-off-by: Doug Ledford --- drivers/infiniband/core/umem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c index 3dbf811d3c51..21e60b1e2ff4 100644 --- a/drivers/infiniband/core/umem.c +++ b/drivers/infiniband/core/umem.c @@ -58,7 +58,7 @@ static void __ib_umem_release(struct ib_device *dev, struct ib_umem *umem, int d for_each_sg(umem->sg_head.sgl, sg, umem->npages, i) { page = sg_page(sg); - if (umem->writable && dirty) + if (!PageDirty(page) && umem->writable && dirty) set_page_dirty_lock(page); put_page(page); } -- cgit v1.2.3 From 79bb5b7ee1776a244484a1be6671d89fbd7c0c9f Mon Sep 17 00:00:00 2001 From: Leon Romanovsky Date: Sun, 21 May 2017 19:08:09 +0300 Subject: RDMA/umem: Fix missing mmap_sem in get umem ODP call Add mmap_sem lock around VMA inspection in ib_umem_odp_get(). Fixes: 0008b84ea9af ('IB/umem: Add support to huge ODP') Signed-off-by: Artemy Kovalyov Reviewed-by: Eli Cohen Signed-off-by: Leon Romanovsky Signed-off-by: Doug Ledford --- drivers/infiniband/core/umem_odp.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/infiniband/core/umem_odp.c b/drivers/infiniband/core/umem_odp.c index 0780b1afefa9..8c4ec564e495 100644 --- a/drivers/infiniband/core/umem_odp.c +++ b/drivers/infiniband/core/umem_odp.c @@ -321,11 +321,15 @@ int ib_umem_odp_get(struct ib_ucontext *context, struct ib_umem *umem, struct vm_area_struct *vma; struct hstate *h; + down_read(&mm->mmap_sem); vma = find_vma(mm, ib_umem_start(umem)); - if (!vma || !is_vm_hugetlb_page(vma)) + if (!vma || !is_vm_hugetlb_page(vma)) { + up_read(&mm->mmap_sem); return -EINVAL; + } h = hstate_vma(vma); umem->page_shift = huge_page_shift(h); + up_read(&mm->mmap_sem); umem->hugetlb = 1; } else { umem->hugetlb = 0; -- cgit v1.2.3 From d3957b86a40612826ef935f474b31359d66cbdca Mon Sep 17 00:00:00 2001 From: Majd Dibbiny Date: Sun, 21 May 2017 19:09:54 +0300 Subject: RDMA/SA: Fix kernel panic in CMA request handler flow Commit 9fdca4da4d8c (IB/SA: Split struct sa_path_rec based on IB and ROCE specific fields) moved the service_id to be specific attribute for IB and OPA SA Path Record, and thus wasn't assigned for RoCE. This caused to the following kernel panic in the CMA request handler flow: [ 27.074594] BUG: unable to handle kernel NULL pointer dereference at 0000000000000008 [ 27.074731] IP: __radix_tree_lookup+0x1d/0xe0 ... [ 27.075356] Workqueue: ib_cm cm_work_handler [ib_cm] [ 27.075401] task: ffff88022e3b8000 task.stack: ffffc90001298000 [ 27.075449] RIP: 0010:__radix_tree_lookup+0x1d/0xe0 ... [ 27.075979] Call Trace: [ 27.076015] radix_tree_lookup+0xd/0x10 [ 27.076055] cma_ps_find+0x59/0x70 [rdma_cm] [ 27.076097] cma_id_from_event+0xd2/0x470 [rdma_cm] [ 27.076144] ? ib_init_ah_from_path+0x39a/0x590 [ib_core] [ 27.076193] cma_req_handler+0x25/0x480 [rdma_cm] [ 27.076237] cm_process_work+0x25/0x120 [ib_cm] [ 27.076280] ? cm_get_bth_pkey.isra.62+0x3c/0xa0 [ib_cm] [ 27.076350] cm_req_handler+0xb03/0xd40 [ib_cm] [ 27.076430] ? sched_clock_cpu+0x11/0xb0 [ 27.076478] cm_work_handler+0x194/0x1588 [ib_cm] [ 27.076525] process_one_work+0x160/0x410 [ 27.076565] worker_thread+0x137/0x4a0 [ 27.076614] kthread+0x112/0x150 [ 27.076684] ? max_active_store+0x60/0x60 [ 27.077642] ? kthread_park+0x90/0x90 [ 27.078530] ret_from_fork+0x2c/0x40 This patch moves it back to the common SA Path Record structure and removes the redundant setter and getter. Tested on Connect-IB and Connect-X4 in Infiniband and RoCE respectively. Fixes: 9fdca4da4d8c (IB/SA: Split struct sa_path_rec based on IB ands ROCE specific fields) Signed-off-by: Majd Dibbiny Reviewed-by: Parav Pandit Signed-off-by: Leon Romanovsky Signed-off-by: Doug Ledford --- drivers/infiniband/core/cm.c | 4 ++-- drivers/infiniband/core/cma.c | 13 ++++++------- drivers/infiniband/core/sa_query.c | 6 +++--- drivers/infiniband/ulp/srp/ib_srp.c | 2 +- include/rdma/ib_sa.h | 25 +++---------------------- 5 files changed, 15 insertions(+), 35 deletions(-) diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index 1844770f3ae8..2b4d613a3474 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c @@ -1429,7 +1429,7 @@ static void cm_format_paths_from_req(struct cm_req_msg *req_msg, primary_path->packet_life_time = cm_req_get_primary_local_ack_timeout(req_msg); primary_path->packet_life_time -= (primary_path->packet_life_time > 0); - sa_path_set_service_id(primary_path, req_msg->service_id); + primary_path->service_id = req_msg->service_id; if (req_msg->alt_local_lid) { alt_path->dgid = req_msg->alt_local_gid; @@ -1452,7 +1452,7 @@ static void cm_format_paths_from_req(struct cm_req_msg *req_msg, alt_path->packet_life_time = cm_req_get_alt_local_ack_timeout(req_msg); alt_path->packet_life_time -= (alt_path->packet_life_time > 0); - sa_path_set_service_id(alt_path, req_msg->service_id); + alt_path->service_id = req_msg->service_id; } } diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 91b7a2fe5a55..31bb82d8ecd7 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -1140,7 +1140,7 @@ static void cma_save_ib_info(struct sockaddr *src_addr, ib->sib_pkey = path->pkey; ib->sib_flowinfo = path->flow_label; memcpy(&ib->sib_addr, &path->sgid, 16); - ib->sib_sid = sa_path_get_service_id(path); + ib->sib_sid = path->service_id; ib->sib_scope_id = 0; } else { ib->sib_pkey = listen_ib->sib_pkey; @@ -1274,8 +1274,7 @@ static int cma_save_req_info(const struct ib_cm_event *ib_event, memcpy(&req->local_gid, &req_param->primary_path->sgid, sizeof(req->local_gid)); req->has_gid = true; - req->service_id = - sa_path_get_service_id(req_param->primary_path); + req->service_id = req_param->primary_path->service_id; req->pkey = be16_to_cpu(req_param->primary_path->pkey); if (req->pkey != req_param->bth_pkey) pr_warn_ratelimited("RDMA CMA: got different BTH P_Key (0x%x) and primary path P_Key (0x%x)\n" @@ -1827,7 +1826,8 @@ static struct rdma_id_private *cma_new_conn_id(struct rdma_cm_id *listen_id, struct rdma_route *rt; const sa_family_t ss_family = listen_id->route.addr.src_addr.ss_family; struct sa_path_rec *path = ib_event->param.req_rcvd.primary_path; - const __be64 service_id = sa_path_get_service_id(path); + const __be64 service_id = + ib_event->param.req_rcvd.primary_path->service_id; int ret; id = rdma_create_id(listen_id->route.addr.dev_addr.net, @@ -2345,9 +2345,8 @@ static int cma_query_ib_route(struct rdma_id_private *id_priv, int timeout_ms, path_rec.pkey = cpu_to_be16(ib_addr_get_pkey(dev_addr)); path_rec.numb_path = 1; path_rec.reversible = 1; - sa_path_set_service_id(&path_rec, - rdma_get_service_id(&id_priv->id, - cma_dst_addr(id_priv))); + path_rec.service_id = rdma_get_service_id(&id_priv->id, + cma_dst_addr(id_priv)); comp_mask = IB_SA_PATH_REC_DGID | IB_SA_PATH_REC_SGID | IB_SA_PATH_REC_PKEY | IB_SA_PATH_REC_NUMB_PATH | diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c index e335b09c022e..fb7aec4047c8 100644 --- a/drivers/infiniband/core/sa_query.c +++ b/drivers/infiniband/core/sa_query.c @@ -194,7 +194,7 @@ static u32 tid; .field_name = "sa_path_rec:" #field static const struct ib_field path_rec_table[] = { - { PATH_REC_FIELD(ib.service_id), + { PATH_REC_FIELD(service_id), .offset_words = 0, .offset_bits = 0, .size_bits = 64 }, @@ -296,7 +296,7 @@ static const struct ib_field path_rec_table[] = { .field_name = "sa_path_rec:" #field static const struct ib_field opa_path_rec_table[] = { - { OPA_PATH_REC_FIELD(opa.service_id), + { OPA_PATH_REC_FIELD(service_id), .offset_words = 0, .offset_bits = 0, .size_bits = 64 }, @@ -774,7 +774,7 @@ static void ib_nl_set_path_rec_attrs(struct sk_buff *skb, /* Now build the attributes */ if (comp_mask & IB_SA_PATH_REC_SERVICE_ID) { - val64 = be64_to_cpu(sa_path_get_service_id(sa_rec)); + val64 = be64_to_cpu(sa_rec->service_id); nla_put(skb, RDMA_NLA_F_MANDATORY | LS_NLA_TYPE_SERVICE_ID, sizeof(val64), &val64); } diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 4306285fb155..2354c742caa1 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -320,7 +320,7 @@ static int srp_new_cm_id(struct srp_rdma_ch *ch) ch->path.sgid = target->sgid; ch->path.dgid = target->orig_dgid; ch->path.pkey = target->pkey; - sa_path_set_service_id(&ch->path, target->service_id); + ch->path.service_id = target->service_id; return 0; } diff --git a/include/rdma/ib_sa.h b/include/rdma/ib_sa.h index f5f70e345318..355b81f4242d 100644 --- a/include/rdma/ib_sa.h +++ b/include/rdma/ib_sa.h @@ -158,7 +158,6 @@ enum sa_path_rec_type { }; struct sa_path_rec_ib { - __be64 service_id; __be16 dlid; __be16 slid; u8 raw_traffic; @@ -174,7 +173,6 @@ struct sa_path_rec_roce { }; struct sa_path_rec_opa { - __be64 service_id; __be32 dlid; __be32 slid; u8 raw_traffic; @@ -189,6 +187,7 @@ struct sa_path_rec_opa { struct sa_path_rec { union ib_gid dgid; union ib_gid sgid; + __be64 service_id; /* reserved */ __be32 flow_label; u8 hop_limit; @@ -262,7 +261,7 @@ static inline void path_conv_opa_to_ib(struct sa_path_rec *ib, ib->ib.dlid = htons(ntohl(opa->opa.dlid)); ib->ib.slid = htons(ntohl(opa->opa.slid)); } - ib->ib.service_id = opa->opa.service_id; + ib->service_id = opa->service_id; ib->ib.raw_traffic = opa->opa.raw_traffic; } @@ -281,7 +280,7 @@ static inline void path_conv_ib_to_opa(struct sa_path_rec *opa, } opa->opa.slid = slid; opa->opa.dlid = dlid; - opa->opa.service_id = ib->ib.service_id; + opa->service_id = ib->service_id; opa->opa.raw_traffic = ib->ib.raw_traffic; } @@ -591,15 +590,6 @@ static inline bool sa_path_is_roce(struct sa_path_rec *rec) (rec->rec_type == SA_PATH_REC_TYPE_ROCE_V2)); } -static inline void sa_path_set_service_id(struct sa_path_rec *rec, - __be64 service_id) -{ - if (rec->rec_type == SA_PATH_REC_TYPE_IB) - rec->ib.service_id = service_id; - else if (rec->rec_type == SA_PATH_REC_TYPE_OPA) - rec->opa.service_id = service_id; -} - static inline void sa_path_set_slid(struct sa_path_rec *rec, __be32 slid) { if (rec->rec_type == SA_PATH_REC_TYPE_IB) @@ -625,15 +615,6 @@ static inline void sa_path_set_raw_traffic(struct sa_path_rec *rec, rec->opa.raw_traffic = raw_traffic; } -static inline __be64 sa_path_get_service_id(struct sa_path_rec *rec) -{ - if (rec->rec_type == SA_PATH_REC_TYPE_IB) - return rec->ib.service_id; - else if (rec->rec_type == SA_PATH_REC_TYPE_OPA) - return rec->opa.service_id; - return 0; -} - static inline __be32 sa_path_get_slid(struct sa_path_rec *rec) { if (rec->rec_type == SA_PATH_REC_TYPE_IB) -- cgit v1.2.3 From cf5cde2199058f1aed33f8b5f637c02a95936031 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Wed, 24 May 2017 14:10:10 +0900 Subject: ARM: dts: versatile: use #include "..." to include local DT Most of DT files in ARM use #include "..." to make pre-processor include DT in the same directory, but this is one of the exceptional files that use #include <...> for that. Fix it to remove -I$(srctree)/arch/$(SRCARCH)/boot/dts path from dtc_cpp_flags. ARM: dts: versatile: use #include "..." to include DT in the same directory Most of DT files in ARM use #include "..." to make pre-processor include DT in the same directory, but we have 3 exceptional files that use #include <...> for that. They must be fixed to remove -I$(srctree)/arch/$(SRCARCH)/boot/dts path from dtc_cpp_flags. Signed-off-by: Masahiro Yamada Signed-off-by: Olof Johansson --- arch/arm/boot/dts/versatile-pb.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/versatile-pb.dts b/arch/arm/boot/dts/versatile-pb.dts index 33a8eb28374e..06e2331f666d 100644 --- a/arch/arm/boot/dts/versatile-pb.dts +++ b/arch/arm/boot/dts/versatile-pb.dts @@ -1,4 +1,4 @@ -#include +#include "versatile-ab.dts" / { model = "ARM Versatile PB"; -- cgit v1.2.3 From 73069883c017d454737d07a5aeab2b1639fcfeca Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Mon, 29 May 2017 17:17:54 +0200 Subject: MAINTAINERS: remove kernel@stlinux.com obsolete mailing list The STMicroelectronics dedicated mailing list kernel@stlinux.com is no more available, remove it to avoid bouncing mails. Several request to create a new mailing list has been send by Benjamin Gaignard and me but without any answers. Signed-off-by: Patrice Chotard Signed-off-by: Olof Johansson --- MAINTAINERS | 2 -- 1 file changed, 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 8c66b44e4235..b66d6dd4cd70 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1829,7 +1829,6 @@ F: drivers/edac/altera_edac. ARM/STI ARCHITECTURE M: Patrice Chotard L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) -L: kernel@stlinux.com W: http://www.stlinux.com S: Maintained F: arch/arm/mach-sti/ @@ -11264,7 +11263,6 @@ F: drivers/media/rc/serial_ir.c STI CEC DRIVER M: Benjamin Gaignard -L: kernel@stlinux.com S: Maintained F: drivers/staging/media/st-cec/ F: Documentation/devicetree/bindings/media/stih-cec.txt -- cgit v1.2.3 From c4beedb8a914af9c8c1b6e67c753adf411e05160 Mon Sep 17 00:00:00 2001 From: Andi Shyti Date: Thu, 1 Jun 2017 22:05:40 -0700 Subject: Input: tm2-touchkey - use LEN_ON as boolean value instead of LED_FULL Commit 4e552c8cb5bc ("leds: add LED_ON brightness as boolean value") has introduced the LED_ON enumeration value that can be used instead of LED_FULL which has more of a linear value. Because the tm2-touchscreen doesn't have brightness levels, but it's a simple on/off led, use LED_ON instead of LED_FULL. Signed-off-by: Andi Shyti Reviewed-by: Jaechul Lee Tested-by: Jaechul Lee Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/tm2-touchkey.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/keyboard/tm2-touchkey.c b/drivers/input/keyboard/tm2-touchkey.c index 485900f953e0..abc266e40e17 100644 --- a/drivers/input/keyboard/tm2-touchkey.c +++ b/drivers/input/keyboard/tm2-touchkey.c @@ -213,7 +213,7 @@ static int tm2_touchkey_probe(struct i2c_client *client, /* led device */ touchkey->led_dev.name = TM2_TOUCHKEY_DEV_NAME; touchkey->led_dev.brightness = LED_FULL; - touchkey->led_dev.max_brightness = LED_FULL; + touchkey->led_dev.max_brightness = LED_ON; touchkey->led_dev.brightness_set = tm2_touchkey_led_brightness_set; error = devm_led_classdev_register(&client->dev, &touchkey->led_dev); -- cgit v1.2.3 From ebcdaee4cebb3a8d0d702ab5e9392373672ec1de Mon Sep 17 00:00:00 2001 From: Jean-Philippe Brucker Date: Thu, 1 Jun 2017 19:22:01 +0100 Subject: dmaengine: pl330: fix warning in pl330_remove When removing a device with less than 9 IRQs (AMBA_NR_IRQS), we'll get a big WARN_ON from devres.c because pl330_remove calls devm_free_irqs for unallocated irqs. Similarly to pl330_probe, check that IRQ number is present before calling devm_free_irq. Signed-off-by: Jean-Philippe Brucker Signed-off-by: Vinod Koul --- drivers/dma/pl330.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c index 8b0da7fa520d..e90a7a0d760a 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -3008,7 +3008,8 @@ static int pl330_remove(struct amba_device *adev) for (i = 0; i < AMBA_NR_IRQS; i++) { irq = adev->irq[i]; - devm_free_irq(&adev->dev, irq, pl330); + if (irq) + devm_free_irq(&adev->dev, irq, pl330); } dma_async_device_unregister(&pl330->ddma); -- cgit v1.2.3 From 55b644fd2431cfd28d04cc28f092d49e7bea3433 Mon Sep 17 00:00:00 2001 From: Martin Blumenstingl Date: Sat, 6 May 2017 19:37:45 +0200 Subject: usb: dwc2: add support for the DWC2 controller on Meson8 SoCs USB support in the Meson8 SoCs is provided by a DWC2 controller which works with the same settings as Meson8b and GXBB. Using the generic "snps,dwc2" binding results in an endless stream of "Overcurrent change detected" messages. Acked-by: Rob Herring Signed-off-by: Martin Blumenstingl Signed-off-by: Felipe Balbi --- Documentation/devicetree/bindings/usb/dwc2.txt | 1 + drivers/usb/dwc2/params.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/usb/dwc2.txt b/Documentation/devicetree/bindings/usb/dwc2.txt index 00bea038639e..fcf199b64d3d 100644 --- a/Documentation/devicetree/bindings/usb/dwc2.txt +++ b/Documentation/devicetree/bindings/usb/dwc2.txt @@ -10,6 +10,7 @@ Required properties: - "rockchip,rk3288-usb", "rockchip,rk3066-usb", "snps,dwc2": for rk3288 Soc; - "lantiq,arx100-usb": The DWC2 USB controller instance in Lantiq ARX SoCs; - "lantiq,xrx200-usb": The DWC2 USB controller instance in Lantiq XRX SoCs; + - "amlogic,meson8-usb": The DWC2 USB controller instance in Amlogic Meson8 SoCs; - "amlogic,meson8b-usb": The DWC2 USB controller instance in Amlogic Meson8b SoCs; - "amlogic,meson-gxbb-usb": The DWC2 USB controller instance in Amlogic S905 SoCs; - "amcc,dwc-otg": The DWC2 USB controller instance in AMCC Canyonlands 460EX SoCs; diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c index 9cd8722f24f6..a3ffe97170ff 100644 --- a/drivers/usb/dwc2/params.c +++ b/drivers/usb/dwc2/params.c @@ -144,6 +144,8 @@ const struct of_device_id dwc2_of_match_table[] = { { .compatible = "lantiq,xrx200-usb", .data = dwc2_set_ltq_params }, { .compatible = "snps,dwc2" }, { .compatible = "samsung,s3c6400-hsotg" }, + { .compatible = "amlogic,meson8-usb", + .data = dwc2_set_amlogic_params }, { .compatible = "amlogic,meson8b-usb", .data = dwc2_set_amlogic_params }, { .compatible = "amlogic,meson-gxbb-usb", -- cgit v1.2.3 From dc9217b69dd6089dcfeb86ed4b3c671504326087 Mon Sep 17 00:00:00 2001 From: Thinh Nguyen Date: Thu, 11 May 2017 17:26:48 -0700 Subject: usb: gadget: f_mass_storage: Serialize wake and sleep execution f_mass_storage has a memorry barrier issue with the sleep and wake functions that can cause a deadlock. This results in intermittent hangs during MSC file transfer. The host will reset the device after receiving no response to resume the transfer. This issue is seen when dwc3 is processing 2 transfer-in-progress events at the same time, invoking completion handlers for CSW and CBW. Also this issue occurs depending on the system timing and latency. To increase the chance to hit this issue, you can force dwc3 driver to wait and process those 2 events at once by adding a small delay (~100us) in dwc3_check_event_buf() whenever the request is for CSW and read the event count again. Avoid debugging with printk and ftrace as extra delays and memory barrier will mask this issue. Scenario which can lead to failure: ----------------------------------- 1) The main thread sleeps and waits for the next command in get_next_command(). 2) bulk_in_complete() wakes up main thread for CSW. 3) bulk_out_complete() tries to wake up the running main thread for CBW. 4) thread_wakeup_needed is not loaded with correct value in sleep_thread(). 5) Main thread goes to sleep again. The pattern is shown below. Note the 2 critical variables. * common->thread_wakeup_needed * bh->state CPU 0 (sleep_thread) CPU 1 (wakeup_thread) ============================== =============================== bh->state = BH_STATE_FULL; smp_wmb(); thread_wakeup_needed = 0; thread_wakeup_needed = 1; smp_rmb(); if (bh->state != BH_STATE_FULL) sleep again ... As pointed out by Alan Stern, this is an R-pattern issue. The issue can be seen when there are two wakeups in quick succession. The thread_wakeup_needed can be overwritten in sleep_thread, and the read of the bh->state maybe reordered before the write to thread_wakeup_needed. This patch applies full memory barrier smp_mb() in both sleep_thread() and wakeup_thread() to ensure the order which the thread_wakeup_needed and bh->state are written and loaded. However, a better solution in the future would be to use wait_queue method that takes care of managing memory barrier between waker and waiter. Cc: Acked-by: Alan Stern Signed-off-by: Thinh Nguyen Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_mass_storage.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c index 4c8aacc232c0..74d57d6994da 100644 --- a/drivers/usb/gadget/function/f_mass_storage.c +++ b/drivers/usb/gadget/function/f_mass_storage.c @@ -396,7 +396,11 @@ static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep) /* Caller must hold fsg->lock */ static void wakeup_thread(struct fsg_common *common) { - smp_wmb(); /* ensure the write of bh->state is complete */ + /* + * Ensure the reading of thread_wakeup_needed + * and the writing of bh->state are completed + */ + smp_mb(); /* Tell the main thread that something has happened */ common->thread_wakeup_needed = 1; if (common->thread_task) @@ -627,7 +631,12 @@ static int sleep_thread(struct fsg_common *common, bool can_freeze) } __set_current_state(TASK_RUNNING); common->thread_wakeup_needed = 0; - smp_rmb(); /* ensure the latest bh->state is visible */ + + /* + * Ensure the writing of thread_wakeup_needed + * and the reading of bh->state are completed + */ + smp_mb(); return rc; } -- cgit v1.2.3 From cdc876877ebc3f0677b267756d4564e2a429e730 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Wed, 26 Apr 2017 20:50:07 +0900 Subject: usb: gadget: udc: renesas_usb3: fix pm_runtime functions calling This patch fixes an issue that this driver is possible to access the registers before pm_runtime_get_sync() if a gadget driver is installed first. After that, oops happens on R-Car Gen3 environment. To avoid it, this patch changes the pm_runtime call timing from probe/remove to udc_start/udc_stop. Fixes: 746bfe63bba3 ("usb: gadget: renesas_usb3: add support for Renesas USB3.0 peripheral controller") Signed-off-by: Yoshihiro Shimoda Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/renesas_usb3.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/usb/gadget/udc/renesas_usb3.c b/drivers/usb/gadget/udc/renesas_usb3.c index 5a2d845fb1a6..10585da8e360 100644 --- a/drivers/usb/gadget/udc/renesas_usb3.c +++ b/drivers/usb/gadget/udc/renesas_usb3.c @@ -1799,6 +1799,9 @@ static int renesas_usb3_start(struct usb_gadget *gadget, /* hook up the driver */ usb3->driver = driver; + pm_runtime_enable(usb3_to_dev(usb3)); + pm_runtime_get_sync(usb3_to_dev(usb3)); + renesas_usb3_init_controller(usb3); return 0; @@ -1816,6 +1819,9 @@ static int renesas_usb3_stop(struct usb_gadget *gadget) renesas_usb3_stop_controller(usb3); spin_unlock_irqrestore(&usb3->lock, flags); + pm_runtime_put(usb3_to_dev(usb3)); + pm_runtime_disable(usb3_to_dev(usb3)); + return 0; } @@ -1891,9 +1897,6 @@ static int renesas_usb3_remove(struct platform_device *pdev) device_remove_file(&pdev->dev, &dev_attr_role); - pm_runtime_put(&pdev->dev); - pm_runtime_disable(&pdev->dev); - usb_del_gadget_udc(&usb3->gadget); __renesas_usb3_ep_free_request(usb3->ep0_req); @@ -2099,9 +2102,6 @@ static int renesas_usb3_probe(struct platform_device *pdev) usb3->workaround_for_vbus = priv->workaround_for_vbus; - pm_runtime_enable(&pdev->dev); - pm_runtime_get_sync(&pdev->dev); - dev_info(&pdev->dev, "probed\n"); return 0; -- cgit v1.2.3 From 067d6fdc558d2c43f0bfdc7af99630dd5eb08dc5 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Wed, 26 Apr 2017 20:50:08 +0900 Subject: usb: gadget: udc: renesas_usb3: fix deadlock by spinlock This patch fixes an issue that this driver is possible to cause deadlock by double-spinclocked in renesas_usb3_stop_controller(). So, this patch removes spinlock API calling in renesas_usb3_stop(). (In other words, the previous code had a redundant lock.) Fixes: 746bfe63bba3 ("usb: gadget: renesas_usb3: add support for Renesas USB3.0 peripheral controller") Signed-off-by: Yoshihiro Shimoda Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/renesas_usb3.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/usb/gadget/udc/renesas_usb3.c b/drivers/usb/gadget/udc/renesas_usb3.c index 10585da8e360..e27d948617e2 100644 --- a/drivers/usb/gadget/udc/renesas_usb3.c +++ b/drivers/usb/gadget/udc/renesas_usb3.c @@ -1810,14 +1810,11 @@ static int renesas_usb3_start(struct usb_gadget *gadget, static int renesas_usb3_stop(struct usb_gadget *gadget) { struct renesas_usb3 *usb3 = gadget_to_renesas_usb3(gadget); - unsigned long flags; - spin_lock_irqsave(&usb3->lock, flags); usb3->softconnect = false; usb3->gadget.speed = USB_SPEED_UNKNOWN; usb3->driver = NULL; renesas_usb3_stop_controller(usb3); - spin_unlock_irqrestore(&usb3->lock, flags); pm_runtime_put(usb3_to_dev(usb3)); pm_runtime_disable(usb3_to_dev(usb3)); -- cgit v1.2.3 From 940f538a100c84c6e72813e4ac88bd1753a86945 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Wed, 26 Apr 2017 20:50:09 +0900 Subject: usb: gadget: udc: renesas_usb3: lock for PN_ registers access This controller disallows to change the PIPE until reading/writing a packet finishes. However. the previous code is not enough to hold the lock in some functions. So, this patch fixes it. Fixes: 746bfe63bba3 ("usb: gadget: renesas_usb3: add support for Renesas USB3.0 peripheral controller") Signed-off-by: Yoshihiro Shimoda Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/renesas_usb3.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/drivers/usb/gadget/udc/renesas_usb3.c b/drivers/usb/gadget/udc/renesas_usb3.c index e27d948617e2..c05097b5661e 100644 --- a/drivers/usb/gadget/udc/renesas_usb3.c +++ b/drivers/usb/gadget/udc/renesas_usb3.c @@ -1475,7 +1475,13 @@ static void usb3_request_done_pipen(struct renesas_usb3 *usb3, struct renesas_usb3_request *usb3_req, int status) { - usb3_pn_stop(usb3); + unsigned long flags; + + spin_lock_irqsave(&usb3->lock, flags); + if (usb3_pn_change(usb3, usb3_ep->num)) + usb3_pn_stop(usb3); + spin_unlock_irqrestore(&usb3->lock, flags); + usb3_disable_pipe_irq(usb3, usb3_ep->num); usb3_request_done(usb3_ep, usb3_req, status); @@ -1504,30 +1510,46 @@ static void usb3_irq_epc_pipen_bfrdy(struct renesas_usb3 *usb3, int num) { struct renesas_usb3_ep *usb3_ep = usb3_get_ep(usb3, num); struct renesas_usb3_request *usb3_req = usb3_get_request(usb3_ep); + bool done = false; if (!usb3_req) return; + spin_lock(&usb3->lock); + if (usb3_pn_change(usb3, num)) + goto out; + if (usb3_ep->dir_in) { /* Do not stop the IN pipe here to detect LSTTR interrupt */ if (!usb3_write_pipe(usb3_ep, usb3_req, USB3_PN_WRITE)) usb3_clear_bit(usb3, PN_INT_BFRDY, USB3_PN_INT_ENA); } else { if (!usb3_read_pipe(usb3_ep, usb3_req, USB3_PN_READ)) - usb3_request_done_pipen(usb3, usb3_ep, usb3_req, 0); + done = true; } + +out: + /* need to unlock because usb3_request_done_pipen() locks it */ + spin_unlock(&usb3->lock); + + if (done) + usb3_request_done_pipen(usb3, usb3_ep, usb3_req, 0); } static void usb3_irq_epc_pipen(struct renesas_usb3 *usb3, int num) { u32 pn_int_sta; - if (usb3_pn_change(usb3, num) < 0) + spin_lock(&usb3->lock); + if (usb3_pn_change(usb3, num) < 0) { + spin_unlock(&usb3->lock); return; + } pn_int_sta = usb3_read(usb3, USB3_PN_INT_STA); pn_int_sta &= usb3_read(usb3, USB3_PN_INT_ENA); usb3_write(usb3, pn_int_sta, USB3_PN_INT_STA); + spin_unlock(&usb3->lock); if (pn_int_sta & PN_INT_LSTTR) usb3_irq_epc_pipen_lsttr(usb3, num); if (pn_int_sta & PN_INT_BFRDY) -- cgit v1.2.3 From afbbc7913a288c29616bd31ae612548f6475151a Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Wed, 26 Apr 2017 20:50:10 +0900 Subject: usb: gadget: udc: renesas_usb3: Fix PN_INT_ENA disabling timing The PN_INT_ENA register should be used after usb3_pn_change() is called. So, this patch moves the access from renesas_usb3_stop_controller() to usb3_disable_pipe_n(). Fixes: 746bfe63bba3 ("usb: gadget: renesas_usb3: add support for Renesas USB3.0 peripheral controller") Signed-off-by: Yoshihiro Shimoda Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/renesas_usb3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/udc/renesas_usb3.c b/drivers/usb/gadget/udc/renesas_usb3.c index c05097b5661e..cd4c88529721 100644 --- a/drivers/usb/gadget/udc/renesas_usb3.c +++ b/drivers/usb/gadget/udc/renesas_usb3.c @@ -623,7 +623,6 @@ static void renesas_usb3_stop_controller(struct renesas_usb3 *usb3) { usb3_disconnect(usb3); usb3_write(usb3, 0, USB3_P0_INT_ENA); - usb3_write(usb3, 0, USB3_PN_INT_ENA); usb3_write(usb3, 0, USB3_USB_OTG_INT_ENA); usb3_write(usb3, 0, USB3_USB_INT_ENA_1); usb3_write(usb3, 0, USB3_USB_INT_ENA_2); @@ -1682,6 +1681,7 @@ static int usb3_disable_pipe_n(struct renesas_usb3_ep *usb3_ep) spin_lock_irqsave(&usb3->lock, flags); if (!usb3_pn_change(usb3, usb3_ep->num)) { + usb3_write(usb3, 0, USB3_PN_INT_ENA); usb3_write(usb3, 0, USB3_PN_RAMMAP); usb3_clear_bit(usb3, PN_CON_EN, USB3_PN_CON); } -- cgit v1.2.3 From 715e944f8a7a1059db5d61ebf197e6f348d747e2 Mon Sep 17 00:00:00 2001 From: Carlo Caione Date: Tue, 30 May 2017 22:39:46 +0200 Subject: HID: asus: Stop underlying hardware on remove We are missing a call to hid_hw_stop() on the remove hook. Among other things this is causing an Oops when (re-)starting GNOME / upowerd / ... after the module has been already rmmod-ed. Signed-off-by: Carlo Caione Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-asus.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c index 101ab2e63d18..a6268f2f7408 100644 --- a/drivers/hid/hid-asus.c +++ b/drivers/hid/hid-asus.c @@ -537,6 +537,8 @@ static void asus_remove(struct hid_device *hdev) drvdata->kbd_backlight->removed = true; cancel_work_sync(&drvdata->kbd_backlight->work); } + + hid_hw_stop(hdev); } static __u8 *asus_report_fixup(struct hid_device *hdev, __u8 *rdesc, -- cgit v1.2.3 From cb7cf772d83d2d4e6995c5bb9e0fb59aea8f7080 Mon Sep 17 00:00:00 2001 From: Lorenzo Pieralisi Date: Fri, 26 May 2017 17:40:02 +0100 Subject: ARM64/ACPI: Fix BAD_MADT_GICC_ENTRY() macro implementation The BAD_MADT_GICC_ENTRY() macro checks if a GICC MADT entry passes muster from an ACPI specification standpoint. Current macro detects the MADT GICC entry length through ACPI firmware version (it changed from 76 to 80 bytes in the transition from ACPI 5.1 to ACPI 6.0 specification) but always uses (erroneously) the ACPICA (latest) struct (ie struct acpi_madt_generic_interrupt - that is 80-bytes long) length to check if the current GICC entry memory record exceeds the MADT table end in memory as defined by the MADT table header itself, which may result in false negatives depending on the ACPI firmware version and how the MADT entries are laid out in memory (ie on ACPI 5.1 firmware MADT GICC entries are 76 bytes long, so by adding 80 to a GICC entry start address in memory the resulting address may well be past the actual MADT end, triggering a false negative). Fix the BAD_MADT_GICC_ENTRY() macro by reshuffling the condition checks and update them to always use the firmware version specific MADT GICC entry length in order to carry out boundary checks. Fixes: b6cfb277378e ("ACPI / ARM64: add BAD_MADT_GICC_ENTRY() macro") Reported-by: Julien Grall Acked-by: Will Deacon Acked-by: Marc Zyngier Signed-off-by: Lorenzo Pieralisi Cc: Julien Grall Cc: Hanjun Guo Cc: Al Stone Signed-off-by: Catalin Marinas --- arch/arm64/include/asm/acpi.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h index 0e99978da3f0..59cca1d6ec54 100644 --- a/arch/arm64/include/asm/acpi.h +++ b/arch/arm64/include/asm/acpi.h @@ -23,9 +23,9 @@ #define ACPI_MADT_GICC_LENGTH \ (acpi_gbl_FADT.header.revision < 6 ? 76 : 80) -#define BAD_MADT_GICC_ENTRY(entry, end) \ - (!(entry) || (unsigned long)(entry) + sizeof(*(entry)) > (end) || \ - (entry)->header.length != ACPI_MADT_GICC_LENGTH) +#define BAD_MADT_GICC_ENTRY(entry, end) \ + (!(entry) || (entry)->header.length != ACPI_MADT_GICC_LENGTH || \ + (unsigned long)(entry) + ACPI_MADT_GICC_LENGTH > (end)) /* Basic configuration for ACPI */ #ifdef CONFIG_ACPI -- cgit v1.2.3 From 918c7b062a0f9198d9503cfece0210c1743c0f88 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Mon, 22 May 2017 18:00:16 -0700 Subject: perf stat: Only print NMI watchdog hint when enabled Only print the NMI watchdog hint when that watchdog it actually enabled. This avoids printing these unnecessarily. Signed-off-by: Andi Kleen Acked-by: Jiri Olsa Link: http://lkml.kernel.org/n/tip-lnw7edxnqsphkmeew857wz1i@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index a935b5023732..ad9324d1daf9 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -1578,6 +1578,7 @@ static void print_header(int argc, const char **argv) static void print_footer(void) { FILE *output = stat_config.output; + int n; if (!null_run) fprintf(output, "\n"); @@ -1590,7 +1591,9 @@ static void print_footer(void) } fprintf(output, "\n\n"); - if (print_free_counters_hint) + if (print_free_counters_hint && + sysctl__read_int("kernel/nmi_watchdog", &n) >= 0 && + n > 0) fprintf(output, "Some events weren't counted. Try disabling the NMI watchdog:\n" " echo 0 > /proc/sys/kernel/nmi_watchdog\n" -- cgit v1.2.3 From d31353cd753c443ace5723d6878a39f393a0c136 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Thu, 1 Jun 2017 18:02:39 -0700 Subject: net: systemport: Fix missing Wake-on-LAN interrupt for SYSTEMPORT Lite On SYSTEMPORT Lite, since we have the main interrupt source in the first cell, the second cell is the Wake-on-LAN interrupt, yet the code was not properly updated to fetch the second cell, and instead looked at the third and non-existing cell for Wake-on-LAN. Fixes: 44a4524c54af ("net: systemport: Add support for SYSTEMPORT Lite") Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bcmsysport.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c index 099b374c1b17..5274501428e4 100644 --- a/drivers/net/ethernet/broadcom/bcmsysport.c +++ b/drivers/net/ethernet/broadcom/bcmsysport.c @@ -2026,9 +2026,12 @@ static int bcm_sysport_probe(struct platform_device *pdev) priv->num_rx_desc_words = params->num_rx_desc_words; priv->irq0 = platform_get_irq(pdev, 0); - if (!priv->is_lite) + if (!priv->is_lite) { priv->irq1 = platform_get_irq(pdev, 1); - priv->wol_irq = platform_get_irq(pdev, 2); + priv->wol_irq = platform_get_irq(pdev, 2); + } else { + priv->wol_irq = platform_get_irq(pdev, 1); + } if (priv->irq0 <= 0 || (priv->irq1 <= 0 && !priv->is_lite)) { dev_err(&pdev->dev, "invalid interrupts\n"); ret = -EINVAL; -- cgit v1.2.3 From ac2629a4797fdc839f7a4775cc141e6f53e064cf Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Thu, 1 Jun 2017 19:53:04 -0700 Subject: net: dsa: Move dsa_switch_{suspend,resume} out of legacy.c dsa_switch_suspend() and dsa_switch_resume() are functions that belong in net/dsa/dsa.c and are not part of the legacy platform support code. Fixes: a6a71f19fe5e ("net: dsa: isolate legacy code") Signed-off-by: Florian Fainelli Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- net/dsa/dsa.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ net/dsa/legacy.c | 47 ----------------------------------------------- 2 files changed, 47 insertions(+), 47 deletions(-) diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c index 26130ae438da..90038d45a547 100644 --- a/net/dsa/dsa.c +++ b/net/dsa/dsa.c @@ -223,6 +223,53 @@ static int dsa_switch_rcv(struct sk_buff *skb, struct net_device *dev, return 0; } +#ifdef CONFIG_PM_SLEEP +int dsa_switch_suspend(struct dsa_switch *ds) +{ + int i, ret = 0; + + /* Suspend slave network devices */ + for (i = 0; i < ds->num_ports; i++) { + if (!dsa_is_port_initialized(ds, i)) + continue; + + ret = dsa_slave_suspend(ds->ports[i].netdev); + if (ret) + return ret; + } + + if (ds->ops->suspend) + ret = ds->ops->suspend(ds); + + return ret; +} +EXPORT_SYMBOL_GPL(dsa_switch_suspend); + +int dsa_switch_resume(struct dsa_switch *ds) +{ + int i, ret = 0; + + if (ds->ops->resume) + ret = ds->ops->resume(ds); + + if (ret) + return ret; + + /* Resume slave network devices */ + for (i = 0; i < ds->num_ports; i++) { + if (!dsa_is_port_initialized(ds, i)) + continue; + + ret = dsa_slave_resume(ds->ports[i].netdev); + if (ret) + return ret; + } + + return 0; +} +EXPORT_SYMBOL_GPL(dsa_switch_resume); +#endif + static struct packet_type dsa_pack_type __read_mostly = { .type = cpu_to_be16(ETH_P_XDSA), .func = dsa_switch_rcv, diff --git a/net/dsa/legacy.c b/net/dsa/legacy.c index ad345c8b0b06..7281098df04e 100644 --- a/net/dsa/legacy.c +++ b/net/dsa/legacy.c @@ -289,53 +289,6 @@ static void dsa_switch_destroy(struct dsa_switch *ds) dsa_switch_unregister_notifier(ds); } -#ifdef CONFIG_PM_SLEEP -int dsa_switch_suspend(struct dsa_switch *ds) -{ - int i, ret = 0; - - /* Suspend slave network devices */ - for (i = 0; i < ds->num_ports; i++) { - if (!dsa_is_port_initialized(ds, i)) - continue; - - ret = dsa_slave_suspend(ds->ports[i].netdev); - if (ret) - return ret; - } - - if (ds->ops->suspend) - ret = ds->ops->suspend(ds); - - return ret; -} -EXPORT_SYMBOL_GPL(dsa_switch_suspend); - -int dsa_switch_resume(struct dsa_switch *ds) -{ - int i, ret = 0; - - if (ds->ops->resume) - ret = ds->ops->resume(ds); - - if (ret) - return ret; - - /* Resume slave network devices */ - for (i = 0; i < ds->num_ports; i++) { - if (!dsa_is_port_initialized(ds, i)) - continue; - - ret = dsa_slave_resume(ds->ports[i].netdev); - if (ret) - return ret; - } - - return 0; -} -EXPORT_SYMBOL_GPL(dsa_switch_resume); -#endif - /* platform driver init and cleanup *****************************************/ static int dev_is_class(struct device *dev, void *class) { -- cgit v1.2.3 From 75fb636324a839c2c31be9f81644034c6142e469 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 1 Jun 2017 13:54:30 +0200 Subject: drm: Fix oops + Xserver hang when unplugging USB drm devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit a39be606f99d ("drm: Do a full device unregister when unplugging") causes backtraces like this one when unplugging an usb drm device while it is in use: usb 2-3: USB disconnect, device number 25 ------------[ cut here ]------------ WARNING: CPU: 0 PID: 242 at drivers/gpu/drm/drm_mode_config.c:424 drm_mode_config_cleanup+0x220/0x280 [drm] ... RIP: 0010:drm_mode_config_cleanup+0x220/0x280 [drm] ... Call Trace: gm12u320_modeset_cleanup+0xe/0x10 [gm12u320] gm12u320_driver_unload+0x35/0x70 [gm12u320] drm_dev_unregister+0x3c/0xe0 [drm] drm_unplug_dev+0x12/0x60 [drm] gm12u320_usb_disconnect+0x36/0x40 [gm12u320] usb_unbind_interface+0x72/0x280 device_release_driver_internal+0x158/0x210 device_release_driver+0x12/0x20 bus_remove_device+0x104/0x180 device_del+0x1d2/0x350 usb_disable_device+0x9f/0x270 usb_disconnect+0xc6/0x260 ... [drm:drm_mode_config_cleanup [drm]] *ERROR* connector Unknown-1 leaked! ------------[ cut here ]------------ WARNING: CPU: 0 PID: 242 at drivers/gpu/drm/drm_mode_config.c:458 drm_mode_config_cleanup+0x268/0x280 [drm] ... ---[ end trace 80df975dae439ed6 ]--- general protection fault: 0000 [#1] SMP ... Call Trace: ? __switch_to+0x225/0x450 drm_mode_rmfb_work_fn+0x55/0x70 [drm] process_one_work+0x193/0x3c0 worker_thread+0x4a/0x3a0 ... RIP: drm_framebuffer_remove+0x62/0x3f0 [drm] RSP: ffffb776c39dfd98 ---[ end trace 80df975dae439ed7 ]--- After which the system is unusable this is caused by drm_dev_unregister getting called immediately on unplug, which calls the drivers unload function which calls drm_mode_config_cleanup which removes the framebuffer object while userspace is still holding a reference to it. Reverting commit a39be606f99d ("drm: Do a full device unregister when unplugging") leads to the following oops on unplug instead, when userspace closes the last fd referencing the drm_dev: sysfs group 'power' not found for kobject 'card1-Unknown-1' ------------[ cut here ]------------ WARNING: CPU: 0 PID: 2459 at fs/sysfs/group.c:237 sysfs_remove_group+0x80/0x90 ... RIP: 0010:sysfs_remove_group+0x80/0x90 ... Call Trace: dpm_sysfs_remove+0x57/0x60 device_del+0xfd/0x350 device_unregister+0x1a/0x60 drm_sysfs_connector_remove+0x39/0x50 [drm] drm_connector_unregister+0x5a/0x70 [drm] drm_connector_unregister_all+0x45/0xa0 [drm] drm_modeset_unregister_all+0x12/0x30 [drm] drm_dev_unregister+0xca/0xe0 [drm] drm_put_dev+0x32/0x60 [drm] drm_release+0x2f3/0x380 [drm] __fput+0xdf/0x1e0 ... ---[ end trace ecfb91ac85688bbe ]--- BUG: unable to handle kernel NULL pointer dereference at 00000000000000a8 IP: down_write+0x1f/0x40 ... Call Trace: debugfs_remove_recursive+0x55/0x1b0 drm_debugfs_connector_remove+0x21/0x40 [drm] drm_connector_unregister+0x62/0x70 [drm] drm_connector_unregister_all+0x45/0xa0 [drm] drm_modeset_unregister_all+0x12/0x30 [drm] drm_dev_unregister+0xca/0xe0 [drm] drm_put_dev+0x32/0x60 [drm] drm_release+0x2f3/0x380 [drm] __fput+0xdf/0x1e0 ... ---[ end trace ecfb91ac85688bbf ]--- This is caused by the revert moving back to drm_unplug_dev calling drm_minor_unregister which does: device_del(minor->kdev); dev_set_drvdata(minor->kdev, NULL); /* safety belt */ drm_debugfs_cleanup(minor); Causing the sysfs entries to already be removed even though we still have references to them in e.g. drm_connector. Note we must call drm_minor_unregister to notify userspace of the unplug of the device, so calling drm_dev_unregister is not completely wrong the problem is that drm_dev_unregister does too much. This commit fixes drm_unplug_dev by not only reverting commit a39be606f99d ("drm: Do a full device unregister when unplugging") but by also adding a call to drm_modeset_unregister_all before the drm_minor_unregister calls to make sure all sysfs entries are removed before calling device_del(minor->kdev) thereby also fixing the second set of oopses caused by just reverting the commit. Fixes: a39be606f99d ("drm: Do a full device unregister when unplugging") Cc: stable@vger.kernel.org Cc: Chris Wilson Cc: Jeffy Cc: Marco Diego Aurélio Mesquita Reported-by: Marco Diego Aurélio Mesquita Signed-off-by: Hans de Goede Reviewed-by: Chris Wilson Signed-off-by: Sean Paul Link: http://patchwork.freedesktop.org/patch/msgid/20170601115430.4113-1-hdegoede@redhat.com --- drivers/gpu/drm/drm_drv.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index b5c6bb46a425..37b8ad3e30d8 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -358,7 +358,12 @@ EXPORT_SYMBOL(drm_put_dev); void drm_unplug_dev(struct drm_device *dev) { /* for a USB device */ - drm_dev_unregister(dev); + if (drm_core_check_feature(dev, DRIVER_MODESET)) + drm_modeset_unregister_all(dev); + + drm_minor_unregister(dev, DRM_MINOR_PRIMARY); + drm_minor_unregister(dev, DRM_MINOR_RENDER); + drm_minor_unregister(dev, DRM_MINOR_CONTROL); mutex_lock(&drm_global_mutex); -- cgit v1.2.3 From 6e80ac5cc992ab6256c3dae87f7e57db15e1a58c Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 31 May 2017 13:15:41 +0100 Subject: ipv6: xfrm: Handle errors reported by xfrm6_find_1stfragopt() xfrm6_find_1stfragopt() may now return an error code and we must not treat it as a length. Fixes: 2423496af35d ("ipv6: Prevent overrun when parsing v6 header options") Signed-off-by: Ben Hutchings Acked-by: Craig Gallek Signed-off-by: David S. Miller --- net/ipv6/xfrm6_mode_ro.c | 2 ++ net/ipv6/xfrm6_mode_transport.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/net/ipv6/xfrm6_mode_ro.c b/net/ipv6/xfrm6_mode_ro.c index 0e015906f9ca..07d36573f50b 100644 --- a/net/ipv6/xfrm6_mode_ro.c +++ b/net/ipv6/xfrm6_mode_ro.c @@ -47,6 +47,8 @@ static int xfrm6_ro_output(struct xfrm_state *x, struct sk_buff *skb) iph = ipv6_hdr(skb); hdr_len = x->type->hdr_offset(x, skb, &prevhdr); + if (hdr_len < 0) + return hdr_len; skb_set_mac_header(skb, (prevhdr - x->props.header_len) - skb->data); skb_set_network_header(skb, -x->props.header_len); skb->transport_header = skb->network_header + hdr_len; diff --git a/net/ipv6/xfrm6_mode_transport.c b/net/ipv6/xfrm6_mode_transport.c index 7a92c0f31912..9ad07a91708e 100644 --- a/net/ipv6/xfrm6_mode_transport.c +++ b/net/ipv6/xfrm6_mode_transport.c @@ -30,6 +30,8 @@ static int xfrm6_transport_output(struct xfrm_state *x, struct sk_buff *skb) skb_set_inner_transport_header(skb, skb_transport_offset(skb)); hdr_len = x->type->hdr_offset(x, skb, &prevhdr); + if (hdr_len < 0) + return hdr_len; skb_set_mac_header(skb, (prevhdr - x->props.header_len) - skb->data); skb_set_network_header(skb, -x->props.header_len); skb->transport_header = skb->network_header + hdr_len; -- cgit v1.2.3 From e7519f9926f1d0d11c776eb0475eb098c7760f68 Mon Sep 17 00:00:00 2001 From: Ganesh Goudar Date: Wed, 31 May 2017 18:26:28 +0530 Subject: cxgb4: avoid enabling napi twice to the same queue Take uld mutex to avoid race between cxgb_up() and cxgb4_register_uld() to enable napi for the same uld queue. Signed-off-by: Ganesh Goudar Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index b512149684fd..77ed2f628f9c 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -2196,10 +2196,14 @@ static int cxgb_up(struct adapter *adap) if (err) goto irq_err; } + + mutex_lock(&uld_mutex); enable_rx(adap); t4_sge_start(adap); t4_intr_enable(adap); adap->flags |= FULL_INIT_DONE; + mutex_unlock(&uld_mutex); + notify_ulds(adap, CXGB4_STATE_UP); #if IS_ENABLED(CONFIG_IPV6) update_clip(adap); -- cgit v1.2.3 From 44abafc4cc094214a99f860f778c48ecb23422fc Mon Sep 17 00:00:00 2001 From: Yuchung Cheng Date: Wed, 31 May 2017 11:21:27 -0700 Subject: tcp: disallow cwnd undo when switching congestion control When the sender switches its congestion control during loss recovery, if the recovery is spurious then it may incorrectly revert cwnd and ssthresh to the older values set by a previous congestion control. Consider a congestion control (like BBR) that does not use ssthresh and keeps it infinite: the connection may incorrectly revert cwnd to an infinite value when switching from BBR to another congestion control. This patch fixes it by disallowing such cwnd undo operation upon switching congestion control. Note that undo_marker is not reset s.t. the packets that were incorrectly marked lost would be corrected. We only avoid undoing the cwnd in tcp_undo_cwnd_reduction(). Signed-off-by: Yuchung Cheng Signed-off-by: Soheil Hassas Yeganeh Signed-off-by: Neal Cardwell Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/tcp_cong.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c index 6e3c512054a6..324c9bcc5456 100644 --- a/net/ipv4/tcp_cong.c +++ b/net/ipv4/tcp_cong.c @@ -180,6 +180,7 @@ void tcp_init_congestion_control(struct sock *sk) { const struct inet_connection_sock *icsk = inet_csk(sk); + tcp_sk(sk)->prior_ssthresh = 0; if (icsk->icsk_ca_ops->init) icsk->icsk_ca_ops->init(sk); if (tcp_ca_needs_ecn(sk)) -- cgit v1.2.3 From 77032732d0e89b83c3bca75b857a1f63e9efb44b Mon Sep 17 00:00:00 2001 From: Thor Thayer Date: Wed, 31 May 2017 14:28:47 -0500 Subject: net: ethernet: stmmac: Fix altr_tse_pcs SGMII Initialization Fix NETDEV WATCHDOG timeout on startup by adding missing register writes that properly setup SGMII. Signed-off-by: Thor Thayer Acked-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c b/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c index 489ef146201e..6a9c954492f2 100644 --- a/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c +++ b/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c @@ -37,6 +37,7 @@ #define TSE_PCS_CONTROL_AN_EN_MASK BIT(12) #define TSE_PCS_CONTROL_REG 0x00 #define TSE_PCS_CONTROL_RESTART_AN_MASK BIT(9) +#define TSE_PCS_CTRL_AUTONEG_SGMII 0x1140 #define TSE_PCS_IF_MODE_REG 0x28 #define TSE_PCS_LINK_TIMER_0_REG 0x24 #define TSE_PCS_LINK_TIMER_1_REG 0x26 @@ -65,6 +66,7 @@ #define TSE_PCS_SW_RESET_TIMEOUT 100 #define TSE_PCS_USE_SGMII_AN_MASK BIT(1) #define TSE_PCS_USE_SGMII_ENA BIT(0) +#define TSE_PCS_IF_USE_SGMII 0x03 #define SGMII_ADAPTER_CTRL_REG 0x00 #define SGMII_ADAPTER_DISABLE 0x0001 @@ -101,7 +103,9 @@ int tse_pcs_init(void __iomem *base, struct tse_pcs *pcs) { int ret = 0; - writew(TSE_PCS_USE_SGMII_ENA, base + TSE_PCS_IF_MODE_REG); + writew(TSE_PCS_IF_USE_SGMII, base + TSE_PCS_IF_MODE_REG); + + writew(TSE_PCS_CTRL_AUTONEG_SGMII, base + TSE_PCS_CONTROL_REG); writew(TSE_PCS_SGMII_LINK_TIMER_0, base + TSE_PCS_LINK_TIMER_0_REG); writew(TSE_PCS_SGMII_LINK_TIMER_1, base + TSE_PCS_LINK_TIMER_1_REG); -- cgit v1.2.3 From 78b07ac1e4c8acc9daf6b7f7b579300328673640 Mon Sep 17 00:00:00 2001 From: Thomas Falcon Date: Thu, 1 Jun 2017 15:32:34 -0500 Subject: ibmvnic: Remove module author mailing address The original author left the project and so far has not responded to emails sent to the listed address. Signed-off-by: John Allen Signed-off-by: Thomas Falcon Signed-off-by: David S. Miller --- drivers/net/ethernet/ibm/ibmvnic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index 4f2d329dba99..a93757c255f7 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -81,7 +81,7 @@ static const char ibmvnic_driver_name[] = "ibmvnic"; static const char ibmvnic_driver_string[] = "IBM System i/p Virtual NIC Driver"; -MODULE_AUTHOR("Santiago Leon "); +MODULE_AUTHOR("Santiago Leon"); MODULE_DESCRIPTION("IBM System i/p Virtual NIC Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(IBMVNIC_DRIVER_VERSION); -- cgit v1.2.3 From a53cb29b0af346af44e4abf13d7e59f807fba690 Mon Sep 17 00:00:00 2001 From: Mark Bloch Date: Fri, 2 Jun 2017 03:24:08 +0300 Subject: vxlan: fix use-after-free on deletion Adding a vxlan interface to a socket isn't symmetrical, while adding is done in vxlan_open() the deletion is done in vxlan_dellink(). This can cause a use-after-free error when we close the vxlan interface before deleting it. We add vxlan_vs_del_dev() to match vxlan_vs_add_dev() and call it from vxlan_stop() to match the call from vxlan_open(). Fixes: 56ef9c909b40 ("vxlan: Move socket initialization to within rtnl scope") Acked-by: Jiri Benc Tested-by: Roi Dayan Signed-off-by: Mark Bloch Acked-by: Roopa Prabhu Signed-off-by: David S. Miller --- drivers/net/vxlan.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 5c1d69e37870..a6b5052c1d36 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -59,6 +59,8 @@ static const u8 all_zeros_mac[ETH_ALEN + 2]; static int vxlan_sock_add(struct vxlan_dev *vxlan); +static void vxlan_vs_del_dev(struct vxlan_dev *vxlan); + /* per-network namespace private data for this module */ struct vxlan_net { struct list_head vxlan_list; @@ -1081,6 +1083,8 @@ static void vxlan_sock_release(struct vxlan_dev *vxlan) rcu_assign_pointer(vxlan->vn4_sock, NULL); synchronize_net(); + vxlan_vs_del_dev(vxlan); + if (__vxlan_sock_release_prep(sock4)) { udp_tunnel_sock_release(sock4->sock); kfree(sock4); @@ -2356,6 +2360,15 @@ static void vxlan_cleanup(unsigned long arg) mod_timer(&vxlan->age_timer, next_timer); } +static void vxlan_vs_del_dev(struct vxlan_dev *vxlan) +{ + struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id); + + spin_lock(&vn->sock_lock); + hlist_del_init_rcu(&vxlan->hlist); + spin_unlock(&vn->sock_lock); +} + static void vxlan_vs_add_dev(struct vxlan_sock *vs, struct vxlan_dev *vxlan) { struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id); @@ -3300,15 +3313,9 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[], static void vxlan_dellink(struct net_device *dev, struct list_head *head) { struct vxlan_dev *vxlan = netdev_priv(dev); - struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id); vxlan_flush(vxlan, true); - spin_lock(&vn->sock_lock); - if (!hlist_unhashed(&vxlan->hlist)) - hlist_del_rcu(&vxlan->hlist); - spin_unlock(&vn->sock_lock); - gro_cells_destroy(&vxlan->gro_cells); list_del(&vxlan->next); unregister_netdevice_queue(dev, head); -- cgit v1.2.3 From 4bd7ef0b033721b659b9357057e76d1ced95c1da Mon Sep 17 00:00:00 2001 From: "Chopra, Manish" Date: Fri, 2 Jun 2017 06:52:54 -0700 Subject: qlcnic: Fix tunnel offload for 82xx adapters Qlogic's 82xx series adapter doesn't support tunnel offloads, driver incorrectly assumes that it is supported and causes firmware hang while running tunnel IO. This patch fixes this by not advertising tunnel offloads for 82xx adapters. Signed-off-by: Manish Chopra Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 26 ++++++++++++++++++++-- .../net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | 2 ++ drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 2 ++ .../ethernet/qlogic/qlcnic/qlcnic_sriov_common.c | 2 ++ 4 files changed, 30 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h index 7245b1072518..81312924df14 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h @@ -1824,22 +1824,44 @@ struct qlcnic_hardware_ops { u32 (*get_cap_size)(void *, int); void (*set_sys_info)(void *, int, u32); void (*store_cap_mask)(void *, u32); + bool (*encap_rx_offload) (struct qlcnic_adapter *adapter); + bool (*encap_tx_offload) (struct qlcnic_adapter *adapter); }; extern struct qlcnic_nic_template qlcnic_vf_ops; -static inline bool qlcnic_encap_tx_offload(struct qlcnic_adapter *adapter) +static inline bool qlcnic_83xx_encap_tx_offload(struct qlcnic_adapter *adapter) { return adapter->ahw->extra_capability[0] & QLCNIC_83XX_FW_CAPAB_ENCAP_TX_OFFLOAD; } -static inline bool qlcnic_encap_rx_offload(struct qlcnic_adapter *adapter) +static inline bool qlcnic_83xx_encap_rx_offload(struct qlcnic_adapter *adapter) { return adapter->ahw->extra_capability[0] & QLCNIC_83XX_FW_CAPAB_ENCAP_RX_OFFLOAD; } +static inline bool qlcnic_82xx_encap_tx_offload(struct qlcnic_adapter *adapter) +{ + return false; +} + +static inline bool qlcnic_82xx_encap_rx_offload(struct qlcnic_adapter *adapter) +{ + return false; +} + +static inline bool qlcnic_encap_rx_offload(struct qlcnic_adapter *adapter) +{ + return adapter->ahw->hw_ops->encap_rx_offload(adapter); +} + +static inline bool qlcnic_encap_tx_offload(struct qlcnic_adapter *adapter) +{ + return adapter->ahw->hw_ops->encap_tx_offload(adapter); +} + static inline int qlcnic_start_firmware(struct qlcnic_adapter *adapter) { return adapter->nic_ops->start_firmware(adapter); diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c index 4fb68797630e..f7080d0ab874 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c @@ -242,6 +242,8 @@ static struct qlcnic_hardware_ops qlcnic_83xx_hw_ops = { .get_cap_size = qlcnic_83xx_get_cap_size, .set_sys_info = qlcnic_83xx_set_sys_info, .store_cap_mask = qlcnic_83xx_store_cap_mask, + .encap_rx_offload = qlcnic_83xx_encap_rx_offload, + .encap_tx_offload = qlcnic_83xx_encap_tx_offload, }; static struct qlcnic_nic_template qlcnic_83xx_ops = { diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index b6628aaa6e4a..1b5f7d57b6f8 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c @@ -632,6 +632,8 @@ static struct qlcnic_hardware_ops qlcnic_hw_ops = { .get_cap_size = qlcnic_82xx_get_cap_size, .set_sys_info = qlcnic_82xx_set_sys_info, .store_cap_mask = qlcnic_82xx_store_cap_mask, + .encap_rx_offload = qlcnic_82xx_encap_rx_offload, + .encap_tx_offload = qlcnic_82xx_encap_tx_offload, }; static int qlcnic_check_multi_tx_capability(struct qlcnic_adapter *adapter) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c index 2f656f395f39..c58180f40844 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c @@ -77,6 +77,8 @@ static struct qlcnic_hardware_ops qlcnic_sriov_vf_hw_ops = { .free_mac_list = qlcnic_sriov_vf_free_mac_list, .enable_sds_intr = qlcnic_83xx_enable_sds_intr, .disable_sds_intr = qlcnic_83xx_disable_sds_intr, + .encap_rx_offload = qlcnic_83xx_encap_rx_offload, + .encap_tx_offload = qlcnic_83xx_encap_tx_offload, }; static struct qlcnic_nic_template qlcnic_sriov_vf_ops = { -- cgit v1.2.3 From f0c3192ceee3c16154e70dfb373f66ed86c6fea9 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Fri, 2 Jun 2017 17:54:33 +0300 Subject: virtio_net: lower limit on buffer size commit d85b758f72b0 ("virtio_net: fix support for small rings") was supposed to increase the buffer size for small rings but had an unintentional side effect of decreasing it for large rings. This seems to break some setups - it's not yet clear why, but increasing buffer size back to what it was before helps. Fixes: d85b758f72b0 ("virtio_net: fix support for small rings") Reported-by: Mikulas Patocka Reported-by: "J. Bruce Fields" Tested-by: Mikulas Patocka Tested-by: "J. Bruce Fields" Signed-off-by: Michael S. Tsirkin Signed-off-by: David S. Miller --- drivers/net/virtio_net.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 3e9246cc49c3..a871f45ecc79 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -869,7 +869,7 @@ static unsigned int get_mergeable_buf_len(struct receive_queue *rq, unsigned int len; len = hdr_len + clamp_t(unsigned int, ewma_pkt_len_read(avg_pkt_len), - rq->min_buf_len - hdr_len, PAGE_SIZE - hdr_len); + rq->min_buf_len, PAGE_SIZE - hdr_len); return ALIGN(len, L1_CACHE_BYTES); } @@ -2144,7 +2144,8 @@ static unsigned int mergeable_min_buf_len(struct virtnet_info *vi, struct virtqu unsigned int buf_len = hdr_len + ETH_HLEN + VLAN_HLEN + packet_len; unsigned int min_buf_len = DIV_ROUND_UP(buf_len, rq_size); - return max(min_buf_len, hdr_len); + return max(max(min_buf_len, hdr_len) - hdr_len, + (unsigned int)GOOD_PACKET_LEN); } static int virtnet_find_vqs(struct virtnet_info *vi) -- cgit v1.2.3 From e0f8e8cf3bf9305f36155a5ac6e16b3b910e6cec Mon Sep 17 00:00:00 2001 From: Varun Prakash Date: Sat, 27 May 2017 20:22:51 +0530 Subject: scsi: cxgb4i: libcxgbi: in error case RST tcp conn If logout response is not received and ->ep_disconnect() is called then close tcp conn by RST instead of FIN to cleanup conn resources immediately. Also move ->csk_push_tx_frames() above 'done:' to avoid calling ->csk_push_tx_frames() in error cases. Signed-off-by: Varun Prakash Signed-off-by: Martin K. Petersen --- drivers/scsi/cxgbi/cxgb4i/cxgb4i.c | 1 - drivers/scsi/cxgbi/libcxgbi.c | 29 ++++++++++++++++++++++------- drivers/scsi/cxgbi/libcxgbi.h | 1 + 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c index 1076c1578322..0aae094ab91c 100644 --- a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c +++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c @@ -1595,7 +1595,6 @@ static void release_offload_resources(struct cxgbi_sock *csk) cxgbi_sock_put(csk); } csk->dst = NULL; - csk->cdev = NULL; } static int init_act_open(struct cxgbi_sock *csk) diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c index fb06974c88c1..e4c83b7c96a8 100644 --- a/drivers/scsi/cxgbi/libcxgbi.c +++ b/drivers/scsi/cxgbi/libcxgbi.c @@ -867,7 +867,8 @@ static void need_active_close(struct cxgbi_sock *csk) log_debug(1 << CXGBI_DBG_SOCK, "csk 0x%p,%u,0x%lx,%u.\n", csk, (csk)->state, (csk)->flags, (csk)->tid); spin_lock_bh(&csk->lock); - dst_confirm(csk->dst); + if (csk->dst) + dst_confirm(csk->dst); data_lost = skb_queue_len(&csk->receive_queue); __skb_queue_purge(&csk->receive_queue); @@ -882,7 +883,8 @@ static void need_active_close(struct cxgbi_sock *csk) } if (close_req) { - if (data_lost) + if (!cxgbi_sock_flag(csk, CTPF_LOGOUT_RSP_RCVD) || + data_lost) csk->cdev->csk_send_abort_req(csk); else csk->cdev->csk_send_close_req(csk); @@ -1186,9 +1188,10 @@ static int cxgbi_sock_send_pdus(struct cxgbi_sock *csk, struct sk_buff *skb) cxgbi_ulp_extra_len(cxgbi_skcb_ulp_mode(skb)); skb = next; } -done: + if (likely(skb_queue_len(&csk->write_queue))) cdev->csk_push_tx_frames(csk, 1); +done: spin_unlock_bh(&csk->lock); return copied; @@ -1568,9 +1571,12 @@ static inline int read_pdu_skb(struct iscsi_conn *conn, } } -static int skb_read_pdu_bhs(struct iscsi_conn *conn, struct sk_buff *skb) +static int +skb_read_pdu_bhs(struct cxgbi_sock *csk, struct iscsi_conn *conn, + struct sk_buff *skb) { struct iscsi_tcp_conn *tcp_conn = conn->dd_data; + int err; log_debug(1 << CXGBI_DBG_PDU_RX, "conn 0x%p, skb 0x%p, len %u, flag 0x%lx.\n", @@ -1608,7 +1614,16 @@ static int skb_read_pdu_bhs(struct iscsi_conn *conn, struct sk_buff *skb) } } - return read_pdu_skb(conn, skb, 0, 0); + err = read_pdu_skb(conn, skb, 0, 0); + if (likely(err >= 0)) { + struct iscsi_hdr *hdr = (struct iscsi_hdr *)skb->data; + u8 opcode = hdr->opcode & ISCSI_OPCODE_MASK; + + if (unlikely(opcode == ISCSI_OP_LOGOUT_RSP)) + cxgbi_sock_set_flag(csk, CTPF_LOGOUT_RSP_RCVD); + } + + return err; } static int skb_read_pdu_data(struct iscsi_conn *conn, struct sk_buff *lskb, @@ -1713,7 +1728,7 @@ void cxgbi_conn_pdu_ready(struct cxgbi_sock *csk) cxgbi_skcb_rx_pdulen(skb)); if (cxgbi_skcb_test_flag(skb, SKCBF_RX_COALESCED)) { - err = skb_read_pdu_bhs(conn, skb); + err = skb_read_pdu_bhs(csk, conn, skb); if (err < 0) { pr_err("coalesced bhs, csk 0x%p, skb 0x%p,%u, " "f 0x%lx, plen %u.\n", @@ -1731,7 +1746,7 @@ void cxgbi_conn_pdu_ready(struct cxgbi_sock *csk) cxgbi_skcb_flags(skb), cxgbi_skcb_rx_pdulen(skb)); } else { - err = skb_read_pdu_bhs(conn, skb); + err = skb_read_pdu_bhs(csk, conn, skb); if (err < 0) { pr_err("bhs, csk 0x%p, skb 0x%p,%u, " "f 0x%lx, plen %u.\n", diff --git a/drivers/scsi/cxgbi/libcxgbi.h b/drivers/scsi/cxgbi/libcxgbi.h index 239462a75760..37f07aaab1e4 100644 --- a/drivers/scsi/cxgbi/libcxgbi.h +++ b/drivers/scsi/cxgbi/libcxgbi.h @@ -187,6 +187,7 @@ enum cxgbi_sock_flags { CTPF_HAS_ATID, /* reserved atid */ CTPF_HAS_TID, /* reserved hw tid */ CTPF_OFFLOAD_DOWN, /* offload function off */ + CTPF_LOGOUT_RSP_RCVD, /* received logout response */ }; struct cxgbi_skb_rx_cb { -- cgit v1.2.3 From a7306c3436e9c8e584a4b9fad5f3dc91be2a6076 Mon Sep 17 00:00:00 2001 From: Andrea Arcangeli Date: Fri, 2 Jun 2017 14:46:11 -0700 Subject: ksm: prevent crash after write_protect_page fails "err" needs to be left set to -EFAULT if split_huge_page succeeds. Otherwise if "err" gets clobbered with zero and write_protect_page fails, try_to_merge_one_page() will succeed instead of returning -EFAULT and then try_to_merge_with_ksm_page() will continue thinking kpage is a PageKsm when in fact it's still an anonymous page. Eventually it'll crash in page_add_anon_rmap. This has been reproduced on Fedora25 kernel but I can reproduce with upstream too. The bug was introduced in commit f765f540598a ("ksm: prepare to new THP semantics") introduced in v4.5. page:fffff67546ce1cc0 count:4 mapcount:2 mapping:ffffa094551e36e1 index:0x7f0f46673 flags: 0x2ffffc0004007c(referenced|uptodate|dirty|lru|active|swapbacked) page dumped because: VM_BUG_ON_PAGE(!PageLocked(page)) page->mem_cgroup:ffffa09674bf0000 ------------[ cut here ]------------ kernel BUG at mm/rmap.c:1222! CPU: 1 PID: 76 Comm: ksmd Not tainted 4.9.3-200.fc25.x86_64 #1 RIP: do_page_add_anon_rmap+0x1c4/0x240 Call Trace: page_add_anon_rmap+0x18/0x20 try_to_merge_with_ksm_page+0x50b/0x780 ksm_scan_thread+0x1211/0x1410 ? prepare_to_wait_event+0x100/0x100 ? try_to_merge_with_ksm_page+0x780/0x780 kthread+0xd9/0xf0 ? kthread_park+0x60/0x60 ret_from_fork+0x25/0x30 Fixes: f765f54059 ("ksm: prepare to new THP semantics") Link: http://lkml.kernel.org/r/20170513131040.21732-1-aarcange@redhat.com Signed-off-by: Andrea Arcangeli Reported-by: Federico Simoncelli Acked-by: Kirill A. Shutemov Cc: Hugh Dickins Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/ksm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mm/ksm.c b/mm/ksm.c index d9fc0e456128..216184af0e19 100644 --- a/mm/ksm.c +++ b/mm/ksm.c @@ -1028,8 +1028,7 @@ static int try_to_merge_one_page(struct vm_area_struct *vma, goto out; if (PageTransCompound(page)) { - err = split_huge_page(page); - if (err) + if (split_huge_page(page)) goto out_unlock; } -- cgit v1.2.3 From 1bde33e051233f0ed93a8bc67137016ab38c3d2d Mon Sep 17 00:00:00 2001 From: Michal Hocko Date: Fri, 2 Jun 2017 14:46:13 -0700 Subject: include/linux/gfp.h: fix ___GFP_NOLOCKDEP value Igor Stoppa has noticed that __GFP_NOLOCKDEP can use a lower bit. At the time commit 7e7844226f10 ("lockdep: allow to disable reclaim lockup detection") was written we still had __GFP_OTHER_NODE but I have removed it in commit 41b6167e8f74 ("mm: get rid of __GFP_OTHER_NODE") and forgot to lower the bit value. The current value is outside of __GFP_BITS_SHIFT so it cannot be used actually. Fixes: 7e7844226f10 ("lockdep: allow to disable reclaim lockup detection") Signed-off-by: Michal Hocko Reported-by: Igor Stoppa Acked-by: Vlastimil Babka Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/gfp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/gfp.h b/include/linux/gfp.h index 2b1a44f5bdb6..a89d37e8b387 100644 --- a/include/linux/gfp.h +++ b/include/linux/gfp.h @@ -41,7 +41,7 @@ struct vm_area_struct; #define ___GFP_WRITE 0x800000u #define ___GFP_KSWAPD_RECLAIM 0x1000000u #ifdef CONFIG_LOCKDEP -#define ___GFP_NOLOCKDEP 0x4000000u +#define ___GFP_NOLOCKDEP 0x2000000u #else #define ___GFP_NOLOCKDEP 0 #endif -- cgit v1.2.3 From 60b0a8c3d2480f3b57282b47b7cae7ee71c48635 Mon Sep 17 00:00:00 2001 From: Matthias Kaehlcke Date: Fri, 2 Jun 2017 14:46:16 -0700 Subject: frv: declare jiffies to be located in the .data section Commit 7c30f352c852 ("jiffies.h: declare jiffies and jiffies_64 with ____cacheline_aligned_in_smp") removed a section specification from the jiffies declaration that caused conflicts on some platforms. Unfortunately this change broke the build for frv: kernel/built-in.o: In function `__do_softirq': (.text+0x6460): relocation truncated to fit: R_FRV_GPREL12 against symbol `jiffies' defined in *ABS* section in .tmp_vmlinux1 kernel/built-in.o: In function `__do_softirq': (.text+0x6574): relocation truncated to fit: R_FRV_GPREL12 against symbol `jiffies' defined in *ABS* section in .tmp_vmlinux1 kernel/built-in.o: In function `pwq_activate_delayed_work': workqueue.c:(.text+0x15b9c): relocation truncated to fit: R_FRV_GPREL12 against symbol `jiffies' defined in *ABS* section in .tmp_vmlinux1 ... Add __jiffy_arch_data to the declaration of jiffies and use it on frv to include the section specification. For all other platforms __jiffy_arch_data (currently) has no effect. Fixes: 7c30f352c852 ("jiffies.h: declare jiffies and jiffies_64 with ____cacheline_aligned_in_smp") Link: http://lkml.kernel.org/r/20170516221333.177280-1-mka@chromium.org Signed-off-by: Matthias Kaehlcke Reported-by: Guenter Roeck Tested-by: Guenter Roeck Reviewed-by: David Howells Cc: Sudip Mukherjee Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/frv/include/asm/timex.h | 6 ++++++ include/linux/jiffies.h | 6 +++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/arch/frv/include/asm/timex.h b/arch/frv/include/asm/timex.h index a89bddefdacf..139093fab326 100644 --- a/arch/frv/include/asm/timex.h +++ b/arch/frv/include/asm/timex.h @@ -16,5 +16,11 @@ static inline cycles_t get_cycles(void) #define vxtime_lock() do {} while (0) #define vxtime_unlock() do {} while (0) +/* This attribute is used in include/linux/jiffies.h alongside with + * __cacheline_aligned_in_smp. It is assumed that __cacheline_aligned_in_smp + * for frv does not contain another section specification. + */ +#define __jiffy_arch_data __attribute__((__section__(".data"))) + #endif diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h index 36872fbb815d..734377ad42e9 100644 --- a/include/linux/jiffies.h +++ b/include/linux/jiffies.h @@ -64,13 +64,17 @@ extern int register_refined_jiffies(long clock_tick_rate); /* TICK_USEC is the time between ticks in usec assuming fake USER_HZ */ #define TICK_USEC ((1000000UL + USER_HZ/2) / USER_HZ) +#ifndef __jiffy_arch_data +#define __jiffy_arch_data +#endif + /* * The 64-bit value is not atomic - you MUST NOT read it * without sampling the sequence number in jiffies_lock. * get_jiffies_64() will do this for you as appropriate. */ extern u64 __cacheline_aligned_in_smp jiffies_64; -extern unsigned long volatile __cacheline_aligned_in_smp jiffies; +extern unsigned long volatile __cacheline_aligned_in_smp __jiffy_arch_data jiffies; #if (BITS_PER_LONG < 64) u64 get_jiffies_64(void); -- cgit v1.2.3 From 4f4f2ba9c531b3d7cee293dd3654ba3b86e7d220 Mon Sep 17 00:00:00 2001 From: Michal Hocko Date: Fri, 2 Jun 2017 14:46:19 -0700 Subject: mm: clarify why we want kmalloc before falling backto vmallock While converting drm_[cm]alloc* helpers to kvmalloc* variants Chris Wilson has wondered why we want to try kmalloc before vmalloc fallback even for larger allocations requests. Let's clarify that one larger physically contiguous block is less likely to fragment memory than many scattered pages which can prevent more large blocks from being created. [akpm@linux-foundation.org: coding-style fixes] Link: http://lkml.kernel.org/r/20170517080932.21423-1-mhocko@kernel.org Signed-off-by: Michal Hocko Suggested-by: Chris Wilson Reviewed-by: Chris Wilson Acked-by: Vlastimil Babka Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/util.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/mm/util.c b/mm/util.c index 464df3489903..26be6407abd7 100644 --- a/mm/util.c +++ b/mm/util.c @@ -357,8 +357,11 @@ void *kvmalloc_node(size_t size, gfp_t flags, int node) WARN_ON_ONCE((flags & GFP_KERNEL) != GFP_KERNEL); /* - * Make sure that larger requests are not too disruptive - no OOM - * killer and no allocation failure warnings as we have a fallback + * We want to attempt a large physically contiguous block first because + * it is less likely to fragment multiple larger blocks and therefore + * contribute to a long term fragmentation less than vmalloc fallback. + * However make sure that larger requests are not too disruptive - no + * OOM killer and no allocation failure warnings as we have a fallback. */ if (size > PAGE_SIZE) { kmalloc_flags |= __GFP_NOWARN; -- cgit v1.2.3 From 57ddfdaa9a72fe726a44d26d99db31bc137dbeff Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 2 Jun 2017 14:46:22 -0700 Subject: initramfs: fix disabling of initramfs (and its compression) Commit db2aa7fd15e8 ("initramfs: allow again choice of the embedded initram compression algorithm") introduced the possibility to select the initramfs compression algorithm from Kconfig and while this is a nice feature it broke the use case described below. Here is what my build system does: - kernel is initially configured not to have an initramfs included - build the user space root file system - re-configure the kernel to have an initramfs included (CONFIG_INITRAMFS_SOURCE="/path/to/romfs") and set relevant CONFIG_INITRAMFS options, in my case, no compression option (CONFIG_INITRAMFS_COMPRESSION_NONE) - kernel is re-built with these options -> kernel+initramfs image is copied - kernel is re-built again without these options -> kernel image is copied Building a kernel without an initramfs means setting this option: CONFIG_INITRAMFS_SOURCE="" (and this one only) whereas building a kernel with an initramfs means setting these options: CONFIG_INITRAMFS_SOURCE="/home/fainelli/work/uclinux-rootfs/romfs /home/fainelli/work/uclinux-rootfs/misc/initramfs.dev" CONFIG_INITRAMFS_ROOT_UID=1000 CONFIG_INITRAMFS_ROOT_GID=1000 CONFIG_INITRAMFS_COMPRESSION_NONE=y CONFIG_INITRAMFS_COMPRESSION="" Commit db2aa7fd15e85 ("initramfs: allow again choice of the embedded initram compression algorithm") is problematic because CONFIG_INITRAMFS_COMPRESSION which is used to determine the initramfs_data.cpio extension/compression is a string, and due to how Kconfig works it will evaluate in order, how to assign it. Setting CONFIG_INITRAMFS_COMPRESSION_NONE with CONFIG_INITRAMFS_SOURCE="" cannot possibly work (because of the depends on INITRAMFS_SOURCE!="" imposed on CONFIG_INITRAMFS_COMPRESSION ) yet we still get CONFIG_INITRAMFS_COMPRESSION assigned to ".gz" because CONFIG_RD_GZIP=y is set in my kernel, even when there is no initramfs being built. So we basically end-up generating two initramfs_data.cpio* files, one without extension, and one with .gz. This causes usr/Makefile to track usr/initramfs_data.cpio.gz, and not usr/initramfs_data.cpio anymore, that is also largely problematic after 9e3596b0c6539e ("kbuild: initramfs cleanup, set target from Kconfig") because we used to track all possible initramfs_data files in the $(targets) variable before that commit. The end result is that the kernel with an initramfs clearly does not contain what we expect it to, it has a stale initramfs_data.cpio file built into it, and we keep re-generating an initramfs_data.cpio.gz file which is not the one that we want to include in the kernel image proper. The fix consists in hiding CONFIG_INITRAMFS_COMPRESSION when CONFIG_INITRAMFS_SOURCE="". This puts us back in a state to the pre-4.10 behavior where we can properly disable and re-enable initramfs within the same kernel .config file, and be in control of what CONFIG_INITRAMFS_COMPRESSION is set to. Fixes: db2aa7fd15e8 ("initramfs: allow again choice of the embedded initram compression algorithm") Fixes: 9e3596b0c653 ("kbuild: initramfs cleanup, set target from Kconfig") Link: http://lkml.kernel.org/r/20170521033337.6197-1-f.fainelli@gmail.com Signed-off-by: Florian Fainelli Acked-by: Nicholas Piggin Cc: P J P Cc: Paul Bolle Cc: Michal Marek Cc: Daniel Thompson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- usr/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/usr/Kconfig b/usr/Kconfig index c0c48507e44e..ad0543e21760 100644 --- a/usr/Kconfig +++ b/usr/Kconfig @@ -220,6 +220,7 @@ config INITRAMFS_COMPRESSION_LZ4 endchoice config INITRAMFS_COMPRESSION + depends on INITRAMFS_SOURCE!="" string default "" if INITRAMFS_COMPRESSION_NONE default ".gz" if INITRAMFS_COMPRESSION_GZIP -- cgit v1.2.3 From 478fe3037b2278d276d4cd9cd0ab06c4cb2e9b32 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 2 Jun 2017 14:46:25 -0700 Subject: slub/memcg: cure the brainless abuse of sysfs attributes memcg_propagate_slab_attrs() abuses the sysfs attribute file functions to propagate settings from the root kmem_cache to a newly created kmem_cache. It does that with: attr->show(root, buf); attr->store(new, buf, strlen(bug); Aside of being a lazy and absurd hackery this is broken because it does not check the return value of the show() function. Some of the show() functions return 0 w/o touching the buffer. That means in such a case the store function is called with the stale content of the previous show(). That causes nonsense like invoking kmem_cache_shrink() on a newly created kmem_cache. In the worst case it would cause handing in an uninitialized buffer. This should be rewritten proper by adding a propagate() callback to those slub_attributes which must be propagated and avoid that insane conversion to and from ASCII, but that's too large for a hot fix. Check at least the return value of the show() function, so calling store() with stale content is prevented. Steven said: "It can cause a deadlock with get_online_cpus() that has been uncovered by recent cpu hotplug and lockdep changes that Thomas and Peter have been doing. Possible unsafe locking scenario: CPU0 CPU1 ---- ---- lock(cpu_hotplug.lock); lock(slab_mutex); lock(cpu_hotplug.lock); lock(slab_mutex); *** DEADLOCK ***" Link: http://lkml.kernel.org/r/alpine.DEB.2.20.1705201244540.2255@nanos Signed-off-by: Thomas Gleixner Reported-by: Steven Rostedt Acked-by: David Rientjes Cc: Johannes Weiner Cc: Michal Hocko Cc: Peter Zijlstra Cc: Christoph Lameter Cc: Pekka Enberg Cc: Joonsoo Kim Cc: Christoph Hellwig Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/slub.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mm/slub.c b/mm/slub.c index 57e5156f02be..7449593fca72 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -5512,6 +5512,7 @@ static void memcg_propagate_slab_attrs(struct kmem_cache *s) char mbuf[64]; char *buf; struct slab_attribute *attr = to_slab_attr(slab_attrs[i]); + ssize_t len; if (!attr || !attr->store || !attr->show) continue; @@ -5536,8 +5537,9 @@ static void memcg_propagate_slab_attrs(struct kmem_cache *s) buf = buffer; } - attr->show(root_cache, buf); - attr->store(s, buf, strlen(buf)); + len = attr->show(root_cache, buf); + if (len > 0) + attr->store(s, buf, len); } if (buffer) -- cgit v1.2.3 From ff5a20169b98d84ad8d7f99f27c5ebbb008204d6 Mon Sep 17 00:00:00 2001 From: Nicolas Iooss Date: Fri, 2 Jun 2017 14:46:28 -0700 Subject: pcmcia: remove left-over %Z format Commit 5b5e0928f742 ("lib/vsprintf.c: remove %Z support") removed some usages of format %Z but forgot "%.2Zx". This makes clang 4.0 reports a -Wformat-extra-args warning because it does not know about %Z. Replace %Z with %z. Link: http://lkml.kernel.org/r/20170520090946.22562-1-nicolas.iooss_linux@m4x.org Signed-off-by: Nicolas Iooss Cc: Harald Welte Cc: Alexey Dobriyan Cc: [4.11+] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/pcmcia/cm4040_cs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c index d4dbd8d8e524..382c864814d9 100644 --- a/drivers/char/pcmcia/cm4040_cs.c +++ b/drivers/char/pcmcia/cm4040_cs.c @@ -374,7 +374,7 @@ static ssize_t cm4040_write(struct file *filp, const char __user *buf, rc = write_sync_reg(SCR_HOST_TO_READER_START, dev); if (rc <= 0) { - DEBUGP(5, dev, "write_sync_reg c=%.2Zx\n", rc); + DEBUGP(5, dev, "write_sync_reg c=%.2zx\n", rc); DEBUGP(2, dev, "<- cm4040_write (failed)\n"); if (rc == -ERESTARTSYS) return rc; @@ -387,7 +387,7 @@ static ssize_t cm4040_write(struct file *filp, const char __user *buf, for (i = 0; i < bytes_to_write; i++) { rc = wait_for_bulk_out_ready(dev); if (rc <= 0) { - DEBUGP(5, dev, "wait_for_bulk_out_ready rc=%.2Zx\n", + DEBUGP(5, dev, "wait_for_bulk_out_ready rc=%.2zx\n", rc); DEBUGP(2, dev, "<- cm4040_write (failed)\n"); if (rc == -ERESTARTSYS) @@ -403,7 +403,7 @@ static ssize_t cm4040_write(struct file *filp, const char __user *buf, rc = write_sync_reg(SCR_HOST_TO_READER_DONE, dev); if (rc <= 0) { - DEBUGP(5, dev, "write_sync_reg c=%.2Zx\n", rc); + DEBUGP(5, dev, "write_sync_reg c=%.2zx\n", rc); DEBUGP(2, dev, "<- cm4040_write (failed)\n"); if (rc == -ERESTARTSYS) return rc; -- cgit v1.2.3 From c288983dddf714216428774e022ad78f48dd8cb1 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Fri, 2 Jun 2017 14:46:31 -0700 Subject: mm/page_alloc.c: make sure OOM victim can try allocations with no watermarks once Roman Gushchin has reported that the OOM killer can trivially selects next OOM victim when a thread doing memory allocation from page fault path was selected as first OOM victim. allocate invoked oom-killer: gfp_mask=0x14280ca(GFP_HIGHUSER_MOVABLE|__GFP_ZERO), nodemask=(null), order=0, oom_score_adj=0 allocate cpuset=/ mems_allowed=0 CPU: 1 PID: 492 Comm: allocate Not tainted 4.12.0-rc1-mm1+ #181 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Ubuntu-1.8.2-1ubuntu1 04/01/2014 Call Trace: oom_kill_process+0x219/0x3e0 out_of_memory+0x11d/0x480 __alloc_pages_slowpath+0xc84/0xd40 __alloc_pages_nodemask+0x245/0x260 alloc_pages_vma+0xa2/0x270 __handle_mm_fault+0xca9/0x10c0 handle_mm_fault+0xf3/0x210 __do_page_fault+0x240/0x4e0 trace_do_page_fault+0x37/0xe0 do_async_page_fault+0x19/0x70 async_page_fault+0x28/0x30 ... Out of memory: Kill process 492 (allocate) score 899 or sacrifice child Killed process 492 (allocate) total-vm:2052368kB, anon-rss:1894576kB, file-rss:4kB, shmem-rss:0kB allocate: page allocation failure: order:0, mode:0x14280ca(GFP_HIGHUSER_MOVABLE|__GFP_ZERO), nodemask=(null) allocate cpuset=/ mems_allowed=0 CPU: 1 PID: 492 Comm: allocate Not tainted 4.12.0-rc1-mm1+ #181 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Ubuntu-1.8.2-1ubuntu1 04/01/2014 Call Trace: __alloc_pages_slowpath+0xd32/0xd40 __alloc_pages_nodemask+0x245/0x260 alloc_pages_vma+0xa2/0x270 __handle_mm_fault+0xca9/0x10c0 handle_mm_fault+0xf3/0x210 __do_page_fault+0x240/0x4e0 trace_do_page_fault+0x37/0xe0 do_async_page_fault+0x19/0x70 async_page_fault+0x28/0x30 ... oom_reaper: reaped process 492 (allocate), now anon-rss:0kB, file-rss:0kB, shmem-rss:0kB ... allocate invoked oom-killer: gfp_mask=0x0(), nodemask=(null), order=0, oom_score_adj=0 allocate cpuset=/ mems_allowed=0 CPU: 1 PID: 492 Comm: allocate Not tainted 4.12.0-rc1-mm1+ #181 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Ubuntu-1.8.2-1ubuntu1 04/01/2014 Call Trace: oom_kill_process+0x219/0x3e0 out_of_memory+0x11d/0x480 pagefault_out_of_memory+0x68/0x80 mm_fault_error+0x8f/0x190 ? handle_mm_fault+0xf3/0x210 __do_page_fault+0x4b2/0x4e0 trace_do_page_fault+0x37/0xe0 do_async_page_fault+0x19/0x70 async_page_fault+0x28/0x30 ... Out of memory: Kill process 233 (firewalld) score 10 or sacrifice child Killed process 233 (firewalld) total-vm:246076kB, anon-rss:20956kB, file-rss:0kB, shmem-rss:0kB There is a race window that the OOM reaper completes reclaiming the first victim's memory while nothing but mutex_trylock() prevents the first victim from calling out_of_memory() from pagefault_out_of_memory() after memory allocation for page fault path failed due to being selected as an OOM victim. This is a side effect of commit 9a67f6488eca926f ("mm: consolidate GFP_NOFAIL checks in the allocator slowpath") because that commit silently changed the behavior from /* Avoid allocations with no watermarks from looping endlessly */ to /* * Give up allocations without trying memory reserves if selected * as an OOM victim */ in __alloc_pages_slowpath() by moving the location to check TIF_MEMDIE flag. I have noticed this change but I didn't post a patch because I thought it is an acceptable change other than noise by warn_alloc() because !__GFP_NOFAIL allocations are allowed to fail. But we overlooked that failing memory allocation from page fault path makes difference due to the race window explained above. While it might be possible to add a check to pagefault_out_of_memory() that prevents the first victim from calling out_of_memory() or remove out_of_memory() from pagefault_out_of_memory(), changing pagefault_out_of_memory() does not suppress noise by warn_alloc() when allocating thread was selected as an OOM victim. There is little point with printing similar backtraces and memory information from both out_of_memory() and warn_alloc(). Instead, if we guarantee that current thread can try allocations with no watermarks once when current thread looping inside __alloc_pages_slowpath() was selected as an OOM victim, we can follow "who can use memory reserves" rules and suppress noise by warn_alloc() and prevent memory allocations from page fault path from calling pagefault_out_of_memory(). If we take the comment literally, this patch would do - if (test_thread_flag(TIF_MEMDIE)) - goto nopage; + if (alloc_flags == ALLOC_NO_WATERMARKS || (gfp_mask & __GFP_NOMEMALLOC)) + goto nopage; because gfp_pfmemalloc_allowed() returns false if __GFP_NOMEMALLOC is given. But if I recall correctly (I couldn't find the message), the condition is meant to apply to only OOM victims despite the comment. Therefore, this patch preserves TIF_MEMDIE check. Fixes: 9a67f6488eca926f ("mm: consolidate GFP_NOFAIL checks in the allocator slowpath") Link: http://lkml.kernel.org/r/201705192112.IAF69238.OQOHSJLFOFFMtV@I-love.SAKURA.ne.jp Signed-off-by: Tetsuo Handa Reported-by: Roman Gushchin Tested-by: Roman Gushchin Acked-by: Michal Hocko Cc: Johannes Weiner Cc: Vladimir Davydov Cc: [4.11] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/page_alloc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index f9e450c6b6e4..b7a6f583a373 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -3870,7 +3870,9 @@ retry: goto got_pg; /* Avoid allocations with no watermarks from looping endlessly */ - if (test_thread_flag(TIF_MEMDIE)) + if (test_thread_flag(TIF_MEMDIE) && + (alloc_flags == ALLOC_NO_WATERMARKS || + (gfp_mask & __GFP_NOMEMALLOC))) goto nopage; /* Retry as long as the OOM killer is making progress */ -- cgit v1.2.3 From d0f0931de936a0a468d7e59284d39581c16d3a73 Mon Sep 17 00:00:00 2001 From: Ross Zwisler Date: Fri, 2 Jun 2017 14:46:34 -0700 Subject: mm: avoid spurious 'bad pmd' warning messages When the pmd_devmap() checks were added by 5c7fb56e5e3f ("mm, dax: dax-pmd vs thp-pmd vs hugetlbfs-pmd") to add better support for DAX huge pages, they were all added to the end of if() statements after existing pmd_trans_huge() checks. So, things like: - if (pmd_trans_huge(*pmd)) + if (pmd_trans_huge(*pmd) || pmd_devmap(*pmd)) When further checks were added after pmd_trans_unstable() checks by commit 7267ec008b5c ("mm: postpone page table allocation until we have page to map") they were also added at the end of the conditional: + if (pmd_trans_unstable(fe->pmd) || pmd_devmap(*fe->pmd)) This ordering is fine for pmd_trans_huge(), but doesn't work for pmd_trans_unstable(). This is because DAX huge pages trip the bad_pmd() check inside of pmd_none_or_trans_huge_or_clear_bad() (called by pmd_trans_unstable()), which prints out a warning and returns 1. So, we do end up doing the right thing, but only after spamming dmesg with suspicious looking messages: mm/pgtable-generic.c:39: bad pmd ffff8808daa49b88(84000001006000a5) Reorder these checks in a helper so that pmd_devmap() is checked first, avoiding the error messages, and add a comment explaining why the ordering is important. Fixes: commit 7267ec008b5c ("mm: postpone page table allocation until we have page to map") Link: http://lkml.kernel.org/r/20170522215749.23516-1-ross.zwisler@linux.intel.com Signed-off-by: Ross Zwisler Reviewed-by: Jan Kara Cc: Pawel Lebioda Cc: "Darrick J. Wong" Cc: Alexander Viro Cc: Christoph Hellwig Cc: Dan Williams Cc: Dave Hansen Cc: Matthew Wilcox Cc: "Kirill A . Shutemov" Cc: Dave Jiang Cc: Xiong Zhou Cc: Eryu Guan Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memory.c | 40 ++++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/mm/memory.c b/mm/memory.c index 6ff5d729ded0..2e65df1831d9 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -3029,6 +3029,17 @@ static int __do_fault(struct vm_fault *vmf) return ret; } +/* + * The ordering of these checks is important for pmds with _PAGE_DEVMAP set. + * If we check pmd_trans_unstable() first we will trip the bad_pmd() check + * inside of pmd_none_or_trans_huge_or_clear_bad(). This will end up correctly + * returning 1 but not before it spams dmesg with the pmd_clear_bad() output. + */ +static int pmd_devmap_trans_unstable(pmd_t *pmd) +{ + return pmd_devmap(*pmd) || pmd_trans_unstable(pmd); +} + static int pte_alloc_one_map(struct vm_fault *vmf) { struct vm_area_struct *vma = vmf->vma; @@ -3052,18 +3063,27 @@ static int pte_alloc_one_map(struct vm_fault *vmf) map_pte: /* * If a huge pmd materialized under us just retry later. Use - * pmd_trans_unstable() instead of pmd_trans_huge() to ensure the pmd - * didn't become pmd_trans_huge under us and then back to pmd_none, as - * a result of MADV_DONTNEED running immediately after a huge pmd fault - * in a different thread of this mm, in turn leading to a misleading - * pmd_trans_huge() retval. All we have to ensure is that it is a - * regular pmd that we can walk with pte_offset_map() and we can do that - * through an atomic read in C, which is what pmd_trans_unstable() - * provides. + * pmd_trans_unstable() via pmd_devmap_trans_unstable() instead of + * pmd_trans_huge() to ensure the pmd didn't become pmd_trans_huge + * under us and then back to pmd_none, as a result of MADV_DONTNEED + * running immediately after a huge pmd fault in a different thread of + * this mm, in turn leading to a misleading pmd_trans_huge() retval. + * All we have to ensure is that it is a regular pmd that we can walk + * with pte_offset_map() and we can do that through an atomic read in + * C, which is what pmd_trans_unstable() provides. */ - if (pmd_trans_unstable(vmf->pmd) || pmd_devmap(*vmf->pmd)) + if (pmd_devmap_trans_unstable(vmf->pmd)) return VM_FAULT_NOPAGE; + /* + * At this point we know that our vmf->pmd points to a page of ptes + * and it cannot become pmd_none(), pmd_devmap() or pmd_trans_huge() + * for the duration of the fault. If a racing MADV_DONTNEED runs and + * we zap the ptes pointed to by our vmf->pmd, the vmf->ptl will still + * be valid and we will re-check to make sure the vmf->pte isn't + * pte_none() under vmf->ptl protection when we return to + * alloc_set_pte(). + */ vmf->pte = pte_offset_map_lock(vma->vm_mm, vmf->pmd, vmf->address, &vmf->ptl); return 0; @@ -3690,7 +3710,7 @@ static int handle_pte_fault(struct vm_fault *vmf) vmf->pte = NULL; } else { /* See comment in pte_alloc_one_map() */ - if (pmd_trans_unstable(vmf->pmd) || pmd_devmap(*vmf->pmd)) + if (pmd_devmap_trans_unstable(vmf->pmd)) return 0; /* * A regular pmd is established and it can't morph into a huge -- cgit v1.2.3 From e2093926a098a8ccf0f1d10f6df8dad452cb28d3 Mon Sep 17 00:00:00 2001 From: Ross Zwisler Date: Fri, 2 Jun 2017 14:46:37 -0700 Subject: dax: fix race between colliding PMD & PTE entries We currently have two related PMD vs PTE races in the DAX code. These can both be easily triggered by having two threads reading and writing simultaneously to the same private mapping, with the key being that private mapping reads can be handled with PMDs but private mapping writes are always handled with PTEs so that we can COW. Here is the first race: CPU 0 CPU 1 (private mapping write) __handle_mm_fault() create_huge_pmd() - FALLBACK handle_pte_fault() passes check for pmd_devmap() (private mapping read) __handle_mm_fault() create_huge_pmd() dax_iomap_pmd_fault() inserts PMD dax_iomap_pte_fault() does a PTE fault, but we already have a DAX PMD installed in our page tables at this spot. Here's the second race: CPU 0 CPU 1 (private mapping read) __handle_mm_fault() passes check for pmd_none() create_huge_pmd() dax_iomap_pmd_fault() inserts PMD (private mapping write) __handle_mm_fault() create_huge_pmd() - FALLBACK (private mapping read) __handle_mm_fault() passes check for pmd_none() create_huge_pmd() handle_pte_fault() dax_iomap_pte_fault() inserts PTE dax_iomap_pmd_fault() inserts PMD, but we already have a PTE at this spot. The core of the issue is that while there is isolation between faults to the same range in the DAX fault handlers via our DAX entry locking, there is no isolation between faults in the code in mm/memory.c. This means for instance that this code in __handle_mm_fault() can run: if (pmd_none(*vmf.pmd) && transparent_hugepage_enabled(vma)) { ret = create_huge_pmd(&vmf); But by the time we actually get to run the fault handler called by create_huge_pmd(), the PMD is no longer pmd_none() because a racing PTE fault has installed a normal PMD here as a parent. This is the cause of the 2nd race. The first race is similar - there is the following check in handle_pte_fault(): } else { /* See comment in pte_alloc_one_map() */ if (pmd_devmap(*vmf->pmd) || pmd_trans_unstable(vmf->pmd)) return 0; So if a pmd_devmap() PMD (a DAX PMD) has been installed at vmf->pmd, we will bail and retry the fault. This is correct, but there is nothing preventing the PMD from being installed after this check but before we actually get to the DAX PTE fault handlers. In my testing these races result in the following types of errors: BUG: Bad rss-counter state mm:ffff8800a817d280 idx:1 val:1 BUG: non-zero nr_ptes on freeing mm: 15 Fix this issue by having the DAX fault handlers verify that it is safe to continue their fault after they have taken an entry lock to block other racing faults. [ross.zwisler@linux.intel.com: improve fix for colliding PMD & PTE entries] Link: http://lkml.kernel.org/r/20170526195932.32178-1-ross.zwisler@linux.intel.com Link: http://lkml.kernel.org/r/20170522215749.23516-2-ross.zwisler@linux.intel.com Signed-off-by: Ross Zwisler Reported-by: Pawel Lebioda Reviewed-by: Jan Kara Cc: "Darrick J. Wong" Cc: Alexander Viro Cc: Christoph Hellwig Cc: Dan Williams Cc: Dave Hansen Cc: Matthew Wilcox Cc: "Kirill A . Shutemov" Cc: Pawel Lebioda Cc: Dave Jiang Cc: Xiong Zhou Cc: Eryu Guan Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/dax.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/fs/dax.c b/fs/dax.c index c22eaf162f95..2a6889b3585f 100644 --- a/fs/dax.c +++ b/fs/dax.c @@ -1154,6 +1154,17 @@ static int dax_iomap_pte_fault(struct vm_fault *vmf, goto out; } + /* + * It is possible, particularly with mixed reads & writes to private + * mappings, that we have raced with a PMD fault that overlaps with + * the PTE we need to set up. If so just return and the fault will be + * retried. + */ + if (pmd_trans_huge(*vmf->pmd) || pmd_devmap(*vmf->pmd)) { + vmf_ret = VM_FAULT_NOPAGE; + goto unlock_entry; + } + /* * Note that we don't bother to use iomap_apply here: DAX required * the file system block size to be equal the page size, which means @@ -1397,6 +1408,18 @@ static int dax_iomap_pmd_fault(struct vm_fault *vmf, if (IS_ERR(entry)) goto fallback; + /* + * It is possible, particularly with mixed reads & writes to private + * mappings, that we have raced with a PTE fault that overlaps with + * the PMD we need to set up. If so just return and the fault will be + * retried. + */ + if (!pmd_none(*vmf->pmd) && !pmd_trans_huge(*vmf->pmd) && + !pmd_devmap(*vmf->pmd)) { + result = 0; + goto unlock_entry; + } + /* * Note that we don't use iomap_apply here. We aren't doing I/O, only * setting up a mapping, so really we're using iomap_begin() as a way -- cgit v1.2.3 From 30809f559a0d348c2dfd7ab05e9a451e2384962e Mon Sep 17 00:00:00 2001 From: Punit Agrawal Date: Fri, 2 Jun 2017 14:46:40 -0700 Subject: mm/migrate: fix refcount handling when !hugepage_migration_supported() On failing to migrate a page, soft_offline_huge_page() performs the necessary update to the hugepage ref-count. But when !hugepage_migration_supported() , unmap_and_move_hugepage() also decrements the page ref-count for the hugepage. The combined behaviour leaves the ref-count in an inconsistent state. This leads to soft lockups when running the overcommitted hugepage test from mce-tests suite. Soft offlining pfn 0x83ed600 at process virtual address 0x400000000000 soft offline: 0x83ed600: migration failed 1, type 1fffc00000008008 (uptodate|head) INFO: rcu_preempt detected stalls on CPUs/tasks: Tasks blocked on level-0 rcu_node (CPUs 0-7): P2715 (detected by 7, t=5254 jiffies, g=963, c=962, q=321) thugetlb_overco R running task 0 2715 2685 0x00000008 Call trace: dump_backtrace+0x0/0x268 show_stack+0x24/0x30 sched_show_task+0x134/0x180 rcu_print_detail_task_stall_rnp+0x54/0x7c rcu_check_callbacks+0xa74/0xb08 update_process_times+0x34/0x60 tick_sched_handle.isra.7+0x38/0x70 tick_sched_timer+0x4c/0x98 __hrtimer_run_queues+0xc0/0x300 hrtimer_interrupt+0xac/0x228 arch_timer_handler_phys+0x3c/0x50 handle_percpu_devid_irq+0x8c/0x290 generic_handle_irq+0x34/0x50 __handle_domain_irq+0x68/0xc0 gic_handle_irq+0x5c/0xb0 Address this by changing the putback_active_hugepage() in soft_offline_huge_page() to putback_movable_pages(). This only triggers on systems that enable memory failure handling (ARCH_SUPPORTS_MEMORY_FAILURE) but not hugepage migration (!ARCH_ENABLE_HUGEPAGE_MIGRATION). I imagine this wasn't triggered as there aren't many systems running this configuration. [akpm@linux-foundation.org: remove dead comment, per Naoya] Link: http://lkml.kernel.org/r/20170525135146.32011-1-punit.agrawal@arm.com Reported-by: Manoj Iyer Tested-by: Manoj Iyer Suggested-by: Naoya Horiguchi Signed-off-by: Punit Agrawal Cc: Joonsoo Kim Cc: Wanpeng Li Cc: Christoph Lameter Cc: Mel Gorman Cc: [3.14+] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memory-failure.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/mm/memory-failure.c b/mm/memory-failure.c index 2527dfeddb00..342fac9ba89b 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -1595,12 +1595,8 @@ static int soft_offline_huge_page(struct page *page, int flags) if (ret) { pr_info("soft offline: %#lx: migration failed %d, type %lx (%pGp)\n", pfn, ret, page->flags, &page->flags); - /* - * We know that soft_offline_huge_page() tries to migrate - * only one hugepage pointed to by hpage, so we need not - * run through the pagelist here. - */ - putback_active_hugepage(hpage); + if (!list_empty(&pagelist)) + putback_movable_pages(&pagelist); if (ret > 0) ret = -EIO; } else { -- cgit v1.2.3 From 70feee0e1ef331b22cc51f383d532a0d043fbdcc Mon Sep 17 00:00:00 2001 From: Yisheng Xie Date: Fri, 2 Jun 2017 14:46:43 -0700 Subject: mlock: fix mlock count can not decrease in race condition Kefeng reported that when running the follow test, the mlock count in meminfo will increase permanently: [1] testcase linux:~ # cat test_mlockal grep Mlocked /proc/meminfo for j in `seq 0 10` do for i in `seq 4 15` do ./p_mlockall >> log & done sleep 0.2 done # wait some time to let mlock counter decrease and 5s may not enough sleep 5 grep Mlocked /proc/meminfo linux:~ # cat p_mlockall.c #include #include #include #define SPACE_LEN 4096 int main(int argc, char ** argv) { int ret; void *adr = malloc(SPACE_LEN); if (!adr) return -1; ret = mlockall(MCL_CURRENT | MCL_FUTURE); printf("mlcokall ret = %d\n", ret); ret = munlockall(); printf("munlcokall ret = %d\n", ret); free(adr); return 0; } In __munlock_pagevec() we should decrement NR_MLOCK for each page where we clear the PageMlocked flag. Commit 1ebb7cc6a583 ("mm: munlock: batch NR_MLOCK zone state updates") has introduced a bug where we don't decrement NR_MLOCK for pages where we clear the flag, but fail to isolate them from the lru list (e.g. when the pages are on some other cpu's percpu pagevec). Since PageMlocked stays cleared, the NR_MLOCK accounting gets permanently disrupted by this. Fix it by counting the number of page whose PageMlock flag is cleared. Fixes: 1ebb7cc6a583 (" mm: munlock: batch NR_MLOCK zone state updates") Link: http://lkml.kernel.org/r/1495678405-54569-1-git-send-email-xieyisheng1@huawei.com Signed-off-by: Yisheng Xie Reported-by: Kefeng Wang Tested-by: Kefeng Wang Cc: Vlastimil Babka Cc: Joern Engel Cc: Mel Gorman Cc: Michel Lespinasse Cc: Hugh Dickins Cc: Rik van Riel Cc: Johannes Weiner Cc: Michal Hocko Cc: Xishi Qiu Cc: zhongjiang Cc: Hanjun Guo Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/mlock.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mm/mlock.c b/mm/mlock.c index c483c5c20b4b..b562b5523a65 100644 --- a/mm/mlock.c +++ b/mm/mlock.c @@ -284,7 +284,7 @@ static void __munlock_pagevec(struct pagevec *pvec, struct zone *zone) { int i; int nr = pagevec_count(pvec); - int delta_munlocked; + int delta_munlocked = -nr; struct pagevec pvec_putback; int pgrescued = 0; @@ -304,6 +304,8 @@ static void __munlock_pagevec(struct pagevec *pvec, struct zone *zone) continue; else __munlock_isolation_failed(page); + } else { + delta_munlocked++; } /* @@ -315,7 +317,6 @@ static void __munlock_pagevec(struct pagevec *pvec, struct zone *zone) pagevec_add(&pvec_putback, pvec->pages[i]); pvec->pages[i] = NULL; } - delta_munlocked = -nr + pagevec_count(&pvec_putback); __mod_zone_page_state(zone, NR_MLOCK, delta_munlocked); spin_unlock_irq(zone_lru_lock(zone)); -- cgit v1.2.3 From 9a291a7c9428155e8e623e4a3989f8be47134df5 Mon Sep 17 00:00:00 2001 From: James Morse Date: Fri, 2 Jun 2017 14:46:46 -0700 Subject: mm/hugetlb: report -EHWPOISON not -EFAULT when FOLL_HWPOISON is specified KVM uses get_user_pages() to resolve its stage2 faults. KVM sets the FOLL_HWPOISON flag causing faultin_page() to return -EHWPOISON when it finds a VM_FAULT_HWPOISON. KVM handles these hwpoison pages as a special case. (check_user_page_hwpoison()) When huge pages are involved, this doesn't work so well. get_user_pages() calls follow_hugetlb_page(), which stops early if it receives VM_FAULT_HWPOISON from hugetlb_fault(), eventually returning -EFAULT to the caller. The step to map this to -EHWPOISON based on the FOLL_ flags is missing. The hwpoison special case is skipped, and -EFAULT is returned to user-space, causing Qemu or kvmtool to exit. Instead, move this VM_FAULT_ to errno mapping code into a header file and use it from faultin_page() and follow_hugetlb_page(). With this, KVM works as expected. This isn't a problem for arm64 today as we haven't enabled MEMORY_FAILURE, but I can't see any reason this doesn't happen on x86 too, so I think this should be a fix. This doesn't apply earlier than stable's v4.11.1 due to all sorts of cleanup. [james.morse@arm.com: add vm_fault_to_errno() call to faultin_page()] suggested. Link: http://lkml.kernel.org/r/20170525171035.16359-1-james.morse@arm.com [akpm@linux-foundation.org: coding-style fixes] Link: http://lkml.kernel.org/r/20170524160900.28786-1-james.morse@arm.com Signed-off-by: James Morse Acked-by: Punit Agrawal Acked-by: Naoya Horiguchi Cc: "Kirill A . Shutemov" Cc: [4.11.1+] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/mm.h | 11 +++++++++++ mm/gup.c | 20 ++++++++------------ mm/hugetlb.c | 5 +++++ 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index 7cb17c6b97de..b892e95d4929 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -2327,6 +2327,17 @@ static inline struct page *follow_page(struct vm_area_struct *vma, #define FOLL_REMOTE 0x2000 /* we are working on non-current tsk/mm */ #define FOLL_COW 0x4000 /* internal GUP flag */ +static inline int vm_fault_to_errno(int vm_fault, int foll_flags) +{ + if (vm_fault & VM_FAULT_OOM) + return -ENOMEM; + if (vm_fault & (VM_FAULT_HWPOISON | VM_FAULT_HWPOISON_LARGE)) + return (foll_flags & FOLL_HWPOISON) ? -EHWPOISON : -EFAULT; + if (vm_fault & (VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV)) + return -EFAULT; + return 0; +} + typedef int (*pte_fn_t)(pte_t *pte, pgtable_t token, unsigned long addr, void *data); extern int apply_to_page_range(struct mm_struct *mm, unsigned long address, diff --git a/mm/gup.c b/mm/gup.c index d9e6fddcc51f..b3c7214d710d 100644 --- a/mm/gup.c +++ b/mm/gup.c @@ -407,12 +407,10 @@ static int faultin_page(struct task_struct *tsk, struct vm_area_struct *vma, ret = handle_mm_fault(vma, address, fault_flags); if (ret & VM_FAULT_ERROR) { - if (ret & VM_FAULT_OOM) - return -ENOMEM; - if (ret & (VM_FAULT_HWPOISON | VM_FAULT_HWPOISON_LARGE)) - return *flags & FOLL_HWPOISON ? -EHWPOISON : -EFAULT; - if (ret & (VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV)) - return -EFAULT; + int err = vm_fault_to_errno(ret, *flags); + + if (err) + return err; BUG(); } @@ -723,12 +721,10 @@ retry: ret = handle_mm_fault(vma, address, fault_flags); major |= ret & VM_FAULT_MAJOR; if (ret & VM_FAULT_ERROR) { - if (ret & VM_FAULT_OOM) - return -ENOMEM; - if (ret & (VM_FAULT_HWPOISON | VM_FAULT_HWPOISON_LARGE)) - return -EHWPOISON; - if (ret & (VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV)) - return -EFAULT; + int err = vm_fault_to_errno(ret, 0); + + if (err) + return err; BUG(); } diff --git a/mm/hugetlb.c b/mm/hugetlb.c index e5828875f7bb..3eedb187e549 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -4170,6 +4170,11 @@ long follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma, } ret = hugetlb_fault(mm, vma, vaddr, fault_flags); if (ret & VM_FAULT_ERROR) { + int err = vm_fault_to_errno(ret, flags); + + if (err) + return err; + remainder = 0; break; } -- cgit v1.2.3 From 864b9a393dcb5aed09b8fd31b9bbda0fdda99374 Mon Sep 17 00:00:00 2001 From: Michal Hocko Date: Fri, 2 Jun 2017 14:46:49 -0700 Subject: mm: consider memblock reservations for deferred memory initialization sizing We have seen an early OOM killer invocation on ppc64 systems with crashkernel=4096M: kthreadd invoked oom-killer: gfp_mask=0x16040c0(GFP_KERNEL|__GFP_COMP|__GFP_NOTRACK), nodemask=7, order=0, oom_score_adj=0 kthreadd cpuset=/ mems_allowed=7 CPU: 0 PID: 2 Comm: kthreadd Not tainted 4.4.68-1.gd7fe927-default #1 Call Trace: dump_stack+0xb0/0xf0 (unreliable) dump_header+0xb0/0x258 out_of_memory+0x5f0/0x640 __alloc_pages_nodemask+0xa8c/0xc80 kmem_getpages+0x84/0x1a0 fallback_alloc+0x2a4/0x320 kmem_cache_alloc_node+0xc0/0x2e0 copy_process.isra.25+0x260/0x1b30 _do_fork+0x94/0x470 kernel_thread+0x48/0x60 kthreadd+0x264/0x330 ret_from_kernel_thread+0x5c/0xa4 Mem-Info: active_anon:0 inactive_anon:0 isolated_anon:0 active_file:0 inactive_file:0 isolated_file:0 unevictable:0 dirty:0 writeback:0 unstable:0 slab_reclaimable:5 slab_unreclaimable:73 mapped:0 shmem:0 pagetables:0 bounce:0 free:0 free_pcp:0 free_cma:0 Node 7 DMA free:0kB min:0kB low:0kB high:0kB active_anon:0kB inactive_anon:0kB active_file:0kB inactive_file:0kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:52428800kB managed:110016kB mlocked:0kB dirty:0kB writeback:0kB mapped:0kB shmem:0kB slab_reclaimable:320kB slab_unreclaimable:4672kB kernel_stack:1152kB pagetables:0kB unstable:0kB bounce:0kB free_pcp:0kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? yes lowmem_reserve[]: 0 0 0 0 Node 7 DMA: 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB 0*8192kB 0*16384kB = 0kB 0 total pagecache pages 0 pages in swap cache Swap cache stats: add 0, delete 0, find 0/0 Free swap = 0kB Total swap = 0kB 819200 pages RAM 0 pages HighMem/MovableOnly 817481 pages reserved 0 pages cma reserved 0 pages hwpoisoned the reason is that the managed memory is too low (only 110MB) while the rest of the the 50GB is still waiting for the deferred intialization to be done. update_defer_init estimates the initial memoty to initialize to 2GB at least but it doesn't consider any memory allocated in that range. In this particular case we've had Reserving 4096MB of memory at 128MB for crashkernel (System RAM: 51200MB) so the low 2GB is mostly depleted. Fix this by considering memblock allocations in the initial static initialization estimation. Move the max_initialise to reset_deferred_meminit and implement a simple memblock_reserved_memory helper which iterates all reserved blocks and sums the size of all that start below the given address. The cumulative size is than added on top of the initial estimation. This is still not ideal because reset_deferred_meminit doesn't consider holes and so reservation might be above the initial estimation whihch we ignore but let's make the logic simpler until we really need to handle more complicated cases. Fixes: 3a80a7fa7989 ("mm: meminit: initialise a subset of struct pages if CONFIG_DEFERRED_STRUCT_PAGE_INIT is set") Link: http://lkml.kernel.org/r/20170531104010.GI27783@dhcp22.suse.cz Signed-off-by: Michal Hocko Acked-by: Mel Gorman Tested-by: Srikar Dronamraju Cc: [4.2+] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/memblock.h | 8 ++++++++ include/linux/mmzone.h | 1 + mm/memblock.c | 23 +++++++++++++++++++++++ mm/page_alloc.c | 33 ++++++++++++++++++++++----------- 4 files changed, 54 insertions(+), 11 deletions(-) diff --git a/include/linux/memblock.h b/include/linux/memblock.h index 4ce24a376262..8098695e5d8d 100644 --- a/include/linux/memblock.h +++ b/include/linux/memblock.h @@ -425,12 +425,20 @@ static inline void early_memtest(phys_addr_t start, phys_addr_t end) } #endif +extern unsigned long memblock_reserved_memory_within(phys_addr_t start_addr, + phys_addr_t end_addr); #else static inline phys_addr_t memblock_alloc(phys_addr_t size, phys_addr_t align) { return 0; } +static inline unsigned long memblock_reserved_memory_within(phys_addr_t start_addr, + phys_addr_t end_addr) +{ + return 0; +} + #endif /* CONFIG_HAVE_MEMBLOCK */ #endif /* __KERNEL__ */ diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index ebaccd4e7d8c..ef6a13b7bd3e 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -678,6 +678,7 @@ typedef struct pglist_data { * is the first PFN that needs to be initialised. */ unsigned long first_deferred_pfn; + unsigned long static_init_size; #endif /* CONFIG_DEFERRED_STRUCT_PAGE_INIT */ #ifdef CONFIG_TRANSPARENT_HUGEPAGE diff --git a/mm/memblock.c b/mm/memblock.c index b049c9b2dba8..7b8a5db76a2f 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -1739,6 +1739,29 @@ static void __init_memblock memblock_dump(struct memblock_type *type) } } +extern unsigned long __init_memblock +memblock_reserved_memory_within(phys_addr_t start_addr, phys_addr_t end_addr) +{ + struct memblock_region *rgn; + unsigned long size = 0; + int idx; + + for_each_memblock_type((&memblock.reserved), rgn) { + phys_addr_t start, end; + + if (rgn->base + rgn->size < start_addr) + continue; + if (rgn->base > end_addr) + continue; + + start = rgn->base; + end = start + rgn->size; + size += end - start; + } + + return size; +} + void __init_memblock __memblock_dump_all(void) { pr_info("MEMBLOCK configuration:\n"); diff --git a/mm/page_alloc.c b/mm/page_alloc.c index b7a6f583a373..2302f250d6b1 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -292,6 +292,26 @@ int page_group_by_mobility_disabled __read_mostly; #ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT static inline void reset_deferred_meminit(pg_data_t *pgdat) { + unsigned long max_initialise; + unsigned long reserved_lowmem; + + /* + * Initialise at least 2G of a node but also take into account that + * two large system hashes that can take up 1GB for 0.25TB/node. + */ + max_initialise = max(2UL << (30 - PAGE_SHIFT), + (pgdat->node_spanned_pages >> 8)); + + /* + * Compensate the all the memblock reservations (e.g. crash kernel) + * from the initial estimation to make sure we will initialize enough + * memory to boot. + */ + reserved_lowmem = memblock_reserved_memory_within(pgdat->node_start_pfn, + pgdat->node_start_pfn + max_initialise); + max_initialise += reserved_lowmem; + + pgdat->static_init_size = min(max_initialise, pgdat->node_spanned_pages); pgdat->first_deferred_pfn = ULONG_MAX; } @@ -314,20 +334,11 @@ static inline bool update_defer_init(pg_data_t *pgdat, unsigned long pfn, unsigned long zone_end, unsigned long *nr_initialised) { - unsigned long max_initialise; - /* Always populate low zones for address-contrained allocations */ if (zone_end < pgdat_end_pfn(pgdat)) return true; - /* - * Initialise at least 2G of a node but also take into account that - * two large system hashes that can take up 1GB for 0.25TB/node. - */ - max_initialise = max(2UL << (30 - PAGE_SHIFT), - (pgdat->node_spanned_pages >> 8)); - (*nr_initialised)++; - if ((*nr_initialised > max_initialise) && + if ((*nr_initialised > pgdat->static_init_size) && (pfn & (PAGES_PER_SECTION - 1)) == 0) { pgdat->first_deferred_pfn = pfn; return false; @@ -6138,7 +6149,6 @@ void __paginginit free_area_init_node(int nid, unsigned long *zones_size, /* pg_data_t should be reset to zero when it's allocated */ WARN_ON(pgdat->nr_zones || pgdat->kswapd_classzone_idx); - reset_deferred_meminit(pgdat); pgdat->node_id = nid; pgdat->node_start_pfn = node_start_pfn; pgdat->per_cpu_nodestats = NULL; @@ -6160,6 +6170,7 @@ void __paginginit free_area_init_node(int nid, unsigned long *zones_size, (unsigned long)pgdat->node_mem_map); #endif + reset_deferred_meminit(pgdat); free_area_init_core(pgdat); } -- cgit v1.2.3 From d6c9708737c2107c38bd75f133d14d5801b8d6d5 Mon Sep 17 00:00:00 2001 From: André Draszik Date: Fri, 2 Jun 2017 14:46:51 -0700 Subject: scripts/gdb: make lx-dmesg command work (reliably) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit lx-dmesg needs access to the log_buf symbol from printk.c. Unfortunately, the symbol log_buf also exists in BPF's verifier.c and hence gdb can pick one or the other. If it happens to pick BPF's log_buf, lx-dmesg doesn't work: (gdb) lx-dmesg Python Exception Cannot access memory at address 0x0: Error occurred in Python command: Cannot access memory at address 0x0 (gdb) p log_buf $15 = 0x0 Luckily, GDB has a way to deal with this, see https://sourceware.org/gdb/onlinedocs/gdb/Symbols.html (gdb) info variables ^log_buf$ All variables matching regular expression "^log_buf$": File /kernel/bpf/verifier.c: static char *log_buf; File /kernel/printk/printk.c: static char *log_buf; (gdb) p 'verifier.c'::log_buf $1 = 0x0 (gdb) p 'printk.c'::log_buf $2 = 0x811a6aa0 <__log_buf> "" (gdb) p &log_buf $3 = (char **) 0x8120fe40 (gdb) p &'verifier.c'::log_buf $4 = (char **) 0x8120fe40 (gdb) p &'printk.c'::log_buf $5 = (char **) 0x8048b7d0 By being explicit about the location of the symbol, we can make lx-dmesg work again. While at it, do the same for the other symbols we need from printk.c Link: http://lkml.kernel.org/r/20170526112222.3414-1-git@andred.net Signed-off-by: André Draszik Tested-by: Kieran Bingham Acked-by: Jan Kiszka Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/gdb/linux/dmesg.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/scripts/gdb/linux/dmesg.py b/scripts/gdb/linux/dmesg.py index f9b92ece7834..5afd1098e33a 100644 --- a/scripts/gdb/linux/dmesg.py +++ b/scripts/gdb/linux/dmesg.py @@ -23,10 +23,11 @@ class LxDmesg(gdb.Command): super(LxDmesg, self).__init__("lx-dmesg", gdb.COMMAND_DATA) def invoke(self, arg, from_tty): - log_buf_addr = int(str(gdb.parse_and_eval("log_buf")).split()[0], 16) - log_first_idx = int(gdb.parse_and_eval("log_first_idx")) - log_next_idx = int(gdb.parse_and_eval("log_next_idx")) - log_buf_len = int(gdb.parse_and_eval("log_buf_len")) + log_buf_addr = int(str(gdb.parse_and_eval( + "'printk.c'::log_buf")).split()[0], 16) + log_first_idx = int(gdb.parse_and_eval("'printk.c'::log_first_idx")) + log_next_idx = int(gdb.parse_and_eval("'printk.c'::log_next_idx")) + log_buf_len = int(gdb.parse_and_eval("'printk.c'::log_buf_len")) inf = gdb.inferiors()[0] start = log_buf_addr + log_first_idx -- cgit v1.2.3 From 8d4b31376974855cd4fb176e5d63ba8e0407928e Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 2 Jun 2017 17:18:47 -0700 Subject: Input: axp20x-pek - only check for "INTCFD9" ACPI device on Cherry Trail MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 9b13a4ca8d2c ("Input: axp20x-pek - do not register input device on some systems") added a check for the INTCFD9 ACPI device which also handles the powerbutton as on some systems the powerbutton is connected to both the PMIC, handled by axp20x-pek, and to a gpio on the SoC, handled by soc_button_array which attaches itself to the INTCFD9 ACPI device. Testing + comparing DSDTs has shown that this only happens on Cherry Trail devices with an AXP288 PMIC, the AXP288 PMIC is also used on Bay Trail devices but there the power button is only connected to the PMIC and not handled by soc_button_array. This means that the INTCFD9 check has caused a regression on Bay Trail devices, causing power-button presses to no longer be seen. This commit fixes this by limiting the check to devices where the ACPI node for the AXP288 contains a _HRV (hardware revision) attribute with a value of 3 which indicates we are dealing with a Cherry Trail platform. Fixes: 9b13a4ca8d2c ("Input: axp20x-pek - do not register input ...") Reported-by: Сергей Трусов Signed-off-by: Hans de Goede Signed-off-by: Dmitry Torokhov --- drivers/input/misc/axp20x-pek.c | 43 ++++++++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/drivers/input/misc/axp20x-pek.c b/drivers/input/misc/axp20x-pek.c index f11807db6979..c0a763a70a00 100644 --- a/drivers/input/misc/axp20x-pek.c +++ b/drivers/input/misc/axp20x-pek.c @@ -256,6 +256,41 @@ static int axp20x_pek_probe_input_device(struct axp20x_pek *axp20x_pek, return 0; } +#ifdef CONFIG_ACPI +static bool axp20x_pek_should_register_input(struct axp20x_pek *axp20x_pek, + struct platform_device *pdev) +{ + unsigned long long hrv = 0; + acpi_status status; + + if (IS_ENABLED(CONFIG_INPUT_SOC_BUTTON_ARRAY) && + axp20x_pek->axp20x->variant == AXP288_ID) { + status = acpi_evaluate_integer(ACPI_HANDLE(pdev->dev.parent), + "_HRV", NULL, &hrv); + if (ACPI_FAILURE(status)) + dev_err(&pdev->dev, "Failed to get PMIC hardware revision\n"); + + /* + * On Cherry Trail platforms (hrv == 3), do not register the + * input device if there is an "INTCFD9" gpio + * button ACPI device, as that handles the power button too, + * and otherwise we end up reporting all presses twice. + */ + if (hrv == 3 && acpi_dev_found("INTCFD9")) + return false; + + } + + return true; +} +#else +static bool axp20x_pek_should_register_input(struct axp20x_pek *axp20x_pek, + struct platform_device *pdev) +{ + return true; +} +#endif + static int axp20x_pek_probe(struct platform_device *pdev) { struct axp20x_pek *axp20x_pek; @@ -268,13 +303,7 @@ static int axp20x_pek_probe(struct platform_device *pdev) axp20x_pek->axp20x = dev_get_drvdata(pdev->dev.parent); - /* - * Do not register the input device if there is an "INTCFD9" - * gpio button ACPI device, that handles the power button too, - * and otherwise we end up reporting all presses twice. - */ - if (!acpi_dev_found("INTCFD9") || - !IS_ENABLED(CONFIG_INPUT_SOC_BUTTON_ARRAY)) { + if (axp20x_pek_should_register_input(axp20x_pek, pdev)) { error = axp20x_pek_probe_input_device(axp20x_pek, pdev); if (error) return error; -- cgit v1.2.3 From 0fd5f221093870d93edb696f6903b058c4d75411 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 2 Jun 2017 17:50:22 -0700 Subject: Input: axp20x-pek - switch to acpi_dev_present and check for ACPI0011 too acpi_dev_found checks that there is a matching ACPI node, but it may be disabled (_STA method returns 0) in which case the soc_button_array driver will not bind to it and axp20x-pek should handle the power-button. This commit switches from acpi_dev_found to acpi_dev_present to avoid not registering an input-dev for the powerbutton when there is a disabled PNP0C40 device. The ACPI-6.0 standard defines a standard gpio button device using the ACPI0011 HID replacing the custom PNP0C40 gpio device, many newer devices define both PNP0C40 and ACPI0011 devices enabling one or the other depending on whether the BIOS thinks it is going to boot Android or Windows. This commit adds a check for the ACPI0011 device, so that if either device is present *and* enabled we don't register an input-dev for the powerbutton. Signed-off-by: Hans de Goede Signed-off-by: Dmitry Torokhov --- drivers/input/misc/axp20x-pek.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/input/misc/axp20x-pek.c b/drivers/input/misc/axp20x-pek.c index c0a763a70a00..400869e61a06 100644 --- a/drivers/input/misc/axp20x-pek.c +++ b/drivers/input/misc/axp20x-pek.c @@ -272,11 +272,12 @@ static bool axp20x_pek_should_register_input(struct axp20x_pek *axp20x_pek, /* * On Cherry Trail platforms (hrv == 3), do not register the - * input device if there is an "INTCFD9" gpio + * input device if there is an "INTCFD9" or "ACPI0011" gpio * button ACPI device, as that handles the power button too, * and otherwise we end up reporting all presses twice. */ - if (hrv == 3 && acpi_dev_found("INTCFD9")) + if (hrv == 3 && (acpi_dev_present("INTCFD9", NULL, -1) || + acpi_dev_present("ACPI0011", NULL, -1))) return false; } -- cgit v1.2.3 From 40da1b11f01e43aad1aa6cea64681b6125e8a2a7 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Fri, 2 Jun 2017 16:27:14 +0200 Subject: cpu/hotplug: Drop the device lock on error If a custom CPU target is specified and that one is not available _or_ can't be interrupted then the code returns to userland without dropping a lock as notices by lockdep: |echo 133 > /sys/devices/system/cpu/cpu7/hotplug/target | ================================================ | [ BUG: lock held when returning to user space! ] | ------------------------------------------------ | bash/503 is leaving the kernel with locks still held! | 1 lock held by bash/503: | #0: (device_hotplug_lock){+.+...}, at: [] lock_device_hotplug_sysfs+0x10/0x40 So release the lock then. Fixes: 757c989b9994 ("cpu/hotplug: Make target state writeable") Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Thomas Gleixner Cc: stable@vger.kernel.org Link: http://lkml.kernel.org/r/20170602142714.3ogo25f2wbq6fjpj@linutronix.de --- kernel/cpu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/cpu.c b/kernel/cpu.c index 9ae6fbe5b5cf..cb5103413bd8 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -1658,13 +1658,13 @@ static ssize_t write_cpuhp_target(struct device *dev, ret = !sp->name || sp->cant_stop ? -EINVAL : 0; mutex_unlock(&cpuhp_state_mutex); if (ret) - return ret; + goto out; if (st->state < target) ret = do_cpu_up(dev->id, target); else ret = do_cpu_down(dev->id, target); - +out: unlock_device_hotplug(); return ret ? ret : count; } -- cgit v1.2.3 From 0a33252e060e97ed3fbdcec9517672f1e91aaef3 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Fri, 26 May 2017 23:40:33 -0400 Subject: staging/lustre/lov: remove set_fs() call from lov_getstripe() lov_getstripe() calls set_fs(KERNEL_DS) so that it can handle a struct lov_user_md pointer from user- or kernel-space. This changes the behavior of copy_from_user() on SPARC and may result in a misaligned access exception which in turn oopses the kernel. In fact the relevant argument to lov_getstripe() is never called with a kernel-space pointer and so changing the address limits is unnecessary and so we remove the calls to save, set, and restore the address limits. Signed-off-by: John L. Hammond Reviewed-on: http://review.whamcloud.com/6150 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3221 Reviewed-by: Andreas Dilger Reviewed-by: Li Wei Signed-off-by: Oleg Drokin Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/lov/lov_pack.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/staging/lustre/lustre/lov/lov_pack.c b/drivers/staging/lustre/lustre/lov/lov_pack.c index 2e1bd47337fd..e6727cefde05 100644 --- a/drivers/staging/lustre/lustre/lov/lov_pack.c +++ b/drivers/staging/lustre/lustre/lov/lov_pack.c @@ -293,18 +293,10 @@ int lov_getstripe(struct lov_object *obj, struct lov_stripe_md *lsm, size_t lmmk_size; size_t lum_size; int rc; - mm_segment_t seg; if (!lsm) return -ENODATA; - /* - * "Switch to kernel segment" to allow copying from kernel space by - * copy_{to,from}_user(). - */ - seg = get_fs(); - set_fs(KERNEL_DS); - if (lsm->lsm_magic != LOV_MAGIC_V1 && lsm->lsm_magic != LOV_MAGIC_V3) { CERROR("bad LSM MAGIC: 0x%08X != 0x%08X nor 0x%08X\n", lsm->lsm_magic, LOV_MAGIC_V1, LOV_MAGIC_V3); @@ -406,6 +398,5 @@ int lov_getstripe(struct lov_object *obj, struct lov_stripe_md *lsm, out_free: kvfree(lmmk); out: - set_fs(seg); return rc; } -- cgit v1.2.3 From 32829da54d9368103a2f03269a5120aa9ee4d5da Mon Sep 17 00:00:00 2001 From: Julius Werner Date: Fri, 2 Jun 2017 15:36:39 -0700 Subject: drivers: char: mem: Fix wraparound check to allow mappings up to the end A recent fix to /dev/mem prevents mappings from wrapping around the end of physical address space. However, the check was written in a way that also prevents a mapping reaching just up to the end of physical address space, which may be a valid use case (especially on 32-bit systems). This patch fixes it by checking the last mapped address (instead of the first address behind that) for overflow. Fixes: b299cde245 ("drivers: char: mem: Check for address space wraparound with mmap()") Cc: Reported-by: Nico Huber Signed-off-by: Julius Werner Signed-off-by: Greg Kroah-Hartman --- drivers/char/mem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 6e0cbe092220..593a8818aca9 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -343,7 +343,7 @@ static int mmap_mem(struct file *file, struct vm_area_struct *vma) phys_addr_t offset = (phys_addr_t)vma->vm_pgoff << PAGE_SHIFT; /* It's illegal to wrap around the end of the physical address space. */ - if (offset + (phys_addr_t)size < offset) + if (offset + (phys_addr_t)size - 1 < offset) return -EINVAL; if (!valid_mmap_phys_addr_range(vma->vm_pgoff, size)) -- cgit v1.2.3 From 6f9193ec044a8f72d8b6ae94a5c4ab6e8b0f00ca Mon Sep 17 00:00:00 2001 From: Pratyush Anand Date: Mon, 29 May 2017 22:08:24 +0300 Subject: mei: make sysfs modalias format similar as uevent modalias modprobe is not able to resolve sysfs modalias for mei devices. # cat /sys/class/watchdog/watchdog0/device/watchdog/watchdog0/device/modalias mei::05b79a6f-4628-4d7f-899d-a91514cb32ab: # modprobe --set-version 4.9.6-200.fc25.x86_64 -R mei::05b79a6f-4628-4d7f-899d-a91514cb32ab: modprobe: FATAL: Module mei::05b79a6f-4628-4d7f-899d-a91514cb32ab: not found in directory /lib/modules/4.9.6-200.fc25.x86_64 # cat /lib/modules/4.9.6-200.fc25.x86_64/modules.alias | grep 05b79a6f-4628-4d7f-899d-a91514cb32ab alias mei:*:05b79a6f-4628-4d7f-899d-a91514cb32ab:*:* mei_wdt commit b26864cad1c9 ("mei: bus: add client protocol version to the device alias"), however sysfs modalias is still in formmat mei:S:uuid:*. This patch equates format of uevent and sysfs modalias so that modprobe is able to resolve the aliases. Cc: 4.7+ Fixes: commit b26864cad1c9 ("mei: bus: add client protocol version to the device alias") Signed-off-by: Pratyush Anand Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/bus.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c index d1928fdd0f43..07aad8576334 100644 --- a/drivers/misc/mei/bus.c +++ b/drivers/misc/mei/bus.c @@ -763,8 +763,10 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *a, { struct mei_cl_device *cldev = to_mei_cl_device(dev); const uuid_le *uuid = mei_me_cl_uuid(cldev->me_cl); + u8 version = mei_me_cl_ver(cldev->me_cl); - return scnprintf(buf, PAGE_SIZE, "mei:%s:%pUl:", cldev->name, uuid); + return scnprintf(buf, PAGE_SIZE, "mei:%s:%pUl:%02X:", + cldev->name, uuid, version); } static DEVICE_ATTR_RO(modalias); -- cgit v1.2.3 From 4d58e7329fdd87d37f04b319d6a5165aaff5d75c Mon Sep 17 00:00:00 2001 From: Stefan Schaeckeler Date: Fri, 2 Jun 2017 12:42:08 -0700 Subject: hwmon: (aspeed-pwm-tacho) Call of_node_put() on a node not claimed Call of_node_put() on a node claimed with of_node_get() or by any other means such as for_each_child_of_node(). Signed-off-by: Stefan Schaeckeler Fixes: 2d7a548a3eff ("drivers: hwmon: Support for ASPEED PWM/Fan tach") Signed-off-by: Guenter Roeck --- drivers/hwmon/aspeed-pwm-tacho.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/hwmon/aspeed-pwm-tacho.c b/drivers/hwmon/aspeed-pwm-tacho.c index 12b716b70ead..cc15bedb3415 100644 --- a/drivers/hwmon/aspeed-pwm-tacho.c +++ b/drivers/hwmon/aspeed-pwm-tacho.c @@ -808,7 +808,6 @@ static int aspeed_pwm_tacho_probe(struct platform_device *pdev) if (ret) return ret; } - of_node_put(np); priv->groups[0] = &pwm_dev_group; priv->groups[1] = &fan_dev_group; -- cgit v1.2.3 From 5f348fa35a28b19cf7ee1eaa420757341a724c86 Mon Sep 17 00:00:00 2001 From: Stefan Schaeckeler Date: Fri, 2 Jun 2017 12:43:28 -0700 Subject: hwmon: (aspeed-pwm-tacho) make fan/pwm names start with index 1 Make fan and pwm names in sysfs start with index 1 in accordance to Documentation/hwmon/sysfs-interface conventions. Current implementation starts with index 0, making tools such as sensors(1) skip the first fan. Signed-off-by: Stefan Schaeckeler Fixes: 2d7a548a3eff ("drivers: hwmon: Support for ASPEED PWM/Fan tach") Signed-off-by: Guenter Roeck --- drivers/hwmon/aspeed-pwm-tacho.c | 52 ++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/drivers/hwmon/aspeed-pwm-tacho.c b/drivers/hwmon/aspeed-pwm-tacho.c index cc15bedb3415..9de13d626c68 100644 --- a/drivers/hwmon/aspeed-pwm-tacho.c +++ b/drivers/hwmon/aspeed-pwm-tacho.c @@ -597,24 +597,23 @@ static umode_t fan_dev_is_visible(struct kobject *kobj, return a->mode; } -static SENSOR_DEVICE_ATTR(pwm0, 0644, - show_pwm, set_pwm, 0); static SENSOR_DEVICE_ATTR(pwm1, 0644, - show_pwm, set_pwm, 1); + show_pwm, set_pwm, 0); static SENSOR_DEVICE_ATTR(pwm2, 0644, - show_pwm, set_pwm, 2); + show_pwm, set_pwm, 1); static SENSOR_DEVICE_ATTR(pwm3, 0644, - show_pwm, set_pwm, 3); + show_pwm, set_pwm, 2); static SENSOR_DEVICE_ATTR(pwm4, 0644, - show_pwm, set_pwm, 4); + show_pwm, set_pwm, 3); static SENSOR_DEVICE_ATTR(pwm5, 0644, - show_pwm, set_pwm, 5); + show_pwm, set_pwm, 4); static SENSOR_DEVICE_ATTR(pwm6, 0644, - show_pwm, set_pwm, 6); + show_pwm, set_pwm, 5); static SENSOR_DEVICE_ATTR(pwm7, 0644, + show_pwm, set_pwm, 6); +static SENSOR_DEVICE_ATTR(pwm8, 0644, show_pwm, set_pwm, 7); static struct attribute *pwm_dev_attrs[] = { - &sensor_dev_attr_pwm0.dev_attr.attr, &sensor_dev_attr_pwm1.dev_attr.attr, &sensor_dev_attr_pwm2.dev_attr.attr, &sensor_dev_attr_pwm3.dev_attr.attr, @@ -622,6 +621,7 @@ static struct attribute *pwm_dev_attrs[] = { &sensor_dev_attr_pwm5.dev_attr.attr, &sensor_dev_attr_pwm6.dev_attr.attr, &sensor_dev_attr_pwm7.dev_attr.attr, + &sensor_dev_attr_pwm8.dev_attr.attr, NULL, }; @@ -630,40 +630,39 @@ static const struct attribute_group pwm_dev_group = { .is_visible = pwm_is_visible, }; -static SENSOR_DEVICE_ATTR(fan0_input, 0444, - show_rpm, NULL, 0); static SENSOR_DEVICE_ATTR(fan1_input, 0444, - show_rpm, NULL, 1); + show_rpm, NULL, 0); static SENSOR_DEVICE_ATTR(fan2_input, 0444, - show_rpm, NULL, 2); + show_rpm, NULL, 1); static SENSOR_DEVICE_ATTR(fan3_input, 0444, - show_rpm, NULL, 3); + show_rpm, NULL, 2); static SENSOR_DEVICE_ATTR(fan4_input, 0444, - show_rpm, NULL, 4); + show_rpm, NULL, 3); static SENSOR_DEVICE_ATTR(fan5_input, 0444, - show_rpm, NULL, 5); + show_rpm, NULL, 4); static SENSOR_DEVICE_ATTR(fan6_input, 0444, - show_rpm, NULL, 6); + show_rpm, NULL, 5); static SENSOR_DEVICE_ATTR(fan7_input, 0444, - show_rpm, NULL, 7); + show_rpm, NULL, 6); static SENSOR_DEVICE_ATTR(fan8_input, 0444, - show_rpm, NULL, 8); + show_rpm, NULL, 7); static SENSOR_DEVICE_ATTR(fan9_input, 0444, - show_rpm, NULL, 9); + show_rpm, NULL, 8); static SENSOR_DEVICE_ATTR(fan10_input, 0444, - show_rpm, NULL, 10); + show_rpm, NULL, 9); static SENSOR_DEVICE_ATTR(fan11_input, 0444, - show_rpm, NULL, 11); + show_rpm, NULL, 10); static SENSOR_DEVICE_ATTR(fan12_input, 0444, - show_rpm, NULL, 12); + show_rpm, NULL, 11); static SENSOR_DEVICE_ATTR(fan13_input, 0444, - show_rpm, NULL, 13); + show_rpm, NULL, 12); static SENSOR_DEVICE_ATTR(fan14_input, 0444, - show_rpm, NULL, 14); + show_rpm, NULL, 13); static SENSOR_DEVICE_ATTR(fan15_input, 0444, + show_rpm, NULL, 14); +static SENSOR_DEVICE_ATTR(fan16_input, 0444, show_rpm, NULL, 15); static struct attribute *fan_dev_attrs[] = { - &sensor_dev_attr_fan0_input.dev_attr.attr, &sensor_dev_attr_fan1_input.dev_attr.attr, &sensor_dev_attr_fan2_input.dev_attr.attr, &sensor_dev_attr_fan3_input.dev_attr.attr, @@ -679,6 +678,7 @@ static struct attribute *fan_dev_attrs[] = { &sensor_dev_attr_fan13_input.dev_attr.attr, &sensor_dev_attr_fan14_input.dev_attr.attr, &sensor_dev_attr_fan15_input.dev_attr.attr, + &sensor_dev_attr_fan16_input.dev_attr.attr, NULL }; -- cgit v1.2.3 From 3116a23bb30272d74ea81baf5d0ee23f602dd15b Mon Sep 17 00:00:00 2001 From: Dmitry Monakhov Date: Wed, 10 May 2017 19:20:44 +0400 Subject: bio-integrity: Do not allocate integrity context for bio w/o data If bio has no data, such as ones from blkdev_issue_flush(), then we have nothing to protect. This patch prevent bugon like follows: kfree_debugcheck: out of range ptr ac1fa1d106742a5ah kernel BUG at mm/slab.c:2773! invalid opcode: 0000 [#1] SMP Modules linked in: bcache CPU: 0 PID: 4428 Comm: xfs_io Tainted: G W 4.11.0-rc4-ext4-00041-g2ef0043-dirty #43 Hardware name: Virtuozzo KVM, BIOS seabios-1.7.5-11.vz7.4 04/01/2014 task: ffff880137786440 task.stack: ffffc90000ba8000 RIP: 0010:kfree_debugcheck+0x25/0x2a RSP: 0018:ffffc90000babde0 EFLAGS: 00010082 RAX: 0000000000000034 RBX: ac1fa1d106742a5a RCX: 0000000000000007 RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff88013f3ccb40 RBP: ffffc90000babde8 R08: 0000000000000000 R09: 0000000000000000 R10: 00000000fcb76420 R11: 00000000725172ed R12: 0000000000000282 R13: ffffffff8150e766 R14: ffff88013a145e00 R15: 0000000000000001 FS: 00007fb09384bf40(0000) GS:ffff88013f200000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007fd0172f9e40 CR3: 0000000137fa9000 CR4: 00000000000006f0 Call Trace: kfree+0xc8/0x1b3 bio_integrity_free+0xc3/0x16b bio_free+0x25/0x66 bio_put+0x14/0x26 blkdev_issue_flush+0x7a/0x85 blkdev_fsync+0x35/0x42 vfs_fsync_range+0x8e/0x9f vfs_fsync+0x1c/0x1e do_fsync+0x31/0x4a SyS_fsync+0x10/0x14 entry_SYSCALL_64_fastpath+0x1f/0xc2 Reviewed-by: Christoph Hellwig Reviewed-by: Hannes Reinecke Reviewed-by: Martin K. Petersen Signed-off-by: Dmitry Monakhov Signed-off-by: Jens Axboe --- block/bio-integrity.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/block/bio-integrity.c b/block/bio-integrity.c index 5384713d48bc..b5009a896a7f 100644 --- a/block/bio-integrity.c +++ b/block/bio-integrity.c @@ -175,6 +175,9 @@ bool bio_integrity_enabled(struct bio *bio) if (bio_op(bio) != REQ_OP_READ && bio_op(bio) != REQ_OP_WRITE) return false; + if (!bio_sectors(bio)) + return false; + /* Already protected? */ if (bio_integrity(bio)) return false; -- cgit v1.2.3 From 4f253e1eb628f5adf7ca4f43aab4bbb1bfffa081 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 16 May 2017 12:18:11 +0200 Subject: nfs: Mark unnecessarily extern functions as static nfs_initialise_sb() and nfs_clone_super() are declared as extern even though they are used only in fs/nfs/super.c. Mark them as static. Also remove explicit 'inline' directive from nfs_initialise_sb() and leave it upto compiler to decide whether inlining is worth it. Signed-off-by: Jan Kara Signed-off-by: Trond Myklebust --- fs/nfs/internal.h | 2 -- fs/nfs/super.c | 5 +++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index e9b4c3320e37..3e24392f2caa 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -398,7 +398,6 @@ extern struct file_system_type nfs4_referral_fs_type; bool nfs_auth_info_match(const struct nfs_auth_info *, rpc_authflavor_t); struct dentry *nfs_try_mount(int, const char *, struct nfs_mount_info *, struct nfs_subversion *); -void nfs_initialise_sb(struct super_block *); int nfs_set_sb_security(struct super_block *, struct dentry *, struct nfs_mount_info *); int nfs_clone_sb_security(struct super_block *, struct dentry *, struct nfs_mount_info *); struct dentry *nfs_fs_mount_common(struct nfs_server *, int, const char *, @@ -458,7 +457,6 @@ extern void nfs_read_prepare(struct rpc_task *task, void *calldata); extern void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio); /* super.c */ -void nfs_clone_super(struct super_block *, struct nfs_mount_info *); void nfs_umount_begin(struct super_block *); int nfs_statfs(struct dentry *, struct kstatfs *); int nfs_show_options(struct seq_file *, struct dentry *); diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 2f3822a4a7d5..eceb4eabb064 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -2301,7 +2301,7 @@ EXPORT_SYMBOL_GPL(nfs_remount); /* * Initialise the common bits of the superblock */ -inline void nfs_initialise_sb(struct super_block *sb) +static void nfs_initialise_sb(struct super_block *sb) { struct nfs_server *server = NFS_SB(sb); @@ -2348,7 +2348,8 @@ EXPORT_SYMBOL_GPL(nfs_fill_super); /* * Finish setting up a cloned NFS2/3/4 superblock */ -void nfs_clone_super(struct super_block *sb, struct nfs_mount_info *mount_info) +static void nfs_clone_super(struct super_block *sb, + struct nfs_mount_info *mount_info) { const struct super_block *old_sb = mount_info->cloned->sb; struct nfs_server *server = NFS_SB(sb); -- cgit v1.2.3 From fc098af16b9ff6d470d779d8ddcfb2d91869045a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 4 Jun 2017 10:23:25 +0200 Subject: Revert "tty: fix port buffer locking" This reverts commit 925bb1ce47f429f69aad35876df7ecd8c53deb7e. It causes lots of warnings and problems so for now, let's just revert it. Reported-by: Reported-by: Russell King Reported-by: Sergey Senozhatsky Reported-by: Geert Uytterhoeven Reported-by: Jiri Slaby Reported-by: Andrey Konovalov Acked-by: Vegard Nossum Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_port.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c index 4fb3165384c4..6b137194069f 100644 --- a/drivers/tty/tty_port.c +++ b/drivers/tty/tty_port.c @@ -34,9 +34,7 @@ static int tty_port_default_receive_buf(struct tty_port *port, if (!disc) return 0; - mutex_lock(&tty->atomic_write_lock); ret = tty_ldisc_receive_buf(disc, p, (char *)f, count); - mutex_unlock(&tty->atomic_write_lock); tty_ldisc_deref(disc); -- cgit v1.2.3 From f224c5768c78cb42f582636c4720a4d81d452778 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 18 May 2017 05:40:18 -0300 Subject: [media] atomisp: don't treat warnings as errors Several atomisp files use: ccflags-y += -Werror As, on media, our usual procedure is to use W=1, and atomisp has *a lot* of warnings with such flag enabled,like: ./drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_common/host/system_local.h:62:26: warning: 'DDR_BASE' defined but not used [-Wunused-const-variable=] At the end, it causes our build to fail, impacting our workflow. So, remove this crap. If one wants to force -Werror, he can still build with it enabled by passing a parameter to make. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/i2c/Makefile | 2 -- drivers/staging/media/atomisp/i2c/imx/Makefile | 2 -- drivers/staging/media/atomisp/i2c/ov5693/Makefile | 2 -- drivers/staging/media/atomisp/pci/atomisp2/Makefile | 2 +- 4 files changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/staging/media/atomisp/i2c/Makefile b/drivers/staging/media/atomisp/i2c/Makefile index 8ea01904c0ea..466517c7c8e6 100644 --- a/drivers/staging/media/atomisp/i2c/Makefile +++ b/drivers/staging/media/atomisp/i2c/Makefile @@ -19,5 +19,3 @@ obj-$(CONFIG_VIDEO_AP1302) += ap1302.o obj-$(CONFIG_VIDEO_LM3554) += lm3554.o -ccflags-y += -Werror - diff --git a/drivers/staging/media/atomisp/i2c/imx/Makefile b/drivers/staging/media/atomisp/i2c/imx/Makefile index 1d7f7ab94cac..6b13a3a66e49 100644 --- a/drivers/staging/media/atomisp/i2c/imx/Makefile +++ b/drivers/staging/media/atomisp/i2c/imx/Makefile @@ -4,5 +4,3 @@ imx1x5-objs := imx.o drv201.o ad5816g.o dw9714.o dw9719.o dw9718.o vcm.o otp.o o ov8858_driver-objs := ../ov8858.o dw9718.o vcm.o obj-$(CONFIG_VIDEO_OV8858) += ov8858_driver.o - -ccflags-y += -Werror diff --git a/drivers/staging/media/atomisp/i2c/ov5693/Makefile b/drivers/staging/media/atomisp/i2c/ov5693/Makefile index fceb9e9b881b..c9c0e1245858 100644 --- a/drivers/staging/media/atomisp/i2c/ov5693/Makefile +++ b/drivers/staging/media/atomisp/i2c/ov5693/Makefile @@ -1,3 +1 @@ obj-$(CONFIG_VIDEO_OV5693) += ov5693.o - -ccflags-y += -Werror diff --git a/drivers/staging/media/atomisp/pci/atomisp2/Makefile b/drivers/staging/media/atomisp/pci/atomisp2/Makefile index 3fa7c1c1479f..f126a89a08e9 100644 --- a/drivers/staging/media/atomisp/pci/atomisp2/Makefile +++ b/drivers/staging/media/atomisp/pci/atomisp2/Makefile @@ -351,5 +351,5 @@ DEFINES := -DHRT_HW -DHRT_ISP_CSS_CUSTOM_HOST -DHRT_USE_VIR_ADDRS -D__HOST__ DEFINES += -DATOMISP_POSTFIX=\"css2400b0_v21\" -DISP2400B0 DEFINES += -DSYSTEM_hive_isp_css_2400_system -DISP2400 -ccflags-y += $(INCLUDES) $(DEFINES) -fno-common -Werror +ccflags-y += $(INCLUDES) $(DEFINES) -fno-common -- cgit v1.2.3 From ca33784ba4949856a94a545c91429aae5c8b658d Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 19 May 2017 14:45:15 -0300 Subject: [media] rainshadow-cec: ensure exit_loop is intialized exit_loop is not being initialized, so it contains garbage. Ensure it is initialized to false. Detected by CoverityScan, CID#1436409 ("Uninitialized scalar variable") Fixes: ea6a69defd3311 ("[media] rainshadow-cec: avoid -Wmaybe-uninitialized warning") Signed-off-by: Colin Ian King Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/rainshadow-cec/rainshadow-cec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/usb/rainshadow-cec/rainshadow-cec.c b/drivers/media/usb/rainshadow-cec/rainshadow-cec.c index 541ca543f71f..71bd68548c9c 100644 --- a/drivers/media/usb/rainshadow-cec/rainshadow-cec.c +++ b/drivers/media/usb/rainshadow-cec/rainshadow-cec.c @@ -119,7 +119,7 @@ static void rain_irq_work_handler(struct work_struct *work) while (true) { unsigned long flags; - bool exit_loop; + bool exit_loop = false; char data; spin_lock_irqsave(&rain->buf_lock, flags); -- cgit v1.2.3 From 9177e51d1434076a91f9bfb693deae8b955d6d57 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 28 May 2017 05:48:37 -0300 Subject: [media] cec: select CEC_CORE instead of depend on it The CEC framework is used by both drm and media. That makes it tricky to get the dependencies right. This patch moves the CEC_CORE and MEDIA_CEC_NOTIFIER config options out of the media menu and instead drivers that want to use CEC should select CEC_CORE and MEDIA_CEC_NOTIFIER (if needed). Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/Kconfig | 6 ++++++ drivers/media/Makefile | 4 ++-- drivers/media/cec/Kconfig | 8 -------- drivers/media/i2c/Kconfig | 9 ++++++--- drivers/media/platform/Kconfig | 6 ++++-- drivers/media/platform/vivid/Kconfig | 3 ++- drivers/media/usb/pulse8-cec/Kconfig | 3 ++- drivers/media/usb/rainshadow-cec/Kconfig | 3 ++- 8 files changed, 24 insertions(+), 18 deletions(-) diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig index b72edd27f880..9ec634e2f2ba 100644 --- a/drivers/media/Kconfig +++ b/drivers/media/Kconfig @@ -2,6 +2,12 @@ # Multimedia device configuration # +config CEC_CORE + tristate + +config MEDIA_CEC_NOTIFIER + bool + menuconfig MEDIA_SUPPORT tristate "Multimedia support" depends on HAS_IOMEM diff --git a/drivers/media/Makefile b/drivers/media/Makefile index 523fea3648ad..044503aa8801 100644 --- a/drivers/media/Makefile +++ b/drivers/media/Makefile @@ -4,8 +4,6 @@ media-objs := media-device.o media-devnode.o media-entity.o -obj-$(CONFIG_CEC_CORE) += cec/ - # # I2C drivers should come before other drivers, otherwise they'll fail # when compiled as builtin drivers @@ -26,6 +24,8 @@ obj-$(CONFIG_DVB_CORE) += dvb-core/ # There are both core and drivers at RC subtree - merge before drivers obj-y += rc/ +obj-$(CONFIG_CEC_CORE) += cec/ + # # Finally, merge the drivers that require the core # diff --git a/drivers/media/cec/Kconfig b/drivers/media/cec/Kconfig index f944d93e3167..b7d876b384f6 100644 --- a/drivers/media/cec/Kconfig +++ b/drivers/media/cec/Kconfig @@ -1,11 +1,3 @@ -config CEC_CORE - tristate - depends on MEDIA_CEC_SUPPORT - default y - -config MEDIA_CEC_NOTIFIER - bool - config MEDIA_CEC_RC bool "HDMI CEC RC integration" depends on CEC_CORE && RC_CORE diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index fd181c99ce11..aaa9471c7d11 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -220,7 +220,8 @@ config VIDEO_ADV7604 config VIDEO_ADV7604_CEC bool "Enable Analog Devices ADV7604 CEC support" - depends on VIDEO_ADV7604 && CEC_CORE + depends on VIDEO_ADV7604 + select CEC_CORE ---help--- When selected the adv7604 will support the optional HDMI CEC feature. @@ -240,7 +241,8 @@ config VIDEO_ADV7842 config VIDEO_ADV7842_CEC bool "Enable Analog Devices ADV7842 CEC support" - depends on VIDEO_ADV7842 && CEC_CORE + depends on VIDEO_ADV7842 + select CEC_CORE ---help--- When selected the adv7842 will support the optional HDMI CEC feature. @@ -478,7 +480,8 @@ config VIDEO_ADV7511 config VIDEO_ADV7511_CEC bool "Enable Analog Devices ADV7511 CEC support" - depends on VIDEO_ADV7511 && CEC_CORE + depends on VIDEO_ADV7511 + select CEC_CORE ---help--- When selected the adv7511 will support the optional HDMI CEC feature. diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index ac026ee1ca07..017419bef9b1 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -501,7 +501,8 @@ if CEC_PLATFORM_DRIVERS config VIDEO_SAMSUNG_S5P_CEC tristate "Samsung S5P CEC driver" - depends on CEC_CORE && (PLAT_S5P || ARCH_EXYNOS || COMPILE_TEST) + depends on PLAT_S5P || ARCH_EXYNOS || COMPILE_TEST + select CEC_CORE select MEDIA_CEC_NOTIFIER ---help--- This is a driver for Samsung S5P HDMI CEC interface. It uses the @@ -511,7 +512,8 @@ config VIDEO_SAMSUNG_S5P_CEC config VIDEO_STI_HDMI_CEC tristate "STMicroelectronics STiH4xx HDMI CEC driver" - depends on CEC_CORE && (ARCH_STI || COMPILE_TEST) + depends on ARCH_STI || COMPILE_TEST + select CEC_CORE select MEDIA_CEC_NOTIFIER ---help--- This is a driver for STIH4xx HDMI CEC interface. It uses the diff --git a/drivers/media/platform/vivid/Kconfig b/drivers/media/platform/vivid/Kconfig index b36ac19dc6e4..154de92dd809 100644 --- a/drivers/media/platform/vivid/Kconfig +++ b/drivers/media/platform/vivid/Kconfig @@ -26,7 +26,8 @@ config VIDEO_VIVID config VIDEO_VIVID_CEC bool "Enable CEC emulation support" - depends on VIDEO_VIVID && CEC_CORE + depends on VIDEO_VIVID + select CEC_CORE ---help--- When selected the vivid module will emulate the optional HDMI CEC feature. diff --git a/drivers/media/usb/pulse8-cec/Kconfig b/drivers/media/usb/pulse8-cec/Kconfig index 8937f3986a01..18ead44824ba 100644 --- a/drivers/media/usb/pulse8-cec/Kconfig +++ b/drivers/media/usb/pulse8-cec/Kconfig @@ -1,6 +1,7 @@ config USB_PULSE8_CEC tristate "Pulse Eight HDMI CEC" - depends on USB_ACM && CEC_CORE + depends on USB_ACM + select CEC_CORE select SERIO select SERIO_SERPORT ---help--- diff --git a/drivers/media/usb/rainshadow-cec/Kconfig b/drivers/media/usb/rainshadow-cec/Kconfig index 3eb86607efb8..030ef01b1ff0 100644 --- a/drivers/media/usb/rainshadow-cec/Kconfig +++ b/drivers/media/usb/rainshadow-cec/Kconfig @@ -1,6 +1,7 @@ config USB_RAINSHADOW_CEC tristate "RainShadow Tech HDMI CEC" - depends on USB_ACM && CEC_CORE + depends on USB_ACM + select CEC_CORE select SERIO select SERIO_SERPORT ---help--- -- cgit v1.2.3 From e94c32818d865b620c9bbd2656ab3199259ef9ec Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 28 May 2017 05:58:04 -0300 Subject: [media] cec: rename MEDIA_CEC_NOTIFIER to CEC_NOTIFIER This config option is strictly speaking independent of the media subsystem since it can be used by drm as well. Besides, it looks odd when drivers select CEC_CORE and MEDIA_CEC_NOTIFIER, that's inconsistent naming. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/Kconfig | 2 +- drivers/media/cec/Makefile | 2 +- drivers/media/cec/cec-core.c | 4 ++-- drivers/media/platform/Kconfig | 4 ++-- include/media/cec-notifier.h | 2 +- include/media/cec.h | 4 ++-- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig index 9ec634e2f2ba..55d9c2b82b7e 100644 --- a/drivers/media/Kconfig +++ b/drivers/media/Kconfig @@ -5,7 +5,7 @@ config CEC_CORE tristate -config MEDIA_CEC_NOTIFIER +config CEC_NOTIFIER bool menuconfig MEDIA_SUPPORT diff --git a/drivers/media/cec/Makefile b/drivers/media/cec/Makefile index 402a6c62a3e8..eaf408e64669 100644 --- a/drivers/media/cec/Makefile +++ b/drivers/media/cec/Makefile @@ -1,6 +1,6 @@ cec-objs := cec-core.o cec-adap.o cec-api.o cec-edid.o -ifeq ($(CONFIG_MEDIA_CEC_NOTIFIER),y) +ifeq ($(CONFIG_CEC_NOTIFIER),y) cec-objs += cec-notifier.o endif diff --git a/drivers/media/cec/cec-core.c b/drivers/media/cec/cec-core.c index f9ebff90f8eb..feeb4c5afa69 100644 --- a/drivers/media/cec/cec-core.c +++ b/drivers/media/cec/cec-core.c @@ -187,7 +187,7 @@ static void cec_devnode_unregister(struct cec_devnode *devnode) put_device(&devnode->dev); } -#ifdef CONFIG_MEDIA_CEC_NOTIFIER +#ifdef CONFIG_CEC_NOTIFIER static void cec_cec_notify(struct cec_adapter *adap, u16 pa) { cec_s_phys_addr(adap, pa, false); @@ -355,7 +355,7 @@ void cec_unregister_adapter(struct cec_adapter *adap) adap->rc = NULL; #endif debugfs_remove_recursive(adap->cec_dir); -#ifdef CONFIG_MEDIA_CEC_NOTIFIER +#ifdef CONFIG_CEC_NOTIFIER if (adap->notifier) cec_notifier_unregister(adap->notifier); #endif diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index 017419bef9b1..041cb80a26b1 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -503,7 +503,7 @@ config VIDEO_SAMSUNG_S5P_CEC tristate "Samsung S5P CEC driver" depends on PLAT_S5P || ARCH_EXYNOS || COMPILE_TEST select CEC_CORE - select MEDIA_CEC_NOTIFIER + select CEC_NOTIFIER ---help--- This is a driver for Samsung S5P HDMI CEC interface. It uses the generic CEC framework interface. @@ -514,7 +514,7 @@ config VIDEO_STI_HDMI_CEC tristate "STMicroelectronics STiH4xx HDMI CEC driver" depends on ARCH_STI || COMPILE_TEST select CEC_CORE - select MEDIA_CEC_NOTIFIER + select CEC_NOTIFIER ---help--- This is a driver for STIH4xx HDMI CEC interface. It uses the generic CEC framework interface. diff --git a/include/media/cec-notifier.h b/include/media/cec-notifier.h index eb50ce54b759..413335c8cb52 100644 --- a/include/media/cec-notifier.h +++ b/include/media/cec-notifier.h @@ -29,7 +29,7 @@ struct edid; struct cec_adapter; struct cec_notifier; -#ifdef CONFIG_MEDIA_CEC_NOTIFIER +#if IS_REACHABLE(CONFIG_CEC_CORE) && IS_ENABLED(CONFIG_CEC_NOTIFIER) /** * cec_notifier_get - find or create a new cec_notifier for the given device. diff --git a/include/media/cec.h b/include/media/cec.h index b8eb895731d5..bfa88d4d67e1 100644 --- a/include/media/cec.h +++ b/include/media/cec.h @@ -173,7 +173,7 @@ struct cec_adapter { bool passthrough; struct cec_log_addrs log_addrs; -#ifdef CONFIG_MEDIA_CEC_NOTIFIER +#ifdef CONFIG_CEC_NOTIFIER struct cec_notifier *notifier; #endif @@ -300,7 +300,7 @@ u16 cec_phys_addr_for_input(u16 phys_addr, u8 input); */ int cec_phys_addr_validate(u16 phys_addr, u16 *parent, u16 *port); -#ifdef CONFIG_MEDIA_CEC_NOTIFIER +#ifdef CONFIG_CEC_NOTIFIER void cec_register_cec_notifier(struct cec_adapter *adap, struct cec_notifier *notifier); #endif -- cgit v1.2.3 From 20249f84238e006ef7b726d3211a70de7454d045 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 28 May 2017 05:52:16 -0300 Subject: [media] cec: drop MEDIA_CEC_DEBUG Just depend on DEBUG_FS, no need to invent a new kernel config. Especially since CEC can be enabled by drm without enabling MEDIA_SUPPORT. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/cec/Kconfig | 6 ------ drivers/media/cec/cec-adap.c | 2 +- drivers/media/cec/cec-core.c | 4 ++-- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/media/cec/Kconfig b/drivers/media/cec/Kconfig index b7d876b384f6..4e25a950ae6f 100644 --- a/drivers/media/cec/Kconfig +++ b/drivers/media/cec/Kconfig @@ -3,9 +3,3 @@ config MEDIA_CEC_RC depends on CEC_CORE && RC_CORE ---help--- Pass on CEC remote control messages to the RC framework. - -config MEDIA_CEC_DEBUG - bool "HDMI CEC debugfs interface" - depends on CEC_CORE && DEBUG_FS - ---help--- - Turns on the DebugFS interface for CEC devices. diff --git a/drivers/media/cec/cec-adap.c b/drivers/media/cec/cec-adap.c index f5fe01c9da8a..9dfc79800c71 100644 --- a/drivers/media/cec/cec-adap.c +++ b/drivers/media/cec/cec-adap.c @@ -1864,7 +1864,7 @@ void cec_monitor_all_cnt_dec(struct cec_adapter *adap) WARN_ON(call_op(adap, adap_monitor_all_enable, 0)); } -#ifdef CONFIG_MEDIA_CEC_DEBUG +#ifdef CONFIG_DEBUG_FS /* * Log the current state of the CEC adapter. * Very useful for debugging. diff --git a/drivers/media/cec/cec-core.c b/drivers/media/cec/cec-core.c index feeb4c5afa69..2f87748ba4fc 100644 --- a/drivers/media/cec/cec-core.c +++ b/drivers/media/cec/cec-core.c @@ -323,7 +323,7 @@ int cec_register_adapter(struct cec_adapter *adap, } dev_set_drvdata(&adap->devnode.dev, adap); -#ifdef CONFIG_MEDIA_CEC_DEBUG +#ifdef CONFIG_DEBUG_FS if (!top_cec_dir) return 0; @@ -395,7 +395,7 @@ static int __init cec_devnode_init(void) return ret; } -#ifdef CONFIG_MEDIA_CEC_DEBUG +#ifdef CONFIG_DEBUG_FS top_cec_dir = debugfs_create_dir("cec", NULL); if (IS_ERR_OR_NULL(top_cec_dir)) { pr_warn("cec: Failed to create debugfs cec dir\n"); -- cgit v1.2.3 From 963761a0b2e85663ee4a5630f72930885a06598a Mon Sep 17 00:00:00 2001 From: Sean Young Date: Wed, 24 May 2017 06:24:51 -0300 Subject: [media] rc-core: race condition during ir_raw_event_register() A rc device can call ir_raw_event_handle() after rc_allocate_device(), but before rc_register_device() has completed. This is racey because rcdev->raw is set before rcdev->raw->thread has a valid value. Cc: stable@kernel.org Reported-by: kbuild test robot Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/rc-ir-raw.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c index 90f66dc7c0d7..a2fc1a1d58b0 100644 --- a/drivers/media/rc/rc-ir-raw.c +++ b/drivers/media/rc/rc-ir-raw.c @@ -211,7 +211,7 @@ EXPORT_SYMBOL_GPL(ir_raw_event_set_idle); */ void ir_raw_event_handle(struct rc_dev *dev) { - if (!dev->raw) + if (!dev->raw || !dev->raw->thread) return; wake_up_process(dev->raw->thread); @@ -490,6 +490,7 @@ int ir_raw_event_register(struct rc_dev *dev) { int rc; struct ir_raw_handler *handler; + struct task_struct *thread; if (!dev) return -EINVAL; @@ -507,13 +508,15 @@ int ir_raw_event_register(struct rc_dev *dev) * because the event is coming from userspace */ if (dev->driver_type != RC_DRIVER_IR_RAW_TX) { - dev->raw->thread = kthread_run(ir_raw_event_thread, dev->raw, - "rc%u", dev->minor); + thread = kthread_run(ir_raw_event_thread, dev->raw, "rc%u", + dev->minor); - if (IS_ERR(dev->raw->thread)) { - rc = PTR_ERR(dev->raw->thread); + if (IS_ERR(thread)) { + rc = PTR_ERR(thread); goto out; } + + dev->raw->thread = thread; } mutex_lock(&ir_raw_handler_lock); -- cgit v1.2.3 From 246096690be0742d9bb5f3456d2cb95b68f7b46d Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Thu, 1 Jun 2017 16:08:13 -0500 Subject: net: qcom/emac: do not use hardware mdio automatic polling Use software polling (PHY_POLL) to check for link state changes instead of relying on the EMAC's hardware polling feature. Some PHY drivers are unable to get a functioning link because the HW polling is not robust enough. The EMAC is able to poll the PHY on the MDIO bus looking for link state changes (via the Link Status bit in the Status Register at address 0x1). When the link state changes, the EMAC triggers an interrupt and tells the driver what the new state is. The feature eliminates the need for software to poll the MDIO bus. Unfortunately, this feature is incompatible with phylib, because it ignores everything that the PHY core and PHY drivers are trying to do. In particular: 1. It assumes a compatible register set, so PHYs with different registers may not work. 2. It doesn't allow for hardware errata that have work-arounds implemented in the PHY driver. 3. It doesn't support multiple register pages. If the PHY core switches the register set to another page, the EMAC won't know the page has changed and will still attempt to read the same PHY register. 4. It only checks the copper side of the link, not the SGMII side. Some PHY drivers (e.g. at803x) may also check the SGMII side, and report the link as not ready during autonegotiation if the SGMII link is still down. Phylib then waits for another interrupt to query the PHY again, but the EMAC won't send another interrupt because it thinks the link is up. Cc: stable@vger.kernel.org # 4.11.x Tested-by: Manoj Iyer Signed-off-by: Timur Tabi Signed-off-by: David S. Miller --- drivers/net/ethernet/qualcomm/emac/emac-mac.c | 2 +- drivers/net/ethernet/qualcomm/emac/emac-phy.c | 75 ++------------------------- drivers/net/ethernet/qualcomm/emac/emac.c | 22 +------- 3 files changed, 6 insertions(+), 93 deletions(-) diff --git a/drivers/net/ethernet/qualcomm/emac/emac-mac.c b/drivers/net/ethernet/qualcomm/emac/emac-mac.c index cc065ffbe4b5..bcd4708b3745 100644 --- a/drivers/net/ethernet/qualcomm/emac/emac-mac.c +++ b/drivers/net/ethernet/qualcomm/emac/emac-mac.c @@ -931,7 +931,7 @@ int emac_mac_up(struct emac_adapter *adpt) emac_mac_config(adpt); emac_mac_rx_descs_refill(adpt, &adpt->rx_q); - adpt->phydev->irq = PHY_IGNORE_INTERRUPT; + adpt->phydev->irq = PHY_POLL; ret = phy_connect_direct(netdev, adpt->phydev, emac_adjust_link, PHY_INTERFACE_MODE_SGMII); if (ret) { diff --git a/drivers/net/ethernet/qualcomm/emac/emac-phy.c b/drivers/net/ethernet/qualcomm/emac/emac-phy.c index 441c19366489..18461fcb9815 100644 --- a/drivers/net/ethernet/qualcomm/emac/emac-phy.c +++ b/drivers/net/ethernet/qualcomm/emac/emac-phy.c @@ -13,15 +13,11 @@ /* Qualcomm Technologies, Inc. EMAC PHY Controller driver. */ -#include -#include -#include #include #include #include #include #include "emac.h" -#include "emac-mac.h" /* EMAC base register offsets */ #define EMAC_MDIO_CTRL 0x001414 @@ -52,62 +48,10 @@ #define MDIO_WAIT_TIMES 1000 -#define EMAC_LINK_SPEED_DEFAULT (\ - EMAC_LINK_SPEED_10_HALF |\ - EMAC_LINK_SPEED_10_FULL |\ - EMAC_LINK_SPEED_100_HALF |\ - EMAC_LINK_SPEED_100_FULL |\ - EMAC_LINK_SPEED_1GB_FULL) - -/** - * emac_phy_mdio_autopoll_disable() - disable mdio autopoll - * @adpt: the emac adapter - * - * The autopoll feature takes over the MDIO bus. In order for - * the PHY driver to be able to talk to the PHY over the MDIO - * bus, we need to temporarily disable the autopoll feature. - */ -static int emac_phy_mdio_autopoll_disable(struct emac_adapter *adpt) -{ - u32 val; - - /* disable autopoll */ - emac_reg_update32(adpt->base + EMAC_MDIO_CTRL, MDIO_AP_EN, 0); - - /* wait for any mdio polling to complete */ - if (!readl_poll_timeout(adpt->base + EMAC_MDIO_CTRL, val, - !(val & MDIO_BUSY), 100, MDIO_WAIT_TIMES * 100)) - return 0; - - /* failed to disable; ensure it is enabled before returning */ - emac_reg_update32(adpt->base + EMAC_MDIO_CTRL, 0, MDIO_AP_EN); - - return -EBUSY; -} - -/** - * emac_phy_mdio_autopoll_disable() - disable mdio autopoll - * @adpt: the emac adapter - * - * The EMAC has the ability to poll the external PHY on the MDIO - * bus for link state changes. This eliminates the need for the - * driver to poll the phy. If if the link state does change, - * the EMAC issues an interrupt on behalf of the PHY. - */ -static void emac_phy_mdio_autopoll_enable(struct emac_adapter *adpt) -{ - emac_reg_update32(adpt->base + EMAC_MDIO_CTRL, 0, MDIO_AP_EN); -} - static int emac_mdio_read(struct mii_bus *bus, int addr, int regnum) { struct emac_adapter *adpt = bus->priv; u32 reg; - int ret; - - ret = emac_phy_mdio_autopoll_disable(adpt); - if (ret) - return ret; emac_reg_update32(adpt->base + EMAC_PHY_STS, PHY_ADDR_BMSK, (addr << PHY_ADDR_SHFT)); @@ -122,24 +66,15 @@ static int emac_mdio_read(struct mii_bus *bus, int addr, int regnum) if (readl_poll_timeout(adpt->base + EMAC_MDIO_CTRL, reg, !(reg & (MDIO_START | MDIO_BUSY)), 100, MDIO_WAIT_TIMES * 100)) - ret = -EIO; - else - ret = (reg >> MDIO_DATA_SHFT) & MDIO_DATA_BMSK; + return -EIO; - emac_phy_mdio_autopoll_enable(adpt); - - return ret; + return (reg >> MDIO_DATA_SHFT) & MDIO_DATA_BMSK; } static int emac_mdio_write(struct mii_bus *bus, int addr, int regnum, u16 val) { struct emac_adapter *adpt = bus->priv; u32 reg; - int ret; - - ret = emac_phy_mdio_autopoll_disable(adpt); - if (ret) - return ret; emac_reg_update32(adpt->base + EMAC_PHY_STS, PHY_ADDR_BMSK, (addr << PHY_ADDR_SHFT)); @@ -155,11 +90,9 @@ static int emac_mdio_write(struct mii_bus *bus, int addr, int regnum, u16 val) if (readl_poll_timeout(adpt->base + EMAC_MDIO_CTRL, reg, !(reg & (MDIO_START | MDIO_BUSY)), 100, MDIO_WAIT_TIMES * 100)) - ret = -EIO; + return -EIO; - emac_phy_mdio_autopoll_enable(adpt); - - return ret; + return 0; } /* Configure the MDIO bus and connect the external PHY */ diff --git a/drivers/net/ethernet/qualcomm/emac/emac.c b/drivers/net/ethernet/qualcomm/emac/emac.c index 28a8cdc36485..98a326faea29 100644 --- a/drivers/net/ethernet/qualcomm/emac/emac.c +++ b/drivers/net/ethernet/qualcomm/emac/emac.c @@ -50,19 +50,7 @@ #define DMAR_DLY_CNT_DEF 15 #define DMAW_DLY_CNT_DEF 4 -#define IMR_NORMAL_MASK (\ - ISR_ERROR |\ - ISR_GPHY_LINK |\ - ISR_TX_PKT |\ - GPHY_WAKEUP_INT) - -#define IMR_EXTENDED_MASK (\ - SW_MAN_INT |\ - ISR_OVER |\ - ISR_ERROR |\ - ISR_GPHY_LINK |\ - ISR_TX_PKT |\ - GPHY_WAKEUP_INT) +#define IMR_NORMAL_MASK (ISR_ERROR | ISR_OVER | ISR_TX_PKT) #define ISR_TX_PKT (\ TX_PKT_INT |\ @@ -70,10 +58,6 @@ TX_PKT_INT2 |\ TX_PKT_INT3) -#define ISR_GPHY_LINK (\ - GPHY_LINK_UP_INT |\ - GPHY_LINK_DOWN_INT) - #define ISR_OVER (\ RFD0_UR_INT |\ RFD1_UR_INT |\ @@ -187,10 +171,6 @@ irqreturn_t emac_isr(int _irq, void *data) if (status & ISR_OVER) net_warn_ratelimited("warning: TX/RX overflow\n"); - /* link event */ - if (status & ISR_GPHY_LINK) - phy_mac_interrupt(adpt->phydev, !!(status & GPHY_LINK_UP_INT)); - exit: /* enable the interrupt */ writel(irq->mask, adpt->base + EMAC_INT_MASK); -- cgit v1.2.3 From 239e250e4acbc0104d514307029c0839e834a51a Mon Sep 17 00:00:00 2001 From: Richard Narron Date: Sun, 4 Jun 2017 16:23:18 -0700 Subject: fs/ufs: Set UFS default maximum bytes per file This fixes a problem with reading files larger than 2GB from a UFS-2 file system: https://bugzilla.kernel.org/show_bug.cgi?id=195721 The incorrect UFS s_maxsize limit became a problem as of commit c2a9737f45e2 ("vfs,mm: fix a dead loop in truncate_inode_pages_range()") which started using s_maxbytes to avoid a page index overflow in do_generic_file_read(). That caused files to be truncated on UFS-2 file systems because the default maximum file size is 2GB (MAX_NON_LFS) and UFS didn't update it. Here I simply increase the default to a common value used by other file systems. Signed-off-by: Richard Narron Cc: Al Viro Cc: Will B Cc: Theodore Ts'o Cc: # v4.9 and backports of c2a9737f45e2 Signed-off-by: Linus Torvalds --- fs/ufs/super.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/fs/ufs/super.c b/fs/ufs/super.c index 131b2b77c818..29ecaf739449 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -812,9 +812,8 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) uspi->s_dirblksize = UFS_SECTOR_SIZE; super_block_offset=UFS_SBLOCK; - /* Keep 2Gig file limit. Some UFS variants need to override - this but as I don't know which I'll let those in the know loosen - the rules */ + sb->s_maxbytes = MAX_LFS_FILESIZE; + switch (sbi->s_mount_opt & UFS_MOUNT_UFSTYPE) { case UFS_MOUNT_UFSTYPE_44BSD: UFSD("ufstype=44bsd\n"); -- cgit v1.2.3 From 3c2993b8c6143d8a5793746a54eba8f86f95240f Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 4 Jun 2017 16:47:43 -0700 Subject: Linux 4.12-rc4 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 470bd4d9513a..853ae9179af9 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 4 PATCHLEVEL = 12 SUBLEVEL = 0 -EXTRAVERSION = -rc3 +EXTRAVERSION = -rc4 NAME = Fearless Coyote # *DOCUMENTATION* -- cgit v1.2.3 From 5f733ee68f9a4df94775299ac6a7ab260704f6ed Mon Sep 17 00:00:00 2001 From: Liam McBirnie Date: Thu, 1 Jun 2017 15:36:01 +1000 Subject: ip6_tunnel: fix traffic class routing for tunnels ip6_route_output() requires that the flowlabel contains the traffic class for policy routing. Commit 0e9a709560db ("ip6_tunnel, ip6_gre: fix setting of DSCP on encapsulated packets") removed the code which previously added the traffic class to the flowlabel. The traffic class is added here because only route lookup needs the flowlabel to contain the traffic class. Fixes: 0e9a709560db ("ip6_tunnel, ip6_gre: fix setting of DSCP on encapsulated packets") Signed-off-by: Liam McBirnie Acked-by: Peter Dawson Signed-off-by: David S. Miller --- net/ipv6/ip6_tunnel.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 7ae6c503f1ca..9b37f9747fc6 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -1095,6 +1095,9 @@ int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield, if (!dst) { route_lookup: + /* add dsfield to flowlabel for route lookup */ + fl6->flowlabel = ip6_make_flowinfo(dsfield, fl6->flowlabel); + dst = ip6_route_output(net, NULL, fl6); if (dst->error) -- cgit v1.2.3 From a7c0b8bee212e22725196fda8389bff9ade3ac68 Mon Sep 17 00:00:00 2001 From: Michal Hocko Date: Fri, 2 Jun 2017 17:54:08 +0200 Subject: amd-xgbe: use PAGE_ALLOC_COSTLY_ORDER in xgbe_map_rx_buffer xgbe_map_rx_buffer is rather confused about what PAGE_ALLOC_COSTLY_ORDER means. It uses PAGE_ALLOC_COSTLY_ORDER-1 assuming that PAGE_ALLOC_COSTLY_ORDER is the first costly order which is not the case actually because orders larger than that are costly. And even that applies only to sleeping allocations which is not the case here. We simply do not perform any costly operations like reclaim or compaction for those. Simplify the code by dropping the order calculation and use PAGE_ALLOC_COSTLY_ORDER directly. Signed-off-by: Michal Hocko Acked-by: Tom Lendacky Signed-off-by: David S. Miller --- drivers/net/ethernet/amd/xgbe/xgbe-desc.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-desc.c b/drivers/net/ethernet/amd/xgbe/xgbe-desc.c index b3bc87fe3764..0a98c369df20 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-desc.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-desc.c @@ -324,7 +324,7 @@ static int xgbe_map_rx_buffer(struct xgbe_prv_data *pdata, struct xgbe_ring *ring, struct xgbe_ring_data *rdata) { - int order, ret; + int ret; if (!ring->rx_hdr_pa.pages) { ret = xgbe_alloc_pages(pdata, &ring->rx_hdr_pa, GFP_ATOMIC, 0); @@ -333,9 +333,8 @@ static int xgbe_map_rx_buffer(struct xgbe_prv_data *pdata, } if (!ring->rx_buf_pa.pages) { - order = max_t(int, PAGE_ALLOC_COSTLY_ORDER - 1, 0); ret = xgbe_alloc_pages(pdata, &ring->rx_buf_pa, GFP_ATOMIC, - order); + PAGE_ALLOC_COSTLY_ORDER); if (ret) return ret; } -- cgit v1.2.3 From 38b257938ac6655d0d6333743303231b9c465ec1 Mon Sep 17 00:00:00 2001 From: Soheil Hassas Yeganeh Date: Fri, 2 Jun 2017 12:38:22 -0400 Subject: sock: reset sk_err when the error queue is empty Prior to f5f99309fa74 (sock: do not set sk_err in sock_dequeue_err_skb), sk_err was reset to the error of the skb on the head of the error queue. Applications, most notably ping, are relying on this behavior to reset sk_err for ICMP packets. Set sk_err to the ICMP error when there is an ICMP packet at the head of the error queue. Fixes: f5f99309fa74 (sock: do not set sk_err in sock_dequeue_err_skb) Reported-by: Cyril Hrubis Tested-by: Cyril Hrubis Signed-off-by: Soheil Hassas Yeganeh Signed-off-by: Eric Dumazet Signed-off-by: Willem de Bruijn Signed-off-by: David S. Miller --- net/core/skbuff.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 346d3e85dfbc..b1be7c01efe2 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -3754,8 +3754,11 @@ struct sk_buff *sock_dequeue_err_skb(struct sock *sk) spin_lock_irqsave(&q->lock, flags); skb = __skb_dequeue(q); - if (skb && (skb_next = skb_peek(q))) + if (skb && (skb_next = skb_peek(q))) { icmp_next = is_icmp_err_skb(skb_next); + if (icmp_next) + sk->sk_err = SKB_EXT_ERR(skb_next)->ee.ee_origin; + } spin_unlock_irqrestore(&q->lock, flags); if (is_icmp_err_skb(skb) && !icmp_next) -- cgit v1.2.3 From 9a1c44d989bff4c992b8b9a112d9fda275ea5515 Mon Sep 17 00:00:00 2001 From: Eric Garver Date: Fri, 2 Jun 2017 14:54:10 -0400 Subject: geneve: fix needed_headroom and max_mtu for collect_metadata Since commit 9b4437a5b870 ("geneve: Unify LWT and netdev handling.") when using COLLECT_METADATA geneve devices are created with too small of a needed_headroom and too large of a max_mtu. This is because ip_tunnel_info_af() is not valid with the device level info when using COLLECT_METADATA and we mistakenly fall into the IPv4 case. For COLLECT_METADATA, always use the worst case of ipv6 since both sockets are created. Fixes: 9b4437a5b870 ("geneve: Unify LWT and netdev handling.") Signed-off-by: Eric Garver Acked-by: Pravin B Shelar Signed-off-by: David S. Miller --- drivers/net/geneve.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c index 959fd12d2e67..6ebb0f559a42 100644 --- a/drivers/net/geneve.c +++ b/drivers/net/geneve.c @@ -1133,7 +1133,7 @@ static int geneve_configure(struct net *net, struct net_device *dev, /* make enough headroom for basic scenario */ encap_len = GENEVE_BASE_HLEN + ETH_HLEN; - if (ip_tunnel_info_af(info) == AF_INET) { + if (!metadata && ip_tunnel_info_af(info) == AF_INET) { encap_len += sizeof(struct iphdr); dev->max_mtu -= sizeof(struct iphdr); } else { -- cgit v1.2.3 From e3e86b5119f81e5e2499bea7ea1ebe8ac6aab789 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 4 Jun 2017 21:41:10 -0400 Subject: ipv6: Fix leak in ipv6_gso_segment(). If ip6_find_1stfragopt() fails and we return an error we have to free up 'segs' because nobody else is going to. Fixes: 2423496af35d ("ipv6: Prevent overrun when parsing v6 header options") Reported-by: Ben Hutchings Signed-off-by: David S. Miller --- net/ipv6/ip6_offload.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c index 280268f1dd7b..cdb3728faca7 100644 --- a/net/ipv6/ip6_offload.c +++ b/net/ipv6/ip6_offload.c @@ -116,8 +116,10 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, if (udpfrag) { int err = ip6_find_1stfragopt(skb, &prevhdr); - if (err < 0) + if (err < 0) { + kfree_skb_list(segs); return ERR_PTR(err); + } fptr = (struct frag_hdr *)((u8 *)ipv6h + err); fptr->frag_off = htons(offset); if (skb->next) -- cgit v1.2.3 From b07ac9894644202614ca87c69f3f45e424a82fef Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 2 Jun 2017 22:05:23 -0700 Subject: net: dsa: Fix stale cpu_switch reference after unbind then bind Commit 9520ed8fb841 ("net: dsa: use cpu_switch instead of ds[0]") replaced the use of dst->ds[0] with dst->cpu_switch since that is functionally equivalent, however, we can now run into an use after free scenario after unbinding then rebinding the switch driver. The use after free happens because we do correctly initialize dst->cpu_switch the first time we probe in dsa_cpu_parse(), then we unbind the driver: dsa_dst_unapply() is called, and we rebind again. dst->cpu_switch now points to a freed "ds" structure, and so when we finally dereference it in dsa_cpu_port_ethtool_setup(), we oops. To fix this, simply set dst->cpu_switch to NULL in dsa_dst_unapply() which guarantees that we always correctly re-assign dst->cpu_switch in dsa_cpu_parse(). Fixes: 9520ed8fb841 ("net: dsa: use cpu_switch instead of ds[0]") Signed-off-by: Florian Fainelli Reviewed-by: Vivien Didelot Signed-off-by: David S. Miller --- net/dsa/dsa2.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c index 033b3bfb63dc..7796580e99ee 100644 --- a/net/dsa/dsa2.c +++ b/net/dsa/dsa2.c @@ -484,8 +484,10 @@ static void dsa_dst_unapply(struct dsa_switch_tree *dst) dsa_ds_unapply(dst, ds); } - if (dst->cpu_switch) + if (dst->cpu_switch) { dsa_cpu_port_ethtool_restore(dst->cpu_switch); + dst->cpu_switch = NULL; + } pr_info("DSA: tree %d unapplied\n", dst->tree); dst->applied = false; -- cgit v1.2.3 From 77d4b1d36926a9b8387c6b53eeba42bcaaffcea3 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sat, 3 Jun 2017 09:29:25 -0700 Subject: net: ping: do not abuse udp_poll() Alexander reported various KASAN messages triggered in recent kernels The problem is that ping sockets should not use udp_poll() in the first place, and recent changes in UDP stack finally exposed this old bug. Fixes: c319b4d76b9e ("net: ipv4: add IPPROTO_ICMP socket kind") Fixes: 6d0bfe226116 ("net: ipv6: Add IPv6 support to the ping socket.") Signed-off-by: Eric Dumazet Reported-by: Sasha Levin Cc: Solar Designer Cc: Vasiliy Kulikov Cc: Lorenzo Colitti Acked-By: Lorenzo Colitti Tested-By: Lorenzo Colitti Signed-off-by: David S. Miller --- include/net/ipv6.h | 1 + net/ipv4/af_inet.c | 2 +- net/ipv6/ping.c | 2 +- net/ipv6/raw.c | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/include/net/ipv6.h b/include/net/ipv6.h index dbf0abba33b8..3e505bbff8ca 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -1007,6 +1007,7 @@ int inet6_hash_connect(struct inet_timewait_death_row *death_row, */ extern const struct proto_ops inet6_stream_ops; extern const struct proto_ops inet6_dgram_ops; +extern const struct proto_ops inet6_sockraw_ops; struct group_source_req; struct group_filter; diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index f3dad1661343..58925b6597de 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -1043,7 +1043,7 @@ static struct inet_protosw inetsw_array[] = .type = SOCK_DGRAM, .protocol = IPPROTO_ICMP, .prot = &ping_prot, - .ops = &inet_dgram_ops, + .ops = &inet_sockraw_ops, .flags = INET_PROTOSW_REUSE, }, diff --git a/net/ipv6/ping.c b/net/ipv6/ping.c index 9b522fa90e6d..ac826dd338ff 100644 --- a/net/ipv6/ping.c +++ b/net/ipv6/ping.c @@ -192,7 +192,7 @@ static struct inet_protosw pingv6_protosw = { .type = SOCK_DGRAM, .protocol = IPPROTO_ICMPV6, .prot = &pingv6_prot, - .ops = &inet6_dgram_ops, + .ops = &inet6_sockraw_ops, .flags = INET_PROTOSW_REUSE, }; diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 1f992d9e261d..60be012fe708 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -1338,7 +1338,7 @@ void raw6_proc_exit(void) #endif /* CONFIG_PROC_FS */ /* Same as inet6_dgram_ops, sans udp_poll. */ -static const struct proto_ops inet6_sockraw_ops = { +const struct proto_ops inet6_sockraw_ops = { .family = PF_INET6, .owner = THIS_MODULE, .release = inet6_release, -- cgit v1.2.3 From b699d0035836f6712917a41e7ae58d84359b8ff9 Mon Sep 17 00:00:00 2001 From: Haishuang Yan Date: Sun, 4 Jun 2017 14:43:43 +0800 Subject: sit: reload iphdr in ipip6_rcv Since iptunnel_pull_header() can call pskb_may_pull(), we must reload any pointer that was related to skb->head. Fixes: a09a4c8dd1ec ("tunnels: Remove encapsulation offloads on decap") Signed-off-by: Haishuang Yan Signed-off-by: David S. Miller --- net/ipv6/sit.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 61e5902f0687..af832e7ce80f 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -657,6 +657,7 @@ static int ipip6_rcv(struct sk_buff *skb) if (iptunnel_pull_header(skb, 0, htons(ETH_P_IPV6), !net_eq(tunnel->net, dev_net(tunnel->dev)))) goto out; + iph = ip_hdr(skb); err = IP_ECN_decapsulate(iph, skb); if (unlikely(err)) { -- cgit v1.2.3 From 6dc06c08bef1c746ff8da33dab677cfbacdcad32 Mon Sep 17 00:00:00 2001 From: Talat Batheesh Date: Sun, 4 Jun 2017 14:30:07 +0300 Subject: net/mlx4: Fix the check in attaching steering rules Our previous patch (cited below) introduced a regression for RAW Eth QPs. Fix it by checking if the QP number provided by user-space exists, hence allowing steering rules to be added for valid QPs only. Fixes: 89c557687a32 ("net/mlx4_en: Avoid adding steering rules with invalid ring") Reported-by: Or Gerlitz Signed-off-by: Talat Batheesh Signed-off-by: Tariq Toukan Acked-by: Or Gerlitz Reviewed-by: Leon Romanovsky Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/en_ethtool.c | 5 ----- drivers/net/ethernet/mellanox/mlx4/mcg.c | 15 +++++++++++---- drivers/net/ethernet/mellanox/mlx4/qp.c | 13 +++++++++++++ include/linux/mlx4/qp.h | 1 + 4 files changed, 25 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c index ae5fdc2df654..ffbcb27c05e5 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c @@ -1562,11 +1562,6 @@ static int mlx4_en_flow_replace(struct net_device *dev, qpn = priv->drop_qp.qpn; else if (cmd->fs.ring_cookie & EN_ETHTOOL_QP_ATTACH) { qpn = cmd->fs.ring_cookie & (EN_ETHTOOL_QP_ATTACH - 1); - if (qpn < priv->rss_map.base_qpn || - qpn >= priv->rss_map.base_qpn + priv->rx_ring_num) { - en_warn(priv, "rxnfc: QP (0x%x) doesn't exist\n", qpn); - return -EINVAL; - } } else { if (cmd->fs.ring_cookie >= priv->rx_ring_num) { en_warn(priv, "rxnfc: RX ring (%llu) doesn't exist\n", diff --git a/drivers/net/ethernet/mellanox/mlx4/mcg.c b/drivers/net/ethernet/mellanox/mlx4/mcg.c index 1a670b681555..0710b3677464 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mcg.c +++ b/drivers/net/ethernet/mellanox/mlx4/mcg.c @@ -35,6 +35,7 @@ #include #include +#include #include #include "mlx4.h" @@ -985,16 +986,21 @@ int mlx4_flow_attach(struct mlx4_dev *dev, if (IS_ERR(mailbox)) return PTR_ERR(mailbox); + if (!mlx4_qp_lookup(dev, rule->qpn)) { + mlx4_err_rule(dev, "QP doesn't exist\n", rule); + ret = -EINVAL; + goto out; + } + trans_rule_ctrl_to_hw(rule, mailbox->buf); size += sizeof(struct mlx4_net_trans_rule_hw_ctrl); list_for_each_entry(cur, &rule->list, list) { ret = parse_trans_rule(dev, cur, mailbox->buf + size); - if (ret < 0) { - mlx4_free_cmd_mailbox(dev, mailbox); - return ret; - } + if (ret < 0) + goto out; + size += ret; } @@ -1021,6 +1027,7 @@ int mlx4_flow_attach(struct mlx4_dev *dev, } } +out: mlx4_free_cmd_mailbox(dev, mailbox); return ret; diff --git a/drivers/net/ethernet/mellanox/mlx4/qp.c b/drivers/net/ethernet/mellanox/mlx4/qp.c index 2d6abd4662b1..ad92d2311478 100644 --- a/drivers/net/ethernet/mellanox/mlx4/qp.c +++ b/drivers/net/ethernet/mellanox/mlx4/qp.c @@ -384,6 +384,19 @@ static void mlx4_qp_free_icm(struct mlx4_dev *dev, int qpn) __mlx4_qp_free_icm(dev, qpn); } +struct mlx4_qp *mlx4_qp_lookup(struct mlx4_dev *dev, u32 qpn) +{ + struct mlx4_qp_table *qp_table = &mlx4_priv(dev)->qp_table; + struct mlx4_qp *qp; + + spin_lock(&qp_table->lock); + + qp = __mlx4_qp_lookup(dev, qpn); + + spin_unlock(&qp_table->lock); + return qp; +} + int mlx4_qp_alloc(struct mlx4_dev *dev, int qpn, struct mlx4_qp *qp, gfp_t gfp) { struct mlx4_priv *priv = mlx4_priv(dev); diff --git a/include/linux/mlx4/qp.h b/include/linux/mlx4/qp.h index b4ee8f62ce8d..8e2828d48d7f 100644 --- a/include/linux/mlx4/qp.h +++ b/include/linux/mlx4/qp.h @@ -470,6 +470,7 @@ struct mlx4_update_qp_params { u16 rate_val; }; +struct mlx4_qp *mlx4_qp_lookup(struct mlx4_dev *dev, u32 qpn); int mlx4_update_qp(struct mlx4_dev *dev, u32 qpn, enum mlx4_update_qp_attr attr, struct mlx4_update_qp_params *params); -- cgit v1.2.3 From 1195892c091a15cc862f4e202482a36adc924e12 Mon Sep 17 00:00:00 2001 From: Breno Leitao Date: Fri, 2 Jun 2017 18:43:30 -0300 Subject: powerpc/kernel: Fix FP and vector register restoration Currently tsk->thread->load_vec and load_fp are not initialized during task creation, which can lead to garbage values in these variables (non-zero values). These variables will be checked later in restore_math() to validate if the FP and vector registers are being utilized. Since these values might be non-zero, the restore_math() will continue to save the FP and vectors even if they were never utilized by the userspace application. load_fp and load_vec counters will then overflow (they wrap at 255) and the FP and Altivec will be finally disabled, but before that condition is reached (counter overflow) several context switches will have restored FP and vector registers without need, causing a performance degradation. Fixes: 70fe3d980f5f ("powerpc: Restore FPU/VEC/VSX if previously used") Cc: stable@vger.kernel.org # v4.6+ Signed-off-by: Breno Leitao Signed-off-by: Gustavo Romero Acked-by: Anton Blanchard Signed-off-by: Michael Ellerman --- arch/powerpc/kernel/process.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index baae104b16c7..a9435397eab8 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -1666,6 +1666,7 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp) #ifdef CONFIG_VSX current->thread.used_vsr = 0; #endif + current->thread.load_fp = 0; memset(¤t->thread.fp_state, 0, sizeof(current->thread.fp_state)); current->thread.fp_save_area = NULL; #ifdef CONFIG_ALTIVEC @@ -1674,6 +1675,7 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp) current->thread.vr_save_area = NULL; current->thread.vrsave = 0; current->thread.used_vr = 0; + current->thread.load_vec = 0; #endif /* CONFIG_ALTIVEC */ #ifdef CONFIG_SPE memset(current->thread.evr, 0, sizeof(current->thread.evr)); -- cgit v1.2.3 From ae1d557d8f30cb097b4d1f2ab04fa294588ee1cf Mon Sep 17 00:00:00 2001 From: Christian Sünkenberg Date: Sun, 4 Jun 2017 19:18:39 +0200 Subject: x86/cpu/cyrix: Add alternative Device ID of Geode GX1 SoC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A SoC variant of Geode GX1, notably NSC branded SC1100, seems to report an inverted Device ID in its DIR0 configuration register, specifically 0xb instead of the expected 0x4. Catch this presumably quirky version so it's properly recognized as GX1 and has its cache switched to write-back mode, which provides a significant performance boost in most workloads. SC1100's datasheet "Geode™ SC1100 Information Appliance On a Chip", states in section 1.1.7.1 "Device ID" that device identification values are specified in SC1100's device errata. These, however, seem to not have been publicly released. Wading through a number of boot logs and /proc/cpuinfo dumps found on pastebin and blogs, this patch should mostly be relevant for a number of now admittedly aging Soekris NET4801 and PC Engines WRAP devices, the latter being the platform this issue was discovered on. Performance impact was verified using "openssl speed", with write-back caching scaling throughput between -3% and +41%. Signed-off-by: Christian Sünkenberg Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1496596719.26725.14.camel@student.kit.edu Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/cyrix.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/kernel/cpu/cyrix.c b/arch/x86/kernel/cpu/cyrix.c index a70fd61095f8..6f077445647a 100644 --- a/arch/x86/kernel/cpu/cyrix.c +++ b/arch/x86/kernel/cpu/cyrix.c @@ -255,6 +255,7 @@ static void init_cyrix(struct cpuinfo_x86 *c) break; case 4: /* MediaGX/GXm or Geode GXM/GXLV/GX1 */ + case 11: /* GX1 with inverted Device ID */ #ifdef CONFIG_PCI { u32 vendor, device; -- cgit v1.2.3 From 7ef4783e19a84fe1e8b58f4c27b858dfdcaef207 Mon Sep 17 00:00:00 2001 From: Vladimir Murzin Date: Wed, 24 May 2017 10:30:18 +0100 Subject: ARM: 8676/1: NOMMU: provide pgprot_device() macro NOMMU build leads to the following error: CC drivers/pci/mmap.o drivers/pci/mmap.c: In function 'pci_mmap_resource_range': drivers/pci/mmap.c:60:3: error: implicit declaration of function 'pgprot_device' [-Werror=implicit-function-declaration] vma->vm_page_prot = pgprot_device(vma->vm_page_prot); ^ cc1: some warnings being treated as errors scripts/Makefile.build:302: recipe for target 'drivers/pci/mmap.o' failed make[2]: *** [drivers/pci/mmap.o] Error 1 scripts/Makefile.build:561: recipe for target 'drivers/pci' failed make[1]: *** [drivers/pci] Error 2 Makefile:1016: recipe for target 'drivers' failed make: *** [drivers] Error 2 Fix it with support of pgprot_device() macro for NOMMU. Fixes: 00d2904ffeac ("ARM/PCI: Use generic pci_mmap_resource_range()") Signed-off-by: Vladimir Murzin Signed-off-by: Russell King --- arch/arm/include/asm/pgtable-nommu.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/include/asm/pgtable-nommu.h b/arch/arm/include/asm/pgtable-nommu.h index 302240c19a5a..a0d726a47c8a 100644 --- a/arch/arm/include/asm/pgtable-nommu.h +++ b/arch/arm/include/asm/pgtable-nommu.h @@ -66,6 +66,7 @@ typedef pte_t *pte_addr_t; #define pgprot_noncached(prot) (prot) #define pgprot_writecombine(prot) (prot) #define pgprot_dmacoherent(prot) (prot) +#define pgprot_device(prot) (prot) /* -- cgit v1.2.3 From 06a4b6d009a1b74a6ec46c5418b46cc53a79fcb8 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Wed, 24 May 2017 15:31:57 +0100 Subject: ARM: 8677/1: boot/compressed: fix decompressor header layout for v7-M As reported by Patrice, the header layout of the decompressor is incorrect when building for v7-M. In this case, the __nop macro resolves to 'mov r0, r0', which is emitted as a narrow encoding, resulting in the header data fields to end up at lower offsets than required. Given the variety of targets we need to support with the same code, the startup sequence is a bit of a jumble, and uses instructions and macros whose encoding widths cannot be specified (badr), or only exist in a narrow encoding (bx) So force the use of a wide encoding in __nop, and replace the start sequence with a simple jump to the label marking the start of code, preceded by a Thumb2 mode switch if required (using explicit wide encodings where appropriate). The label itself can be moved to the start of code [where it belongs] due to the larger range of branch instructions as compared to adr instructions. Reported-by: Patrice CHOTARD Acked-by: Nicolas Pitre Signed-off-by: Ard Biesheuvel Signed-off-by: Russell King --- arch/arm/boot/compressed/efi-header.S | 4 +--- arch/arm/boot/compressed/head.S | 17 ++++++++++------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/arch/arm/boot/compressed/efi-header.S b/arch/arm/boot/compressed/efi-header.S index 9d5dc4fda3c1..3f7d1b74c5e0 100644 --- a/arch/arm/boot/compressed/efi-header.S +++ b/arch/arm/boot/compressed/efi-header.S @@ -17,14 +17,12 @@ @ there. .inst 'M' | ('Z' << 8) | (0x1310 << 16) @ tstne r0, #0x4d000 #else - mov r0, r0 + W(mov) r0, r0 #endif .endm .macro __EFI_HEADER #ifdef CONFIG_EFI_STUB - b __efi_start - .set start_offset, __efi_start - start .org start + 0x3c @ diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index 7c711ba61417..8a756870c238 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -130,19 +130,22 @@ start: .rept 7 __nop .endr - ARM( mov r0, r0 ) - ARM( b 1f ) - THUMB( badr r12, 1f ) - THUMB( bx r12 ) +#ifndef CONFIG_THUMB2_KERNEL + mov r0, r0 +#else + AR_CLASS( sub pc, pc, #3 ) @ A/R: switch to Thumb2 mode + M_CLASS( nop.w ) @ M: already in Thumb2 mode + .thumb +#endif + W(b) 1f .word _magic_sig @ Magic numbers to help the loader .word _magic_start @ absolute load/run zImage address .word _magic_end @ zImage end address .word 0x04030201 @ endianness flag - THUMB( .thumb ) -1: __EFI_HEADER - + __EFI_HEADER +1: ARM_BE8( setend be ) @ go BE8 if compiled for BE8 AR_CLASS( mrs r9, cpsr ) #ifdef CONFIG_ARM_VIRT_EXT -- cgit v1.2.3 From 57caf4ec2b8bfbcb4f738ab5a12eedf3a8786045 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 5 Jun 2017 14:51:18 +0200 Subject: cpufreq: intel_pstate: Avoid division by 0 in min_perf_pct_min() Commit c5a2ee7dde89 (cpufreq: intel_pstate: Active mode P-state limits rework) incorrectly assumed that pstate.turbo_pstate would always be nonzero for CPU0 in min_perf_pct_min() if cpufreq_register_driver() had succeeded which may not be the case in virtualized environments. If that assumption doesn't hold, it leads to an early crash on boot in intel_pstate_register_driver(), so add a sanity check to min_perf_pct_min() to prevent the crash from happening. Fixes: c5a2ee7dde89 (cpufreq: intel_pstate: Active mode P-state limits rework) Reported-and-tested-by: Jongman Heo Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/intel_pstate.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index b7de5bd76a31..eb1158532de3 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -571,9 +571,10 @@ static inline void update_turbo_state(void) static int min_perf_pct_min(void) { struct cpudata *cpu = all_cpu_data[0]; + int turbo_pstate = cpu->pstate.turbo_pstate; - return DIV_ROUND_UP(cpu->pstate.min_pstate * 100, - cpu->pstate.turbo_pstate); + return turbo_pstate ? + DIV_ROUND_UP(cpu->pstate.min_pstate * 100, turbo_pstate) : 0; } static s16 intel_pstate_get_epb(struct cpudata *cpu_data) -- cgit v1.2.3 From 1e0ce2a1ee0d5fb334e82e80600f1e8e77df525c Mon Sep 17 00:00:00 2001 From: Anmol Sarma Date: Sat, 3 Jun 2017 17:40:54 +0530 Subject: net: Update TCP congestion control documentation Update tcp.txt to fix mandatory congestion control ops and default CCA selection. Also, fix comment in tcp.h for undo_cwnd. Signed-off-by: Anmol Sarma Signed-off-by: David S. Miller --- Documentation/networking/tcp.txt | 31 +++++++++++++------------------ include/net/tcp.h | 2 +- 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/Documentation/networking/tcp.txt b/Documentation/networking/tcp.txt index bdc4c0db51e1..9c7139d57e57 100644 --- a/Documentation/networking/tcp.txt +++ b/Documentation/networking/tcp.txt @@ -1,7 +1,7 @@ TCP protocol ============ -Last updated: 9 February 2008 +Last updated: 3 June 2017 Contents ======== @@ -29,18 +29,19 @@ As of 2.6.13, Linux supports pluggable congestion control algorithms. A congestion control mechanism can be registered through functions in tcp_cong.c. The functions used by the congestion control mechanism are registered via passing a tcp_congestion_ops struct to -tcp_register_congestion_control. As a minimum name, ssthresh, -cong_avoid must be valid. +tcp_register_congestion_control. As a minimum, the congestion control +mechanism must provide a valid name and must implement either ssthresh, +cong_avoid and undo_cwnd hooks or the "omnipotent" cong_control hook. Private data for a congestion control mechanism is stored in tp->ca_priv. tcp_ca(tp) returns a pointer to this space. This is preallocated space - it is important to check the size of your private data will fit this space, or -alternatively space could be allocated elsewhere and a pointer to it could +alternatively, space could be allocated elsewhere and a pointer to it could be stored here. There are three kinds of congestion control algorithms currently: The simplest ones are derived from TCP reno (highspeed, scalable) and just -provide an alternative the congestion window calculation. More complex +provide an alternative congestion window calculation. More complex ones like BIC try to look at other events to provide better heuristics. There are also round trip time based algorithms like Vegas and Westwood+. @@ -49,21 +50,15 @@ Good TCP congestion control is a complex problem because the algorithm needs to maintain fairness and performance. Please review current research and RFC's before developing new modules. -The method that is used to determine which congestion control mechanism is -determined by the setting of the sysctl net.ipv4.tcp_congestion_control. -The default congestion control will be the last one registered (LIFO); -so if you built everything as modules, the default will be reno. If you -build with the defaults from Kconfig, then CUBIC will be builtin (not a -module) and it will end up the default. +The default congestion control mechanism is chosen based on the +DEFAULT_TCP_CONG Kconfig parameter. If you really want a particular default +value then you can set it using sysctl net.ipv4.tcp_congestion_control. The +module will be autoloaded if needed and you will get the expected protocol. If +you ask for an unknown congestion method, then the sysctl attempt will fail. -If you really want a particular default value then you will need -to set it with the sysctl. If you use a sysctl, the module will be autoloaded -if needed and you will get the expected protocol. If you ask for an -unknown congestion method, then the sysctl attempt will fail. - -If you remove a tcp congestion control module, then you will get the next +If you remove a TCP congestion control module, then you will get the next available one. Since reno cannot be built as a module, and cannot be -deleted, it will always be available. +removed, it will always be available. How the new TCP output machine [nyi] works. =========================================== diff --git a/include/net/tcp.h b/include/net/tcp.h index 38a7427ae902..be6223c586fa 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -924,7 +924,7 @@ struct tcp_congestion_ops { void (*cwnd_event)(struct sock *sk, enum tcp_ca_event ev); /* call when ack arrives (optional) */ void (*in_ack_event)(struct sock *sk, u32 flags); - /* new value of cwnd after loss (optional) */ + /* new value of cwnd after loss (required) */ u32 (*undo_cwnd)(struct sock *sk); /* hook for packet ack accounting (optional) */ void (*pkts_acked)(struct sock *sk, const struct ack_sample *sample); -- cgit v1.2.3 From 6044bd4a7d580d4459b992bc6631c817486a1514 Mon Sep 17 00:00:00 2001 From: Haishuang Yan Date: Mon, 5 Jun 2017 08:57:21 +0800 Subject: devlink: fix potential memort leak We must free allocated skb when genlmsg_put() return fails. Fixes: 1555d204e743 ("devlink: Support for pipeline debug (dpipe)") Signed-off-by: Haishuang Yan Acked-by: Jiri Pirko Signed-off-by: David S. Miller --- net/core/devlink.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/net/core/devlink.c b/net/core/devlink.c index b0b87a292e7c..a0adfc31a3fe 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -1680,8 +1680,10 @@ start_again: hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq, &devlink_nl_family, NLM_F_MULTI, cmd); - if (!hdr) + if (!hdr) { + nlmsg_free(skb); return -EMSGSIZE; + } if (devlink_nl_put_handle(skb, devlink)) goto nla_put_failure; @@ -2098,8 +2100,10 @@ start_again: hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq, &devlink_nl_family, NLM_F_MULTI, cmd); - if (!hdr) + if (!hdr) { + nlmsg_free(skb); return -EMSGSIZE; + } if (devlink_nl_put_handle(skb, devlink)) goto nla_put_failure; -- cgit v1.2.3 From 6c6ab3e73b391b38c9749c77775bf21479ed7d60 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sun, 4 Jun 2017 19:46:53 -0700 Subject: net: phy: fix kernel-doc warnings Fix kernel-doc warnings (typo) in drivers/net/phy/phy.c: ..//drivers/net/phy/phy.c:259: warning: No description found for parameter 'features' ..//drivers/net/phy/phy.c:259: warning: Excess function parameter 'feature' description in 'phy_lookup_setting' Signed-off-by: Randy Dunlap Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/phy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 82ab8fb82587..7524caa0f29d 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -241,7 +241,7 @@ static const struct phy_setting settings[] = { * phy_lookup_setting - lookup a PHY setting * @speed: speed to match * @duplex: duplex to match - * @feature: allowed link modes + * @features: allowed link modes * @exact: an exact match is required * * Search the settings array for a setting that matches the speed and -- cgit v1.2.3 From 269f9883fe254d109afdfc657875c456d6fabb08 Mon Sep 17 00:00:00 2001 From: Ido Shamay Date: Mon, 5 Jun 2017 10:44:56 +0300 Subject: net/mlx4: Check if Granular QoS per VF has been enabled before updating QP qos_vport The Granular QoS per VF feature must be enabled in FW before it can be used. Thus, the driver cannot modify a QP's qos_vport value (via the UPDATE_QP FW command) if the feature has not been enabled -- the FW returns an error if this is attempted. Fixes: 08068cd5683f ("net/mlx4: Added qos_vport QP configuration in VST mode") Signed-off-by: Ido Shamay Signed-off-by: Jack Morgenstein Signed-off-by: Tariq Toukan Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/qp.c | 6 ++++++ drivers/net/ethernet/mellanox/mlx4/resource_tracker.c | 16 +++++++++++----- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/qp.c b/drivers/net/ethernet/mellanox/mlx4/qp.c index ad92d2311478..5a310d313e94 100644 --- a/drivers/net/ethernet/mellanox/mlx4/qp.c +++ b/drivers/net/ethernet/mellanox/mlx4/qp.c @@ -484,6 +484,12 @@ int mlx4_update_qp(struct mlx4_dev *dev, u32 qpn, } if (attr & MLX4_UPDATE_QP_QOS_VPORT) { + if (!(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_QOS_VPP)) { + mlx4_warn(dev, "Granular QoS per VF is not enabled\n"); + err = -EOPNOTSUPP; + goto out; + } + qp_mask |= 1ULL << MLX4_UPD_QP_MASK_QOS_VPP; cmd->qp_context.qos_vport = params->qos_vport; } diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c index 07516545474f..812783865205 100644 --- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c @@ -5255,6 +5255,13 @@ void mlx4_delete_all_resources_for_slave(struct mlx4_dev *dev, int slave) mutex_unlock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex); } +static void update_qos_vpp(struct mlx4_update_qp_context *ctx, + struct mlx4_vf_immed_vlan_work *work) +{ + ctx->qp_mask |= cpu_to_be64(1ULL << MLX4_UPD_QP_MASK_QOS_VPP); + ctx->qp_context.qos_vport = work->qos_vport; +} + void mlx4_vf_immed_vlan_work_handler(struct work_struct *_work) { struct mlx4_vf_immed_vlan_work *work = @@ -5369,11 +5376,10 @@ void mlx4_vf_immed_vlan_work_handler(struct work_struct *_work) qp->sched_queue & 0xC7; upd_context->qp_context.pri_path.sched_queue |= ((work->qos & 0x7) << 3); - upd_context->qp_mask |= - cpu_to_be64(1ULL << - MLX4_UPD_QP_MASK_QOS_VPP); - upd_context->qp_context.qos_vport = - work->qos_vport; + + if (dev->caps.flags2 & + MLX4_DEV_CAP_FLAG2_QOS_VPP) + update_qos_vpp(upd_context, work); } err = mlx4_cmd(dev, mailbox->dma, -- cgit v1.2.3 From 1deec1bd96ccd8beb04d2112a6d12fe20505c3a6 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Wed, 31 May 2017 21:01:03 +0900 Subject: perf header: Set proper module name when build-id event found When perf processes build-id event, it creates DSOs with the build-id. But it didn't set the module short name (like '[module-name]') so when processing a kernel mmap event of the module, it cannot found the DSO as it only checks the short names. That leads for perf to create a same DSO without the build-id info and it'll lookup the system path even if the DSO is already in the build-id cache. After kernel was updated, perf cannot find the DSO and cannot show symbols in it anymore. You can see this if you have an old data file (w/ old kernel version): $ perf report -i perf.data.old -v |& grep scsi_mod build id event received for /lib/modules/3.19.2-1-ARCH/kernel/drivers/scsi/scsi_mod.ko.gz : cafe1ce6ca13a98a5d9ed3425cde249e57a27fc1 Failed to open /lib/modules/3.19.2-1-ARCH/kernel/drivers/scsi/scsi_mod.ko.gz, continuing without symbols ... The second message didn't show the build-id. With this patch: $ perf report -i perf.data.old -v |& grep scsi_mod build id event received for /lib/modules/3.19.2-1-ARCH/kernel/drivers/scsi/scsi_mod.ko.gz: cafe1ce6ca13a98a5d9ed3425cde249e57a27fc1 /lib/modules/3.19.2-1-ARCH/kernel/drivers/scsi/scsi_mod.ko.gz with build id cafe1ce6ca13a98a5d9ed3425cde249e57a27fc1 not found, continuing without symbols ... Now it shows the build-id but still cannot load the symbol table. This is a different problem which will be fixed in the next patch. Signed-off-by: Namhyung Kim Acked-by: Jiri Olsa Cc: Andi Kleen Cc: David Ahern Cc: Peter Zijlstra Cc: kernel-team@lge.com Link: http://lkml.kernel.org/r/20170531120105.21731-1-namhyung@kernel.org [ Fix the build on older compilers (debian <= 8, fedora <= 21, etc) wrt kmod_path var init ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/header.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 314a07151fb7..c40a4d8acf8b 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -1469,8 +1469,16 @@ static int __event_process_build_id(struct build_id_event *bev, dso__set_build_id(dso, &bev->build_id); - if (!is_kernel_module(filename, cpumode)) - dso->kernel = dso_type; + if (dso_type != DSO_TYPE_USER) { + struct kmod_path m = { .name = NULL, }; + + if (!kmod_path__parse_name(&m, filename) && m.kmod) + dso__set_short_name(dso, strdup(m.name), true); + else + dso->kernel = dso_type; + + free(m.name); + } build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id); -- cgit v1.2.3 From 6b335e8f545591c07df0f34231bd7ff7506c98c1 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Wed, 31 May 2017 21:01:04 +0900 Subject: perf symbols: Set module info when build-id event found Like machine__findnew_module_dso(), it should set necessary info for kernel modules to find symbol info from the file. Factor out dso__set_module_info() to do it. This is needed for dso__needs_decompress() to detect such DSOs. Signed-off-by: Namhyung Kim Acked-by: Jiri Olsa Cc: Andi Kleen Cc: David Ahern Cc: Peter Zijlstra Cc: kernel-team@lge.com Link: http://lkml.kernel.org/r/20170531120105.21731-2-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/dso.c | 15 +++++++++++++++ tools/perf/util/dso.h | 3 +++ tools/perf/util/header.c | 2 +- tools/perf/util/machine.c | 11 +---------- 4 files changed, 20 insertions(+), 11 deletions(-) diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index a96a99d2369f..b27d127cdf68 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -335,6 +335,21 @@ int __kmod_path__parse(struct kmod_path *m, const char *path, return 0; } +void dso__set_module_info(struct dso *dso, struct kmod_path *m, + struct machine *machine) +{ + if (machine__is_host(machine)) + dso->symtab_type = DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE; + else + dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE; + + /* _KMODULE_COMP should be next to _KMODULE */ + if (m->kmod && m->comp) + dso->symtab_type++; + + dso__set_short_name(dso, strdup(m->name), true); +} + /* * Global list of open DSOs and the counter. */ diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h index 12350b171727..5fe2ab5877bd 100644 --- a/tools/perf/util/dso.h +++ b/tools/perf/util/dso.h @@ -259,6 +259,9 @@ int __kmod_path__parse(struct kmod_path *m, const char *path, #define kmod_path__parse_name(__m, __p) __kmod_path__parse(__m, __p, true , false) #define kmod_path__parse_ext(__m, __p) __kmod_path__parse(__m, __p, false, true) +void dso__set_module_info(struct dso *dso, struct kmod_path *m, + struct machine *machine); + /* * The dso__data_* external interface provides following functions: * dso__data_get_fd diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index c40a4d8acf8b..5cac8d5e009a 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -1473,7 +1473,7 @@ static int __event_process_build_id(struct build_id_event *bev, struct kmod_path m = { .name = NULL, }; if (!kmod_path__parse_name(&m, filename) && m.kmod) - dso__set_short_name(dso, strdup(m.name), true); + dso__set_module_info(dso, &m, machine); else dso->kernel = dso_type; diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index d97e014c3df3..d7f31cb0a4cb 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -572,16 +572,7 @@ static struct dso *machine__findnew_module_dso(struct machine *machine, if (dso == NULL) goto out_unlock; - if (machine__is_host(machine)) - dso->symtab_type = DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE; - else - dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE; - - /* _KMODULE_COMP should be next to _KMODULE */ - if (m->kmod && m->comp) - dso->symtab_type++; - - dso__set_short_name(dso, strdup(m->name), true); + dso__set_module_info(dso, m, machine); dso__set_long_name(dso, strdup(filename), true); } -- cgit v1.2.3 From a09935b878dc8efd4b030ed1ffa0553fc9011fb8 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Wed, 31 May 2017 21:01:05 +0900 Subject: perf symbols: Use correct filename for compressed modules in build-id cache The decompress_kmodule() decompresses kernel modules in order to load symbols from it. In the DSO_BINARY_TYPE__BUILD_ID_CACHE case, it needs the full file path to extract the file extension to determine the decompression method. But overwriting 'name' will fail the decompression since it might point to a non-existing old file. Instead, use dso->long_name for having the correct extension and use the real filename to decompress. In the DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP case, both names should be the same. This allows resolving symbols in the old modules. Before: $ perf report -i perf.data.old | grep scsi_mod 0.00% cc1 [scsi_mod] [k] 0x0000000000004aa6 0.00% as [scsi_mod] [k] 0x00000000000099e1 0.00% cc1 [scsi_mod] [k] 0x0000000000009830 0.00% cc1 [scsi_mod] [k] 0x0000000000001b8f After: 0.00% cc1 [scsi_mod] [k] scsi_handle_queue_ramp_up 0.00% as [scsi_mod] [k] scsi_sg_alloc 0.00% cc1 [scsi_mod] [k] scsi_setup_cmnd 0.00% cc1 [scsi_mod] [k] scsi_get_command Signed-off-by: Namhyung Kim Acked-by: Jiri Olsa Cc: Andi Kleen Cc: David Ahern Cc: Peter Zijlstra Cc: kernel-team@lge.com Link: http://lkml.kernel.org/r/20170531120105.21731-3-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/symbol-elf.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index e7ee47f7377a..1fb2efae4f02 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c @@ -649,10 +649,7 @@ static int decompress_kmodule(struct dso *dso, const char *name, type != DSO_BINARY_TYPE__BUILD_ID_CACHE) return -1; - if (type == DSO_BINARY_TYPE__BUILD_ID_CACHE) - name = dso->long_name; - - if (kmod_path__parse_ext(&m, name) || !m.comp) + if (kmod_path__parse_ext(&m, dso->long_name) || !m.comp) return -1; fd = mkstemp(tmpbuf); -- cgit v1.2.3 From 598762cf91532e6e86dd21199b5e7f803df73f49 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 1 Jun 2017 22:54:50 +0200 Subject: perf test: Disable breakpoint signal tests for powerpc The following tests are failing on powerpc: # perf test break 18: Breakpoint overflow signal handler : FAILED! 19: Breakpoint overflow sampling : FAILED! The powerpc kenel so far does not have support to even create instruction breakpoints using the perf event interface, so those tests fail early in the config phase. I added a '->is_supported()' callback to test struct to be able to disable specific tests. It seems better than putting ifdefs directly to the test array. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20170601205450.GA398@krava Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/bp_signal.c | 14 ++++++++++++++ tools/perf/tests/builtin-test.c | 7 +++++++ tools/perf/tests/tests.h | 3 +++ 3 files changed, 24 insertions(+) diff --git a/tools/perf/tests/bp_signal.c b/tools/perf/tests/bp_signal.c index e7664fe3bd33..8ba2c4618fe9 100644 --- a/tools/perf/tests/bp_signal.c +++ b/tools/perf/tests/bp_signal.c @@ -288,3 +288,17 @@ int test__bp_signal(int subtest __maybe_unused) return count1 == 1 && overflows == 3 && count2 == 3 && overflows_2 == 3 && count3 == 2 ? TEST_OK : TEST_FAIL; } + +bool test__bp_signal_is_supported(void) +{ +/* + * The powerpc so far does not have support to even create + * instruction breakpoint using the perf event interface. + * Once it's there we can release this. + */ +#ifdef __powerpc__ + return false; +#else + return true; +#endif +} diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index 9e08d297f1a9..3ccfd58a8c3c 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -97,10 +97,12 @@ static struct test generic_tests[] = { { .desc = "Breakpoint overflow signal handler", .func = test__bp_signal, + .is_supported = test__bp_signal_is_supported, }, { .desc = "Breakpoint overflow sampling", .func = test__bp_signal_overflow, + .is_supported = test__bp_signal_is_supported, }, { .desc = "Number of exit events of a simple workload", @@ -401,6 +403,11 @@ static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist) if (!perf_test__matches(t, curr, argc, argv)) continue; + if (t->is_supported && !t->is_supported()) { + pr_debug("%2d: %-*s: Disabled\n", i, width, t->desc); + continue; + } + pr_info("%2d: %-*s:", i, width, t->desc); if (intlist__find(skiplist, i)) { diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h index 631859629403..577363809c9b 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h @@ -34,6 +34,7 @@ struct test { int (*get_nr)(void); const char *(*get_desc)(int subtest); } subtest; + bool (*is_supported)(void); }; /* Tests */ @@ -99,6 +100,8 @@ const char *test__clang_subtest_get_desc(int subtest); int test__clang_subtest_get_nr(void); int test__unit_number__scnprint(int subtest); +bool test__bp_signal_is_supported(void); + #if defined(__arm__) || defined(__aarch64__) #ifdef HAVE_DWARF_UNWIND_SUPPORT struct thread; -- cgit v1.2.3 From 6db47fdec7562b02703e346c10f7f4efdda6af5a Mon Sep 17 00:00:00 2001 From: Kim Phillips Date: Mon, 29 May 2017 14:27:54 -0500 Subject: perf annotate: Add missing powerpc triplet On an Ubuntu xenial system, 'perf annotate' says to install powerpc objdump on a system that already has binutils-powerpc-linux-gnu installed. Make perf aware of the missing triplet for the powerpc-linux-gnu target. Signed-off-by: Kim Phillips Cc: Alexander Shishkin Cc: He Kuang Cc: Jiri Olsa Cc: Peter Zijlstra Cc: Ravi Bangoria Link: http://lkml.kernel.org/r/20170529142754.7fbfb1152fd8f2663de0ea70@arm.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/common.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/perf/arch/common.c b/tools/perf/arch/common.c index 837067f48a4c..6b40e9f01740 100644 --- a/tools/perf/arch/common.c +++ b/tools/perf/arch/common.c @@ -26,6 +26,7 @@ const char *const arm64_triplets[] = { const char *const powerpc_triplets[] = { "powerpc-unknown-linux-gnu-", + "powerpc-linux-gnu-", "powerpc64-unknown-linux-gnu-", "powerpc64-linux-gnu-", "powerpc64le-linux-gnu-", -- cgit v1.2.3 From 5ea0416f51cc93436bbe497c62ab49fd9cb245b6 Mon Sep 17 00:00:00 2001 From: Milian Wolff Date: Thu, 1 Jun 2017 23:00:21 +0200 Subject: perf report: Include partial stacks unwound with libdw So far the whole stack was thrown away when any error occurred before the maximum stack depth was unwound. This is actually a very common scenario though. The stacks that got unwound so far are still interesting. This removes a large chunk of differences when comparing perf script output for libunwind and libdw perf unwinding. E.g. with libunwind: ~~~~~ heaptrack_gui 2228 135073.388524: 479408 cycles: ffffffff811749ed perf_iterate_ctx ([kernel.kallsyms]) ffffffff81181662 perf_event_mmap ([kernel.kallsyms]) ffffffff811cf5ed mmap_region ([kernel.kallsyms]) ffffffff811cfe6b do_mmap ([kernel.kallsyms]) ffffffff811b0dca vm_mmap_pgoff ([kernel.kallsyms]) ffffffff811cdb0c sys_mmap_pgoff ([kernel.kallsyms]) ffffffff81033acb sys_mmap ([kernel.kallsyms]) ffffffff81631d37 entry_SYSCALL_64_fastpath ([kernel.kallsyms]) 192ca mmap64 (/usr/lib/ld-2.25.so) 59a9 _dl_map_object_from_fd (/usr/lib/ld-2.25.so) 83d0 _dl_map_object (/usr/lib/ld-2.25.so) cda1 openaux (/usr/lib/ld-2.25.so) 1834f _dl_catch_error (/usr/lib/ld-2.25.so) cfe2 _dl_map_object_deps (/usr/lib/ld-2.25.so) 3481 dl_main (/usr/lib/ld-2.25.so) 17387 _dl_sysdep_start (/usr/lib/ld-2.25.so) 4d37 _dl_start (/usr/lib/ld-2.25.so) d87 _start (/usr/lib/ld-2.25.so) heaptrack_gui 2228 135073.388677: 611329 cycles: 1a3e0 strcmp (/usr/lib/ld-2.25.so) 82b2 _dl_map_object (/usr/lib/ld-2.25.so) cda1 openaux (/usr/lib/ld-2.25.so) 1834f _dl_catch_error (/usr/lib/ld-2.25.so) cfe2 _dl_map_object_deps (/usr/lib/ld-2.25.so) 3481 dl_main (/usr/lib/ld-2.25.so) 17387 _dl_sysdep_start (/usr/lib/ld-2.25.so) 4d37 _dl_start (/usr/lib/ld-2.25.so) d87 _start (/usr/lib/ld-2.25.so) ~~~~~ With libdw without this patch: ~~~~~ heaptrack_gui 2228 135073.388524: 479408 cycles: ffffffff811749ed perf_iterate_ctx ([kernel.kallsyms]) ffffffff81181662 perf_event_mmap ([kernel.kallsyms]) ffffffff811cf5ed mmap_region ([kernel.kallsyms]) ffffffff811cfe6b do_mmap ([kernel.kallsyms]) ffffffff811b0dca vm_mmap_pgoff ([kernel.kallsyms]) ffffffff811cdb0c sys_mmap_pgoff ([kernel.kallsyms]) ffffffff81033acb sys_mmap ([kernel.kallsyms]) ffffffff81631d37 entry_SYSCALL_64_fastpath ([kernel.kallsyms]) heaptrack_gui 2228 135073.388677: 611329 cycles: ~~~~~ With this patch applied, the libdw unwinder will produce the same output as the libunwind unwinder. Signed-off-by: Milian Wolff Cc: Jiri Olsa Cc: Namhyung Kim Link: http://lkml.kernel.org/r/20170601210021.20046-1-milian.wolff@kdab.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/unwind-libdw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/unwind-libdw.c b/tools/perf/util/unwind-libdw.c index 943a06291587..b4c20124d2ee 100644 --- a/tools/perf/util/unwind-libdw.c +++ b/tools/perf/util/unwind-libdw.c @@ -224,7 +224,7 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg, err = dwfl_getthread_frames(ui->dwfl, thread->tid, frame_callback, ui); - if (err && !ui->max_stack) + if (err && ui->max_stack != max_stack) err = 0; /* -- cgit v1.2.3 From 2538b9e2450ae255337c04356e9e0f8cb9ec48d9 Mon Sep 17 00:00:00 2001 From: Milian Wolff Date: Fri, 2 Jun 2017 16:37:52 +0200 Subject: perf report: Ensure the perf DSO mapping matches what libdw sees In some situations the libdw unwinder stopped working properly. I.e. with libunwind we see: ~~~~~ heaptrack_gui 2228 135073.400112: 641314 cycles: e8ed _dl_fixup (/usr/lib/ld-2.25.so) 15f06 _dl_runtime_resolve_sse_vex (/usr/lib/ld-2.25.so) ed94c KDynamicJobTracker::KDynamicJobTracker (/home/milian/projects/compiled/kf5/lib64/libKF5KIOWidgets.so.5.35.0) 608f3 _GLOBAL__sub_I_kdynamicjobtracker.cpp (/home/milian/projects/compiled/kf5/lib64/libKF5KIOWidgets.so.5.35.0) f199 call_init.part.0 (/usr/lib/ld-2.25.so) f2a5 _dl_init (/usr/lib/ld-2.25.so) db9 _dl_start_user (/usr/lib/ld-2.25.so) ~~~~~ But with libdw and without this patch this sample is not properly unwound: ~~~~~ heaptrack_gui 2228 135073.400112: 641314 cycles: e8ed _dl_fixup (/usr/lib/ld-2.25.so) 15f06 _dl_runtime_resolve_sse_vex (/usr/lib/ld-2.25.so) ed94c KDynamicJobTracker::KDynamicJobTracker (/home/milian/projects/compiled/kf5/lib64/libKF5KIOWidgets.so.5.35.0) ~~~~~ Debug output showed me that libdw found a module for the last frame address, but it thinks it belongs to /usr/lib/ld-2.25.so. This patch double-checks what libdw sees and what perf knows. If the mappings mismatch, we now report the elf known to perf. This fixes the situation above, and the libdw unwinder produces the same stack as libunwind. Signed-off-by: Milian Wolff Cc: Jiri Olsa Cc: Namhyung Kim Link: http://lkml.kernel.org/r/20170602143753.16907-1-milian.wolff@kdab.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/unwind-libdw.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tools/perf/util/unwind-libdw.c b/tools/perf/util/unwind-libdw.c index b4c20124d2ee..da45c4be5fb3 100644 --- a/tools/perf/util/unwind-libdw.c +++ b/tools/perf/util/unwind-libdw.c @@ -39,6 +39,14 @@ static int __report_module(struct addr_location *al, u64 ip, return 0; mod = dwfl_addrmodule(ui->dwfl, ip); + if (mod) { + Dwarf_Addr s; + + dwfl_module_info(mod, NULL, &s, NULL, NULL, NULL, NULL, NULL); + if (s != al->map->start) + mod = 0; + } + if (!mod) mod = dwfl_report_elf(ui->dwfl, dso->short_name, dso->long_name, -1, al->map->start, -- cgit v1.2.3 From 1b4af13ff2cc6897557bb0b8d9e2fad4fa4d67aa Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 5 Jun 2017 11:28:57 -0700 Subject: sparc64: Add __multi3 for gcc 7.x and later. Reported-by: Waldemar Brodkorb Signed-off-by: David S. Miller --- arch/sparc/lib/Makefile | 1 + arch/sparc/lib/multi3.S | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 arch/sparc/lib/multi3.S diff --git a/arch/sparc/lib/Makefile b/arch/sparc/lib/Makefile index 69912d2f8b54..07c03e72d812 100644 --- a/arch/sparc/lib/Makefile +++ b/arch/sparc/lib/Makefile @@ -15,6 +15,7 @@ lib-$(CONFIG_SPARC32) += copy_user.o locks.o lib-$(CONFIG_SPARC64) += atomic_64.o lib-$(CONFIG_SPARC32) += lshrdi3.o ashldi3.o lib-$(CONFIG_SPARC32) += muldi3.o bitext.o cmpdi2.o +lib-$(CONFIG_SPARC64) += multi3.o lib-$(CONFIG_SPARC64) += copy_page.o clear_page.o bzero.o lib-$(CONFIG_SPARC64) += csum_copy.o csum_copy_from_user.o csum_copy_to_user.o diff --git a/arch/sparc/lib/multi3.S b/arch/sparc/lib/multi3.S new file mode 100644 index 000000000000..d6b6c97fe3c7 --- /dev/null +++ b/arch/sparc/lib/multi3.S @@ -0,0 +1,35 @@ +#include +#include + + .text + .align 4 +ENTRY(__multi3) /* %o0 = u, %o1 = v */ + mov %o1, %g1 + srl %o3, 0, %g4 + mulx %g4, %g1, %o1 + srlx %g1, 0x20, %g3 + mulx %g3, %g4, %g5 + sllx %g5, 0x20, %o5 + srl %g1, 0, %g4 + sub %o1, %o5, %o5 + srlx %o5, 0x20, %o5 + addcc %g5, %o5, %g5 + srlx %o3, 0x20, %o5 + mulx %g4, %o5, %g4 + mulx %g3, %o5, %o5 + sethi %hi(0x80000000), %g3 + addcc %g5, %g4, %g5 + srlx %g5, 0x20, %g5 + add %g3, %g3, %g3 + movcc %xcc, %g0, %g3 + addcc %o5, %g5, %o5 + sllx %g4, 0x20, %g4 + add %o1, %g4, %o1 + add %o5, %g3, %g2 + mulx %g1, %o2, %g1 + add %g1, %g2, %g1 + mulx %o0, %o3, %o0 + retl + add %g1, %o0, %o0 +ENDPROC(__multi3) +EXPORT_SYMBOL(__multi3) -- cgit v1.2.3 From ea42d1cbe3f067fb714c3ec3e1792fa273b99561 Mon Sep 17 00:00:00 2001 From: Gregory Greenman Date: Mon, 6 Mar 2017 11:15:41 +0200 Subject: iwlwifi: mvm: rs: start using LQ command color Up until now, the driver was comparing the rate reported by the FW and the rate of the latest LQ command to avoid processing data belonging to the old LQ command. Recently, FW changed the meaning of the initial rate field in tx response and it holds the actual rate (which is not necessarily the initial rate of LQ's rate table). Use instead LQ cmd color to be able to filter out tx responses/BA notifications which where sent during earlier LQ commands' time frame. This fixes some throughput degradation in noisy environments. Signed-off-by: Gregory Greenman Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rs.h | 5 +++ drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h | 3 ++ drivers/net/wireless/intel/iwlwifi/mvm/rs.c | 46 ++++++---------------- drivers/net/wireless/intel/iwlwifi/mvm/rs.h | 15 +++++++ drivers/net/wireless/intel/iwlwifi/mvm/sta.h | 2 + drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 12 +++++- 6 files changed, 47 insertions(+), 36 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rs.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rs.h index 1b7d265ffb0a..a10c6aae9ab9 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rs.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rs.h @@ -307,6 +307,11 @@ enum { /* Bit 1-3: LQ command color. Used to match responses to LQ commands */ #define LQ_FLAG_COLOR_POS 1 #define LQ_FLAG_COLOR_MSK (7 << LQ_FLAG_COLOR_POS) +#define LQ_FLAG_COLOR_GET(_f) (((_f) & LQ_FLAG_COLOR_MSK) >>\ + LQ_FLAG_COLOR_POS) +#define LQ_FLAGS_COLOR_INC(_c) ((((_c) + 1) << LQ_FLAG_COLOR_POS) &\ + LQ_FLAG_COLOR_MSK) +#define LQ_FLAG_COLOR_SET(_f, _c) ((_c) | ((_f) & ~LQ_FLAG_COLOR_MSK)) /* Bit 4-5: Tx RTS BW Signalling * (0) No RTS BW signalling diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h index 81b98915b1a4..1360ebfdc51b 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h @@ -519,8 +519,11 @@ struct agg_tx_status { * bit-7 invalid rate indication */ #define TX_RES_INIT_RATE_INDEX_MSK 0x0f +#define TX_RES_RATE_TABLE_COLOR_POS 4 #define TX_RES_RATE_TABLE_COLOR_MSK 0x70 #define TX_RES_INV_RATE_INDEX_MSK 0x80 +#define TX_RES_RATE_TABLE_COL_GET(_f) (((_f) & TX_RES_RATE_TABLE_COLOR_MSK) >>\ + TX_RES_RATE_TABLE_COLOR_POS) #define IWL_MVM_TX_RES_GET_TID(_ra_tid) ((_ra_tid) & 0x0f) #define IWL_MVM_TX_RES_GET_RA(_ra_tid) ((_ra_tid) >> 4) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c index 7788eefcd2bd..aa785cf3cf68 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c @@ -2,7 +2,7 @@ * * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH - * Copyright(c) 2016 Intel Deutschland GmbH + * Copyright(c) 2016 - 2017 Intel Deutschland GmbH * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -1083,34 +1083,6 @@ static void rs_get_lower_rate_down_column(struct iwl_lq_sta *lq_sta, rs_get_lower_rate_in_column(lq_sta, rate); } -/* Check if both rates are identical - * allow_ant_mismatch enables matching a SISO rate on ANT_A or ANT_B - * with a rate indicating STBC/BFER and ANT_AB. - */ -static inline bool rs_rate_equal(struct rs_rate *a, - struct rs_rate *b, - bool allow_ant_mismatch) - -{ - bool ant_match = (a->ant == b->ant) && (a->stbc == b->stbc) && - (a->bfer == b->bfer); - - if (allow_ant_mismatch) { - if (a->stbc || a->bfer) { - WARN_ONCE(a->ant != ANT_AB, "stbc %d bfer %d ant %d", - a->stbc, a->bfer, a->ant); - ant_match |= (b->ant == ANT_A || b->ant == ANT_B); - } else if (b->stbc || b->bfer) { - WARN_ONCE(b->ant != ANT_AB, "stbc %d bfer %d ant %d", - b->stbc, b->bfer, b->ant); - ant_match |= (a->ant == ANT_A || a->ant == ANT_B); - } - } - - return (a->type == b->type) && (a->bw == b->bw) && (a->sgi == b->sgi) && - (a->ldpc == b->ldpc) && (a->index == b->index) && ant_match; -} - /* Check if both rates share the same column */ static inline bool rs_rate_column_match(struct rs_rate *a, struct rs_rate *b) @@ -1182,12 +1154,12 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta, u32 lq_hwrate; struct rs_rate lq_rate, tx_resp_rate; struct iwl_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl; - u8 reduced_txp = (uintptr_t)info->status.status_driver_data[0]; + u32 tlc_info = (uintptr_t)info->status.status_driver_data[0]; + u8 reduced_txp = tlc_info & RS_DRV_DATA_TXP_MSK; + u8 lq_color = RS_DRV_DATA_LQ_COLOR_GET(tlc_info); u32 tx_resp_hwrate = (uintptr_t)info->status.status_driver_data[1]; struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); struct iwl_lq_sta *lq_sta = &mvmsta->lq_sta; - bool allow_ant_mismatch = fw_has_api(&mvm->fw->ucode_capa, - IWL_UCODE_TLV_API_LQ_SS_PARAMS); /* Treat uninitialized rate scaling data same as non-existing. */ if (!lq_sta) { @@ -1262,10 +1234,10 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta, rs_rate_from_ucode_rate(lq_hwrate, info->band, &lq_rate); /* Here we actually compare this rate to the latest LQ command */ - if (!rs_rate_equal(&tx_resp_rate, &lq_rate, allow_ant_mismatch)) { + if (lq_color != LQ_FLAG_COLOR_GET(table->flags)) { IWL_DEBUG_RATE(mvm, - "initial tx resp rate 0x%x does not match 0x%x\n", - tx_resp_hwrate, lq_hwrate); + "tx resp color 0x%x does not match 0x%x\n", + lq_color, LQ_FLAG_COLOR_GET(table->flags)); /* * Since rates mis-match, the last LQ command may have failed. @@ -3326,6 +3298,7 @@ static void rs_build_rates_table(struct iwl_mvm *mvm, u8 valid_tx_ant = 0; struct iwl_lq_cmd *lq_cmd = &lq_sta->lq; bool toggle_ant = false; + u32 color; memcpy(&rate, initial_rate, sizeof(rate)); @@ -3380,6 +3353,9 @@ static void rs_build_rates_table(struct iwl_mvm *mvm, num_rates, num_retries, valid_tx_ant, toggle_ant); + /* update the color of the LQ command (as a counter at bits 1-3) */ + color = LQ_FLAGS_COLOR_INC(LQ_FLAG_COLOR_GET(lq_cmd->flags)); + lq_cmd->flags = LQ_FLAG_COLOR_SET(lq_cmd->flags, color); } struct rs_bfer_active_iter_data { diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.h b/drivers/net/wireless/intel/iwlwifi/mvm/rs.h index ee207f2c0a90..3abde1cb0303 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.h @@ -2,6 +2,7 @@ * * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2015 Intel Mobile Communications GmbH + * Copyright(c) 2017 Intel Deutschland GmbH * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -357,6 +358,20 @@ struct iwl_lq_sta { } pers; }; +/* ieee80211_tx_info's status_driver_data[0] is packed with lq color and txp + * Note, it's iwlmvm <-> mac80211 interface. + * bits 0-7: reduced tx power + * bits 8-10: LQ command's color + */ +#define RS_DRV_DATA_TXP_MSK 0xff +#define RS_DRV_DATA_LQ_COLOR_POS 8 +#define RS_DRV_DATA_LQ_COLOR_MSK (7 << RS_DRV_DATA_LQ_COLOR_POS) +#define RS_DRV_DATA_LQ_COLOR_GET(_f) (((_f) & RS_DRV_DATA_LQ_COLOR_MSK) >>\ + RS_DRV_DATA_LQ_COLOR_POS) +#define RS_DRV_DATA_PACK(_c, _p) ((void *)(uintptr_t)\ + (((uintptr_t)_p) |\ + ((_c) << RS_DRV_DATA_LQ_COLOR_POS))) + /* Initialize station's rate scaling information after adding station */ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, enum nl80211_band band, bool init); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h index 2716cb5483bf..ad62b67dceb2 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h @@ -313,6 +313,7 @@ enum iwl_mvm_agg_state { * This is basically (last acked packet++). * @rate_n_flags: Rate at which Tx was attempted. Holds the data between the * Tx response (TX_CMD), and the block ack notification (COMPRESSED_BA). + * @lq_color: the color of the LQ command as it appears in tx response. * @amsdu_in_ampdu_allowed: true if A-MSDU in A-MPDU is allowed. * @state: state of the BA agreement establishment / tear down. * @txq_id: Tx queue used by the BA session / DQA @@ -331,6 +332,7 @@ struct iwl_mvm_tid_data { u16 next_reclaimed; /* The rest is Tx AGG related */ u32 rate_n_flags; + u8 lq_color; bool amsdu_in_ampdu_allowed; enum iwl_mvm_agg_state state; u16 txq_id; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c index bcaceb64a6e8..f21901cd4a4f 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c @@ -1323,6 +1323,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta; struct sk_buff_head skbs; u8 skb_freed = 0; + u8 lq_color; u16 next_reclaimed, seq_ctl; bool is_ndp = false; @@ -1405,8 +1406,9 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, info->status.tx_time = le16_to_cpu(tx_resp->wireless_media_time); BUILD_BUG_ON(ARRAY_SIZE(info->status.status_driver_data) < 1); + lq_color = TX_RES_RATE_TABLE_COL_GET(tx_resp->tlc_info); info->status.status_driver_data[0] = - (void *)(uintptr_t)tx_resp->reduced_tpc; + RS_DRV_DATA_PACK(lq_color, tx_resp->reduced_tpc); ieee80211_tx_status(mvm->hw, skb); } @@ -1638,6 +1640,9 @@ static void iwl_mvm_rx_tx_cmd_agg(struct iwl_mvm *mvm, le32_to_cpu(tx_resp->initial_rate); mvmsta->tid_data[tid].tx_time = le16_to_cpu(tx_resp->wireless_media_time); + mvmsta->tid_data[tid].lq_color = + (tx_resp->tlc_info & TX_RES_RATE_TABLE_COLOR_MSK) >> + TX_RES_RATE_TABLE_COLOR_POS; } rcu_read_unlock(); @@ -1707,6 +1712,11 @@ static void iwl_mvm_tx_reclaim(struct iwl_mvm *mvm, int sta_id, int tid, iwl_mvm_check_ratid_empty(mvm, sta, tid); freed = 0; + + /* pack lq color from tid_data along the reduced txp */ + ba_info->status.status_driver_data[0] = + RS_DRV_DATA_PACK(tid_data->lq_color, + ba_info->status.status_driver_data[0]); ba_info->status.status_driver_data[1] = (void *)(uintptr_t)rate; skb_queue_walk(&reclaimed_skbs, skb) { -- cgit v1.2.3 From c72c37b7f392ad7edc10b6092fa48c632ba6f4ed Mon Sep 17 00:00:00 2001 From: Haim Dreyfuss Date: Thu, 16 Mar 2017 17:26:03 +0200 Subject: iwlwifi: mvm: Fix command queue number on d0i3 flow During d0i3 flow we flush all the queue except from the command queue. Currently, in this flow the command queue is hard coded to 9. In DQA the command queue number has changed from 9 to 0. Fix that. This fixes a problem in runtime PM resume flow. Fixes: 097129c9e625 ("iwlwifi: mvm: move cmd queue to be #0 in dqa mode") Signed-off-by: Haim Dreyfuss Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 4e74a6b90e70..ed20c0c5abc8 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -1730,8 +1730,11 @@ int iwl_mvm_find_free_queue(struct iwl_mvm *mvm, u8 sta_id, u8 minq, u8 maxq); */ static inline u32 iwl_mvm_flushable_queues(struct iwl_mvm *mvm) { + u32 cmd_queue = iwl_mvm_is_dqa_supported(mvm) ? IWL_MVM_DQA_CMD_QUEUE : + IWL_MVM_CMD_QUEUE; + return ((BIT(mvm->cfg->base_params->num_of_queues) - 1) & - ~BIT(IWL_MVM_CMD_QUEUE)); + ~BIT(cmd_queue)); } static inline -- cgit v1.2.3 From ee48b72211f844a58a06819e9ccceee6acf04b2d Mon Sep 17 00:00:00 2001 From: Liad Kaufman Date: Tue, 21 Mar 2017 17:13:16 +0200 Subject: iwlwifi: mvm: support ibss in dqa mode Allow working IBSS also when working in DQA mode. This is done by setting it to treat the queues the same as a BSS AP treats the queues. Fixes: 7948b87308a4 ("iwlwifi: mvm: enable dynamic queue allocation mode") Signed-off-by: Liad Kaufman Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index f5c786ddc526..9184ce09b89a 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -2120,7 +2120,8 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) if (!iwl_mvm_is_dqa_supported(mvm)) return 0; - if (WARN_ON(vif->type != NL80211_IFTYPE_AP)) + if (WARN_ON(vif->type != NL80211_IFTYPE_AP && + vif->type != NL80211_IFTYPE_ADHOC)) return -ENOTSUPP; /* @@ -2155,6 +2156,16 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) mvmvif->cab_queue = queue; } else if (!fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_STA_TYPE)) { + /* + * In IBSS, ieee80211_check_queues() sets the cab_queue to be + * invalid, so make sure we use the queue we want. + * Note that this is done here as we want to avoid making DQA + * changes in mac80211 layer. + */ + if (vif->type == NL80211_IFTYPE_ADHOC) { + vif->cab_queue = IWL_MVM_DQA_GCAST_QUEUE; + mvmvif->cab_queue = vif->cab_queue; + } iwl_mvm_enable_txq(mvm, vif->cab_queue, vif->cab_queue, 0, &cfg, timeout); } -- cgit v1.2.3 From d9954405758a0cbbe258d9b4d4dc12a06fa48a28 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 22 Mar 2017 22:00:10 +0100 Subject: iwlwifi: tt: move ucode_loaded check under mutex The ucode_loaded check should be under the mutex, since it can otherwise change state after we looked at it and before we got the mutex. Fix that. Fixes: 5c89e7bc557e ("iwlwifi: mvm: add registration to cooling device") Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/tt.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c index f9cbd197246f..506d58104e1c 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c @@ -790,11 +790,13 @@ static int iwl_mvm_tcool_set_cur_state(struct thermal_cooling_device *cdev, struct iwl_mvm *mvm = (struct iwl_mvm *)(cdev->devdata); int ret; - if (!mvm->ucode_loaded || !(mvm->cur_ucode == IWL_UCODE_REGULAR)) - return -EIO; - mutex_lock(&mvm->mutex); + if (!mvm->ucode_loaded || !(mvm->cur_ucode == IWL_UCODE_REGULAR)) { + ret = -EIO; + goto unlock; + } + if (new_state >= ARRAY_SIZE(iwl_mvm_cdev_budgets)) { ret = -EINVAL; goto unlock; -- cgit v1.2.3 From addce854f164a68da9cb158e2e7e447705068549 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Wed, 29 Mar 2017 10:21:09 +0300 Subject: iwlwifi: mvm: fix firmware debug restart recording When we want to stop the recording of the firmware debug and restart it later without reloading the firmware we don't need to resend the configuration that comes with host commands. Sending those commands confused the hardware and led to an NMI 0x66. Change the flow as following: * read the relevant registers (DBGC_IN_SAMPLE, DBGC_OUT_CTRL) * clear those registers * wait for the hardware to complete its write to the buffer * get the data * restore the value of those registers (to restart the recording) For early start (where the configuration is already compiled in the firmware), we don't need to set those registers after the firmware has been loaded, but only when we want to restart the recording without having restarted the firmware. Signed-off-by: Emmanuel Grumbach Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/iwl-prph.h | 1 + drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c | 12 +--------- drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 1 + drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 32 ++++++++++++++++++------- 4 files changed, 27 insertions(+), 19 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h index 306bc967742e..77efbb78e867 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h @@ -370,6 +370,7 @@ #define MON_DMARB_RD_DATA_ADDR (0xa03c5c) #define DBGC_IN_SAMPLE (0xa03c00) +#define DBGC_OUT_CTRL (0xa03c0c) /* enable the ID buf for read */ #define WFPM_PS_CTL_CLR 0xA0300C diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c index 7b86a4f1b574..c8712e6eea74 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c @@ -1002,14 +1002,6 @@ int iwl_mvm_fw_dbg_collect_trig(struct iwl_mvm *mvm, return 0; } -static inline void iwl_mvm_restart_early_start(struct iwl_mvm *mvm) -{ - if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) - iwl_clear_bits_prph(mvm->trans, MON_BUFF_SAMPLE_CTL, 0x100); - else - iwl_write_prph(mvm->trans, DBGC_IN_SAMPLE, 1); -} - int iwl_mvm_start_fw_dbg_conf(struct iwl_mvm *mvm, u8 conf_id) { u8 *ptr; @@ -1023,10 +1015,8 @@ int iwl_mvm_start_fw_dbg_conf(struct iwl_mvm *mvm, u8 conf_id) /* EARLY START - firmware's configuration is hard coded */ if ((!mvm->fw->dbg_conf_tlv[conf_id] || !mvm->fw->dbg_conf_tlv[conf_id]->num_of_hcmds) && - conf_id == FW_DBG_START_FROM_ALIVE) { - iwl_mvm_restart_early_start(mvm); + conf_id == FW_DBG_START_FROM_ALIVE) return 0; - } if (!mvm->fw->dbg_conf_tlv[conf_id]) return -EINVAL; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index ed20c0c5abc8..52f8d7a6a7dc 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -1756,6 +1756,7 @@ static inline void iwl_mvm_stop_device(struct iwl_mvm *mvm) if (!iwl_mvm_has_new_tx_api(mvm)) iwl_free_fw_paging(mvm); mvm->ucode_loaded = false; + mvm->fw_dbg_conf = FW_DBG_INVALID; iwl_trans_stop_device(mvm->trans); } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index 9ffff6ed8133..3da5ec40aaea 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -1149,21 +1149,37 @@ static void iwl_mvm_fw_error_dump_wk(struct work_struct *work) mutex_lock(&mvm->mutex); - /* stop recording */ if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) { + /* stop recording */ iwl_set_bits_prph(mvm->trans, MON_BUFF_SAMPLE_CTL, 0x100); + + iwl_mvm_fw_error_dump(mvm); + + /* start recording again if the firmware is not crashed */ + if (!test_bit(STATUS_FW_ERROR, &mvm->trans->status) && + mvm->fw->dbg_dest_tlv) + iwl_clear_bits_prph(mvm->trans, + MON_BUFF_SAMPLE_CTL, 0x100); } else { + u32 in_sample = iwl_read_prph(mvm->trans, DBGC_IN_SAMPLE); + u32 out_ctrl = iwl_read_prph(mvm->trans, DBGC_OUT_CTRL); + + /* stop recording */ iwl_write_prph(mvm->trans, DBGC_IN_SAMPLE, 0); - /* wait before we collect the data till the DBGC stop */ udelay(100); - } + iwl_write_prph(mvm->trans, DBGC_OUT_CTRL, 0); + /* wait before we collect the data till the DBGC stop */ + udelay(500); - iwl_mvm_fw_error_dump(mvm); + iwl_mvm_fw_error_dump(mvm); - /* start recording again if the firmware is not crashed */ - WARN_ON_ONCE((!test_bit(STATUS_FW_ERROR, &mvm->trans->status)) && - mvm->fw->dbg_dest_tlv && - iwl_mvm_start_fw_dbg_conf(mvm, mvm->fw_dbg_conf)); + /* start recording again if the firmware is not crashed */ + if (!test_bit(STATUS_FW_ERROR, &mvm->trans->status) && + mvm->fw->dbg_dest_tlv) { + iwl_write_prph(mvm->trans, DBGC_IN_SAMPLE, in_sample); + iwl_write_prph(mvm->trans, DBGC_OUT_CTRL, out_ctrl); + } + } mutex_unlock(&mvm->mutex); -- cgit v1.2.3 From e4c49c4937951de1cdbe35572ade40c948dec1e1 Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Fri, 24 Mar 2017 11:01:45 +0200 Subject: iwlwifi: pcie: only use d0i3 in suspend/resume if system_pm is set to d0i3 We only need to handle d0i3 entry and exit during suspend resume if system_pm is set to IWL_PLAT_PM_MODE_D0I3, otherwise d0i3 entry failures will cause suspend to fail. This fixes https://bugzilla.kernel.org/show_bug.cgi?id=194791 Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index 70acf850a9f1..93cbc7a69bcd 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -2803,7 +2803,8 @@ static struct iwl_trans_dump_data #ifdef CONFIG_PM_SLEEP static int iwl_trans_pcie_suspend(struct iwl_trans *trans) { - if (trans->runtime_pm_mode == IWL_PLAT_PM_MODE_D0I3) + if (trans->runtime_pm_mode == IWL_PLAT_PM_MODE_D0I3 && + (trans->system_pm_mode == IWL_PLAT_PM_MODE_D0I3)) return iwl_pci_fw_enter_d0i3(trans); return 0; @@ -2811,7 +2812,8 @@ static int iwl_trans_pcie_suspend(struct iwl_trans *trans) static void iwl_trans_pcie_resume(struct iwl_trans *trans) { - if (trans->runtime_pm_mode == IWL_PLAT_PM_MODE_D0I3) + if (trans->runtime_pm_mode == IWL_PLAT_PM_MODE_D0I3 && + (trans->system_pm_mode == IWL_PLAT_PM_MODE_D0I3)) iwl_pci_fw_exit_d0i3(trans); } #endif /* CONFIG_PM_SLEEP */ -- cgit v1.2.3 From 71793b7d3eb0897ca0dc4a109ede608d3e2c70ed Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Thu, 30 Mar 2017 12:04:47 +0300 Subject: iwlwifi: mvm: don't fail when removing a key from an inexisting sta The iwl_mvm_remove_sta_key() function handles removing a key when the sta doesn't exist anymore. Mistakenly, this was changed to return an error while fixing another bug. If the mvm_sta doesn't exist, we continue normally, but just don't try to remove the igtk key. Fixes: cd4d23c1ea9b ("iwlwifi: mvm: Fix removal of IGTK") Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index 9184ce09b89a..614d67810d05 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -3332,18 +3332,15 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm, /* Get the station from the mvm local station table */ mvm_sta = iwl_mvm_get_key_sta(mvm, vif, sta); - if (!mvm_sta) { - IWL_ERR(mvm, "Failed to find station\n"); - return -EINVAL; - } - sta_id = mvm_sta->sta_id; + if (mvm_sta) + sta_id = mvm_sta->sta_id; IWL_DEBUG_WEP(mvm, "mvm remove dynamic key: idx=%d sta=%d\n", keyconf->keyidx, sta_id); - if (keyconf->cipher == WLAN_CIPHER_SUITE_AES_CMAC || - keyconf->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 || - keyconf->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256) + if (mvm_sta && (keyconf->cipher == WLAN_CIPHER_SUITE_AES_CMAC || + keyconf->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 || + keyconf->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256)) return iwl_mvm_send_sta_igtk(mvm, keyconf, sta_id, true); if (!__test_and_clear_bit(keyconf->hw_key_idx, mvm->fw_key_table)) { -- cgit v1.2.3 From 40cbeca3c09965f3084d591476559cbb3df150ec Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 31 Mar 2017 10:47:35 +0200 Subject: iwlwifi: mvm: clear new beacon command template struct Clear the struct so that all reserved fields are zero when we send the struct down to the device. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c index 0f1831b41915..fd2fc46e2fe5 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c @@ -1040,7 +1040,7 @@ static int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm, struct iwl_mac_beacon_cmd_v6 beacon_cmd_v6; struct iwl_mac_beacon_cmd_v7 beacon_cmd; } u = {}; - struct iwl_mac_beacon_cmd beacon_cmd; + struct iwl_mac_beacon_cmd beacon_cmd = {}; struct ieee80211_tx_info *info; u32 beacon_skb_len; u32 rate, tx_flags; -- cgit v1.2.3 From 15098803d38778070b8edfa5a3d5fc4fef10d0a1 Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Tue, 25 Apr 2017 10:18:10 +0300 Subject: iwlwifi: fix min API version for 7265D, 3168, 8000 and 8265 In a previous commit, we removed support for API versions earlier than 22 for these NICs. By mistake, the *_UCODE_API_MIN definitions were set to 17. Fix that. Fixes: 4b87e5af638b ("iwlwifi: remove support for fw older than -17 and -22") Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/iwl-7000.c | 4 ++-- drivers/net/wireless/intel/iwlwifi/iwl-8000.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-7000.c b/drivers/net/wireless/intel/iwlwifi/iwl-7000.c index 3b3e076571d6..45e2efc70d19 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-7000.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-7000.c @@ -79,8 +79,8 @@ /* Lowest firmware API version supported */ #define IWL7260_UCODE_API_MIN 17 #define IWL7265_UCODE_API_MIN 17 -#define IWL7265D_UCODE_API_MIN 17 -#define IWL3168_UCODE_API_MIN 20 +#define IWL7265D_UCODE_API_MIN 22 +#define IWL3168_UCODE_API_MIN 22 /* NVM versions */ #define IWL7260_NVM_VERSION 0x0a1d diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-8000.c b/drivers/net/wireless/intel/iwlwifi/iwl-8000.c index b9718c0cf174..89137717c1fc 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-8000.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-8000.c @@ -74,8 +74,8 @@ #define IWL8265_UCODE_API_MAX 30 /* Lowest firmware API version supported */ -#define IWL8000_UCODE_API_MIN 17 -#define IWL8265_UCODE_API_MIN 20 +#define IWL8000_UCODE_API_MIN 22 +#define IWL8265_UCODE_API_MIN 22 /* NVM versions */ #define IWL8000_NVM_VERSION 0x0a1d -- cgit v1.2.3 From dc1cd1d5ac22dbcd158c3de62b76ebb80e55d46b Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Thu, 6 Apr 2017 13:35:38 +0300 Subject: iwlwifi: fix host command memory leaks Sending host command with CMD_WANT_SKB flag demands the release of the response buffer with iwl_free_resp function. The patch adds the memory release in all the relevant places Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c index 9fb46a6f47cf..9c9bfbbabdf1 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c @@ -906,7 +906,7 @@ int iwl_trans_pcie_dyn_txq_alloc(struct iwl_trans *trans, if (WARN_ON(iwl_rx_packet_payload_len(hcmd.resp_pkt) != sizeof(*rsp))) { ret = -EINVAL; - goto error; + goto error_free_resp; } rsp = (void *)hcmd.resp_pkt->data; @@ -915,13 +915,13 @@ int iwl_trans_pcie_dyn_txq_alloc(struct iwl_trans *trans, if (qid > ARRAY_SIZE(trans_pcie->txq)) { WARN_ONCE(1, "queue index %d unsupported", qid); ret = -EIO; - goto error; + goto error_free_resp; } if (test_and_set_bit(qid, trans_pcie->queue_used)) { WARN_ONCE(1, "queue %d already used", qid); ret = -EIO; - goto error; + goto error_free_resp; } txq->id = qid; @@ -934,8 +934,11 @@ int iwl_trans_pcie_dyn_txq_alloc(struct iwl_trans *trans, (txq->write_ptr) | (qid << 16)); IWL_DEBUG_TX_QUEUES(trans, "Activate queue %d\n", qid); + iwl_free_resp(&hcmd); return qid; +error_free_resp: + iwl_free_resp(&hcmd); error: iwl_pcie_gen2_txq_free_memory(trans, txq); return ret; -- cgit v1.2.3 From a415c0f10627913793709ddb75add09d2ea334dc Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 5 Jun 2017 16:05:13 +1000 Subject: md: initialise ->writes_pending in personality modules. The new per-cpu counter for writes_pending is initialised in md_alloc(), which is not called by dm-raid. So dm-raid fails when md_write_start() is called. Move the initialization to the personality modules that need it. This way it is always initialised when needed, but isn't unnecessarily initialized (requiring memory allocation) when the personality doesn't use writes_pending. Reported-by: Heinz Mauelshagen Fixes: 4ad23a976413 ("MD: use per-cpu counter for writes_pending") Signed-off-by: NeilBrown Signed-off-by: Shaohua Li --- drivers/md/md.c | 16 ++++++++++++---- drivers/md/md.h | 1 + drivers/md/raid1.c | 2 ++ drivers/md/raid10.c | 3 +++ drivers/md/raid5.c | 3 +++ 5 files changed, 21 insertions(+), 4 deletions(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index 212a6777ff31..87edc342ccb3 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -5174,6 +5174,18 @@ static void mddev_delayed_delete(struct work_struct *ws) static void no_op(struct percpu_ref *r) {} +int mddev_init_writes_pending(struct mddev *mddev) +{ + if (mddev->writes_pending.percpu_count_ptr) + return 0; + if (percpu_ref_init(&mddev->writes_pending, no_op, 0, GFP_KERNEL) < 0) + return -ENOMEM; + /* We want to start with the refcount at zero */ + percpu_ref_put(&mddev->writes_pending); + return 0; +} +EXPORT_SYMBOL_GPL(mddev_init_writes_pending); + static int md_alloc(dev_t dev, char *name) { /* @@ -5239,10 +5251,6 @@ static int md_alloc(dev_t dev, char *name) blk_queue_make_request(mddev->queue, md_make_request); blk_set_stacking_limits(&mddev->queue->limits); - if (percpu_ref_init(&mddev->writes_pending, no_op, 0, GFP_KERNEL) < 0) - goto abort; - /* We want to start with the refcount at zero */ - percpu_ref_put(&mddev->writes_pending); disk = alloc_disk(1 << shift); if (!disk) { blk_cleanup_queue(mddev->queue); diff --git a/drivers/md/md.h b/drivers/md/md.h index 11f15146ce51..0fa1de42c42b 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h @@ -648,6 +648,7 @@ extern void md_unregister_thread(struct md_thread **threadp); extern void md_wakeup_thread(struct md_thread *thread); extern void md_check_recovery(struct mddev *mddev); extern void md_reap_sync_thread(struct mddev *mddev); +extern int mddev_init_writes_pending(struct mddev *mddev); extern void md_write_start(struct mddev *mddev, struct bio *bi); extern void md_write_inc(struct mddev *mddev, struct bio *bi); extern void md_write_end(struct mddev *mddev); diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index af5056d56878..e1a7e3d4c5e4 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -3063,6 +3063,8 @@ static int raid1_run(struct mddev *mddev) mdname(mddev)); return -EIO; } + if (mddev_init_writes_pending(mddev) < 0) + return -ENOMEM; /* * copy the already verified devices into our private RAID1 * bookkeeping area. [whatever we allocate in run(), diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 4343d7ff9916..797ed60abd5e 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -3611,6 +3611,9 @@ static int raid10_run(struct mddev *mddev) int first = 1; bool discard_supported = false; + if (mddev_init_writes_pending(mddev) < 0) + return -ENOMEM; + if (mddev->private == NULL) { conf = setup_conf(mddev); if (IS_ERR(conf)) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 722064689e82..ec0f951ae19f 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -7118,6 +7118,9 @@ static int raid5_run(struct mddev *mddev) long long min_offset_diff = 0; int first = 1; + if (mddev_init_writes_pending(mddev) < 0) + return -ENOMEM; + if (mddev->recovery_cp != MaxSector) pr_notice("md/raid:%s: not clean -- starting background reconstruction\n", mdname(mddev)); -- cgit v1.2.3 From 86276921a17ee3090749c9f38f57dcfb73733bd4 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Mon, 22 May 2017 14:12:37 -0500 Subject: drm/nouveau/kms/nv50: add null check before pointer dereference Add null check before dereferencing pointer asyc Addresses-Coverity-ID: 1397932 Signed-off-by: Gustavo A. R. Silva Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nv50_display.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index a7663249b3ba..06e564a9ccb2 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -2107,7 +2107,8 @@ nv50_head_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state) asyc->set.dither = true; } } else { - asyc->set.mask = ~0; + if (asyc) + asyc->set.mask = ~0; asyh->set.mask = ~0; } -- cgit v1.2.3 From 321f5c5f2c494f3c94cec2289c8add678657ba2d Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 2 Jun 2017 14:38:07 +1000 Subject: drm/nouveau: replace multiple open-coded runpm support checks with function Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_drm.c | 34 +++++++++++++++------------------- drivers/gpu/drm/nouveau/nouveau_drv.h | 3 +-- drivers/gpu/drm/nouveau/nouveau_vga.c | 13 ++----------- 3 files changed, 18 insertions(+), 32 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 36268e1802b5..210910712606 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -80,7 +80,7 @@ int nouveau_modeset = -1; module_param_named(modeset, nouveau_modeset, int, 0400); MODULE_PARM_DESC(runpm, "disable (0), force enable (1), optimus only default (-1)"); -int nouveau_runtime_pm = -1; +static int nouveau_runtime_pm = -1; module_param_named(runpm, nouveau_runtime_pm, int, 0400); static struct drm_driver driver_stub; @@ -726,6 +726,14 @@ nouveau_pmops_thaw(struct device *dev) return nouveau_do_resume(drm_dev, false); } +bool +nouveau_pmops_runtime() +{ + if (nouveau_runtime_pm == -1) + return nouveau_is_optimus() || nouveau_is_v1_dsm(); + return nouveau_runtime_pm == 1; +} + static int nouveau_pmops_runtime_suspend(struct device *dev) { @@ -733,14 +741,7 @@ nouveau_pmops_runtime_suspend(struct device *dev) struct drm_device *drm_dev = pci_get_drvdata(pdev); int ret; - if (nouveau_runtime_pm == 0) { - pm_runtime_forbid(dev); - return -EBUSY; - } - - /* are we optimus enabled? */ - if (nouveau_runtime_pm == -1 && !nouveau_is_optimus() && !nouveau_is_v1_dsm()) { - DRM_DEBUG_DRIVER("failing to power off - not optimus\n"); + if (!nouveau_pmops_runtime()) { pm_runtime_forbid(dev); return -EBUSY; } @@ -765,8 +766,10 @@ nouveau_pmops_runtime_resume(struct device *dev) struct nvif_device *device = &nouveau_drm(drm_dev)->client.device; int ret; - if (nouveau_runtime_pm == 0) - return -EINVAL; + if (!nouveau_pmops_runtime()) { + pm_runtime_forbid(dev); + return -EBUSY; + } pci_set_power_state(pdev, PCI_D0); pci_restore_state(pdev); @@ -796,14 +799,7 @@ nouveau_pmops_runtime_idle(struct device *dev) struct nouveau_drm *drm = nouveau_drm(drm_dev); struct drm_crtc *crtc; - if (nouveau_runtime_pm == 0) { - pm_runtime_forbid(dev); - return -EBUSY; - } - - /* are we optimus enabled? */ - if (nouveau_runtime_pm == -1 && !nouveau_is_optimus() && !nouveau_is_v1_dsm()) { - DRM_DEBUG_DRIVER("failing to power off - not optimus\n"); + if (!nouveau_pmops_runtime()) { pm_runtime_forbid(dev); return -EBUSY; } diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index eadec2f49ad3..a11b6aaed325 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -108,8 +108,6 @@ nouveau_cli(struct drm_file *fpriv) #include #include -extern int nouveau_runtime_pm; - struct nouveau_drm { struct nouveau_cli client; struct drm_device *dev; @@ -195,6 +193,7 @@ nouveau_drm(struct drm_device *dev) int nouveau_pmops_suspend(struct device *); int nouveau_pmops_resume(struct device *); +bool nouveau_pmops_runtime(void); #include diff --git a/drivers/gpu/drm/nouveau/nouveau_vga.c b/drivers/gpu/drm/nouveau/nouveau_vga.c index a4aacbc0cec8..02fe0efb9e16 100644 --- a/drivers/gpu/drm/nouveau/nouveau_vga.c +++ b/drivers/gpu/drm/nouveau/nouveau_vga.c @@ -87,7 +87,7 @@ void nouveau_vga_init(struct nouveau_drm *drm) { struct drm_device *dev = drm->dev; - bool runtime = false; + bool runtime = nouveau_pmops_runtime(); /* only relevant for PCI devices */ if (!dev->pdev) @@ -99,10 +99,6 @@ nouveau_vga_init(struct nouveau_drm *drm) if (pci_is_thunderbolt_attached(dev->pdev)) return; - if (nouveau_runtime_pm == 1) - runtime = true; - if ((nouveau_runtime_pm == -1) && (nouveau_is_optimus() || nouveau_is_v1_dsm())) - runtime = true; vga_switcheroo_register_client(dev->pdev, &nouveau_switcheroo_ops, runtime); if (runtime && nouveau_is_v1_dsm() && !nouveau_is_optimus()) @@ -113,18 +109,13 @@ void nouveau_vga_fini(struct nouveau_drm *drm) { struct drm_device *dev = drm->dev; - bool runtime = false; + bool runtime = nouveau_pmops_runtime(); vga_client_register(dev->pdev, NULL, NULL, NULL); if (pci_is_thunderbolt_attached(dev->pdev)) return; - if (nouveau_runtime_pm == 1) - runtime = true; - if ((nouveau_runtime_pm == -1) && (nouveau_is_optimus() || nouveau_is_v1_dsm())) - runtime = true; - vga_switcheroo_unregister_client(dev->pdev); if (runtime && nouveau_is_v1_dsm() && !nouveau_is_optimus()) vga_switcheroo_fini_domain_pm_ops(drm->dev->dev); -- cgit v1.2.3 From 8fa4338acca96cbc231e4125229632e879476464 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 2 Jun 2017 14:49:45 +1000 Subject: drm/nouveau: enable autosuspend only when it'll actually be used This prevents a deadlock that somehow results from the suspend() -> forbid() -> resume() callchain. [ 125.266960] [drm] Initialized nouveau 1.3.1 20120801 for 0000:02:00.0 on minor 1 [ 370.120872] INFO: task kworker/4:1:77 blocked for more than 120 seconds. [ 370.120920] Tainted: G O 4.12.0-rc3 #20 [ 370.120947] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. [ 370.120982] kworker/4:1 D13808 77 2 0x00000000 [ 370.120998] Workqueue: pm pm_runtime_work [ 370.121004] Call Trace: [ 370.121018] __schedule+0x2bf/0xb40 [ 370.121025] ? mark_held_locks+0x5f/0x90 [ 370.121038] schedule+0x3d/0x90 [ 370.121044] rpm_resume+0x107/0x870 [ 370.121052] ? finish_wait+0x90/0x90 [ 370.121065] ? pci_pm_runtime_resume+0xa0/0xa0 [ 370.121070] pm_runtime_forbid+0x4c/0x60 [ 370.121129] nouveau_pmops_runtime_suspend+0xaf/0xc0 [nouveau] [ 370.121139] pci_pm_runtime_suspend+0x5f/0x170 [ 370.121147] ? pci_pm_runtime_resume+0xa0/0xa0 [ 370.121152] __rpm_callback+0xb9/0x1e0 [ 370.121159] ? pci_pm_runtime_resume+0xa0/0xa0 [ 370.121166] rpm_callback+0x24/0x80 [ 370.121171] ? pci_pm_runtime_resume+0xa0/0xa0 [ 370.121176] rpm_suspend+0x138/0x6e0 [ 370.121192] pm_runtime_work+0x7b/0xc0 [ 370.121199] process_one_work+0x253/0x6a0 [ 370.121216] worker_thread+0x4d/0x3b0 [ 370.121229] kthread+0x133/0x150 [ 370.121234] ? process_one_work+0x6a0/0x6a0 [ 370.121238] ? kthread_create_on_node+0x70/0x70 [ 370.121246] ret_from_fork+0x2a/0x40 [ 370.121283] Showing all locks held in the system: [ 370.121291] 2 locks held by kworker/4:1/77: [ 370.121298] #0: ("pm"){.+.+.+}, at: [] process_one_work+0x1d0/0x6a0 [ 370.121315] #1: ((&dev->power.work)){+.+.+.}, at: [] process_one_work+0x1d0/0x6a0 [ 370.121330] 1 lock held by khungtaskd/81: [ 370.121333] #0: (tasklist_lock){.+.+..}, at: [] debug_show_all_locks+0x3d/0x1a0 [ 370.121355] 1 lock held by dmesg/1639: [ 370.121358] #0: (&user->lock){+.+.+.}, at: [] devkmsg_read+0x4d/0x360 [ 370.121377] ============================================= Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_drm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 210910712606..15a13d09d431 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -495,7 +495,7 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags) nouveau_fbcon_init(dev); nouveau_led_init(dev); - if (nouveau_runtime_pm != 0) { + if (nouveau_pmops_runtime()) { pm_runtime_use_autosuspend(dev->dev); pm_runtime_set_autosuspend_delay(dev->dev, 5000); pm_runtime_set_active(dev->dev); @@ -527,7 +527,7 @@ nouveau_drm_unload(struct drm_device *dev) { struct nouveau_drm *drm = nouveau_drm(dev); - if (nouveau_runtime_pm != 0) { + if (nouveau_pmops_runtime()) { pm_runtime_get_sync(dev->dev); pm_runtime_forbid(dev->dev); } -- cgit v1.2.3 From b4e382ca7586a63b6c1e5221ce0863ff867c2df6 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 5 Jun 2017 17:23:32 +1000 Subject: drm/nouveau/tmr: fully separate alarm execution/pending lists Reusing the list_head for both is a bad idea. Callback execution is done with the lock dropped so that alarms can be rescheduled from the callback, which means that with some unfortunate timing, lists can get corrupted. The execution list should not require its own locking, the single function that uses it can only be called from a single context. Signed-off-by: Ben Skeggs Cc: stable@vger.kernel.org --- drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h index 6a567fe347b3..820a4805916f 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h @@ -4,6 +4,7 @@ struct nvkm_alarm { struct list_head head; + struct list_head exec; u64 timestamp; void (*func)(struct nvkm_alarm *); }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c index f2a86eae0a0d..2437f7d41ca2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c @@ -50,7 +50,8 @@ nvkm_timer_alarm_trigger(struct nvkm_timer *tmr) /* Move to completed list. We'll drop the lock before * executing the callback so it can reschedule itself. */ - list_move_tail(&alarm->head, &exec); + list_del_init(&alarm->head); + list_add(&alarm->exec, &exec); } /* Shut down interrupt if no more pending alarms. */ @@ -59,8 +60,8 @@ nvkm_timer_alarm_trigger(struct nvkm_timer *tmr) spin_unlock_irqrestore(&tmr->lock, flags); /* Execute completed callbacks. */ - list_for_each_entry_safe(alarm, atemp, &exec, head) { - list_del_init(&alarm->head); + list_for_each_entry_safe(alarm, atemp, &exec, exec) { + list_del(&alarm->exec); alarm->func(alarm); } } -- cgit v1.2.3 From d68356cc51e304ff9a389f006b6249d41f2c2319 Mon Sep 17 00:00:00 2001 From: Christoffer Dall Date: Sun, 4 Jun 2017 22:17:02 +0200 Subject: KVM: arm/arm64: vgic-v3: Fix nr_pre_bits bitfield extraction We used to extract PRIbits from the ICH_VT_EL2 which was the upper field in the register word, so a mask wasn't necessary, but as we switched to looking at PREbits, which is bits 26 through 28 with the PRIbits field being potentially non-zero, we really need to mask off the field value, otherwise fun things may happen. Signed-off-by: Christoffer Dall Acked-by: Marc Zyngier --- virt/kvm/arm/hyp/vgic-v3-sr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c index 32c3295929b0..87940364570b 100644 --- a/virt/kvm/arm/hyp/vgic-v3-sr.c +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c @@ -22,7 +22,7 @@ #include #define vtr_to_max_lr_idx(v) ((v) & 0xf) -#define vtr_to_nr_pre_bits(v) (((u32)(v) >> 26) + 1) +#define vtr_to_nr_pre_bits(v) ((((u32)(v) >> 26) & 7) + 1) static u64 __hyp_text __gic_v3_get_lr(unsigned int lr) { -- cgit v1.2.3 From 47c298f792992c6eda26fc4e4630c7ca54dcec47 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Wed, 3 May 2017 10:38:18 +0200 Subject: gpu: ipu-v3: pre: only use internal clock gating By setting the SFTRST bit, the PRE will be held in the lowest power state with clocks to the internal blocks gated. When external clock gating is used (from the external clock controller, or by setting the CLKGATE bit) the PRE will sporadically fail to start. Signed-off-by: Lucas Stach Fixes: d2a34232580a ("gpu: ipu-v3: add driver for Prefetch Resolve Engine") Signed-off-by: Philipp Zabel --- drivers/gpu/ipu-v3/ipu-pre.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/ipu-v3/ipu-pre.c b/drivers/gpu/ipu-v3/ipu-pre.c index c55563379e2e..c35f74c83065 100644 --- a/drivers/gpu/ipu-v3/ipu-pre.c +++ b/drivers/gpu/ipu-v3/ipu-pre.c @@ -131,8 +131,6 @@ int ipu_pre_get(struct ipu_pre *pre) if (pre->in_use) return -EBUSY; - clk_prepare_enable(pre->clk_axi); - /* first get the engine out of reset and remove clock gating */ writel(0, pre->regs + IPU_PRE_CTRL); @@ -149,12 +147,7 @@ int ipu_pre_get(struct ipu_pre *pre) void ipu_pre_put(struct ipu_pre *pre) { - u32 val; - - val = IPU_PRE_CTRL_SFTRST | IPU_PRE_CTRL_CLKGATE; - writel(val, pre->regs + IPU_PRE_CTRL); - - clk_disable_unprepare(pre->clk_axi); + writel(IPU_PRE_CTRL_SFTRST, pre->regs + IPU_PRE_CTRL); pre->in_use = false; } @@ -249,6 +242,8 @@ static int ipu_pre_probe(struct platform_device *pdev) if (!pre->buffer_virt) return -ENOMEM; + clk_prepare_enable(pre->clk_axi); + pre->dev = dev; platform_set_drvdata(pdev, pre); mutex_lock(&ipu_pre_list_mutex); @@ -268,6 +263,8 @@ static int ipu_pre_remove(struct platform_device *pdev) available_pres--; mutex_unlock(&ipu_pre_list_mutex); + clk_disable_unprepare(pre->clk_axi); + if (pre->buffer_virt) gen_pool_free(pre->iram, (unsigned long)pre->buffer_virt, IPU_PRE_MAX_WIDTH * IPU_PRE_NUM_SCANLINES * 4); -- cgit v1.2.3 From e36aecba54bf24387271f2d7b989cc686a389931 Mon Sep 17 00:00:00 2001 From: Leonard Crestez Date: Wed, 10 May 2017 16:17:13 +0300 Subject: drm/imx: imx-ldb: Accept drm_of_find_panel_or_bridge failure Not having an endpoint bound in DT should not cause a failure here, there are fallbacks. So explicitly accept a missing endpoint. This behavior change was introduced by refactoring in drm_of parsing code and it should not require dts changes. In particular this fixes imx6qdl-sabreauto boards. Link: https://lists.freedesktop.org/archives/dri-devel/2017-May/141233.html Fixes: ebc944613567 ("drm: convert drivers to use drm_of_find_panel_or_bridge") Signed-off-by: Leonard Crestez Signed-off-by: Philipp Zabel --- drivers/gpu/drm/imx/imx-ldb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c index 8fb801fab039..8b05ecb8fdef 100644 --- a/drivers/gpu/drm/imx/imx-ldb.c +++ b/drivers/gpu/drm/imx/imx-ldb.c @@ -673,7 +673,7 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data) ret = drm_of_find_panel_or_bridge(child, imx_ldb->lvds_mux ? 4 : 2, 0, &channel->panel, &channel->bridge); - if (ret) + if (ret && ret != -ENODEV) return ret; /* panel ddc only if there is no bridge */ -- cgit v1.2.3 From b7dfee2433576f1f030cb84cdb04b70f36554992 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 3 Jun 2017 11:57:21 -0700 Subject: gpu: ipu-v3: Fix CSI selection for VDIC The description of the CSI_SEL bit in the i.MX6 reference manual is incorrect. It states "This bit defines which CSI is the input to the IC. This bit is effective only if IC_INPUT is bit cleared". From experiment it was found this is in fact not correct. The CSI_SEL bit selects which CSI is input to _both_ the VDIC _and_ the IC. If the IC_INPUT bit is set so that the IC is receiving from the VDIC, the IC ignores the CSI_SEL bit, but CSI_SEL still selects which CSI the VDIC receives from in that case. Signed-off-by: Marek Vasut Signed-off-by: Steve Longerbeam Signed-off-by: Philipp Zabel --- drivers/gpu/ipu-v3/ipu-common.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/ipu-v3/ipu-common.c b/drivers/gpu/ipu-v3/ipu-common.c index 16d556816b5f..2fb5f432a54c 100644 --- a/drivers/gpu/ipu-v3/ipu-common.c +++ b/drivers/gpu/ipu-v3/ipu-common.c @@ -725,15 +725,16 @@ void ipu_set_ic_src_mux(struct ipu_soc *ipu, int csi_id, bool vdi) spin_lock_irqsave(&ipu->lock, flags); val = ipu_cm_read(ipu, IPU_CONF); - if (vdi) { + if (vdi) val |= IPU_CONF_IC_INPUT; - } else { + else val &= ~IPU_CONF_IC_INPUT; - if (csi_id == 1) - val |= IPU_CONF_CSI_SEL; - else - val &= ~IPU_CONF_CSI_SEL; - } + + if (csi_id == 1) + val |= IPU_CONF_CSI_SEL; + else + val &= ~IPU_CONF_CSI_SEL; + ipu_cm_write(ipu, val, IPU_CONF); spin_unlock_irqrestore(&ipu->lock, flags); -- cgit v1.2.3 From 7f22ced4377628074e2ac25f41a88f98eb3b03f1 Mon Sep 17 00:00:00 2001 From: Breno Leitao Date: Mon, 5 Jun 2017 11:40:59 -0300 Subject: powerpc/kernel: Initialize load_tm on task creation Currently tsk->thread.load_tm is not initialized in the task creation and can contain garbage on a new task. This is an undesired behaviour, since it affects the timing to enable and disable the transactional memory laziness (disabling and enabling the MSR TM bit, which affects TM reclaim and recheckpoint in the scheduling process). Fixes: 5d176f751ee3 ("powerpc: tm: Enable transactional memory (TM) lazily for userspace") Cc: stable@vger.kernel.org # v4.9+ Signed-off-by: Breno Leitao Signed-off-by: Michael Ellerman --- arch/powerpc/kernel/process.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index a9435397eab8..2ad725ef4368 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -1687,6 +1687,7 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp) current->thread.tm_tfhar = 0; current->thread.tm_texasr = 0; current->thread.tm_tfiar = 0; + current->thread.load_tm = 0; #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */ } EXPORT_SYMBOL(start_thread); -- cgit v1.2.3 From b3aa20ba2ba8072b73bd799605b8c98927b7056c Mon Sep 17 00:00:00 2001 From: Vaibhav Jain Date: Fri, 2 Jun 2017 22:26:48 +0530 Subject: cxl: Avoid double free_irq() for psl,slice interrupts During an eeh call to cxl_remove can result in double free_irq of psl,slice interrupts. This can happen if perst_reloads_same_image == 1 and call to cxl_configure_adapter() fails during slot_reset callback. In such a case we see a kernel oops with following back-trace: Oops: Kernel access of bad area, sig: 11 [#1] Call Trace: free_irq+0x88/0xd0 (unreliable) cxl_unmap_irq+0x20/0x40 [cxl] cxl_native_release_psl_irq+0x78/0xd8 [cxl] pci_deconfigure_afu+0xac/0x110 [cxl] cxl_remove+0x104/0x210 [cxl] pci_device_remove+0x6c/0x110 device_release_driver_internal+0x204/0x2e0 pci_stop_bus_device+0xa0/0xd0 pci_stop_and_remove_bus_device+0x28/0x40 pci_hp_remove_devices+0xb0/0x150 pci_hp_remove_devices+0x68/0x150 eeh_handle_normal_event+0x140/0x580 eeh_handle_event+0x174/0x360 eeh_event_handler+0x1e8/0x1f0 This patch fixes the issue of double free_irq by checking that variables that hold the virqs (err_hwirq, serr_hwirq, psl_virq) are not '0' before un-mapping and resetting these variables to '0' when they are un-mapped. Cc: stable@vger.kernel.org Signed-off-by: Vaibhav Jain Reviewed-by: Andrew Donnellan Acked-by: Frederic Barrat Signed-off-by: Michael Ellerman --- drivers/misc/cxl/native.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/misc/cxl/native.c b/drivers/misc/cxl/native.c index 871a2f09c718..8d6ea9712dbd 100644 --- a/drivers/misc/cxl/native.c +++ b/drivers/misc/cxl/native.c @@ -1302,13 +1302,16 @@ int cxl_native_register_psl_err_irq(struct cxl *adapter) void cxl_native_release_psl_err_irq(struct cxl *adapter) { - if (adapter->native->err_virq != irq_find_mapping(NULL, adapter->native->err_hwirq)) + if (adapter->native->err_virq == 0 || + adapter->native->err_virq != + irq_find_mapping(NULL, adapter->native->err_hwirq)) return; cxl_p1_write(adapter, CXL_PSL_ErrIVTE, 0x0000000000000000); cxl_unmap_irq(adapter->native->err_virq, adapter); cxl_ops->release_one_irq(adapter, adapter->native->err_hwirq); kfree(adapter->irq_name); + adapter->native->err_virq = 0; } int cxl_native_register_serr_irq(struct cxl_afu *afu) @@ -1346,13 +1349,15 @@ int cxl_native_register_serr_irq(struct cxl_afu *afu) void cxl_native_release_serr_irq(struct cxl_afu *afu) { - if (afu->serr_virq != irq_find_mapping(NULL, afu->serr_hwirq)) + if (afu->serr_virq == 0 || + afu->serr_virq != irq_find_mapping(NULL, afu->serr_hwirq)) return; cxl_p1n_write(afu, CXL_PSL_SERR_An, 0x0000000000000000); cxl_unmap_irq(afu->serr_virq, afu); cxl_ops->release_one_irq(afu->adapter, afu->serr_hwirq); kfree(afu->err_irq_name); + afu->serr_virq = 0; } int cxl_native_register_psl_irq(struct cxl_afu *afu) @@ -1375,12 +1380,15 @@ int cxl_native_register_psl_irq(struct cxl_afu *afu) void cxl_native_release_psl_irq(struct cxl_afu *afu) { - if (afu->native->psl_virq != irq_find_mapping(NULL, afu->native->psl_hwirq)) + if (afu->native->psl_virq == 0 || + afu->native->psl_virq != + irq_find_mapping(NULL, afu->native->psl_hwirq)) return; cxl_unmap_irq(afu->native->psl_virq, afu); cxl_ops->release_one_irq(afu->adapter, afu->native->psl_hwirq); kfree(afu->psl_irq_name); + afu->native->psl_virq = 0; } static void recover_psl_err(struct cxl_afu *afu, u64 errstat) -- cgit v1.2.3 From 9e6c9c0f2ce67534fda1fdd305fb5da3defece3e Mon Sep 17 00:00:00 2001 From: "Mauro S. M. Rodrigues" Date: Fri, 12 May 2017 23:26:56 -0300 Subject: i40e: Fix state flags for bit set and clean operations of PF Commit 0da36b9774cc ("i40e: use DECLARE_BITMAP for state fields") introduced changes in the way i40e works with state flags converting them to bitmaps using kernel bitmap API. This change introduced a regression due to a mistaken substitution using __I40E_VSI_DOWN instead of __I40E_DOWN when testing state of a PF at i40e_reset_subtask() function. This caused a flood in the kernel log with the follow message: [49.013] i40e 0002:01:00.0: bad reset request 0x00000020 Commit d19cb64b9222 ("i40e: separate PF and VSI state flags") also introduced some misuse of the VSI and PF flags, so both could be considered as the offenders. This patch simply fixes the flags where it makes sense by changing __I40E_VSI_DOWN to __I40E_DOWN. Fixes: 0da36b9774cc ("i40e: use DECLARE_BITMAP for state fields") Fixes: d19cb64b9222 ("i40e: separate PF and VSI state flags") Reviewed-by: "Guilherme G. Piccoli" Signed-off-by: "Mauro S. M. Rodrigues" Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 36 ++++++++++++++--------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index d5c9c9e06ff5..150caf6ca2b4 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -295,7 +295,7 @@ struct i40e_vsi *i40e_find_vsi_from_id(struct i40e_pf *pf, u16 id) **/ void i40e_service_event_schedule(struct i40e_pf *pf) { - if (!test_bit(__I40E_VSI_DOWN, pf->state) && + if (!test_bit(__I40E_DOWN, pf->state) && !test_bit(__I40E_RESET_RECOVERY_PENDING, pf->state)) queue_work(i40e_wq, &pf->service_task); } @@ -3611,7 +3611,7 @@ static irqreturn_t i40e_intr(int irq, void *data) * this is not a performance path and napi_schedule() * can deal with rescheduling. */ - if (!test_bit(__I40E_VSI_DOWN, pf->state)) + if (!test_bit(__I40E_DOWN, pf->state)) napi_schedule_irqoff(&q_vector->napi); } @@ -3687,7 +3687,7 @@ static irqreturn_t i40e_intr(int irq, void *data) enable_intr: /* re-enable interrupt causes */ wr32(hw, I40E_PFINT_ICR0_ENA, ena_mask); - if (!test_bit(__I40E_VSI_DOWN, pf->state)) { + if (!test_bit(__I40E_DOWN, pf->state)) { i40e_service_event_schedule(pf); i40e_irq_dynamic_enable_icr0(pf, false); } @@ -6203,7 +6203,7 @@ static void i40e_fdir_reinit_subtask(struct i40e_pf *pf) { /* if interface is down do nothing */ - if (test_bit(__I40E_VSI_DOWN, pf->state)) + if (test_bit(__I40E_DOWN, pf->state)) return; if (test_bit(__I40E_FD_FLUSH_REQUESTED, pf->state)) @@ -6344,7 +6344,7 @@ static void i40e_watchdog_subtask(struct i40e_pf *pf) int i; /* if interface is down do nothing */ - if (test_bit(__I40E_VSI_DOWN, pf->state) || + if (test_bit(__I40E_DOWN, pf->state) || test_bit(__I40E_CONFIG_BUSY, pf->state)) return; @@ -6399,9 +6399,9 @@ static void i40e_reset_subtask(struct i40e_pf *pf) reset_flags |= BIT(__I40E_GLOBAL_RESET_REQUESTED); clear_bit(__I40E_GLOBAL_RESET_REQUESTED, pf->state); } - if (test_bit(__I40E_VSI_DOWN_REQUESTED, pf->state)) { - reset_flags |= BIT(__I40E_VSI_DOWN_REQUESTED); - clear_bit(__I40E_VSI_DOWN_REQUESTED, pf->state); + if (test_bit(__I40E_DOWN_REQUESTED, pf->state)) { + reset_flags |= BIT(__I40E_DOWN_REQUESTED); + clear_bit(__I40E_DOWN_REQUESTED, pf->state); } /* If there's a recovery already waiting, it takes @@ -6415,7 +6415,7 @@ static void i40e_reset_subtask(struct i40e_pf *pf) /* If we're already down or resetting, just bail */ if (reset_flags && - !test_bit(__I40E_VSI_DOWN, pf->state) && + !test_bit(__I40E_DOWN, pf->state) && !test_bit(__I40E_CONFIG_BUSY, pf->state)) { rtnl_lock(); i40e_do_reset(pf, reset_flags, true); @@ -7002,7 +7002,7 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired) u32 val; int v; - if (test_bit(__I40E_VSI_DOWN, pf->state)) + if (test_bit(__I40E_DOWN, pf->state)) goto clear_recovery; dev_dbg(&pf->pdev->dev, "Rebuilding internal switch\n"); @@ -9767,7 +9767,7 @@ int i40e_vsi_release(struct i40e_vsi *vsi) return -ENODEV; } if (vsi == pf->vsi[pf->lan_vsi] && - !test_bit(__I40E_VSI_DOWN, pf->state)) { + !test_bit(__I40E_DOWN, pf->state)) { dev_info(&pf->pdev->dev, "Can't remove PF VSI\n"); return -ENODEV; } @@ -11003,7 +11003,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } pf->next_vsi = 0; pf->pdev = pdev; - set_bit(__I40E_VSI_DOWN, pf->state); + set_bit(__I40E_DOWN, pf->state); hw = &pf->hw; hw->back = pf; @@ -11293,7 +11293,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) * before setting up the misc vector or we get a race and the vector * ends up disabled forever. */ - clear_bit(__I40E_VSI_DOWN, pf->state); + clear_bit(__I40E_DOWN, pf->state); /* In case of MSIX we are going to setup the misc vector right here * to handle admin queue events etc. In case of legacy and MSI @@ -11448,7 +11448,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* Unwind what we've done if something failed in the setup */ err_vsis: - set_bit(__I40E_VSI_DOWN, pf->state); + set_bit(__I40E_DOWN, pf->state); i40e_clear_interrupt_scheme(pf); kfree(pf->vsi); err_switch_setup: @@ -11500,7 +11500,7 @@ static void i40e_remove(struct pci_dev *pdev) /* no more scheduling of any task */ set_bit(__I40E_SUSPENDED, pf->state); - set_bit(__I40E_VSI_DOWN, pf->state); + set_bit(__I40E_DOWN, pf->state); if (pf->service_timer.data) del_timer_sync(&pf->service_timer); if (pf->service_task.func) @@ -11740,7 +11740,7 @@ static void i40e_shutdown(struct pci_dev *pdev) struct i40e_hw *hw = &pf->hw; set_bit(__I40E_SUSPENDED, pf->state); - set_bit(__I40E_VSI_DOWN, pf->state); + set_bit(__I40E_DOWN, pf->state); rtnl_lock(); i40e_prep_for_reset(pf, true); rtnl_unlock(); @@ -11789,7 +11789,7 @@ static int i40e_suspend(struct pci_dev *pdev, pm_message_t state) int retval = 0; set_bit(__I40E_SUSPENDED, pf->state); - set_bit(__I40E_VSI_DOWN, pf->state); + set_bit(__I40E_DOWN, pf->state); if (pf->wol_en && (pf->flags & I40E_FLAG_WOL_MC_MAGIC_PKT_WAKE)) i40e_enable_mc_magic_wake(pf); @@ -11841,7 +11841,7 @@ static int i40e_resume(struct pci_dev *pdev) /* handling the reset will rebuild the device state */ if (test_and_clear_bit(__I40E_SUSPENDED, pf->state)) { - clear_bit(__I40E_VSI_DOWN, pf->state); + clear_bit(__I40E_DOWN, pf->state); rtnl_lock(); i40e_reset_and_rebuild(pf, false, true); rtnl_unlock(); -- cgit v1.2.3 From 2aae918c7a21fb8388ab30b8abd4d9240e8ebd7f Mon Sep 17 00:00:00 2001 From: Björn Töpel Date: Mon, 15 May 2017 06:52:00 +0200 Subject: i40e/i40evf: proper update of the page_offset field MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In f8b45b74cc62 ("i40e/i40evf: Use build_skb to build frames") i40e_build_skb updates the page_offset field with an incorrect offset, which can lead to data corruption. This patch updates page_offset correctly, by properly setting truesize. Note that the bug only appears on architectures where PAGE_SIZE is 8192 or larger. Fixes: f8b45b74cc62 ("i40e/i40evf: Use build_skb to build frames") Signed-off-by: Björn Töpel Acked-by: Alexander Duyck Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 3 ++- drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 29321a6167a6..cd894f4023b1 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -1854,7 +1854,8 @@ static struct sk_buff *i40e_build_skb(struct i40e_ring *rx_ring, #if (PAGE_SIZE < 8192) unsigned int truesize = i40e_rx_pg_size(rx_ring) / 2; #else - unsigned int truesize = SKB_DATA_ALIGN(size); + unsigned int truesize = SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) + + SKB_DATA_ALIGN(I40E_SKB_PAD + size); #endif struct sk_buff *skb; diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c index dfe241a12ad0..12b02e530503 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c @@ -1190,7 +1190,8 @@ static struct sk_buff *i40e_build_skb(struct i40e_ring *rx_ring, #if (PAGE_SIZE < 8192) unsigned int truesize = i40e_rx_pg_size(rx_ring) / 2; #else - unsigned int truesize = SKB_DATA_ALIGN(size); + unsigned int truesize = SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) + + SKB_DATA_ALIGN(I40E_SKB_PAD + size); #endif struct sk_buff *skb; -- cgit v1.2.3 From 28e8af8a163ed6afe9498f1d499a5061c2214755 Mon Sep 17 00:00:00 2001 From: Chris Chiu Date: Mon, 5 Jun 2017 15:05:30 -0600 Subject: ALSA: hda/realtek: Fix mic and headset jack sense on Asus X705UD The ASUS X705UD laptop requires the known fixup ALC256_FIXUP_ASUS_MIC in order to fix headphone jack sensing and to enable use of the internal microphone. Unfortunately jack sensing for the headset mic is still not working. [rearranged the position to keep the PCI SSID order -- tiwai] Signed-off-by: Chris Chiu Signed-off-by: Daniel Drake Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index a57988d617e9..8f9a41f4e2d2 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -5862,6 +5862,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1043, 0x1517, "Asus Zenbook UX31A", ALC269VB_FIXUP_ASUS_ZENBOOK_UX31A), SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC), SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW), + SND_PCI_QUIRK(0x1043, 0x1a30, "ASUS X705UD", ALC256_FIXUP_ASUS_MIC), SND_PCI_QUIRK(0x1043, 0x1b13, "Asus U41SV", ALC269_FIXUP_INV_DMIC), SND_PCI_QUIRK(0x1043, 0x1c23, "Asus X55U", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), SND_PCI_QUIRK(0x1043, 0x1bbd, "ASUS Z550MA", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE), -- cgit v1.2.3 From 4eab0ea196f569ed2085a0fa3729f60eb8edaad1 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 6 Jun 2017 12:33:17 +0200 Subject: ALSA: hda/realtek - Reorder ALC269 ASUS quirk entries A disorder is found in some ALC269 quirk entries for ASUS (1043:xxxx), which should have been sorted in PCI SSID order. Rearrange them, so that I won't overlook the already existing entry like I did a couple of times in the past... Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 8f9a41f4e2d2..cbeebc0a9711 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -5854,7 +5854,11 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300), SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), SND_PCI_QUIRK(0x1043, 0x10c0, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC), + SND_PCI_QUIRK(0x1043, 0x10d0, "ASUS X540LA/X540LJ", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1043, 0x115d, "Asus 1015E", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), + SND_PCI_QUIRK(0x1043, 0x11c0, "ASUS X556UR", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1043, 0x1290, "ASUS X441SA", ALC233_FIXUP_EAPD_COEF_AND_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1043, 0x12a0, "ASUS X441UV", ALC233_FIXUP_EAPD_COEF_AND_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1043, 0x12f0, "ASUS X541UV", ALC256_FIXUP_ASUS_MIC), SND_PCI_QUIRK(0x1043, 0x12e0, "ASUS X541SA", ALC256_FIXUP_ASUS_MIC), SND_PCI_QUIRK(0x1043, 0x13b0, "ASUS Z550SA", ALC256_FIXUP_ASUS_MIC), @@ -5864,12 +5868,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW), SND_PCI_QUIRK(0x1043, 0x1a30, "ASUS X705UD", ALC256_FIXUP_ASUS_MIC), SND_PCI_QUIRK(0x1043, 0x1b13, "Asus U41SV", ALC269_FIXUP_INV_DMIC), - SND_PCI_QUIRK(0x1043, 0x1c23, "Asus X55U", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), SND_PCI_QUIRK(0x1043, 0x1bbd, "ASUS Z550MA", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x1043, 0x10d0, "ASUS X540LA/X540LJ", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x1043, 0x11c0, "ASUS X556UR", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x1043, 0x1290, "ASUS X441SA", ALC233_FIXUP_EAPD_COEF_AND_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x1043, 0x12a0, "ASUS X441UV", ALC233_FIXUP_EAPD_COEF_AND_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1043, 0x1c23, "Asus X55U", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), SND_PCI_QUIRK(0x1043, 0x1ccd, "ASUS X555UB", ALC256_FIXUP_ASUS_MIC), SND_PCI_QUIRK(0x1043, 0x3030, "ASUS ZN270IE", ALC256_FIXUP_ASUS_AIO_GPIO2), SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC), -- cgit v1.2.3 From ba4a648f12f4cd0a8003dd229b6ca8a53348ee4b Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 6 Jun 2017 20:23:57 +1000 Subject: powerpc/numa: Fix percpu allocations to be NUMA aware In commit 8c272261194d ("powerpc/numa: Enable USE_PERCPU_NUMA_NODE_ID"), we switched to the generic implementation of cpu_to_node(), which uses a percpu variable to hold the NUMA node for each CPU. Unfortunately we neglected to notice that we use cpu_to_node() in the allocation of our percpu areas, leading to a chicken and egg problem. In practice what happens is when we are setting up the percpu areas, cpu_to_node() reports that all CPUs are on node 0, so we allocate all percpu areas on node 0. This is visible in the dmesg output, as all pcpu allocs being in group 0: pcpu-alloc: [0] 00 01 02 03 [0] 04 05 06 07 pcpu-alloc: [0] 08 09 10 11 [0] 12 13 14 15 pcpu-alloc: [0] 16 17 18 19 [0] 20 21 22 23 pcpu-alloc: [0] 24 25 26 27 [0] 28 29 30 31 pcpu-alloc: [0] 32 33 34 35 [0] 36 37 38 39 pcpu-alloc: [0] 40 41 42 43 [0] 44 45 46 47 To fix it we need an early_cpu_to_node() which can run prior to percpu being setup. We already have the numa_cpu_lookup_table we can use, so just plumb it in. With the patch dmesg output shows two groups, 0 and 1: pcpu-alloc: [0] 00 01 02 03 [0] 04 05 06 07 pcpu-alloc: [0] 08 09 10 11 [0] 12 13 14 15 pcpu-alloc: [0] 16 17 18 19 [0] 20 21 22 23 pcpu-alloc: [1] 24 25 26 27 [1] 28 29 30 31 pcpu-alloc: [1] 32 33 34 35 [1] 36 37 38 39 pcpu-alloc: [1] 40 41 42 43 [1] 44 45 46 47 We can also check the data_offset in the paca of various CPUs, with the fix we see: CPU 0: data_offset = 0x0ffe8b0000 CPU 24: data_offset = 0x1ffe5b0000 And we can see from dmesg that CPU 24 has an allocation on node 1: node 0: [mem 0x0000000000000000-0x0000000fffffffff] node 1: [mem 0x0000001000000000-0x0000001fffffffff] Cc: stable@vger.kernel.org # v3.16+ Fixes: 8c272261194d ("powerpc/numa: Enable USE_PERCPU_NUMA_NODE_ID") Signed-off-by: Michael Ellerman Reviewed-by: Nicholas Piggin Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/topology.h | 14 ++++++++++++++ arch/powerpc/kernel/setup_64.c | 4 ++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/include/asm/topology.h b/arch/powerpc/include/asm/topology.h index 8b3b46b7b0f2..329771559cbb 100644 --- a/arch/powerpc/include/asm/topology.h +++ b/arch/powerpc/include/asm/topology.h @@ -44,8 +44,22 @@ extern void __init dump_numa_cpu_topology(void); extern int sysfs_add_device_to_node(struct device *dev, int nid); extern void sysfs_remove_device_from_node(struct device *dev, int nid); +static inline int early_cpu_to_node(int cpu) +{ + int nid; + + nid = numa_cpu_lookup_table[cpu]; + + /* + * Fall back to node 0 if nid is unset (it should be, except bugs). + * This allows callers to safely do NODE_DATA(early_cpu_to_node(cpu)). + */ + return (nid < 0) ? 0 : nid; +} #else +static inline int early_cpu_to_node(int cpu) { return 0; } + static inline void dump_numa_cpu_topology(void) {} static inline int sysfs_add_device_to_node(struct device *dev, int nid) diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index f35ff9dea4fb..a8c1f99e9607 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -661,7 +661,7 @@ void __init emergency_stack_init(void) static void * __init pcpu_fc_alloc(unsigned int cpu, size_t size, size_t align) { - return __alloc_bootmem_node(NODE_DATA(cpu_to_node(cpu)), size, align, + return __alloc_bootmem_node(NODE_DATA(early_cpu_to_node(cpu)), size, align, __pa(MAX_DMA_ADDRESS)); } @@ -672,7 +672,7 @@ static void __init pcpu_fc_free(void *ptr, size_t size) static int pcpu_cpu_distance(unsigned int from, unsigned int to) { - if (cpu_to_node(from) == cpu_to_node(to)) + if (early_cpu_to_node(from) == early_cpu_to_node(to)) return LOCAL_DISTANCE; else return REMOTE_DISTANCE; -- cgit v1.2.3 From 8c218578fcbbbdb10416c8614658bf32e3bf1655 Mon Sep 17 00:00:00 2001 From: Madhavan Srinivasan Date: Fri, 26 May 2017 13:38:27 +0530 Subject: powerpc/perf: Fix Power9 test_adder fields Commit 8d911904f3ce4 ('powerpc/perf: Add restrictions to PMC5 in power9 DD1') was added to restrict the use of PMC5 in Power9 DD1. Intention was to disable the use of PMC5 using raw event code. But instead of updating the power9_isa207_pmu structure (used on DD1), the commit incorrectly updated the power9_pmu structure. Fix it. Fixes: 8d911904f3ce ("powerpc/perf: Add restrictions to PMC5 in power9 DD1") Reported-by: Shriya Signed-off-by: Madhavan Srinivasan Tested-by: Shriya Signed-off-by: Michael Ellerman --- arch/powerpc/perf/power9-pmu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/perf/power9-pmu.c b/arch/powerpc/perf/power9-pmu.c index 018f8e90ac35..bb28e1a41257 100644 --- a/arch/powerpc/perf/power9-pmu.c +++ b/arch/powerpc/perf/power9-pmu.c @@ -402,7 +402,7 @@ static struct power_pmu power9_isa207_pmu = { .name = "POWER9", .n_counter = MAX_PMU_COUNTERS, .add_fields = ISA207_ADD_FIELDS, - .test_adder = ISA207_TEST_ADDER, + .test_adder = P9_DD1_TEST_ADDER, .compute_mmcr = isa207_compute_mmcr, .config_bhrb = power9_config_bhrb, .bhrb_filter_map = power9_bhrb_filter_map, @@ -421,7 +421,7 @@ static struct power_pmu power9_pmu = { .name = "POWER9", .n_counter = MAX_PMU_COUNTERS, .add_fields = ISA207_ADD_FIELDS, - .test_adder = P9_DD1_TEST_ADDER, + .test_adder = ISA207_TEST_ADDER, .compute_mmcr = isa207_compute_mmcr, .config_bhrb = power9_config_bhrb, .bhrb_filter_map = power9_bhrb_filter_map, -- cgit v1.2.3 From bbaf0e2b1c1b4f88abd6ef49576f0efb1734eae5 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 26 Apr 2017 16:56:26 +0200 Subject: kvm: async_pf: fix rcu_irq_enter() with irqs enabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit native_safe_halt enables interrupts, and you just shouldn't call rcu_irq_enter() with interrupts enabled. Reorder the call with the following local_irq_disable() to respect the invariant. Reported-by: Ross Zwisler Cc: stable@vger.kernel.org Signed-off-by: Paolo Bonzini Acked-by: Paul E. McKenney Tested-by: Wanpeng Li Signed-off-by: Radim Krčmář --- arch/x86/kernel/kvm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c index da5c09789984..43e10d6fdbed 100644 --- a/arch/x86/kernel/kvm.c +++ b/arch/x86/kernel/kvm.c @@ -161,8 +161,8 @@ void kvm_async_pf_task_wait(u32 token) */ rcu_irq_exit(); native_safe_halt(); - rcu_irq_enter(); local_irq_disable(); + rcu_irq_enter(); } } if (!n.halted) -- cgit v1.2.3 From d4912215d1031e4fb3d1038d2e1857218dba0d0a Mon Sep 17 00:00:00 2001 From: Wanpeng Li Date: Mon, 5 Jun 2017 05:19:09 -0700 Subject: KVM: nVMX: Fix exception injection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit WARNING: CPU: 3 PID: 2840 at arch/x86/kvm/vmx.c:10966 nested_vmx_vmexit+0xdcd/0xde0 [kvm_intel] CPU: 3 PID: 2840 Comm: qemu-system-x86 Tainted: G OE 4.12.0-rc3+ #23 RIP: 0010:nested_vmx_vmexit+0xdcd/0xde0 [kvm_intel] Call Trace: ? kvm_check_async_pf_completion+0xef/0x120 [kvm] ? rcu_read_lock_sched_held+0x79/0x80 vmx_queue_exception+0x104/0x160 [kvm_intel] ? vmx_queue_exception+0x104/0x160 [kvm_intel] kvm_arch_vcpu_ioctl_run+0x1171/0x1ce0 [kvm] ? kvm_arch_vcpu_load+0x47/0x240 [kvm] ? kvm_arch_vcpu_load+0x62/0x240 [kvm] kvm_vcpu_ioctl+0x384/0x7b0 [kvm] ? kvm_vcpu_ioctl+0x384/0x7b0 [kvm] ? __fget+0xf3/0x210 do_vfs_ioctl+0xa4/0x700 ? __fget+0x114/0x210 SyS_ioctl+0x79/0x90 do_syscall_64+0x81/0x220 entry_SYSCALL64_slow_path+0x25/0x25 This is triggered occasionally by running both win7 and win2016 in L2, in addition, EPT is disabled on both L1 and L2. It can't be reproduced easily. Commit 0b6ac343fc (KVM: nVMX: Correct handling of exception injection) mentioned that "KVM wants to inject page-faults which it got to the guest. This function assumes it is called with the exit reason in vmcs02 being a #PF exception". Commit e011c663 (KVM: nVMX: Check all exceptions for intercept during delivery to L2) allows to check all exceptions for intercept during delivery to L2. However, there is no guarantee the exit reason is exception currently, when there is an external interrupt occurred on host, maybe a time interrupt for host which should not be injected to guest, and somewhere queues an exception, then the function nested_vmx_check_exception() will be called and the vmexit emulation codes will try to emulate the "Acknowledge interrupt on exit" behavior, the warning is triggered. Reusing the exit reason from the L2->L0 vmexit is wrong in this case, the reason must always be EXCEPTION_NMI when injecting an exception into L1 as a nested vmexit. Cc: Paolo Bonzini Cc: Radim Krčmář Signed-off-by: Wanpeng Li Fixes: e011c663b9c7 ("KVM: nVMX: Check all exceptions for intercept during delivery to L2") Signed-off-by: Radim Krčmář --- arch/x86/kvm/vmx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 9b4b5d6dcd34..ca5d2b93385c 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -2425,7 +2425,7 @@ static int nested_vmx_check_exception(struct kvm_vcpu *vcpu, unsigned nr) if (!(vmcs12->exception_bitmap & (1u << nr))) return 0; - nested_vmx_vmexit(vcpu, to_vmx(vcpu)->exit_reason, + nested_vmx_vmexit(vcpu, EXIT_REASON_EXCEPTION_NMI, vmcs_read32(VM_EXIT_INTR_INFO), vmcs_readl(EXIT_QUALIFICATION)); return 1; -- cgit v1.2.3 From d6dbdd3c8558cad3b6d74cc357b408622d122331 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Mon, 5 Jun 2017 19:17:18 +0100 Subject: KVM: arm/arm64: Handle possible NULL stage2 pud when ageing pages Under memory pressure, we start ageing pages, which amounts to parsing the page tables. Since we don't want to allocate any extra level, we pass NULL for our private allocation cache. Which means that stage2_get_pud() is allowed to fail. This results in the following splat: [ 1520.409577] Unable to handle kernel NULL pointer dereference at virtual address 00000008 [ 1520.417741] pgd = ffff810f52fef000 [ 1520.421201] [00000008] *pgd=0000010f636c5003, *pud=0000010f56f48003, *pmd=0000000000000000 [ 1520.429546] Internal error: Oops: 96000006 [#1] PREEMPT SMP [ 1520.435156] Modules linked in: [ 1520.438246] CPU: 15 PID: 53550 Comm: qemu-system-aar Tainted: G W 4.12.0-rc4-00027-g1885c397eaec #7205 [ 1520.448705] Hardware name: FOXCONN R2-1221R-A4/C2U4N_MB, BIOS G31FB12A 10/26/2016 [ 1520.463726] task: ffff800ac5fb4e00 task.stack: ffff800ce04e0000 [ 1520.469666] PC is at stage2_get_pmd+0x34/0x110 [ 1520.474119] LR is at kvm_age_hva_handler+0x44/0xf0 [ 1520.478917] pc : [] lr : [] pstate: 40000145 [ 1520.486325] sp : ffff800ce04e33d0 [ 1520.489644] x29: ffff800ce04e33d0 x28: 0000000ffff40064 [ 1520.494967] x27: 0000ffff27e00000 x26: 0000000000000000 [ 1520.500289] x25: ffff81051ba65008 x24: 0000ffff40065000 [ 1520.505618] x23: 0000ffff40064000 x22: 0000000000000000 [ 1520.510947] x21: ffff810f52b20000 x20: 0000000000000000 [ 1520.516274] x19: 0000000058264000 x18: 0000000000000000 [ 1520.521603] x17: 0000ffffa6fe7438 x16: ffff000008278b70 [ 1520.526940] x15: 000028ccd8000000 x14: 0000000000000008 [ 1520.532264] x13: ffff7e0018298000 x12: 0000000000000002 [ 1520.537582] x11: ffff000009241b93 x10: 0000000000000940 [ 1520.542908] x9 : ffff0000092ef800 x8 : 0000000000000200 [ 1520.548229] x7 : ffff800ce04e36a8 x6 : 0000000000000000 [ 1520.553552] x5 : 0000000000000001 x4 : 0000000000000000 [ 1520.558873] x3 : 0000000000000000 x2 : 0000000000000008 [ 1520.571696] x1 : ffff000008fd5000 x0 : ffff0000080b149c [ 1520.577039] Process qemu-system-aar (pid: 53550, stack limit = 0xffff800ce04e0000) [...] [ 1521.510735] [] stage2_get_pmd+0x34/0x110 [ 1521.516221] [] kvm_age_hva_handler+0x44/0xf0 [ 1521.522054] [] handle_hva_to_gpa+0xb8/0xe8 [ 1521.527716] [] kvm_age_hva+0x44/0xf0 [ 1521.532854] [] kvm_mmu_notifier_clear_flush_young+0x70/0xc0 [ 1521.539992] [] __mmu_notifier_clear_flush_young+0x88/0xd0 [ 1521.546958] [] page_referenced_one+0xf0/0x188 [ 1521.552881] [] rmap_walk_anon+0xec/0x250 [ 1521.558370] [] rmap_walk+0x78/0xa0 [ 1521.563337] [] page_referenced+0x164/0x180 [ 1521.569002] [] shrink_active_list+0x178/0x3b8 [ 1521.574922] [] shrink_node_memcg+0x328/0x600 [ 1521.580758] [] shrink_node+0xc4/0x328 [ 1521.585986] [] do_try_to_free_pages+0xc0/0x340 [ 1521.592000] [] try_to_free_pages+0xcc/0x240 [...] The trivial fix is to handle this NULL pud value early, rather than dereferencing it blindly. Cc: stable@vger.kernel.org Signed-off-by: Marc Zyngier Reviewed-by: Christoffer Dall Signed-off-by: Christoffer Dall --- virt/kvm/arm/mmu.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/virt/kvm/arm/mmu.c b/virt/kvm/arm/mmu.c index a2d63247d1bb..e2e5effba2a9 100644 --- a/virt/kvm/arm/mmu.c +++ b/virt/kvm/arm/mmu.c @@ -879,6 +879,9 @@ static pmd_t *stage2_get_pmd(struct kvm *kvm, struct kvm_mmu_memory_cache *cache pmd_t *pmd; pud = stage2_get_pud(kvm, cache, addr); + if (!pud) + return NULL; + if (stage2_pud_none(*pud)) { if (!cache) return NULL; -- cgit v1.2.3 From 26f4b1f7a8da3eaa6c32e12f87c9f5388196dc67 Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Tue, 6 Jun 2017 11:00:45 +0300 Subject: staging: ccree: fix buffer copy Fix a bug where the copying of scatterlist buffers incorrectly ignored bytes to skip in a scatterlist and ended 1 byte short. This fixes testmgr hmac and hash test failures currently obscured by hash import/export not being supported. Fixes: abefd6741d ("staging: ccree: introduce CryptoCell HW driver"). Signed-off-by: Gilad Ben-Yossef Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_buffer_mgr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/ccree/ssi_buffer_mgr.c b/drivers/staging/ccree/ssi_buffer_mgr.c index 038e2ff5e545..6471d3d2d375 100644 --- a/drivers/staging/ccree/ssi_buffer_mgr.c +++ b/drivers/staging/ccree/ssi_buffer_mgr.c @@ -216,7 +216,8 @@ void ssi_buffer_mgr_copy_scatterlist_portion( uint32_t nents, lbytes; nents = ssi_buffer_mgr_get_sgl_nents(sg, end, &lbytes, NULL); - sg_copy_buffer(sg, nents, (void *)dest, (end - to_skip), 0, (direct == SSI_SG_TO_BUF)); + sg_copy_buffer(sg, nents, (void *)dest, (end - to_skip + 1), to_skip, + (direct == SSI_SG_TO_BUF)); } static inline int ssi_buffer_mgr_render_buff_to_mlli( -- cgit v1.2.3 From b2cc3c8071bee6e3defa54b701671d310cb94f3c Mon Sep 17 00:00:00 2001 From: John Stultz Date: Tue, 23 May 2017 09:40:26 -0700 Subject: drm: kirin: Fix drm_of_find_panel_or_bridge conversion This fixes a regression introduced by ebc944613567 ("drm: convert drivers to use drm_of_find_panel_or_bridge") that was recently merged, causing HDMI output to not work. For the kirin driver, the port value should be 1 instead of 0, so this oneline patch fixes it and gets graphics working again. Cc: Rob Herring Cc: Archit Taneja Cc: Philipp Zabel Cc: Maxime Ripard Cc: Sean Paul Cc: Dave Airlie Cc: Xinliang Liu Fix-suggested-by: Rob Herring Signed-off-by: John Stultz Reviewed-by: Xinliang Liu Signed-off-by: Sean Paul Link: http://patchwork.freedesktop.org/patch/msgid/1495557626-25285-1-git-send-email-john.stultz@linaro.org --- drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c index 5abc69c9630f..f77dcfaade6c 100644 --- a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c +++ b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c @@ -760,7 +760,7 @@ static int dsi_parse_dt(struct platform_device *pdev, struct dw_dsi *dsi) * Get the endpoint node. In our case, dsi has one output port1 * to which the external HDMI bridge is connected. */ - ret = drm_of_find_panel_or_bridge(np, 0, 0, NULL, &dsi->bridge); + ret = drm_of_find_panel_or_bridge(np, 1, 0, NULL, &dsi->bridge); if (ret) return ret; -- cgit v1.2.3 From f4eb17e1efe538d4da7d574bedb00a8dafcc26b7 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 6 Jun 2017 11:34:06 -0400 Subject: Revert "sit: reload iphdr in ipip6_rcv" This reverts commit b699d0035836f6712917a41e7ae58d84359b8ff9. As per Eric Dumazet, the pskb_may_pull() is a NOP in this particular case, so the 'iph' reload is unnecessary. Signed-off-by: David S. Miller --- net/ipv6/sit.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index af832e7ce80f..61e5902f0687 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -657,7 +657,6 @@ static int ipip6_rcv(struct sk_buff *skb) if (iptunnel_pull_header(skb, 0, htons(ETH_P_IPV6), !net_eq(tunnel->net, dev_net(tunnel->dev)))) goto out; - iph = ip_hdr(skb); err = IP_ECN_decapsulate(iph, skb); if (unlikely(err)) { -- cgit v1.2.3 From dad7a3be4960e5545882a0cd8d7613af22874314 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Tue, 6 Jun 2017 23:21:59 +0800 Subject: blk-mq: pass correct hctx to blk_mq_try_issue_directly When direct issue is done on request picked up from plug list, the hctx need to be updated with the actual hw queue, otherwise wrong hctx is used and may hurt performance, especially when wrong SRCU readlock is acquired/released Reported-by: Bart Van Assche Signed-off-by: Ming Lei Signed-off-by: Jens Axboe --- block/blk-mq.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/block/blk-mq.c b/block/blk-mq.c index 1bcccedcc74f..4ddfa019face 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -1619,9 +1619,12 @@ static blk_qc_t blk_mq_make_request(struct request_queue *q, struct bio *bio) blk_mq_put_ctx(data.ctx); - if (same_queue_rq) + if (same_queue_rq) { + data.hctx = blk_mq_map_queue(q, + same_queue_rq->mq_ctx->cpu); blk_mq_try_issue_directly(data.hctx, same_queue_rq, &cookie); + } } else if (q->nr_hw_queues > 1 && is_sync) { blk_mq_put_ctx(data.ctx); blk_mq_bio_to_request(rq, bio); -- cgit v1.2.3 From d964f04a8fde84d978eff0d96561faa6e8de24de Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Tue, 6 Jun 2017 23:22:00 +0800 Subject: blk-mq: fix direct issue If queue is stopped, we shouldn't dispatch request into driver and hardware, unfortunately the check is removed in bd166ef183c2(blk-mq-sched: add framework for MQ capable IO schedulers). This patch fixes the issue by moving the check back into __blk_mq_try_issue_directly(). This patch fixes request use-after-free[1][2] during canceling requets of NVMe in nvme_dev_disable(), which can be triggered easily during NVMe reset & remove test. [1] oops kernel log when CONFIG_BLK_DEV_INTEGRITY is on [ 103.412969] BUG: unable to handle kernel NULL pointer dereference at 000000000000000a [ 103.412980] IP: bio_integrity_advance+0x48/0xf0 [ 103.412981] PGD 275a88067 [ 103.412981] P4D 275a88067 [ 103.412982] PUD 276c43067 [ 103.412983] PMD 0 [ 103.412984] [ 103.412986] Oops: 0000 [#1] SMP [ 103.412989] Modules linked in: vfat fat intel_rapl sb_edac x86_pkg_temp_thermal intel_powerclamp coretemp kvm_intel kvm irqbypass crct10dif_pclmul crc32_pclmul ghash_clmulni_intel pcbc aesni_intel crypto_simd cryptd ipmi_ssif iTCO_wdt iTCO_vendor_support mxm_wmi glue_helper dcdbas ipmi_si mei_me pcspkr mei sg ipmi_devintf lpc_ich ipmi_msghandler shpchp acpi_power_meter wmi nfsd auth_rpcgss nfs_acl lockd grace sunrpc ip_tables xfs libcrc32c sd_mod mgag200 i2c_algo_bit drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops ttm drm crc32c_intel nvme ahci nvme_core libahci libata tg3 i2c_core megaraid_sas ptp pps_core dm_mirror dm_region_hash dm_log dm_mod [ 103.413035] CPU: 0 PID: 102 Comm: kworker/0:2 Not tainted 4.11.0+ #1 [ 103.413036] Hardware name: Dell Inc. PowerEdge R730xd/072T6D, BIOS 2.2.5 09/06/2016 [ 103.413041] Workqueue: events nvme_remove_dead_ctrl_work [nvme] [ 103.413043] task: ffff9cc8775c8000 task.stack: ffffc033c252c000 [ 103.413045] RIP: 0010:bio_integrity_advance+0x48/0xf0 [ 103.413046] RSP: 0018:ffffc033c252fc10 EFLAGS: 00010202 [ 103.413048] RAX: 0000000000000000 RBX: ffff9cc8720a8cc0 RCX: ffff9cca72958240 [ 103.413049] RDX: ffff9cca72958000 RSI: 0000000000000008 RDI: ffff9cc872537f00 [ 103.413049] RBP: ffffc033c252fc28 R08: 0000000000000000 R09: ffffffffb963a0d5 [ 103.413050] R10: 000000000000063e R11: 0000000000000000 R12: ffff9cc8720a8d18 [ 103.413051] R13: 0000000000001000 R14: ffff9cc872682e00 R15: 00000000fffffffb [ 103.413053] FS: 0000000000000000(0000) GS:ffff9cc877c00000(0000) knlGS:0000000000000000 [ 103.413054] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 103.413055] CR2: 000000000000000a CR3: 0000000276c41000 CR4: 00000000001406f0 [ 103.413056] Call Trace: [ 103.413063] bio_advance+0x2a/0xe0 [ 103.413067] blk_update_request+0x76/0x330 [ 103.413072] blk_mq_end_request+0x1a/0x70 [ 103.413074] blk_mq_dispatch_rq_list+0x370/0x410 [ 103.413076] ? blk_mq_flush_busy_ctxs+0x94/0xe0 [ 103.413080] blk_mq_sched_dispatch_requests+0x173/0x1a0 [ 103.413083] __blk_mq_run_hw_queue+0x8e/0xa0 [ 103.413085] __blk_mq_delay_run_hw_queue+0x9d/0xa0 [ 103.413088] blk_mq_start_hw_queue+0x17/0x20 [ 103.413090] blk_mq_start_hw_queues+0x32/0x50 [ 103.413095] nvme_kill_queues+0x54/0x80 [nvme_core] [ 103.413097] nvme_remove_dead_ctrl_work+0x1f/0x40 [nvme] [ 103.413103] process_one_work+0x149/0x360 [ 103.413105] worker_thread+0x4d/0x3c0 [ 103.413109] kthread+0x109/0x140 [ 103.413111] ? rescuer_thread+0x380/0x380 [ 103.413113] ? kthread_park+0x60/0x60 [ 103.413120] ret_from_fork+0x2c/0x40 [ 103.413121] Code: 08 4c 8b 63 50 48 8b 80 80 00 00 00 48 8b 90 d0 03 00 00 31 c0 48 83 ba 40 02 00 00 00 48 8d 8a 40 02 00 00 48 0f 45 c1 c1 ee 09 <0f> b6 48 0a 0f b6 40 09 41 89 f5 83 e9 09 41 d3 ed 44 0f af e8 [ 103.413145] RIP: bio_integrity_advance+0x48/0xf0 RSP: ffffc033c252fc10 [ 103.413146] CR2: 000000000000000a [ 103.413157] ---[ end trace cd6875d16eb5a11e ]--- [ 103.455368] Kernel panic - not syncing: Fatal exception [ 103.459826] Kernel Offset: 0x37600000 from 0xffffffff81000000 (relocation range: 0xffffffff80000000-0xffffffffbfffffff) [ 103.850916] ---[ end Kernel panic - not syncing: Fatal exception [ 103.857637] sched: Unexpected reschedule of offline CPU#1! [ 103.863762] ------------[ cut here ]------------ [2] kernel hang in blk_mq_freeze_queue_wait() when CONFIG_BLK_DEV_INTEGRITY is off [ 247.129825] INFO: task nvme-test:1772 blocked for more than 120 seconds. [ 247.137311] Not tainted 4.12.0-rc2.upstream+ #4 [ 247.142954] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. [ 247.151704] Call Trace: [ 247.154445] __schedule+0x28a/0x880 [ 247.158341] schedule+0x36/0x80 [ 247.161850] blk_mq_freeze_queue_wait+0x4b/0xb0 [ 247.166913] ? remove_wait_queue+0x60/0x60 [ 247.171485] blk_freeze_queue+0x1a/0x20 [ 247.175770] blk_cleanup_queue+0x7f/0x140 [ 247.180252] nvme_ns_remove+0xa3/0xb0 [nvme_core] [ 247.185503] nvme_remove_namespaces+0x32/0x50 [nvme_core] [ 247.191532] nvme_uninit_ctrl+0x2d/0xa0 [nvme_core] [ 247.196977] nvme_remove+0x70/0x110 [nvme] [ 247.201545] pci_device_remove+0x39/0xc0 [ 247.205927] device_release_driver_internal+0x141/0x200 [ 247.211761] device_release_driver+0x12/0x20 [ 247.216531] pci_stop_bus_device+0x8c/0xa0 [ 247.221104] pci_stop_and_remove_bus_device_locked+0x1a/0x30 [ 247.227420] remove_store+0x7c/0x90 [ 247.231320] dev_attr_store+0x18/0x30 [ 247.235409] sysfs_kf_write+0x3a/0x50 [ 247.239497] kernfs_fop_write+0xff/0x180 [ 247.243867] __vfs_write+0x37/0x160 [ 247.247757] ? selinux_file_permission+0xe5/0x120 [ 247.253011] ? security_file_permission+0x3b/0xc0 [ 247.258260] vfs_write+0xb2/0x1b0 [ 247.261964] ? syscall_trace_enter+0x1d0/0x2b0 [ 247.266924] SyS_write+0x55/0xc0 [ 247.270540] do_syscall_64+0x67/0x150 [ 247.274636] entry_SYSCALL64_slow_path+0x25/0x25 [ 247.279794] RIP: 0033:0x7f5c96740840 [ 247.283785] RSP: 002b:00007ffd00e87ee8 EFLAGS: 00000246 ORIG_RAX: 0000000000000001 [ 247.292238] RAX: ffffffffffffffda RBX: 0000000000000002 RCX: 00007f5c96740840 [ 247.300194] RDX: 0000000000000002 RSI: 00007f5c97060000 RDI: 0000000000000001 [ 247.308159] RBP: 00007f5c97060000 R08: 000000000000000a R09: 00007f5c97059740 [ 247.316123] R10: 0000000000000001 R11: 0000000000000246 R12: 00007f5c96a14400 [ 247.324087] R13: 0000000000000002 R14: 0000000000000001 R15: 0000000000000000 [ 370.016340] INFO: task nvme-test:1772 blocked for more than 120 seconds. Fixes: 12d70958a2e8(blk-mq: don't fail allocating driver tag for stopped hw queue) Cc: stable@vger.kernel.org Signed-off-by: Ming Lei Reviewed-by: Bart Van Assche Signed-off-by: Jens Axboe --- block/blk-mq.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/block/blk-mq.c b/block/blk-mq.c index 4ddfa019face..bb66c96850b1 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -1461,22 +1461,28 @@ static blk_qc_t request_to_qc_t(struct blk_mq_hw_ctx *hctx, struct request *rq) return blk_tag_to_qc_t(rq->internal_tag, hctx->queue_num, true); } -static void __blk_mq_try_issue_directly(struct request *rq, blk_qc_t *cookie, - bool may_sleep) +static void __blk_mq_try_issue_directly(struct blk_mq_hw_ctx *hctx, + struct request *rq, + blk_qc_t *cookie, bool may_sleep) { struct request_queue *q = rq->q; struct blk_mq_queue_data bd = { .rq = rq, .last = true, }; - struct blk_mq_hw_ctx *hctx; blk_qc_t new_cookie; int ret; + bool run_queue = true; + + if (blk_mq_hctx_stopped(hctx)) { + run_queue = false; + goto insert; + } if (q->elevator) goto insert; - if (!blk_mq_get_driver_tag(rq, &hctx, false)) + if (!blk_mq_get_driver_tag(rq, NULL, false)) goto insert; new_cookie = request_to_qc_t(hctx, rq); @@ -1500,7 +1506,7 @@ static void __blk_mq_try_issue_directly(struct request *rq, blk_qc_t *cookie, __blk_mq_requeue_request(rq); insert: - blk_mq_sched_insert_request(rq, false, true, false, may_sleep); + blk_mq_sched_insert_request(rq, false, run_queue, false, may_sleep); } static void blk_mq_try_issue_directly(struct blk_mq_hw_ctx *hctx, @@ -1508,7 +1514,7 @@ static void blk_mq_try_issue_directly(struct blk_mq_hw_ctx *hctx, { if (!(hctx->flags & BLK_MQ_F_BLOCKING)) { rcu_read_lock(); - __blk_mq_try_issue_directly(rq, cookie, false); + __blk_mq_try_issue_directly(hctx, rq, cookie, false); rcu_read_unlock(); } else { unsigned int srcu_idx; @@ -1516,7 +1522,7 @@ static void blk_mq_try_issue_directly(struct blk_mq_hw_ctx *hctx, might_sleep(); srcu_idx = srcu_read_lock(&hctx->queue_rq_srcu); - __blk_mq_try_issue_directly(rq, cookie, true); + __blk_mq_try_issue_directly(hctx, rq, cookie, true); srcu_read_unlock(&hctx->queue_rq_srcu, srcu_idx); } } -- cgit v1.2.3 From 9bd2bbc01d17ddd567cc0f81f77fe1163e497462 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Fri, 2 Jun 2017 20:35:51 -0700 Subject: elevator: fix truncation of icq_cache_name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gcc 7.1 reports the following warning: block/elevator.c: In function ‘elv_register’: block/elevator.c:898:5: warning: ‘snprintf’ output may be truncated before the last format character [-Wformat-truncation=] "%s_io_cq", e->elevator_name); ^~~~~~~~~~ block/elevator.c:897:3: note: ‘snprintf’ output between 7 and 22 bytes into a destination of size 21 snprintf(e->icq_cache_name, sizeof(e->icq_cache_name), ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ "%s_io_cq", e->elevator_name); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The bug is that the name of the icq_cache is 6 characters longer than the elevator name, but only ELV_NAME_MAX + 5 characters were reserved for it --- so in the case of a maximum-length elevator name, the 'q' character in "_io_cq" would be truncated by snprintf(). Fix it by reserving ELV_NAME_MAX + 6 characters instead. Signed-off-by: Eric Biggers Reviewed-by: Bart Van Assche Signed-off-by: Jens Axboe --- include/linux/elevator.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/elevator.h b/include/linux/elevator.h index 9ec5e22846e0..0e306c5a86d6 100644 --- a/include/linux/elevator.h +++ b/include/linux/elevator.h @@ -153,7 +153,7 @@ struct elevator_type #endif /* managed by elevator core */ - char icq_cache_name[ELV_NAME_MAX + 5]; /* elvname + "_io_cq" */ + char icq_cache_name[ELV_NAME_MAX + 6]; /* elvname + "_io_cq" */ struct list_head list; }; -- cgit v1.2.3 From 594238158bf748c285f0a73222cd9b7ccf3c525d Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 5 Jun 2017 10:04:52 +0100 Subject: net: stmmac: ensure jumbo_frm error return is correctly checked for -ve value The current comparison of entry < 0 will never be true since entry is an unsigned integer. Make entry an int to ensure -ve error return values from the call to jumbo_frm are correctly being caught. Detected by CoverityScan, CID#1238760 ("Macro compares unsigned to 0") Signed-off-by: Colin Ian King Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index a74c481401c4..e5515c521d86 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -2947,7 +2947,8 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) int i, csum_insertion = 0, is_jumbo = 0; u32 queue = skb_get_queue_mapping(skb); int nfrags = skb_shinfo(skb)->nr_frags; - unsigned int entry, first_entry; + int entry; + unsigned int first_entry; struct dma_desc *desc, *first; struct stmmac_tx_queue *tx_q; unsigned int enh_desc; -- cgit v1.2.3 From e3ebdb20fddacded2740a333ff66781e0d28b05c Mon Sep 17 00:00:00 2001 From: Richard Haines Date: Mon, 5 Jun 2017 16:44:40 +0100 Subject: net/ipv6: Fix CALIPSO causing GPF with datagram support When using CALIPSO with IPPROTO_UDP it is possible to trigger a GPF as the IP header may have moved. Also update the payload length after adding the CALIPSO option. Signed-off-by: Richard Haines Acked-by: Paul Moore Signed-off-by: Huw Davies Signed-off-by: David S. Miller --- net/ipv6/calipso.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/net/ipv6/calipso.c b/net/ipv6/calipso.c index 37ac9de713c6..8d772fea1dde 100644 --- a/net/ipv6/calipso.c +++ b/net/ipv6/calipso.c @@ -1319,7 +1319,7 @@ static int calipso_skbuff_setattr(struct sk_buff *skb, struct ipv6hdr *ip6_hdr; struct ipv6_opt_hdr *hop; unsigned char buf[CALIPSO_MAX_BUFFER]; - int len_delta, new_end, pad; + int len_delta, new_end, pad, payload; unsigned int start, end; ip6_hdr = ipv6_hdr(skb); @@ -1346,6 +1346,8 @@ static int calipso_skbuff_setattr(struct sk_buff *skb, if (ret_val < 0) return ret_val; + ip6_hdr = ipv6_hdr(skb); /* Reset as skb_cow() may have moved it */ + if (len_delta) { if (len_delta > 0) skb_push(skb, len_delta); @@ -1355,6 +1357,8 @@ static int calipso_skbuff_setattr(struct sk_buff *skb, sizeof(*ip6_hdr) + start); skb_reset_network_header(skb); ip6_hdr = ipv6_hdr(skb); + payload = ntohs(ip6_hdr->payload_len); + ip6_hdr->payload_len = htons(payload + len_delta); } hop = (struct ipv6_opt_hdr *)(ip6_hdr + 1); -- cgit v1.2.3 From 79514ef670e9e575a1fe36922268c439d0f0ca8a Mon Sep 17 00:00:00 2001 From: Eugeniu Rosca Date: Tue, 6 Jun 2017 00:08:10 +0200 Subject: ravb: Fix use-after-free on `ifconfig eth0 down` Commit a47b70ea86bd ("ravb: unmap descriptors when freeing rings") has introduced the issue seen in [1] reproduced on H3ULCB board. Fix this by relocating the RX skb ringbuffer free operation, so that swiotlb page unmapping can be done first. Freeing of aligned TX buffers is not relevant to the issue seen in [1]. Still, reposition TX free calls as well, to have all kfree() operations performed consistently _after_ dma_unmap_*()/dma_free_*(). [1] Console screenshot with the problem reproduced: salvator-x login: root root@salvator-x:~# ifconfig eth0 up Micrel KSZ9031 Gigabit PHY e6800000.ethernet-ffffffff:00: \ attached PHY driver [Micrel KSZ9031 Gigabit PHY] \ (mii_bus:phy_addr=e6800000.ethernet-ffffffff:00, irq=235) IPv6: ADDRCONF(NETDEV_UP): eth0: link is not ready root@salvator-x:~# root@salvator-x:~# ifconfig eth0 down ================================================================== BUG: KASAN: use-after-free in swiotlb_tbl_unmap_single+0xc4/0x35c Write of size 1538 at addr ffff8006d884f780 by task ifconfig/1649 CPU: 0 PID: 1649 Comm: ifconfig Not tainted 4.12.0-rc4-00004-g112eb07287d1 #32 Hardware name: Renesas H3ULCB board based on r8a7795 (DT) Call trace: [] dump_backtrace+0x0/0x3a4 [] show_stack+0x14/0x1c [] dump_stack+0xf8/0x150 [] print_address_description+0x7c/0x330 [] kasan_report+0x2e0/0x2f4 [] check_memory_region+0x20/0x14c [] memcpy+0x48/0x68 [] swiotlb_tbl_unmap_single+0xc4/0x35c [] unmap_single+0x90/0xa4 [] swiotlb_unmap_page+0xc/0x14 [] __swiotlb_unmap_page+0xcc/0xe4 [] ravb_ring_free+0x514/0x870 [] ravb_close+0x288/0x36c [] __dev_close_many+0x14c/0x174 [] __dev_close+0xc8/0x144 [] __dev_change_flags+0xd8/0x194 [] dev_change_flags+0x60/0xb0 [] devinet_ioctl+0x484/0x9d4 [] inet_ioctl+0x190/0x194 [] sock_do_ioctl+0x78/0xa8 [] sock_ioctl+0x110/0x3c4 [] vfs_ioctl+0x90/0xa0 [] do_vfs_ioctl+0x148/0xc38 [] SyS_ioctl+0x44/0x74 [] el0_svc_naked+0x24/0x28 The buggy address belongs to the page: page:ffff7e001b6213c0 count:0 mapcount:0 mapping: (null) index:0x0 flags: 0x4000000000000000() raw: 4000000000000000 0000000000000000 0000000000000000 00000000ffffffff raw: 0000000000000000 ffff7e001b6213e0 0000000000000000 0000000000000000 page dumped because: kasan: bad access detected Memory state around the buggy address: ffff8006d884f680: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ffff8006d884f700: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff >ffff8006d884f780: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ^ ffff8006d884f800: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ffff8006d884f880: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ================================================================== Disabling lock debugging due to kernel taint root@salvator-x:~# Fixes: a47b70ea86bd ("ravb: unmap descriptors when freeing rings") Signed-off-by: Eugeniu Rosca Acked-by: Sergei Shtylyov Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/ravb_main.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c index 3cd7989c007d..784782da3a85 100644 --- a/drivers/net/ethernet/renesas/ravb_main.c +++ b/drivers/net/ethernet/renesas/ravb_main.c @@ -230,18 +230,6 @@ static void ravb_ring_free(struct net_device *ndev, int q) int ring_size; int i; - /* Free RX skb ringbuffer */ - if (priv->rx_skb[q]) { - for (i = 0; i < priv->num_rx_ring[q]; i++) - dev_kfree_skb(priv->rx_skb[q][i]); - } - kfree(priv->rx_skb[q]); - priv->rx_skb[q] = NULL; - - /* Free aligned TX buffers */ - kfree(priv->tx_align[q]); - priv->tx_align[q] = NULL; - if (priv->rx_ring[q]) { for (i = 0; i < priv->num_rx_ring[q]; i++) { struct ravb_ex_rx_desc *desc = &priv->rx_ring[q][i]; @@ -270,6 +258,18 @@ static void ravb_ring_free(struct net_device *ndev, int q) priv->tx_ring[q] = NULL; } + /* Free RX skb ringbuffer */ + if (priv->rx_skb[q]) { + for (i = 0; i < priv->num_rx_ring[q]; i++) + dev_kfree_skb(priv->rx_skb[q][i]); + } + kfree(priv->rx_skb[q]); + priv->rx_skb[q] = NULL; + + /* Free aligned TX buffers */ + kfree(priv->tx_align[q]); + priv->tx_align[q] = NULL; + /* Free TX skb ringbuffer. * SKBs are freed by ravb_tx_free() call above. */ -- cgit v1.2.3 From 1020ce3108cc26fbf09d70550ea2937cb1a211d2 Mon Sep 17 00:00:00 2001 From: Nikolay Aleksandrov Date: Tue, 6 Jun 2017 01:26:24 +0300 Subject: net: bridge: fix a null pointer dereference in br_afspec We might call br_afspec() with p == NULL which is a valid use case if the action is on the bridge device itself, but the bridge tunnel code dereferences the p pointer without checking, so check if p is null first. Reported-by: Gustavo A. R. Silva Fixes: efa5356b0d97 ("bridge: per vlan dst_metadata netlink support") Signed-off-by: Nikolay Aleksandrov Acked-by: Roopa Prabhu Signed-off-by: David S. Miller --- net/bridge/br_netlink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index 574f78824d8a..32bd3ead9ba1 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@ -595,7 +595,7 @@ static int br_afspec(struct net_bridge *br, err = 0; switch (nla_type(attr)) { case IFLA_BRIDGE_VLAN_TUNNEL_INFO: - if (!(p->flags & BR_VLAN_TUNNEL)) + if (!p || !(p->flags & BR_VLAN_TUNNEL)) return -EINVAL; err = br_parse_vlan_tunnel_info(attr, &tinfo_curr); if (err) -- cgit v1.2.3 From d68c1f7fd1b7148dab5fe658321d511998969f2d Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 6 Jun 2017 19:08:33 +0100 Subject: arm64: KVM: Preserve RES1 bits in SCTLR_EL2 __do_hyp_init has the rather bad habit of ignoring RES1 bits and writing them back as zero. On a v8.0-8.2 CPU, this doesn't do anything bad, but may end-up being pretty nasty on future revisions of the architecture. Let's preserve those bits so that we don't have to fix this later on. Cc: stable@vger.kernel.org Signed-off-by: Marc Zyngier Signed-off-by: Christoffer Dall --- arch/arm64/include/asm/sysreg.h | 4 ++++ arch/arm64/kvm/hyp-init.S | 10 ++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h index 15c142ce991c..b4d13d9267ff 100644 --- a/arch/arm64/include/asm/sysreg.h +++ b/arch/arm64/include/asm/sysreg.h @@ -286,6 +286,10 @@ #define SCTLR_ELx_A (1 << 1) #define SCTLR_ELx_M 1 +#define SCTLR_EL2_RES1 ((1 << 4) | (1 << 5) | (1 << 11) | (1 << 16) | \ + (1 << 16) | (1 << 18) | (1 << 22) | (1 << 23) | \ + (1 << 28) | (1 << 29)) + #define SCTLR_ELx_FLAGS (SCTLR_ELx_M | SCTLR_ELx_A | SCTLR_ELx_C | \ SCTLR_ELx_SA | SCTLR_ELx_I) diff --git a/arch/arm64/kvm/hyp-init.S b/arch/arm64/kvm/hyp-init.S index 839425c24b1c..4072d408a4b4 100644 --- a/arch/arm64/kvm/hyp-init.S +++ b/arch/arm64/kvm/hyp-init.S @@ -106,10 +106,12 @@ __do_hyp_init: tlbi alle2 dsb sy - mrs x4, sctlr_el2 - and x4, x4, #SCTLR_ELx_EE // preserve endianness of EL2 - ldr x5, =SCTLR_ELx_FLAGS - orr x4, x4, x5 + /* + * Preserve all the RES1 bits while setting the default flags, + * as well as the EE bit on BE. + */ + ldr x4, =(SCTLR_EL2_RES1 | SCTLR_ELx_FLAGS) +CPU_BE( orr x4, x4, #SCTLR_ELx_EE) msr sctlr_el2, x4 isb -- cgit v1.2.3 From 78fd6dcf11468a5a131b8365580d0c613bcc02cb Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 6 Jun 2017 19:08:34 +0100 Subject: arm64: KVM: Allow unaligned accesses at EL2 We currently have the SCTLR_EL2.A bit set, trapping unaligned accesses at EL2, but we're not really prepared to deal with it. So far, this has been unnoticed, until GCC 7 started emitting those (in particular 64bit writes on a 32bit boundary). Since the rest of the kernel is pretty happy about that, let's follow its example and set SCTLR_EL2.A to zero. Modern CPUs don't really care. Cc: stable@vger.kernel.org Reported-by: Alexander Graf Signed-off-by: Marc Zyngier Signed-off-by: Christoffer Dall --- arch/arm64/kvm/hyp-init.S | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm64/kvm/hyp-init.S b/arch/arm64/kvm/hyp-init.S index 4072d408a4b4..3f9615582377 100644 --- a/arch/arm64/kvm/hyp-init.S +++ b/arch/arm64/kvm/hyp-init.S @@ -108,9 +108,10 @@ __do_hyp_init: /* * Preserve all the RES1 bits while setting the default flags, - * as well as the EE bit on BE. + * as well as the EE bit on BE. Drop the A flag since the compiler + * is allowed to generate unaligned accesses. */ - ldr x4, =(SCTLR_EL2_RES1 | SCTLR_ELx_FLAGS) + ldr x4, =(SCTLR_EL2_RES1 | (SCTLR_ELx_FLAGS & ~SCTLR_ELx_A)) CPU_BE( orr x4, x4, #SCTLR_ELx_EE) msr sctlr_el2, x4 isb -- cgit v1.2.3 From 33b5c38852b29736f3b472dd095c9a18ec22746f Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 6 Jun 2017 19:08:35 +0100 Subject: arm: KVM: Allow unaligned accesses at HYP We currently have the HSCTLR.A bit set, trapping unaligned accesses at HYP, but we're not really prepared to deal with it. Since the rest of the kernel is pretty happy about that, let's follow its example and set HSCTLR.A to zero. Modern CPUs don't really care. Cc: stable@vger.kernel.org Signed-off-by: Marc Zyngier Signed-off-by: Christoffer Dall --- arch/arm/kvm/init.S | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/arch/arm/kvm/init.S b/arch/arm/kvm/init.S index 570ed4a9c261..5386528665b5 100644 --- a/arch/arm/kvm/init.S +++ b/arch/arm/kvm/init.S @@ -104,7 +104,6 @@ __do_hyp_init: @ - Write permission implies XN: disabled @ - Instruction cache: enabled @ - Data/Unified cache: enabled - @ - Memory alignment checks: enabled @ - MMU: enabled (this code must be run from an identity mapping) mrc p15, 4, r0, c1, c0, 0 @ HSCR ldr r2, =HSCTLR_MASK @@ -112,8 +111,8 @@ __do_hyp_init: mrc p15, 0, r1, c1, c0, 0 @ SCTLR ldr r2, =(HSCTLR_EE | HSCTLR_FI | HSCTLR_I | HSCTLR_C) and r1, r1, r2 - ARM( ldr r2, =(HSCTLR_M | HSCTLR_A) ) - THUMB( ldr r2, =(HSCTLR_M | HSCTLR_A | HSCTLR_TE) ) + ARM( ldr r2, =(HSCTLR_M) ) + THUMB( ldr r2, =(HSCTLR_M | HSCTLR_TE) ) orr r1, r1, r2 orr r0, r0, r1 mcr p15, 4, r0, c1, c0, 0 @ HSCR -- cgit v1.2.3 From d220b942a4b6a0640aee78841608f4aa5e8e185e Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Mon, 5 Jun 2017 18:31:16 -0700 Subject: net: ethoc: enable NAPI before poll may be scheduled ethoc_reset enables device interrupts, ethoc_interrupt may schedule a NAPI poll before NAPI is enabled in the ethoc_open, which results in device being unable to send or receive anything until it's closed and reopened. In case the device is flooded with ingress packets it may be unable to recover at all. Move napi_enable above ethoc_reset in the ethoc_open to fix that. Fixes: a1702857724f ("net: Add support for the OpenCores 10/100 Mbps Ethernet MAC.") Signed-off-by: Max Filippov Reviewed-by: Tobias Klauser Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/ethoc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/ethoc.c b/drivers/net/ethernet/ethoc.c index e863ba74d005..8bb0db990c8f 100644 --- a/drivers/net/ethernet/ethoc.c +++ b/drivers/net/ethernet/ethoc.c @@ -739,6 +739,8 @@ static int ethoc_open(struct net_device *dev) if (ret) return ret; + napi_enable(&priv->napi); + ethoc_init_ring(priv, dev->mem_start); ethoc_reset(priv); @@ -754,7 +756,6 @@ static int ethoc_open(struct net_device *dev) priv->old_duplex = -1; phy_start(dev->phydev); - napi_enable(&priv->napi); if (netif_msg_ifup(priv)) { dev_info(&dev->dev, "I/O: %08lx Memory: %08lx-%08lx\n", -- cgit v1.2.3 From 426849e6611f2092553f8d53372ae310818a6292 Mon Sep 17 00:00:00 2001 From: Niklas Cassel Date: Tue, 6 Jun 2017 09:25:00 +0200 Subject: net: stmmac: fix completely hung TX when using TSO stmmac_tso_allocator can fail to set the Last Descriptor bit on a descriptor that actually was the last descriptor. This happens when the buffer of the last descriptor ends up having a size of exactly TSO_MAX_BUFF_SIZE. When the IP eventually reaches the next last descriptor, which actually has the bit set, the DMA will hang. When the DMA hangs, we get a tx timeout, however, since stmmac does not do a complete reset of the IP in stmmac_tx_timeout, we end up in a state with completely hung TX. Signed-off-by: Niklas Cassel Acked-by: Giuseppe Cavallaro Acked-by: Alexandre TORGUE 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 e5515c521d86..dcbe4537ad99 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -2724,7 +2724,7 @@ static void stmmac_tso_allocator(struct stmmac_priv *priv, unsigned int des, priv->hw->desc->prepare_tso_tx_desc(desc, 0, buff_size, 0, 1, - (last_segment) && (buff_size < TSO_MAX_BUFF_SIZE), + (last_segment) && (tmp_len <= TSO_MAX_BUFF_SIZE), 0, 0); tmp_len -= TSO_MAX_BUFF_SIZE; -- cgit v1.2.3 From 1d3028f4c16487d63861ab6c68451768a7a109df Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 6 Jun 2017 14:10:49 +0100 Subject: net: stmmac: fix a broken u32 less than zero check The check that queue is less or equal to zero is always true because queue is a u32; queue is decremented and will wrap around and never go -ve. Fix this by making queue an int. Detected by CoverityScan, CID#1428988 ("Unsigned compared against 0") Signed-off-by: Colin Ian King 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 dcbe4537ad99..12236daf7bb6 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1208,7 +1208,7 @@ static int init_dma_rx_desc_rings(struct net_device *dev, gfp_t flags) u32 rx_count = priv->plat->rx_queues_to_use; unsigned int bfsize = 0; int ret = -ENOMEM; - u32 queue; + int queue; int i; if (priv->hw->mode->set_16kib_bfsize) -- cgit v1.2.3 From c79a13734d104b5b147d7cb0870276ccdd660dae Mon Sep 17 00:00:00 2001 From: Jane Chu Date: Tue, 6 Jun 2017 14:32:29 -0600 Subject: arch/sparc: support NR_CPUS = 4096 Linux SPARC64 limits NR_CPUS to 4064 because init_cpu_send_mondo_info() only allocates a single page for NR_CPUS mondo entries. Thus we cannot use all 4096 CPUs on some SPARC platforms. To fix, allocate (2^order) pages where order is set according to the size of cpu_list for possible cpus. Since cpu_list_pa and cpu_mondo_block_pa are not used in asm code, there are no imm13 offsets from the base PA that will break because they can only reach one page. Orabug: 25505750 Signed-off-by: Jane Chu Reviewed-by: Bob Picco Reviewed-by: Atish Patra Signed-off-by: David S. Miller --- arch/sparc/Kconfig | 4 ++-- arch/sparc/kernel/irq_64.c | 17 +++++++++++++---- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index e544ac12737e..b558c9e29de3 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -192,9 +192,9 @@ config NR_CPUS int "Maximum number of CPUs" depends on SMP range 2 32 if SPARC32 - range 2 1024 if SPARC64 + range 2 4096 if SPARC64 default 32 if SPARC32 - default 64 if SPARC64 + default 4096 if SPARC64 source kernel/Kconfig.hz diff --git a/arch/sparc/kernel/irq_64.c b/arch/sparc/kernel/irq_64.c index 4d0248aa0928..99dd133a029f 100644 --- a/arch/sparc/kernel/irq_64.c +++ b/arch/sparc/kernel/irq_64.c @@ -1034,17 +1034,26 @@ static void __init init_cpu_send_mondo_info(struct trap_per_cpu *tb) { #ifdef CONFIG_SMP unsigned long page; + void *mondo, *p; - BUILD_BUG_ON((NR_CPUS * sizeof(u16)) > (PAGE_SIZE - 64)); + BUILD_BUG_ON((NR_CPUS * sizeof(u16)) > PAGE_SIZE); + + /* Make sure mondo block is 64byte aligned */ + p = kzalloc(127, GFP_KERNEL); + if (!p) { + prom_printf("SUN4V: Error, cannot allocate mondo block.\n"); + prom_halt(); + } + mondo = (void *)(((unsigned long)p + 63) & ~0x3f); + tb->cpu_mondo_block_pa = __pa(mondo); page = get_zeroed_page(GFP_KERNEL); if (!page) { - prom_printf("SUN4V: Error, cannot allocate cpu mondo page.\n"); + prom_printf("SUN4V: Error, cannot allocate cpu list page.\n"); prom_halt(); } - tb->cpu_mondo_block_pa = __pa(page); - tb->cpu_list_pa = __pa(page + 64); + tb->cpu_list_pa = __pa(page); #endif } -- cgit v1.2.3 From 654f4807624a657f364417c2a7454f0df9961734 Mon Sep 17 00:00:00 2001 From: Mike Kravetz Date: Fri, 2 Jun 2017 14:51:12 -0700 Subject: sparc64: mm: fix copy_tsb to correctly copy huge page TSBs When a TSB grows beyond its current capacity, a new TSB is allocated and copy_tsb is called to copy entries from the old TSB to the new. A hash shift based on page size is used to calculate the index of an entry in the TSB. copy_tsb has hard coded PAGE_SHIFT in these calculations. However, for huge page TSBs the value REAL_HPAGE_SHIFT should be used. As a result, when copy_tsb is called for a huge page TSB the entries are placed at the incorrect index in the newly allocated TSB. When doing hardware table walk, the MMU does not match these entries and we end up in the TSB miss handling code. This code will then create and write an entry to the correct index in the TSB. We take a performance hit for the table walk miss and recreation of these entries. Pass a new parameter to copy_tsb that is the page size shift to be used when copying the TSB. Suggested-by: Anthony Yznaga Signed-off-by: Mike Kravetz Signed-off-by: David S. Miller --- arch/sparc/kernel/tsb.S | 11 +++++++---- arch/sparc/mm/tsb.c | 7 +++++-- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/arch/sparc/kernel/tsb.S b/arch/sparc/kernel/tsb.S index 10689cfd0ad4..07c0df924960 100644 --- a/arch/sparc/kernel/tsb.S +++ b/arch/sparc/kernel/tsb.S @@ -455,13 +455,16 @@ __tsb_context_switch: .type copy_tsb,#function copy_tsb: /* %o0=old_tsb_base, %o1=old_tsb_size * %o2=new_tsb_base, %o3=new_tsb_size + * %o4=page_size_shift */ sethi %uhi(TSB_PASS_BITS), %g7 srlx %o3, 4, %o3 - add %o0, %o1, %g1 /* end of old tsb */ + add %o0, %o1, %o1 /* end of old tsb */ sllx %g7, 32, %g7 sub %o3, 1, %o3 /* %o3 == new tsb hash mask */ + mov %o4, %g1 /* page_size_shift */ + 661: prefetcha [%o0] ASI_N, #one_read .section .tsb_phys_patch, "ax" .word 661b @@ -486,9 +489,9 @@ copy_tsb: /* %o0=old_tsb_base, %o1=old_tsb_size /* This can definitely be computed faster... */ srlx %o0, 4, %o5 /* Build index */ and %o5, 511, %o5 /* Mask index */ - sllx %o5, PAGE_SHIFT, %o5 /* Put into vaddr position */ + sllx %o5, %g1, %o5 /* Put into vaddr position */ or %o4, %o5, %o4 /* Full VADDR. */ - srlx %o4, PAGE_SHIFT, %o4 /* Shift down to create index */ + srlx %o4, %g1, %o4 /* Shift down to create index */ and %o4, %o3, %o4 /* Mask with new_tsb_nents-1 */ sllx %o4, 4, %o4 /* Shift back up into tsb ent offset */ TSB_STORE(%o2 + %o4, %g2) /* Store TAG */ @@ -496,7 +499,7 @@ copy_tsb: /* %o0=old_tsb_base, %o1=old_tsb_size TSB_STORE(%o2 + %o4, %g3) /* Store TTE */ 80: add %o0, 16, %o0 - cmp %o0, %g1 + cmp %o0, %o1 bne,pt %xcc, 90b nop diff --git a/arch/sparc/mm/tsb.c b/arch/sparc/mm/tsb.c index bedf08b22a47..0d4b998c7d7b 100644 --- a/arch/sparc/mm/tsb.c +++ b/arch/sparc/mm/tsb.c @@ -496,7 +496,8 @@ retry_tsb_alloc: extern void copy_tsb(unsigned long old_tsb_base, unsigned long old_tsb_size, unsigned long new_tsb_base, - unsigned long new_tsb_size); + unsigned long new_tsb_size, + unsigned long page_size_shift); unsigned long old_tsb_base = (unsigned long) old_tsb; unsigned long new_tsb_base = (unsigned long) new_tsb; @@ -504,7 +505,9 @@ retry_tsb_alloc: old_tsb_base = __pa(old_tsb_base); new_tsb_base = __pa(new_tsb_base); } - copy_tsb(old_tsb_base, old_size, new_tsb_base, new_size); + copy_tsb(old_tsb_base, old_size, new_tsb_base, new_size, + tsb_index == MM_TSB_BASE ? + PAGE_SHIFT : REAL_HPAGE_SHIFT); } mm->context.tsb_block[tsb_index].tsb = new_tsb; -- cgit v1.2.3 From c982aa9c304bf0b9a7522fd118fed4afa5a0263c Mon Sep 17 00:00:00 2001 From: James Clarke Date: Mon, 29 May 2017 20:17:56 +0100 Subject: sparc: Machine description indices can vary VIO devices were being looked up by their index in the machine description node block, but this often varies over time as devices are added and removed. Instead, store the ID and look up using the type, config handle and ID. Signed-off-by: James Clarke Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=112541 Signed-off-by: David S. Miller --- arch/sparc/include/asm/vio.h | 1 + arch/sparc/kernel/vio.c | 68 +++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 65 insertions(+), 4 deletions(-) diff --git a/arch/sparc/include/asm/vio.h b/arch/sparc/include/asm/vio.h index 8174f6cdbbbb..9dca7a892978 100644 --- a/arch/sparc/include/asm/vio.h +++ b/arch/sparc/include/asm/vio.h @@ -327,6 +327,7 @@ struct vio_dev { int compat_len; u64 dev_no; + u64 id; unsigned long channel_id; diff --git a/arch/sparc/kernel/vio.c b/arch/sparc/kernel/vio.c index f6bb857254fc..075d38980dee 100644 --- a/arch/sparc/kernel/vio.c +++ b/arch/sparc/kernel/vio.c @@ -302,13 +302,16 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, if (!id) { dev_set_name(&vdev->dev, "%s", bus_id_name); vdev->dev_no = ~(u64)0; + vdev->id = ~(u64)0; } else if (!cfg_handle) { dev_set_name(&vdev->dev, "%s-%llu", bus_id_name, *id); vdev->dev_no = *id; + vdev->id = ~(u64)0; } else { dev_set_name(&vdev->dev, "%s-%llu-%llu", bus_id_name, *cfg_handle, *id); vdev->dev_no = *cfg_handle; + vdev->id = *id; } vdev->dev.parent = parent; @@ -351,27 +354,84 @@ static void vio_add(struct mdesc_handle *hp, u64 node) (void) vio_create_one(hp, node, &root_vdev->dev); } +struct vio_md_node_query { + const char *type; + u64 dev_no; + u64 id; +}; + static int vio_md_node_match(struct device *dev, void *arg) { + struct vio_md_node_query *query = (struct vio_md_node_query *) arg; struct vio_dev *vdev = to_vio_dev(dev); - if (vdev->mp == (u64) arg) - return 1; + if (vdev->dev_no != query->dev_no) + return 0; + if (vdev->id != query->id) + return 0; + if (strcmp(vdev->type, query->type)) + return 0; - return 0; + return 1; } static void vio_remove(struct mdesc_handle *hp, u64 node) { + const char *type; + const u64 *id, *cfg_handle; + u64 a; + struct vio_md_node_query query; struct device *dev; - dev = device_find_child(&root_vdev->dev, (void *) node, + type = mdesc_get_property(hp, node, "device-type", NULL); + if (!type) { + type = mdesc_get_property(hp, node, "name", NULL); + if (!type) + type = mdesc_node_name(hp, node); + } + + query.type = type; + + id = mdesc_get_property(hp, node, "id", NULL); + cfg_handle = NULL; + mdesc_for_each_arc(a, hp, node, MDESC_ARC_TYPE_BACK) { + u64 target; + + target = mdesc_arc_target(hp, a); + cfg_handle = mdesc_get_property(hp, target, + "cfg-handle", NULL); + if (cfg_handle) + break; + } + + if (!id) { + query.dev_no = ~(u64)0; + query.id = ~(u64)0; + } else if (!cfg_handle) { + query.dev_no = *id; + query.id = ~(u64)0; + } else { + query.dev_no = *cfg_handle; + query.id = *id; + } + + dev = device_find_child(&root_vdev->dev, &query, vio_md_node_match); if (dev) { printk(KERN_INFO "VIO: Removing device %s\n", dev_name(dev)); device_unregister(dev); put_device(dev); + } else { + if (!id) + printk(KERN_ERR "VIO: Removed unknown %s node.\n", + type); + else if (!cfg_handle) + printk(KERN_ERR "VIO: Removed unknown %s node %llu.\n", + type, *id); + else + printk(KERN_ERR "VIO: Removed unknown %s node %llu-%llu.\n", + type, *cfg_handle, *id); } } -- cgit v1.2.3 From f322980b74a15e08f8c70a34a5864ecdbf957251 Mon Sep 17 00:00:00 2001 From: "Liam R. Howlett" Date: Tue, 30 May 2017 15:45:00 -0400 Subject: sparc/mm/hugepages: Fix setup_hugepagesz for invalid values. hugetlb_bad_size needs to be called on invalid values. Also change the pr_warn to a pr_err to better align with other platforms. Signed-off-by: Liam R. Howlett Signed-off-by: David S. Miller --- arch/sparc/mm/init_64.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c index 0cda653ae007..7ca1b9dc7d64 100644 --- a/arch/sparc/mm/init_64.c +++ b/arch/sparc/mm/init_64.c @@ -358,7 +358,8 @@ static int __init setup_hugepagesz(char *string) } if ((hv_pgsz_mask & cpu_pgsz_mask) == 0U) { - pr_warn("hugepagesz=%llu not supported by MMU.\n", + hugetlb_bad_size(); + pr_err("hugepagesz=%llu not supported by MMU.\n", hugepage_size); goto out; } -- cgit v1.2.3 From 588974857359861891f478a070b1dc7ae04a3880 Mon Sep 17 00:00:00 2001 From: Pavel Tatashin Date: Wed, 31 May 2017 11:25:20 -0400 Subject: sparc64: reset mm cpumask after wrap After a wrap (getting a new context version) a process must get a new context id, which means that we would need to flush the context id from the TLB before running for the first time with this ID on every CPU. But, we use mm_cpumask to determine if this process has been running on this CPU before, and this mask is not reset after a wrap. So, there are two possible fixes for this issue: 1. Clear mm cpumask whenever mm gets a new context id 2. Unconditionally flush context every time process is running on a CPU This patch implements the first solution Signed-off-by: Pavel Tatashin Reviewed-by: Bob Picco Reviewed-by: Steven Sistare Signed-off-by: David S. Miller --- arch/sparc/mm/init_64.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c index 7ca1b9dc7d64..f8e30a3906be 100644 --- a/arch/sparc/mm/init_64.c +++ b/arch/sparc/mm/init_64.c @@ -759,6 +759,8 @@ void get_new_mmu_context(struct mm_struct *mm) goto out; } } + if (mm->context.sparc64_ctx_val) + cpumask_clear(mm_cpumask(mm)); mmu_context_bmap[new_ctx>>6] |= (1UL << (new_ctx & 63)); new_ctx |= (tlb_context_cache & CTX_VERSION_MASK); out: -- cgit v1.2.3 From 14d0334c6748ff2aedb3f2f7fdc51ee90a9b54e7 Mon Sep 17 00:00:00 2001 From: Pavel Tatashin Date: Wed, 31 May 2017 11:25:21 -0400 Subject: sparc64: combine activate_mm and switch_mm The only difference between these two functions is that in activate_mm we unconditionally flush context. However, there is no need to keep this difference after fixing a bug where cpumask was not reset on a wrap. So, in this patch we combine these. Signed-off-by: Pavel Tatashin Reviewed-by: Bob Picco Reviewed-by: Steven Sistare Signed-off-by: David S. Miller --- arch/sparc/include/asm/mmu_context_64.h | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/arch/sparc/include/asm/mmu_context_64.h b/arch/sparc/include/asm/mmu_context_64.h index 22fede6eba11..734a1343d77d 100644 --- a/arch/sparc/include/asm/mmu_context_64.h +++ b/arch/sparc/include/asm/mmu_context_64.h @@ -133,26 +133,7 @@ static inline void switch_mm(struct mm_struct *old_mm, struct mm_struct *mm, str } #define deactivate_mm(tsk,mm) do { } while (0) - -/* Activate a new MM instance for the current task. */ -static inline void activate_mm(struct mm_struct *active_mm, struct mm_struct *mm) -{ - unsigned long flags; - int cpu; - - spin_lock_irqsave(&mm->context.lock, flags); - if (!CTX_VALID(mm->context)) - get_new_mmu_context(mm); - cpu = smp_processor_id(); - if (!cpumask_test_cpu(cpu, mm_cpumask(mm))) - cpumask_set_cpu(cpu, mm_cpumask(mm)); - - load_secondary_context(mm); - __flush_tlb_mm(CTX_HWBITS(mm->context), SECONDARY_CONTEXT); - tsb_context_switch(mm); - spin_unlock_irqrestore(&mm->context.lock, flags); -} - +#define activate_mm(active_mm, mm) switch_mm(active_mm, mm, NULL) #endif /* !(__ASSEMBLY__) */ #endif /* !(__SPARC64_MMU_CONTEXT_H) */ -- cgit v1.2.3 From c4415235b2be0cc791572e8e7f7466ab8f73a2bf Mon Sep 17 00:00:00 2001 From: Pavel Tatashin Date: Wed, 31 May 2017 11:25:22 -0400 Subject: sparc64: redefine first version CTX_FIRST_VERSION defines the first context version, but also it defines first context. This patch redefines it to only include the first context version. Signed-off-by: Pavel Tatashin Reviewed-by: Bob Picco Reviewed-by: Steven Sistare Signed-off-by: David S. Miller --- arch/sparc/include/asm/mmu_64.h | 2 +- arch/sparc/mm/init_64.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/sparc/include/asm/mmu_64.h b/arch/sparc/include/asm/mmu_64.h index f7de0dbc38af..83b36a5371ff 100644 --- a/arch/sparc/include/asm/mmu_64.h +++ b/arch/sparc/include/asm/mmu_64.h @@ -52,7 +52,7 @@ #define CTX_NR_MASK TAG_CONTEXT_BITS #define CTX_HW_MASK (CTX_NR_MASK | CTX_PGSZ_MASK) -#define CTX_FIRST_VERSION ((_AC(1,UL) << CTX_VERSION_SHIFT) + _AC(1,UL)) +#define CTX_FIRST_VERSION BIT(CTX_VERSION_SHIFT) #define CTX_VALID(__ctx) \ (!(((__ctx.sparc64_ctx_val) ^ tlb_context_cache) & CTX_VERSION_MASK)) #define CTX_HWBITS(__ctx) ((__ctx.sparc64_ctx_val) & CTX_HW_MASK) diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c index f8e30a3906be..63b50447bb62 100644 --- a/arch/sparc/mm/init_64.c +++ b/arch/sparc/mm/init_64.c @@ -707,7 +707,7 @@ EXPORT_SYMBOL(__flush_dcache_range); /* get_new_mmu_context() uses "cache + 1". */ DEFINE_SPINLOCK(ctx_alloc_lock); -unsigned long tlb_context_cache = CTX_FIRST_VERSION - 1; +unsigned long tlb_context_cache = CTX_FIRST_VERSION; #define MAX_CTX_NR (1UL << CTX_NR_BITS) #define CTX_BMAP_SLOTS BITS_TO_LONGS(MAX_CTX_NR) DECLARE_BITMAP(mmu_context_bmap, MAX_CTX_NR); @@ -738,9 +738,9 @@ void get_new_mmu_context(struct mm_struct *mm) if (new_ctx >= ctx) { int i; new_ctx = (tlb_context_cache & CTX_VERSION_MASK) + - CTX_FIRST_VERSION; + CTX_FIRST_VERSION + 1; if (new_ctx == 1) - new_ctx = CTX_FIRST_VERSION; + new_ctx = CTX_FIRST_VERSION + 1; /* Don't call memset, for 16 entries that's just * plain silly... -- cgit v1.2.3 From 7a5b4bbf49fe86ce77488a70c5dccfe2d50d7a2d Mon Sep 17 00:00:00 2001 From: Pavel Tatashin Date: Wed, 31 May 2017 11:25:23 -0400 Subject: sparc64: add per-cpu mm of secondary contexts The new wrap is going to use information from this array to figure out mm's that currently have valid secondary contexts setup. Signed-off-by: Pavel Tatashin Reviewed-by: Bob Picco Reviewed-by: Steven Sistare Signed-off-by: David S. Miller --- arch/sparc/include/asm/mmu_context_64.h | 5 +++-- arch/sparc/mm/init_64.c | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/sparc/include/asm/mmu_context_64.h b/arch/sparc/include/asm/mmu_context_64.h index 734a1343d77d..edb45247bfa9 100644 --- a/arch/sparc/include/asm/mmu_context_64.h +++ b/arch/sparc/include/asm/mmu_context_64.h @@ -19,6 +19,7 @@ extern spinlock_t ctx_alloc_lock; extern unsigned long tlb_context_cache; extern unsigned long mmu_context_bmap[]; +DECLARE_PER_CPU(struct mm_struct *, per_cpu_secondary_mm); void get_new_mmu_context(struct mm_struct *mm); #ifdef CONFIG_SMP void smp_new_mmu_context_version(void); @@ -76,8 +77,9 @@ void __flush_tlb_mm(unsigned long, unsigned long); static inline void switch_mm(struct mm_struct *old_mm, struct mm_struct *mm, struct task_struct *tsk) { unsigned long ctx_valid, flags; - int cpu; + int cpu = smp_processor_id(); + per_cpu(per_cpu_secondary_mm, cpu) = mm; if (unlikely(mm == &init_mm)) return; @@ -123,7 +125,6 @@ static inline void switch_mm(struct mm_struct *old_mm, struct mm_struct *mm, str * for the first time, we must flush that context out of the * local TLB. */ - cpu = smp_processor_id(); if (!ctx_valid || !cpumask_test_cpu(cpu, mm_cpumask(mm))) { cpumask_set_cpu(cpu, mm_cpumask(mm)); __flush_tlb_mm(CTX_HWBITS(mm->context), diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c index 63b50447bb62..a4c0bc8af820 100644 --- a/arch/sparc/mm/init_64.c +++ b/arch/sparc/mm/init_64.c @@ -711,6 +711,7 @@ unsigned long tlb_context_cache = CTX_FIRST_VERSION; #define MAX_CTX_NR (1UL << CTX_NR_BITS) #define CTX_BMAP_SLOTS BITS_TO_LONGS(MAX_CTX_NR) DECLARE_BITMAP(mmu_context_bmap, MAX_CTX_NR); +DEFINE_PER_CPU(struct mm_struct *, per_cpu_secondary_mm) = {0}; /* Caller does TLB context flushing on local CPU if necessary. * The caller also ensures that CTX_VALID(mm->context) is false. -- cgit v1.2.3 From a0582f26ec9dfd5360ea2f35dd9a1b026f8adda0 Mon Sep 17 00:00:00 2001 From: Pavel Tatashin Date: Wed, 31 May 2017 11:25:24 -0400 Subject: sparc64: new context wrap The current wrap implementation has a race issue: it is called outside of the ctx_alloc_lock, and also does not wait for all CPUs to complete the wrap. This means that a thread can get a new context with a new version and another thread might still be running with the same context. The problem is especially severe on CPUs with shared TLBs, like sun4v. I used the following test to very quickly reproduce the problem: - start over 8K processes (must be more than context IDs) - write and read values at a memory location in every process. Very quickly memory corruptions start happening, and what we read back does not equal what we wrote. Several approaches were explored before settling on this one: Approach 1: Move smp_new_mmu_context_version() inside ctx_alloc_lock, and wait for every process to complete the wrap. (Note: every CPU must WAIT before leaving smp_new_mmu_context_version_client() until every one arrives). This approach ends up with deadlocks, as some threads own locks which other threads are waiting for, and they never receive softint until these threads exit smp_new_mmu_context_version_client(). Since we do not allow the exit, deadlock happens. Approach 2: Handle wrap right during mondo interrupt. Use etrap/rtrap to enter into into C code, and issue new versions to every CPU. This approach adds some overhead to runtime: in switch_mm() we must add some checks to make sure that versions have not changed due to wrap while we were loading the new secondary context. (could be protected by PSTATE_IE but that degrades performance as on M7 and older CPUs as it takes 50 cycles for each access). Also, we still need a global per-cpu array of MMs to know where we need to load new contexts, otherwise we can change context to a thread that is going way (if we received mondo between switch_mm() and switch_to() time). Finally, there are some issues with window registers in rtrap() when context IDs are changed during CPU mondo time. The approach in this patch is the simplest and has almost no impact on runtime. We use the array with mm's where last secondary contexts were loaded onto CPUs and bump their versions to the new generation without changing context IDs. If a new process comes in to get a context ID, it will go through get_new_mmu_context() because of version mismatch. But the running processes do not need to be interrupted. And wrap is quicker as we do not need to xcall and wait for everyone to receive and complete wrap. Signed-off-by: Pavel Tatashin Reviewed-by: Bob Picco Reviewed-by: Steven Sistare Signed-off-by: David S. Miller --- arch/sparc/mm/init_64.c | 81 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 54 insertions(+), 27 deletions(-) diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c index a4c0bc8af820..3c40ebd50f92 100644 --- a/arch/sparc/mm/init_64.c +++ b/arch/sparc/mm/init_64.c @@ -713,6 +713,53 @@ unsigned long tlb_context_cache = CTX_FIRST_VERSION; DECLARE_BITMAP(mmu_context_bmap, MAX_CTX_NR); DEFINE_PER_CPU(struct mm_struct *, per_cpu_secondary_mm) = {0}; +static void mmu_context_wrap(void) +{ + unsigned long old_ver = tlb_context_cache & CTX_VERSION_MASK; + unsigned long new_ver, new_ctx, old_ctx; + struct mm_struct *mm; + int cpu; + + bitmap_zero(mmu_context_bmap, 1 << CTX_NR_BITS); + + /* Reserve kernel context */ + set_bit(0, mmu_context_bmap); + + new_ver = (tlb_context_cache & CTX_VERSION_MASK) + CTX_FIRST_VERSION; + if (unlikely(new_ver == 0)) + new_ver = CTX_FIRST_VERSION; + tlb_context_cache = new_ver; + + /* + * Make sure that any new mm that are added into per_cpu_secondary_mm, + * are going to go through get_new_mmu_context() path. + */ + mb(); + + /* + * Updated versions to current on those CPUs that had valid secondary + * contexts + */ + for_each_online_cpu(cpu) { + /* + * If a new mm is stored after we took this mm from the array, + * it will go into get_new_mmu_context() path, because we + * already bumped the version in tlb_context_cache. + */ + mm = per_cpu(per_cpu_secondary_mm, cpu); + + if (unlikely(!mm || mm == &init_mm)) + continue; + + old_ctx = mm->context.sparc64_ctx_val; + if (likely((old_ctx & CTX_VERSION_MASK) == old_ver)) { + new_ctx = (old_ctx & ~CTX_VERSION_MASK) | new_ver; + set_bit(new_ctx & CTX_NR_MASK, mmu_context_bmap); + mm->context.sparc64_ctx_val = new_ctx; + } + } +} + /* Caller does TLB context flushing on local CPU if necessary. * The caller also ensures that CTX_VALID(mm->context) is false. * @@ -727,50 +774,30 @@ void get_new_mmu_context(struct mm_struct *mm) { unsigned long ctx, new_ctx; unsigned long orig_pgsz_bits; - int new_version; spin_lock(&ctx_alloc_lock); +retry: + /* wrap might have happened, test again if our context became valid */ + if (unlikely(CTX_VALID(mm->context))) + goto out; orig_pgsz_bits = (mm->context.sparc64_ctx_val & CTX_PGSZ_MASK); ctx = (tlb_context_cache + 1) & CTX_NR_MASK; new_ctx = find_next_zero_bit(mmu_context_bmap, 1 << CTX_NR_BITS, ctx); - new_version = 0; if (new_ctx >= (1 << CTX_NR_BITS)) { new_ctx = find_next_zero_bit(mmu_context_bmap, ctx, 1); if (new_ctx >= ctx) { - int i; - new_ctx = (tlb_context_cache & CTX_VERSION_MASK) + - CTX_FIRST_VERSION + 1; - if (new_ctx == 1) - new_ctx = CTX_FIRST_VERSION + 1; - - /* Don't call memset, for 16 entries that's just - * plain silly... - */ - mmu_context_bmap[0] = 3; - mmu_context_bmap[1] = 0; - mmu_context_bmap[2] = 0; - mmu_context_bmap[3] = 0; - for (i = 4; i < CTX_BMAP_SLOTS; i += 4) { - mmu_context_bmap[i + 0] = 0; - mmu_context_bmap[i + 1] = 0; - mmu_context_bmap[i + 2] = 0; - mmu_context_bmap[i + 3] = 0; - } - new_version = 1; - goto out; + mmu_context_wrap(); + goto retry; } } if (mm->context.sparc64_ctx_val) cpumask_clear(mm_cpumask(mm)); mmu_context_bmap[new_ctx>>6] |= (1UL << (new_ctx & 63)); new_ctx |= (tlb_context_cache & CTX_VERSION_MASK); -out: tlb_context_cache = new_ctx; mm->context.sparc64_ctx_val = new_ctx | orig_pgsz_bits; +out: spin_unlock(&ctx_alloc_lock); - - if (unlikely(new_version)) - smp_new_mmu_context_version(); } static int numa_enabled = 1; -- cgit v1.2.3 From 0197e41ce70511dc3b71f7fefa1a676e2b5cd60b Mon Sep 17 00:00:00 2001 From: Pavel Tatashin Date: Wed, 31 May 2017 11:25:25 -0400 Subject: sparc64: delete old wrap code The old method that is using xcall and softint to get new context id is deleted, as it is replaced by a method of using per_cpu_secondary_mm without xcall to perform the context wrap. Signed-off-by: Pavel Tatashin Reviewed-by: Bob Picco Reviewed-by: Steven Sistare Signed-off-by: David S. Miller --- arch/sparc/include/asm/mmu_context_64.h | 6 ------ arch/sparc/include/asm/pil.h | 1 - arch/sparc/kernel/kernel.h | 1 - arch/sparc/kernel/smp_64.c | 31 ------------------------------- arch/sparc/kernel/ttable_64.S | 2 +- arch/sparc/mm/ultra.S | 5 ----- 6 files changed, 1 insertion(+), 45 deletions(-) diff --git a/arch/sparc/include/asm/mmu_context_64.h b/arch/sparc/include/asm/mmu_context_64.h index edb45247bfa9..2cddcda4f85f 100644 --- a/arch/sparc/include/asm/mmu_context_64.h +++ b/arch/sparc/include/asm/mmu_context_64.h @@ -21,12 +21,6 @@ extern unsigned long mmu_context_bmap[]; DECLARE_PER_CPU(struct mm_struct *, per_cpu_secondary_mm); void get_new_mmu_context(struct mm_struct *mm); -#ifdef CONFIG_SMP -void smp_new_mmu_context_version(void); -#else -#define smp_new_mmu_context_version() do { } while (0) -#endif - int init_new_context(struct task_struct *tsk, struct mm_struct *mm); void destroy_context(struct mm_struct *mm); diff --git a/arch/sparc/include/asm/pil.h b/arch/sparc/include/asm/pil.h index 266937030546..522b43db2ed3 100644 --- a/arch/sparc/include/asm/pil.h +++ b/arch/sparc/include/asm/pil.h @@ -20,7 +20,6 @@ #define PIL_SMP_CALL_FUNC 1 #define PIL_SMP_RECEIVE_SIGNAL 2 #define PIL_SMP_CAPTURE 3 -#define PIL_SMP_CTX_NEW_VERSION 4 #define PIL_DEVICE_IRQ 5 #define PIL_SMP_CALL_FUNC_SNGL 6 #define PIL_DEFERRED_PCR_WORK 7 diff --git a/arch/sparc/kernel/kernel.h b/arch/sparc/kernel/kernel.h index c9804551262c..6ae1e77be0bf 100644 --- a/arch/sparc/kernel/kernel.h +++ b/arch/sparc/kernel/kernel.h @@ -37,7 +37,6 @@ void handle_stdfmna(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr /* smp_64.c */ void __irq_entry smp_call_function_client(int irq, struct pt_regs *regs); void __irq_entry smp_call_function_single_client(int irq, struct pt_regs *regs); -void __irq_entry smp_new_mmu_context_version_client(int irq, struct pt_regs *regs); void __irq_entry smp_penguin_jailcell(int irq, struct pt_regs *regs); void __irq_entry smp_receive_signal_client(int irq, struct pt_regs *regs); diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c index b3bc0ac757cc..fdf31040a7dc 100644 --- a/arch/sparc/kernel/smp_64.c +++ b/arch/sparc/kernel/smp_64.c @@ -964,37 +964,6 @@ void flush_dcache_page_all(struct mm_struct *mm, struct page *page) preempt_enable(); } -void __irq_entry smp_new_mmu_context_version_client(int irq, struct pt_regs *regs) -{ - struct mm_struct *mm; - unsigned long flags; - - clear_softint(1 << irq); - - /* See if we need to allocate a new TLB context because - * the version of the one we are using is now out of date. - */ - mm = current->active_mm; - if (unlikely(!mm || (mm == &init_mm))) - return; - - spin_lock_irqsave(&mm->context.lock, flags); - - if (unlikely(!CTX_VALID(mm->context))) - get_new_mmu_context(mm); - - spin_unlock_irqrestore(&mm->context.lock, flags); - - load_secondary_context(mm); - __flush_tlb_mm(CTX_HWBITS(mm->context), - SECONDARY_CONTEXT); -} - -void smp_new_mmu_context_version(void) -{ - smp_cross_call(&xcall_new_mmu_context_version, 0, 0, 0); -} - #ifdef CONFIG_KGDB void kgdb_roundup_cpus(unsigned long flags) { diff --git a/arch/sparc/kernel/ttable_64.S b/arch/sparc/kernel/ttable_64.S index 7bd8f6556352..efe93ab4a9c0 100644 --- a/arch/sparc/kernel/ttable_64.S +++ b/arch/sparc/kernel/ttable_64.S @@ -50,7 +50,7 @@ tl0_resv03e: BTRAP(0x3e) BTRAP(0x3f) BTRAP(0x40) tl0_irq1: TRAP_IRQ(smp_call_function_client, 1) tl0_irq2: TRAP_IRQ(smp_receive_signal_client, 2) tl0_irq3: TRAP_IRQ(smp_penguin_jailcell, 3) -tl0_irq4: TRAP_IRQ(smp_new_mmu_context_version_client, 4) +tl0_irq4: BTRAP(0x44) #else tl0_irq1: BTRAP(0x41) tl0_irq2: BTRAP(0x42) diff --git a/arch/sparc/mm/ultra.S b/arch/sparc/mm/ultra.S index 5d2fd6cd3189..fcf4d27a38fb 100644 --- a/arch/sparc/mm/ultra.S +++ b/arch/sparc/mm/ultra.S @@ -971,11 +971,6 @@ xcall_capture: wr %g0, (1 << PIL_SMP_CAPTURE), %set_softint retry - .globl xcall_new_mmu_context_version -xcall_new_mmu_context_version: - wr %g0, (1 << PIL_SMP_CTX_NEW_VERSION), %set_softint - retry - #ifdef CONFIG_KGDB .globl xcall_kgdb_capture xcall_kgdb_capture: -- cgit v1.2.3 From abb2ea7dfd82451d85ce669b811310c05ab5ca46 Mon Sep 17 00:00:00 2001 From: David Rientjes Date: Tue, 6 Jun 2017 13:36:24 -0700 Subject: compiler, clang: suppress warning for unused static inline functions GCC explicitly does not warn for unused static inline functions for -Wunused-function. The manual states: Warn whenever a static function is declared but not defined or a non-inline static function is unused. Clang does warn for static inline functions that are unused. It turns out that suppressing the warnings avoids potentially complex #ifdef directives, which also reduces LOC. Suppress the warning for clang. Signed-off-by: David Rientjes Signed-off-by: Linus Torvalds --- include/linux/compiler-clang.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/linux/compiler-clang.h b/include/linux/compiler-clang.h index de179993e039..ea9126006a69 100644 --- a/include/linux/compiler-clang.h +++ b/include/linux/compiler-clang.h @@ -15,3 +15,10 @@ * with any version that can compile the kernel */ #define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__) + +/* + * GCC does not warn about unused static inline functions for + * -Wunused-function. This turns out to avoid the need for complex #ifdef + * directives. Suppress the warning in clang as well. + */ +#define inline inline __attribute__((unused)) -- cgit v1.2.3 From f3b7eaae1b35eb8077610eb7c7db042c9b0645e1 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 7 Jun 2017 00:57:37 +0200 Subject: Revert "ACPI / sleep: Ignore spurious SCI wakeups from suspend-to-idle" Revert commit eed4d47efe95 (ACPI / sleep: Ignore spurious SCI wakeups from suspend-to-idle) as it turned out to be premature and triggered a number of different issues on various systems. That includes, but is not limited to, premature suspend-to-RAM aborts on Dell XPS 13 (9343) reported by Dominik. The issue the commit in question attempted to address is real and will need to be taken care of going forward, but evidently more work is needed for this purpose. Reported-by: Dominik Brodowski Signed-off-by: Rafael J. Wysocki --- drivers/acpi/battery.c | 2 +- drivers/acpi/button.c | 5 ++--- drivers/acpi/device_pm.c | 3 +-- drivers/acpi/sleep.c | 28 ---------------------------- drivers/base/power/main.c | 5 +++++ drivers/base/power/wakeup.c | 18 ++++++------------ include/linux/suspend.h | 7 ++----- kernel/power/process.c | 2 +- kernel/power/suspend.c | 29 ++++------------------------- 9 files changed, 22 insertions(+), 77 deletions(-) diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 83ab17e4a795..4ef1e4624b2b 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -776,7 +776,7 @@ static int acpi_battery_update(struct acpi_battery *battery, bool resume) if ((battery->state & ACPI_BATTERY_STATE_CRITICAL) || (test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags) && (battery->capacity_now <= battery->alarm))) - pm_wakeup_hard_event(&battery->device->dev); + pm_wakeup_event(&battery->device->dev, 0); return result; } diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index b7c2a06963d6..668137e4a069 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -216,7 +216,7 @@ static int acpi_lid_notify_state(struct acpi_device *device, int state) } if (state) - pm_wakeup_hard_event(&device->dev); + pm_wakeup_event(&device->dev, 0); ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, device); if (ret == NOTIFY_DONE) @@ -398,7 +398,7 @@ static void acpi_button_notify(struct acpi_device *device, u32 event) } else { int keycode; - pm_wakeup_hard_event(&device->dev); + pm_wakeup_event(&device->dev, 0); if (button->suspended) break; @@ -530,7 +530,6 @@ static int acpi_button_add(struct acpi_device *device) lid_device = device; } - device_init_wakeup(&device->dev, true); printk(KERN_INFO PREFIX "%s [%s]\n", name, acpi_device_bid(device)); return 0; diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index 798d5003a039..993fd31394c8 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c @@ -24,7 +24,6 @@ #include #include #include -#include #include "internal.h" @@ -400,7 +399,7 @@ static void acpi_pm_notify_handler(acpi_handle handle, u32 val, void *not_used) mutex_lock(&acpi_pm_notifier_lock); if (adev->wakeup.flags.notifier_present) { - pm_wakeup_ws_event(adev->wakeup.ws, 0, true); + __pm_wakeup_event(adev->wakeup.ws, 0); if (adev->wakeup.context.work.func) queue_pm_work(&adev->wakeup.context.work); } diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index e84005d642e6..a4327af676fe 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -662,40 +662,14 @@ static int acpi_freeze_prepare(void) acpi_os_wait_events_complete(); if (acpi_sci_irq_valid()) enable_irq_wake(acpi_sci_irq); - return 0; } -static void acpi_freeze_wake(void) -{ - /* - * If IRQD_WAKEUP_ARMED is not set for the SCI at this point, it means - * that the SCI has triggered while suspended, so cancel the wakeup in - * case it has not been a wakeup event (the GPEs will be checked later). - */ - if (acpi_sci_irq_valid() && - !irqd_is_wakeup_armed(irq_get_irq_data(acpi_sci_irq))) - pm_system_cancel_wakeup(); -} - -static void acpi_freeze_sync(void) -{ - /* - * Process all pending events in case there are any wakeup ones. - * - * The EC driver uses the system workqueue, so that one needs to be - * flushed too. - */ - acpi_os_wait_events_complete(); - flush_scheduled_work(); -} - static void acpi_freeze_restore(void) { acpi_disable_wakeup_devices(ACPI_STATE_S0); if (acpi_sci_irq_valid()) disable_irq_wake(acpi_sci_irq); - acpi_enable_all_runtime_gpes(); } @@ -707,8 +681,6 @@ static void acpi_freeze_end(void) static const struct platform_freeze_ops acpi_freeze_ops = { .begin = acpi_freeze_begin, .prepare = acpi_freeze_prepare, - .wake = acpi_freeze_wake, - .sync = acpi_freeze_sync, .restore = acpi_freeze_restore, .end = acpi_freeze_end, }; diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index e987a6f55d36..9faee1c893e5 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -1091,6 +1091,11 @@ static int __device_suspend_noirq(struct device *dev, pm_message_t state, bool a if (async_error) goto Complete; + if (pm_wakeup_pending()) { + async_error = -EBUSY; + goto Complete; + } + if (dev->power.syscore || dev->power.direct_complete) goto Complete; diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c index 9c36b27996fc..c313b600d356 100644 --- a/drivers/base/power/wakeup.c +++ b/drivers/base/power/wakeup.c @@ -28,8 +28,8 @@ bool events_check_enabled __read_mostly; /* First wakeup IRQ seen by the kernel in the last cycle. */ unsigned int pm_wakeup_irq __read_mostly; -/* If greater than 0 and the system is suspending, terminate the suspend. */ -static atomic_t pm_abort_suspend __read_mostly; +/* If set and the system is suspending, terminate the suspend. */ +static bool pm_abort_suspend __read_mostly; /* * Combined counters of registered wakeup events and wakeup events in progress. @@ -855,26 +855,20 @@ bool pm_wakeup_pending(void) pm_print_active_wakeup_sources(); } - return ret || atomic_read(&pm_abort_suspend) > 0; + return ret || pm_abort_suspend; } void pm_system_wakeup(void) { - atomic_inc(&pm_abort_suspend); + pm_abort_suspend = true; freeze_wake(); } EXPORT_SYMBOL_GPL(pm_system_wakeup); -void pm_system_cancel_wakeup(void) -{ - atomic_dec(&pm_abort_suspend); -} - -void pm_wakeup_clear(bool reset) +void pm_wakeup_clear(void) { + pm_abort_suspend = false; pm_wakeup_irq = 0; - if (reset) - atomic_set(&pm_abort_suspend, 0); } void pm_system_irq_wakeup(unsigned int irq_number) diff --git a/include/linux/suspend.h b/include/linux/suspend.h index 0b1cf32edfd7..d9718378a8be 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h @@ -189,8 +189,6 @@ struct platform_suspend_ops { struct platform_freeze_ops { int (*begin)(void); int (*prepare)(void); - void (*wake)(void); - void (*sync)(void); void (*restore)(void); void (*end)(void); }; @@ -430,8 +428,7 @@ extern unsigned int pm_wakeup_irq; extern bool pm_wakeup_pending(void); extern void pm_system_wakeup(void); -extern void pm_system_cancel_wakeup(void); -extern void pm_wakeup_clear(bool reset); +extern void pm_wakeup_clear(void); extern void pm_system_irq_wakeup(unsigned int irq_number); extern bool pm_get_wakeup_count(unsigned int *count, bool block); extern bool pm_save_wakeup_count(unsigned int count); @@ -481,7 +478,7 @@ static inline int unregister_pm_notifier(struct notifier_block *nb) static inline bool pm_wakeup_pending(void) { return false; } static inline void pm_system_wakeup(void) {} -static inline void pm_wakeup_clear(bool reset) {} +static inline void pm_wakeup_clear(void) {} static inline void pm_system_irq_wakeup(unsigned int irq_number) {} static inline void lock_system_sleep(void) {} diff --git a/kernel/power/process.c b/kernel/power/process.c index 78672d324a6e..c7209f060eeb 100644 --- a/kernel/power/process.c +++ b/kernel/power/process.c @@ -132,7 +132,7 @@ int freeze_processes(void) if (!pm_freezing) atomic_inc(&system_freezing_cnt); - pm_wakeup_clear(true); + pm_wakeup_clear(); pr_info("Freezing user space processes ... "); pm_freezing = true; error = try_to_freeze_tasks(true); diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c index c0248c74d6d4..15e6baef5c73 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c @@ -72,8 +72,6 @@ static void freeze_begin(void) static void freeze_enter(void) { - trace_suspend_resume(TPS("machine_suspend"), PM_SUSPEND_FREEZE, true); - spin_lock_irq(&suspend_freeze_lock); if (pm_wakeup_pending()) goto out; @@ -100,27 +98,6 @@ static void freeze_enter(void) out: suspend_freeze_state = FREEZE_STATE_NONE; spin_unlock_irq(&suspend_freeze_lock); - - trace_suspend_resume(TPS("machine_suspend"), PM_SUSPEND_FREEZE, false); -} - -static void s2idle_loop(void) -{ - do { - freeze_enter(); - - if (freeze_ops && freeze_ops->wake) - freeze_ops->wake(); - - dpm_resume_noirq(PMSG_RESUME); - if (freeze_ops && freeze_ops->sync) - freeze_ops->sync(); - - if (pm_wakeup_pending()) - break; - - pm_wakeup_clear(false); - } while (!dpm_suspend_noirq(PMSG_SUSPEND)); } void freeze_wake(void) @@ -394,8 +371,10 @@ static int suspend_enter(suspend_state_t state, bool *wakeup) * all the devices are suspended. */ if (state == PM_SUSPEND_FREEZE) { - s2idle_loop(); - goto Platform_early_resume; + trace_suspend_resume(TPS("machine_suspend"), state, true); + freeze_enter(); + trace_suspend_resume(TPS("machine_suspend"), state, false); + goto Platform_wake; } error = disable_nonboot_cpus(); -- cgit v1.2.3 From 151d1d752bb681f29898c68c966f6e17b446456c Mon Sep 17 00:00:00 2001 From: Alexander Sverdlin Date: Mon, 22 May 2017 15:30:21 +0200 Subject: MAINTAINERS: EP93XX: Update maintainership As agreed with Ryan, change the maintainership. Signed-off-by: Alexander Sverdlin Acked-by: Ryan Mallon Acked-by: H Hartley Sweeten Signed-off-by: Olof Johansson --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 6df2afb5585e..2edcff83e0eb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1172,7 +1172,7 @@ N: clps711x ARM/CIRRUS LOGIC EP93XX ARM ARCHITECTURE M: Hartley Sweeten -M: Ryan Mallon +M: Alexander Sverdlin L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained F: arch/arm/mach-ep93xx/ -- cgit v1.2.3 From d11662f4f798b50d8c8743f433842c3e40fe3378 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 2 Jun 2017 15:03:38 +0200 Subject: ALSA: timer: Fix race between read and ioctl The read from ALSA timer device, the function snd_timer_user_tread(), may access to an uninitialized struct snd_timer_user fields when the read is concurrently performed while the ioctl like snd_timer_user_tselect() is invoked. We have already fixed the races among ioctls via a mutex, but we seem to have forgotten the race between read vs ioctl. This patch simply applies (more exactly extends the already applied range of) tu->ioctl_lock in snd_timer_user_tread() for closing the race window. Reported-by: Alexander Potapenko Tested-by: Alexander Potapenko Cc: Signed-off-by: Takashi Iwai --- sound/core/timer.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sound/core/timer.c b/sound/core/timer.c index 2f836ca09860..1118bd8e2d3c 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -1959,6 +1959,7 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, tu = file->private_data; unit = tu->tread ? sizeof(struct snd_timer_tread) : sizeof(struct snd_timer_read); + mutex_lock(&tu->ioctl_lock); spin_lock_irq(&tu->qlock); while ((long)count - result >= unit) { while (!tu->qused) { @@ -1974,7 +1975,9 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, add_wait_queue(&tu->qchange_sleep, &wait); spin_unlock_irq(&tu->qlock); + mutex_unlock(&tu->ioctl_lock); schedule(); + mutex_lock(&tu->ioctl_lock); spin_lock_irq(&tu->qlock); remove_wait_queue(&tu->qchange_sleep, &wait); @@ -1994,7 +1997,6 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, tu->qused--; spin_unlock_irq(&tu->qlock); - mutex_lock(&tu->ioctl_lock); if (tu->tread) { if (copy_to_user(buffer, &tu->tqueue[qhead], sizeof(struct snd_timer_tread))) @@ -2004,7 +2006,6 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, sizeof(struct snd_timer_read))) err = -EFAULT; } - mutex_unlock(&tu->ioctl_lock); spin_lock_irq(&tu->qlock); if (err < 0) @@ -2014,6 +2015,7 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, } _error: spin_unlock_irq(&tu->qlock); + mutex_unlock(&tu->ioctl_lock); return result > 0 ? result : err; } -- cgit v1.2.3 From ba3021b2c79b2fa9114f92790a99deb27a65b728 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 2 Jun 2017 17:26:56 +0200 Subject: ALSA: timer: Fix missing queue indices reset at SNDRV_TIMER_IOCTL_SELECT snd_timer_user_tselect() reallocates the queue buffer dynamically, but it forgot to reset its indices. Since the read may happen concurrently with ioctl and snd_timer_user_tselect() allocates the buffer via kmalloc(), this may lead to the leak of uninitialized kernel-space data, as spotted via KMSAN: BUG: KMSAN: use of unitialized memory in snd_timer_user_read+0x6c4/0xa10 CPU: 0 PID: 1037 Comm: probe Not tainted 4.11.0-rc5+ #2739 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 Call Trace: __dump_stack lib/dump_stack.c:16 dump_stack+0x143/0x1b0 lib/dump_stack.c:52 kmsan_report+0x12a/0x180 mm/kmsan/kmsan.c:1007 kmsan_check_memory+0xc2/0x140 mm/kmsan/kmsan.c:1086 copy_to_user ./arch/x86/include/asm/uaccess.h:725 snd_timer_user_read+0x6c4/0xa10 sound/core/timer.c:2004 do_loop_readv_writev fs/read_write.c:716 __do_readv_writev+0x94c/0x1380 fs/read_write.c:864 do_readv_writev fs/read_write.c:894 vfs_readv fs/read_write.c:908 do_readv+0x52a/0x5d0 fs/read_write.c:934 SYSC_readv+0xb6/0xd0 fs/read_write.c:1021 SyS_readv+0x87/0xb0 fs/read_write.c:1018 This patch adds the missing reset of queue indices. Together with the previous fix for the ioctl/read race, we cover the whole problem. Reported-by: Alexander Potapenko Tested-by: Alexander Potapenko Cc: Signed-off-by: Takashi Iwai --- sound/core/timer.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/core/timer.c b/sound/core/timer.c index 1118bd8e2d3c..cd67d1c12cf1 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -1618,6 +1618,7 @@ static int snd_timer_user_tselect(struct file *file, if (err < 0) goto __err; + tu->qhead = tu->qtail = tu->qused = 0; kfree(tu->queue); tu->queue = NULL; kfree(tu->tqueue); -- cgit v1.2.3 From 82654b6b8ef8b93ee87a97fc562f87f081fc2f91 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Fri, 2 Jun 2017 16:32:08 +0800 Subject: nvme: fix hang in remove path We need to start admin queues too in nvme_kill_queues() for avoiding hang in remove path[1]. This patch is very similar with 806f026f9b901eaf(nvme: use blk_mq_start_hw_queues() in nvme_kill_queues()). [1] hang stack trace [] blk_execute_rq+0x56/0x80 [] __nvme_submit_sync_cmd+0x89/0xf0 [] nvme_set_features+0x5e/0x90 [] nvme_configure_apst+0x166/0x200 [] nvme_set_latency_tolerance+0x35/0x50 [] apply_constraint+0xb1/0xc0 [] dev_pm_qos_constraints_destroy+0xf4/0x1f0 [] dpm_sysfs_remove+0x2a/0x60 [] device_del+0x101/0x320 [] device_unregister+0x1a/0x60 [] device_destroy+0x3c/0x50 [] nvme_uninit_ctrl+0x45/0xa0 [] nvme_remove+0x78/0x110 [] pci_device_remove+0x39/0xb0 [] device_release_driver_internal+0x155/0x210 [] device_release_driver+0x12/0x20 [] nvme_remove_dead_ctrl_work+0x6b/0x70 [] process_one_work+0x18c/0x3a0 [] worker_thread+0x4e/0x3b0 [] kthread+0x109/0x140 [] ret_from_fork+0x2c/0x40 [] 0xffffffffffffffff Fixes: c5552fde102fc("nvme: Enable autonomous power state transitions") Reported-by: Rakesh Pandit Tested-by: Rakesh Pandit Reviewed-by: Sagi Grimberg Signed-off-by: Ming Lei Signed-off-by: Christoph Hellwig --- drivers/nvme/host/core.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index a60926410438..0f9cc0c55e15 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -2438,6 +2438,10 @@ void nvme_kill_queues(struct nvme_ctrl *ctrl) struct nvme_ns *ns; mutex_lock(&ctrl->namespaces_mutex); + + /* Forcibly start all queues to avoid having stuck requests */ + blk_mq_start_hw_queues(ctrl->admin_q); + list_for_each_entry(ns, &ctrl->namespaces, list) { /* * Revalidating a dead namespace sets capacity to 0. This will -- cgit v1.2.3 From 82b057caefaff2a891f821a617d939f46e03e844 Mon Sep 17 00:00:00 2001 From: Rakesh Pandit Date: Mon, 5 Jun 2017 14:43:11 +0300 Subject: nvme-pci: fix multiple ctrl removal scheduling Commit c5f6ce97c1210 tries to address multiple resets but fails as work_busy doesn't involve any synchronization and can fail. This is reproducible easily as can be seen by WARNING below which is triggered with line: WARN_ON(dev->ctrl.state == NVME_CTRL_RESETTING) Allowing multiple resets can result in multiple controller removal as well if different conditions inside nvme_reset_work fail and which might deadlock on device_release_driver. [ 480.327007] WARNING: CPU: 3 PID: 150 at drivers/nvme/host/pci.c:1900 nvme_reset_work+0x36c/0xec0 [ 480.327008] Modules linked in: rfcomm fuse nf_conntrack_netbios_ns nf_conntrack_broadcast... [ 480.327044] btusb videobuf2_core ghash_clmulni_intel snd_hwdep cfg80211 acer_wmi hci_uart.. [ 480.327065] CPU: 3 PID: 150 Comm: kworker/u16:2 Not tainted 4.12.0-rc1+ #13 [ 480.327065] Hardware name: Acer Predator G9-591/Mustang_SLS, BIOS V1.10 03/03/2016 [ 480.327066] Workqueue: nvme nvme_reset_work [ 480.327067] task: ffff880498ad8000 task.stack: ffffc90002218000 [ 480.327068] RIP: 0010:nvme_reset_work+0x36c/0xec0 [ 480.327069] RSP: 0018:ffffc9000221bdb8 EFLAGS: 00010246 [ 480.327070] RAX: 0000000000460000 RBX: ffff880498a98128 RCX: dead000000000200 [ 480.327070] RDX: 0000000000000001 RSI: ffff8804b1028020 RDI: ffff880498a98128 [ 480.327071] RBP: ffffc9000221be50 R08: 0000000000000000 R09: 0000000000000000 [ 480.327071] R10: ffffc90001963ce8 R11: 000000000000020d R12: ffff880498a98000 [ 480.327072] R13: ffff880498a53500 R14: ffff880498a98130 R15: ffff880498a98128 [ 480.327072] FS: 0000000000000000(0000) GS:ffff8804c1cc0000(0000) knlGS:0000000000000000 [ 480.327073] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 480.327074] CR2: 00007ffcf3c37f78 CR3: 0000000001e09000 CR4: 00000000003406e0 [ 480.327074] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 480.327075] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 480.327075] Call Trace: [ 480.327079] ? __switch_to+0x227/0x400 [ 480.327081] process_one_work+0x18c/0x3a0 [ 480.327082] worker_thread+0x4e/0x3b0 [ 480.327084] kthread+0x109/0x140 [ 480.327085] ? process_one_work+0x3a0/0x3a0 [ 480.327087] ? kthread_park+0x60/0x60 [ 480.327102] ret_from_fork+0x2c/0x40 [ 480.327103] Code: e8 5a dc ff ff 85 c0 41 89 c1 0f..... This patch addresses the problem by using state of controller to decide whether reset should be queued or not as state change is synchronizated using controller spinlock. Also cancel_work_sync is used to make sure remove cancels the reset_work and waits for it to finish. This patch also changes return value from -ENODEV to more appropriate -EBUSY if nvme_reset fails to change state. Fixes: c5f6ce97c1210 ("nvme: don't schedule multiple resets") Signed-off-by: Rakesh Pandit Reviewed-by: Sagi Grimberg Signed-off-by: Christoph Hellwig --- drivers/nvme/host/pci.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index d52701df7245..951042a375d6 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -1367,7 +1367,7 @@ static bool nvme_should_reset(struct nvme_dev *dev, u32 csts) bool nssro = dev->subsystem && (csts & NVME_CSTS_NSSRO); /* If there is a reset ongoing, we shouldn't reset again. */ - if (work_busy(&dev->reset_work)) + if (dev->ctrl.state == NVME_CTRL_RESETTING) return false; /* We shouldn't reset unless the controller is on fatal error state @@ -1903,7 +1903,7 @@ static void nvme_reset_work(struct work_struct *work) bool was_suspend = !!(dev->ctrl.ctrl_config & NVME_CC_SHN_NORMAL); int result = -ENODEV; - if (WARN_ON(dev->ctrl.state == NVME_CTRL_RESETTING)) + if (WARN_ON(dev->ctrl.state != NVME_CTRL_RESETTING)) goto out; /* @@ -1913,9 +1913,6 @@ static void nvme_reset_work(struct work_struct *work) if (dev->ctrl.ctrl_config & NVME_CC_ENABLE) nvme_dev_disable(dev, false); - if (!nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_RESETTING)) - goto out; - result = nvme_pci_enable(dev); if (result) goto out; @@ -2009,8 +2006,8 @@ static int nvme_reset(struct nvme_dev *dev) { if (!dev->ctrl.admin_q || blk_queue_dying(dev->ctrl.admin_q)) return -ENODEV; - if (work_busy(&dev->reset_work)) - return -ENODEV; + if (!nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_RESETTING)) + return -EBUSY; if (!queue_work(nvme_workq, &dev->reset_work)) return -EBUSY; return 0; @@ -2136,6 +2133,7 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (result) goto release_pools; + nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_RESETTING); dev_info(dev->ctrl.device, "pci function %s\n", dev_name(&pdev->dev)); queue_work(nvme_workq, &dev->reset_work); @@ -2179,6 +2177,7 @@ static void nvme_remove(struct pci_dev *pdev) nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_DELETING); + cancel_work_sync(&dev->reset_work); pci_set_drvdata(pdev, NULL); if (!pci_device_is_present(pdev)) { -- cgit v1.2.3 From e818a5b487fea20494b0e48548c1085634abdc0d Mon Sep 17 00:00:00 2001 From: Sagi Grimberg Date: Mon, 5 Jun 2017 20:35:56 +0300 Subject: nvme-rdma: fast fail incoming requests while we reconnect When we encounter an transport/controller errors, error recovery kicks in which performs: 1. stops io/admin queues 2. moves transport queues out of LIVE state 3. fast fail pending io 4. schedule periodic reconnects. But we also need to fast fail incoming IO taht enters after we already scheduled. Given that our queue is not LIVE anymore, simply restart the request queues to fail in .queue_rq Reported-by: Alex Turin Reported-by: shahar.salzman Signed-off-by: Sagi Grimberg Signed-off-by: Christoph Hellwig Cc: stable@vger.kernel.org --- drivers/nvme/host/rdma.c | 44 +++++++++++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c index 28bd255c144d..24397d306d53 100644 --- a/drivers/nvme/host/rdma.c +++ b/drivers/nvme/host/rdma.c @@ -753,28 +753,26 @@ static void nvme_rdma_reconnect_ctrl_work(struct work_struct *work) if (ret) goto requeue; - blk_mq_start_stopped_hw_queues(ctrl->ctrl.admin_q, true); - ret = nvmf_connect_admin_queue(&ctrl->ctrl); if (ret) - goto stop_admin_q; + goto requeue; set_bit(NVME_RDMA_Q_LIVE, &ctrl->queues[0].flags); ret = nvme_enable_ctrl(&ctrl->ctrl, ctrl->cap); if (ret) - goto stop_admin_q; + goto requeue; nvme_start_keep_alive(&ctrl->ctrl); if (ctrl->queue_count > 1) { ret = nvme_rdma_init_io_queues(ctrl); if (ret) - goto stop_admin_q; + goto requeue; ret = nvme_rdma_connect_io_queues(ctrl); if (ret) - goto stop_admin_q; + goto requeue; } changed = nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_LIVE); @@ -782,7 +780,6 @@ static void nvme_rdma_reconnect_ctrl_work(struct work_struct *work) ctrl->ctrl.opts->nr_reconnects = 0; if (ctrl->queue_count > 1) { - nvme_start_queues(&ctrl->ctrl); nvme_queue_scan(&ctrl->ctrl); nvme_queue_async_events(&ctrl->ctrl); } @@ -791,8 +788,6 @@ static void nvme_rdma_reconnect_ctrl_work(struct work_struct *work) return; -stop_admin_q: - blk_mq_stop_hw_queues(ctrl->ctrl.admin_q); requeue: dev_info(ctrl->ctrl.device, "Failed reconnect attempt %d\n", ctrl->ctrl.opts->nr_reconnects); @@ -823,6 +818,13 @@ static void nvme_rdma_error_recovery_work(struct work_struct *work) blk_mq_tagset_busy_iter(&ctrl->admin_tag_set, nvme_cancel_request, &ctrl->ctrl); + /* + * queues are not a live anymore, so restart the queues to fail fast + * new IO + */ + blk_mq_start_stopped_hw_queues(ctrl->ctrl.admin_q, true); + nvme_start_queues(&ctrl->ctrl); + nvme_rdma_reconnect_or_remove(ctrl); } @@ -1433,7 +1435,7 @@ nvme_rdma_timeout(struct request *rq, bool reserved) /* * We cannot accept any other command until the Connect command has completed. */ -static inline bool nvme_rdma_queue_is_ready(struct nvme_rdma_queue *queue, +static inline int nvme_rdma_queue_is_ready(struct nvme_rdma_queue *queue, struct request *rq) { if (unlikely(!test_bit(NVME_RDMA_Q_LIVE, &queue->flags))) { @@ -1441,11 +1443,22 @@ static inline bool nvme_rdma_queue_is_ready(struct nvme_rdma_queue *queue, if (!blk_rq_is_passthrough(rq) || cmd->common.opcode != nvme_fabrics_command || - cmd->fabrics.fctype != nvme_fabrics_type_connect) - return false; + cmd->fabrics.fctype != nvme_fabrics_type_connect) { + /* + * reconnecting state means transport disruption, which + * can take a long time and even might fail permanently, + * so we can't let incoming I/O be requeued forever. + * fail it fast to allow upper layers a chance to + * failover. + */ + if (queue->ctrl->ctrl.state == NVME_CTRL_RECONNECTING) + return -EIO; + else + return -EAGAIN; + } } - return true; + return 0; } static int nvme_rdma_queue_rq(struct blk_mq_hw_ctx *hctx, @@ -1463,8 +1476,9 @@ static int nvme_rdma_queue_rq(struct blk_mq_hw_ctx *hctx, WARN_ON_ONCE(rq->tag < 0); - if (!nvme_rdma_queue_is_ready(queue, rq)) - return BLK_MQ_RQ_QUEUE_BUSY; + ret = nvme_rdma_queue_is_ready(queue, rq); + if (unlikely(ret)) + goto err; dev = queue->device->dev; ib_dma_sync_single_for_cpu(dev, sqe->dma, -- cgit v1.2.3 From f874d5d079ec35158fa1a1509554c9d641bd5770 Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 1 Jun 2017 22:54:21 -0700 Subject: nvme-fc: on lldd/transport io error, terminate association Per FC-NVME, when lldd or transport detects an i/o error, the connection must be terminated, which in turn requires the association to be termianted. Currently the transport simply creates a nvme completion status of transport error and returns the io. The FC-NVME spec makes the mandate as initiator and host, depending on the error, can get out of sync on outstanding io counts (sqhd/sqtail). Implement the association teardown on lldd or transport detected errors. Signed-off-by: James Smart Signed-off-by: Christoph Hellwig Reviewed-by: Sagi Grimberg --- drivers/nvme/host/fc.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c index 5b14cbefb724..2edae54688e8 100644 --- a/drivers/nvme/host/fc.c +++ b/drivers/nvme/host/fc.c @@ -1139,6 +1139,7 @@ nvme_fc_xmt_disconnect_assoc(struct nvme_fc_ctrl *ctrl) /* *********************** NVME Ctrl Routines **************************** */ static void __nvme_fc_final_op_cleanup(struct request *rq); +static void nvme_fc_error_recovery(struct nvme_fc_ctrl *ctrl, char *errmsg); static int nvme_fc_reinit_request(void *data, struct request *rq) @@ -1265,7 +1266,7 @@ nvme_fc_fcpio_done(struct nvmefc_fcp_req *req) struct nvme_command *sqe = &op->cmd_iu.sqe; __le16 status = cpu_to_le16(NVME_SC_SUCCESS << 1); union nvme_result result; - bool complete_rq; + bool complete_rq, terminate_assoc = true; /* * WARNING: @@ -1294,6 +1295,14 @@ nvme_fc_fcpio_done(struct nvmefc_fcp_req *req) * fabricate a CQE, the following fields will not be set as they * are not referenced: * cqe.sqid, cqe.sqhd, cqe.command_id + * + * Failure or error of an individual i/o, in a transport + * detected fashion unrelated to the nvme completion status, + * potentially cause the initiator and target sides to get out + * of sync on SQ head/tail (aka outstanding io count allowed). + * Per FC-NVME spec, failure of an individual command requires + * the connection to be terminated, which in turn requires the + * association to be terminated. */ fc_dma_sync_single_for_cpu(ctrl->lport->dev, op->fcp_req.rspdma, @@ -1359,6 +1368,8 @@ nvme_fc_fcpio_done(struct nvmefc_fcp_req *req) goto done; } + terminate_assoc = false; + done: if (op->flags & FCOP_FLAGS_AEN) { nvme_complete_async_event(&queue->ctrl->ctrl, status, &result); @@ -1366,7 +1377,7 @@ done: atomic_set(&op->state, FCPOP_STATE_IDLE); op->flags = FCOP_FLAGS_AEN; /* clear other flags */ nvme_fc_ctrl_put(ctrl); - return; + goto check_error; } complete_rq = __nvme_fc_fcpop_chk_teardowns(ctrl, op); @@ -1379,6 +1390,10 @@ done: nvme_end_request(rq, status, result); } else __nvme_fc_final_op_cleanup(rq); + +check_error: + if (terminate_assoc) + nvme_fc_error_recovery(ctrl, "transport detected io error"); } static int -- cgit v1.2.3 From 24b7f0592f738a1127c72dbf5b72a83997dd6997 Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 5 Jun 2017 15:03:42 -0700 Subject: nvme-fc: fix missing put reference on controller create failure The failure case, of a create controller request, called nvme_uninit_ctrl() but didn't do a put to allow the nvme controller to be deleted. Signed-off-by: James Smart Signed-off-by: Christoph Hellwig --- drivers/nvme/host/fc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c index 2edae54688e8..92964cef0f4b 100644 --- a/drivers/nvme/host/fc.c +++ b/drivers/nvme/host/fc.c @@ -2806,6 +2806,7 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts, ctrl->ctrl.opts = NULL; /* initiate nvme ctrl ref counting teardown */ nvme_uninit_ctrl(&ctrl->ctrl); + nvme_put_ctrl(&ctrl->ctrl); /* as we're past the point where we transition to the ref * counting teardown path, if we return a bad pointer here, -- cgit v1.2.3 From da87591bea92204fcb921bac927666eb7141908e Mon Sep 17 00:00:00 2001 From: Kai-Heng Feng Date: Wed, 7 Jun 2017 15:25:42 +0800 Subject: nvme: only consider exit latency when choosing useful non-op power states When a NVMe is in non-op states, the latency is exlat. The latency will be enlat + exlat only when the NVMe tries to transit from operational state right atfer it begins to transit to non-operational state, which should be a rare case. Therefore, as Andy Lutomirski suggests, use exlat only when deciding power states to trainsit to. Signed-off-by: Kai-Heng Feng Signed-off-by: Christoph Hellwig --- drivers/nvme/host/core.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 0f9cc0c55e15..c07d8d4e18c9 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -1342,7 +1342,7 @@ static void nvme_configure_apst(struct nvme_ctrl *ctrl) * transitioning between power states. Therefore, when running * in any given state, we will enter the next lower-power * non-operational state after waiting 50 * (enlat + exlat) - * microseconds, as long as that state's total latency is under + * microseconds, as long as that state's exit latency is under * the requested maximum latency. * * We will not autonomously enter any non-operational state for @@ -1387,7 +1387,7 @@ static void nvme_configure_apst(struct nvme_ctrl *ctrl) * lowest-power state, not the number of states. */ for (state = (int)ctrl->npss; state >= 0; state--) { - u64 total_latency_us, transition_ms; + u64 total_latency_us, exit_latency_us, transition_ms; if (target) table->entries[state] = target; @@ -1408,12 +1408,15 @@ static void nvme_configure_apst(struct nvme_ctrl *ctrl) NVME_PS_FLAGS_NON_OP_STATE)) continue; - total_latency_us = - (u64)le32_to_cpu(ctrl->psd[state].entry_lat) + - + le32_to_cpu(ctrl->psd[state].exit_lat); - if (total_latency_us > ctrl->ps_max_latency_us) + exit_latency_us = + (u64)le32_to_cpu(ctrl->psd[state].exit_lat); + if (exit_latency_us > ctrl->ps_max_latency_us) continue; + total_latency_us = + exit_latency_us + + le32_to_cpu(ctrl->psd[state].entry_lat); + /* * This state is good. Use it as the APST idle * target for higher power states. -- cgit v1.2.3 From 9947d6a09cd71937dade2fc14640e4843ae19802 Mon Sep 17 00:00:00 2001 From: Kai-Heng Feng Date: Wed, 7 Jun 2017 15:25:43 +0800 Subject: nvme: relax APST default max latency to 100ms Christoph Hellwig suggests we should to make APST work out of the box. Hence relax the the default max latency to make them able to enter deepest power state on default. Here are id-ctrl excerpts from two high latency NVMes: vid : 0x14a4 ssvid : 0x1b4b mn : CX2-GB1024-Q11 NVMe LITEON 1024GB ps 3 : mp:0.1000W non-operational enlat:5000 exlat:5000 rrt:3 rrl:3 rwt:3 rwl:3 idle_power:- active_power:- ps 4 : mp:0.0100W non-operational enlat:50000 exlat:100000 rrt:4 rrl:4 rwt:4 rwl:4 idle_power:- active_power:- vid : 0x15b7 ssvid : 0x1b4b mn : A400 NVMe SanDisk 512GB ps 3 : mp:0.0500W non-operational enlat:51000 exlat:10000 rrt:0 rrl:0 rwt:0 rwl:0 idle_power:- active_power:- ps 4 : mp:0.0055W non-operational enlat:1000000 exlat:100000 rrt:0 rrl:0 rwt:0 rwl:0 idle_power:- active_power:- Signed-off-by: Kai-Heng Feng Signed-off-by: Christoph Hellwig --- drivers/nvme/host/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index c07d8d4e18c9..903d5813023a 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -56,7 +56,7 @@ MODULE_PARM_DESC(max_retries, "max number of retries a command may have"); static int nvme_char_major; module_param(nvme_char_major, int, 0); -static unsigned long default_ps_max_latency_us = 25000; +static unsigned long default_ps_max_latency_us = 100000; module_param(default_ps_max_latency_us, ulong, 0644); MODULE_PARM_DESC(default_ps_max_latency_us, "max power saving latency for new devices; use PM QOS to change per device"); -- cgit v1.2.3 From 753c09b5652bb4fe53e2db648002ec64b32b8827 Mon Sep 17 00:00:00 2001 From: Julien Grall Date: Wed, 31 May 2017 14:03:57 +0100 Subject: xen/privcmd: Support correctly 64KB page granularity when mapping memory Commit 5995a68 "xen/privcmd: Add support for Linux 64KB page granularity" did not go far enough to support 64KB in mmap_batch_fn. The variable 'nr' is the number of 4KB chunk to map. However, when Linux is using 64KB page granularity the array of pages (vma->vm_private_data) contain one page per 64KB. Fix it by incrementing st->index correctly. Furthermore, st->va is not correctly incremented as PAGE_SIZE != XEN_PAGE_SIZE. Fixes: 5995a68 ("xen/privcmd: Add support for Linux 64KB page granularity") CC: stable@vger.kernel.org Reported-by: Feng Kan Signed-off-by: Julien Grall Reviewed-by: Boris Ostrovsky Signed-off-by: Juergen Gross --- drivers/xen/privcmd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c index 7a92a5e1d40c..feca75b07fdd 100644 --- a/drivers/xen/privcmd.c +++ b/drivers/xen/privcmd.c @@ -362,8 +362,8 @@ static int mmap_batch_fn(void *data, int nr, void *state) st->global_error = 1; } } - st->va += PAGE_SIZE * nr; - st->index += nr; + st->va += XEN_PAGE_SIZE * nr; + st->index += nr / XEN_PFN_PER_PAGE; return 0; } -- cgit v1.2.3 From d86b18a06cf361e12ccdf61ae240d432182d8d6b Mon Sep 17 00:00:00 2001 From: Jon Bloomfield Date: Wed, 24 May 2017 08:54:11 -0700 Subject: drm/i915: Serialize GTT/Aperture accesses on BXT BXT has a H/W issue with IOMMU which can lead to system hangs when Aperture accesses are queued within the GAM behind GTT Accesses. This patch avoids the condition by wrapping all GTT updates in stop_machine and using a flushing read prior to restarting the machine. The stop_machine guarantees no new Aperture accesses can begin while the PTE writes are being emmitted. The flushing read ensures that any following Aperture accesses cannot begin until the PTE writes have been cleared out of the GAM's fifo. Only FOLLOWING Aperture accesses need to be separated from in flight PTE updates. PTE Writes may follow tightly behind already in flight Aperture accesses, so no flushing read is required at the start of a PTE update sequence. This issue was reproduced by running igt/gem_readwrite and igt/gem_render_copy simultaneously from different processes, each in a tight loop, with INTEL_IOMMU enabled. This patch was originally published as: drm/i915: Serialize GTT Updates on BXT [Note: This will cause a performance penalty for some use cases, but avoiding hangs trumps performance hits. This may need to be worked around in Mesa to recover the lost performance.] v2: Move bxt/iommu detection into static function Remove #ifdef CONFIG_INTEL_IOMMU protection Make function names more reflective of purpose Move flushing read into static function v3: Tidy up for checkpatch.pl Testcase: igt/gem_concurrent_blit Signed-off-by: Jon Bloomfield Cc: John Harrison Cc: Chris Wilson Cc: Daniel Vetter Cc: Tvrtko Ursulin Cc: stable@vger.kernel.org Link: http://patchwork.freedesktop.org/patch/msgid/1495641251-30022-1-git-send-email-jon.bloomfield@intel.com Reviewed-by: Tvrtko Ursulin Signed-off-by: Chris Wilson (cherry picked from commit 0ef34ad6222abfa513117515fec720c33a58f105) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_drv.h | 10 ++++ drivers/gpu/drm/i915/i915_gem_gtt.c | 103 ++++++++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 963f6d4481f7..2c453a4e97d5 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2991,6 +2991,16 @@ static inline bool intel_scanout_needs_vtd_wa(struct drm_i915_private *dev_priv) return false; } +static inline bool +intel_ggtt_update_needs_vtd_wa(struct drm_i915_private *dev_priv) +{ +#ifdef CONFIG_INTEL_IOMMU + if (IS_BROXTON(dev_priv) && intel_iommu_gfx_mapped) + return true; +#endif + return false; +} + int intel_sanitize_enable_ppgtt(struct drm_i915_private *dev_priv, int enable_ppgtt); diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 50b8f1139ff9..db89843bdd46 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -2191,6 +2191,101 @@ static void gen8_ggtt_clear_range(struct i915_address_space *vm, gen8_set_pte(>t_base[i], scratch_pte); } +static void bxt_vtd_ggtt_wa(struct i915_address_space *vm) +{ + struct drm_i915_private *dev_priv = vm->i915; + + /* + * Make sure the internal GAM fifo has been cleared of all GTT + * writes before exiting stop_machine(). This guarantees that + * any aperture accesses waiting to start in another process + * cannot back up behind the GTT writes causing a hang. + * The register can be any arbitrary GAM register. + */ + POSTING_READ(GFX_FLSH_CNTL_GEN6); +} + +struct insert_page { + struct i915_address_space *vm; + dma_addr_t addr; + u64 offset; + enum i915_cache_level level; +}; + +static int bxt_vtd_ggtt_insert_page__cb(void *_arg) +{ + struct insert_page *arg = _arg; + + gen8_ggtt_insert_page(arg->vm, arg->addr, arg->offset, arg->level, 0); + bxt_vtd_ggtt_wa(arg->vm); + + return 0; +} + +static void bxt_vtd_ggtt_insert_page__BKL(struct i915_address_space *vm, + dma_addr_t addr, + u64 offset, + enum i915_cache_level level, + u32 unused) +{ + struct insert_page arg = { vm, addr, offset, level }; + + stop_machine(bxt_vtd_ggtt_insert_page__cb, &arg, NULL); +} + +struct insert_entries { + struct i915_address_space *vm; + struct sg_table *st; + u64 start; + enum i915_cache_level level; +}; + +static int bxt_vtd_ggtt_insert_entries__cb(void *_arg) +{ + struct insert_entries *arg = _arg; + + gen8_ggtt_insert_entries(arg->vm, arg->st, arg->start, arg->level, 0); + bxt_vtd_ggtt_wa(arg->vm); + + return 0; +} + +static void bxt_vtd_ggtt_insert_entries__BKL(struct i915_address_space *vm, + struct sg_table *st, + u64 start, + enum i915_cache_level level, + u32 unused) +{ + struct insert_entries arg = { vm, st, start, level }; + + stop_machine(bxt_vtd_ggtt_insert_entries__cb, &arg, NULL); +} + +struct clear_range { + struct i915_address_space *vm; + u64 start; + u64 length; +}; + +static int bxt_vtd_ggtt_clear_range__cb(void *_arg) +{ + struct clear_range *arg = _arg; + + gen8_ggtt_clear_range(arg->vm, arg->start, arg->length); + bxt_vtd_ggtt_wa(arg->vm); + + return 0; +} + +static void bxt_vtd_ggtt_clear_range__BKL(struct i915_address_space *vm, + u64 start, + u64 length) +{ + struct clear_range arg = { vm, start, length }; + + stop_machine(bxt_vtd_ggtt_clear_range__cb, &arg, NULL); +} + static void gen6_ggtt_clear_range(struct i915_address_space *vm, u64 start, u64 length) { @@ -2785,6 +2880,14 @@ static int gen8_gmch_probe(struct i915_ggtt *ggtt) ggtt->base.insert_entries = gen8_ggtt_insert_entries; + /* Serialize GTT updates with aperture access on BXT if VT-d is on. */ + if (intel_ggtt_update_needs_vtd_wa(dev_priv)) { + ggtt->base.insert_entries = bxt_vtd_ggtt_insert_entries__BKL; + ggtt->base.insert_page = bxt_vtd_ggtt_insert_page__BKL; + if (ggtt->base.clear_range != nop_clear_range) + ggtt->base.clear_range = bxt_vtd_ggtt_clear_range__BKL; + } + ggtt->invalidate = gen6_ggtt_invalidate; return ggtt_probe_common(ggtt, size); -- cgit v1.2.3 From ee9c4e681ec4f58e42a83cb0c22a0289ade1aacf Mon Sep 17 00:00:00 2001 From: Vladis Dronov Date: Fri, 2 Jun 2017 07:42:09 +0200 Subject: drm/vmwgfx: limit the number of mip levels in vmw_gb_surface_define_ioctl() The 'req->mip_levels' parameter in vmw_gb_surface_define_ioctl() is a user-controlled 'uint32_t' value which is used as a loop count limit. This can lead to a kernel lockup and DoS. Add check for 'req->mip_levels'. References: https://bugzilla.redhat.com/show_bug.cgi?id=1437431 Cc: Signed-off-by: Vladis Dronov Reviewed-by: Sinclair Yeh --- drivers/gpu/drm/vmwgfx/vmwgfx_surface.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c index 7681341fe32b..baf03d4d86d2 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c @@ -1279,6 +1279,9 @@ int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data, if (req->multisample_count != 0) return -EINVAL; + if (req->mip_levels > DRM_VMW_MAX_MIP_LEVELS) + return -EINVAL; + if (unlikely(vmw_user_surface_size == 0)) vmw_user_surface_size = ttm_round_pot(sizeof(*user_srf)) + 128; -- cgit v1.2.3 From bbd5fefeea59412af4b4a325c2743f53a1d6c417 Mon Sep 17 00:00:00 2001 From: Sinclair Yeh Date: Fri, 2 Jun 2017 07:44:53 +0200 Subject: drm/vmwgfx: Don't create proxy surface for cursor With atomic, the cursor surface is treated like a FB. Creating a proxy surface for cursor doesn't gain us much benefit. This fixes the issue on atomic enabled 2D VMs where the cursor disappears. Signed-off-by: Sinclair Yeh Reviewed-by: Thomas Hellstrom --- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index ef9f3a2a4030..bcb6ddbdf43c 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -1498,6 +1498,7 @@ vmw_kms_new_framebuffer(struct vmw_private *dev_priv, */ if (vmw_kms_srf_ok(dev_priv, mode_cmd->width, mode_cmd->height) && dmabuf && only_2d && + mode_cmd->width > 64 && /* Don't create a proxy for cursor */ dev_priv->active_display_unit == vmw_du_screen_target) { ret = vmw_create_dmabuf_proxy(dev_priv->dev, mode_cmd, dmabuf, &surface); -- cgit v1.2.3 From f0c62e9878024300319ba2438adc7b06c6b9c448 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 27 Apr 2017 12:12:08 +0300 Subject: drm/vmwgfx: Handle vmalloc() failure in vmw_local_fifo_reserve() If vmalloc() fails then we need to a bit of cleanup before returning. Cc: Fixes: fb1d9738ca05 ("drm/vmwgfx: Add DRM driver for VMware Virtual GPU") Signed-off-by: Dan Carpenter Reviewed-by: Sinclair Yeh --- drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c index b6a0806b06bf..a1c68e6a689e 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c @@ -368,6 +368,8 @@ static void *vmw_local_fifo_reserve(struct vmw_private *dev_priv, return fifo_state->static_buffer; else { fifo_state->dynamic_buffer = vmalloc(bytes); + if (!fifo_state->dynamic_buffer) + goto out_err; return fifo_state->dynamic_buffer; } } -- cgit v1.2.3 From 07678eca2cf9c9a18584e546c2b2a0d0c9a3150c Mon Sep 17 00:00:00 2001 From: Sinclair Yeh Date: Fri, 2 Jun 2017 07:50:57 +0200 Subject: drm/vmwgfx: Make sure backup_handle is always valid When vmw_gb_surface_define_ioctl() is called with an existing buffer, we end up returning an uninitialized variable in the backup_handle. The fix is to first initialize backup_handle to 0 just to be sure, and second, when a user-provided buffer is found, we will use the req->buffer_handle as the backup_handle. Cc: Reported-by: Murray McAllister Signed-off-by: Sinclair Yeh Reviewed-by: Deepak Rawat --- drivers/gpu/drm/vmwgfx/vmwgfx_surface.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c index baf03d4d86d2..834bb10973a2 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c @@ -1274,7 +1274,7 @@ int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data, struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; int ret; uint32_t size; - uint32_t backup_handle; + uint32_t backup_handle = 0; if (req->multisample_count != 0) return -EINVAL; @@ -1317,12 +1317,16 @@ int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data, ret = vmw_user_dmabuf_lookup(tfile, req->buffer_handle, &res->backup, &user_srf->backup_base); - if (ret == 0 && res->backup->base.num_pages * PAGE_SIZE < - res->backup_size) { - DRM_ERROR("Surface backup buffer is too small.\n"); - vmw_dmabuf_unreference(&res->backup); - ret = -EINVAL; - goto out_unlock; + if (ret == 0) { + if (res->backup->base.num_pages * PAGE_SIZE < + res->backup_size) { + DRM_ERROR("Surface backup buffer is too small.\n"); + vmw_dmabuf_unreference(&res->backup); + ret = -EINVAL; + goto out_unlock; + } else { + backup_handle = req->buffer_handle; + } } } else if (req->drm_surface_flags & drm_vmw_surface_flag_create_buffer) ret = vmw_user_dmabuf_alloc(dev_priv, tfile, -- cgit v1.2.3 From 8a309c8a2d0619efe29ec652c163d6b89eff9f9f Mon Sep 17 00:00:00 2001 From: Sinclair Yeh Date: Fri, 2 Jun 2017 07:53:27 +0200 Subject: drm/vmwgfx: Make sure to update STDU when FB is updated When a new FB is bound, we have to send an update command otherwise the new FB may not be shown Signed-off-by: Sinclair Yeh Reviewed-by: Thomas Hellstrom --- drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c index bad31bdf09b6..60ace30246cf 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c @@ -1355,6 +1355,11 @@ vmw_stdu_primary_plane_atomic_update(struct drm_plane *plane, DRM_ERROR("Failed to bind surface to STDU.\n"); else crtc->primary->fb = plane->state->fb; + + ret = vmw_stdu_update_st(dev_priv, stdu); + + if (ret) + DRM_ERROR("Failed to update STDU.\n"); } -- cgit v1.2.3 From a1ac633912305168bf432c3d47979d43b16164f8 Mon Sep 17 00:00:00 2001 From: Sinclair Yeh Date: Fri, 2 Jun 2017 07:55:50 +0200 Subject: drm/vmwgfx: Fix large topology crash The previous attempt at this had an issue with with num_clips > 1 because it would always end up using the coordinates of the last clip while using width and height calculated from the bounding box of all the clips. So if the last clip happens to be not at the top-left corner of the bounding box, the CPU blit operation would go out of bounds. The original intent was to coalesce all the clips into one blit, and to do that we need to also track the starting point of the content buffer. Signed-off-by: Sinclair Yeh Reviewed-by: Thomas Hellstrom --- drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c index 60ace30246cf..50be1f034f9e 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c @@ -56,6 +56,8 @@ enum stdu_content_type { * @right: Right side of bounding box. * @top: Top side of bounding box. * @bottom: Bottom side of bounding box. + * @fb_left: Left side of the framebuffer/content bounding box + * @fb_top: Top of the framebuffer/content bounding box * @buf: DMA buffer when DMA-ing between buffer and screen targets. * @sid: Surface ID when copying between surface and screen targets. */ @@ -63,6 +65,7 @@ struct vmw_stdu_dirty { struct vmw_kms_dirty base; SVGA3dTransferType transfer; s32 left, right, top, bottom; + s32 fb_left, fb_top; u32 pitch; union { struct vmw_dma_buffer *buf; @@ -647,7 +650,7 @@ static void vmw_stdu_dmabuf_fifo_commit(struct vmw_kms_dirty *dirty) * * @dirty: The closure structure. * - * This function calculates the bounding box for all the incoming clips + * This function calculates the bounding box for all the incoming clips. */ static void vmw_stdu_dmabuf_cpu_clip(struct vmw_kms_dirty *dirty) { @@ -656,11 +659,19 @@ static void vmw_stdu_dmabuf_cpu_clip(struct vmw_kms_dirty *dirty) dirty->num_hits = 1; - /* Calculate bounding box */ + /* Calculate destination bounding box */ ddirty->left = min_t(s32, ddirty->left, dirty->unit_x1); ddirty->top = min_t(s32, ddirty->top, dirty->unit_y1); ddirty->right = max_t(s32, ddirty->right, dirty->unit_x2); ddirty->bottom = max_t(s32, ddirty->bottom, dirty->unit_y2); + + /* + * Calculate content bounding box. We only need the top-left + * coordinate because width and height will be the same as the + * destination bounding box above + */ + ddirty->fb_left = min_t(s32, ddirty->fb_left, dirty->fb_x); + ddirty->fb_top = min_t(s32, ddirty->fb_top, dirty->fb_y); } @@ -697,11 +708,11 @@ static void vmw_stdu_dmabuf_cpu_commit(struct vmw_kms_dirty *dirty) /* Assume we are blitting from Host (display_srf) to Guest (dmabuf) */ src_pitch = stdu->display_srf->base_size.width * stdu->cpp; src = ttm_kmap_obj_virtual(&stdu->host_map, ¬_used); - src += dirty->unit_y1 * src_pitch + dirty->unit_x1 * stdu->cpp; + src += ddirty->top * src_pitch + ddirty->left * stdu->cpp; dst_pitch = ddirty->pitch; dst = ttm_kmap_obj_virtual(&stdu->guest_map, ¬_used); - dst += dirty->fb_y * dst_pitch + dirty->fb_x * stdu->cpp; + dst += ddirty->fb_top * dst_pitch + ddirty->fb_left * stdu->cpp; /* Figure out the real direction */ @@ -760,7 +771,7 @@ static void vmw_stdu_dmabuf_cpu_commit(struct vmw_kms_dirty *dirty) } out_cleanup: - ddirty->left = ddirty->top = S32_MAX; + ddirty->left = ddirty->top = ddirty->fb_left = ddirty->fb_top = S32_MAX; ddirty->right = ddirty->bottom = S32_MIN; } @@ -812,6 +823,7 @@ int vmw_kms_stdu_dma(struct vmw_private *dev_priv, SVGA3D_READ_HOST_VRAM; ddirty.left = ddirty.top = S32_MAX; ddirty.right = ddirty.bottom = S32_MIN; + ddirty.fb_left = ddirty.fb_top = S32_MAX; ddirty.pitch = vfb->base.pitches[0]; ddirty.buf = buf; ddirty.base.fifo_commit = vmw_stdu_dmabuf_fifo_commit; -- cgit v1.2.3 From a2e5a3e2f8cc48cc9ed10a919ae582ab0222da80 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sat, 27 May 2017 19:52:30 +0100 Subject: drm/vmwgfx: fix spelling mistake "exeeds" -> "exceeds" Trivial fix to spelling mistake in DRM_ERROR error message. Signed-off-by: Colin Ian King Reviewed-by: Sinclair Yeh --- drivers/gpu/drm/vmwgfx/vmwgfx_surface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c index 834bb10973a2..6b70bd259953 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c @@ -1498,7 +1498,7 @@ int vmw_surface_gb_priv_define(struct drm_device *dev, dev_priv->stdu_max_height); if (size.width > max_width || size.height > max_height) { - DRM_ERROR("%ux%u\n, exeeds max surface size %ux%u", + DRM_ERROR("%ux%u\n, exceeds max surface size %ux%u", size.width, size.height, max_width, max_height); return -EINVAL; -- cgit v1.2.3 From f470a7740f8c7577df1db5923ec89d890cf32040 Mon Sep 17 00:00:00 2001 From: Sinclair Yeh Date: Wed, 7 Jun 2017 14:24:08 +0200 Subject: drm/vmwgfx: Remove unused legacy cursor functions These function implementations and/or declarations are no longer used now that atomic is enabled. Signed-off-by: Sinclair Yeh Reported-by: Daniel Vetter Reviewed-by: Thomas Hellstrom --- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 114 ------------------------------------ drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 15 ----- 2 files changed, 129 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index bcb6ddbdf43c..1d2db5d912b0 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -274,108 +274,6 @@ void vmw_kms_cursor_post_execbuf(struct vmw_private *dev_priv) } - -/** - * vmw_du_cursor_plane_update() - Update cursor image and location - * - * @plane: plane object to update - * @crtc: owning CRTC of @plane - * @fb: framebuffer to flip onto plane - * @crtc_x: x offset of plane on crtc - * @crtc_y: y offset of plane on crtc - * @crtc_w: width of plane rectangle on crtc - * @crtc_h: height of plane rectangle on crtc - * @src_x: Not used - * @src_y: Not used - * @src_w: Not used - * @src_h: Not used - * - * - * RETURNS: - * Zero on success, error code on failure - */ -int vmw_du_cursor_plane_update(struct drm_plane *plane, - struct drm_crtc *crtc, - struct drm_framebuffer *fb, - int crtc_x, int crtc_y, - unsigned int crtc_w, - unsigned int crtc_h, - uint32_t src_x, uint32_t src_y, - uint32_t src_w, uint32_t src_h) -{ - struct vmw_private *dev_priv = vmw_priv(crtc->dev); - struct vmw_display_unit *du = vmw_crtc_to_du(crtc); - struct vmw_surface *surface = NULL; - struct vmw_dma_buffer *dmabuf = NULL; - s32 hotspot_x, hotspot_y; - int ret; - - hotspot_x = du->hotspot_x + fb->hot_x; - hotspot_y = du->hotspot_y + fb->hot_y; - - /* A lot of the code assumes this */ - if (crtc_w != 64 || crtc_h != 64) { - ret = -EINVAL; - goto out; - } - - if (vmw_framebuffer_to_vfb(fb)->dmabuf) - dmabuf = vmw_framebuffer_to_vfbd(fb)->buffer; - else - surface = vmw_framebuffer_to_vfbs(fb)->surface; - - if (surface && !surface->snooper.image) { - DRM_ERROR("surface not suitable for cursor\n"); - ret = -EINVAL; - goto out; - } - - /* setup new image */ - ret = 0; - if (surface) { - /* vmw_user_surface_lookup takes one reference */ - du->cursor_surface = surface; - - du->cursor_age = du->cursor_surface->snooper.age; - - ret = vmw_cursor_update_image(dev_priv, surface->snooper.image, - 64, 64, hotspot_x, hotspot_y); - } else if (dmabuf) { - /* vmw_user_surface_lookup takes one reference */ - du->cursor_dmabuf = dmabuf; - - ret = vmw_cursor_update_dmabuf(dev_priv, dmabuf, crtc_w, crtc_h, - hotspot_x, hotspot_y); - } else { - vmw_cursor_update_position(dev_priv, false, 0, 0); - goto out; - } - - if (!ret) { - du->cursor_x = crtc_x + du->set_gui_x; - du->cursor_y = crtc_y + du->set_gui_y; - - vmw_cursor_update_position(dev_priv, true, - du->cursor_x + hotspot_x, - du->cursor_y + hotspot_y); - } - -out: - return ret; -} - - -int vmw_du_cursor_plane_disable(struct drm_plane *plane) -{ - if (plane->fb) { - drm_framebuffer_unreference(plane->fb); - plane->fb = NULL; - } - - return -EINVAL; -} - - void vmw_du_cursor_plane_destroy(struct drm_plane *plane) { vmw_cursor_update_position(plane->dev->dev_private, false, 0, 0); @@ -472,18 +370,6 @@ vmw_du_cursor_plane_prepare_fb(struct drm_plane *plane, } -void -vmw_du_cursor_plane_atomic_disable(struct drm_plane *plane, - struct drm_plane_state *old_state) -{ - struct drm_crtc *crtc = plane->state->crtc ?: old_state->crtc; - struct vmw_private *dev_priv = vmw_priv(crtc->dev); - - drm_atomic_set_fb_for_plane(plane->state, NULL); - vmw_cursor_update_position(dev_priv, false, 0, 0); -} - - void vmw_du_cursor_plane_atomic_update(struct drm_plane *plane, struct drm_plane_state *old_state) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h index 13f2f1d2818a..5f8d678ae675 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h @@ -256,10 +256,6 @@ int vmw_du_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, uint32_t size, struct drm_modeset_acquire_ctx *ctx); -int vmw_du_crtc_cursor_set2(struct drm_crtc *crtc, struct drm_file *file_priv, - uint32_t handle, uint32_t width, uint32_t height, - int32_t hot_x, int32_t hot_y); -int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y); int vmw_du_connector_set_property(struct drm_connector *connector, struct drm_property *property, uint64_t val); @@ -339,15 +335,6 @@ void vmw_kms_create_implicit_placement_property(struct vmw_private *dev_priv, /* Universal Plane Helpers */ void vmw_du_primary_plane_destroy(struct drm_plane *plane); void vmw_du_cursor_plane_destroy(struct drm_plane *plane); -int vmw_du_cursor_plane_disable(struct drm_plane *plane); -int vmw_du_cursor_plane_update(struct drm_plane *plane, - struct drm_crtc *crtc, - struct drm_framebuffer *fb, - int crtc_x, int crtc_y, - unsigned int crtc_w, - unsigned int crtc_h, - uint32_t src_x, uint32_t src_y, - uint32_t src_w, uint32_t src_h); /* Atomic Helpers */ int vmw_du_primary_plane_atomic_check(struct drm_plane *plane, @@ -356,8 +343,6 @@ int vmw_du_cursor_plane_atomic_check(struct drm_plane *plane, struct drm_plane_state *state); void vmw_du_cursor_plane_atomic_update(struct drm_plane *plane, struct drm_plane_state *old_state); -void vmw_du_cursor_plane_atomic_disable(struct drm_plane *plane, - struct drm_plane_state *old_state); int vmw_du_cursor_plane_prepare_fb(struct drm_plane *plane, struct drm_plane_state *new_state); void vmw_du_plane_cleanup_fb(struct drm_plane *plane, -- cgit v1.2.3 From 1929e6610bddf0cc44f0859fc72d4016cba0c1fa Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 7 Jun 2017 14:46:15 +0200 Subject: drm/vmwgfx: Bump driver minor and date While the atomic modesetting capability is signaled also elsewhere, also reflect it by a driver minor bump. Signed-off-by: Thomas Hellstrom --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 130d51c5ec6a..4b948fba9eec 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -41,9 +41,9 @@ #include #include "vmwgfx_fence.h" -#define VMWGFX_DRIVER_DATE "20170221" +#define VMWGFX_DRIVER_DATE "20170607" #define VMWGFX_DRIVER_MAJOR 2 -#define VMWGFX_DRIVER_MINOR 12 +#define VMWGFX_DRIVER_MINOR 13 #define VMWGFX_DRIVER_PATCHLEVEL 0 #define VMWGFX_FILE_PAGE_OFFSET 0x00100000 #define VMWGFX_FIFO_STATIC_SIZE (1024*1024) -- cgit v1.2.3 From 4ca9a5821972b431cb94c6a1ac69a64aefe1c17d Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Thu, 18 May 2017 11:31:02 +0000 Subject: drm/i915/guc: Remove stale comment for q_fail This member was dropped long time ago. Fixes: 774439e1 ("drm/i915/guc: re-optimise i915_guc_client layout") Signed-off-by: Michal Wajdeczko Cc: Tvrtko Ursulin Link: http://patchwork.freedesktop.org/patch/msgid/20170518113104.54400-1-michal.wajdeczko@intel.com Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson (cherry picked from commit 4afc67be8e203ee8f5e95e829c0777eae7a14702) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_uc.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_uc.h b/drivers/gpu/drm/i915/intel_uc.h index 4b7f73aeddac..f84115261ae7 100644 --- a/drivers/gpu/drm/i915/intel_uc.h +++ b/drivers/gpu/drm/i915/intel_uc.h @@ -59,8 +59,6 @@ struct drm_i915_gem_request; * available in the work queue (note, the queue is shared, * not per-engine). It is OK for this to be nonzero, but * it should not be huge! - * q_fail: failed to enqueue a work item. This should never happen, - * because we check for space beforehand. * b_fail: failed to ring the doorbell. This should never happen, unless * somehow the hardware misbehaves, or maybe if the GuC firmware * crashes? We probably need to reset the GPU to recover. -- cgit v1.2.3 From 4c4c565513cca1c53a12956640b5915727431631 Mon Sep 17 00:00:00 2001 From: Kai Chen Date: Tue, 23 May 2017 14:58:11 -0700 Subject: drm/i915: Disable decoupled MMIO The decoupled MMIO feature doesn't work as intended by HW team. Enabling it with forcewake will only make debugging efforts more difficult, so let's disable it. Fixes: 85ee17ebeedd ("drm/i915/bxt: Broxton decoupled MMIO") Cc: Zhe Wang Cc: Praveen Paneri Cc: Tvrtko Ursulin Cc: Daniel Vetter Cc: Jani Nikula Cc: intel-gfx@lists.freedesktop.org Cc: # v4.10+ Signed-off-by: Kai Chen Reviewed-by: Tvrtko Ursulin Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/20170523215812.18328-2-kai.chen@intel.com (cherry picked from commit 0051c10acabb631cfd439eae73289e6e4c39b2b7) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_pci.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index f87b0c4e564d..03dbc7f2861e 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -390,7 +390,6 @@ static const struct intel_device_info intel_skylake_gt3_info = { .has_hw_contexts = 1, \ .has_logical_ring_contexts = 1, \ .has_guc = 1, \ - .has_decoupled_mmio = 1, \ .has_aliasing_ppgtt = 1, \ .has_full_ppgtt = 1, \ .has_full_48bit_ppgtt = 1, \ -- cgit v1.2.3 From e0da1963fe84ee86b59dc4b9ff1a69cb4e1275c7 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 30 May 2017 13:13:32 +0100 Subject: drm/i915: Short-circuit i915_gem_wait_for_idle() if already idle If the device is asleep (no GT wakeref), we know the GPU is already idle. If we add an early return, we can avoid touching registers and checking hw state outside of the assumed GT wakelock. This prevents causing such errors whilst debugging: [ 2613.401647] RPM wakelock ref not held during HW access [ 2613.401684] ------------[ cut here ]------------ [ 2613.401720] WARNING: CPU: 5 PID: 7739 at drivers/gpu/drm/i915/intel_drv.h:1787 gen6_read32+0x21f/0x2b0 [i915] [ 2613.401731] Modules linked in: snd_hda_intel i915 vgem snd_hda_codec_hdmi x86_pkg_temp_thermal intel_powerclamp snd_hda_codec_realtek coretemp snd_hda_codec_generic crct10dif_pclmul crc32_pclmul ghash_clmulni_intel snd_hda_codec snd_hwdep snd_hda_core snd_pcm r8169 mii mei_me lpc_ich mei prime_numbers [last unloaded: i915] [ 2613.401823] CPU: 5 PID: 7739 Comm: drv_missed_irq Tainted: G U 4.12.0-rc2-CI-CI_DRM_421+ #1 [ 2613.401825] Hardware name: MSI MS-7924/Z97M-G43(MS-7924), BIOS V1.12 02/15/2016 [ 2613.401840] task: ffff880409e3a740 task.stack: ffffc900084dc000 [ 2613.401861] RIP: 0010:gen6_read32+0x21f/0x2b0 [i915] [ 2613.401863] RSP: 0018:ffffc900084dfce8 EFLAGS: 00010292 [ 2613.401869] RAX: 000000000000002a RBX: ffff8804016a8000 RCX: 0000000000000006 [ 2613.401871] RDX: 0000000000000006 RSI: ffffffff81cbf2d9 RDI: ffffffff81c9e3a7 [ 2613.401874] RBP: ffffc900084dfd18 R08: ffff880409e3afc8 R09: 0000000000000000 [ 2613.401877] R10: 000000008a1c483f R11: 0000000000000000 R12: 000000000000209c [ 2613.401879] R13: 0000000000000001 R14: ffff8804016a8000 R15: ffff8804016ac150 [ 2613.401882] FS: 00007f39ef3dd8c0(0000) GS:ffff88041fb40000(0000) knlGS:0000000000000000 [ 2613.401885] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 2613.401887] CR2: 00000000023717c8 CR3: 00000002e7b34000 CR4: 00000000001406e0 [ 2613.401889] Call Trace: [ 2613.401912] intel_engine_is_idle+0x76/0x90 [i915] [ 2613.401931] i915_gem_wait_for_idle+0xe6/0x1e0 [i915] [ 2613.401951] fault_irq_set+0x40/0x90 [i915] [ 2613.401970] i915_ring_test_irq_set+0x42/0x50 [i915] [ 2613.401976] simple_attr_write+0xc7/0xe0 [ 2613.401981] full_proxy_write+0x4f/0x70 [ 2613.401987] __vfs_write+0x23/0x120 [ 2613.401992] ? rcu_read_lock_sched_held+0x75/0x80 [ 2613.401996] ? rcu_sync_lockdep_assert+0x2a/0x50 [ 2613.401999] ? __sb_start_write+0xfa/0x1f0 [ 2613.402004] vfs_write+0xc5/0x1d0 [ 2613.402008] ? trace_hardirqs_on_caller+0xe7/0x1c0 [ 2613.402013] SyS_write+0x44/0xb0 [ 2613.402020] entry_SYSCALL_64_fastpath+0x1c/0xb1 [ 2613.402022] RIP: 0033:0x7f39eded6670 [ 2613.402025] RSP: 002b:00007fffdcdcb1a8 EFLAGS: 00000246 ORIG_RAX: 0000000000000001 [ 2613.402030] RAX: ffffffffffffffda RBX: ffffffff81470203 RCX: 00007f39eded6670 [ 2613.402033] RDX: 0000000000000001 RSI: 000000000041bc33 RDI: 0000000000000006 [ 2613.402036] RBP: ffffc900084dff88 R08: 00007f39ef3dd8c0 R09: 0000000000000001 [ 2613.402038] R10: 0000000000000000 R11: 0000000000000246 R12: 000000000041bc33 [ 2613.402041] R13: 0000000000000006 R14: 0000000000000000 R15: 0000000000000000 [ 2613.402046] ? __this_cpu_preempt_check+0x13/0x20 [ 2613.402052] Code: 01 9b fa e0 0f ff e9 28 fe ff ff 80 3d 6a dd 0e 00 00 0f 85 29 fe ff ff 48 c7 c7 48 19 29 a0 c6 05 56 dd 0e 00 01 e8 da 9a fa e0 <0f> ff e9 0f fe ff ff b9 01 00 00 00 ba 01 00 00 00 44 89 e6 48 [ 2613.402199] ---[ end trace 31f0cfa93ab632bf ]--- Fixes: 25112b64b3d2 ("drm/i915: Wait for all engines to be idle as part of i915_gem_wait_for_idle()") Signed-off-by: Chris Wilson Cc: Joonas Lahtinen Cc: Tvrtko Ursulin Link: http://patchwork.freedesktop.org/patch/msgid/20170530121334.17364-1-chris@chris-wilson.co.uk Reviewed-by: Joonas Lahtinen (cherry picked from commit 863e9fde1a7061dad09bb299c65bed5f1ccb44ff) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_gem.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index b6ac3df18b58..462031cbd77f 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3298,6 +3298,10 @@ int i915_gem_wait_for_idle(struct drm_i915_private *i915, unsigned int flags) { int ret; + /* If the device is asleep, we have no requests outstanding */ + if (!READ_ONCE(i915->gt.awake)) + return 0; + if (flags & I915_WAIT_LOCKED) { struct i915_gem_timeline *tl; -- cgit v1.2.3 From d9533f19d8401b7072da2d484a9514af0d473148 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 30 May 2017 13:13:33 +0100 Subject: drm/i915: Hold a wakeref for probing the ring registers Allow intel_engine_is_idle() to be called outside of the GT wakeref by acquiring the device runtime pm for ourselves. This allows the function to act as check after we assume the engine is idle and we release the GT wakeref held whilst we have requests. At the moment, we do not call it outside of an awake context but taking the wakeref as required makes it more convenient to use for quick debugging in future. [ 2613.401647] RPM wakelock ref not held during HW access [ 2613.401684] ------------[ cut here ]------------ [ 2613.401720] WARNING: CPU: 5 PID: 7739 at drivers/gpu/drm/i915/intel_drv.h:1787 gen6_read32+0x21f/0x2b0 [i915] [ 2613.401731] Modules linked in: snd_hda_intel i915 vgem snd_hda_codec_hdmi x86_pkg_temp_thermal intel_powerclamp snd_hda_codec_realtek coretemp snd_hda_codec_generic crct10dif_pclmul crc32_pclmul ghash_clmulni_intel snd_hda_codec snd_hwdep snd_hda_core snd_pcm r8169 mii mei_me lpc_ich mei prime_numbers [last unloaded: i915] [ 2613.401823] CPU: 5 PID: 7739 Comm: drv_missed_irq Tainted: G U 4.12.0-rc2-CI-CI_DRM_421+ #1 [ 2613.401825] Hardware name: MSI MS-7924/Z97M-G43(MS-7924), BIOS V1.12 02/15/2016 [ 2613.401840] task: ffff880409e3a740 task.stack: ffffc900084dc000 [ 2613.401861] RIP: 0010:gen6_read32+0x21f/0x2b0 [i915] [ 2613.401863] RSP: 0018:ffffc900084dfce8 EFLAGS: 00010292 [ 2613.401869] RAX: 000000000000002a RBX: ffff8804016a8000 RCX: 0000000000000006 [ 2613.401871] RDX: 0000000000000006 RSI: ffffffff81cbf2d9 RDI: ffffffff81c9e3a7 [ 2613.401874] RBP: ffffc900084dfd18 R08: ffff880409e3afc8 R09: 0000000000000000 [ 2613.401877] R10: 000000008a1c483f R11: 0000000000000000 R12: 000000000000209c [ 2613.401879] R13: 0000000000000001 R14: ffff8804016a8000 R15: ffff8804016ac150 [ 2613.401882] FS: 00007f39ef3dd8c0(0000) GS:ffff88041fb40000(0000) knlGS:0000000000000000 [ 2613.401885] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 2613.401887] CR2: 00000000023717c8 CR3: 00000002e7b34000 CR4: 00000000001406e0 [ 2613.401889] Call Trace: [ 2613.401912] intel_engine_is_idle+0x76/0x90 [i915] [ 2613.401931] i915_gem_wait_for_idle+0xe6/0x1e0 [i915] [ 2613.401951] fault_irq_set+0x40/0x90 [i915] [ 2613.401970] i915_ring_test_irq_set+0x42/0x50 [i915] [ 2613.401976] simple_attr_write+0xc7/0xe0 [ 2613.401981] full_proxy_write+0x4f/0x70 [ 2613.401987] __vfs_write+0x23/0x120 [ 2613.401992] ? rcu_read_lock_sched_held+0x75/0x80 [ 2613.401996] ? rcu_sync_lockdep_assert+0x2a/0x50 [ 2613.401999] ? __sb_start_write+0xfa/0x1f0 [ 2613.402004] vfs_write+0xc5/0x1d0 [ 2613.402008] ? trace_hardirqs_on_caller+0xe7/0x1c0 [ 2613.402013] SyS_write+0x44/0xb0 [ 2613.402020] entry_SYSCALL_64_fastpath+0x1c/0xb1 [ 2613.402022] RIP: 0033:0x7f39eded6670 [ 2613.402025] RSP: 002b:00007fffdcdcb1a8 EFLAGS: 00000246 ORIG_RAX: 0000000000000001 [ 2613.402030] RAX: ffffffffffffffda RBX: ffffffff81470203 RCX: 00007f39eded6670 [ 2613.402033] RDX: 0000000000000001 RSI: 000000000041bc33 RDI: 0000000000000006 [ 2613.402036] RBP: ffffc900084dff88 R08: 00007f39ef3dd8c0 R09: 0000000000000001 [ 2613.402038] R10: 0000000000000000 R11: 0000000000000246 R12: 000000000041bc33 [ 2613.402041] R13: 0000000000000006 R14: 0000000000000000 R15: 0000000000000000 [ 2613.402046] ? __this_cpu_preempt_check+0x13/0x20 [ 2613.402052] Code: 01 9b fa e0 0f ff e9 28 fe ff ff 80 3d 6a dd 0e 00 00 0f 85 29 fe ff ff 48 c7 c7 48 19 29 a0 c6 05 56 dd 0e 00 01 e8 da 9a fa e0 <0f> ff e9 0f fe ff ff b9 01 00 00 00 ba 01 00 00 00 44 89 e6 48 [ 2613.402199] ---[ end trace 31f0cfa93ab632bf ]--- Fixes: 5400367a864d ("drm/i915: Ensure the engine is idle before manually changing HWS") Signed-off-by: Chris Wilson Cc: Mika Kuoppala Cc: Joonas Lahtinen Cc: Tvrtko Ursulin Link: http://patchwork.freedesktop.org/patch/msgid/20170530121334.17364-2-chris@chris-wilson.co.uk Reviewed-by: Tvrtko Ursulin (cherry picked from commit a091d4ee931b16ce4fef945d39a20b851a7e17b7) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_engine_cs.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index 854e8e0c836b..9a0fb3cdd4e0 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -1075,6 +1075,22 @@ int intel_ring_workarounds_emit(struct drm_i915_gem_request *req) return 0; } +static bool ring_is_idle(struct intel_engine_cs *engine) +{ + struct drm_i915_private *dev_priv = engine->i915; + bool idle = true; + + intel_runtime_pm_get(dev_priv); + + /* No bit for gen2, so assume the CS parser is idle */ + if (INTEL_GEN(dev_priv) > 2 && !(I915_READ_MODE(engine) & MODE_IDLE)) + idle = false; + + intel_runtime_pm_put(dev_priv); + + return idle; +} + /** * intel_engine_is_idle() - Report if the engine has finished process all work * @engine: the intel_engine_cs @@ -1100,7 +1116,7 @@ bool intel_engine_is_idle(struct intel_engine_cs *engine) return false; /* Ring stopped? */ - if (INTEL_GEN(dev_priv) > 2 && !(I915_READ_MODE(engine) & MODE_IDLE)) + if (!ring_is_idle(engine)) return false; return true; -- cgit v1.2.3 From bd709898a50184de4fe418bf85486c5b1e002901 Mon Sep 17 00:00:00 2001 From: "Nagaraju, Vathsala" Date: Thu, 25 May 2017 22:13:29 +0530 Subject: drm/i915/psr: disable psr2 for resolution greater than 32X20 psr1 is also disabled for panel resolution greater than 32X20. Added psr2 check to disable only for psr2 panels having resolution greater than 32X20. issue was introduced by commit-id : "acf45d11050abd751dcec986ab121cb2367dcbba" commit message: "PSR2 is restricted to work with panel resolutions upto 3200x2000, move the check to intel_psr_match_conditions and fully block psr." v2: (Rodrigo) Add previous commit details which introduced the issue Fixes: acf45d11050a ("drm/i915/psr: disable psr2 for resolution greater than 32X20") Cc: Rodrigo Vivi Cc: Jim Bride Cc: Yaroslav Shabalin Reported-by: Yaroslav Shabalin Reviewed-by: Rodrigo Vivi Signed-off-by: vathsala nagaraju Signed-off-by: Rodrigo Vivi Link: http://patchwork.freedesktop.org/patch/msgid/49935bdff896ee3140bed471012b9f9110a863a4.1495729964.git.vathsala.nagaraju@intel.com (cherry picked from commit bef8c056fba09aa4629fe5a2d3efe64068d049db) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_psr.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index c3780d0d2baf..559f1ab42bfc 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -435,8 +435,9 @@ static bool intel_psr_match_conditions(struct intel_dp *intel_dp) } /* PSR2 is restricted to work with panel resolutions upto 3200x2000 */ - if (intel_crtc->config->pipe_src_w > 3200 || - intel_crtc->config->pipe_src_h > 2000) { + if (dev_priv->psr.psr2_support && + (intel_crtc->config->pipe_src_w > 3200 || + intel_crtc->config->pipe_src_h > 2000)) { dev_priv->psr.psr2_support = false; return false; } -- cgit v1.2.3 From 6ab92afc95c9bd6877cb42e7b24f65be887a5440 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 2 May 2017 15:04:09 +0300 Subject: drm/i915: Prevent the system suspend complete optimization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit bac2a909a096c9110525c18cbb8ce73c660d5f71 Author: Rafael J. Wysocki Date: Wed Jan 21 02:17:42 2015 +0100 PCI / PM: Avoid resuming PCI devices during system suspend PCI devices will default to allowing the system suspend complete optimization where devices are not woken up during system suspend if they were already runtime suspended. This however breaks the i915/HDA drivers for two reasons: - The i915 driver has system suspend specific steps that it needs to run, that bring the device to a different state than its runtime suspended state. - The HDA driver's suspend handler requires power that it will request from the i915 driver's power domain handler. This in turn requires the i915 driver to runtime resume itself, but this won't be possible if the suspend complete optimization is in effect: in this case the i915 runtime PM is disabled and trying to get an RPM reference returns -EACCESS. Solve this by requiring the PCI/PM core to resume the device during system suspend which in effect disables the suspend complete optimization. Regardless of the above commit the optimization stayed disabled for DRM devices until commit d14d2a8453d650bea32a1c5271af1458cd283a0f Author: Lukas Wunner Date: Wed Jun 8 12:49:29 2016 +0200 drm: Remove dev_pm_ops from drm_class so this patch is in practice a fix for this commit. Another reason for the bug staying hidden for so long is that the optimization for a device is disabled if it's disabled for any of its children devices. i915 may have a backlight device as its child which doesn't support runtime PM and so doesn't allow the optimization either. So if this backlight device got registered the bug stayed hidden. Credits to Marta, Tomi and David who enabled pstore logging, that caught one instance of this issue across a suspend/ resume-to-ram and Ville who rememberd that the optimization was enabled for some devices at one point. The first WARN triggered by the problem: [ 6250.746445] WARNING: CPU: 2 PID: 17384 at drivers/gpu/drm/i915/intel_runtime_pm.c:2846 intel_runtime_pm_get+0x6b/0xd0 [i915] [ 6250.746448] pm_runtime_get_sync() failed: -13 [ 6250.746451] Modules linked in: snd_hda_intel i915 vgem snd_hda_codec_hdmi x86_pkg_temp_thermal intel_powerclamp coretemp crct10dif_pclmul crc32_pclmul snd_hda_codec_realtek snd_hda_codec_generic ghash_clmulni_intel e1000e snd_hda_codec snd_hwdep snd_hda_core ptp mei_me pps_core snd_pcm lpc_ich mei prime_ numbers i2c_hid i2c_designware_platform i2c_designware_core [last unloaded: i915] [ 6250.746512] CPU: 2 PID: 17384 Comm: kworker/u8:0 Tainted: G U W 4.11.0-rc5-CI-CI_DRM_334+ #1 [ 6250.746515] Hardware name: /NUC5i5RYB, BIOS RYBDWi35.86A.0362.2017.0118.0940 01/18/2017 [ 6250.746521] Workqueue: events_unbound async_run_entry_fn [ 6250.746525] Call Trace: [ 6250.746530] dump_stack+0x67/0x92 [ 6250.746536] __warn+0xc6/0xe0 [ 6250.746542] ? pci_restore_standard_config+0x40/0x40 [ 6250.746546] warn_slowpath_fmt+0x46/0x50 [ 6250.746553] ? __pm_runtime_resume+0x56/0x80 [ 6250.746584] intel_runtime_pm_get+0x6b/0xd0 [i915] [ 6250.746610] intel_display_power_get+0x1b/0x40 [i915] [ 6250.746646] i915_audio_component_get_power+0x15/0x20 [i915] [ 6250.746654] snd_hdac_display_power+0xc8/0x110 [snd_hda_core] [ 6250.746661] azx_runtime_resume+0x218/0x280 [snd_hda_intel] [ 6250.746667] pci_pm_runtime_resume+0x76/0xa0 [ 6250.746672] __rpm_callback+0xb4/0x1f0 [ 6250.746677] ? pci_restore_standard_config+0x40/0x40 [ 6250.746682] rpm_callback+0x1f/0x80 [ 6250.746686] ? pci_restore_standard_config+0x40/0x40 [ 6250.746690] rpm_resume+0x4ba/0x740 [ 6250.746698] __pm_runtime_resume+0x49/0x80 [ 6250.746703] pci_pm_suspend+0x57/0x140 [ 6250.746709] dpm_run_callback+0x6f/0x330 [ 6250.746713] ? pci_pm_freeze+0xe0/0xe0 [ 6250.746718] __device_suspend+0xf9/0x370 [ 6250.746724] ? dpm_watchdog_set+0x60/0x60 [ 6250.746730] async_suspend+0x1a/0x90 [ 6250.746735] async_run_entry_fn+0x34/0x160 [ 6250.746741] process_one_work+0x1f2/0x6d0 [ 6250.746749] worker_thread+0x49/0x4a0 [ 6250.746755] kthread+0x107/0x140 [ 6250.746759] ? process_one_work+0x6d0/0x6d0 [ 6250.746763] ? kthread_create_on_node+0x40/0x40 [ 6250.746768] ret_from_fork+0x2e/0x40 [ 6250.746778] ---[ end trace 102a62fd2160f5e6 ]--- v2: - Use the new pci_dev->needs_resume flag, to avoid any overhead during the ->pm_prepare hook. (Rafael) v3: - Update commit message to reference the actual regressing commit. (Lukas) v4: - Rebase on v4 of patch 1/2. Fixes: d14d2a8453d6 ("drm: Remove dev_pm_ops from drm_class") References: https://bugs.freedesktop.org/show_bug.cgi?id=100378 References: https://bugs.freedesktop.org/show_bug.cgi?id=100770 Cc: Rafael J. Wysocki Cc: Marta Lofstedt Cc: David Weinehall Cc: Tomi Sarvela Cc: Ville Syrjälä Cc: Mika Kuoppala Cc: Chris Wilson Cc: Takashi Iwai Cc: Bjorn Helgaas Cc: Lukas Wunner Cc: linux-pci@vger.kernel.org Cc: # v4.10.x: 4d071c3 - PCI/PM: Add needs_resume flag Cc: # v4.10.x Signed-off-by: Imre Deak Reviewed-by: Chris Wilson Reported-and-tested-by: Marta Lofstedt Link: http://patchwork.freedesktop.org/patch/msgid/1493726649-32094-2-git-send-email-imre.deak@intel.com (cherry picked from commit adfdf85d795f4d4f487b61ee0b169d64c6e19081) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_drv.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index c994fe6e65b2..48428672fc6e 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1235,6 +1235,15 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent) goto out_fini; pci_set_drvdata(pdev, &dev_priv->drm); + /* + * Disable the system suspend direct complete optimization, which can + * leave the device suspended skipping the driver's suspend handlers + * if the device was already runtime suspended. This is needed due to + * the difference in our runtime and system suspend sequence and + * becaue the HDA driver may require us to enable the audio power + * domain during system suspend. + */ + pdev->dev_flags |= PCI_DEV_FLAGS_NEEDS_RESUME; ret = i915_driver_init_early(dev_priv, ent); if (ret < 0) -- cgit v1.2.3 From 4e3aed844547f63614363a386de126e6304e55fb Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 31 May 2017 17:42:36 +0200 Subject: drm/i915: Always recompute watermarks when distrust_bios_wm is set, v2. On some systems there can be a race condition in which no crtc state is added to the first atomic commit. This results in all crtc's having a null DDB allocation, causing a FIFO underrun on any update until the first modeset. Changes since v1: - Do not take the connection_mutex, this is already done below. Reported-by: Maarten Lankhorst Inspired-by: Mahesh Kumar Signed-off-by: Maarten Lankhorst Fixes: 98d39494d375 ("drm/i915/gen9: Compute DDB allocation at atomic check time (v4)") Cc: # v4.8+ Cc: Mahesh Kumar Cc: Matt Roper Link: http://patchwork.freedesktop.org/patch/msgid/20170531154236.27180-1-maarten.lankhorst@linux.intel.com Reviewed-by: Mahesh Kumar Reviewed-by: Matt Roper (cherry picked from commit 367d73d2806085bb507ab44c1f532640917fd5ca) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_pm.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 570bd603f401..2ca481b5aa69 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4335,10 +4335,18 @@ skl_compute_wm(struct drm_atomic_state *state) struct drm_crtc_state *cstate; struct intel_atomic_state *intel_state = to_intel_atomic_state(state); struct skl_wm_values *results = &intel_state->wm_results; + struct drm_device *dev = state->dev; struct skl_pipe_wm *pipe_wm; bool changed = false; int ret, i; + /* + * When we distrust bios wm we always need to recompute to set the + * expected DDB allocations for each CRTC. + */ + if (to_i915(dev)->wm.distrust_bios_wm) + changed = true; + /* * If this transaction isn't actually touching any CRTC's, don't * bother with watermark calculation. Note that if we pass this @@ -4349,6 +4357,7 @@ skl_compute_wm(struct drm_atomic_state *state) */ for_each_new_crtc_in_state(state, crtc, cstate, i) changed = true; + if (!changed) return 0; -- cgit v1.2.3 From d90c98905afd00c15d5d255d845b646a37173ce9 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 31 May 2017 20:05:14 +0100 Subject: drm/i915: Guard against i915_ggtt_disable_guc() being invoked unconditionally MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 7c3f86b6dc51 ("drm/i915: Invalidate the guc ggtt TLB upon insertion") added the restoration of the invalidation routine after the GuC was disabled, but missed that the GuC was unconditionally disabled when not used. This then overwrites the invalidate routine for the older chipsets, causing havoc and breaking resume as the most obvious victim. We place the guard inside i915_ggtt_disable_guc() to be backport friendly (the bug was introduced into v4.11) but it would be preferred to be in more control over when this was guard (i.e. do not try and teardown the data structures before we have enabled them). That should be true with the reorganisation of the guc loaders. Reported-by: Ville Syrjälä Signed-off-by: Chris Wilson Fixes: 7c3f86b6dc51 ("drm/i915: Invalidate the guc ggtt TLB upon insertion") Cc: Tvrtko Ursulin Cc: Joonas Lahtinen Cc: Oscar Mateo Cc: Daniele Ceraolo Spurio Cc: Michal Wajdeczko Cc: Arkadiusz Hiler Cc: # v4.11+ Link: http://patchwork.freedesktop.org/patch/msgid/20170531190514.3691-1-chris@chris-wilson.co.uk Reviewed-by: Michel Thierry (cherry picked from commit cb60606d835ca8b2f744835116bcabe64ce88849) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_gem_gtt.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index db89843bdd46..f1989b8792dd 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -3100,7 +3100,8 @@ void i915_ggtt_enable_guc(struct drm_i915_private *i915) void i915_ggtt_disable_guc(struct drm_i915_private *i915) { - i915->ggtt.invalidate = gen6_ggtt_invalidate; + if (i915->ggtt.invalidate == guc_ggtt_invalidate) + i915->ggtt.invalidate = gen6_ggtt_invalidate; } void i915_gem_restore_gtt_mappings(struct drm_i915_private *dev_priv) -- cgit v1.2.3 From 5857dbfabc15ae9e17fd5a355c4920b46295ff1f Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 21 May 2017 13:40:14 +0100 Subject: drm/i915: Fix logical inversion for gen4 quirking The assertion that we want to make before disabling the pin of the pages for the unknown swizzling quirk is that the quirk is indeed active, and that the quirk is disabled before we do apply it to the pages. Fixes: 2c3a3f44dc13 ("drm/i915: Fix pages pin counting around swizzle quirk") Fixes: 957870f93412 ("drm/i915: Split out i915_gem_object_set_tiling()") Signed-off-by: Chris Wilson Cc: Chris Wilson Cc: Joonas Lahtinen Cc: Tvrtko Ursulin Link: http://patchwork.freedesktop.org/patch/msgid/20170521124014.27678-1-chris@chris-wilson.co.uk Reviewed-bhy: Joonas Lahtinen (cherry picked from commit 20bb377106af69d16269b1837e9a945b9f508a2e) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_gem_tiling.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c index a0d6d4317a49..fb5231f98c0d 100644 --- a/drivers/gpu/drm/i915/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/i915_gem_tiling.c @@ -278,7 +278,7 @@ i915_gem_object_set_tiling(struct drm_i915_gem_object *obj, obj->mm.quirked = false; } if (!i915_gem_object_is_tiled(obj)) { - GEM_BUG_ON(!obj->mm.quirked); + GEM_BUG_ON(obj->mm.quirked); __i915_gem_object_pin_pages(obj); obj->mm.quirked = true; } -- cgit v1.2.3 From 8f4d38099b3098eae75f7755e1801931f8141350 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 15 Dec 2016 19:47:34 +0200 Subject: drm/i915: Workaround VLV/CHV DSI scanline counter hardware fail MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The scanline counter is bonkers on VLV/CHV DSI. The scanline counter increment is not lined up with the start of vblank like it is on every other platform and output type. This causes problems for both the vblank timestamping and atomic update vblank evasion. On my FFRD8 machine at least, the scanline counter increment happens about 1/3 of a scanline ahead of the start of vblank (which is where all register latching happens still). That means we can't trust the scanline counter to tell us whether we're in vblank or not while we're on that particular line. In order to keep vblank timestamping in working condition when called from the vblank irq, we'll leave scanline_offset at one, which means that the entire line containing the start of vblank is considered to be inside the vblank. For the vblank evasion we'll need to consider that entire line to be bad, since we can't tell whether the registers already got latched or not. And we can't actually use the start of vblank interrupt to get us past that line as the interrupt would fire too soon, and then we'd up waiting for the next start of vblank instead. One way around that would using the frame start interrupt instead since that wouldn't fire until the next scanline, but that would require some bigger changes in the interrupt code. So for simplicity we'll just poll until we get past the bad line. v2: Adjust the comments a bit Cc: stable@vger.kernel.org Cc: Jonas Aaberg Tested-by: Jonas Aaberg Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=99086 Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/20161215174734.28779-1-ville.syrjala@linux.intel.com Tested-by: Mika Kahola Reviewed-by: Mika Kahola (cherry picked from commit ec1b4ee2834e66884e5b0d3d465f347ff212e372) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_display.c | 9 +++++++++ drivers/gpu/drm/i915/intel_sprite.c | 21 +++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 3cabe52a4e3b..569717a12723 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -12203,6 +12203,15 @@ static void update_scanline_offset(struct intel_crtc *crtc) * type. For DP ports it behaves like most other platforms, but on HDMI * there's an extra 1 line difference. So we need to add two instead of * one to the value. + * + * On VLV/CHV DSI the scanline counter would appear to increment + * approx. 1/3 of a scanline before start of vblank. Unfortunately + * that means we can't tell whether we're in vblank or not while + * we're on that particular line. We must still set scanline_offset + * to 1 so that the vblank timestamps come out correct when we query + * the scanline counter from within the vblank interrupt handler. + * However if queried just before the start of vblank we'll get an + * answer that's slightly in the future. */ if (IS_GEN2(dev_priv)) { const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode; diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 8c87c717c7cd..e6517edcd16b 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -83,10 +83,13 @@ int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode, */ void intel_pipe_update_start(struct intel_crtc *crtc) { + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode; long timeout = msecs_to_jiffies_timeout(1); int scanline, min, max, vblank_start; wait_queue_head_t *wq = drm_crtc_vblank_waitqueue(&crtc->base); + bool need_vlv_dsi_wa = (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) && + intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DSI); DEFINE_WAIT(wait); vblank_start = adjusted_mode->crtc_vblank_start; @@ -139,6 +142,24 @@ void intel_pipe_update_start(struct intel_crtc *crtc) drm_crtc_vblank_put(&crtc->base); + /* + * On VLV/CHV DSI the scanline counter would appear to + * increment approx. 1/3 of a scanline before start of vblank. + * The registers still get latched at start of vblank however. + * This means we must not write any registers on the first + * line of vblank (since not the whole line is actually in + * vblank). And unfortunately we can't use the interrupt to + * wait here since it will fire too soon. We could use the + * frame start interrupt instead since it will fire after the + * critical scanline, but that would require more changes + * in the interrupt code. So for now we'll just do the nasty + * thing and poll for the bad scanline to pass us by. + * + * FIXME figure out if BXT+ DSI suffers from this as well + */ + while (need_vlv_dsi_wa && scanline == vblank_start) + scanline = intel_get_crtc_scanline(crtc); + crtc->debug.scanline_start = scanline; crtc->debug.start_vbl_time = ktime_get(); crtc->debug.start_vbl_count = intel_crtc_get_vblank_counter(crtc); -- cgit v1.2.3 From 27fe407cb5122f12cfe976813686e8206425c32a Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 6 Jun 2017 16:32:29 +0300 Subject: drm/i915: Restore has_fbc=1 for ILK-M MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restore the lost has_fbc flag for mobile ILK. Cc: Carlos Santa Cc: Rodrigo Vivi Fixes: a13233804686 ("drm/i915: Introduce GEN5_FEATURES for device info") Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/20170606133229.12439-1-ville.syrjala@linux.intel.com Reviewed-by: Rodrigo Vivi (cherry picked from commit c2d1a0ced2603c4a17fa9c53c37e415905cf5a6d) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 03dbc7f2861e..1a78363c7f4a 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -208,7 +208,7 @@ static const struct intel_device_info intel_ironlake_d_info = { static const struct intel_device_info intel_ironlake_m_info = { GEN5_FEATURES, .platform = INTEL_IRONLAKE, - .is_mobile = 1, + .is_mobile = 1, .has_fbc = 1, }; #define GEN6_FEATURES \ -- cgit v1.2.3 From 1065467ed8e2601bf2d7018cf47c557ccbea3769 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 31 Mar 2017 21:00:56 +0300 Subject: drm/i915: Fix 90/270 rotated coordinates for FBC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The clipped src coordinates have already been rotated by 270 degrees for when the plane rotation is 90/270 degrees, hence the FBC code should no longer swap the width and height. Cc: stable@vger.kernel.org Cc: Tvrtko Ursulin Cc: Paulo Zanoni Fixes: b63a16f6cd89 ("drm/i915: Compute display surface offset in the plane check hook for SKL+") Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/20170331180056.14086-4-ville.syrjala@linux.intel.com Reviewed-by: Paulo Zanoni Tested-by: Tvrtko Ursulin Reviewed-by: Maarten Lankhorst (cherry picked from commit 73714c05df97d7527e7eaaa771472ef2ede46fa3) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_fbc.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index ded2add18b26..d93c58410bff 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -82,20 +82,10 @@ static unsigned int get_crtc_fence_y_offset(struct intel_crtc *crtc) static void intel_fbc_get_plane_source_size(struct intel_fbc_state_cache *cache, int *width, int *height) { - int w, h; - - if (drm_rotation_90_or_270(cache->plane.rotation)) { - w = cache->plane.src_h; - h = cache->plane.src_w; - } else { - w = cache->plane.src_w; - h = cache->plane.src_h; - } - if (width) - *width = w; + *width = cache->plane.src_w; if (height) - *height = h; + *height = cache->plane.src_h; } static int intel_fbc_calculate_cfb_size(struct drm_i915_private *dev_priv, @@ -746,6 +736,11 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc, cache->crtc.hsw_bdw_pixel_rate = crtc_state->pixel_rate; cache->plane.rotation = plane_state->base.rotation; + /* + * Src coordinates are already rotated by 270 degrees for + * the 90/270 degree plane rotation cases (to match the + * GTT mapping), hence no need to account for rotation here. + */ cache->plane.src_w = drm_rect_width(&plane_state->base.src) >> 16; cache->plane.src_h = drm_rect_height(&plane_state->base.src) >> 16; cache->plane.visible = plane_state->base.visible; -- cgit v1.2.3 From a41b816c174409417d91b4ceef0145c9f0bef67c Mon Sep 17 00:00:00 2001 From: Joseph Qi Date: Wed, 7 Jun 2017 11:36:14 +0800 Subject: blk-throttle: fix NULL pointer dereference in throtl_schedule_pending_timer I have encountered a NULL pointer dereference in throtl_schedule_pending_timer: [ 413.735396] BUG: unable to handle kernel NULL pointer dereference at 0000000000000038 [ 413.735535] IP: [] throtl_schedule_pending_timer+0x3f/0x210 [ 413.735643] PGD 22c8cf067 PUD 22cb34067 PMD 0 [ 413.735713] Oops: 0000 [#1] SMP ...... This is caused by the following case: blk_throtl_bio throtl_schedule_next_dispatch <= sq is top level one without parent throtl_schedule_pending_timer sq_to_tg(sq)->td->throtl_slice <= sq_to_tg(sq) returns NULL Fix it by using sq_to_td instead of sq_to_tg(sq)->td, which will always return a valid td. Fixes: 297e3d854784 ("blk-throttle: make throtl_slice tunable") Signed-off-by: Joseph Qi Reviewed-by: Shaohua Li Signed-off-by: Jens Axboe --- block/blk-throttle.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block/blk-throttle.c b/block/blk-throttle.c index fc13dd0c6e39..3b751f706c61 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -698,7 +698,7 @@ static void throtl_dequeue_tg(struct throtl_grp *tg) static void throtl_schedule_pending_timer(struct throtl_service_queue *sq, unsigned long expires) { - unsigned long max_expire = jiffies + 8 * sq_to_tg(sq)->td->throtl_slice; + unsigned long max_expire = jiffies + 8 * sq_to_td(sq)->throtl_slice; /* * Since we are adjusting the throttle limit dynamically, the sleep -- cgit v1.2.3 From 8604889f83381cac42b849acc6c420af6df9b35b Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Mon, 29 May 2017 16:15:52 +0200 Subject: drm/meson: Fix driver bind when only CVBS is available While introducing HDMI support, component matching on connectors node were bypassed since no driver would actually bind on the DT node. But when only a CVBS connector is present, only a single node is found in the graph, but ignored and a NULL match table is given to the component code. This code permits bypassing the components framework by binding directly the DRM driver when no components needs to be loaded. Fixes: a41e82e6c457 ("drm/meson: Add support for components") Signed-off-by: Neil Armstrong Signed-off-by: Sean Paul Link: http://patchwork.freedesktop.org/patch/msgid/1496067352-8733-1-git-send-email-narmstrong@baylibre.com --- drivers/gpu/drm/meson/meson_drv.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c index 75382f5f0fce..10b227d83e9a 100644 --- a/drivers/gpu/drm/meson/meson_drv.c +++ b/drivers/gpu/drm/meson/meson_drv.c @@ -152,7 +152,7 @@ static struct regmap_config meson_regmap_config = { .max_register = 0x1000, }; -static int meson_drv_bind(struct device *dev) +static int meson_drv_bind_master(struct device *dev, bool has_components) { struct platform_device *pdev = to_platform_device(dev); struct meson_drm *priv; @@ -233,10 +233,12 @@ static int meson_drv_bind(struct device *dev) if (ret) goto free_drm; - ret = component_bind_all(drm->dev, drm); - if (ret) { - dev_err(drm->dev, "Couldn't bind all components\n"); - goto free_drm; + if (has_components) { + ret = component_bind_all(drm->dev, drm); + if (ret) { + dev_err(drm->dev, "Couldn't bind all components\n"); + goto free_drm; + } } ret = meson_plane_create(priv); @@ -276,6 +278,11 @@ free_drm: return ret; } +static int meson_drv_bind(struct device *dev) +{ + return meson_drv_bind_master(dev, true); +} + static void meson_drv_unbind(struct device *dev) { struct drm_device *drm = dev_get_drvdata(dev); @@ -357,6 +364,9 @@ static int meson_drv_probe(struct platform_device *pdev) count += meson_probe_remote(pdev, &match, np, remote); } + if (count && !match) + return meson_drv_bind_master(&pdev->dev, false); + /* If some endpoints were found, initialize the nodes */ if (count) { dev_info(&pdev->dev, "Queued %d outputs on vpu\n", count); -- cgit v1.2.3 From 6679a90c4b0dc2563383df1fe0eb170736952a2e Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Tue, 6 Jun 2017 12:40:43 -0700 Subject: blk-throttle: set default latency baseline for harddisk hard disk IO latency varies a lot depending on spindle move. The latency range could be from several microseconds to several milliseconds. It's pretty hard to get the baseline latency used by io.low. We will use a different stragety here. The idea is only using IO with spindle move to determine if cgroup IO is in good state. For HD, if io latency is small (< 1ms), we ignore the IO. Such IO is likely from sequential IO, and is helpless to help determine if a cgroup's IO is impacted by other cgroups. With this, we only account IO with big latency. Then we can choose a hardcoded baseline latency for HD (4ms, which is typical IO latency with seek). With all these settings, the io.low latency works for both HD and SSD. Signed-off-by: Shaohua Li Signed-off-by: Jens Axboe --- block/blk-throttle.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/block/blk-throttle.c b/block/blk-throttle.c index 3b751f706c61..a7285bf2831c 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -27,6 +27,13 @@ static int throtl_quantum = 32; #define MIN_THROTL_IOPS (10) #define DFL_LATENCY_TARGET (-1L) #define DFL_IDLE_THRESHOLD (0) +#define DFL_HD_BASELINE_LATENCY (4000L) /* 4ms */ +#define LATENCY_FILTERED_SSD (0) +/* + * For HD, very small latency comes from sequential IO. Such IO is helpless to + * help determine if its IO is impacted by others, hence we ignore the IO + */ +#define LATENCY_FILTERED_HD (1000L) /* 1ms */ #define SKIP_LATENCY (((u64)1) << BLK_STAT_RES_SHIFT) @@ -212,6 +219,7 @@ struct throtl_data struct avg_latency_bucket avg_buckets[LATENCY_BUCKET_SIZE]; struct latency_bucket __percpu *latency_buckets; unsigned long last_calculate_time; + unsigned long filtered_latency; bool track_bio_latency; }; @@ -2281,7 +2289,7 @@ void blk_throtl_bio_endio(struct bio *bio) throtl_track_latency(tg->td, blk_stat_size(&bio->bi_issue_stat), bio_op(bio), lat); - if (tg->latency_target) { + if (tg->latency_target && lat >= tg->td->filtered_latency) { int bucket; unsigned int threshold; @@ -2417,14 +2425,20 @@ void blk_throtl_exit(struct request_queue *q) void blk_throtl_register_queue(struct request_queue *q) { struct throtl_data *td; + int i; td = q->td; BUG_ON(!td); - if (blk_queue_nonrot(q)) + if (blk_queue_nonrot(q)) { td->throtl_slice = DFL_THROTL_SLICE_SSD; - else + td->filtered_latency = LATENCY_FILTERED_SSD; + } else { td->throtl_slice = DFL_THROTL_SLICE_HD; + td->filtered_latency = LATENCY_FILTERED_HD; + for (i = 0; i < LATENCY_BUCKET_SIZE; i++) + td->avg_buckets[i].latency = DFL_HD_BASELINE_LATENCY; + } #ifndef CONFIG_BLK_DEV_THROTTLING_LOW /* if no low limit, use previous default */ td->throtl_slice = DFL_THROTL_SLICE_HD; -- cgit v1.2.3 From 47eb0c8b4d9eb6368941c6a9bb443f00847a46d7 Mon Sep 17 00:00:00 2001 From: Ulrik De Bie Date: Wed, 7 Jun 2017 10:30:57 -0700 Subject: Input: elantech - add Fujitsu Lifebook E546/E557 to force crc_enabled The Lifebook E546 and E557 touchpad were also not functioning and worked after running: echo "1" > /sys/devices/platform/i8042/serio2/crc_enabled Add them to the list of machines that need this workaround. Signed-off-by: Ulrik De Bie Reviewed-by: Arjan Opmeer Cc: stable@vger.kernel.org Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/elantech.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index e73d968023f7..f1fa1f172107 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -1118,8 +1118,10 @@ static int elantech_get_resolution_v4(struct psmouse *psmouse, * Asus UX32VD 0x361f02 00, 15, 0e clickpad * Avatar AVIU-145A2 0x361f00 ? clickpad * Fujitsu LIFEBOOK E544 0x470f00 d0, 12, 09 2 hw buttons + * Fujitsu LIFEBOOK E546 0x470f00 50, 12, 09 2 hw buttons * Fujitsu LIFEBOOK E547 0x470f00 50, 12, 09 2 hw buttons * Fujitsu LIFEBOOK E554 0x570f01 40, 14, 0c 2 hw buttons + * Fujitsu LIFEBOOK E557 0x570f01 40, 14, 0c 2 hw buttons * Fujitsu T725 0x470f01 05, 12, 09 2 hw buttons * Fujitsu H730 0x570f00 c0, 14, 0c 3 hw buttons (**) * Gigabyte U2442 0x450f01 58, 17, 0c 2 hw buttons @@ -1524,6 +1526,13 @@ static const struct dmi_system_id elantech_dmi_force_crc_enabled[] = { DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E544"), }, }, + { + /* Fujitsu LIFEBOOK E546 does not work with crc_enabled == 0 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), + DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E546"), + }, + }, { /* Fujitsu LIFEBOOK E547 does not work with crc_enabled == 0 */ .matches = { @@ -1545,6 +1554,13 @@ static const struct dmi_system_id elantech_dmi_force_crc_enabled[] = { DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E556"), }, }, + { + /* Fujitsu LIFEBOOK E557 does not work with crc_enabled == 0 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), + DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E557"), + }, + }, { /* Fujitsu LIFEBOOK U745 does not work with crc_enabled == 0 */ .matches = { -- cgit v1.2.3 From 92e75428ffc90e2a0321062379f883f3671cfebe Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Wed, 7 Jun 2017 19:01:32 -0400 Subject: random: use lockless method of accessing and updating f->reg_idx Linus pointed out that there is a much more efficient way of avoiding the problem that we were trying to address in commit 9dfa7bba35ac0: "fix race in drivers/char/random.c:get_reg()". Signed-off-by: Theodore Ts'o --- drivers/char/random.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/char/random.c b/drivers/char/random.c index a561f0c2f428..473ad34378f2 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1097,15 +1097,15 @@ static void add_interrupt_bench(cycles_t start) static __u32 get_reg(struct fast_pool *f, struct pt_regs *regs) { __u32 *ptr = (__u32 *) regs; - unsigned long flags; + unsigned int idx; if (regs == NULL) return 0; - local_irq_save(flags); - if (f->reg_idx >= sizeof(struct pt_regs) / sizeof(__u32)) - f->reg_idx = 0; - ptr += f->reg_idx++; - local_irq_restore(flags); + idx = READ_ONCE(f->reg_idx); + if (idx >= sizeof(struct pt_regs) / sizeof(__u32)) + idx = 0; + ptr += idx++; + WRITE_ONCE(f->reg_idx, idx); return *ptr; } -- cgit v1.2.3 From d89269a89ebb6a74512f3f40e89cd12017f60a75 Mon Sep 17 00:00:00 2001 From: SeongJae Park Date: Sun, 7 May 2017 19:36:42 +0900 Subject: perf probe: Fix examples section of documentation An example in perf-probe documentation for pattern of function name based probe addition is not providing example command for that case. This commit fixes the example to give appropriate example command. Signed-off-by: SeongJae Park Acked-by: Masami Hiramatsu Cc: Peter Zijlstra Cc: Taeung Song Fixes: ee391de876ae ("perf probe: Update perf probe document") Link: http://lkml.kernel.org/r/20170507103642.30560-1-sj38.park@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-probe.txt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt index e6c9902c6d82..165c2b1d4317 100644 --- a/tools/perf/Documentation/perf-probe.txt +++ b/tools/perf/Documentation/perf-probe.txt @@ -240,9 +240,13 @@ Add a probe on schedule() function 12th line with recording cpu local variable: or ./perf probe --add='schedule:12 cpu' - this will add one or more probes which has the name start with "schedule". +Add one or more probes which has the name start with "schedule". - Add probes on lines in schedule() function which calls update_rq_clock(). + ./perf probe schedule* + or + ./perf probe --add='schedule*' + +Add probes on lines in schedule() function which calls update_rq_clock(). ./perf probe 'schedule;update_rq_clock*' or -- cgit v1.2.3 From c76132dc5182776b98e946d674cb41c421661ea9 Mon Sep 17 00:00:00 2001 From: SeongJae Park Date: Tue, 30 May 2017 20:18:23 +0900 Subject: perf script: Fix outdated comment for perf-trace-python Script generated by the '--gen-script' option contains an outdated comment. It mentions a 'perf-trace-python' document while it has been renamed to 'perf-script-python'. Fix it. Signed-off-by: SeongJae Park Cc: Alexander Shishkin Cc: Peter Zijlstra Cc: Thomas Gleixner Fixes: 133dc4c39c57 ("perf: Rename 'perf trace' to 'perf script'") Link: http://lkml.kernel.org/r/20170530111827.21732-2-sj38.park@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/scripting-engines/trace-event-python.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index 9d92af7d0718..40de3cb40d21 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c @@ -1219,7 +1219,7 @@ static int python_generate_script(struct pevent *pevent, const char *outfile) fprintf(ofp, "# be retrieved using Python functions of the form " "common_*(context).\n"); - fprintf(ofp, "# See the perf-trace-python Documentation for the list " + fprintf(ofp, "# See the perf-script-python Documentation for the list " "of available functions.\n\n"); fprintf(ofp, "import os\n"); -- cgit v1.2.3 From 34d4453dac257be53c21abf2f713c992fb692b5c Mon Sep 17 00:00:00 2001 From: SeongJae Park Date: Tue, 30 May 2017 20:18:24 +0900 Subject: perf script: Fix documentation errors This commit fixes two errors in documents for perf-script-python and perf-script-perl as below: - /sys/kernel/debug/tracing events -> /sys/kernel/debug/tracing/events/ - trace_handled -> trace_unhandled Signed-off-by: SeongJae Park Cc: Alexander Shishkin Cc: Frederic Weisbecker Cc: Peter Zijlstra Cc: Tom Zanussi Fixes: cff68e582237 ("perf/scripts: Add perf-trace-python Documentation") Link: http://lkml.kernel.org/r/20170530111827.21732-3-sj38.park@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-script-perl.txt | 2 +- tools/perf/Documentation/perf-script-python.txt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/perf/Documentation/perf-script-perl.txt b/tools/perf/Documentation/perf-script-perl.txt index dfbb506d2c34..142606c0ec9c 100644 --- a/tools/perf/Documentation/perf-script-perl.txt +++ b/tools/perf/Documentation/perf-script-perl.txt @@ -39,7 +39,7 @@ EVENT HANDLERS When perf script is invoked using a trace script, a user-defined 'handler function' is called for each event in the trace. If there's no handler function defined for a given event type, the event is -ignored (or passed to a 'trace_handled' function, see below) and the +ignored (or passed to a 'trace_unhandled' function, see below) and the next event is processed. Most of the event's field values are passed as arguments to the diff --git a/tools/perf/Documentation/perf-script-python.txt b/tools/perf/Documentation/perf-script-python.txt index 54acba221558..087b87c956ba 100644 --- a/tools/perf/Documentation/perf-script-python.txt +++ b/tools/perf/Documentation/perf-script-python.txt @@ -321,7 +321,7 @@ So those are the essential steps in writing and running a script. The process can be generalized to any tracepoint or set of tracepoints you're interested in - basically find the tracepoint(s) you're interested in by looking at the list of available events shown by -'perf list' and/or look in /sys/kernel/debug/tracing events for +'perf list' and/or look in /sys/kernel/debug/tracing/events/ for detailed event and field info, record the corresponding trace data using 'perf record', passing it the list of interesting events, generate a skeleton script using 'perf script -g python' and modify the @@ -437,7 +437,7 @@ EVENT HANDLERS When perf script is invoked using a trace script, a user-defined 'handler function' is called for each event in the trace. If there's no handler function defined for a given event type, the event is -ignored (or passed to a 'trace_handled' function, see below) and the +ignored (or passed to a 'trace_unhandled' function, see below) and the next event is processed. Most of the event's field values are passed as arguments to the -- cgit v1.2.3 From 26ddb8722df865aa67fbe459107d2f3f8e5c6829 Mon Sep 17 00:00:00 2001 From: SeongJae Park Date: Tue, 30 May 2017 20:18:26 +0900 Subject: perf script python: Fix wrong code snippets in documentation This commit fixes wrong code snippets for trace_begin() and trace_end() function example definition. Signed-off-by: SeongJae Park Cc: Alexander Shishkin Cc: Frederic Weisbecker Cc: Peter Zijlstra Cc: Tom Zanussi Fixes: cff68e582237 ("perf/scripts: Add perf-trace-python Documentation") Link: http://lkml.kernel.org/r/20170530111827.21732-5-sj38.park@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-script-python.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/perf/Documentation/perf-script-python.txt b/tools/perf/Documentation/perf-script-python.txt index 087b87c956ba..bad6e93cceff 100644 --- a/tools/perf/Documentation/perf-script-python.txt +++ b/tools/perf/Documentation/perf-script-python.txt @@ -532,7 +532,7 @@ can implement a set of optional functions: gives scripts a chance to do setup tasks: ---- -def trace_begin: +def trace_begin(): pass ---- @@ -541,7 +541,7 @@ def trace_begin: as display results: ---- -def trace_end: +def trace_end(): pass ---- -- cgit v1.2.3 From 1bf8d5a4a5da19b1f6e7958fe67db4118fa7a1c1 Mon Sep 17 00:00:00 2001 From: SeongJae Park Date: Tue, 30 May 2017 20:18:27 +0900 Subject: perf script python: Updated trace_unhandled() signature Default function signature of trace_unhandled() got changed to include a field dict, but its documentation, perf-script-python.txt has not been updated. Fix it. Signed-off-by: SeongJae Park Cc: Alexander Shishkin Cc: Peter Zijlstra Cc: Pierre Tardy Fixes: c02514850d67 ("perf scripts python: Give field dict to unhandled callback") Link: http://lkml.kernel.org/r/20170530111827.21732-6-sj38.park@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-script-python.txt | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/tools/perf/Documentation/perf-script-python.txt b/tools/perf/Documentation/perf-script-python.txt index bad6e93cceff..378783fe2b6b 100644 --- a/tools/perf/Documentation/perf-script-python.txt +++ b/tools/perf/Documentation/perf-script-python.txt @@ -149,10 +149,8 @@ def raw_syscalls__sys_enter(event_name, context, common_cpu, print "id=%d, args=%s\n" % \ (id, args), -def trace_unhandled(event_name, context, common_cpu, common_secs, common_nsecs, - common_pid, common_comm): - print_header(event_name, common_cpu, common_secs, common_nsecs, - common_pid, common_comm) +def trace_unhandled(event_name, context, event_fields_dict): + print ' '.join(['%s=%s'%(k,str(v))for k,v in sorted(event_fields_dict.items())]) def print_header(event_name, cpu, secs, nsecs, pid, comm): print "%-20s %5u %05u.%09u %8u %-20s " % \ @@ -550,8 +548,7 @@ def trace_end(): of common arguments are passed into it: ---- -def trace_unhandled(event_name, context, common_cpu, common_secs, - common_nsecs, common_pid, common_comm): +def trace_unhandled(event_name, context, event_fields_dict): pass ---- -- cgit v1.2.3 From 14fc42fa1b3e7ea5160c84d0e686a3a0c1ffe619 Mon Sep 17 00:00:00 2001 From: SeongJae Park Date: Tue, 30 May 2017 20:18:25 +0900 Subject: perf script python: Remove dups in documentation examples Few shell command examples in perf-script-python.txt has few nitpicks include: - tools/perf/scripts/python directory listing command is unnecessarily repeated. - few examples contain additional information in command prompt unnecessarily and inconsistently. This commit fixes them to enhance readability of the document. Signed-off-by: SeongJae Park Cc: Alexander Shishkin Cc: Frederic Weisbecker Cc: Peter Zijlstra Cc: Tom Zanussi Fixes: cff68e582237 ("perf/scripts: Add perf-trace-python Documentation") Link: http://lkml.kernel.org/r/20170530111827.21732-4-sj38.park@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-script-python.txt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tools/perf/Documentation/perf-script-python.txt b/tools/perf/Documentation/perf-script-python.txt index 378783fe2b6b..51ec2d20068a 100644 --- a/tools/perf/Documentation/perf-script-python.txt +++ b/tools/perf/Documentation/perf-script-python.txt @@ -332,7 +332,7 @@ right place, you can have your script listed alongside the other scripts listed by the 'perf script -l' command e.g.: ---- -root@tropicana:~# perf script -l +# perf script -l List of available trace scripts: wakeup-latency system-wide min/max/avg wakeup latency rw-by-file r/w activity for a program, by file @@ -381,8 +381,6 @@ source tree: ---- # ls -al kernel-source/tools/perf/scripts/python - -root@tropicana:/home/trz/src/tip# ls -al tools/perf/scripts/python total 32 drwxr-xr-x 4 trz trz 4096 2010-01-26 22:30 . drwxr-xr-x 4 trz trz 4096 2010-01-26 22:29 .. @@ -397,7 +395,7 @@ otherwise your script won't show up at run-time), 'perf script -l' should show a new entry for your script: ---- -root@tropicana:~# perf script -l +# perf script -l List of available trace scripts: wakeup-latency system-wide min/max/avg wakeup latency rw-by-file r/w activity for a program, by file -- cgit v1.2.3 From b169c13de473a85b3c859bb36216a4cb5f00a54a Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Wed, 7 Jun 2017 19:45:31 -0400 Subject: random: invalidate batched entropy after crng init It's possible that get_random_{u32,u64} is used before the crng has initialized, in which case, its output might not be cryptographically secure. For this problem, directly, this patch set is introducing the *_wait variety of functions, but even with that, there's a subtle issue: what happens to our batched entropy that was generated before initialization. Prior to this commit, it'd stick around, supplying bad numbers. After this commit, we force the entropy to be re-extracted after each phase of the crng has initialized. In order to avoid a race condition with the position counter, we introduce a simple rwlock for this invalidation. Since it's only during this awkward transition period, after things are all set up, we stop using it, so that it doesn't have an impact on performance. Signed-off-by: Jason A. Donenfeld Cc: Greg Kroah-Hartman Signed-off-by: Theodore Ts'o Cc: stable@vger.kernel.org # v4.11+ --- drivers/char/random.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/drivers/char/random.c b/drivers/char/random.c index 473ad34378f2..e870f329db88 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1,6 +1,9 @@ /* * random.c -- A strong random number generator * + * Copyright (C) 2017 Jason A. Donenfeld . All + * Rights Reserved. + * * Copyright Matt Mackall , 2003, 2004, 2005 * * Copyright Theodore Ts'o, 1994, 1995, 1996, 1997, 1998, 1999. All @@ -762,6 +765,8 @@ static DECLARE_WAIT_QUEUE_HEAD(crng_init_wait); static struct crng_state **crng_node_pool __read_mostly; #endif +static void invalidate_batched_entropy(void); + static void crng_initialize(struct crng_state *crng) { int i; @@ -799,6 +804,7 @@ static int crng_fast_load(const char *cp, size_t len) cp++; crng_init_cnt++; len--; } if (crng_init_cnt >= CRNG_INIT_CNT_THRESH) { + invalidate_batched_entropy(); crng_init = 1; wake_up_interruptible(&crng_init_wait); pr_notice("random: fast init done\n"); @@ -836,6 +842,7 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r) memzero_explicit(&buf, sizeof(buf)); crng->init_time = jiffies; if (crng == &primary_crng && crng_init < 2) { + invalidate_batched_entropy(); crng_init = 2; process_random_ready_list(); wake_up_interruptible(&crng_init_wait); @@ -2023,6 +2030,7 @@ struct batched_entropy { }; unsigned int position; }; +static rwlock_t batched_entropy_reset_lock = __RW_LOCK_UNLOCKED(batched_entropy_reset_lock); /* * Get a random word for internal kernel use only. The quality of the random @@ -2033,6 +2041,8 @@ static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_u64); u64 get_random_u64(void) { u64 ret; + bool use_lock = crng_init < 2; + unsigned long flags; struct batched_entropy *batch; #if BITS_PER_LONG == 64 @@ -2045,11 +2055,15 @@ u64 get_random_u64(void) #endif batch = &get_cpu_var(batched_entropy_u64); + if (use_lock) + read_lock_irqsave(&batched_entropy_reset_lock, flags); if (batch->position % ARRAY_SIZE(batch->entropy_u64) == 0) { extract_crng((u8 *)batch->entropy_u64); batch->position = 0; } ret = batch->entropy_u64[batch->position++]; + if (use_lock) + read_unlock_irqrestore(&batched_entropy_reset_lock, flags); put_cpu_var(batched_entropy_u64); return ret; } @@ -2059,22 +2073,45 @@ static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_u32); u32 get_random_u32(void) { u32 ret; + bool use_lock = crng_init < 2; + unsigned long flags; struct batched_entropy *batch; if (arch_get_random_int(&ret)) return ret; batch = &get_cpu_var(batched_entropy_u32); + if (use_lock) + read_lock_irqsave(&batched_entropy_reset_lock, flags); if (batch->position % ARRAY_SIZE(batch->entropy_u32) == 0) { extract_crng((u8 *)batch->entropy_u32); batch->position = 0; } ret = batch->entropy_u32[batch->position++]; + if (use_lock) + read_unlock_irqrestore(&batched_entropy_reset_lock, flags); put_cpu_var(batched_entropy_u32); return ret; } EXPORT_SYMBOL(get_random_u32); +/* It's important to invalidate all potential batched entropy that might + * be stored before the crng is initialized, which we can do lazily by + * simply resetting the counter to zero so that it's re-extracted on the + * next usage. */ +static void invalidate_batched_entropy(void) +{ + int cpu; + unsigned long flags; + + write_lock_irqsave(&batched_entropy_reset_lock, flags); + for_each_possible_cpu (cpu) { + per_cpu_ptr(&batched_entropy_u32, cpu)->position = 0; + per_cpu_ptr(&batched_entropy_u64, cpu)->position = 0; + } + write_unlock_irqrestore(&batched_entropy_reset_lock, flags); +} + /** * randomize_page - Generate a random, page aligned address * @start: The smallest acceptable address the caller will take. -- cgit v1.2.3 From 462c5a826eba39fad819ccef916f9943ff42bf0d Mon Sep 17 00:00:00 2001 From: Jessica Yu Date: Wed, 7 Jun 2017 23:52:36 -0700 Subject: MAINTAINERS: update email address for Jessica Yu I will be traveling in the upcoming months and it'll be much easier for me to access my kernel.org email rather than my work one. Change my email address in the MAINTAINERS file from jeyu@redhat.com to jeyu@kernel.org. Signed-off-by: Jessica Yu --- MAINTAINERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 053c3bdd1fe5..4c3051018744 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7707,7 +7707,7 @@ F: drivers/platform/x86/hp_accel.c LIVE PATCHING M: Josh Poimboeuf -M: Jessica Yu +M: Jessica Yu M: Jiri Kosina M: Miroslav Benes R: Petr Mladek @@ -8588,7 +8588,7 @@ S: Maintained F: drivers/media/dvb-frontends/mn88473* MODULE SUPPORT -M: Jessica Yu +M: Jessica Yu M: Rusty Russell T: git git://git.kernel.org/pub/scm/linux/kernel/git/jeyu/linux.git modules-next S: Maintained -- cgit v1.2.3 From 5b0bc9ac2ce4881ee318a21f31140584ce4dbdad Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Wed, 7 Jun 2017 11:58:19 +0200 Subject: x86/microcode/intel: Clear patch pointer before jettisoning the initrd During early boot, load_ucode_intel_ap() uses __load_ucode_intel() to obtain a pointer to the relevant microcode patch (embedded in the initrd), and stores this value in 'intel_ucode_patch' to speed up the microcode patch application for subsequent CPUs. On resuming from suspend-to-RAM, however, load_ucode_ap() calls load_ucode_intel_ap() for each non-boot-CPU. By then the initramfs is long gone so the pointer stored in 'intel_ucode_patch' no longer points to a valid microcode patch. Clear that pointer so that we effectively fall back to the CPU hotplug notifier callbacks to update the microcode. Signed-off-by: Dominik Brodowski [ Edit and massage commit message. ] Signed-off-by: Borislav Petkov Cc: # 4.10.. Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/20170607095819.9754-1-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/microcode/intel.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c index afdfd237b59f..f522415bf9e5 100644 --- a/arch/x86/kernel/cpu/microcode/intel.c +++ b/arch/x86/kernel/cpu/microcode/intel.c @@ -619,6 +619,9 @@ int __init save_microcode_in_initrd_intel(void) show_saved_mc(); + /* initrd is going away, clear patch ptr. */ + intel_ucode_patch = NULL; + return 0; } -- cgit v1.2.3 From cc1582c231ea041fbc68861dfaf957eaf902b829 Mon Sep 17 00:00:00 2001 From: Jin Yao Date: Thu, 25 May 2017 18:09:07 +0800 Subject: perf/core: Drop kernel samples even though :u is specified When doing sampling, for example: perf record -e cycles:u ... On workloads that do a lot of kernel entry/exits we see kernel samples, even though :u is specified. This is due to skid existing. This might be a security issue because it can leak kernel addresses even though kernel sampling support is disabled. The patch drops the kernel samples if exclude_kernel is specified. For example, test on Haswell desktop: perf record -e cycles:u perf report --stdio Before patch applied: 99.77% mgen mgen [.] buf_read 0.20% mgen mgen [.] rand_buf_init 0.01% mgen [kernel.vmlinux] [k] apic_timer_interrupt 0.00% mgen mgen [.] last_free_elem 0.00% mgen libc-2.23.so [.] __random_r 0.00% mgen libc-2.23.so [.] _int_malloc 0.00% mgen mgen [.] rand_array_init 0.00% mgen [kernel.vmlinux] [k] page_fault 0.00% mgen libc-2.23.so [.] __random 0.00% mgen libc-2.23.so [.] __strcasestr 0.00% mgen ld-2.23.so [.] strcmp 0.00% mgen ld-2.23.so [.] _dl_start 0.00% mgen libc-2.23.so [.] sched_setaffinity@@GLIBC_2.3.4 0.00% mgen ld-2.23.so [.] _start We can see kernel symbols apic_timer_interrupt and page_fault. After patch applied: 99.79% mgen mgen [.] buf_read 0.19% mgen mgen [.] rand_buf_init 0.00% mgen libc-2.23.so [.] __random_r 0.00% mgen mgen [.] rand_array_init 0.00% mgen mgen [.] last_free_elem 0.00% mgen libc-2.23.so [.] vfprintf 0.00% mgen libc-2.23.so [.] rand 0.00% mgen libc-2.23.so [.] __random 0.00% mgen libc-2.23.so [.] _int_malloc 0.00% mgen libc-2.23.so [.] _IO_doallocbuf 0.00% mgen ld-2.23.so [.] do_lookup_x 0.00% mgen ld-2.23.so [.] open_verify.constprop.7 0.00% mgen ld-2.23.so [.] _dl_important_hwcaps 0.00% mgen libc-2.23.so [.] sched_setaffinity@@GLIBC_2.3.4 0.00% mgen ld-2.23.so [.] _start There are only userspace symbols. Signed-off-by: Jin Yao Signed-off-by: Peter Zijlstra (Intel) Cc: Cc: Alexander Shishkin Cc: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: Linus Torvalds Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Thomas Gleixner Cc: Vince Weaver Cc: acme@kernel.org Cc: jolsa@kernel.org Cc: kan.liang@intel.com Cc: mark.rutland@arm.com Cc: will.deacon@arm.com Cc: yao.jin@intel.com Link: http://lkml.kernel.org/r/1495706947-3744-1-git-send-email-yao.jin@linux.intel.com Signed-off-by: Ingo Molnar --- kernel/events/core.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/kernel/events/core.c b/kernel/events/core.c index 6e75a5c9412d..6c4e523dc1e2 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -7316,6 +7316,21 @@ int perf_event_account_interrupt(struct perf_event *event) return __perf_event_account_interrupt(event, 1); } +static bool sample_is_allowed(struct perf_event *event, struct pt_regs *regs) +{ + /* + * Due to interrupt latency (AKA "skid"), we may enter the + * kernel before taking an overflow, even if the PMU is only + * counting user events. + * To avoid leaking information to userspace, we must always + * reject kernel samples when exclude_kernel is set. + */ + if (event->attr.exclude_kernel && !user_mode(regs)) + return false; + + return true; +} + /* * Generic event overflow handling, sampling. */ @@ -7336,6 +7351,12 @@ static int __perf_event_overflow(struct perf_event *event, ret = __perf_event_account_interrupt(event, throttle); + /* + * For security, drop the skid kernel samples if necessary. + */ + if (!sample_is_allowed(event, regs)) + return ret; + /* * XXX event_limit might not quite work as expected on inherited * events -- cgit v1.2.3 From dac8bbbae1d0ccba96402d25deeed3a2e87992c6 Mon Sep 17 00:00:00 2001 From: Petr Mladek Date: Thu, 8 Jun 2017 12:01:30 +0200 Subject: Revert "printk: fix double printing with earlycon" This reverts commit cf39bf58afdaabc0b86f141630fb3fd18190294e. The commit regression to users that define both console=ttyS1 and console=ttyS0 on the command line, see https://lkml.kernel.org/r/20170509082915.GA13236@bistromath.localdomain The kernel log messages always appeared only on one serial port. It is even documented in Documentation/admin-guide/serial-console.rst: "Note that you can only define one console per device type (serial, video)." The above mentioned commit changed the order in which the command line parameters are searched. As a result, the kernel log messages go to the last mentioned ttyS* instead of the first one. We long thought that using two console=ttyS* on the command line did not make sense. But then we realized that console= parameters were handled also by systemd, see http://0pointer.de/blog/projects/serial-console.html "By default systemd will instantiate one serial-getty@.service on the main kernel console, if it is not a virtual terminal." where "[4] If multiple kernel consoles are used simultaneously, the main console is the one listed first in /sys/class/tty/console/active, which is the last one listed on the kernel command line." This puts the original report into another light. The system is running in qemu. The first serial port is used to store the messages into a file. The second one is used to login to the system via a socket. It depends on systemd and the historic kernel behavior. By other words, systemd causes that it makes sense to define both console=ttyS1 console=ttyS0 on the command line. The kernel fix caused regression related to userspace (systemd) and need to be reverted. In addition, it went out that the fix helped only partially. The messages still were duplicated when the boot console was removed early by late_initcall(printk_late_init). Then the entire log was replayed when the same console was registered as a normal one. Link: 20170606160339.GC7604@pathway.suse.cz Cc: Aleksey Makarov Cc: Sabrina Dubroca Cc: Sudeep Holla Cc: Greg Kroah-Hartman Cc: Peter Hurley Cc: Jiri Slaby Cc: Robin Murphy , Cc: Steven Rostedt Cc: "Nair, Jayachandran" Cc: linux-serial@vger.kernel.org Cc: linux-kernel@vger.kernel.org Reported-by: Sabrina Dubroca Acked-by: Sergey Senozhatsky Signed-off-by: Petr Mladek --- kernel/printk/printk.c | 46 ++++++++++------------------------------------ 1 file changed, 10 insertions(+), 36 deletions(-) diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index 779479ac9f57..9dbceb76e6bc 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -269,7 +269,6 @@ static struct console *exclusive_console; #define MAX_CMDLINECONSOLES 8 static struct console_cmdline console_cmdline[MAX_CMDLINECONSOLES]; -static int console_cmdline_cnt; static int preferred_console = -1; int console_set_on_cmdline; @@ -1906,25 +1905,12 @@ static int __add_preferred_console(char *name, int idx, char *options, * See if this tty is not yet registered, and * if we have a slot free. */ - for (i = 0, c = console_cmdline; i < console_cmdline_cnt; i++, c++) { + for (i = 0, c = console_cmdline; + i < MAX_CMDLINECONSOLES && c->name[0]; + i++, c++) { if (strcmp(c->name, name) == 0 && c->index == idx) { - if (brl_options) - return 0; - - /* - * Maintain an invariant that will help to find if - * the matching console is preferred, see - * register_console(): - * - * The last non-braille console is always - * the preferred one. - */ - if (i != console_cmdline_cnt - 1) - swap(console_cmdline[i], - console_cmdline[console_cmdline_cnt - 1]); - - preferred_console = console_cmdline_cnt - 1; - + if (!brl_options) + preferred_console = i; return 0; } } @@ -1937,7 +1923,6 @@ static int __add_preferred_console(char *name, int idx, char *options, braille_set_options(c, brl_options); c->index = idx; - console_cmdline_cnt++; return 0; } /* @@ -2477,23 +2462,12 @@ void register_console(struct console *newcon) } /* - * See if this console matches one we selected on the command line. - * - * There may be several entries in the console_cmdline array matching - * with the same console, one with newcon->match(), another by - * name/index: - * - * pl011,mmio,0x87e024000000,115200 -- added from SPCR - * ttyAMA0 -- added from command line - * - * Traverse the console_cmdline array in reverse order to be - * sure that if this console is preferred then it will be the first - * matching entry. We use the invariant that is maintained in - * __add_preferred_console(). + * See if this console matches one we selected on + * the command line. */ - for (i = console_cmdline_cnt - 1; i >= 0; i--) { - c = console_cmdline + i; - + for (i = 0, c = console_cmdline; + i < MAX_CMDLINECONSOLES && c->name[0]; + i++, c++) { if (!newcon->match || newcon->match(newcon, c->name, c->index, c->options) != 0) { /* default matching */ -- cgit v1.2.3 From cec422c11caeeccae709e9942058b6b644ce434c Mon Sep 17 00:00:00 2001 From: Frederic Barrat Date: Tue, 6 Jun 2017 11:43:41 +0200 Subject: cxl: Fix error path on bad ioctl Fix error path if we can't copy user structure on CXL_IOCTL_START_WORK ioctl. We shouldn't unlock the context status mutex as it was not locked (yet). Fixes: 0712dc7e73e5 ("cxl: Fix issues when unmapping contexts") Cc: stable@vger.kernel.org # v3.19+ Signed-off-by: Frederic Barrat Reviewed-by: Vaibhav Jain Reviewed-by: Andrew Donnellan Signed-off-by: Michael Ellerman --- drivers/misc/cxl/file.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/misc/cxl/file.c b/drivers/misc/cxl/file.c index 17b433f1ce23..0761271d68c5 100644 --- a/drivers/misc/cxl/file.c +++ b/drivers/misc/cxl/file.c @@ -159,11 +159,8 @@ static long afu_ioctl_start_work(struct cxl_context *ctx, /* Do this outside the status_mutex to avoid a circular dependency with * the locking in cxl_mmap_fault() */ - if (copy_from_user(&work, uwork, - sizeof(struct cxl_ioctl_start_work))) { - rc = -EFAULT; - goto out; - } + if (copy_from_user(&work, uwork, sizeof(work))) + return -EFAULT; mutex_lock(&ctx->status_mutex); if (ctx->status != OPENED) { -- cgit v1.2.3 From 92d9dfda8b547cc292af27e11e11c9eff3bb574f Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Thu, 1 Jun 2017 20:05:04 +0530 Subject: powerpc/mm/4k: Limit 4k page size config to 64TB virtual address space Supporting 512TB requires us to do a order 3 allocation for level 1 page table (pgd). This results in page allocation failures with certain workloads. For now limit 4k linux page size config to 64TB. Fixes: f6eedbba7a26 ("powerpc/mm/hash: Increase VA range to 128TB") Reported-by: Hugh Dickins Signed-off-by: Aneesh Kumar K.V Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/book3s/64/hash-4k.h | 2 +- arch/powerpc/include/asm/processor.h | 25 ++++++++++++------------- arch/powerpc/kernel/setup-common.c | 2 +- arch/powerpc/mm/mmu_context_book3s64.c | 2 +- 4 files changed, 15 insertions(+), 16 deletions(-) diff --git a/arch/powerpc/include/asm/book3s/64/hash-4k.h b/arch/powerpc/include/asm/book3s/64/hash-4k.h index b4b5e6b671ca..0c4e470571ca 100644 --- a/arch/powerpc/include/asm/book3s/64/hash-4k.h +++ b/arch/powerpc/include/asm/book3s/64/hash-4k.h @@ -8,7 +8,7 @@ #define H_PTE_INDEX_SIZE 9 #define H_PMD_INDEX_SIZE 7 #define H_PUD_INDEX_SIZE 9 -#define H_PGD_INDEX_SIZE 12 +#define H_PGD_INDEX_SIZE 9 #ifndef __ASSEMBLY__ #define H_PTE_TABLE_SIZE (sizeof(pte_t) << H_PTE_INDEX_SIZE) diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h index a2123f291ab0..bb99b651085a 100644 --- a/arch/powerpc/include/asm/processor.h +++ b/arch/powerpc/include/asm/processor.h @@ -110,13 +110,18 @@ void release_thread(struct task_struct *); #define TASK_SIZE_128TB (0x0000800000000000UL) #define TASK_SIZE_512TB (0x0002000000000000UL) -#ifdef CONFIG_PPC_BOOK3S_64 +/* + * For now 512TB is only supported with book3s and 64K linux page size. + */ +#if defined(CONFIG_PPC_BOOK3S_64) && defined(CONFIG_PPC_64K_PAGES) /* * Max value currently used: */ -#define TASK_SIZE_USER64 TASK_SIZE_512TB +#define TASK_SIZE_USER64 TASK_SIZE_512TB +#define DEFAULT_MAP_WINDOW_USER64 TASK_SIZE_128TB #else -#define TASK_SIZE_USER64 TASK_SIZE_64TB +#define TASK_SIZE_USER64 TASK_SIZE_64TB +#define DEFAULT_MAP_WINDOW_USER64 TASK_SIZE_64TB #endif /* @@ -132,7 +137,7 @@ void release_thread(struct task_struct *); * space during mmap's. */ #define TASK_UNMAPPED_BASE_USER32 (PAGE_ALIGN(TASK_SIZE_USER32 / 4)) -#define TASK_UNMAPPED_BASE_USER64 (PAGE_ALIGN(TASK_SIZE_128TB / 4)) +#define TASK_UNMAPPED_BASE_USER64 (PAGE_ALIGN(DEFAULT_MAP_WINDOW_USER64 / 4)) #define TASK_UNMAPPED_BASE ((is_32bit_task()) ? \ TASK_UNMAPPED_BASE_USER32 : TASK_UNMAPPED_BASE_USER64 ) @@ -143,21 +148,15 @@ void release_thread(struct task_struct *); * with 128TB and conditionally enable upto 512TB */ #ifdef CONFIG_PPC_BOOK3S_64 -#define DEFAULT_MAP_WINDOW ((is_32bit_task()) ? \ - TASK_SIZE_USER32 : TASK_SIZE_128TB) +#define DEFAULT_MAP_WINDOW ((is_32bit_task()) ? \ + TASK_SIZE_USER32 : DEFAULT_MAP_WINDOW_USER64) #else #define DEFAULT_MAP_WINDOW TASK_SIZE #endif #ifdef __powerpc64__ -#ifdef CONFIG_PPC_BOOK3S_64 -/* Limit stack to 128TB */ -#define STACK_TOP_USER64 TASK_SIZE_128TB -#else -#define STACK_TOP_USER64 TASK_SIZE_USER64 -#endif - +#define STACK_TOP_USER64 DEFAULT_MAP_WINDOW_USER64 #define STACK_TOP_USER32 TASK_SIZE_USER32 #define STACK_TOP (is_32bit_task() ? \ diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index 71dcda91755d..857129acf960 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c @@ -928,7 +928,7 @@ void __init setup_arch(char **cmdline_p) #ifdef CONFIG_PPC_MM_SLICES #ifdef CONFIG_PPC64 - init_mm.context.addr_limit = TASK_SIZE_128TB; + init_mm.context.addr_limit = DEFAULT_MAP_WINDOW_USER64; #else #error "context.addr_limit not initialized." #endif diff --git a/arch/powerpc/mm/mmu_context_book3s64.c b/arch/powerpc/mm/mmu_context_book3s64.c index c6dca2ae78ef..a3edf813d455 100644 --- a/arch/powerpc/mm/mmu_context_book3s64.c +++ b/arch/powerpc/mm/mmu_context_book3s64.c @@ -99,7 +99,7 @@ static int hash__init_new_context(struct mm_struct *mm) * mm->context.addr_limit. Default to max task size so that we copy the * default values to paca which will help us to handle slb miss early. */ - mm->context.addr_limit = TASK_SIZE_128TB; + mm->context.addr_limit = DEFAULT_MAP_WINDOW_USER64; /* * The old code would re-promote on fork, we don't do that when using -- cgit v1.2.3 From c6ee9619e2edd9912316f7e2eaf9ffa14fafe9f9 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 8 Jun 2017 16:29:59 +1000 Subject: powerpc/book3s64: Move PPC_DT_CPU_FTRs and enable it by default The PPC_DT_CPU_FTRs is a bit misplaced in menuconfig, it shows up with other general kernel options. It's really more at home in the "Platform Support" section, so move it there. Also enable it by default, for Book3s 64. It does mostly nothing unless the device tree properties are found, and we will want it enabled eventually in distro kernels, so turn it on to start getting more testing. Fixes: 5a61ef74f269 ("powerpc/64s: Support new device tree binding for discovering CPU features") Signed-off-by: Michael Ellerman --- arch/powerpc/Kconfig | 11 ----------- arch/powerpc/platforms/Kconfig | 11 +++++++++++ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 4a4a05afcaf7..964da1891ea9 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -380,17 +380,6 @@ source "arch/powerpc/platforms/Kconfig" menu "Kernel options" -config PPC_DT_CPU_FTRS - bool "Device-tree based CPU feature discovery & setup" - depends on PPC_BOOK3S_64 - default n - help - This enables code to use a new device tree binding for describing CPU - compatibility and features. Saying Y here will attempt to use the new - binding if the firmware provides it. Currently only the skiboot - firmware provides this binding. - If you're not sure say Y. - config HIGHMEM bool "High memory support" depends on PPC32 diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig index 33244e3d9375..4fd64d3f5c44 100644 --- a/arch/powerpc/platforms/Kconfig +++ b/arch/powerpc/platforms/Kconfig @@ -59,6 +59,17 @@ config PPC_OF_BOOT_TRAMPOLINE In case of doubt, say Y +config PPC_DT_CPU_FTRS + bool "Device-tree based CPU feature discovery & setup" + depends on PPC_BOOK3S_64 + default y + help + This enables code to use a new device tree binding for describing CPU + compatibility and features. Saying Y here will attempt to use the new + binding if the firmware provides it. Currently only the skiboot + firmware provides this binding. + If you're not sure say Y. + config UDBG_RTAS_CONSOLE bool "RTAS based debug console" depends on PPC_RTAS -- cgit v1.2.3 From a3641631d14571242eec0d30c9faa786cbf52d44 Mon Sep 17 00:00:00 2001 From: Wanpeng Li Date: Thu, 8 Jun 2017 01:22:07 -0700 Subject: KVM: cpuid: Fix read/write out-of-bounds vulnerability in cpuid emulation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If "i" is the last element in the vcpu->arch.cpuid_entries[] array, it potentially can be exploited the vulnerability. this will out-of-bounds read and write. Luckily, the effect is small: /* when no next entry is found, the current entry[i] is reselected */ for (j = i + 1; ; j = (j + 1) % nent) { struct kvm_cpuid_entry2 *ej = &vcpu->arch.cpuid_entries[j]; if (ej->function == e->function) { It reads ej->maxphyaddr, which is user controlled. However... ej->flags |= KVM_CPUID_FLAG_STATE_READ_NEXT; After cpuid_entries there is int maxphyaddr; struct x86_emulate_ctxt emulate_ctxt; /* 16-byte aligned */ So we have: - cpuid_entries at offset 1B50 (6992) - maxphyaddr at offset 27D0 (6992 + 3200 = 10192) - padding at 27D4...27DF - emulate_ctxt at 27E0 And it writes in the padding. Pfew, writing the ops field of emulate_ctxt would have been much worse. This patch fixes it by modding the index to avoid the out-of-bounds access. Worst case, i == j and ej->function == e->function, the loop can bail out. Reported-by: Moguofang Cc: Paolo Bonzini Cc: Radim Krčmář Cc: Guofang Mo Cc: stable@vger.kernel.org Signed-off-by: Wanpeng Li Signed-off-by: Paolo Bonzini --- arch/x86/kvm/cpuid.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index a181ae76c71c..59ca2eea522c 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -780,18 +780,20 @@ out: static int move_to_next_stateful_cpuid_entry(struct kvm_vcpu *vcpu, int i) { struct kvm_cpuid_entry2 *e = &vcpu->arch.cpuid_entries[i]; - int j, nent = vcpu->arch.cpuid_nent; + struct kvm_cpuid_entry2 *ej; + int j = i; + int nent = vcpu->arch.cpuid_nent; e->flags &= ~KVM_CPUID_FLAG_STATE_READ_NEXT; /* when no next entry is found, the current entry[i] is reselected */ - for (j = i + 1; ; j = (j + 1) % nent) { - struct kvm_cpuid_entry2 *ej = &vcpu->arch.cpuid_entries[j]; - if (ej->function == e->function) { - ej->flags |= KVM_CPUID_FLAG_STATE_READ_NEXT; - return j; - } - } - return 0; /* silence gcc, even though control never reaches here */ + do { + j = (j + 1) % nent; + ej = &vcpu->arch.cpuid_entries[j]; + } while (ej->function != e->function); + + ej->flags |= KVM_CPUID_FLAG_STATE_READ_NEXT; + + return j; } /* find an entry with matching function, matching index (if needed), and that -- cgit v1.2.3 From 6460495709aeb651896bc8e5c134b2e4ca7d34a8 Mon Sep 17 00:00:00 2001 From: James Wang Date: Thu, 8 Jun 2017 14:52:51 +0800 Subject: Fix loop device flush before configure v3 While installing SLES-12 (based on v4.4), I found that the installer will stall for 60+ seconds during LVM disk scan. The root cause was determined to be the removal of a bound device check in loop_flush() by commit b5dd2f6047ca ("block: loop: improve performance via blk-mq"). Restoring this check, examining ->lo_state as set by loop_set_fd() eliminates the bad behavior. Test method: modprobe loop max_loop=64 dd if=/dev/zero of=disk bs=512 count=200K for((i=0;i<4;i++))do losetup -f disk; done mkfs.ext4 -F /dev/loop0 for((i=0;i<4;i++))do mkdir t$i; mount /dev/loop$i t$i;done for f in `ls /dev/loop[0-9]*|sort`; do \ echo $f; dd if=$f of=/dev/null bs=512 count=1; \ done Test output: stock patched /dev/loop0 18.1217e-05 8.3842e-05 /dev/loop1 6.1114e-05 0.000147979 /dev/loop10 0.414701 0.000116564 /dev/loop11 0.7474 6.7942e-05 /dev/loop12 0.747986 8.9082e-05 /dev/loop13 0.746532 7.4799e-05 /dev/loop14 0.480041 9.3926e-05 /dev/loop15 1.26453 7.2522e-05 Note that from loop10 onward, the device is not mounted, yet the stock kernel consumes several orders of magnitude more wall time than it does for a mounted device. (Thanks for Mike Galbraith , give a changelog review.) Reviewed-by: Hannes Reinecke Reviewed-by: Ming Lei Signed-off-by: James Wang Fixes: b5dd2f6047ca ("block: loop: improve performance via blk-mq") Signed-off-by: Jens Axboe --- drivers/block/loop.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 28d932906f24..ebbd0c3fe0ed 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -608,6 +608,9 @@ static int loop_switch(struct loop_device *lo, struct file *file) */ static int loop_flush(struct loop_device *lo) { + /* loop not yet configured, no running thread, nothing to flush */ + if (lo->lo_state != Lo_bound) + return 0; return loop_switch(lo, NULL); } -- cgit v1.2.3 From ef6c4d75e35345f8f362d6754bcd9a28292a897c Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 8 Jun 2017 16:58:23 +0300 Subject: drm/i915: fix warning for unused variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/gpu/drm/i915/intel_engine_cs.c: In function ‘intel_engine_is_idle’: drivers/gpu/drm/i915/intel_engine_cs.c:1103:27: error: unused variable ‘dev_priv’ [-Werror=unused-variable] struct drm_i915_private *dev_priv = engine->i915; ^~~~~~~~ Reviewed-by: Chris Wilson Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_engine_cs.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index 9a0fb3cdd4e0..f94eacff196c 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -1100,8 +1100,6 @@ static bool ring_is_idle(struct intel_engine_cs *engine) */ bool intel_engine_is_idle(struct intel_engine_cs *engine) { - struct drm_i915_private *dev_priv = engine->i915; - /* Any inflight/incomplete requests? */ if (!i915_seqno_passed(intel_engine_get_seqno(engine), intel_engine_last_submit(engine))) -- cgit v1.2.3 From cdf7abc4610a7f1c43d06cda246c5f748a4fd267 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 31 May 2017 14:03:10 +0200 Subject: srcu: Allow use of Tiny/Tree SRCU from both process and interrupt context Linu Cherian reported a WARN in cleanup_srcu_struct() when shutting down a guest running iperf on a VFIO assigned device. This happens because irqfd_wakeup() calls srcu_read_lock(&kvm->irq_srcu) in interrupt context, while a worker thread does the same inside kvm_set_irq(). If the interrupt happens while the worker thread is executing __srcu_read_lock(), updates to the Classic SRCU ->lock_count[] field or the Tree SRCU ->srcu_lock_count[] field can be lost. The docs say you are not supposed to call srcu_read_lock() and srcu_read_unlock() from irq context, but KVM interrupt injection happens from (host) interrupt context and it would be nice if SRCU supported the use case. KVM is using SRCU here not really for the "sleepable" part, but rather due to its IPI-free fast detection of grace periods. It is therefore not desirable to switch back to RCU, which would effectively revert commit 719d93cd5f5c ("kvm/irqchip: Speed up KVM_SET_GSI_ROUTING", 2014-01-16). However, the docs are overly conservative. You can have an SRCU instance only has users in irq context, and you can mix process and irq context as long as process context users disable interrupts. In addition, __srcu_read_unlock() actually uses this_cpu_dec() on both Tree SRCU and Classic SRCU. For those two implementations, only srcu_read_lock() is unsafe. When Classic SRCU's __srcu_read_unlock() was changed to use this_cpu_dec(), in commit 5a41344a3d83 ("srcu: Simplify __srcu_read_unlock() via this_cpu_dec()", 2012-11-29), __srcu_read_lock() did two increments. Therefore it kept __this_cpu_inc(), with preempt_disable/enable in the caller. Tree SRCU however only does one increment, so on most architectures it is more efficient for __srcu_read_lock() to use this_cpu_inc(), and any performance differences appear to be down in the noise. Unlike Classic and Tree SRCU, Tiny SRCU does increments and decrements on a single variable. Therefore, as Peter Zijlstra pointed out, Tiny SRCU's implementation already supports mixed-context use of srcu_read_lock() and srcu_read_unlock(), at least as long as uses of srcu_read_lock() and srcu_read_unlock() in each handler are nested and paired properly. In other words, it is still illegal to (say) invoke srcu_read_lock() in an interrupt handler and to invoke the matching srcu_read_unlock() in a softirq handler. Therefore, the only change required for Tiny SRCU is to its comments. Fixes: 719d93cd5f5c ("kvm/irqchip: Speed up KVM_SET_GSI_ROUTING") Reported-by: Linu Cherian Suggested-by: Linu Cherian Cc: kvm@vger.kernel.org Signed-off-by: Paolo Bonzini Cc: Linus Torvalds Signed-off-by: Paul E. McKenney Tested-by: Paolo Bonzini --- kernel/rcu/srcutiny.c | 7 ++++--- kernel/rcu/srcutree.c | 5 ++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/kernel/rcu/srcutiny.c b/kernel/rcu/srcutiny.c index 36e1f82faed1..32798eb14853 100644 --- a/kernel/rcu/srcutiny.c +++ b/kernel/rcu/srcutiny.c @@ -97,8 +97,9 @@ EXPORT_SYMBOL_GPL(cleanup_srcu_struct); /* * Counts the new reader in the appropriate per-CPU element of the - * srcu_struct. Must be called from process context. - * Returns an index that must be passed to the matching srcu_read_unlock(). + * srcu_struct. Can be invoked from irq/bh handlers, but the matching + * __srcu_read_unlock() must be in the same handler instance. Returns an + * index that must be passed to the matching srcu_read_unlock(). */ int __srcu_read_lock(struct srcu_struct *sp) { @@ -112,7 +113,7 @@ EXPORT_SYMBOL_GPL(__srcu_read_lock); /* * Removes the count for the old reader from the appropriate element of - * the srcu_struct. Must be called from process context. + * the srcu_struct. */ void __srcu_read_unlock(struct srcu_struct *sp, int idx) { diff --git a/kernel/rcu/srcutree.c b/kernel/rcu/srcutree.c index 3ae8474557df..157654fa436a 100644 --- a/kernel/rcu/srcutree.c +++ b/kernel/rcu/srcutree.c @@ -357,7 +357,7 @@ EXPORT_SYMBOL_GPL(cleanup_srcu_struct); /* * Counts the new reader in the appropriate per-CPU element of the - * srcu_struct. Must be called from process context. + * srcu_struct. * Returns an index that must be passed to the matching srcu_read_unlock(). */ int __srcu_read_lock(struct srcu_struct *sp) @@ -365,7 +365,7 @@ int __srcu_read_lock(struct srcu_struct *sp) int idx; idx = READ_ONCE(sp->srcu_idx) & 0x1; - __this_cpu_inc(sp->sda->srcu_lock_count[idx]); + this_cpu_inc(sp->sda->srcu_lock_count[idx]); smp_mb(); /* B */ /* Avoid leaking the critical section. */ return idx; } @@ -375,7 +375,6 @@ EXPORT_SYMBOL_GPL(__srcu_read_lock); * Removes the count for the old reader from the appropriate per-CPU * element of the srcu_struct. Note that this may well be a different * CPU than that which was incremented by the corresponding srcu_read_lock(). - * Must be called from process context. */ void __srcu_read_unlock(struct srcu_struct *sp, int idx) { -- cgit v1.2.3 From 1123a6041654e8f889014659593bad4168e542c2 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 31 May 2017 14:03:11 +0200 Subject: srcu: Allow use of Classic SRCU from both process and interrupt context Linu Cherian reported a WARN in cleanup_srcu_struct() when shutting down a guest running iperf on a VFIO assigned device. This happens because irqfd_wakeup() calls srcu_read_lock(&kvm->irq_srcu) in interrupt context, while a worker thread does the same inside kvm_set_irq(). If the interrupt happens while the worker thread is executing __srcu_read_lock(), updates to the Classic SRCU ->lock_count[] field or the Tree SRCU ->srcu_lock_count[] field can be lost. The docs say you are not supposed to call srcu_read_lock() and srcu_read_unlock() from irq context, but KVM interrupt injection happens from (host) interrupt context and it would be nice if SRCU supported the use case. KVM is using SRCU here not really for the "sleepable" part, but rather due to its IPI-free fast detection of grace periods. It is therefore not desirable to switch back to RCU, which would effectively revert commit 719d93cd5f5c ("kvm/irqchip: Speed up KVM_SET_GSI_ROUTING", 2014-01-16). However, the docs are overly conservative. You can have an SRCU instance only has users in irq context, and you can mix process and irq context as long as process context users disable interrupts. In addition, __srcu_read_unlock() actually uses this_cpu_dec() on both Tree SRCU and Classic SRCU. For those two implementations, only srcu_read_lock() is unsafe. When Classic SRCU's __srcu_read_unlock() was changed to use this_cpu_dec(), in commit 5a41344a3d83 ("srcu: Simplify __srcu_read_unlock() via this_cpu_dec()", 2012-11-29), __srcu_read_lock() did two increments. Therefore it kept __this_cpu_inc(), with preempt_disable/enable in the caller. Tree SRCU however only does one increment, so on most architectures it is more efficient for __srcu_read_lock() to use this_cpu_inc(), and any performance differences appear to be down in the noise. Cc: stable@vger.kernel.org Fixes: 719d93cd5f5c ("kvm/irqchip: Speed up KVM_SET_GSI_ROUTING") Reported-by: Linu Cherian Suggested-by: Linu Cherian Cc: kvm@vger.kernel.org Signed-off-by: Paolo Bonzini Cc: Linus Torvalds Signed-off-by: Paul E. McKenney --- include/linux/srcu.h | 2 -- kernel/rcu/srcu.c | 5 ++--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/include/linux/srcu.h b/include/linux/srcu.h index 167ad8831aaf..4c1d5f7e62c4 100644 --- a/include/linux/srcu.h +++ b/include/linux/srcu.h @@ -172,9 +172,7 @@ static inline int srcu_read_lock(struct srcu_struct *sp) __acquires(sp) { int retval; - preempt_disable(); retval = __srcu_read_lock(sp); - preempt_enable(); rcu_lock_acquire(&(sp)->dep_map); return retval; } diff --git a/kernel/rcu/srcu.c b/kernel/rcu/srcu.c index 584d8a983883..dea03614263f 100644 --- a/kernel/rcu/srcu.c +++ b/kernel/rcu/srcu.c @@ -263,7 +263,7 @@ EXPORT_SYMBOL_GPL(cleanup_srcu_struct); /* * Counts the new reader in the appropriate per-CPU element of the - * srcu_struct. Must be called from process context. + * srcu_struct. * Returns an index that must be passed to the matching srcu_read_unlock(). */ int __srcu_read_lock(struct srcu_struct *sp) @@ -271,7 +271,7 @@ int __srcu_read_lock(struct srcu_struct *sp) int idx; idx = READ_ONCE(sp->completed) & 0x1; - __this_cpu_inc(sp->per_cpu_ref->lock_count[idx]); + this_cpu_inc(sp->per_cpu_ref->lock_count[idx]); smp_mb(); /* B */ /* Avoid leaking the critical section. */ return idx; } @@ -281,7 +281,6 @@ EXPORT_SYMBOL_GPL(__srcu_read_lock); * Removes the count for the old reader from the appropriate per-CPU * element of the srcu_struct. Note that this may well be a different * CPU than that which was incremented by the corresponding srcu_read_lock(). - * Must be called from process context. */ void __srcu_read_unlock(struct srcu_struct *sp, int idx) { -- cgit v1.2.3 From 8f9bebc33dd718283183582fc4a762e178552fb8 Mon Sep 17 00:00:00 2001 From: Paolo Valente Date: Mon, 5 Jun 2017 10:11:15 +0200 Subject: block, bfq: access and cache blkg data only when safe In blk-cgroup, operations on blkg objects are protected with the request_queue lock. This is no more the lock that protects I/O-scheduler operations in blk-mq. In fact, the latter are now protected with a finer-grained per-scheduler-instance lock. As a consequence, although blkg lookups are also rcu-protected, blk-mq I/O schedulers may see inconsistent data when they access blkg and blkg-related objects. BFQ does access these objects, and does incur this problem, in the following case. The blkg_lookup performed in bfq_get_queue, being protected (only) through rcu, may happen to return the address of a copy of the original blkg. If this is the case, then the blkg_get performed in bfq_get_queue, to pin down the blkg, is useless: it does not prevent blk-cgroup code from destroying both the original blkg and all objects directly or indirectly referred by the copy of the blkg. BFQ accesses these objects, which typically causes a crash for NULL-pointer dereference of memory-protection violation. Some additional protection mechanism should be added to blk-cgroup to address this issue. In the meantime, this commit provides a quick temporary fix for BFQ: cache (when safe) blkg data that might disappear right after a blkg_lookup. In particular, this commit exploits the following facts to achieve its goal without introducing further locks. Destroy operations on a blkg invoke, as a first step, hooks of the scheduler associated with the blkg. And these hooks are executed with bfqd->lock held for BFQ. As a consequence, for any blkg associated with the request queue an instance of BFQ is attached to, we are guaranteed that such a blkg is not destroyed, and that all the pointers it contains are consistent, while that instance is holding its bfqd->lock. A blkg_lookup performed with bfqd->lock held then returns a fully consistent blkg, which remains consistent until this lock is held. In more detail, this holds even if the returned blkg is a copy of the original one. Finally, also the object describing a group inside BFQ needs to be protected from destruction on the blkg_free of the original blkg (which invokes bfq_pd_free). This commit adds private refcounting for this object, to let it disappear only after no bfq_queue refers to it any longer. This commit also removes or updates some stale comments on locking issues related to blk-cgroup operations. Reported-by: Tomas Konir Reported-by: Lee Tibbert Reported-by: Marco Piazza Signed-off-by: Paolo Valente Tested-by: Tomas Konir Tested-by: Lee Tibbert Tested-by: Marco Piazza Signed-off-by: Jens Axboe --- block/bfq-cgroup.c | 116 +++++++++++++++++++++++++++++++++++++++++----------- block/bfq-iosched.c | 2 +- block/bfq-iosched.h | 23 +++++------ 3 files changed, 105 insertions(+), 36 deletions(-) diff --git a/block/bfq-cgroup.c b/block/bfq-cgroup.c index c8a32fb345cf..78b2e0db4fb2 100644 --- a/block/bfq-cgroup.c +++ b/block/bfq-cgroup.c @@ -52,7 +52,7 @@ BFQG_FLAG_FNS(idling) BFQG_FLAG_FNS(empty) #undef BFQG_FLAG_FNS -/* This should be called with the queue_lock held. */ +/* This should be called with the scheduler lock held. */ static void bfqg_stats_update_group_wait_time(struct bfqg_stats *stats) { unsigned long long now; @@ -67,7 +67,7 @@ static void bfqg_stats_update_group_wait_time(struct bfqg_stats *stats) bfqg_stats_clear_waiting(stats); } -/* This should be called with the queue_lock held. */ +/* This should be called with the scheduler lock held. */ static void bfqg_stats_set_start_group_wait_time(struct bfq_group *bfqg, struct bfq_group *curr_bfqg) { @@ -81,7 +81,7 @@ static void bfqg_stats_set_start_group_wait_time(struct bfq_group *bfqg, bfqg_stats_mark_waiting(stats); } -/* This should be called with the queue_lock held. */ +/* This should be called with the scheduler lock held. */ static void bfqg_stats_end_empty_time(struct bfqg_stats *stats) { unsigned long long now; @@ -203,12 +203,30 @@ struct bfq_group *bfqq_group(struct bfq_queue *bfqq) static void bfqg_get(struct bfq_group *bfqg) { - return blkg_get(bfqg_to_blkg(bfqg)); + bfqg->ref++; } void bfqg_put(struct bfq_group *bfqg) { - return blkg_put(bfqg_to_blkg(bfqg)); + bfqg->ref--; + + if (bfqg->ref == 0) + kfree(bfqg); +} + +static void bfqg_and_blkg_get(struct bfq_group *bfqg) +{ + /* see comments in bfq_bic_update_cgroup for why refcounting bfqg */ + bfqg_get(bfqg); + + blkg_get(bfqg_to_blkg(bfqg)); +} + +void bfqg_and_blkg_put(struct bfq_group *bfqg) +{ + bfqg_put(bfqg); + + blkg_put(bfqg_to_blkg(bfqg)); } void bfqg_stats_update_io_add(struct bfq_group *bfqg, struct bfq_queue *bfqq, @@ -312,7 +330,11 @@ void bfq_init_entity(struct bfq_entity *entity, struct bfq_group *bfqg) if (bfqq) { bfqq->ioprio = bfqq->new_ioprio; bfqq->ioprio_class = bfqq->new_ioprio_class; - bfqg_get(bfqg); + /* + * Make sure that bfqg and its associated blkg do not + * disappear before entity. + */ + bfqg_and_blkg_get(bfqg); } entity->parent = bfqg->my_entity; /* NULL for root group */ entity->sched_data = &bfqg->sched_data; @@ -399,6 +421,8 @@ struct blkg_policy_data *bfq_pd_alloc(gfp_t gfp, int node) return NULL; } + /* see comments in bfq_bic_update_cgroup for why refcounting */ + bfqg_get(bfqg); return &bfqg->pd; } @@ -426,7 +450,7 @@ void bfq_pd_free(struct blkg_policy_data *pd) struct bfq_group *bfqg = pd_to_bfqg(pd); bfqg_stats_exit(&bfqg->stats); - return kfree(bfqg); + bfqg_put(bfqg); } void bfq_pd_reset_stats(struct blkg_policy_data *pd) @@ -496,9 +520,10 @@ struct bfq_group *bfq_find_set_group(struct bfq_data *bfqd, * Move @bfqq to @bfqg, deactivating it from its old group and reactivating * it on the new one. Avoid putting the entity on the old group idle tree. * - * Must be called under the queue lock; the cgroup owning @bfqg must - * not disappear (by now this just means that we are called under - * rcu_read_lock()). + * Must be called under the scheduler lock, to make sure that the blkg + * owning @bfqg does not disappear (see comments in + * bfq_bic_update_cgroup on guaranteeing the consistency of blkg + * objects). */ void bfq_bfqq_move(struct bfq_data *bfqd, struct bfq_queue *bfqq, struct bfq_group *bfqg) @@ -519,16 +544,12 @@ void bfq_bfqq_move(struct bfq_data *bfqd, struct bfq_queue *bfqq, bfq_deactivate_bfqq(bfqd, bfqq, false, false); else if (entity->on_st) bfq_put_idle_entity(bfq_entity_service_tree(entity), entity); - bfqg_put(bfqq_group(bfqq)); + bfqg_and_blkg_put(bfqq_group(bfqq)); - /* - * Here we use a reference to bfqg. We don't need a refcounter - * as the cgroup reference will not be dropped, so that its - * destroy() callback will not be invoked. - */ entity->parent = bfqg->my_entity; entity->sched_data = &bfqg->sched_data; - bfqg_get(bfqg); + /* pin down bfqg and its associated blkg */ + bfqg_and_blkg_get(bfqg); if (bfq_bfqq_busy(bfqq)) { bfq_pos_tree_add_move(bfqd, bfqq); @@ -545,8 +566,9 @@ void bfq_bfqq_move(struct bfq_data *bfqd, struct bfq_queue *bfqq, * @bic: the bic to move. * @blkcg: the blk-cgroup to move to. * - * Move bic to blkcg, assuming that bfqd->queue is locked; the caller - * has to make sure that the reference to cgroup is valid across the call. + * Move bic to blkcg, assuming that bfqd->lock is held; which makes + * sure that the reference to cgroup is valid across the call (see + * comments in bfq_bic_update_cgroup on this issue) * * NOTE: an alternative approach might have been to store the current * cgroup in bfqq and getting a reference to it, reducing the lookup @@ -604,6 +626,57 @@ void bfq_bic_update_cgroup(struct bfq_io_cq *bic, struct bio *bio) goto out; bfqg = __bfq_bic_change_cgroup(bfqd, bic, bio_blkcg(bio)); + /* + * Update blkg_path for bfq_log_* functions. We cache this + * path, and update it here, for the following + * reasons. Operations on blkg objects in blk-cgroup are + * protected with the request_queue lock, and not with the + * lock that protects the instances of this scheduler + * (bfqd->lock). This exposes BFQ to the following sort of + * race. + * + * The blkg_lookup performed in bfq_get_queue, protected + * through rcu, may happen to return the address of a copy of + * the original blkg. If this is the case, then the + * bfqg_and_blkg_get performed in bfq_get_queue, to pin down + * the blkg, is useless: it does not prevent blk-cgroup code + * from destroying both the original blkg and all objects + * directly or indirectly referred by the copy of the + * blkg. + * + * On the bright side, destroy operations on a blkg invoke, as + * a first step, hooks of the scheduler associated with the + * blkg. And these hooks are executed with bfqd->lock held for + * BFQ. As a consequence, for any blkg associated with the + * request queue this instance of the scheduler is attached + * to, we are guaranteed that such a blkg is not destroyed, and + * that all the pointers it contains are consistent, while we + * are holding bfqd->lock. A blkg_lookup performed with + * bfqd->lock held then returns a fully consistent blkg, which + * remains consistent until this lock is held. + * + * Thanks to the last fact, and to the fact that: (1) bfqg has + * been obtained through a blkg_lookup in the above + * assignment, and (2) bfqd->lock is being held, here we can + * safely use the policy data for the involved blkg (i.e., the + * field bfqg->pd) to get to the blkg associated with bfqg, + * and then we can safely use any field of blkg. After we + * release bfqd->lock, even just getting blkg through this + * bfqg may cause dangling references to be traversed, as + * bfqg->pd may not exist any more. + * + * In view of the above facts, here we cache, in the bfqg, any + * blkg data we may need for this bic, and for its associated + * bfq_queue. As of now, we need to cache only the path of the + * blkg, which is used in the bfq_log_* functions. + * + * Finally, note that bfqg itself needs to be protected from + * destruction on the blkg_free of the original blkg (which + * invokes bfq_pd_free). We use an additional private + * refcounter for bfqg, to let it disappear only after no + * bfq_queue refers to it any longer. + */ + blkg_path(bfqg_to_blkg(bfqg), bfqg->blkg_path, sizeof(bfqg->blkg_path)); bic->blkcg_serial_nr = serial_nr; out: rcu_read_unlock(); @@ -640,8 +713,6 @@ static void bfq_reparent_leaf_entity(struct bfq_data *bfqd, * @bfqd: the device data structure with the root group. * @bfqg: the group to move from. * @st: the service tree with the entities. - * - * Needs queue_lock to be taken and reference to be valid over the call. */ static void bfq_reparent_active_entities(struct bfq_data *bfqd, struct bfq_group *bfqg, @@ -692,8 +763,7 @@ void bfq_pd_offline(struct blkg_policy_data *pd) /* * The idle tree may still contain bfq_queues belonging * to exited task because they never migrated to a different - * cgroup from the one being destroyed now. No one else - * can access them so it's safe to act without any lock. + * cgroup from the one being destroyed now. */ bfq_flush_idle_tree(st); diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c index 08ce45096350..ed93da2462ab 100644 --- a/block/bfq-iosched.c +++ b/block/bfq-iosched.c @@ -3665,7 +3665,7 @@ void bfq_put_queue(struct bfq_queue *bfqq) kmem_cache_free(bfq_pool, bfqq); #ifdef CONFIG_BFQ_GROUP_IOSCHED - bfqg_put(bfqg); + bfqg_and_blkg_put(bfqg); #endif } diff --git a/block/bfq-iosched.h b/block/bfq-iosched.h index ae783c06dfd9..5c3bf9861492 100644 --- a/block/bfq-iosched.h +++ b/block/bfq-iosched.h @@ -759,6 +759,12 @@ struct bfq_group { /* must be the first member */ struct blkg_policy_data pd; + /* cached path for this blkg (see comments in bfq_bic_update_cgroup) */ + char blkg_path[128]; + + /* reference counter (see comments in bfq_bic_update_cgroup) */ + int ref; + struct bfq_entity entity; struct bfq_sched_data sched_data; @@ -838,7 +844,7 @@ struct bfq_group *bfq_find_set_group(struct bfq_data *bfqd, struct blkcg_gq *bfqg_to_blkg(struct bfq_group *bfqg); struct bfq_group *bfqq_group(struct bfq_queue *bfqq); struct bfq_group *bfq_create_group_hierarchy(struct bfq_data *bfqd, int node); -void bfqg_put(struct bfq_group *bfqg); +void bfqg_and_blkg_put(struct bfq_group *bfqg); #ifdef CONFIG_BFQ_GROUP_IOSCHED extern struct cftype bfq_blkcg_legacy_files[]; @@ -910,20 +916,13 @@ void bfq_add_bfqq_busy(struct bfq_data *bfqd, struct bfq_queue *bfqq); struct bfq_group *bfqq_group(struct bfq_queue *bfqq); #define bfq_log_bfqq(bfqd, bfqq, fmt, args...) do { \ - char __pbuf[128]; \ - \ - blkg_path(bfqg_to_blkg(bfqq_group(bfqq)), __pbuf, sizeof(__pbuf)); \ - blk_add_trace_msg((bfqd)->queue, "bfq%d%c %s " fmt, (bfqq)->pid, \ + blk_add_trace_msg((bfqd)->queue, "bfq%d%c %s " fmt, (bfqq)->pid,\ bfq_bfqq_sync((bfqq)) ? 'S' : 'A', \ - __pbuf, ##args); \ + bfqq_group(bfqq)->blkg_path, ##args); \ } while (0) -#define bfq_log_bfqg(bfqd, bfqg, fmt, args...) do { \ - char __pbuf[128]; \ - \ - blkg_path(bfqg_to_blkg(bfqg), __pbuf, sizeof(__pbuf)); \ - blk_add_trace_msg((bfqd)->queue, "%s " fmt, __pbuf, ##args); \ -} while (0) +#define bfq_log_bfqg(bfqd, bfqg, fmt, args...) \ + blk_add_trace_msg((bfqd)->queue, "%s " fmt, (bfqg)->blkg_path, ##args) #else /* CONFIG_BFQ_GROUP_IOSCHED */ -- cgit v1.2.3 From 3619ef76b37d4803bc9daee9d03d82c8526db378 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 8 Jun 2017 16:31:01 +0900 Subject: perf annotate: Fix symbolic link of build-id cache The commit 6ebd2547dd24 ("perf annotate: Fix a bug following symbolic link of a build-id file") changed to use dirname to follow the symlink. But it only considers new-style build-id cache names so old names fail on readlink() and force to use system path which might not available. Signed-off-by: Namhyung Kim Acked-by: Jiri Olsa Cc: Adrian Hunter Cc: David Ahern Cc: Peter Zijlstra Cc: Taeung Song Cc: Wang Nan Cc: kernel-team@lge.com Fixes: 6ebd2547dd24 ("perf annotate: Fix a bug following symbolic link of a build-id file") Link: http://lkml.kernel.org/r/20170608073109.30699-2-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/annotate.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 1367d7e35242..df4486c3a2fa 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -1321,6 +1321,7 @@ static int dso__disassemble_filename(struct dso *dso, char *filename, size_t fil char linkname[PATH_MAX]; char *build_id_filename; char *build_id_path = NULL; + char *pos; if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS && !dso__is_kcore(dso)) @@ -1340,7 +1341,14 @@ static int dso__disassemble_filename(struct dso *dso, char *filename, size_t fil if (!build_id_path) return -1; - dirname(build_id_path); + /* + * old style build-id cache has name of XX/XXXXXXX.. while + * new style has XX/XXXXXXX../{elf,kallsyms,vdso}. + * extract the build-id part of dirname in the new style only. + */ + pos = strrchr(build_id_path, '/'); + if (pos && strlen(pos) < SBUILD_ID_SIZE - 2) + dirname(build_id_path); if (dso__is_kcore(dso) || readlink(build_id_path, linkname, sizeof(linkname)) < 0 || -- cgit v1.2.3 From 44ad6b8852529eb39066edbedc027a6901da6803 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 8 Jun 2017 16:31:02 +0900 Subject: perf tools: Fix a memory leak in __open_dso() The 'name' variable should be freed on the error path. Signed-off-by: Namhyung Kim Acked-by: Jiri Olsa Cc: Adrian Hunter Cc: David Ahern Cc: Peter Zijlstra Cc: Wang Nan Cc: kernel-team@lge.com Link: http://lkml.kernel.org/r/20170608073109.30699-3-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/dso.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index b27d127cdf68..1f29e4fe7af0 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -412,8 +412,10 @@ static int __open_dso(struct dso *dso, struct machine *machine) return -EINVAL; } - if (!is_regular_file(name)) + if (!is_regular_file(name)) { + free(name); return -EINVAL; + } fd = do_open(name); free(name); -- cgit v1.2.3 From 42b3fa670825983fc8bd0ac7b80cc84ae3abb75b Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 8 Jun 2017 16:31:03 +0900 Subject: perf tools: Introduce dso__decompress_kmodule_{fd,path} Move decompress_kmodule() to util/dso.c and split it into two functions returning fd and (decompressed) file path. The existing user only wants the fd version but the path version will be used soon. Signed-off-by: Namhyung Kim Acked-by: Jiri Olsa Cc: Adrian Hunter Cc: David Ahern Cc: Peter Zijlstra Cc: Wang Nan Cc: kernel-team@lge.com Link: http://lkml.kernel.org/r/20170608073109.30699-4-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/dso.c | 58 ++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/dso.h | 6 +++++ tools/perf/util/symbol-elf.c | 36 +-------------------------- 3 files changed, 65 insertions(+), 35 deletions(-) diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index 1f29e4fe7af0..b346b8eba65c 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -248,6 +248,64 @@ bool dso__needs_decompress(struct dso *dso) dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE_COMP; } +static int decompress_kmodule(struct dso *dso, const char *name, char *tmpbuf) +{ + int fd = -1; + struct kmod_path m; + + if (!dso__needs_decompress(dso)) + return -1; + + if (kmod_path__parse_ext(&m, dso->long_name)) + return -1; + + if (!m.comp) + goto out; + + fd = mkstemp(tmpbuf); + if (fd < 0) { + dso->load_errno = errno; + goto out; + } + + if (!decompress_to_file(m.ext, name, fd)) { + dso->load_errno = DSO_LOAD_ERRNO__DECOMPRESSION_FAILURE; + close(fd); + fd = -1; + } + +out: + free(m.ext); + return fd; +} + +int dso__decompress_kmodule_fd(struct dso *dso, const char *name) +{ + char tmpbuf[] = KMOD_DECOMP_NAME; + int fd; + + fd = decompress_kmodule(dso, name, tmpbuf); + unlink(tmpbuf); + return fd; +} + +int dso__decompress_kmodule_path(struct dso *dso, const char *name, + char *pathname, size_t len) +{ + char tmpbuf[] = KMOD_DECOMP_NAME; + int fd; + + fd = decompress_kmodule(dso, name, tmpbuf); + if (fd < 0) { + unlink(tmpbuf); + return -1; + } + + strncpy(pathname, tmpbuf, len); + close(fd); + return 0; +} + /* * Parses kernel module specified in @path and updates * @m argument like: diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h index 5fe2ab5877bd..bd061ba7b47c 100644 --- a/tools/perf/util/dso.h +++ b/tools/perf/util/dso.h @@ -244,6 +244,12 @@ bool is_supported_compression(const char *ext); bool is_kernel_module(const char *pathname, int cpumode); bool decompress_to_file(const char *ext, const char *filename, int output_fd); bool dso__needs_decompress(struct dso *dso); +int dso__decompress_kmodule_fd(struct dso *dso, const char *name); +int dso__decompress_kmodule_path(struct dso *dso, const char *name, + char *pathname, size_t len); + +#define KMOD_DECOMP_NAME "/tmp/perf-kmod-XXXXXX" +#define KMOD_DECOMP_LEN sizeof(KMOD_DECOMP_NAME) struct kmod_path { char *name; diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index 1fb2efae4f02..d342e771dbad 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c @@ -637,40 +637,6 @@ static int dso__swap_init(struct dso *dso, unsigned char eidata) return 0; } -static int decompress_kmodule(struct dso *dso, const char *name, - enum dso_binary_type type) -{ - int fd = -1; - char tmpbuf[] = "/tmp/perf-kmod-XXXXXX"; - struct kmod_path m; - - if (type != DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP && - type != DSO_BINARY_TYPE__GUEST_KMODULE_COMP && - type != DSO_BINARY_TYPE__BUILD_ID_CACHE) - return -1; - - if (kmod_path__parse_ext(&m, dso->long_name) || !m.comp) - return -1; - - fd = mkstemp(tmpbuf); - if (fd < 0) { - dso->load_errno = errno; - goto out; - } - - if (!decompress_to_file(m.ext, name, fd)) { - dso->load_errno = DSO_LOAD_ERRNO__DECOMPRESSION_FAILURE; - close(fd); - fd = -1; - } - - unlink(tmpbuf); - -out: - free(m.ext); - return fd; -} - bool symsrc__possibly_runtime(struct symsrc *ss) { return ss->dynsym || ss->opdsec; @@ -702,7 +668,7 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name, int fd; if (dso__needs_decompress(dso)) { - fd = decompress_kmodule(dso, name, type); + fd = dso__decompress_kmodule_fd(dso, name); if (fd < 0) return -1; } else { -- cgit v1.2.3 From 3c84fd53044f98017271101b59a21ddb20fb312b Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 8 Jun 2017 16:31:04 +0900 Subject: perf annotate: Use dso__decompress_kmodule_path() Convert open-coded decompress routine to use the function. Signed-off-by: Namhyung Kim Acked-by: Jiri Olsa Cc: Adrian Hunter Cc: David Ahern Cc: Peter Zijlstra Cc: Wang Nan Cc: kernel-team@lge.com Link: http://lkml.kernel.org/r/20170608073109.30699-5-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/annotate.c | 27 +++------------------------ 1 file changed, 3 insertions(+), 24 deletions(-) diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index df4486c3a2fa..ddbd56df9187 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -1431,31 +1431,10 @@ int symbol__disassemble(struct symbol *sym, struct map *map, const char *arch_na sizeof(symfs_filename)); } } else if (dso__needs_decompress(dso)) { - char tmp[PATH_MAX]; - struct kmod_path m; - int fd; - bool ret; + char tmp[KMOD_DECOMP_LEN]; - if (kmod_path__parse_ext(&m, symfs_filename)) - goto out; - - snprintf(tmp, PATH_MAX, "/tmp/perf-kmod-XXXXXX"); - - fd = mkstemp(tmp); - if (fd < 0) { - free(m.ext); - goto out; - } - - ret = decompress_to_file(m.ext, symfs_filename, fd); - - if (ret) - pr_err("Cannot decompress %s %s\n", m.ext, symfs_filename); - - free(m.ext); - close(fd); - - if (!ret) + if (dso__decompress_kmodule_path(dso, symfs_filename, + tmp, sizeof(tmp)) < 0) goto out; strcpy(symfs_filename, tmp); -- cgit v1.2.3 From 1d6b3c9ba756a5134fd7ad1959acac776d17404b Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 8 Jun 2017 16:31:05 +0900 Subject: perf tools: Decompress kernel module when reading DSO data Currently perf decompresses kernel modules when loading the symbol table but it missed to do it when reading raw data. Signed-off-by: Namhyung Kim Acked-by: Jiri Olsa Cc: Adrian Hunter Cc: David Ahern Cc: Peter Zijlstra Cc: Wang Nan Cc: kernel-team@lge.com Link: http://lkml.kernel.org/r/20170608073109.30699-6-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/dso.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index b346b8eba65c..c63525d845c5 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -475,7 +475,23 @@ static int __open_dso(struct dso *dso, struct machine *machine) return -EINVAL; } + if (dso__needs_decompress(dso)) { + char newpath[KMOD_DECOMP_LEN]; + size_t len = sizeof(newpath); + + if (dso__decompress_kmodule_path(dso, name, newpath, len) < 0) { + free(name); + return -dso->load_errno; + } + + strcpy(name, newpath); + } + fd = do_open(name); + + if (dso__needs_decompress(dso)) + unlink(name); + free(name); return fd; } -- cgit v1.2.3 From 8ba29adf9a7cdff3c7283d5fc0dcf5e777d3b40f Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 8 Jun 2017 16:31:06 +0900 Subject: perf tools: Consolidate error path in __open_dso() On failure, it should free the 'name', so clean up the error path using goto. Signed-off-by: Namhyung Kim Suggested-by: Arnaldo Carvalho de Melo Acked-by: Jiri Olsa Cc: Adrian Hunter Cc: David Ahern Cc: Peter Zijlstra Cc: Wang Nan Cc: kernel-team@lge.com Link: http://lkml.kernel.org/r/20170608073109.30699-7-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/dso.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index c63525d845c5..4e7ab611377a 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -454,7 +454,7 @@ static int do_open(char *name) static int __open_dso(struct dso *dso, struct machine *machine) { - int fd; + int fd = -EINVAL; char *root_dir = (char *)""; char *name = malloc(PATH_MAX); @@ -465,23 +465,19 @@ static int __open_dso(struct dso *dso, struct machine *machine) root_dir = machine->root_dir; if (dso__read_binary_type_filename(dso, dso->binary_type, - root_dir, name, PATH_MAX)) { - free(name); - return -EINVAL; - } + root_dir, name, PATH_MAX)) + goto out; - if (!is_regular_file(name)) { - free(name); - return -EINVAL; - } + if (!is_regular_file(name)) + goto out; if (dso__needs_decompress(dso)) { char newpath[KMOD_DECOMP_LEN]; size_t len = sizeof(newpath); if (dso__decompress_kmodule_path(dso, name, newpath, len) < 0) { - free(name); - return -dso->load_errno; + fd = -dso->load_errno; + goto out; } strcpy(name, newpath); @@ -492,6 +488,7 @@ static int __open_dso(struct dso *dso, struct machine *machine) if (dso__needs_decompress(dso)) unlink(name); +out: free(name); return fd; } -- cgit v1.2.3 From 94df1040b1e6aacd8dec0ba3c61d7e77cd695f26 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 8 Jun 2017 16:31:07 +0900 Subject: perf tests: Decompress kernel module before objdump If a kernel modules is compressed, it should be decompressed before running objdump to parse binary data correctly. This fixes a failure of object code reading test for me. Signed-off-by: Namhyung Kim Acked-by: Adrian Hunter Acked-by: Jiri Olsa Cc: David Ahern Cc: Peter Zijlstra Cc: Wang Nan Cc: kernel-team@lge.com Link: http://lkml.kernel.org/r/20170608073109.30699-8-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/code-reading.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c index 1f14e7612cbb..94b7c7b02bde 100644 --- a/tools/perf/tests/code-reading.c +++ b/tools/perf/tests/code-reading.c @@ -229,6 +229,8 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode, unsigned char buf2[BUFSZ]; size_t ret_len; u64 objdump_addr; + const char *objdump_name; + char decomp_name[KMOD_DECOMP_LEN]; int ret; pr_debug("Reading object code for memory address: %#"PRIx64"\n", addr); @@ -289,9 +291,25 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode, state->done[state->done_cnt++] = al.map->start; } + objdump_name = al.map->dso->long_name; + if (dso__needs_decompress(al.map->dso)) { + if (dso__decompress_kmodule_path(al.map->dso, objdump_name, + decomp_name, + sizeof(decomp_name)) < 0) { + pr_debug("decompression failed\n"); + return -1; + } + + objdump_name = decomp_name; + } + /* Read the object code using objdump */ objdump_addr = map__rip_2objdump(al.map, al.addr); - ret = read_via_objdump(al.map->dso->long_name, objdump_addr, buf2, len); + ret = read_via_objdump(objdump_name, objdump_addr, buf2, len); + + if (dso__needs_decompress(al.map->dso)) + unlink(objdump_name); + if (ret > 0) { /* * The kernel maps are inaccurate - assume objdump is right in -- cgit v1.2.3 From c25ec42f846f702f8f532fbc890171e3a1f6ec85 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 8 Jun 2017 16:31:08 +0900 Subject: perf symbols: Keep DSO->symtab_type after decompress The symsrc__init() overwrites dso->symtab_type as symsrc->type in dso__load_sym(). But for compressed kernel modules in the build-id cache, it should have original symtab type to be decompressed as needed. This fixes perf annotate to show disassembly of the function properly. Signed-off-by: Namhyung Kim Acked-by: Jiri Olsa Cc: Adrian Hunter Cc: David Ahern Cc: Peter Zijlstra Cc: Wang Nan Cc: kernel-team@lge.com Link: http://lkml.kernel.org/r/20170608073109.30699-9-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/symbol-elf.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index d342e771dbad..502505cf236a 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c @@ -671,6 +671,8 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name, fd = dso__decompress_kmodule_fd(dso, name); if (fd < 0) return -1; + + type = dso->symtab_type; } else { fd = open(name, O_RDONLY); if (fd < 0) { -- cgit v1.2.3 From b89fe63fbafe307fb72546f7a2320380bf41bdd4 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 8 Jun 2017 16:31:09 +0900 Subject: perf symbols: Kill dso__build_id_is_kmod() The commit e7ee40475760 ("perf symbols: Fix symbols searching for module in buildid-cache") added the function to check kernel modules reside in the build-id cache. This was because there's no way to identify a DSO which is actually a kernel module. So it searched linkname of the file and find ".ko" suffix. But this does not work for compressed kernel modules and now such DSOs hCcave correct symtab_type now. So no need to check it anymore. This patch essentially reverts the commit. Signed-off-by: Namhyung Kim Acked-by: Jiri Olsa Cc: Adrian Hunter Cc: David Ahern Cc: Peter Zijlstra Cc: Wang Nan Cc: kernel-team@lge.com Link: http://lkml.kernel.org/r/20170608073109.30699-10-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/build-id.c | 45 --------------------------------------------- tools/perf/util/build-id.h | 1 - tools/perf/util/symbol.c | 4 ---- 3 files changed, 50 deletions(-) diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c index 168cc49654e7..e0148b081bdf 100644 --- a/tools/perf/util/build-id.c +++ b/tools/perf/util/build-id.c @@ -278,51 +278,6 @@ char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size) return bf; } -bool dso__build_id_is_kmod(const struct dso *dso, char *bf, size_t size) -{ - char *id_name = NULL, *ch; - struct stat sb; - char sbuild_id[SBUILD_ID_SIZE]; - - if (!dso->has_build_id) - goto err; - - build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id); - id_name = build_id_cache__linkname(sbuild_id, NULL, 0); - if (!id_name) - goto err; - if (access(id_name, F_OK)) - goto err; - if (lstat(id_name, &sb) == -1) - goto err; - if ((size_t)sb.st_size > size - 1) - goto err; - if (readlink(id_name, bf, size - 1) < 0) - goto err; - - bf[sb.st_size] = '\0'; - - /* - * link should be: - * ../../lib/modules/4.4.0-rc4/kernel/net/ipv4/netfilter/nf_nat_ipv4.ko/a09fe3eb3147dafa4e3b31dbd6257e4d696bdc92 - */ - ch = strrchr(bf, '/'); - if (!ch) - goto err; - if (ch - 3 < bf) - goto err; - - free(id_name); - return strncmp(".ko", ch - 3, 3) == 0; -err: - pr_err("Invalid build id: %s\n", id_name ? : - dso->long_name ? : - dso->short_name ? : - "[unknown]"); - free(id_name); - return false; -} - #define dsos__for_each_with_build_id(pos, head) \ list_for_each_entry(pos, head, node) \ if (!pos->has_build_id) \ diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h index 8a89b195c1fc..96690a55c62c 100644 --- a/tools/perf/util/build-id.h +++ b/tools/perf/util/build-id.h @@ -17,7 +17,6 @@ char *build_id_cache__kallsyms_path(const char *sbuild_id, char *bf, size_t size); char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size); -bool dso__build_id_is_kmod(const struct dso *dso, char *bf, size_t size); int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, struct perf_evsel *evsel, diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 8f2b068ff756..e7a98dbd2aed 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -1562,10 +1562,6 @@ int dso__load(struct dso *dso, struct map *map) if (!runtime_ss && syms_ss) runtime_ss = syms_ss; - if (syms_ss && syms_ss->type == DSO_BINARY_TYPE__BUILD_ID_CACHE) - if (dso__build_id_is_kmod(dso, name, PATH_MAX)) - kmod = true; - if (syms_ss) ret = dso__load_sym(dso, map, syms_ss, runtime_ss, kmod); else -- cgit v1.2.3 From 47b2c3fff4932e6fc17ce13d51a43c6969714e20 Mon Sep 17 00:00:00 2001 From: Bilal Amarni Date: Thu, 8 Jun 2017 14:47:26 +0100 Subject: security/keys: add CONFIG_KEYS_COMPAT to Kconfig CONFIG_KEYS_COMPAT is defined in arch-specific Kconfigs and is missing for several 64-bit architectures : mips, parisc, tile. At the moment and for those architectures, calling in 32-bit userspace the keyctl syscall would return an ENOSYS error. This patch moves the CONFIG_KEYS_COMPAT option to security/keys/Kconfig, to make sure the compatibility wrapper is registered by default for any 64-bit architecture as long as it is configured with CONFIG_COMPAT. [DH: Modified to remove arm64 compat enablement also as requested by Eric Biggers] Signed-off-by: Bilal Amarni Signed-off-by: David Howells Reviewed-by: Arnd Bergmann cc: Eric Biggers Signed-off-by: James Morris --- arch/arm64/Kconfig | 4 ---- arch/powerpc/Kconfig | 5 ----- arch/s390/Kconfig | 3 --- arch/sparc/Kconfig | 3 --- arch/x86/Kconfig | 4 ---- security/keys/Kconfig | 4 ++++ 6 files changed, 4 insertions(+), 19 deletions(-) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 3dcd7ec69bca..b2024db225a9 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -1084,10 +1084,6 @@ config SYSVIPC_COMPAT def_bool y depends on COMPAT && SYSVIPC -config KEYS_COMPAT - def_bool y - depends on COMPAT && KEYS - endmenu menu "Power management options" diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index f7c8f9972f61..83d2e0f43c26 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -1215,11 +1215,6 @@ source "arch/powerpc/Kconfig.debug" source "security/Kconfig" -config KEYS_COMPAT - bool - depends on COMPAT && KEYS - default y - source "crypto/Kconfig" config PPC_LIB_RHEAP diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index e161fafb495b..6967addc6a89 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -363,9 +363,6 @@ config COMPAT config SYSVIPC_COMPAT def_bool y if COMPAT && SYSVIPC -config KEYS_COMPAT - def_bool y if COMPAT && KEYS - config SMP def_bool y prompt "Symmetric multi-processing support" diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index b558c9e29de3..5639c9fe5b55 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -577,9 +577,6 @@ config SYSVIPC_COMPAT depends on COMPAT && SYSVIPC default y -config KEYS_COMPAT - def_bool y if COMPAT && KEYS - endmenu source "net/Kconfig" diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 4ccfacc7232a..0efb4c9497bc 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -2776,10 +2776,6 @@ config COMPAT_FOR_U64_ALIGNMENT config SYSVIPC_COMPAT def_bool y depends on SYSVIPC - -config KEYS_COMPAT - def_bool y - depends on KEYS endif endmenu diff --git a/security/keys/Kconfig b/security/keys/Kconfig index 6fd95f76bfae..00b7431a8aeb 100644 --- a/security/keys/Kconfig +++ b/security/keys/Kconfig @@ -20,6 +20,10 @@ config KEYS If you are unsure as to whether this is required, answer N. +config KEYS_COMPAT + def_bool y + depends on COMPAT && KEYS + config PERSISTENT_KEYRINGS bool "Enable register of persistent per-UID keyrings" depends on KEYS -- cgit v1.2.3 From 381f20fceba8ea540aef5241a9099f4552700d0c Mon Sep 17 00:00:00 2001 From: Davidlohr Bueso Date: Thu, 8 Jun 2017 14:47:34 +0100 Subject: security: use READ_ONCE instead of deprecated ACCESS_ONCE With the new standardized functions, we can replace all ACCESS_ONCE() calls across relevant security/keyrings/. ACCESS_ONCE() does not work reliably on non-scalar types. For example gcc 4.6 and 4.7 might remove the volatile tag for such accesses during the SRA (scalar replacement of aggregates) step: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58145 Update the new calls regardless of if it is a scalar type, this is cleaner than having three alternatives. Signed-off-by: Davidlohr Bueso Signed-off-by: David Howells Signed-off-by: James Morris --- security/keys/keyring.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/security/keys/keyring.c b/security/keys/keyring.c index 4d1678e4586f..de81793f9920 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c @@ -706,7 +706,7 @@ descend_to_keyring: * Non-keyrings avoid the leftmost branch of the root entirely (root * slots 1-15). */ - ptr = ACCESS_ONCE(keyring->keys.root); + ptr = READ_ONCE(keyring->keys.root); if (!ptr) goto not_this_keyring; @@ -720,7 +720,7 @@ descend_to_keyring: if ((shortcut->index_key[0] & ASSOC_ARRAY_FAN_MASK) != 0) goto not_this_keyring; - ptr = ACCESS_ONCE(shortcut->next_node); + ptr = READ_ONCE(shortcut->next_node); node = assoc_array_ptr_to_node(ptr); goto begin_node; } @@ -740,7 +740,7 @@ descend_to_node: if (assoc_array_ptr_is_shortcut(ptr)) { shortcut = assoc_array_ptr_to_shortcut(ptr); smp_read_barrier_depends(); - ptr = ACCESS_ONCE(shortcut->next_node); + ptr = READ_ONCE(shortcut->next_node); BUG_ON(!assoc_array_ptr_is_node(ptr)); } node = assoc_array_ptr_to_node(ptr); @@ -752,7 +752,7 @@ begin_node: ascend_to_node: /* Go through the slots in a node */ for (; slot < ASSOC_ARRAY_FAN_OUT; slot++) { - ptr = ACCESS_ONCE(node->slots[slot]); + ptr = READ_ONCE(node->slots[slot]); if (assoc_array_ptr_is_meta(ptr) && node->back_pointer) goto descend_to_node; @@ -790,13 +790,13 @@ ascend_to_node: /* We've dealt with all the slots in the current node, so now we need * to ascend to the parent and continue processing there. */ - ptr = ACCESS_ONCE(node->back_pointer); + ptr = READ_ONCE(node->back_pointer); slot = node->parent_slot; if (ptr && assoc_array_ptr_is_shortcut(ptr)) { shortcut = assoc_array_ptr_to_shortcut(ptr); smp_read_barrier_depends(); - ptr = ACCESS_ONCE(shortcut->back_pointer); + ptr = READ_ONCE(shortcut->back_pointer); slot = shortcut->parent_slot; } if (!ptr) -- cgit v1.2.3 From 4e880168e9ffb1cdbdb72b3b48ab0324b30c2d62 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 8 Jun 2017 14:47:49 +0100 Subject: X.509: Fix error code in x509_cert_parse() We forgot to set the error code on this path so it could result in returning NULL which leads to a NULL dereference. Fixes: db6c43bd2132 ("crypto: KEYS: convert public key and digsig asym to the akcipher api") Signed-off-by: Dan Carpenter Signed-off-by: David Howells Signed-off-by: James Morris --- crypto/asymmetric_keys/x509_cert_parser.c | 1 + 1 file changed, 1 insertion(+) diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c index c80765b211cf..dd03fead1ca3 100644 --- a/crypto/asymmetric_keys/x509_cert_parser.c +++ b/crypto/asymmetric_keys/x509_cert_parser.c @@ -102,6 +102,7 @@ struct x509_certificate *x509_cert_parse(const void *data, size_t datalen) } } + ret = -ENOMEM; cert->pub->key = kmemdup(ctx->key, ctx->key_size, GFP_KERNEL); if (!cert->pub->key) goto error_decode; -- cgit v1.2.3 From 41f1c53e0d7d6e79087d5f5e18c467747126a3fc Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Thu, 8 Jun 2017 14:47:56 +0100 Subject: KEYS: Delete an error message for a failed memory allocation in get_derived_key() Omit an extra message for a memory allocation failure in this function. This issue was detected by using the Coccinelle software. Link: http://events.linuxfoundation.org/sites/events/files/slides/LCJ16-Refactor_Strings-WSang_0.pdf Signed-off-by: Markus Elfring Signed-off-by: David Howells Signed-off-by: James Morris --- security/keys/encrypted-keys/encrypted.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c index 0010955d7876..2ab48eab29a1 100644 --- a/security/keys/encrypted-keys/encrypted.c +++ b/security/keys/encrypted-keys/encrypted.c @@ -385,10 +385,9 @@ static int get_derived_key(u8 *derived_key, enum derived_key_type key_type, derived_buf_len = HASH_SIZE; derived_buf = kzalloc(derived_buf_len, GFP_KERNEL); - if (!derived_buf) { - pr_err("encrypted_key: out of memory\n"); + if (!derived_buf) return -ENOMEM; - } + if (key_type) strcpy(derived_buf, "AUTH_KEY"); else -- cgit v1.2.3 From d636bd9f12a66ea3775c9fabbf3f8e118253467a Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 8 Jun 2017 14:48:03 +0100 Subject: KEYS: put keyring if install_session_keyring_to_cred() fails In join_session_keyring(), if install_session_keyring_to_cred() were to fail, we would leak the keyring reference, just like in the bug fixed by commit 23567fd052a9 ("KEYS: Fix keyring ref leak in join_session_keyring()"). Fortunately this cannot happen currently, but we really should be more careful. Do this by adding and using a new error label at which the keyring reference is dropped. Signed-off-by: Eric Biggers Signed-off-by: David Howells Signed-off-by: James Morris --- security/keys/process_keys.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index 2217dfec7996..86bced9fdbdf 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c @@ -809,15 +809,14 @@ long join_session_keyring(const char *name) ret = PTR_ERR(keyring); goto error2; } else if (keyring == new->session_keyring) { - key_put(keyring); ret = 0; - goto error2; + goto error3; } /* we've got a keyring - now to install it */ ret = install_session_keyring_to_cred(new, keyring); if (ret < 0) - goto error2; + goto error3; commit_creds(new); mutex_unlock(&key_session_mutex); @@ -827,6 +826,8 @@ long join_session_keyring(const char *name) okay: return ret; +error3: + key_put(keyring); error2: mutex_unlock(&key_session_mutex); error: -- cgit v1.2.3 From e9ff56ac352446f55141aaef1553cee662b2e310 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 8 Jun 2017 14:48:10 +0100 Subject: KEYS: encrypted: avoid encrypting/decrypting stack buffers Since v4.9, the crypto API cannot (normally) be used to encrypt/decrypt stack buffers because the stack may be virtually mapped. Fix this for the padding buffers in encrypted-keys by using ZERO_PAGE for the encryption padding and by allocating a temporary heap buffer for the decryption padding. Tested with CONFIG_DEBUG_SG=y: keyctl new_session keyctl add user master "abcdefghijklmnop" @s keyid=$(keyctl add encrypted desc "new user:master 25" @s) datablob="$(keyctl pipe $keyid)" keyctl unlink $keyid keyid=$(keyctl add encrypted desc "load $datablob" @s) datablob2="$(keyctl pipe $keyid)" [ "$datablob" = "$datablob2" ] && echo "Success!" Cc: Andy Lutomirski Cc: Herbert Xu Cc: Mimi Zohar Cc: stable@vger.kernel.org # 4.9+ Signed-off-by: Eric Biggers Signed-off-by: David Howells Signed-off-by: James Morris --- security/keys/encrypted-keys/encrypted.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c index 2ab48eab29a1..d14f1a47a130 100644 --- a/security/keys/encrypted-keys/encrypted.c +++ b/security/keys/encrypted-keys/encrypted.c @@ -479,12 +479,9 @@ static int derived_key_encrypt(struct encrypted_key_payload *epayload, struct skcipher_request *req; unsigned int encrypted_datalen; u8 iv[AES_BLOCK_SIZE]; - unsigned int padlen; - char pad[16]; int ret; encrypted_datalen = roundup(epayload->decrypted_datalen, blksize); - padlen = encrypted_datalen - epayload->decrypted_datalen; req = init_skcipher_req(derived_key, derived_keylen); ret = PTR_ERR(req); @@ -492,11 +489,10 @@ static int derived_key_encrypt(struct encrypted_key_payload *epayload, goto out; dump_decrypted_data(epayload); - memset(pad, 0, sizeof pad); sg_init_table(sg_in, 2); sg_set_buf(&sg_in[0], epayload->decrypted_data, epayload->decrypted_datalen); - sg_set_buf(&sg_in[1], pad, padlen); + sg_set_page(&sg_in[1], ZERO_PAGE(0), AES_BLOCK_SIZE, 0); sg_init_table(sg_out, 1); sg_set_buf(sg_out, epayload->encrypted_data, encrypted_datalen); @@ -583,9 +579,14 @@ static int derived_key_decrypt(struct encrypted_key_payload *epayload, struct skcipher_request *req; unsigned int encrypted_datalen; u8 iv[AES_BLOCK_SIZE]; - char pad[16]; + u8 *pad; int ret; + /* Throwaway buffer to hold the unused zero padding at the end */ + pad = kmalloc(AES_BLOCK_SIZE, GFP_KERNEL); + if (!pad) + return -ENOMEM; + encrypted_datalen = roundup(epayload->decrypted_datalen, blksize); req = init_skcipher_req(derived_key, derived_keylen); ret = PTR_ERR(req); @@ -593,13 +594,12 @@ static int derived_key_decrypt(struct encrypted_key_payload *epayload, goto out; dump_encrypted_data(epayload, encrypted_datalen); - memset(pad, 0, sizeof pad); sg_init_table(sg_in, 1); sg_init_table(sg_out, 2); sg_set_buf(sg_in, epayload->encrypted_data, encrypted_datalen); sg_set_buf(&sg_out[0], epayload->decrypted_data, epayload->decrypted_datalen); - sg_set_buf(&sg_out[1], pad, sizeof pad); + sg_set_buf(&sg_out[1], pad, AES_BLOCK_SIZE); memcpy(iv, epayload->iv, sizeof(iv)); skcipher_request_set_crypt(req, sg_in, sg_out, encrypted_datalen, iv); @@ -611,6 +611,7 @@ static int derived_key_decrypt(struct encrypted_key_payload *epayload, goto out; dump_decrypted_data(epayload); out: + kfree(pad); return ret; } -- cgit v1.2.3 From 794b4bc292f5d31739d89c0202c54e7dc9bc3add Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 8 Jun 2017 14:48:18 +0100 Subject: KEYS: encrypted: fix buffer overread in valid_master_desc() With the 'encrypted' key type it was possible for userspace to provide a data blob ending with a master key description shorter than expected, e.g. 'keyctl add encrypted desc "new x" @s'. When validating such a master key description, validate_master_desc() could read beyond the end of the buffer. Fix this by using strncmp() instead of memcmp(). [Also clean up the code to deduplicate some logic.] Cc: Mimi Zohar Signed-off-by: Eric Biggers Signed-off-by: David Howells Signed-off-by: James Morris --- security/keys/encrypted-keys/encrypted.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c index d14f1a47a130..0f7b95de3b5f 100644 --- a/security/keys/encrypted-keys/encrypted.c +++ b/security/keys/encrypted-keys/encrypted.c @@ -141,23 +141,22 @@ static int valid_ecryptfs_desc(const char *ecryptfs_desc) */ static int valid_master_desc(const char *new_desc, const char *orig_desc) { - if (!memcmp(new_desc, KEY_TRUSTED_PREFIX, KEY_TRUSTED_PREFIX_LEN)) { - if (strlen(new_desc) == KEY_TRUSTED_PREFIX_LEN) - goto out; - if (orig_desc) - if (memcmp(new_desc, orig_desc, KEY_TRUSTED_PREFIX_LEN)) - goto out; - } else if (!memcmp(new_desc, KEY_USER_PREFIX, KEY_USER_PREFIX_LEN)) { - if (strlen(new_desc) == KEY_USER_PREFIX_LEN) - goto out; - if (orig_desc) - if (memcmp(new_desc, orig_desc, KEY_USER_PREFIX_LEN)) - goto out; - } else - goto out; + int prefix_len; + + if (!strncmp(new_desc, KEY_TRUSTED_PREFIX, KEY_TRUSTED_PREFIX_LEN)) + prefix_len = KEY_TRUSTED_PREFIX_LEN; + else if (!strncmp(new_desc, KEY_USER_PREFIX, KEY_USER_PREFIX_LEN)) + prefix_len = KEY_USER_PREFIX_LEN; + else + return -EINVAL; + + if (!new_desc[prefix_len]) + return -EINVAL; + + if (orig_desc && strncmp(new_desc, orig_desc, prefix_len)) + return -EINVAL; + return 0; -out: - return -EINVAL; } /* -- cgit v1.2.3 From 64d107d3acca1565c39c044c459fd18f70943534 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 8 Jun 2017 14:48:25 +0100 Subject: KEYS: encrypted: fix race causing incorrect HMAC calculations The encrypted-keys module was using a single global HMAC transform, which could be rekeyed by multiple threads concurrently operating on different keys, causing incorrect HMAC values to be calculated. Fix this by allocating a new HMAC transform whenever we need to calculate a HMAC. Also simplify things a bit by allocating the shash_desc's using SHASH_DESC_ON_STACK() for both the HMAC and unkeyed hashes. The following script reproduces the bug: keyctl new_session keyctl add user master "abcdefghijklmnop" @s for i in $(seq 2); do ( set -e for j in $(seq 1000); do keyid=$(keyctl add encrypted desc$i "new user:master 25" @s) datablob="$(keyctl pipe $keyid)" keyctl unlink $keyid > /dev/null keyid=$(keyctl add encrypted desc$i "load $datablob" @s) keyctl unlink $keyid > /dev/null done ) & done Output with bug: [ 439.691094] encrypted_key: bad hmac (-22) add_key: Invalid argument add_key: Invalid argument Cc: Mimi Zohar Cc: Herbert Xu Signed-off-by: Eric Biggers Signed-off-by: David Howells Signed-off-by: James Morris --- security/keys/encrypted-keys/encrypted.c | 115 +++++++++---------------------- 1 file changed, 32 insertions(+), 83 deletions(-) diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c index 0f7b95de3b5f..702c80662069 100644 --- a/security/keys/encrypted-keys/encrypted.c +++ b/security/keys/encrypted-keys/encrypted.c @@ -54,13 +54,7 @@ static int blksize; #define MAX_DATA_SIZE 4096 #define MIN_DATA_SIZE 20 -struct sdesc { - struct shash_desc shash; - char ctx[]; -}; - -static struct crypto_shash *hashalg; -static struct crypto_shash *hmacalg; +static struct crypto_shash *hash_tfm; enum { Opt_err = -1, Opt_new, Opt_load, Opt_update @@ -320,53 +314,38 @@ error: return ukey; } -static struct sdesc *alloc_sdesc(struct crypto_shash *alg) -{ - struct sdesc *sdesc; - int size; - - size = sizeof(struct shash_desc) + crypto_shash_descsize(alg); - sdesc = kmalloc(size, GFP_KERNEL); - if (!sdesc) - return ERR_PTR(-ENOMEM); - sdesc->shash.tfm = alg; - sdesc->shash.flags = 0x0; - return sdesc; -} - -static int calc_hmac(u8 *digest, const u8 *key, unsigned int keylen, +static int calc_hash(struct crypto_shash *tfm, u8 *digest, const u8 *buf, unsigned int buflen) { - struct sdesc *sdesc; - int ret; + SHASH_DESC_ON_STACK(desc, tfm); + int err; - sdesc = alloc_sdesc(hmacalg); - if (IS_ERR(sdesc)) { - pr_info("encrypted_key: can't alloc %s\n", hmac_alg); - return PTR_ERR(sdesc); - } + desc->tfm = tfm; + desc->flags = 0; - ret = crypto_shash_setkey(hmacalg, key, keylen); - if (!ret) - ret = crypto_shash_digest(&sdesc->shash, buf, buflen, digest); - kfree(sdesc); - return ret; + err = crypto_shash_digest(desc, buf, buflen, digest); + shash_desc_zero(desc); + return err; } -static int calc_hash(u8 *digest, const u8 *buf, unsigned int buflen) +static int calc_hmac(u8 *digest, const u8 *key, unsigned int keylen, + const u8 *buf, unsigned int buflen) { - struct sdesc *sdesc; - int ret; + struct crypto_shash *tfm; + int err; - sdesc = alloc_sdesc(hashalg); - if (IS_ERR(sdesc)) { - pr_info("encrypted_key: can't alloc %s\n", hash_alg); - return PTR_ERR(sdesc); + tfm = crypto_alloc_shash(hmac_alg, 0, CRYPTO_ALG_ASYNC); + if (IS_ERR(tfm)) { + pr_err("encrypted_key: can't alloc %s transform: %ld\n", + hmac_alg, PTR_ERR(tfm)); + return PTR_ERR(tfm); } - ret = crypto_shash_digest(&sdesc->shash, buf, buflen, digest); - kfree(sdesc); - return ret; + err = crypto_shash_setkey(tfm, key, keylen); + if (!err) + err = calc_hash(tfm, digest, buf, buflen); + crypto_free_shash(tfm); + return err; } enum derived_key_type { ENC_KEY, AUTH_KEY }; @@ -394,7 +373,7 @@ static int get_derived_key(u8 *derived_key, enum derived_key_type key_type, memcpy(derived_buf + strlen(derived_buf) + 1, master_key, master_keylen); - ret = calc_hash(derived_key, derived_buf, derived_buf_len); + ret = calc_hash(hash_tfm, derived_key, derived_buf, derived_buf_len); kfree(derived_buf); return ret; } @@ -998,47 +977,17 @@ struct key_type key_type_encrypted = { }; EXPORT_SYMBOL_GPL(key_type_encrypted); -static void encrypted_shash_release(void) -{ - if (hashalg) - crypto_free_shash(hashalg); - if (hmacalg) - crypto_free_shash(hmacalg); -} - -static int __init encrypted_shash_alloc(void) +static int __init init_encrypted(void) { int ret; - hmacalg = crypto_alloc_shash(hmac_alg, 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(hmacalg)) { - pr_info("encrypted_key: could not allocate crypto %s\n", - hmac_alg); - return PTR_ERR(hmacalg); + hash_tfm = crypto_alloc_shash(hash_alg, 0, CRYPTO_ALG_ASYNC); + if (IS_ERR(hash_tfm)) { + pr_err("encrypted_key: can't allocate %s transform: %ld\n", + hash_alg, PTR_ERR(hash_tfm)); + return PTR_ERR(hash_tfm); } - hashalg = crypto_alloc_shash(hash_alg, 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(hashalg)) { - pr_info("encrypted_key: could not allocate crypto %s\n", - hash_alg); - ret = PTR_ERR(hashalg); - goto hashalg_fail; - } - - return 0; - -hashalg_fail: - crypto_free_shash(hmacalg); - return ret; -} - -static int __init init_encrypted(void) -{ - int ret; - - ret = encrypted_shash_alloc(); - if (ret < 0) - return ret; ret = aes_get_sizes(); if (ret < 0) goto out; @@ -1047,14 +996,14 @@ static int __init init_encrypted(void) goto out; return 0; out: - encrypted_shash_release(); + crypto_free_shash(hash_tfm); return ret; } static void __exit cleanup_encrypted(void) { - encrypted_shash_release(); + crypto_free_shash(hash_tfm); unregister_key_type(&key_type_encrypted); } -- cgit v1.2.3 From 0f534e4a13496b02ae284f50fcb0263f6ea37007 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 8 Jun 2017 14:48:32 +0100 Subject: KEYS: encrypted: use constant-time HMAC comparison MACs should, in general, be compared using crypto_memneq() to prevent timing attacks. Cc: Mimi Zohar Cc: Herbert Xu Signed-off-by: Eric Biggers Signed-off-by: David Howells Signed-off-by: James Morris --- security/keys/encrypted-keys/encrypted.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c index 702c80662069..5c98c2fe03f0 100644 --- a/security/keys/encrypted-keys/encrypted.c +++ b/security/keys/encrypted-keys/encrypted.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -534,8 +535,8 @@ static int datablob_hmac_verify(struct encrypted_key_payload *epayload, ret = calc_hmac(digest, derived_key, sizeof derived_key, p, len); if (ret < 0) goto out; - ret = memcmp(digest, epayload->format + epayload->datablob_len, - sizeof digest); + ret = crypto_memneq(digest, epayload->format + epayload->datablob_len, + sizeof(digest)); if (ret) { ret = -EINVAL; dump_hmac("datablob", -- cgit v1.2.3 From 5649645d725c73df4302428ee4e02c869248b4c5 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 8 Jun 2017 14:48:40 +0100 Subject: KEYS: fix dereferencing NULL payload with nonzero length sys_add_key() and the KEYCTL_UPDATE operation of sys_keyctl() allowed a NULL payload with nonzero length to be passed to the key type's ->preparse(), ->instantiate(), and/or ->update() methods. Various key types including asymmetric, cifs.idmap, cifs.spnego, and pkcs7_test did not handle this case, allowing an unprivileged user to trivially cause a NULL pointer dereference (kernel oops) if one of these key types was present. Fix it by doing the copy_from_user() when 'plen' is nonzero rather than when '_payload' is non-NULL, causing the syscall to fail with EFAULT as expected when an invalid buffer is specified. Cc: stable@vger.kernel.org # 2.6.10+ Signed-off-by: Eric Biggers Signed-off-by: David Howells Signed-off-by: James Morris --- security/keys/keyctl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 447a7d5cee0f..94c2790f8283 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c @@ -99,7 +99,7 @@ SYSCALL_DEFINE5(add_key, const char __user *, _type, /* pull the payload in if one was supplied */ payload = NULL; - if (_payload) { + if (plen) { ret = -ENOMEM; payload = kvmalloc(plen, GFP_KERNEL); if (!payload) @@ -324,7 +324,7 @@ long keyctl_update_key(key_serial_t id, /* pull the payload in if one was supplied */ payload = NULL; - if (_payload) { + if (plen) { ret = -ENOMEM; payload = kmalloc(plen, GFP_KERNEL); if (!payload) -- cgit v1.2.3 From 63a0b0509e700717a59f049ec6e4e04e903c7fe2 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 8 Jun 2017 14:48:47 +0100 Subject: KEYS: fix freeing uninitialized memory in key_update() key_update() freed the key_preparsed_payload even if it was not initialized first. This would cause a crash if userspace called keyctl_update() on a key with type like "asymmetric" that has a ->preparse() method but not an ->update() method. Possibly it could even be triggered for other key types by racing with keyctl_setperm() to make the KEY_NEED_WRITE check fail (the permission was already checked, so normally it wouldn't fail there). Reproducer with key type "asymmetric", given a valid cert.der: keyctl new_session keyid=$(keyctl padd asymmetric desc @s < cert.der) keyctl setperm $keyid 0x3f000000 keyctl update $keyid data [ 150.686666] BUG: unable to handle kernel NULL pointer dereference at 0000000000000001 [ 150.687601] IP: asymmetric_key_free_kids+0x12/0x30 [ 150.688139] PGD 38a3d067 [ 150.688141] PUD 3b3de067 [ 150.688447] PMD 0 [ 150.688745] [ 150.689160] Oops: 0000 [#1] SMP [ 150.689455] Modules linked in: [ 150.689769] CPU: 1 PID: 2478 Comm: keyctl Not tainted 4.11.0-rc4-xfstests-00187-ga9f6b6b8cd2f #742 [ 150.690916] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-20170228_101828-anatol 04/01/2014 [ 150.692199] task: ffff88003b30c480 task.stack: ffffc90000350000 [ 150.692952] RIP: 0010:asymmetric_key_free_kids+0x12/0x30 [ 150.693556] RSP: 0018:ffffc90000353e58 EFLAGS: 00010202 [ 150.694142] RAX: 0000000000000000 RBX: 0000000000000001 RCX: 0000000000000004 [ 150.694845] RDX: ffffffff81ee3920 RSI: ffff88003d4b0700 RDI: 0000000000000001 [ 150.697569] RBP: ffffc90000353e60 R08: ffff88003d5d2140 R09: 0000000000000000 [ 150.702483] R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000001 [ 150.707393] R13: 0000000000000004 R14: ffff880038a4d2d8 R15: 000000000040411f [ 150.709720] FS: 00007fcbcee35700(0000) GS:ffff88003fd00000(0000) knlGS:0000000000000000 [ 150.711504] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 150.712733] CR2: 0000000000000001 CR3: 0000000039eab000 CR4: 00000000003406e0 [ 150.714487] Call Trace: [ 150.714975] asymmetric_key_free_preparse+0x2f/0x40 [ 150.715907] key_update+0xf7/0x140 [ 150.716560] ? key_default_cmp+0x20/0x20 [ 150.717319] keyctl_update_key+0xb0/0xe0 [ 150.718066] SyS_keyctl+0x109/0x130 [ 150.718663] entry_SYSCALL_64_fastpath+0x1f/0xc2 [ 150.719440] RIP: 0033:0x7fcbce75ff19 [ 150.719926] RSP: 002b:00007ffd5d167088 EFLAGS: 00000206 ORIG_RAX: 00000000000000fa [ 150.720918] RAX: ffffffffffffffda RBX: 0000000000404d80 RCX: 00007fcbce75ff19 [ 150.721874] RDX: 00007ffd5d16785e RSI: 000000002866cd36 RDI: 0000000000000002 [ 150.722827] RBP: 0000000000000006 R08: 000000002866cd36 R09: 00007ffd5d16785e [ 150.723781] R10: 0000000000000004 R11: 0000000000000206 R12: 0000000000404d80 [ 150.724650] R13: 00007ffd5d16784d R14: 00007ffd5d167238 R15: 000000000040411f [ 150.725447] Code: 83 c4 08 31 c0 5b 41 5c 41 5d 41 5e 41 5f 5d c3 66 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 85 ff 74 23 55 48 89 e5 53 48 89 fb <48> 8b 3f e8 06 21 c5 ff 48 8b 7b 08 e8 fd 20 c5 ff 48 89 df e8 [ 150.727489] RIP: asymmetric_key_free_kids+0x12/0x30 RSP: ffffc90000353e58 [ 150.728117] CR2: 0000000000000001 [ 150.728430] ---[ end trace f7f8fe1da2d5ae8d ]--- Fixes: 4d8c0250b841 ("KEYS: Call ->free_preparse() even after ->preparse() returns an error") Cc: stable@vger.kernel.org # 3.17+ Signed-off-by: Eric Biggers Signed-off-by: David Howells Signed-off-by: James Morris --- security/keys/key.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/security/keys/key.c b/security/keys/key.c index 455c04d80bbb..cbae368c0e57 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -966,12 +966,11 @@ int key_update(key_ref_t key_ref, const void *payload, size_t plen) /* the key must be writable */ ret = key_permission(key_ref, KEY_NEED_WRITE); if (ret < 0) - goto error; + return ret; /* attempt to update it if supported */ - ret = -EOPNOTSUPP; if (!key->type->update) - goto error; + return -EOPNOTSUPP; memset(&prep, 0, sizeof(prep)); prep.data = payload; -- cgit v1.2.3 From 57070c850a03ee0cea654fc22cb8032fc3139d39 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 8 Jun 2017 14:48:57 +0100 Subject: KEYS: sanitize add_key() and keyctl() key payloads Before returning from add_key() or one of the keyctl() commands that takes in a key payload, zero the temporary buffer that was allocated to hold the key payload copied from userspace. This may contain sensitive key material that should not be kept around in the slab caches. Signed-off-by: Eric Biggers Signed-off-by: David Howells Signed-off-by: James Morris --- security/keys/keyctl.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 94c2790f8283..ab0b337c84b4 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c @@ -132,7 +132,10 @@ SYSCALL_DEFINE5(add_key, const char __user *, _type, key_ref_put(keyring_ref); error3: - kvfree(payload); + if (payload) { + memzero_explicit(payload, plen); + kvfree(payload); + } error2: kfree(description); error: @@ -347,7 +350,7 @@ long keyctl_update_key(key_serial_t id, key_ref_put(key_ref); error2: - kfree(payload); + kzfree(payload); error: return ret; } @@ -1093,7 +1096,10 @@ long keyctl_instantiate_key_common(key_serial_t id, keyctl_change_reqkey_auth(NULL); error2: - kvfree(payload); + if (payload) { + memzero_explicit(payload, plen); + kvfree(payload); + } error: return ret; } -- cgit v1.2.3 From 6966c74932b328b3d6df92b11b083bfbcd067986 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 8 Jun 2017 14:49:04 +0100 Subject: KEYS: user_defined: sanitize key payloads Zero the payloads of user and logon keys before freeing them. This prevents sensitive key material from being kept around in the slab caches after a key is released. Signed-off-by: Eric Biggers Signed-off-by: David Howells Signed-off-by: James Morris --- security/keys/user_defined.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c index 26605134f17a..3d8c68eba516 100644 --- a/security/keys/user_defined.c +++ b/security/keys/user_defined.c @@ -86,10 +86,18 @@ EXPORT_SYMBOL_GPL(user_preparse); */ void user_free_preparse(struct key_preparsed_payload *prep) { - kfree(prep->payload.data[0]); + kzfree(prep->payload.data[0]); } EXPORT_SYMBOL_GPL(user_free_preparse); +static void user_free_payload_rcu(struct rcu_head *head) +{ + struct user_key_payload *payload; + + payload = container_of(head, struct user_key_payload, rcu); + kzfree(payload); +} + /* * update a user defined key * - the key's semaphore is write-locked @@ -112,7 +120,7 @@ int user_update(struct key *key, struct key_preparsed_payload *prep) prep->payload.data[0] = NULL; if (zap) - kfree_rcu(zap, rcu); + call_rcu(&zap->rcu, user_free_payload_rcu); return ret; } EXPORT_SYMBOL_GPL(user_update); @@ -130,7 +138,7 @@ void user_revoke(struct key *key) if (upayload) { rcu_assign_keypointer(key, NULL); - kfree_rcu(upayload, rcu); + call_rcu(&upayload->rcu, user_free_payload_rcu); } } @@ -143,7 +151,7 @@ void user_destroy(struct key *key) { struct user_key_payload *upayload = key->payload.data[0]; - kfree(upayload); + kzfree(upayload); } EXPORT_SYMBOL_GPL(user_destroy); -- cgit v1.2.3 From a9dd74b252e04b7e41ffe78d418b896b33b70a13 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 8 Jun 2017 14:49:11 +0100 Subject: KEYS: encrypted: sanitize all key material For keys of type "encrypted", consistently zero sensitive key material before freeing it. This was already being done for the decrypted payloads of encrypted keys, but not for the master key and the keys derived from the master key. Out of an abundance of caution and because it is trivial to do so, also zero buffers containing the key payload in encrypted form, although depending on how the encrypted-keys feature is used such information does not necessarily need to be kept secret. Cc: Mimi Zohar Cc: David Safford Signed-off-by: Eric Biggers Signed-off-by: David Howells Signed-off-by: James Morris --- security/keys/encrypted-keys/encrypted.c | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c index 5c98c2fe03f0..bb6324d1ccec 100644 --- a/security/keys/encrypted-keys/encrypted.c +++ b/security/keys/encrypted-keys/encrypted.c @@ -375,7 +375,7 @@ static int get_derived_key(u8 *derived_key, enum derived_key_type key_type, memcpy(derived_buf + strlen(derived_buf) + 1, master_key, master_keylen); ret = calc_hash(hash_tfm, derived_key, derived_buf, derived_buf_len); - kfree(derived_buf); + kzfree(derived_buf); return ret; } @@ -507,6 +507,7 @@ static int datablob_hmac_append(struct encrypted_key_payload *epayload, if (!ret) dump_hmac(NULL, digest, HASH_SIZE); out: + memzero_explicit(derived_key, sizeof(derived_key)); return ret; } @@ -545,6 +546,7 @@ static int datablob_hmac_verify(struct encrypted_key_payload *epayload, dump_hmac("calc", digest, HASH_SIZE); } out: + memzero_explicit(derived_key, sizeof(derived_key)); return ret; } @@ -701,6 +703,7 @@ static int encrypted_key_decrypt(struct encrypted_key_payload *epayload, out: up_read(&mkey->sem); key_put(mkey); + memzero_explicit(derived_key, sizeof(derived_key)); return ret; } @@ -807,13 +810,13 @@ static int encrypted_instantiate(struct key *key, ret = encrypted_init(epayload, key->description, format, master_desc, decrypted_datalen, hex_encoded_iv); if (ret < 0) { - kfree(epayload); + kzfree(epayload); goto out; } rcu_assign_keypointer(key, epayload); out: - kfree(datablob); + kzfree(datablob); return ret; } @@ -822,8 +825,7 @@ static void encrypted_rcu_free(struct rcu_head *rcu) struct encrypted_key_payload *epayload; epayload = container_of(rcu, struct encrypted_key_payload, rcu); - memset(epayload->decrypted_data, 0, epayload->decrypted_datalen); - kfree(epayload); + kzfree(epayload); } /* @@ -881,7 +883,7 @@ static int encrypted_update(struct key *key, struct key_preparsed_payload *prep) rcu_assign_keypointer(key, new_epayload); call_rcu(&epayload->rcu, encrypted_rcu_free); out: - kfree(buf); + kzfree(buf); return ret; } @@ -939,33 +941,26 @@ static long encrypted_read(const struct key *key, char __user *buffer, up_read(&mkey->sem); key_put(mkey); + memzero_explicit(derived_key, sizeof(derived_key)); if (copy_to_user(buffer, ascii_buf, asciiblob_len) != 0) ret = -EFAULT; - kfree(ascii_buf); + kzfree(ascii_buf); return asciiblob_len; out: up_read(&mkey->sem); key_put(mkey); + memzero_explicit(derived_key, sizeof(derived_key)); return ret; } /* - * encrypted_destroy - before freeing the key, clear the decrypted data - * - * Before freeing the key, clear the memory containing the decrypted - * key data. + * encrypted_destroy - clear and free the key's payload */ static void encrypted_destroy(struct key *key) { - struct encrypted_key_payload *epayload = key->payload.data[0]; - - if (!epayload) - return; - - memzero_explicit(epayload->decrypted_data, epayload->decrypted_datalen); - kfree(key->payload.data[0]); + kzfree(key->payload.data[0]); } struct key_type key_type_encrypted = { -- cgit v1.2.3 From ee618b4619b72527aaed765f0f0b74072b281159 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 8 Jun 2017 14:49:18 +0100 Subject: KEYS: trusted: sanitize all key material As the previous patch did for encrypted-keys, zero sensitive any potentially sensitive data related to the "trusted" key type before it is freed. Notably, we were not zeroing the tpm_buf structures in which the actual key is stored for TPM seal and unseal, nor were we zeroing the trusted_key_payload in certain error paths. Cc: Mimi Zohar Cc: David Safford Signed-off-by: Eric Biggers Signed-off-by: David Howells Signed-off-by: James Morris --- security/keys/trusted.c | 50 ++++++++++++++++++++++--------------------------- 1 file changed, 22 insertions(+), 28 deletions(-) diff --git a/security/keys/trusted.c b/security/keys/trusted.c index 2ae31c5a87de..435e86e13879 100644 --- a/security/keys/trusted.c +++ b/security/keys/trusted.c @@ -70,7 +70,7 @@ static int TSS_sha1(const unsigned char *data, unsigned int datalen, } ret = crypto_shash_digest(&sdesc->shash, data, datalen, digest); - kfree(sdesc); + kzfree(sdesc); return ret; } @@ -114,7 +114,7 @@ static int TSS_rawhmac(unsigned char *digest, const unsigned char *key, if (!ret) ret = crypto_shash_final(&sdesc->shash, digest); out: - kfree(sdesc); + kzfree(sdesc); return ret; } @@ -165,7 +165,7 @@ static int TSS_authhmac(unsigned char *digest, const unsigned char *key, paramdigest, TPM_NONCE_SIZE, h1, TPM_NONCE_SIZE, h2, 1, &c, 0, 0); out: - kfree(sdesc); + kzfree(sdesc); return ret; } @@ -246,7 +246,7 @@ static int TSS_checkhmac1(unsigned char *buffer, if (memcmp(testhmac, authdata, SHA1_DIGEST_SIZE)) ret = -EINVAL; out: - kfree(sdesc); + kzfree(sdesc); return ret; } @@ -347,7 +347,7 @@ static int TSS_checkhmac2(unsigned char *buffer, if (memcmp(testhmac2, authdata2, SHA1_DIGEST_SIZE)) ret = -EINVAL; out: - kfree(sdesc); + kzfree(sdesc); return ret; } @@ -564,7 +564,7 @@ static int tpm_seal(struct tpm_buf *tb, uint16_t keytype, *bloblen = storedsize; } out: - kfree(td); + kzfree(td); return ret; } @@ -678,7 +678,7 @@ static int key_seal(struct trusted_key_payload *p, if (ret < 0) pr_info("trusted_key: srkseal failed (%d)\n", ret); - kfree(tb); + kzfree(tb); return ret; } @@ -703,7 +703,7 @@ static int key_unseal(struct trusted_key_payload *p, /* pull migratable flag out of sealed key */ p->migratable = p->key[--p->key_len]; - kfree(tb); + kzfree(tb); return ret; } @@ -1037,12 +1037,12 @@ static int trusted_instantiate(struct key *key, if (!ret && options->pcrlock) ret = pcrlock(options->pcrlock); out: - kfree(datablob); - kfree(options); + kzfree(datablob); + kzfree(options); if (!ret) rcu_assign_keypointer(key, payload); else - kfree(payload); + kzfree(payload); return ret; } @@ -1051,8 +1051,7 @@ static void trusted_rcu_free(struct rcu_head *rcu) struct trusted_key_payload *p; p = container_of(rcu, struct trusted_key_payload, rcu); - memset(p->key, 0, p->key_len); - kfree(p); + kzfree(p); } /* @@ -1094,13 +1093,13 @@ static int trusted_update(struct key *key, struct key_preparsed_payload *prep) ret = datablob_parse(datablob, new_p, new_o); if (ret != Opt_update) { ret = -EINVAL; - kfree(new_p); + kzfree(new_p); goto out; } if (!new_o->keyhandle) { ret = -EINVAL; - kfree(new_p); + kzfree(new_p); goto out; } @@ -1114,22 +1113,22 @@ static int trusted_update(struct key *key, struct key_preparsed_payload *prep) ret = key_seal(new_p, new_o); if (ret < 0) { pr_info("trusted_key: key_seal failed (%d)\n", ret); - kfree(new_p); + kzfree(new_p); goto out; } if (new_o->pcrlock) { ret = pcrlock(new_o->pcrlock); if (ret < 0) { pr_info("trusted_key: pcrlock failed (%d)\n", ret); - kfree(new_p); + kzfree(new_p); goto out; } } rcu_assign_keypointer(key, new_p); call_rcu(&p->rcu, trusted_rcu_free); out: - kfree(datablob); - kfree(new_o); + kzfree(datablob); + kzfree(new_o); return ret; } @@ -1158,24 +1157,19 @@ static long trusted_read(const struct key *key, char __user *buffer, for (i = 0; i < p->blob_len; i++) bufp = hex_byte_pack(bufp, p->blob[i]); if ((copy_to_user(buffer, ascii_buf, 2 * p->blob_len)) != 0) { - kfree(ascii_buf); + kzfree(ascii_buf); return -EFAULT; } - kfree(ascii_buf); + kzfree(ascii_buf); return 2 * p->blob_len; } /* - * trusted_destroy - before freeing the key, clear the decrypted data + * trusted_destroy - clear and free the key's payload */ static void trusted_destroy(struct key *key) { - struct trusted_key_payload *p = key->payload.data[0]; - - if (!p) - return; - memset(p->key, 0, p->key_len); - kfree(key->payload.data[0]); + kzfree(key->payload.data[0]); } struct key_type key_type_trusted = { -- cgit v1.2.3 From 0620fddb56dfaf0e1034eeb69d79c73b361debbf Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 8 Jun 2017 14:49:26 +0100 Subject: KEYS: sanitize key structs before freeing While a 'struct key' itself normally does not contain sensitive information, Documentation/security/keys.txt actually encourages this: "Having a payload is not required; and the payload can, in fact, just be a value stored in the struct key itself." In case someone has taken this advice, or will take this advice in the future, zero the key structure before freeing it. We might as well, and as a bonus this could make it a bit more difficult for an adversary to determine which keys have recently been in use. This is safe because the key_jar cache does not use a constructor. Signed-off-by: Eric Biggers Signed-off-by: David Howells Signed-off-by: James Morris --- include/linux/key.h | 1 - security/keys/gc.c | 4 +--- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/include/linux/key.h b/include/linux/key.h index 0c9b93b0d1f7..78e25aabedaf 100644 --- a/include/linux/key.h +++ b/include/linux/key.h @@ -173,7 +173,6 @@ struct key { #ifdef KEY_DEBUGGING unsigned magic; #define KEY_DEBUG_MAGIC 0x18273645u -#define KEY_DEBUG_MAGIC_X 0xf8e9dacbu #endif unsigned long flags; /* status flags (change with bitops) */ diff --git a/security/keys/gc.c b/security/keys/gc.c index 595becc6d0d2..87cb260e4890 100644 --- a/security/keys/gc.c +++ b/security/keys/gc.c @@ -158,9 +158,7 @@ static noinline void key_gc_unused_keys(struct list_head *keys) kfree(key->description); -#ifdef KEY_DEBUGGING - key->magic = KEY_DEBUG_MAGIC_X; -#endif + memzero_explicit(key, sizeof(*key)); kmem_cache_free(key_jar, key); } } -- cgit v1.2.3 From bbe240454d86be95151e0ecfd6ac55fe5ef5a6f5 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 8 Jun 2017 14:49:34 +0100 Subject: KEYS: DH: forbid using digest_null as the KDF hash Requesting "digest_null" in the keyctl_kdf_params caused an infinite loop in kdf_ctr() because the "null" hash has a digest size of 0. Fix it by rejecting hash algorithms with a digest size of 0. Signed-off-by: Eric Biggers Signed-off-by: David Howells Acked-by: Stephan Mueller Signed-off-by: James Morris --- security/keys/dh.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/security/keys/dh.c b/security/keys/dh.c index e603bd912e4c..8abc70ebe22d 100644 --- a/security/keys/dh.c +++ b/security/keys/dh.c @@ -89,6 +89,7 @@ static int kdf_alloc(struct kdf_sdesc **sdesc_ret, char *hashname) struct crypto_shash *tfm; struct kdf_sdesc *sdesc; int size; + int err; /* allocate synchronous hash */ tfm = crypto_alloc_shash(hashname, 0, 0); @@ -97,16 +98,25 @@ static int kdf_alloc(struct kdf_sdesc **sdesc_ret, char *hashname) return PTR_ERR(tfm); } + err = -EINVAL; + if (crypto_shash_digestsize(tfm) == 0) + goto out_free_tfm; + + err = -ENOMEM; size = sizeof(struct shash_desc) + crypto_shash_descsize(tfm); sdesc = kmalloc(size, GFP_KERNEL); if (!sdesc) - return -ENOMEM; + goto out_free_tfm; sdesc->shash.tfm = tfm; sdesc->shash.flags = 0x0; *sdesc_ret = sdesc; return 0; + +out_free_tfm: + crypto_free_shash(tfm); + return err; } static void kdf_dealloc(struct kdf_sdesc *sdesc) -- cgit v1.2.3 From 281590b4221779dbc4a5e2c33c0c5b0239cfe794 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 8 Jun 2017 14:49:42 +0100 Subject: KEYS: DH: don't feed uninitialized "otherinfo" into KDF If userspace called KEYCTL_DH_COMPUTE with kdf_params containing NULL otherinfo but nonzero otherinfolen, the kernel would allocate a buffer for the otherinfo, then feed it into the KDF without initializing it. Fix this by always doing the copy from userspace (which will fail with EFAULT in this scenario). Signed-off-by: Eric Biggers Signed-off-by: David Howells Acked-by: Stephan Mueller Signed-off-by: James Morris --- security/keys/dh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/security/keys/dh.c b/security/keys/dh.c index 8abc70ebe22d..1c1cac677041 100644 --- a/security/keys/dh.c +++ b/security/keys/dh.c @@ -317,7 +317,7 @@ long __keyctl_dh_compute(struct keyctl_dh_params __user *params, * Concatenate SP800-56A otherinfo past DH shared secret -- the * input to the KDF is (DH shared secret || otherinfo) */ - if (kdfcopy && kdfcopy->otherinfo && + if (kdfcopy && copy_from_user(kbuf + resultlen, kdfcopy->otherinfo, kdfcopy->otherinfolen) != 0) { ret = -EFAULT; -- cgit v1.2.3 From 0ddd9f1a6b7e5746b52959f645fc66859b805e88 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 8 Jun 2017 14:49:49 +0100 Subject: KEYS: DH: ensure the KDF counter is properly aligned Accessing a 'u8[4]' through a '__be32 *' violates alignment rules. Just make the counter a __be32 instead. Signed-off-by: Eric Biggers Signed-off-by: David Howells Acked-by: Stephan Mueller Signed-off-by: James Morris --- security/keys/dh.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/security/keys/dh.c b/security/keys/dh.c index 1c1cac677041..63ac87d430db 100644 --- a/security/keys/dh.c +++ b/security/keys/dh.c @@ -130,14 +130,6 @@ static void kdf_dealloc(struct kdf_sdesc *sdesc) kzfree(sdesc); } -/* convert 32 bit integer into its string representation */ -static inline void crypto_kw_cpu_to_be32(u32 val, u8 *buf) -{ - __be32 *a = (__be32 *)buf; - - *a = cpu_to_be32(val); -} - /* * Implementation of the KDF in counter mode according to SP800-108 section 5.1 * as well as SP800-56A section 5.8.1 (Single-step KDF). @@ -154,16 +146,14 @@ static int kdf_ctr(struct kdf_sdesc *sdesc, const u8 *src, unsigned int slen, unsigned int h = crypto_shash_digestsize(desc->tfm); int err = 0; u8 *dst_orig = dst; - u32 i = 1; - u8 iteration[sizeof(u32)]; + __be32 counter = cpu_to_be32(1); while (dlen) { err = crypto_shash_init(desc); if (err) goto err; - crypto_kw_cpu_to_be32(i, iteration); - err = crypto_shash_update(desc, iteration, sizeof(u32)); + err = crypto_shash_update(desc, (u8 *)&counter, sizeof(__be32)); if (err) goto err; @@ -189,7 +179,7 @@ static int kdf_ctr(struct kdf_sdesc *sdesc, const u8 *src, unsigned int slen, dlen -= h; dst += h; - i++; + counter = cpu_to_be32(be32_to_cpu(counter) + 1); } } -- cgit v1.2.3 From a77395447b0aeab9473a066ff28fbee01130206b Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 8 Jun 2017 14:49:57 +0100 Subject: KEYS: DH: add __user annotations to keyctl_kdf_params Signed-off-by: Eric Biggers Signed-off-by: David Howells Acked-by: Stephan Mueller Signed-off-by: James Morris --- include/uapi/linux/keyctl.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/uapi/linux/keyctl.h b/include/uapi/linux/keyctl.h index 201c6644b237..ef16df06642a 100644 --- a/include/uapi/linux/keyctl.h +++ b/include/uapi/linux/keyctl.h @@ -70,8 +70,8 @@ struct keyctl_dh_params { }; struct keyctl_kdf_params { - char *hashname; - char *otherinfo; + char __user *hashname; + char __user *otherinfo; __u32 otherinfolen; __u32 __spare[8]; }; -- cgit v1.2.3 From da7798a7b6714cf35ea6084ad6b1fe0497566cf2 Mon Sep 17 00:00:00 2001 From: Loganaden Velvindron Date: Thu, 8 Jun 2017 14:50:04 +0100 Subject: crypto : asymmetric_keys : verify_pefile:zero memory content before freeing Signed-off-by: Loganaden Velvindron Signed-off-by: Yasir Auleear Signed-off-by: David Howells Signed-off-by: James Morris --- crypto/asymmetric_keys/verify_pefile.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crypto/asymmetric_keys/verify_pefile.c b/crypto/asymmetric_keys/verify_pefile.c index 672a94c2c3ff..d178650fd524 100644 --- a/crypto/asymmetric_keys/verify_pefile.c +++ b/crypto/asymmetric_keys/verify_pefile.c @@ -381,7 +381,7 @@ static int pefile_digest_pe(const void *pebuf, unsigned int pelen, } error: - kfree(desc); + kzfree(desc); error_no_desc: crypto_free_shash(tfm); kleave(" = %d", ret); @@ -450,6 +450,6 @@ int verify_pefile_signature(const void *pebuf, unsigned pelen, ret = pefile_digest_pe(pebuf, pelen, &ctx); error: - kfree(ctx.digest); + kzfree(ctx.digest); return ret; } -- cgit v1.2.3 From 7cbe0932c2f2014d6e24e716e79ea3910b468950 Mon Sep 17 00:00:00 2001 From: Mat Martineau Date: Thu, 8 Jun 2017 14:50:11 +0100 Subject: KEYS: Convert KEYCTL_DH_COMPUTE to use the crypto KPP API The initial Diffie-Hellman computation made direct use of the MPI library because the crypto module did not support DH at the time. Now that KPP is implemented, KEYCTL_DH_COMPUTE should use it to get rid of duplicate code and leverage possible hardware acceleration. This fixes an issue whereby the input to the KDF computation would include additional uninitialized memory when the result of the Diffie-Hellman computation was shorter than the input prime number. Signed-off-by: Mat Martineau Signed-off-by: David Howells Signed-off-by: James Morris --- security/keys/Kconfig | 2 +- security/keys/dh.c | 272 +++++++++++++++++++++++++++++++------------------- 2 files changed, 171 insertions(+), 103 deletions(-) diff --git a/security/keys/Kconfig b/security/keys/Kconfig index 00b7431a8aeb..a7a23b5541f8 100644 --- a/security/keys/Kconfig +++ b/security/keys/Kconfig @@ -93,9 +93,9 @@ config ENCRYPTED_KEYS config KEY_DH_OPERATIONS bool "Diffie-Hellman operations on retained keys" depends on KEYS - select MPILIB select CRYPTO select CRYPTO_HASH + select CRYPTO_DH help This option provides support for calculating Diffie-Hellman public keys and shared secrets using values stored as keys diff --git a/security/keys/dh.c b/security/keys/dh.c index 63ac87d430db..4755d4b4f945 100644 --- a/security/keys/dh.c +++ b/security/keys/dh.c @@ -8,34 +8,17 @@ * 2 of the License, or (at your option) any later version. */ -#include #include #include +#include #include #include +#include +#include #include #include "internal.h" -/* - * Public key or shared secret generation function [RFC2631 sec 2.1.1] - * - * ya = g^xa mod p; - * or - * ZZ = yb^xa mod p; - * - * where xa is the local private key, ya is the local public key, g is - * the generator, p is the prime, yb is the remote public key, and ZZ - * is the shared secret. - * - * Both are the same calculation, so g or yb are the "base" and ya or - * ZZ are the "result". - */ -static int do_dh(MPI result, MPI base, MPI xa, MPI p) -{ - return mpi_powm(result, base, xa, p); -} - -static ssize_t mpi_from_key(key_serial_t keyid, size_t maxlen, MPI *mpi) +static ssize_t dh_data_from_key(key_serial_t keyid, void **data) { struct key *key; key_ref_t key_ref; @@ -56,19 +39,17 @@ static ssize_t mpi_from_key(key_serial_t keyid, size_t maxlen, MPI *mpi) status = key_validate(key); if (status == 0) { const struct user_key_payload *payload; + uint8_t *duplicate; payload = user_key_payload_locked(key); - if (maxlen == 0) { - *mpi = NULL; + duplicate = kmemdup(payload->data, payload->datalen, + GFP_KERNEL); + if (duplicate) { + *data = duplicate; ret = payload->datalen; - } else if (payload->datalen <= maxlen) { - *mpi = mpi_read_raw_data(payload->data, - payload->datalen); - if (*mpi) - ret = payload->datalen; } else { - ret = -EINVAL; + ret = -ENOMEM; } } up_read(&key->sem); @@ -79,6 +60,29 @@ error: return ret; } +static void dh_free_data(struct dh *dh) +{ + kzfree(dh->key); + kzfree(dh->p); + kzfree(dh->g); +} + +struct dh_completion { + struct completion completion; + int err; +}; + +static void dh_crypto_done(struct crypto_async_request *req, int err) +{ + struct dh_completion *compl = req->data; + + if (err == -EINPROGRESS) + return; + + compl->err = err; + complete(&compl->completion); +} + struct kdf_sdesc { struct shash_desc shash; char ctx[]; @@ -140,7 +144,7 @@ static void kdf_dealloc(struct kdf_sdesc *sdesc) * 5.8.1.2). */ static int kdf_ctr(struct kdf_sdesc *sdesc, const u8 *src, unsigned int slen, - u8 *dst, unsigned int dlen) + u8 *dst, unsigned int dlen, unsigned int zlen) { struct shash_desc *desc = &sdesc->shash; unsigned int h = crypto_shash_digestsize(desc->tfm); @@ -157,6 +161,22 @@ static int kdf_ctr(struct kdf_sdesc *sdesc, const u8 *src, unsigned int slen, if (err) goto err; + if (zlen && h) { + u8 tmpbuffer[h]; + size_t chunk = min_t(size_t, zlen, h); + memset(tmpbuffer, 0, chunk); + + do { + err = crypto_shash_update(desc, tmpbuffer, + chunk); + if (err) + goto err; + + zlen -= chunk; + chunk = min_t(size_t, zlen, h); + } while (zlen); + } + if (src && slen) { err = crypto_shash_update(desc, src, slen); if (err) @@ -192,7 +212,7 @@ err: static int keyctl_dh_compute_kdf(struct kdf_sdesc *sdesc, char __user *buffer, size_t buflen, - uint8_t *kbuf, size_t kbuflen) + uint8_t *kbuf, size_t kbuflen, size_t lzero) { uint8_t *outbuf = NULL; int ret; @@ -203,7 +223,7 @@ static int keyctl_dh_compute_kdf(struct kdf_sdesc *sdesc, goto err; } - ret = kdf_ctr(sdesc, kbuf, kbuflen, outbuf, buflen); + ret = kdf_ctr(sdesc, kbuf, kbuflen, outbuf, buflen, lzero); if (ret) goto err; @@ -221,21 +241,26 @@ long __keyctl_dh_compute(struct keyctl_dh_params __user *params, struct keyctl_kdf_params *kdfcopy) { long ret; - MPI base, private, prime, result; - unsigned nbytes; + ssize_t dlen; + int secretlen; + int outlen; struct keyctl_dh_params pcopy; - uint8_t *kbuf; - ssize_t keylen; - size_t resultlen; + struct dh dh_inputs; + struct scatterlist outsg; + struct dh_completion compl; + struct crypto_kpp *tfm; + struct kpp_request *req; + uint8_t *secret; + uint8_t *outbuf; struct kdf_sdesc *sdesc = NULL; if (!params || (!buffer && buflen)) { ret = -EINVAL; - goto out; + goto out1; } if (copy_from_user(&pcopy, params, sizeof(pcopy)) != 0) { ret = -EFAULT; - goto out; + goto out1; } if (kdfcopy) { @@ -244,104 +269,147 @@ long __keyctl_dh_compute(struct keyctl_dh_params __user *params, if (buflen > KEYCTL_KDF_MAX_OUTPUT_LEN || kdfcopy->otherinfolen > KEYCTL_KDF_MAX_OI_LEN) { ret = -EMSGSIZE; - goto out; + goto out1; } /* get KDF name string */ hashname = strndup_user(kdfcopy->hashname, CRYPTO_MAX_ALG_NAME); if (IS_ERR(hashname)) { ret = PTR_ERR(hashname); - goto out; + goto out1; } /* allocate KDF from the kernel crypto API */ ret = kdf_alloc(&sdesc, hashname); kfree(hashname); if (ret) - goto out; + goto out1; } - /* - * If the caller requests postprocessing with a KDF, allow an - * arbitrary output buffer size since the KDF ensures proper truncation. - */ - keylen = mpi_from_key(pcopy.prime, kdfcopy ? SIZE_MAX : buflen, &prime); - if (keylen < 0 || !prime) { - /* buflen == 0 may be used to query the required buffer size, - * which is the prime key length. - */ - ret = keylen; - goto out; + memset(&dh_inputs, 0, sizeof(dh_inputs)); + + dlen = dh_data_from_key(pcopy.prime, &dh_inputs.p); + if (dlen < 0) { + ret = dlen; + goto out1; } + dh_inputs.p_size = dlen; - /* The result is never longer than the prime */ - resultlen = keylen; + dlen = dh_data_from_key(pcopy.base, &dh_inputs.g); + if (dlen < 0) { + ret = dlen; + goto out2; + } + dh_inputs.g_size = dlen; - keylen = mpi_from_key(pcopy.base, SIZE_MAX, &base); - if (keylen < 0 || !base) { - ret = keylen; - goto error1; + dlen = dh_data_from_key(pcopy.private, &dh_inputs.key); + if (dlen < 0) { + ret = dlen; + goto out2; } + dh_inputs.key_size = dlen; - keylen = mpi_from_key(pcopy.private, SIZE_MAX, &private); - if (keylen < 0 || !private) { - ret = keylen; - goto error2; + secretlen = crypto_dh_key_len(&dh_inputs); + secret = kmalloc(secretlen, GFP_KERNEL); + if (!secret) { + ret = -ENOMEM; + goto out2; + } + ret = crypto_dh_encode_key(secret, secretlen, &dh_inputs); + if (ret) + goto out3; + + tfm = crypto_alloc_kpp("dh", CRYPTO_ALG_TYPE_KPP, 0); + if (IS_ERR(tfm)) { + ret = PTR_ERR(tfm); + goto out3; + } + + ret = crypto_kpp_set_secret(tfm, secret, secretlen); + if (ret) + goto out4; + + outlen = crypto_kpp_maxsize(tfm); + + if (!kdfcopy) { + /* + * When not using a KDF, buflen 0 is used to read the + * required buffer length + */ + if (buflen == 0) { + ret = outlen; + goto out4; + } else if (outlen > buflen) { + ret = -EOVERFLOW; + goto out4; + } } - result = mpi_alloc(0); - if (!result) { + outbuf = kzalloc(kdfcopy ? (outlen + kdfcopy->otherinfolen) : outlen, + GFP_KERNEL); + if (!outbuf) { ret = -ENOMEM; - goto error3; + goto out4; } - /* allocate space for DH shared secret and SP800-56A otherinfo */ - kbuf = kmalloc(kdfcopy ? (resultlen + kdfcopy->otherinfolen) : resultlen, - GFP_KERNEL); - if (!kbuf) { + sg_init_one(&outsg, outbuf, outlen); + + req = kpp_request_alloc(tfm, GFP_KERNEL); + if (!req) { ret = -ENOMEM; - goto error4; + goto out5; } + kpp_request_set_input(req, NULL, 0); + kpp_request_set_output(req, &outsg, outlen); + init_completion(&compl.completion); + kpp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | + CRYPTO_TFM_REQ_MAY_SLEEP, + dh_crypto_done, &compl); + /* - * Concatenate SP800-56A otherinfo past DH shared secret -- the - * input to the KDF is (DH shared secret || otherinfo) + * For DH, generate_public_key and generate_shared_secret are + * the same calculation */ - if (kdfcopy && - copy_from_user(kbuf + resultlen, kdfcopy->otherinfo, - kdfcopy->otherinfolen) != 0) { - ret = -EFAULT; - goto error5; + ret = crypto_kpp_generate_public_key(req); + if (ret == -EINPROGRESS) { + wait_for_completion(&compl.completion); + ret = compl.err; + if (ret) + goto out6; } - ret = do_dh(result, base, private, prime); - if (ret) - goto error5; - - ret = mpi_read_buffer(result, kbuf, resultlen, &nbytes, NULL); - if (ret != 0) - goto error5; - if (kdfcopy) { - ret = keyctl_dh_compute_kdf(sdesc, buffer, buflen, kbuf, - resultlen + kdfcopy->otherinfolen); - } else { - ret = nbytes; - if (copy_to_user(buffer, kbuf, nbytes) != 0) + /* + * Concatenate SP800-56A otherinfo past DH shared secret -- the + * input to the KDF is (DH shared secret || otherinfo) + */ + if (copy_from_user(outbuf + req->dst_len, kdfcopy->otherinfo, + kdfcopy->otherinfolen) != 0) { ret = -EFAULT; + goto out6; + } + + ret = keyctl_dh_compute_kdf(sdesc, buffer, buflen, outbuf, + req->dst_len + kdfcopy->otherinfolen, + outlen - req->dst_len); + } else if (copy_to_user(buffer, outbuf, req->dst_len) == 0) { + ret = req->dst_len; + } else { + ret = -EFAULT; } -error5: - kzfree(kbuf); -error4: - mpi_free(result); -error3: - mpi_free(private); -error2: - mpi_free(base); -error1: - mpi_free(prime); -out: +out6: + kpp_request_free(req); +out5: + kzfree(outbuf); +out4: + crypto_free_kpp(tfm); +out3: + kzfree(secret); +out2: + dh_free_data(&dh_inputs); +out1: kdf_dealloc(sdesc); return ret; } -- cgit v1.2.3 From 92347cfd62c174ab91ad97dd4bfbaa1d4aa28e67 Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Thu, 8 Jun 2017 14:47:41 +0100 Subject: KEYS: fix refcount_inc() on zero If a key's refcount is dropped to zero between key_lookup() peeking at the refcount and subsequently attempting to increment it, refcount_inc() will see a zero refcount. Here, refcount_inc() will WARN_ONCE(), and will *not* increment the refcount, which will remain zero. Once key_lookup() drops key_serial_lock, it is possible for the key to be freed behind our back. This patch uses refcount_inc_not_zero() to perform the peek and increment atomically. Fixes: fff292914d3a2f1e ("security, keys: convert key.usage from atomic_t to refcount_t") Signed-off-by: Mark Rutland Signed-off-by: David Howells Cc: David Windsor Cc: Elena Reshetova Cc: Hans Liljestrand Cc: James Morris Cc: Kees Cook Cc: Peter Zijlstra Signed-off-by: James Morris --- security/keys/key.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/security/keys/key.c b/security/keys/key.c index cbae368c0e57..83da68d98b40 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -660,14 +660,11 @@ not_found: goto error; found: - /* pretend it doesn't exist if it is awaiting deletion */ - if (refcount_read(&key->usage) == 0) - goto not_found; - - /* this races with key_put(), but that doesn't matter since key_put() - * doesn't actually change the key + /* A key is allowed to be looked up only if someone still owns a + * reference to it - otherwise it's awaiting the gc. */ - __key_get(key); + if (!refcount_inc_not_zero(&key->usage)) + goto not_found; error: spin_unlock(&key_serial_lock); -- cgit v1.2.3 From c528eb27a3be2600e724c8a57cb69eab1fd9afa2 Mon Sep 17 00:00:00 2001 From: Richard Genoud Date: Thu, 1 Jun 2017 14:18:25 +0200 Subject: gpio: mvebu: fix blink counter register selection The blink counter A was always selected because 0 was forced in the blink select counter register. The variable 'set' was obviously there to be used as the register value, selecting the B counter when id==1 and A counter when id==0. Tested on clearfog-pro (Marvell 88F6828) Fixes: 757642f9a584 ("gpio: mvebu: Add limited PWM support") Reviewed-by: Gregory CLEMENT Reviewed-by: Ralph Sennhauser Signed-off-by: Richard Genoud Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mvebu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index 19a92efabbef..cdef2c78cb3b 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c @@ -747,7 +747,7 @@ static int mvebu_pwm_probe(struct platform_device *pdev, set = U32_MAX; else return -EINVAL; - writel_relaxed(0, mvebu_gpioreg_blink_counter_select(mvchip)); + writel_relaxed(set, mvebu_gpioreg_blink_counter_select(mvchip)); mvpwm = devm_kzalloc(dev, sizeof(struct mvebu_pwm), GFP_KERNEL); if (!mvpwm) -- cgit v1.2.3 From fc7a90686777e7d2da7a08cf0202c21f3b96febb Mon Sep 17 00:00:00 2001 From: Richard Genoud Date: Thu, 1 Jun 2017 14:18:26 +0200 Subject: gpio: mvebu: fix gpio bank registration when pwm is used If more than one gpio bank has the "pwm" property, only one will be registered successfully, all the others will fail with: mvebu-gpio: probe of f1018140.gpio failed with error -17 That's because in alloc_pwms(), the chip->base (aka "int pwm"), was not set (thus, ==0) ; and 0 is a meaningful start value in alloc_pwm(). What was intended is mvpwm->chip->base = -1. Like that, the numbering will be done auto-magically Moreover, as the region might be already occupied by another pwm, we shouldn't force: mvpwm->chip->base = 0 nor mvpwm->chip->base = id * MVEBU_MAX_GPIO_PER_BANK; Tested on clearfog-pro (Marvell 88F6828) Fixes: 757642f9a584 ("gpio: mvebu: Add limited PWM support") Signed-off-by: Richard Genoud Reviewed-by: Gregory CLEMENT Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mvebu.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index cdef2c78cb3b..5104b6398139 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c @@ -768,6 +768,13 @@ static int mvebu_pwm_probe(struct platform_device *pdev, mvpwm->chip.dev = dev; mvpwm->chip.ops = &mvebu_pwm_ops; mvpwm->chip.npwm = mvchip->chip.ngpio; + /* + * There may already be some PWM allocated, so we can't force + * mvpwm->chip.base to a fixed point like mvchip->chip.base. + * So, we let pwmchip_add() do the numbering and take the next free + * region. + */ + mvpwm->chip.base = -1; spin_lock_init(&mvpwm->lock); -- cgit v1.2.3 From ed45509b550488f6a71a4b6cc5b12265e8c1f85d Mon Sep 17 00:00:00 2001 From: Vaibhav Jain Date: Fri, 2 Jun 2017 22:26:48 +0530 Subject: cxl: Avoid double free_irq() for psl,slice interrupts During an eeh call to cxl_remove can result in double free_irq of psl,slice interrupts. This can happen if perst_reloads_same_image == 1 and call to cxl_configure_adapter() fails during slot_reset callback. In such a case we see a kernel oops with following back-trace: Oops: Kernel access of bad area, sig: 11 [#1] Call Trace: free_irq+0x88/0xd0 (unreliable) cxl_unmap_irq+0x20/0x40 [cxl] cxl_native_release_psl_irq+0x78/0xd8 [cxl] pci_deconfigure_afu+0xac/0x110 [cxl] cxl_remove+0x104/0x210 [cxl] pci_device_remove+0x6c/0x110 device_release_driver_internal+0x204/0x2e0 pci_stop_bus_device+0xa0/0xd0 pci_stop_and_remove_bus_device+0x28/0x40 pci_hp_remove_devices+0xb0/0x150 pci_hp_remove_devices+0x68/0x150 eeh_handle_normal_event+0x140/0x580 eeh_handle_event+0x174/0x360 eeh_event_handler+0x1e8/0x1f0 This patch fixes the issue of double free_irq by checking that variables that hold the virqs (err_hwirq, serr_hwirq, psl_virq) are not '0' before un-mapping and resetting these variables to '0' when they are un-mapped. Cc: stable@vger.kernel.org Signed-off-by: Vaibhav Jain Signed-off-by: Greg Kroah-Hartman --- drivers/misc/cxl/native.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/misc/cxl/native.c b/drivers/misc/cxl/native.c index 871a2f09c718..8d6ea9712dbd 100644 --- a/drivers/misc/cxl/native.c +++ b/drivers/misc/cxl/native.c @@ -1302,13 +1302,16 @@ int cxl_native_register_psl_err_irq(struct cxl *adapter) void cxl_native_release_psl_err_irq(struct cxl *adapter) { - if (adapter->native->err_virq != irq_find_mapping(NULL, adapter->native->err_hwirq)) + if (adapter->native->err_virq == 0 || + adapter->native->err_virq != + irq_find_mapping(NULL, adapter->native->err_hwirq)) return; cxl_p1_write(adapter, CXL_PSL_ErrIVTE, 0x0000000000000000); cxl_unmap_irq(adapter->native->err_virq, adapter); cxl_ops->release_one_irq(adapter, adapter->native->err_hwirq); kfree(adapter->irq_name); + adapter->native->err_virq = 0; } int cxl_native_register_serr_irq(struct cxl_afu *afu) @@ -1346,13 +1349,15 @@ int cxl_native_register_serr_irq(struct cxl_afu *afu) void cxl_native_release_serr_irq(struct cxl_afu *afu) { - if (afu->serr_virq != irq_find_mapping(NULL, afu->serr_hwirq)) + if (afu->serr_virq == 0 || + afu->serr_virq != irq_find_mapping(NULL, afu->serr_hwirq)) return; cxl_p1n_write(afu, CXL_PSL_SERR_An, 0x0000000000000000); cxl_unmap_irq(afu->serr_virq, afu); cxl_ops->release_one_irq(afu->adapter, afu->serr_hwirq); kfree(afu->err_irq_name); + afu->serr_virq = 0; } int cxl_native_register_psl_irq(struct cxl_afu *afu) @@ -1375,12 +1380,15 @@ int cxl_native_register_psl_irq(struct cxl_afu *afu) void cxl_native_release_psl_irq(struct cxl_afu *afu) { - if (afu->native->psl_virq != irq_find_mapping(NULL, afu->native->psl_hwirq)) + if (afu->native->psl_virq == 0 || + afu->native->psl_virq != + irq_find_mapping(NULL, afu->native->psl_hwirq)) return; cxl_unmap_irq(afu->native->psl_virq, afu); cxl_ops->release_one_irq(afu->adapter, afu->native->psl_hwirq); kfree(afu->psl_irq_name); + afu->native->psl_virq = 0; } static void recover_psl_err(struct cxl_afu *afu, u64 errstat) -- cgit v1.2.3 From 792ef14df5c585c19b2831673a077504a09e5203 Mon Sep 17 00:00:00 2001 From: Dave Young Date: Fri, 9 Jun 2017 08:45:58 +0000 Subject: efi: Fix boot panic because of invalid BGRT image address Maniaxx reported a kernel boot crash in the EFI code, which I emulated by using same invalid phys addr in code: BUG: unable to handle kernel paging request at ffffffffff280001 IP: efi_bgrt_init+0xfb/0x153 ... Call Trace: ? bgrt_init+0xbc/0xbc acpi_parse_bgrt+0xe/0x12 acpi_table_parse+0x89/0xb8 acpi_boot_init+0x445/0x4e2 ? acpi_parse_x2apic+0x79/0x79 ? dmi_ignore_irq0_timer_override+0x33/0x33 setup_arch+0xb63/0xc82 ? early_idt_handler_array+0x120/0x120 start_kernel+0xb7/0x443 ? early_idt_handler_array+0x120/0x120 x86_64_start_reservations+0x29/0x2b x86_64_start_kernel+0x154/0x177 secondary_startup_64+0x9f/0x9f There is also a similar bug filed in bugzilla.kernel.org: https://bugzilla.kernel.org/show_bug.cgi?id=195633 The crash is caused by this commit: 7b0a911478c7 efi/x86: Move the EFI BGRT init code to early init code The root cause is the firmware on those machines provides invalid BGRT image addresses. In a kernel before above commit BGRT initializes late and uses ioremap() to map the image address. Ioremap validates the address, if it is not a valid physical address ioremap() just fails and returns. However in current kernel EFI BGRT initializes early and uses early_memremap() which does not validate the image address, and kernel panic happens. According to ACPI spec the BGRT image address should fall into EFI_BOOT_SERVICES_DATA, see the section 5.2.22.4 of below document: http://www.uefi.org/sites/default/files/resources/ACPI_6_1.pdf Fix this issue by validating the image address in efi_bgrt_init(). If the image address does not fall into any EFI_BOOT_SERVICES_DATA areas we just bail out with a warning message. Reported-by: Maniaxx Signed-off-by: Dave Young Signed-off-by: Ard Biesheuvel Cc: Linus Torvalds Cc: Matt Fleming Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: linux-efi@vger.kernel.org Fixes: 7b0a911478c7 ("efi/x86: Move the EFI BGRT init code to early init code") Link: http://lkml.kernel.org/r/20170609084558.26766-2-ard.biesheuvel@linaro.org Signed-off-by: Ingo Molnar --- drivers/firmware/efi/efi-bgrt.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/drivers/firmware/efi/efi-bgrt.c b/drivers/firmware/efi/efi-bgrt.c index 8bf27323f7a3..b58233e4ed71 100644 --- a/drivers/firmware/efi/efi-bgrt.c +++ b/drivers/firmware/efi/efi-bgrt.c @@ -27,6 +27,26 @@ struct bmp_header { u32 size; } __packed; +static bool efi_bgrt_addr_valid(u64 addr) +{ + efi_memory_desc_t *md; + + for_each_efi_memory_desc(md) { + u64 size; + u64 end; + + if (md->type != EFI_BOOT_SERVICES_DATA) + continue; + + size = md->num_pages << EFI_PAGE_SHIFT; + end = md->phys_addr + size; + if (addr >= md->phys_addr && addr < end) + return true; + } + + return false; +} + void __init efi_bgrt_init(struct acpi_table_header *table) { void *image; @@ -36,7 +56,7 @@ void __init efi_bgrt_init(struct acpi_table_header *table) if (acpi_disabled) return; - if (!efi_enabled(EFI_BOOT)) + if (!efi_enabled(EFI_MEMMAP)) return; if (table->length < sizeof(bgrt_tab)) { @@ -65,6 +85,10 @@ void __init efi_bgrt_init(struct acpi_table_header *table) goto out; } + if (!efi_bgrt_addr_valid(bgrt->image_address)) { + pr_notice("Ignoring BGRT: invalid image address\n"); + goto out; + } image = early_memremap(bgrt->image_address, sizeof(bmp_header)); if (!image) { pr_notice("Ignoring BGRT: failed to map image header memory\n"); -- cgit v1.2.3 From b9d39d17e4819ca2e69ad1f14acaad12240a1de5 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 9 Jun 2017 08:50:49 -0700 Subject: device-dax: fix 'dax' device filesystem inode destruction crash The inode destruction path for the 'dax' device filesystem incorrectly assumes that the inode was initialized through 'alloc_dax()'. However, if someone attempts to directly mount the dax filesystem with 'mount -t dax dax mnt' that will bypass 'alloc_dax()' and the following failure signatures may occur as a result: kill_dax() must be called before final iput() WARNING: CPU: 2 PID: 1188 at drivers/dax/super.c:243 dax_destroy_inode+0x48/0x50 RIP: 0010:dax_destroy_inode+0x48/0x50 Call Trace: destroy_inode+0x3b/0x60 evict+0x139/0x1c0 iput+0x1f9/0x2d0 dentry_unlink_inode+0xc3/0x160 __dentry_kill+0xcf/0x180 ? dput+0x37/0x3b0 dput+0x3a3/0x3b0 do_one_tree+0x36/0x40 shrink_dcache_for_umount+0x2d/0x90 generic_shutdown_super+0x1f/0x120 kill_anon_super+0x12/0x20 deactivate_locked_super+0x43/0x70 deactivate_super+0x4e/0x60 general protection fault: 0000 [#1] SMP DEBUG_PAGEALLOC RIP: 0010:kfree+0x6d/0x290 Call Trace: dax_i_callback+0x22/0x60 ? dax_destroy_inode+0x50/0x50 rcu_process_callbacks+0x298/0x740 ida_remove called for id=0 which is not allocated. WARNING: CPU: 0 PID: 0 at lib/idr.c:383 ida_remove+0x110/0x120 [..] Call Trace: ida_simple_remove+0x2b/0x50 ? dax_destroy_inode+0x50/0x50 dax_i_callback+0x3c/0x60 rcu_process_callbacks+0x298/0x740 Add missing initialization of the 'struct dax_device' and inode so that the destruction path does not kfree() or ida_simple_remove() uninitialized data. Fixes: 7b6be8444e0f ("dax: refactor dax-fs into a generic provider of 'struct dax_device' instances") Reported-by: Sasha Levin Signed-off-by: Dan Williams --- drivers/dax/super.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/dax/super.c b/drivers/dax/super.c index 6ed32aac8bbe..922d0823f8ec 100644 --- a/drivers/dax/super.c +++ b/drivers/dax/super.c @@ -210,9 +210,12 @@ EXPORT_SYMBOL_GPL(kill_dax); static struct inode *dax_alloc_inode(struct super_block *sb) { struct dax_device *dax_dev; + struct inode *inode; dax_dev = kmem_cache_alloc(dax_cache, GFP_KERNEL); - return &dax_dev->inode; + inode = &dax_dev->inode; + inode->i_rdev = 0; + return inode; } static struct dax_device *to_dax_dev(struct inode *inode) @@ -227,7 +230,8 @@ static void dax_i_callback(struct rcu_head *head) kfree(dax_dev->host); dax_dev->host = NULL; - ida_simple_remove(&dax_minor_ida, MINOR(inode->i_rdev)); + if (inode->i_rdev) + ida_simple_remove(&dax_minor_ida, MINOR(inode->i_rdev)); kmem_cache_free(dax_cache, dax_dev); } @@ -423,6 +427,7 @@ static void init_once(void *_dax_dev) struct dax_device *dax_dev = _dax_dev; struct inode *inode = &dax_dev->inode; + memset(dax_dev, 0, sizeof(*dax_dev)); inode_init_once(inode); } -- cgit v1.2.3 From a0897d5f2c2d884d20840c82aea517e8a7801441 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 6 Jun 2017 13:05:03 -0700 Subject: Input: synaptics-rmi4 - register F03 port as pass-through serio The 5th generation Thinkpad X1 Carbons use Synaptics touchpads accessible over SMBus/RMI, combined with ALPS or Elantech trackpoint devices instead of classic IBM/Lenovo trackpoints. Unfortunately there is no way for ALPS driver to detect whether it is dealing with touchpad + trackpoint combination or just a trackpoint, so we end up with a "phantom" dualpoint ALPS device in addition to real touchpad and trackpoint. Given that we do not have any special advanced handling for ALPS or Elantech trackpoints (unlike IBM trackpoints that have separate driver and a host of options) we are better off keeping the trackpoints in PS/2 emulation mode. We achieve that by setting serio type to SERIO_PS_PSTHRU, which will limit number of protocols psmouse driver will try. In addition to getting rid of the "phantom" touchpads, this will also speed up probing of F03 pass-through port. Reported-by: Damjan Georgievski Suggested-by: Benjamin Tissoires Acked-by: Benjamin Tissoires Signed-off-by: Dmitry Torokhov --- drivers/input/rmi4/rmi_f03.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/rmi4/rmi_f03.c b/drivers/input/rmi4/rmi_f03.c index 77dad045a468..ad71a5e768dc 100644 --- a/drivers/input/rmi4/rmi_f03.c +++ b/drivers/input/rmi4/rmi_f03.c @@ -146,7 +146,7 @@ static int rmi_f03_register_pt(struct f03_data *f03) if (!serio) return -ENOMEM; - serio->id.type = SERIO_8042; + serio->id.type = SERIO_PS_PSTHRU; serio->write = rmi_f03_pt_write; serio->port_data = f03; -- cgit v1.2.3 From 286b92f43c0d0ae2c29a61769b66219fe5ae6701 Mon Sep 17 00:00:00 2001 From: Su Yue Date: Wed, 24 May 2017 09:31:32 +0800 Subject: btrfs: tree-log.c: Wrong printk information about namelen In verify_dir_item, it wants to printk name_len of dir_item but printk data_len acutally. Fix it by calling btrfs_dir_name_len instead of btrfs_dir_data_len. Signed-off-by: Su Yue Reviewed-by: David Sterba Signed-off-by: David Sterba Signed-off-by: Chris Mason --- fs/btrfs/dir-item.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c index 60a750678a82..c24d615e3d7f 100644 --- a/fs/btrfs/dir-item.c +++ b/fs/btrfs/dir-item.c @@ -468,7 +468,7 @@ int verify_dir_item(struct btrfs_fs_info *fs_info, if (btrfs_dir_name_len(leaf, dir_item) > namelen) { btrfs_crit(fs_info, "invalid dir item name len: %u", - (unsigned)btrfs_dir_data_len(leaf, dir_item)); + (unsigned)btrfs_dir_name_len(leaf, dir_item)); return 1; } -- cgit v1.2.3 From 452e62b71fbbefe2646fad3a968371a026936c6d Mon Sep 17 00:00:00 2001 From: Liu Bo Date: Fri, 26 May 2017 17:44:23 -0600 Subject: Btrfs: clear EXTENT_DEFRAG bits in finish_ordered_io Before this, we use 'filled' mode here, ie. if all range has been filled with EXTENT_DEFRAG bits, get to clear it, but if the defrag range joins the adjacent delalloc range, then we'll have EXTENT_DEFRAG bits in extent_state until releasing this inode's pages, and that prevents extent_data from being freed. This clears the bit if any was found within the ordered extent. Signed-off-by: Liu Bo Reviewed-by: David Sterba Signed-off-by: David Sterba Signed-off-by: Chris Mason --- fs/btrfs/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 3fc3e10594a4..ef3c98c527c1 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -2952,7 +2952,7 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent) ret = test_range_bit(io_tree, ordered_extent->file_offset, ordered_extent->file_offset + ordered_extent->len - 1, - EXTENT_DEFRAG, 1, cached_state); + EXTENT_DEFRAG, 0, cached_state); if (ret) { u64 last_snapshot = btrfs_root_last_snapshot(&root->root_item); if (0 && last_snapshot >= BTRFS_I(inode)->generation) -- cgit v1.2.3 From 70e7af244f24c94604ef6eca32ad297632018583 Mon Sep 17 00:00:00 2001 From: Omar Sandoval Date: Fri, 2 Jun 2017 01:20:01 -0700 Subject: Btrfs: fix delalloc accounting leak caused by u32 overflow btrfs_calc_trans_metadata_size() does an unsigned 32-bit multiplication, which can overflow if num_items >= 4 GB / (nodesize * BTRFS_MAX_LEVEL * 2). For a nodesize of 16kB, this overflow happens at 16k items. Usually, num_items is a small constant passed to btrfs_start_transaction(), but we also use btrfs_calc_trans_metadata_size() for metadata reservations for extent items in btrfs_delalloc_{reserve,release}_metadata(). In drop_outstanding_extents(), num_items is calculated as inode->reserved_extents - inode->outstanding_extents. The difference between these two counters is usually small, but if many delalloc extents are reserved and then the outstanding extents are merged in btrfs_merge_extent_hook(), the difference can become large enough to overflow in btrfs_calc_trans_metadata_size(). The overflow manifests itself as a leak of a multiple of 4 GB in delalloc_block_rsv and the metadata bytes_may_use counter. This in turn can cause early ENOSPC errors. Additionally, these WARN_ONs in extent-tree.c will be hit when unmounting: WARN_ON(fs_info->delalloc_block_rsv.size > 0); WARN_ON(fs_info->delalloc_block_rsv.reserved > 0); WARN_ON(space_info->bytes_pinned > 0 || space_info->bytes_reserved > 0 || space_info->bytes_may_use > 0); Fix it by casting nodesize to a u64 so that btrfs_calc_trans_metadata_size() does a full 64-bit multiplication. While we're here, do the same in btrfs_calc_trunc_metadata_size(); this can't overflow with any existing uses, but it's better to be safe here than have another hard-to-debug problem later on. Cc: stable@vger.kernel.org Signed-off-by: Omar Sandoval Reviewed-by: David Sterba Signed-off-by: Chris Mason --- fs/btrfs/ctree.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 1e82516fe2d8..43a8c42cdf07 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -2564,7 +2564,7 @@ u64 btrfs_csum_bytes_to_leaves(struct btrfs_fs_info *fs_info, u64 csum_bytes); static inline u64 btrfs_calc_trans_metadata_size(struct btrfs_fs_info *fs_info, unsigned num_items) { - return fs_info->nodesize * BTRFS_MAX_LEVEL * 2 * num_items; + return (u64)fs_info->nodesize * BTRFS_MAX_LEVEL * 2 * num_items; } /* @@ -2574,7 +2574,7 @@ static inline u64 btrfs_calc_trans_metadata_size(struct btrfs_fs_info *fs_info, static inline u64 btrfs_calc_trunc_metadata_size(struct btrfs_fs_info *fs_info, unsigned num_items) { - return fs_info->nodesize * BTRFS_MAX_LEVEL * num_items; + return (u64)fs_info->nodesize * BTRFS_MAX_LEVEL * num_items; } int btrfs_should_throttle_delayed_refs(struct btrfs_trans_handle *trans, -- cgit v1.2.3 From 8785d84d002c2ce0f68fbcd6c2c86be859802c7e Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 8 Jun 2017 02:42:03 -0400 Subject: ufs: restore proper tail allocation Cc: stable@vger.kernel.org Signed-off-by: Al Viro --- fs/ufs/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c index 7e41aee7b69a..feb5f280db09 100644 --- a/fs/ufs/inode.c +++ b/fs/ufs/inode.c @@ -284,7 +284,7 @@ ufs_inode_getfrag(struct inode *inode, unsigned index, goal += uspi->s_fpb; } tmp = ufs_new_fragments(inode, p, ufs_blknum(new_fragment), - goal, uspi->s_fpb, err, locked_page); + goal, nfrags, err, locked_page); if (!tmp) { *err = -ENOSPC; -- cgit v1.2.3 From 414cf7186dbec29bd946c138d6b5c09da5955a08 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 8 Jun 2017 18:15:18 -0400 Subject: fix ufs_isblockset() Cc: stable@vger.kernel.org Signed-off-by: Al Viro --- fs/ufs/util.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/fs/ufs/util.h b/fs/ufs/util.h index b7fbf53dbc81..398019fb1448 100644 --- a/fs/ufs/util.h +++ b/fs/ufs/util.h @@ -473,15 +473,19 @@ static inline unsigned _ubh_find_last_zero_bit_( static inline int _ubh_isblockset_(struct ufs_sb_private_info * uspi, struct ufs_buffer_head * ubh, unsigned begin, unsigned block) { + u8 mask; switch (uspi->s_fpb) { case 8: return (*ubh_get_addr (ubh, begin + block) == 0xff); case 4: - return (*ubh_get_addr (ubh, begin + (block >> 1)) == (0x0f << ((block & 0x01) << 2))); + mask = 0x0f << ((block & 0x01) << 2); + return (*ubh_get_addr (ubh, begin + (block >> 1)) & mask) == mask; case 2: - return (*ubh_get_addr (ubh, begin + (block >> 2)) == (0x03 << ((block & 0x03) << 1))); + mask = 0x03 << ((block & 0x03) << 1); + return (*ubh_get_addr (ubh, begin + (block >> 2)) & mask) == mask; case 1: - return (*ubh_get_addr (ubh, begin + (block >> 3)) == (0x01 << (block & 0x07))); + mask = 0x01 << (block & 0x07); + return (*ubh_get_addr (ubh, begin + (block >> 3)) & mask) == mask; } return 0; } -- cgit v1.2.3 From eb315d2ae614493fd1ebb026c75a80573d84f7ad Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 8 Jun 2017 21:15:03 -0400 Subject: ufs: restore maintaining ->i_blocks Cc: stable@vger.kernel.org Signed-off-by: Al Viro --- fs/stat.c | 1 + fs/ufs/balloc.c | 26 +++++++++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/fs/stat.c b/fs/stat.c index f494b182c7c7..c35610845ab1 100644 --- a/fs/stat.c +++ b/fs/stat.c @@ -672,6 +672,7 @@ void __inode_add_bytes(struct inode *inode, loff_t bytes) inode->i_bytes -= 512; } } +EXPORT_SYMBOL(__inode_add_bytes); void inode_add_bytes(struct inode *inode, loff_t bytes) { diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c index a0376a2c1c29..d642cc0a8271 100644 --- a/fs/ufs/balloc.c +++ b/fs/ufs/balloc.c @@ -82,7 +82,8 @@ void ufs_free_fragments(struct inode *inode, u64 fragment, unsigned count) ufs_error (sb, "ufs_free_fragments", "bit already cleared for fragment %u", i); } - + + inode_sub_bytes(inode, count << uspi->s_fshift); fs32_add(sb, &ucg->cg_cs.cs_nffree, count); uspi->cs_total.cs_nffree += count; fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, count); @@ -184,6 +185,7 @@ do_more: ufs_error(sb, "ufs_free_blocks", "freeing free fragment"); } ubh_setblock(UCPI_UBH(ucpi), ucpi->c_freeoff, blkno); + inode_sub_bytes(inode, uspi->s_fpb << uspi->s_fshift); if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD) ufs_clusteracct (sb, ucpi, blkno, 1); @@ -494,6 +496,20 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment, return 0; } +static bool try_add_frags(struct inode *inode, unsigned frags) +{ + unsigned size = frags * i_blocksize(inode); + spin_lock(&inode->i_lock); + __inode_add_bytes(inode, size); + if (unlikely((u32)inode->i_blocks != inode->i_blocks)) { + __inode_sub_bytes(inode, size); + spin_unlock(&inode->i_lock); + return false; + } + spin_unlock(&inode->i_lock); + return true; +} + static u64 ufs_add_fragments(struct inode *inode, u64 fragment, unsigned oldcount, unsigned newcount) { @@ -530,6 +546,9 @@ static u64 ufs_add_fragments(struct inode *inode, u64 fragment, for (i = oldcount; i < newcount; i++) if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_freeoff, fragno + i)) return 0; + + if (!try_add_frags(inode, count)) + return 0; /* * Block can be extended */ @@ -647,6 +666,7 @@ cg_found: ubh_setbit (UCPI_UBH(ucpi), ucpi->c_freeoff, goal + i); i = uspi->s_fpb - count; + inode_sub_bytes(inode, i << uspi->s_fshift); fs32_add(sb, &ucg->cg_cs.cs_nffree, i); uspi->cs_total.cs_nffree += i; fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, i); @@ -657,6 +677,8 @@ cg_found: result = ufs_bitmap_search (sb, ucpi, goal, allocsize); if (result == INVBLOCK) return 0; + if (!try_add_frags(inode, count)) + return 0; for (i = 0; i < count; i++) ubh_clrbit (UCPI_UBH(ucpi), ucpi->c_freeoff, result + i); @@ -716,6 +738,8 @@ norot: return INVBLOCK; ucpi->c_rotor = result; gotit: + if (!try_add_frags(inode, uspi->s_fpb)) + return 0; blkno = ufs_fragstoblks(result); ubh_clrblock (UCPI_UBH(ucpi), ucpi->c_freeoff, blkno); if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD) -- cgit v1.2.3 From 6b0d144fa758869bdd652c50aa41aaf601232550 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 8 Jun 2017 21:15:45 -0400 Subject: ufs: set correct ->s_maxsize Cc: stable@vger.kernel.org Signed-off-by: Al Viro --- fs/ufs/super.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/fs/ufs/super.c b/fs/ufs/super.c index 131b2b77c818..d9aa2627c9df 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -746,6 +746,23 @@ static void ufs_put_super(struct super_block *sb) return; } +static u64 ufs_max_bytes(struct super_block *sb) +{ + struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; + int bits = uspi->s_apbshift; + u64 res; + + if (bits > 21) + res = ~0ULL; + else + res = UFS_NDADDR + (1LL << bits) + (1LL << (2*bits)) + + (1LL << (3*bits)); + + if (res >= (MAX_LFS_FILESIZE >> uspi->s_bshift)) + return MAX_LFS_FILESIZE; + return res << uspi->s_bshift; +} + static int ufs_fill_super(struct super_block *sb, void *data, int silent) { struct ufs_sb_info * sbi; @@ -1212,6 +1229,7 @@ magic_found: "fast symlink size (%u)\n", uspi->s_maxsymlinklen); uspi->s_maxsymlinklen = maxsymlen; } + sb->s_maxbytes = ufs_max_bytes(sb); sb->s_max_links = UFS_LINK_MAX; inode = ufs_iget(sb, UFS_ROOTINO); -- cgit v1.2.3 From 940ef1a0ed939c2ca029fca715e25e7778ce1e34 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 8 Jun 2017 23:27:12 -0400 Subject: ufs_extend_tail(): fix the braino in calling conventions of ufs_new_fragments() ... and it really needs splitting into "new" and "extend" cases, but that's for later Cc: stable@vger.kernel.org Signed-off-by: Al Viro --- fs/ufs/inode.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c index feb5f280db09..966cced0f88e 100644 --- a/fs/ufs/inode.c +++ b/fs/ufs/inode.c @@ -235,7 +235,8 @@ ufs_extend_tail(struct inode *inode, u64 writes_to, p = ufs_get_direct_data_ptr(uspi, ufsi, block); tmp = ufs_new_fragments(inode, p, lastfrag, ufs_data_ptr_to_cpu(sb, p), - new_size, err, locked_page); + new_size - (lastfrag & uspi->s_fpbmask), err, + locked_page); return tmp != 0; } -- cgit v1.2.3 From 006351ac8ead0d4a67dd3845e3ceffe650a23212 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 8 Jun 2017 23:28:53 -0400 Subject: ufs_getfrag_block(): we only grab ->truncate_mutex on block creation path Cc: stable@vger.kernel.org Signed-off-by: Al Viro --- fs/ufs/inode.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c index 966cced0f88e..9bf10285c628 100644 --- a/fs/ufs/inode.c +++ b/fs/ufs/inode.c @@ -403,7 +403,9 @@ static int ufs_getfrag_block(struct inode *inode, sector_t fragment, struct buff if (!create) { phys64 = ufs_frag_map(inode, offsets, depth); - goto out; + if (phys64) + map_bh(bh_result, sb, phys64 + frag); + return 0; } /* This code entered only while writing ....? */ -- cgit v1.2.3 From babef37dccbaa49249a22bae9150686815d7be71 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 9 Jun 2017 16:20:34 -0400 Subject: excessive checks in ufs_write_failed() and ufs_evict_inode() As it is, short copy in write() to append-only file will fail to truncate the excessive allocated blocks. As the matter of fact, all checks in ufs_truncate_blocks() are either redundant or wrong for that caller. As for the only other caller (ufs_evict_inode()), we only need the file type checks there. Cc: stable@vger.kernel.org Signed-off-by: Al Viro --- fs/ufs/inode.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c index 9bf10285c628..34f11cf0900a 100644 --- a/fs/ufs/inode.c +++ b/fs/ufs/inode.c @@ -844,7 +844,9 @@ void ufs_evict_inode(struct inode * inode) truncate_inode_pages_final(&inode->i_data); if (want_delete) { inode->i_size = 0; - if (inode->i_blocks) + if (inode->i_blocks && + (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || + S_ISLNK(inode->i_mode))) ufs_truncate_blocks(inode); } @@ -1103,7 +1105,7 @@ out: return err; } -static void __ufs_truncate_blocks(struct inode *inode) +static void ufs_truncate_blocks(struct inode *inode) { struct ufs_inode_info *ufsi = UFS_I(inode); struct super_block *sb = inode->i_sb; @@ -1186,7 +1188,7 @@ static int ufs_truncate(struct inode *inode, loff_t size) truncate_setsize(inode, size); - __ufs_truncate_blocks(inode); + ufs_truncate_blocks(inode); inode->i_mtime = inode->i_ctime = current_time(inode); mark_inode_dirty(inode); out: @@ -1194,16 +1196,6 @@ out: return err; } -static void ufs_truncate_blocks(struct inode *inode) -{ - if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || - S_ISLNK(inode->i_mode))) - return; - if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) - return; - __ufs_truncate_blocks(inode); -} - int ufs_setattr(struct dentry *dentry, struct iattr *attr) { struct inode *inode = d_inode(dentry); -- cgit v1.2.3 From 67a70017fa0a152657bc7e337e69bb9c9f5549bf Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 10 Jun 2017 12:01:50 -0400 Subject: ufs: we need to sync inode before freeing it Signed-off-by: Al Viro --- fs/ufs/inode.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c index 34f11cf0900a..da553ffec85b 100644 --- a/fs/ufs/inode.c +++ b/fs/ufs/inode.c @@ -848,6 +848,7 @@ void ufs_evict_inode(struct inode * inode) (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))) ufs_truncate_blocks(inode); + ufs_update_inode(inode, inode_needs_sync(inode)); } invalidate_inode_buffers(inode); -- cgit v1.2.3 From 4d801cca0bb7011699c2d29f0139902dcfb3482d Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 2 May 2017 20:44:16 -0700 Subject: hexagon: Use raw_copy_to_user Commit ac4691fac8ad ("hexagon: switch to RAW_COPY_USER") replaced __copy_to_user_hexagon() with raw_copy_to_user(), but did not catch all callers, resulting in the following build error. arch/hexagon/mm/uaccess.c: In function '__clear_user_hexagon': arch/hexagon/mm/uaccess.c:40:3: error: implicit declaration of function '__copy_to_user_hexagon' Fixes: ac4691fac8ad ("hexagon: switch to RAW_COPY_USER") Cc: Al Viro Acked-by: Al Viro Acked-by: Richard Kuo Signed-off-by: Guenter Roeck --- arch/hexagon/mm/uaccess.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/arch/hexagon/mm/uaccess.c b/arch/hexagon/mm/uaccess.c index ec90afdb3ad0..c599eb126c9e 100644 --- a/arch/hexagon/mm/uaccess.c +++ b/arch/hexagon/mm/uaccess.c @@ -37,15 +37,14 @@ __kernel_size_t __clear_user_hexagon(void __user *dest, unsigned long count) long uncleared; while (count > PAGE_SIZE) { - uncleared = __copy_to_user_hexagon(dest, &empty_zero_page, - PAGE_SIZE); + uncleared = raw_copy_to_user(dest, &empty_zero_page, PAGE_SIZE); if (uncleared) return count - (PAGE_SIZE - uncleared); count -= PAGE_SIZE; dest += PAGE_SIZE; } if (count) - count = __copy_to_user_hexagon(dest, &empty_zero_page, count); + count = raw_copy_to_user(dest, &empty_zero_page, count); return count; } -- cgit v1.2.3 From 9bc1f09f6fa76fdf31eb7d6a4a4df43574725f93 Mon Sep 17 00:00:00 2001 From: Wanpeng Li Date: Thu, 8 Jun 2017 20:13:40 -0700 Subject: KVM: async_pf: avoid async pf injection when in guest mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit INFO: task gnome-terminal-:1734 blocked for more than 120 seconds. Not tainted 4.12.0-rc4+ #8 "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. gnome-terminal- D 0 1734 1015 0x00000000 Call Trace: __schedule+0x3cd/0xb30 schedule+0x40/0x90 kvm_async_pf_task_wait+0x1cc/0x270 ? __vfs_read+0x37/0x150 ? prepare_to_swait+0x22/0x70 do_async_page_fault+0x77/0xb0 ? do_async_page_fault+0x77/0xb0 async_page_fault+0x28/0x30 This is triggered by running both win7 and win2016 on L1 KVM simultaneously, and then gives stress to memory on L1, I can observed this hang on L1 when at least ~70% swap area is occupied on L0. This is due to async pf was injected to L2 which should be injected to L1, L2 guest starts receiving pagefault w/ bogus %cr2(apf token from the host actually), and L1 guest starts accumulating tasks stuck in D state in kvm_async_pf_task_wait() since missing PAGE_READY async_pfs. This patch fixes the hang by doing async pf when executing L1 guest. Cc: Paolo Bonzini Cc: Radim Krčmář Cc: stable@vger.kernel.org Signed-off-by: Wanpeng Li Signed-off-by: Paolo Bonzini --- arch/x86/kvm/mmu.c | 7 +++++-- arch/x86/kvm/mmu.h | 1 + arch/x86/kvm/x86.c | 3 +-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 5d3376f67794..cb8225969255 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -3698,12 +3698,15 @@ static int kvm_arch_setup_async_pf(struct kvm_vcpu *vcpu, gva_t gva, gfn_t gfn) return kvm_setup_async_pf(vcpu, gva, kvm_vcpu_gfn_to_hva(vcpu, gfn), &arch); } -static bool can_do_async_pf(struct kvm_vcpu *vcpu) +bool kvm_can_do_async_pf(struct kvm_vcpu *vcpu) { if (unlikely(!lapic_in_kernel(vcpu) || kvm_event_needs_reinjection(vcpu))) return false; + if (is_guest_mode(vcpu)) + return false; + return kvm_x86_ops->interrupt_allowed(vcpu); } @@ -3719,7 +3722,7 @@ static bool try_async_pf(struct kvm_vcpu *vcpu, bool prefault, gfn_t gfn, if (!async) return false; /* *pfn has correct page already */ - if (!prefault && can_do_async_pf(vcpu)) { + if (!prefault && kvm_can_do_async_pf(vcpu)) { trace_kvm_try_async_get_page(gva, gfn); if (kvm_find_async_pf_gfn(vcpu, gfn)) { trace_kvm_async_pf_doublefault(gva, gfn); diff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h index 27975807cc64..330bf3a811fb 100644 --- a/arch/x86/kvm/mmu.h +++ b/arch/x86/kvm/mmu.h @@ -76,6 +76,7 @@ int handle_mmio_page_fault(struct kvm_vcpu *vcpu, u64 addr, bool direct); void kvm_init_shadow_mmu(struct kvm_vcpu *vcpu); void kvm_init_shadow_ept_mmu(struct kvm_vcpu *vcpu, bool execonly, bool accessed_dirty); +bool kvm_can_do_async_pf(struct kvm_vcpu *vcpu); static inline unsigned int kvm_mmu_available_pages(struct kvm *kvm) { diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index a2cd0997343c..87d3cb901935 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -8607,8 +8607,7 @@ bool kvm_arch_can_inject_async_page_present(struct kvm_vcpu *vcpu) if (!(vcpu->arch.apf.msr_val & KVM_ASYNC_PF_ENABLED)) return true; else - return !kvm_event_needs_reinjection(vcpu) && - kvm_x86_ops->interrupt_allowed(vcpu); + return kvm_can_do_async_pf(vcpu); } void kvm_arch_start_assignment(struct kvm *kvm) -- cgit v1.2.3 From 6d53cefb18e4646fb4bf62ccb6098fb3808486df Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 11 Jun 2017 15:51:56 -0700 Subject: compiler, clang: properly override 'inline' for clang Commit abb2ea7dfd82 ("compiler, clang: suppress warning for unused static inline functions") just caused more warnings due to re-defining the 'inline' macro. So undef it before re-defining it, and also add the 'notrace' attribute like the gcc version that this is overriding does. Maybe this makes clang happier. Signed-off-by: Linus Torvalds --- include/linux/compiler-clang.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/linux/compiler-clang.h b/include/linux/compiler-clang.h index ea9126006a69..d614c5ea1b5e 100644 --- a/include/linux/compiler-clang.h +++ b/include/linux/compiler-clang.h @@ -21,4 +21,5 @@ * -Wunused-function. This turns out to avoid the need for complex #ifdef * directives. Suppress the warning in clang as well. */ -#define inline inline __attribute__((unused)) +#undef inline +#define inline inline __attribute__((unused)) notrace -- cgit v1.2.3 From 32c1431eea4881a6b17bd7c639315010aeefa452 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 11 Jun 2017 16:48:20 -0700 Subject: Linux 4.12-rc5 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 853ae9179af9..83f6d9972cab 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 4 PATCHLEVEL = 12 SUBLEVEL = 0 -EXTRAVERSION = -rc4 +EXTRAVERSION = -rc5 NAME = Fearless Coyote # *DOCUMENTATION* -- cgit v1.2.3