From 8d7bc77acdc2675054c659934a4321de3f785292 Mon Sep 17 00:00:00 2001 From: Yuanyuan Liu Date: Fri, 5 Jan 2018 15:55:23 -0800 Subject: [PATCH 001/159] icnss: Remove sending uevent after FW ready FW ready indication doesn't mean it is safe to access HW register. FW ready only means that WLAN FW is initialized. The HW register is safe to access only after FW ack the wlan enable mode request. Hence removing uevent in FW ready indication handler. WLAN driver will responsible for setting FW ready state once wlan enable mode request is return success. CRs-Fixed: 2168628 Change-Id: I769d848efb9dd427da0d71494090fcbf9514cfb2 Signed-off-by: Yuanyuan Liu --- drivers/soc/qcom/icnss.c | 4 +--- include/soc/qcom/icnss.h | 3 +-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c index 7f71824d9548..122f758888a6 100644 --- a/drivers/soc/qcom/icnss.c +++ b/drivers/soc/qcom/icnss.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -2235,8 +2235,6 @@ static int icnss_driver_event_fw_ready_ind(void *data) set_bit(ICNSS_FW_READY, &penv->state); - icnss_call_driver_uevent(penv, ICNSS_UEVENT_FW_READY, NULL); - icnss_pr_info("WLAN FW is ready: 0x%lx\n", penv->state); icnss_hw_power_off(penv); diff --git a/include/soc/qcom/icnss.h b/include/soc/qcom/icnss.h index 4fff429dc0b2..ae8834d3fe54 100644 --- a/include/soc/qcom/icnss.h +++ b/include/soc/qcom/icnss.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -23,7 +23,6 @@ #endif enum icnss_uevent { - ICNSS_UEVENT_FW_READY, ICNSS_UEVENT_FW_CRASHED, ICNSS_UEVENT_FW_DOWN, }; From bacd1e0ae2f090b5fb7f4fafd496161e691ba27b Mon Sep 17 00:00:00 2001 From: Yong Ding Date: Wed, 4 Jul 2018 15:05:37 +0800 Subject: [PATCH 002/159] soc: qcom: hab: check the buffer's pointer before exporting it When the buffer's pointer is NULL, -EINVAL will be returned for its export. Change-Id: I3fc949c6152974db360dc55d3dfdb0cb24150473 Signed-off-by: Yong Ding --- drivers/soc/qcom/hab/hab_mimex.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/qcom/hab/hab_mimex.c b/drivers/soc/qcom/hab/hab_mimex.c index 86d763f65657..dddf51a80373 100644 --- a/drivers/soc/qcom/hab/hab_mimex.c +++ b/drivers/soc/qcom/hab/hab_mimex.c @@ -240,7 +240,7 @@ int hab_mem_export(struct uhab_context *ctx, int page_count; int compressed = 0; - if (!ctx || !param) + if (!ctx || !param || !param->buffer) return -EINVAL; vchan = hab_get_vchan_fromvcid(param->vcid, ctx); From 2372ea39384e71fc67bab40dafc5bbcc7d514444 Mon Sep 17 00:00:00 2001 From: Zhiqiang Tu Date: Fri, 15 Jun 2018 10:52:41 +0800 Subject: [PATCH 003/159] usb: dwc3-msm: Add boot marker Add boot marker for booting KPI measurement. Change-Id: Idf57bed89437d85abc419f7774e0c2d975d214c9 Signed-off-by: Zhiqiang Tu --- drivers/usb/dwc3/dwc3-msm.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index f94d0ba2f966..8ffb2723a1b0 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -46,6 +46,7 @@ #include #include #include +#include #include "power.h" #include "core.h" @@ -2913,6 +2914,7 @@ static int dwc3_msm_probe(struct platform_device *pdev) int ret = 0; int ext_hub_reset_gpio; u32 val; + char boot_marker[40]; mdwc = devm_kzalloc(&pdev->dev, sizeof(*mdwc), GFP_KERNEL); if (!mdwc) @@ -3260,8 +3262,15 @@ static int dwc3_msm_probe(struct platform_device *pdev) mdwc->host_only_mode = true; mdwc->id_state = DWC3_ID_GROUND; dwc3_ext_event_notify(mdwc); + snprintf(boot_marker, sizeof(boot_marker), + "M - DRIVER %s Host Ready", dev_name(&pdev->dev)); + } else { + snprintf(boot_marker, sizeof(boot_marker), + "M - DRIVER %s Device Ready", dev_name(&pdev->dev)); } + place_marker(boot_marker); + return 0; put_dwc3: From ed11739bc12aac4b63046d8dd896dac814587ef2 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Thu, 14 Jul 2016 15:41:30 +0200 Subject: [PATCH 004/159] usbnet: move the CDC parser into USB core The dependencies were impossible to handle preventing drivers for CDC devices not which are not network drivers from using the common parser. Change-Id: Ied0d1d037bfb8b60bc82236382ef894755755cef Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman Git-commit: e4c6fb779498243ec001c5547b3504fe6b1993ec Git-repo: https://android.googlesource.com/kernel/common Signed-off-by: Srinivasa Rao Kuppala Signed-off-by: Ajay Agarwal --- drivers/net/usb/usbnet.c | 142 ---------------------------------- drivers/usb/core/message.c | 153 +++++++++++++++++++++++++++++++++++++ 2 files changed, 153 insertions(+), 142 deletions(-) diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 9710cf71054a..c0bcfa979253 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -42,7 +42,6 @@ #include #include #include -#include #include #include #include @@ -1964,147 +1963,6 @@ out: return err; } -int cdc_parse_cdc_header(struct usb_cdc_parsed_header *hdr, - struct usb_interface *intf, - u8 *buffer, - int buflen) -{ - /* duplicates are ignored */ - struct usb_cdc_union_desc *union_header = NULL; - - /* duplicates are not tolerated */ - struct usb_cdc_header_desc *header = NULL; - struct usb_cdc_ether_desc *ether = NULL; - struct usb_cdc_mdlm_detail_desc *detail = NULL; - struct usb_cdc_mdlm_desc *desc = NULL; - - unsigned int elength; - int cnt = 0; - - memset(hdr, 0x00, sizeof(struct usb_cdc_parsed_header)); - hdr->phonet_magic_present = false; - while (buflen > 0) { - elength = buffer[0]; - if (!elength) { - dev_err(&intf->dev, "skipping garbage byte\n"); - elength = 1; - goto next_desc; - } - if ((buflen < elength) || (elength < 3)) { - dev_err(&intf->dev, "invalid descriptor buffer length\n"); - break; - } - if (buffer[1] != USB_DT_CS_INTERFACE) { - dev_err(&intf->dev, "skipping garbage\n"); - goto next_desc; - } - - switch (buffer[2]) { - case USB_CDC_UNION_TYPE: /* we've found it */ - if (elength < sizeof(struct usb_cdc_union_desc)) - goto next_desc; - if (union_header) { - dev_err(&intf->dev, "More than one union descriptor, skipping ...\n"); - goto next_desc; - } - union_header = (struct usb_cdc_union_desc *)buffer; - break; - case USB_CDC_COUNTRY_TYPE: - if (elength < sizeof(struct usb_cdc_country_functional_desc)) - goto next_desc; - hdr->usb_cdc_country_functional_desc = - (struct usb_cdc_country_functional_desc *)buffer; - break; - case USB_CDC_HEADER_TYPE: - if (elength != sizeof(struct usb_cdc_header_desc)) - goto next_desc; - if (header) - return -EINVAL; - header = (struct usb_cdc_header_desc *)buffer; - break; - case USB_CDC_ACM_TYPE: - if (elength < sizeof(struct usb_cdc_acm_descriptor)) - goto next_desc; - hdr->usb_cdc_acm_descriptor = - (struct usb_cdc_acm_descriptor *)buffer; - break; - case USB_CDC_ETHERNET_TYPE: - if (elength != sizeof(struct usb_cdc_ether_desc)) - goto next_desc; - if (ether) - return -EINVAL; - ether = (struct usb_cdc_ether_desc *)buffer; - break; - case USB_CDC_CALL_MANAGEMENT_TYPE: - if (elength < sizeof(struct usb_cdc_call_mgmt_descriptor)) - goto next_desc; - hdr->usb_cdc_call_mgmt_descriptor = - (struct usb_cdc_call_mgmt_descriptor *)buffer; - break; - case USB_CDC_DMM_TYPE: - if (elength < sizeof(struct usb_cdc_dmm_desc)) - goto next_desc; - hdr->usb_cdc_dmm_desc = - (struct usb_cdc_dmm_desc *)buffer; - break; - case USB_CDC_MDLM_TYPE: - if (elength < sizeof(struct usb_cdc_mdlm_desc *)) - goto next_desc; - if (desc) - return -EINVAL; - desc = (struct usb_cdc_mdlm_desc *)buffer; - break; - case USB_CDC_MDLM_DETAIL_TYPE: - if (elength < sizeof(struct usb_cdc_mdlm_detail_desc *)) - goto next_desc; - if (detail) - return -EINVAL; - detail = (struct usb_cdc_mdlm_detail_desc *)buffer; - break; - case USB_CDC_NCM_TYPE: - if (elength < sizeof(struct usb_cdc_ncm_desc)) - goto next_desc; - hdr->usb_cdc_ncm_desc = (struct usb_cdc_ncm_desc *)buffer; - break; - case USB_CDC_MBIM_TYPE: - if (elength < sizeof(struct usb_cdc_mbim_desc)) - goto next_desc; - - hdr->usb_cdc_mbim_desc = (struct usb_cdc_mbim_desc *)buffer; - break; - case USB_CDC_MBIM_EXTENDED_TYPE: - if (elength < sizeof(struct usb_cdc_mbim_extended_desc)) - break; - hdr->usb_cdc_mbim_extended_desc = - (struct usb_cdc_mbim_extended_desc *)buffer; - break; - case CDC_PHONET_MAGIC_NUMBER: - hdr->phonet_magic_present = true; - break; - default: - /* - * there are LOTS more CDC descriptors that - * could legitimately be found here. - */ - dev_dbg(&intf->dev, "Ignoring descriptor: type %02x, length %ud\n", - buffer[2], elength); - goto next_desc; - } - cnt++; -next_desc: - buflen -= elength; - buffer += elength; - } - hdr->usb_cdc_union_desc = union_header; - hdr->usb_cdc_header_desc = header; - hdr->usb_cdc_mdlm_detail_desc = detail; - hdr->usb_cdc_mdlm_desc = desc; - hdr->usb_cdc_ether_desc = ether; - return cnt; -} - -EXPORT_SYMBOL(cdc_parse_cdc_header); - /* * The function can't be called inside suspend/resume callback, * otherwise deadlock will be caused. diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 29adabdb305f..e7db64662537 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include /* for usbcore internals */ #include @@ -2031,3 +2032,155 @@ int usb_driver_set_configuration(struct usb_device *udev, int config) return 0; } EXPORT_SYMBOL_GPL(usb_driver_set_configuration); + +/** + * cdc_parse_cdc_header - parse the extra headers present in CDC devices + * @hdr: the place to put the results of the parsing + * @intf: the interface for which parsing is requested + * @buffer: pointer to the extra headers to be parsed + * @buflen: length of the extra headers + * + * This evaluates the extra headers present in CDC devices which + * bind the interfaces for data and control and provide details + * about the capabilities of the device. + * + * Return: number of descriptors parsed or -EINVAL + * if the header is contradictory beyond salvage + */ + +int cdc_parse_cdc_header(struct usb_cdc_parsed_header *hdr, + struct usb_interface *intf, + u8 *buffer, + int buflen) +{ + /* duplicates are ignored */ + struct usb_cdc_union_desc *union_header = NULL; + + /* duplicates are not tolerated */ + struct usb_cdc_header_desc *header = NULL; + struct usb_cdc_ether_desc *ether = NULL; + struct usb_cdc_mdlm_detail_desc *detail = NULL; + struct usb_cdc_mdlm_desc *desc = NULL; + + unsigned int elength; + int cnt = 0; + + memset(hdr, 0x00, sizeof(struct usb_cdc_parsed_header)); + hdr->phonet_magic_present = false; + while (buflen > 0) { + elength = buffer[0]; + if (!elength) { + dev_err(&intf->dev, "skipping garbage byte\n"); + elength = 1; + goto next_desc; + } + if (buffer[1] != USB_DT_CS_INTERFACE) { + dev_err(&intf->dev, "skipping garbage\n"); + goto next_desc; + } + + switch (buffer[2]) { + case USB_CDC_UNION_TYPE: /* we've found it */ + if (elength < sizeof(struct usb_cdc_union_desc)) + goto next_desc; + if (union_header) { + dev_err(&intf->dev, "More than one union descriptor, skipping ...\n"); + goto next_desc; + } + union_header = (struct usb_cdc_union_desc *)buffer; + break; + case USB_CDC_COUNTRY_TYPE: + if (elength < sizeof(struct usb_cdc_country_functional_desc)) + goto next_desc; + hdr->usb_cdc_country_functional_desc = + (struct usb_cdc_country_functional_desc *)buffer; + break; + case USB_CDC_HEADER_TYPE: + if (elength != sizeof(struct usb_cdc_header_desc)) + goto next_desc; + if (header) + return -EINVAL; + header = (struct usb_cdc_header_desc *)buffer; + break; + case USB_CDC_ACM_TYPE: + if (elength < sizeof(struct usb_cdc_acm_descriptor)) + goto next_desc; + hdr->usb_cdc_acm_descriptor = + (struct usb_cdc_acm_descriptor *)buffer; + break; + case USB_CDC_ETHERNET_TYPE: + if (elength != sizeof(struct usb_cdc_ether_desc)) + goto next_desc; + if (ether) + return -EINVAL; + ether = (struct usb_cdc_ether_desc *)buffer; + break; + case USB_CDC_CALL_MANAGEMENT_TYPE: + if (elength < sizeof(struct usb_cdc_call_mgmt_descriptor)) + goto next_desc; + hdr->usb_cdc_call_mgmt_descriptor = + (struct usb_cdc_call_mgmt_descriptor *)buffer; + break; + case USB_CDC_DMM_TYPE: + if (elength < sizeof(struct usb_cdc_dmm_desc)) + goto next_desc; + hdr->usb_cdc_dmm_desc = + (struct usb_cdc_dmm_desc *)buffer; + break; + case USB_CDC_MDLM_TYPE: + if (elength < sizeof(struct usb_cdc_mdlm_desc *)) + goto next_desc; + if (desc) + return -EINVAL; + desc = (struct usb_cdc_mdlm_desc *)buffer; + break; + case USB_CDC_MDLM_DETAIL_TYPE: + if (elength < sizeof(struct usb_cdc_mdlm_detail_desc *)) + goto next_desc; + if (detail) + return -EINVAL; + detail = (struct usb_cdc_mdlm_detail_desc *)buffer; + break; + case USB_CDC_NCM_TYPE: + if (elength < sizeof(struct usb_cdc_ncm_desc)) + goto next_desc; + hdr->usb_cdc_ncm_desc = (struct usb_cdc_ncm_desc *)buffer; + break; + case USB_CDC_MBIM_TYPE: + if (elength < sizeof(struct usb_cdc_mbim_desc)) + goto next_desc; + + hdr->usb_cdc_mbim_desc = (struct usb_cdc_mbim_desc *)buffer; + break; + case USB_CDC_MBIM_EXTENDED_TYPE: + if (elength < sizeof(struct usb_cdc_mbim_extended_desc)) + break; + hdr->usb_cdc_mbim_extended_desc = + (struct usb_cdc_mbim_extended_desc *)buffer; + break; + case CDC_PHONET_MAGIC_NUMBER: + hdr->phonet_magic_present = true; + break; + default: + /* + * there are LOTS more CDC descriptors that + * could legitimately be found here. + */ + dev_dbg(&intf->dev, "Ignoring descriptor: type %02x, length %ud\n", + buffer[2], elength); + goto next_desc; + } + cnt++; +next_desc: + buflen -= elength; + buffer += elength; + } + hdr->usb_cdc_union_desc = union_header; + hdr->usb_cdc_header_desc = header; + hdr->usb_cdc_mdlm_detail_desc = detail; + hdr->usb_cdc_mdlm_desc = desc; + hdr->usb_cdc_ether_desc = ether; + return cnt; +} + +EXPORT_SYMBOL(cdc_parse_cdc_header); From 808b3542a7b0e8ab9d89a16b663d2b30d9a73b72 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 21 Sep 2017 16:58:48 +0200 Subject: [PATCH 005/159] USB: core: harden cdc_parse_cdc_header Andrey Konovalov reported a possible out-of-bounds problem for the cdc_parse_cdc_header function. He writes: It looks like cdc_parse_cdc_header() doesn't validate buflen before accessing buffer[1], buffer[2] and so on. The only check present is while (buflen > 0). So fix this issue up by properly validating the buffer length matches what the descriptor says it is. Change-Id: I9c65dc98778aa357911e554c8d28deef2bf9a5b3 Reported-by: Andrey Konovalov Tested-by: Andrey Konovalov Cc: stable Signed-off-by: Greg Kroah-Hartman Git-commit: 2e1c42391ff2556387b3cb6308b24f6f65619feb Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git Signed-off-by: Srinivasa Rao Kuppala --- drivers/usb/core/message.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index e7db64662537..7855b3e9a97f 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -2074,6 +2074,10 @@ int cdc_parse_cdc_header(struct usb_cdc_parsed_header *hdr, elength = 1; goto next_desc; } + if ((buflen < elength) || (elength < 3)) { + dev_err(&intf->dev, "invalid descriptor buffer length\n"); + break; + } if (buffer[1] != USB_DT_CS_INTERFACE) { dev_err(&intf->dev, "skipping garbage\n"); goto next_desc; From 6f8b3fd2a4726648c9a57f49df8358573414774d Mon Sep 17 00:00:00 2001 From: Houston Yaroschoff Date: Mon, 11 Jun 2018 12:39:09 +0200 Subject: [PATCH 006/159] usb: cdc_acm: Add quirk for Uniden UBC125 scanner commit 4a762569a2722b8a48066c7bacf0e1dc67d17fa1 upstream. Uniden UBC125 radio scanner has USB interface which fails to work with cdc_acm driver: usb 1-1.5: new full-speed USB device number 4 using xhci_hcd cdc_acm 1-1.5:1.0: Zero length descriptor references cdc_acm: probe of 1-1.5:1.0 failed with error -22 Adding the NO_UNION_NORMAL quirk for the device fixes the issue: usb 1-4: new full-speed USB device number 15 using xhci_hcd usb 1-4: New USB device found, idVendor=1965, idProduct=0018 usb 1-4: New USB device strings: Mfr=1, Product=2, SerialNumber=3 usb 1-4: Product: UBC125XLT usb 1-4: Manufacturer: Uniden Corp. usb 1-4: SerialNumber: 0001 cdc_acm 1-4:1.0: ttyACM0: USB ACM device `lsusb -v` of the device: Bus 001 Device 015: ID 1965:0018 Uniden Corporation Device Descriptor: bLength 18 bDescriptorType 1 bcdUSB 2.00 bDeviceClass 2 Communications bDeviceSubClass 0 bDeviceProtocol 0 bMaxPacketSize0 64 idVendor 0x1965 Uniden Corporation idProduct 0x0018 bcdDevice 0.01 iManufacturer 1 Uniden Corp. iProduct 2 UBC125XLT iSerial 3 0001 bNumConfigurations 1 Configuration Descriptor: bLength 9 bDescriptorType 2 wTotalLength 48 bNumInterfaces 2 bConfigurationValue 1 iConfiguration 0 bmAttributes 0x80 (Bus Powered) MaxPower 500mA Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber 0 bAlternateSetting 0 bNumEndpoints 1 bInterfaceClass 2 Communications bInterfaceSubClass 2 Abstract (modem) bInterfaceProtocol 0 None iInterface 0 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x87 EP 7 IN bmAttributes 3 Transfer Type Interrupt Synch Type None Usage Type Data wMaxPacketSize 0x0008 1x 8 bytes bInterval 10 Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber 1 bAlternateSetting 0 bNumEndpoints 2 bInterfaceClass 10 CDC Data bInterfaceSubClass 0 Unused bInterfaceProtocol 0 iInterface 0 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x81 EP 1 IN bmAttributes 2 Transfer Type Bulk Synch Type None Usage Type Data wMaxPacketSize 0x0040 1x 64 bytes bInterval 0 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x02 EP 2 OUT bmAttributes 2 Transfer Type Bulk Synch Type None Usage Type Data wMaxPacketSize 0x0040 1x 64 bytes bInterval 0 Device Status: 0x0000 (Bus Powered) Signed-off-by: Houston Yaroschoff Cc: stable Acked-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index edd8ef4ee502..7ed30d0b5273 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1698,6 +1698,9 @@ static const struct usb_device_id acm_ids[] = { { USB_DEVICE(0x11ca, 0x0201), /* VeriFone Mx870 Gadget Serial */ .driver_info = SINGLE_RX_URB, }, + { USB_DEVICE(0x1965, 0x0018), /* Uniden UBC125XLT */ + .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ + }, { USB_DEVICE(0x22b8, 0x7000), /* Motorola Q Phone */ .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ }, From 3357fbc733cd84523c09c35c1924daad7e389dbf Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 18 Jun 2018 10:24:03 +0200 Subject: [PATCH 007/159] USB: serial: cp210x: add CESINEL device ids commit 24160628a34af962ac99f2f58e547ac3c4cbd26f upstream. Add device ids for CESINEL products. Reported-by: Carlos Barcala Lara Cc: stable Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp210x.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index e7a051386b32..041fa09f0505 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -91,6 +91,9 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x10C4, 0x8156) }, /* B&G H3000 link cable */ { USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */ { USB_DEVICE(0x10C4, 0x815F) }, /* Timewave HamLinkUSB */ + { USB_DEVICE(0x10C4, 0x817C) }, /* CESINEL MEDCAL N Power Quality Monitor */ + { USB_DEVICE(0x10C4, 0x817D) }, /* CESINEL MEDCAL NT Power Quality Monitor */ + { USB_DEVICE(0x10C4, 0x817E) }, /* CESINEL MEDCAL S Power Quality Monitor */ { USB_DEVICE(0x10C4, 0x818B) }, /* AVIT Research USB to TTL */ { USB_DEVICE(0x10C4, 0x819F) }, /* MJS USB Toslink Switcher */ { USB_DEVICE(0x10C4, 0x81A6) }, /* ThinkOptics WavIt */ @@ -108,6 +111,9 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x10C4, 0x826B) }, /* Cygnal Integrated Products, Inc., Fasttrax GPS demonstration module */ { USB_DEVICE(0x10C4, 0x8281) }, /* Nanotec Plug & Drive */ { USB_DEVICE(0x10C4, 0x8293) }, /* Telegesis ETRX2USB */ + { USB_DEVICE(0x10C4, 0x82EF) }, /* CESINEL FALCO 6105 AC Power Supply */ + { USB_DEVICE(0x10C4, 0x82F1) }, /* CESINEL MEDCAL EFD Earth Fault Detector */ + { USB_DEVICE(0x10C4, 0x82F2) }, /* CESINEL MEDCAL ST Network Analyzer */ { USB_DEVICE(0x10C4, 0x82F4) }, /* Starizona MicroTouch */ { USB_DEVICE(0x10C4, 0x82F9) }, /* Procyon AVS */ { USB_DEVICE(0x10C4, 0x8341) }, /* Siemens MC35PU GPRS Modem */ @@ -120,7 +126,9 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x10C4, 0x8470) }, /* Juniper Networks BX Series System Console */ { USB_DEVICE(0x10C4, 0x8477) }, /* Balluff RFID */ { USB_DEVICE(0x10C4, 0x84B6) }, /* Starizona Hyperion */ + { USB_DEVICE(0x10C4, 0x851E) }, /* CESINEL MEDCAL PT Network Analyzer */ { USB_DEVICE(0x10C4, 0x85A7) }, /* LifeScan OneTouch Verio IQ */ + { USB_DEVICE(0x10C4, 0x85B8) }, /* CESINEL ReCon T Energy Logger */ { USB_DEVICE(0x10C4, 0x85EA) }, /* AC-Services IBUS-IF */ { USB_DEVICE(0x10C4, 0x85EB) }, /* AC-Services CIS-IBUS */ { USB_DEVICE(0x10C4, 0x85F8) }, /* Virtenio Preon32 */ @@ -130,10 +138,13 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x10C4, 0x8857) }, /* CEL EM357 ZigBee USB Stick */ { USB_DEVICE(0x10C4, 0x88A4) }, /* MMB Networks ZigBee USB Device */ { USB_DEVICE(0x10C4, 0x88A5) }, /* Planet Innovation Ingeni ZigBee USB Device */ + { USB_DEVICE(0x10C4, 0x88FB) }, /* CESINEL MEDCAL STII Network Analyzer */ + { USB_DEVICE(0x10C4, 0x8938) }, /* CESINEL MEDCAL S II Network Analyzer */ { USB_DEVICE(0x10C4, 0x8946) }, /* Ketra N1 Wireless Interface */ { USB_DEVICE(0x10C4, 0x8962) }, /* Brim Brothers charging dock */ { USB_DEVICE(0x10C4, 0x8977) }, /* CEL MeshWorks DevKit Device */ { USB_DEVICE(0x10C4, 0x8998) }, /* KCF Technologies PRN */ + { USB_DEVICE(0x10C4, 0x89A4) }, /* CESINEL FTBC Flexible Thyristor Bridge Controller */ { USB_DEVICE(0x10C4, 0x8A2A) }, /* HubZ dual ZigBee and Z-Wave dongle */ { USB_DEVICE(0x10C4, 0x8A5E) }, /* CEL EM3588 ZigBee USB Stick Long Range */ { USB_DEVICE(0x10C4, 0x8B34) }, /* Qivicon ZigBee USB Radio Stick */ From 216c5fab831e394d4a15e31c20fb5fa46ba24cd8 Mon Sep 17 00:00:00 2001 From: Karoly Pados Date: Sat, 9 Jun 2018 13:26:08 +0200 Subject: [PATCH 008/159] USB: serial: cp210x: add Silicon Labs IDs for Windows Update commit 2f839823382748664b643daa73f41ee0cc01ced6 upstream. Silicon Labs defines alternative VID/PID pairs for some chips that when used will automatically install drivers for Windows users without manual intervention. Unfortunately, these IDs are not recognized by the Linux module, so using these IDs improves user experience on one platform but degrades it on Linux. This patch addresses this problem. Signed-off-by: Karoly Pados Cc: stable Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp210x.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 041fa09f0505..73835027a7cc 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -150,8 +150,11 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x10C4, 0x8B34) }, /* Qivicon ZigBee USB Radio Stick */ { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */ + { USB_DEVICE(0x10C4, 0xEA63) }, /* Silicon Labs Windows Update (CP2101-4/CP2102N) */ { USB_DEVICE(0x10C4, 0xEA70) }, /* Silicon Labs factory default */ { USB_DEVICE(0x10C4, 0xEA71) }, /* Infinity GPS-MIC-1 Radio Monophone */ + { USB_DEVICE(0x10C4, 0xEA7A) }, /* Silicon Labs Windows Update (CP2105) */ + { USB_DEVICE(0x10C4, 0xEA7B) }, /* Silicon Labs Windows Update (CP2108) */ { USB_DEVICE(0x10C4, 0xF001) }, /* Elan Digital Systems USBscope50 */ { USB_DEVICE(0x10C4, 0xF002) }, /* Elan Digital Systems USBwave12 */ { USB_DEVICE(0x10C4, 0xF003) }, /* Elan Digital Systems USBpulse100 */ From a1f75c3f3a79147441649ea96d3a0b58e13ded31 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Sat, 26 May 2018 09:53:13 +0900 Subject: [PATCH 009/159] n_tty: Fix stall at n_tty_receive_char_special(). commit 3d63b7e4ae0dc5e02d28ddd2fa1f945defc68d81 upstream. syzbot is reporting stalls at n_tty_receive_char_special() [1]. This is because comparison is not working as expected since ldata->read_head can change at any moment. Mitigate this by explicitly masking with buffer size when checking condition for "while" loops. [1] https://syzkaller.appspot.com/bug?id=3d7481a346958d9469bebbeb0537d5f056bdd6e8 Signed-off-by: Tetsuo Handa Reported-by: syzbot Fixes: bc5a5e3f45d04784 ("n_tty: Don't wrap input buffer indices at buffer size") Cc: stable Cc: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 190e5dc15738..1d4d20e65dc3 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -128,6 +128,8 @@ struct n_tty_data { struct mutex output_lock; }; +#define MASK(x) ((x) & (N_TTY_BUF_SIZE - 1)) + static inline size_t read_cnt(struct n_tty_data *ldata) { return ldata->read_head - ldata->read_tail; @@ -1006,14 +1008,15 @@ static void eraser(unsigned char c, struct tty_struct *tty) } seen_alnums = 0; - while (ldata->read_head != ldata->canon_head) { + while (MASK(ldata->read_head) != MASK(ldata->canon_head)) { head = ldata->read_head; /* erase a single possibly multibyte character */ do { head--; c = read_buf(ldata, head); - } while (is_continuation(c, tty) && head != ldata->canon_head); + } while (is_continuation(c, tty) && + MASK(head) != MASK(ldata->canon_head)); /* do not partially erase */ if (is_continuation(c, tty)) @@ -1055,7 +1058,7 @@ static void eraser(unsigned char c, struct tty_struct *tty) * This info is used to go back the correct * number of columns. */ - while (tail != ldata->canon_head) { + while (MASK(tail) != MASK(ldata->canon_head)) { tail--; c = read_buf(ldata, tail); if (c == '\t') { @@ -1332,7 +1335,7 @@ n_tty_receive_char_special(struct tty_struct *tty, unsigned char c) finish_erasing(ldata); echo_char(c, tty); echo_char_raw('\n', ldata); - while (tail != ldata->read_head) { + while (MASK(tail) != MASK(ldata->read_head)) { echo_char(read_buf(ldata, tail), tty); tail++; } @@ -2479,7 +2482,7 @@ static unsigned long inq_canon(struct n_tty_data *ldata) tail = ldata->read_tail; nr = head - tail; /* Skip EOF-chars.. */ - while (head != tail) { + while (MASK(head) != MASK(tail)) { if (test_bit(tail & (N_TTY_BUF_SIZE - 1), ldata->read_flags) && read_buf(ldata, tail) == __DISABLED_CHAR) nr--; From 58fcaeb30e27df934c3cd5f13733292d2b455fa0 Mon Sep 17 00:00:00 2001 From: Laura Abbott Date: Mon, 11 Jun 2018 11:06:53 -0700 Subject: [PATCH 010/159] staging: android: ion: Return an ERR_PTR in ion_map_kernel commit 0a2bc00341dcfcc793c0dbf4f8d43adf60458b05 upstream. The expected return value from ion_map_kernel is an ERR_PTR. The error path for a vmalloc failure currently just returns NULL, triggering a warning in ion_buffer_kmap_get. Encode the vmalloc failure as an ERR_PTR. Reported-by: syzbot+55b1d9f811650de944c6@syzkaller.appspotmail.com Signed-off-by: Laura Abbott Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_heap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index ca15a87f6fd3..13a9b4c42b26 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -38,7 +38,7 @@ void *ion_heap_map_kernel(struct ion_heap *heap, struct page **tmp = pages; if (!pages) - return NULL; + return ERR_PTR(-ENOMEM); if (buffer->flags & ION_FLAG_CACHED) pgprot = PAGE_KERNEL; From 80fbfb1ce6fdfdb265d4ab3b0b87a7c3cf8f6aff Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Sat, 26 May 2018 09:53:14 +0900 Subject: [PATCH 011/159] n_tty: Access echo_* variables carefully. commit ebec3f8f5271139df618ebdf8427e24ba102ba94 upstream. syzbot is reporting stalls at __process_echoes() [1]. This is because since ldata->echo_commit < ldata->echo_tail becomes true for some reason, the discard loop is serving as almost infinite loop. This patch tries to avoid falling into ldata->echo_commit < ldata->echo_tail situation by making access to echo_* variables more carefully. Since reset_buffer_flags() is called without output_lock held, it should not touch echo_* variables. And omit a call to reset_buffer_flags() from n_tty_open() by using vzalloc(). Since add_echo_byte() is called without output_lock held, it needs memory barrier between storing into echo_buf[] and incrementing echo_head counter. echo_buf() needs corresponding memory barrier before reading echo_buf[]. Lack of handling the possibility of not-yet-stored multi-byte operation might be the reason of falling into ldata->echo_commit < ldata->echo_tail situation, for if I do WARN_ON(ldata->echo_commit == tail + 1) prior to echo_buf(ldata, tail + 1), the WARN_ON() fires. Also, explicitly masking with buffer for the former "while" loop, and use ldata->echo_commit > tail for the latter "while" loop. [1] https://syzkaller.appspot.com/bug?id=17f23b094cd80df750e5b0f8982c521ee6bcbf40 Signed-off-by: Tetsuo Handa Reported-by: syzbot Cc: Peter Hurley Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 42 ++++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 1d4d20e65dc3..b1ec202099b2 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -147,6 +147,7 @@ static inline unsigned char *read_buf_addr(struct n_tty_data *ldata, size_t i) static inline unsigned char echo_buf(struct n_tty_data *ldata, size_t i) { + smp_rmb(); /* Matches smp_wmb() in add_echo_byte(). */ return ldata->echo_buf[i & (N_TTY_BUF_SIZE - 1)]; } @@ -324,9 +325,7 @@ static inline void put_tty_queue(unsigned char c, struct n_tty_data *ldata) static void reset_buffer_flags(struct n_tty_data *ldata) { ldata->read_head = ldata->canon_head = ldata->read_tail = 0; - ldata->echo_head = ldata->echo_tail = ldata->echo_commit = 0; ldata->commit_head = 0; - ldata->echo_mark = 0; ldata->line_start = 0; ldata->erasing = 0; @@ -647,12 +646,19 @@ static size_t __process_echoes(struct tty_struct *tty) old_space = space = tty_write_room(tty); tail = ldata->echo_tail; - while (ldata->echo_commit != tail) { + while (MASK(ldata->echo_commit) != MASK(tail)) { c = echo_buf(ldata, tail); if (c == ECHO_OP_START) { unsigned char op; int no_space_left = 0; + /* + * Since add_echo_byte() is called without holding + * output_lock, we might see only portion of multi-byte + * operation. + */ + if (MASK(ldata->echo_commit) == MASK(tail + 1)) + goto not_yet_stored; /* * If the buffer byte is the start of a multi-byte * operation, get the next byte, which is either the @@ -664,6 +670,8 @@ static size_t __process_echoes(struct tty_struct *tty) unsigned int num_chars, num_bs; case ECHO_OP_ERASE_TAB: + if (MASK(ldata->echo_commit) == MASK(tail + 2)) + goto not_yet_stored; num_chars = echo_buf(ldata, tail + 2); /* @@ -758,7 +766,8 @@ static size_t __process_echoes(struct tty_struct *tty) /* If the echo buffer is nearly full (so that the possibility exists * of echo overrun before the next commit), then discard enough * data at the tail to prevent a subsequent overrun */ - while (ldata->echo_commit - tail >= ECHO_DISCARD_WATERMARK) { + while (ldata->echo_commit > tail && + ldata->echo_commit - tail >= ECHO_DISCARD_WATERMARK) { if (echo_buf(ldata, tail) == ECHO_OP_START) { if (echo_buf(ldata, tail + 1) == ECHO_OP_ERASE_TAB) tail += 3; @@ -768,6 +777,7 @@ static size_t __process_echoes(struct tty_struct *tty) tail++; } + not_yet_stored: ldata->echo_tail = tail; return old_space - space; } @@ -778,6 +788,7 @@ static void commit_echoes(struct tty_struct *tty) size_t nr, old, echoed; size_t head; + mutex_lock(&ldata->output_lock); head = ldata->echo_head; ldata->echo_mark = head; old = ldata->echo_commit - ldata->echo_tail; @@ -786,10 +797,12 @@ static void commit_echoes(struct tty_struct *tty) * is over the threshold (and try again each time another * block is accumulated) */ nr = head - ldata->echo_tail; - if (nr < ECHO_COMMIT_WATERMARK || (nr % ECHO_BLOCK > old % ECHO_BLOCK)) + if (nr < ECHO_COMMIT_WATERMARK || + (nr % ECHO_BLOCK > old % ECHO_BLOCK)) { + mutex_unlock(&ldata->output_lock); return; + } - mutex_lock(&ldata->output_lock); ldata->echo_commit = head; echoed = __process_echoes(tty); mutex_unlock(&ldata->output_lock); @@ -840,7 +853,9 @@ static void flush_echoes(struct tty_struct *tty) static inline void add_echo_byte(unsigned char c, struct n_tty_data *ldata) { - *echo_buf_addr(ldata, ldata->echo_head++) = c; + *echo_buf_addr(ldata, ldata->echo_head) = c; + smp_wmb(); /* Matches smp_rmb() in echo_buf(). */ + ldata->echo_head++; } /** @@ -1920,31 +1935,22 @@ static int n_tty_open(struct tty_struct *tty) struct n_tty_data *ldata; /* Currently a malloc failure here can panic */ - ldata = vmalloc(sizeof(*ldata)); + ldata = vzalloc(sizeof(*ldata)); if (!ldata) - goto err; + return -ENOMEM; ldata->overrun_time = jiffies; mutex_init(&ldata->atomic_read_lock); mutex_init(&ldata->output_lock); tty->disc_data = ldata; - reset_buffer_flags(tty->disc_data); - ldata->column = 0; - ldata->canon_column = 0; ldata->minimum_to_wake = 1; - ldata->num_overrun = 0; - ldata->no_room = 0; - ldata->lnext = 0; tty->closing = 0; /* indicate buffer work may resume */ clear_bit(TTY_LDISC_HALTED, &tty->flags); n_tty_set_termios(tty, NULL); tty_unthrottle(tty); - return 0; -err: - return -ENOMEM; } static inline int input_available_p(struct tty_struct *tty, int poll) From 99580265784e108e0f294564db80f689039b2e07 Mon Sep 17 00:00:00 2001 From: Dave Hansen Date: Tue, 22 Dec 2015 14:52:38 -0800 Subject: [PATCH 012/159] x86/boot: Fix early command-line parsing when matching at end commit 02afeaae9843733a39cd9b11053748b2d1dc5ae7 upstream. The x86 early command line parsing in cmdline_find_option_bool() is buggy. If it matches a specified 'option' all the way to the end of the command-line, it will consider it a match. For instance, cmdline = "foo"; cmdline_find_option_bool(cmdline, "fool"); will return 1. This is particularly annoying since we have actual FPU options like "noxsave" and "noxsaves" So, command-line "foo bar noxsave" will match *BOTH* a "noxsave" and "noxsaves". (This turns out not to be an actual problem because "noxsave" implies "noxsaves", but it's still confusing.) To fix this, we simplify the code and stop tracking 'len'. 'len' was trying to indicate either the NULL terminator *OR* the end of a non-NULL-terminated command line at 'COMMAND_LINE_SIZE'. But, each of the three states is *already* checking 'cmdline' for a NULL terminator. We _only_ need to check if we have overrun 'COMMAND_LINE_SIZE', and that we can do without keeping 'len' around. Also add some commends to clarify what is going on. Signed-off-by: Dave Hansen Signed-off-by: Borislav Petkov Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: fenghua.yu@intel.com Cc: yu-cheng.yu@intel.com Link: http://lkml.kernel.org/r/20151222225238.9AEB560C@viggo.jf.intel.com Signed-off-by: Ingo Molnar Cc: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- arch/x86/lib/cmdline.c | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/arch/x86/lib/cmdline.c b/arch/x86/lib/cmdline.c index a744506856b1..88ce150186c6 100644 --- a/arch/x86/lib/cmdline.c +++ b/arch/x86/lib/cmdline.c @@ -21,12 +21,14 @@ static inline int myisspace(u8 c) * @option: option string to look for * * Returns the position of that @option (starts counting with 1) - * or 0 on not found. + * or 0 on not found. @option will only be found if it is found + * as an entire word in @cmdline. For instance, if @option="car" + * then a cmdline which contains "cart" will not match. */ int cmdline_find_option_bool(const char *cmdline, const char *option) { char c; - int len, pos = 0, wstart = 0; + int pos = 0, wstart = 0; const char *opptr = NULL; enum { st_wordstart = 0, /* Start of word/after whitespace */ @@ -37,11 +39,14 @@ int cmdline_find_option_bool(const char *cmdline, const char *option) if (!cmdline) return -1; /* No command line */ - len = min_t(int, strlen(cmdline), COMMAND_LINE_SIZE); - if (!len) + if (!strlen(cmdline)) return 0; - while (len--) { + /* + * This 'pos' check ensures we do not overrun + * a non-NULL-terminated 'cmdline' + */ + while (pos < COMMAND_LINE_SIZE) { c = *(char *)cmdline++; pos++; @@ -58,17 +63,26 @@ int cmdline_find_option_bool(const char *cmdline, const char *option) /* fall through */ case st_wordcmp: - if (!*opptr) + if (!*opptr) { + /* + * We matched all the way to the end of the + * option we were looking for. If the + * command-line has a space _or_ ends, then + * we matched! + */ if (!c || myisspace(c)) return wstart; else state = st_wordskip; - else if (!c) + } else if (!c) { + /* + * Hit the NULL terminator on the end of + * cmdline. + */ return 0; - else if (c != *opptr++) + } else if (c != *opptr++) { state = st_wordskip; - else if (!len) /* last word and is matching */ - return wstart; + } break; case st_wordskip: From 8d33a08bd4c623fbf0e1be97725c59c8fa868ddb Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Mon, 26 Sep 2016 21:56:24 +0300 Subject: [PATCH 013/159] ath10k: fix rfc1042 header retrieval in QCA4019 with eth decap mode commit 2f38c3c01de945234d23dd163e3528ccb413066d upstream. Chipset from QCA99X0 onwards (QCA99X0, QCA9984, QCA4019 & future) rx_hdr_status is not padded to align in 4-byte boundary. Define a new hw_params field to handle different alignment behaviour between different hw. This patch fixes improper retrieval of rfc1042 header with QCA4019. This patch along with "ath10k: Properly remove padding from the start of rx payload" will fix traffic failure in ethernet decap mode for QCA4019. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Kalle Valo [bwh: This just adds the part that was left out of the previous backport, commit b88fb9ea475a.] Signed-off-by: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath10k/htt_rx.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index d26cb37b1fbd..b32c47fe926d 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -1166,6 +1166,7 @@ static void *ath10k_htt_rx_h_find_rfc1042(struct ath10k *ar, size_t hdr_len, crypto_len; void *rfc1042; bool is_first, is_last, is_amsdu; + int bytes_aligned = ar->hw_params.decap_align_bytes; rxd = (void *)msdu->data - sizeof(*rxd); hdr = (void *)rxd->rx_hdr_status; @@ -1182,8 +1183,8 @@ static void *ath10k_htt_rx_h_find_rfc1042(struct ath10k *ar, hdr_len = ieee80211_hdrlen(hdr->frame_control); crypto_len = ath10k_htt_rx_crypto_param_len(ar, enctype); - rfc1042 += round_up(hdr_len, 4) + - round_up(crypto_len, 4); + rfc1042 += round_up(hdr_len, bytes_aligned) + + round_up(crypto_len, bytes_aligned); } if (is_amsdu) From 2aa465dbe267a09311560fcf4592db7689270f90 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 18 Apr 2017 20:38:35 +0200 Subject: [PATCH 014/159] i2c: rcar: fix resume by always initializing registers before transfer commit ae481cc139658e89eb3ea671dd00b67bd87f01a3 upstream. Resume failed because of uninitialized registers. Instead of adding a resume callback, we simply initialize registers before every transfer. This lightweight change is more robust and will keep us safe if we ever need support for power domains or dynamic frequency changes. Signed-off-by: Wolfram Sang Acked-by: Kuninori Morimoto Signed-off-by: Wolfram Sang Cc: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/busses/i2c-rcar.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c index 6f89484765e3..dfe1a53ce4ad 100644 --- a/drivers/i2c/busses/i2c-rcar.c +++ b/drivers/i2c/busses/i2c-rcar.c @@ -484,6 +484,8 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap, pm_runtime_get_sync(dev); + rcar_i2c_init(priv); + ret = rcar_i2c_bus_barrier(priv); if (ret < 0) goto out; @@ -624,7 +626,6 @@ static int rcar_i2c_probe(struct platform_device *pdev) if (ret < 0) goto out_pm_put; - rcar_i2c_init(priv); pm_runtime_put(dev); irq = platform_get_irq(pdev, 0); From 21e9341ed96024aaead1a12c77e9869ad81f8b96 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 19 Jun 2018 18:47:52 +0100 Subject: [PATCH 015/159] ipv4: Fix error return value in fib_convert_metrics() The validation code modified by commit 5b5e7a0de2bb ("net: metrics: add proper netlink validation") is organised differently in older kernel versions. The fib_convert_metrics() function that is modified in the backports to 4.4 and 4.9 needs to returns an error code, not a success flag. Signed-off-by: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- net/ipv4/fib_semantics.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index 9d144cbd4e62..03ebff3950d8 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c @@ -980,7 +980,7 @@ fib_convert_metrics(struct fib_info *fi, const struct fib_config *cfg) return -EINVAL; } else { if (nla_len(nla) != sizeof(u32)) - return false; + return -EINVAL; val = nla_get_u32(nla); } if (type == RTAX_ADVMSS && val > 65535 - 40) From 5ac07564b47fdffbc293f9b129eb5af394b3d31f Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Wed, 29 Mar 2017 14:00:25 +0900 Subject: [PATCH 016/159] kprobes/x86: Do not modify singlestep buffer while resuming commit 804dec5bda9b4fcdab5f67fe61db4a0498af5221 upstream. Do not modify singlestep execution buffer (kprobe.ainsn.insn) while resuming from single-stepping, instead, modifies the buffer to add a jump back instruction at preparing buffer. Signed-off-by: Masami Hiramatsu Cc: Ananth N Mavinakayanahalli Cc: Andrey Ryabinin Cc: Anil S Keshavamurthy Cc: Borislav Petkov Cc: Brian Gerst Cc: David S . Miller Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Josh Poimboeuf Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Ye Xiaolong Link: http://lkml.kernel.org/r/149076361560.22469.1610155860343077495.stgit@devbox Signed-off-by: Ingo Molnar Reviewed-by: "Steven Rostedt (VMware)" Signed-off-by: Alexey Makhalov Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/kprobes/core.c | 42 ++++++++++++++++------------------ 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c index df9be5b91270..1f5c47a49e35 100644 --- a/arch/x86/kernel/kprobes/core.c +++ b/arch/x86/kernel/kprobes/core.c @@ -411,25 +411,38 @@ void free_insn_page(void *page) module_memfree(page); } +/* Prepare reljump right after instruction to boost */ +static void prepare_boost(struct kprobe *p, int length) +{ + if (can_boost(p->ainsn.insn, p->addr) && + MAX_INSN_SIZE - length >= RELATIVEJUMP_SIZE) { + /* + * These instructions can be executed directly if it + * jumps back to correct address. + */ + synthesize_reljump(p->ainsn.insn + length, p->addr + length); + p->ainsn.boostable = 1; + } else { + p->ainsn.boostable = -1; + } +} + static int arch_copy_kprobe(struct kprobe *p) { - int ret; + int len; set_memory_rw((unsigned long)p->ainsn.insn & PAGE_MASK, 1); /* Copy an instruction with recovering if other optprobe modifies it.*/ - ret = __copy_instruction(p->ainsn.insn, p->addr); - if (!ret) + len = __copy_instruction(p->ainsn.insn, p->addr); + if (!len) return -EINVAL; /* * __copy_instruction can modify the displacement of the instruction, * but it doesn't affect boostable check. */ - if (can_boost(p->ainsn.insn, p->addr)) - p->ainsn.boostable = 0; - else - p->ainsn.boostable = -1; + prepare_boost(p, len); set_memory_ro((unsigned long)p->ainsn.insn & PAGE_MASK, 1); @@ -894,21 +907,6 @@ static void resume_execution(struct kprobe *p, struct pt_regs *regs, break; } - if (p->ainsn.boostable == 0) { - if ((regs->ip > copy_ip) && - (regs->ip - copy_ip) + 5 < MAX_INSN_SIZE) { - /* - * These instructions can be executed directly if it - * jumps back to correct address. - */ - synthesize_reljump((void *)regs->ip, - (void *)orig_ip + (regs->ip - copy_ip)); - p->ainsn.boostable = 1; - } else { - p->ainsn.boostable = -1; - } - } - regs->ip += orig_ip - copy_ip; no_change: From 1e40d09a5575f6a2db841473baf329dc17bbe3ff Mon Sep 17 00:00:00 2001 From: Keith Busch Date: Thu, 14 Sep 2017 13:54:39 -0400 Subject: [PATCH 017/159] nvme-pci: initialize queue memory before interrupts commit 161b8be2bd6abad250d4b3f674bdd5480f15beeb upstream. A spurious interrupt before the nvme driver has initialized the completion queue may inadvertently cause the driver to believe it has a completion to process. This may result in a NULL dereference since the nvmeq's tags are not set at this point. The patch initializes the host's CQ memory so that a spurious interrupt isn't mistaken for a real completion. Signed-off-by: Keith Busch Reviewed-by: Johannes Thumshirn Signed-off-by: Christoph Hellwig Signed-off-by: Jens Axboe [bwh: Backported to 4.4: adjust context] Cc: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- drivers/nvme/host/pci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index e86fcc9e9852..01f47b68b6e7 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -1589,11 +1589,11 @@ static int nvme_create_queue(struct nvme_queue *nvmeq, int qid) if (result < 0) goto release_cq; + nvme_init_queue(nvmeq, qid); result = queue_request_irq(dev, nvmeq, nvmeq->irqname); if (result < 0) goto release_sq; - nvme_init_queue(nvmeq, qid); return result; release_sq: @@ -1797,6 +1797,7 @@ static int nvme_configure_admin_queue(struct nvme_dev *dev) goto free_nvmeq; nvmeq->cq_vector = 0; + nvme_init_queue(nvmeq, 0); result = queue_request_irq(dev, nvmeq, nvmeq->irqname); if (result) { nvmeq->cq_vector = -1; @@ -3165,7 +3166,6 @@ static void nvme_probe_work(struct work_struct *work) goto disable; } - nvme_init_queue(dev->queues[0], 0); result = nvme_alloc_admin_tags(dev); if (result) goto disable; From 753465123663c7c96b515befe4a199a2104582d3 Mon Sep 17 00:00:00 2001 From: Taehee Yoo Date: Mon, 11 Jun 2018 22:16:33 +0900 Subject: [PATCH 018/159] netfilter: nf_tables: use WARN_ON_ONCE instead of BUG_ON in nft_do_chain() commit adc972c5b88829d38ede08b1069718661c7330ae upstream. When depth of chain is bigger than NFT_JUMP_STACK_SIZE, the nft_do_chain crashes. But there is no need to crash hard here. Suggested-by: Florian Westphal Signed-off-by: Taehee Yoo Acked-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso Signed-off-by: Greg Kroah-Hartman --- net/netfilter/nf_tables_core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c index f3695a497408..99bc2f87a974 100644 --- a/net/netfilter/nf_tables_core.c +++ b/net/netfilter/nf_tables_core.c @@ -167,7 +167,8 @@ next_rule: switch (regs.verdict.code) { case NFT_JUMP: - BUG_ON(stackptr >= NFT_JUMP_STACK_SIZE); + if (WARN_ON_ONCE(stackptr >= NFT_JUMP_STACK_SIZE)) + return NF_DROP; jumpstack[stackptr].chain = chain; jumpstack[stackptr].rule = rule; jumpstack[stackptr].rulenum = rulenum; From 45f47e3a14933afa5261110dbeb580fbf6f6df1d Mon Sep 17 00:00:00 2001 From: Sean Nyekjaer Date: Tue, 22 May 2018 19:45:09 +0200 Subject: [PATCH 019/159] ARM: dts: imx6q: Use correct SDMA script for SPI5 core commit df07101e1c4a29e820df02f9989a066988b160e6 upstream. According to the reference manual the shp_2_mcu / mcu_2_shp scripts must be used for devices connected through the SPBA. This fixes an issue we saw with DMA transfers. Sometimes the SPI controller RX FIFO was not empty after a DMA transfer and the driver got stuck in the next PIO transfer when it read one word more than expected. commit dd4b487b32a35 ("ARM: dts: imx6: Use correct SDMA script for SPI cores") is fixing the same issue but only for SPI1 - 4. Fixes: 677940258dd8e ("ARM: dts: imx6q: enable dma for ecspi5") Signed-off-by: Sean Nyekjaer Reviewed-by: Fabio Estevam Signed-off-by: Shawn Guo Signed-off-by: Greg Kroah-Hartman --- arch/arm/boot/dts/imx6q.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi index 399103b8e2c9..c81fb8fdc41f 100644 --- a/arch/arm/boot/dts/imx6q.dtsi +++ b/arch/arm/boot/dts/imx6q.dtsi @@ -95,7 +95,7 @@ clocks = <&clks IMX6Q_CLK_ECSPI5>, <&clks IMX6Q_CLK_ECSPI5>; clock-names = "ipg", "per"; - dmas = <&sdma 11 7 1>, <&sdma 12 7 2>; + dmas = <&sdma 11 8 1>, <&sdma 12 8 2>; dma-names = "rx", "tx"; status = "disabled"; }; From 69a044d59c37221f97ae0308995573960b646252 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 28 May 2018 22:04:32 +0200 Subject: [PATCH 020/159] ubi: fastmap: Correctly handle interrupted erasures in EBA commit 781932375ffc6411713ee0926ccae8596ed0261c upstream. Fastmap cannot track the LEB unmap operation, therefore it can happen that after an interrupted erasure the mapping still looks good from Fastmap's point of view, while reading from the PEB will cause an ECC error and confuses the upper layer. Instead of teaching users of UBI how to deal with that, we read back the VID header and check for errors. If the PEB is empty or shows ECC errors we fixup the mapping and schedule the PEB for erasure. Fixes: dbb7d2a88d2a ("UBI: Add fastmap core") Cc: Reported-by: martin bayern Signed-off-by: Richard Weinberger Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/ubi/eba.c | 92 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 91 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index 4dd0391d2942..c4a25c858c07 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c @@ -350,6 +350,82 @@ out_unlock: return err; } +#ifdef CONFIG_MTD_UBI_FASTMAP +/** + * check_mapping - check and fixup a mapping + * @ubi: UBI device description object + * @vol: volume description object + * @lnum: logical eraseblock number + * @pnum: physical eraseblock number + * + * Checks whether a given mapping is valid. Fastmap cannot track LEB unmap + * operations, if such an operation is interrupted the mapping still looks + * good, but upon first read an ECC is reported to the upper layer. + * Normaly during the full-scan at attach time this is fixed, for Fastmap + * we have to deal with it while reading. + * If the PEB behind a LEB shows this symthom we change the mapping to + * %UBI_LEB_UNMAPPED and schedule the PEB for erasure. + * + * Returns 0 on success, negative error code in case of failure. + */ +static int check_mapping(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, + int *pnum) +{ + int err; + struct ubi_vid_hdr *vid_hdr; + + if (!ubi->fast_attach) + return 0; + + vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS); + if (!vid_hdr) + return -ENOMEM; + + err = ubi_io_read_vid_hdr(ubi, *pnum, vid_hdr, 0); + if (err > 0 && err != UBI_IO_BITFLIPS) { + int torture = 0; + + switch (err) { + case UBI_IO_FF: + case UBI_IO_FF_BITFLIPS: + case UBI_IO_BAD_HDR: + case UBI_IO_BAD_HDR_EBADMSG: + break; + default: + ubi_assert(0); + } + + if (err == UBI_IO_BAD_HDR_EBADMSG || err == UBI_IO_FF_BITFLIPS) + torture = 1; + + down_read(&ubi->fm_eba_sem); + vol->eba_tbl[lnum] = UBI_LEB_UNMAPPED; + up_read(&ubi->fm_eba_sem); + ubi_wl_put_peb(ubi, vol->vol_id, lnum, *pnum, torture); + + *pnum = UBI_LEB_UNMAPPED; + } else if (err < 0) { + ubi_err(ubi, "unable to read VID header back from PEB %i: %i", + *pnum, err); + + goto out_free; + } + + err = 0; + +out_free: + ubi_free_vid_hdr(ubi, vid_hdr); + + return err; +} +#else +static int check_mapping(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, + int *pnum) +{ + return 0; +} +#endif + /** * ubi_eba_read_leb - read data. * @ubi: UBI device description object @@ -381,7 +457,13 @@ int ubi_eba_read_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, return err; pnum = vol->eba_tbl[lnum]; - if (pnum < 0) { + if (pnum >= 0) { + err = check_mapping(ubi, vol, lnum, &pnum); + if (err < 0) + goto out_unlock; + } + + if (pnum == UBI_LEB_UNMAPPED) { /* * The logical eraseblock is not mapped, fill the whole buffer * with 0xFF bytes. The exception is static volumes for which @@ -696,6 +778,14 @@ int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, return err; pnum = vol->eba_tbl[lnum]; + if (pnum >= 0) { + err = check_mapping(ubi, vol, lnum, &pnum); + if (err < 0) { + leb_write_unlock(ubi, vol_id, lnum); + return err; + } + } + if (pnum >= 0) { dbg_eba("write %d bytes at offset %d of LEB %d:%d, PEB %d", len, offset, vol_id, lnum, pnum); From 9d45ae0158172943ba789cf39babaefaa67eaba2 Mon Sep 17 00:00:00 2001 From: Cannon Matthews Date: Tue, 3 Jul 2018 17:02:43 -0700 Subject: [PATCH 021/159] mm: hugetlb: yield when prepping struct pages commit 520495fe96d74e05db585fc748351e0504d8f40d upstream. When booting with very large numbers of gigantic (i.e. 1G) pages, the operations in the loop of gather_bootmem_prealloc, and specifically prep_compound_gigantic_page, takes a very long time, and can cause a softlockup if enough pages are requested at boot. For example booting with 3844 1G pages requires prepping (set_compound_head, init the count) over 1 billion 4K tail pages, which takes considerable time. Add a cond_resched() to the outer loop in gather_bootmem_prealloc() to prevent this lockup. Tested: Booted with softlockup_panic=1 hugepagesz=1G hugepages=3844 and no softlockup is reported, and the hugepages are reported as successfully setup. Link: http://lkml.kernel.org/r/20180627214447.260804-1-cannonmatthews@google.com Signed-off-by: Cannon Matthews Reviewed-by: Andrew Morton Reviewed-by: Mike Kravetz Acked-by: Michal Hocko Cc: Andres Lagar-Cavilla Cc: Peter Feiner Cc: Greg Thelen Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/hugetlb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 7294301d8495..a813b03021b7 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -2038,6 +2038,7 @@ static void __init gather_bootmem_prealloc(void) */ if (hstate_is_gigantic(h)) adjust_managed_page_count(page, 1 << h->order); + cond_resched(); } } From 02a8a256f5bea9fc7156cea4d3c7f10958c0355d Mon Sep 17 00:00:00 2001 From: Changbin Du Date: Wed, 31 Jan 2018 23:48:49 +0800 Subject: [PATCH 022/159] tracing: Fix missing return symbol in function_graph output commit 1fe4293f4b8de75824935f8d8e9a99c7fc6873da upstream. The function_graph tracer does not show the interrupt return marker for the leaf entry. On leaf entries, we see an unbalanced interrupt marker (the interrupt was entered, but nevern left). Before: 1) | SyS_write() { 1) | __fdget_pos() { 1) 0.061 us | __fget_light(); 1) 0.289 us | } 1) | vfs_write() { 1) 0.049 us | rw_verify_area(); 1) + 15.424 us | __vfs_write(); 1) ==========> | 1) 6.003 us | smp_apic_timer_interrupt(); 1) 0.055 us | __fsnotify_parent(); 1) 0.073 us | fsnotify(); 1) + 23.665 us | } 1) + 24.501 us | } After: 0) | SyS_write() { 0) | __fdget_pos() { 0) 0.052 us | __fget_light(); 0) 0.328 us | } 0) | vfs_write() { 0) 0.057 us | rw_verify_area(); 0) | __vfs_write() { 0) ==========> | 0) 8.548 us | smp_apic_timer_interrupt(); 0) <========== | 0) + 36.507 us | } /* __vfs_write */ 0) 0.049 us | __fsnotify_parent(); 0) 0.066 us | fsnotify(); 0) + 50.064 us | } 0) + 50.952 us | } Link: http://lkml.kernel.org/r/1517413729-20411-1-git-send-email-changbin.du@intel.com Cc: stable@vger.kernel.org Fixes: f8b755ac8e0cc ("tracing/function-graph-tracer: Output arrows signal on hardirq call/return") Signed-off-by: Changbin Du Signed-off-by: Steven Rostedt (VMware) Signed-off-by: Greg Kroah-Hartman --- kernel/trace/trace_functions_graph.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c index 7fd6f5a26143..e212ec4cfb4e 100644 --- a/kernel/trace/trace_functions_graph.c +++ b/kernel/trace/trace_functions_graph.c @@ -768,6 +768,7 @@ print_graph_entry_leaf(struct trace_iterator *iter, struct ftrace_graph_ret *graph_ret; struct ftrace_graph_ent *call; unsigned long long duration; + int cpu = iter->cpu; int i; graph_ret = &ret_entry->ret; @@ -776,7 +777,6 @@ print_graph_entry_leaf(struct trace_iterator *iter, if (data) { struct fgraph_cpu_data *cpu_data; - int cpu = iter->cpu; cpu_data = per_cpu_ptr(data->cpu_data, cpu); @@ -806,6 +806,9 @@ print_graph_entry_leaf(struct trace_iterator *iter, trace_seq_printf(s, "%ps();\n", (void *)call->func); + print_graph_irq(iter, graph_ret->func, TRACE_GRAPH_RET, + cpu, iter->ent->pid, flags); + return trace_handle_return(s); } From 9a737329c7c4a341009b7398164db8fa8e5358f0 Mon Sep 17 00:00:00 2001 From: Jann Horn Date: Mon, 25 Jun 2018 16:25:44 +0200 Subject: [PATCH 023/159] scsi: sg: mitigate read/write abuse commit 26b5b874aff5659a7e26e5b1997e3df2c41fa7fd upstream. As Al Viro noted in commit 128394eff343 ("sg_write()/bsg_write() is not fit to be called under KERNEL_DS"), sg improperly accesses userspace memory outside the provided buffer, permitting kernel memory corruption via splice(). But it doesn't just do it on ->write(), also on ->read(). As a band-aid, make sure that the ->read() and ->write() handlers can not be called in weird contexts (kernel context or credentials different from file opener), like for ib_safe_file_access(). If someone needs to use these interfaces from different security contexts, a new interface should be written that goes through the ->ioctl() handler. I've mostly copypasted ib_safe_file_access() over as sg_safe_file_access() because I couldn't find a good common header - please tell me if you know a better way. [mkp: s/_safe_/_check_/] Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Cc: Signed-off-by: Jann Horn Acked-by: Douglas Gilbert Signed-off-by: Martin K. Petersen Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/sg.c | 42 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 841f3fbec77c..4302880a20b3 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -51,6 +51,7 @@ static int sg_version_num = 30536; /* 2 digits for each component */ #include #include #include +#include /* for sg_check_file_access() */ #include "scsi.h" #include @@ -221,6 +222,33 @@ static void sg_device_destroy(struct kref *kref); sdev_prefix_printk(prefix, (sdp)->device, \ (sdp)->disk->disk_name, fmt, ##a) +/* + * The SCSI interfaces that use read() and write() as an asynchronous variant of + * ioctl(..., SG_IO, ...) are fundamentally unsafe, since there are lots of ways + * to trigger read() and write() calls from various contexts with elevated + * privileges. This can lead to kernel memory corruption (e.g. if these + * interfaces are called through splice()) and privilege escalation inside + * userspace (e.g. if a process with access to such a device passes a file + * descriptor to a SUID binary as stdin/stdout/stderr). + * + * This function provides protection for the legacy API by restricting the + * calling context. + */ +static int sg_check_file_access(struct file *filp, const char *caller) +{ + if (filp->f_cred != current_real_cred()) { + pr_err_once("%s: process %d (%s) changed security contexts after opening file descriptor, this is not allowed.\n", + caller, task_tgid_vnr(current), current->comm); + return -EPERM; + } + if (unlikely(segment_eq(get_fs(), KERNEL_DS))) { + pr_err_once("%s: process %d (%s) called from kernel context, this is not allowed.\n", + caller, task_tgid_vnr(current), current->comm); + return -EACCES; + } + return 0; +} + static int sg_allow_access(struct file *filp, unsigned char *cmd) { struct sg_fd *sfp = filp->private_data; @@ -405,6 +433,14 @@ sg_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos) struct sg_header *old_hdr = NULL; int retval = 0; + /* + * This could cause a response to be stranded. Close the associated + * file descriptor to free up any resources being held. + */ + retval = sg_check_file_access(filp, __func__); + if (retval) + return retval; + if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp))) return -ENXIO; SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp, @@ -592,9 +628,11 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) struct sg_header old_hdr; sg_io_hdr_t *hp; unsigned char cmnd[SG_MAX_CDB_SIZE]; + int retval; - if (unlikely(segment_eq(get_fs(), KERNEL_DS))) - return -EINVAL; + retval = sg_check_file_access(filp, __func__); + if (retval) + return retval; if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp))) return -ENXIO; From 8e0817deeb968cfd0e176ed204754b712af7ecd2 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Thu, 21 Jun 2018 14:49:38 +0200 Subject: [PATCH 024/159] s390: Correct register corruption in critical section cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 891f6a726cacbb87e5b06076693ffab53bd378d7 upstream. In the critical section cleanup we must not mess with r1. For march=z9 or older, larl + ex (instead of exrl) are used with r1 as a temporary register. This can clobber r1 in several interrupt handlers. Fix this by using r11 as a temp register. r11 is being saved by all callers of cleanup_critical. Fixes: 6dd85fbb87 ("s390: move expoline assembler macros to a header") Cc: stable@vger.kernel.org #v4.16 Reported-by: Oliver Kurz Reported-by: Petr Tesařík Signed-off-by: Christian Borntraeger Reviewed-by: Hendrik Brueckner Signed-off-by: Martin Schwidefsky Signed-off-by: Greg Kroah-Hartman --- arch/s390/kernel/entry.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 5416d5d68308..4cad1adff16b 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -1170,7 +1170,7 @@ cleanup_critical: jl 0f clg %r9,BASED(.Lcleanup_table+104) # .Lload_fpu_regs_end jl .Lcleanup_load_fpu_regs -0: BR_EX %r14 +0: BR_EX %r14,%r11 .align 8 .Lcleanup_table: @@ -1200,7 +1200,7 @@ cleanup_critical: ni __SIE_PROG0C+3(%r9),0xfe # no longer in SIE lctlg %c1,%c1,__LC_USER_ASCE # load primary asce larl %r9,sie_exit # skip forward to sie_exit - BR_EX %r14 + BR_EX %r14,%r11 #endif .Lcleanup_system_call: From df0fe72e2e1f18da3d045f0211b2c833d22578ff Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Mon, 25 Jun 2018 11:39:52 +0200 Subject: [PATCH 025/159] drbd: fix access after free commit 64dafbc9530c10300acffc57fae3269d95fa8f93 upstream. We have struct drbd_requests { ... struct bio *private_bio; ... } to hold a bio clone for local submission. On local IO completion, we put that bio, and in case we want to use the result later, we overload that member to hold the ERR_PTR() of the completion result, Which, before v4.3, used to be the passed in "int error", so we could first bio_put(), then assign. v4.3-rc1~100^2~21 4246a0b63bd8 block: add a bi_error field to struct bio changed that: bio_put(req->private_bio); - req->private_bio = ERR_PTR(error); + req->private_bio = ERR_PTR(bio->bi_error); Which introduces an access after free, because it was non obvious that req->private_bio == bio. Impact of that was mostly unnoticable, because we only use that value in a multiple-failure case, and even then map any "unexpected" error code to EIO, so worst case we could potentially mask a more specific error with EIO in a multiple failure case. Unless the pointed to memory region was unmapped, as is the case with CONFIG_DEBUG_PAGEALLOC, in which case this results in BUG: unable to handle kernel paging request v4.13-rc1~70^2~75 4e4cbee93d56 block: switch bios to blk_status_t changes it further to bio_put(req->private_bio); req->private_bio = ERR_PTR(blk_status_to_errno(bio->bi_status)); And blk_status_to_errno() now contains a WARN_ON_ONCE() for unexpected values, which catches this "sometimes", if the memory has been reused quickly enough for other things. Should also go into stable since 4.3, with the trivial change around 4.13. Cc: stable@vger.kernel.org Fixes: 4246a0b63bd8 block: add a bi_error field to struct bio Reported-by: Sarah Newman Signed-off-by: Lars Ellenberg Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- drivers/block/drbd/drbd_worker.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index 5578c1477ba6..8bfd4fd7e9ec 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c @@ -256,8 +256,8 @@ void drbd_request_endio(struct bio *bio) } else what = COMPLETED_OK; - bio_put(req->private_bio); req->private_bio = ERR_PTR(bio->bi_error); + bio_put(bio); /* not req_mod(), we need irqsave here! */ spin_lock_irqsave(&device->resource->req_lock, flags); From 6ee6f1787e69db4b8b155450ca8694c145c2517c Mon Sep 17 00:00:00 2001 From: Paulo Alcantara Date: Thu, 5 Jul 2018 13:46:34 -0300 Subject: [PATCH 026/159] cifs: Fix infinite loop when using hard mount option commit 7ffbe65578b44fafdef577a360eb0583929f7c6e upstream. For every request we send, whether it is SMB1 or SMB2+, we attempt to reconnect tcon (cifs_reconnect_tcon or smb2_reconnect) before carrying out the request. So, while server->tcpStatus != CifsNeedReconnect, we wait for the reconnection to succeed on wait_event_interruptible_timeout(). If it returns, that means that either the condition was evaluated to true, or timeout elapsed, or it was interrupted by a signal. Since we're not handling the case where the process woke up due to a received signal (-ERESTARTSYS), the next call to wait_event_interruptible_timeout() will _always_ fail and we end up looping forever inside either cifs_reconnect_tcon() or smb2_reconnect(). Here's an example of how to trigger that: $ mount.cifs //foo/share /mnt/test -o username=foo,password=foo,vers=1.0,hard (break connection to server before executing bellow cmd) $ stat -f /mnt/test & sleep 140 [1] 2511 $ ps -aux -q 2511 USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 2511 0.0 0.0 12892 1008 pts/0 S 12:24 0:00 stat -f /mnt/test $ kill -9 2511 (wait for a while; process is stuck in the kernel) $ ps -aux -q 2511 USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 2511 83.2 0.0 12892 1008 pts/0 R 12:24 30:01 stat -f /mnt/test By using 'hard' mount point means that cifs.ko will keep retrying indefinitely, however we must allow the process to be killed otherwise it would hang the system. Signed-off-by: Paulo Alcantara Cc: stable@vger.kernel.org Reviewed-by: Aurelien Aptel Signed-off-by: Steve French Signed-off-by: Greg Kroah-Hartman --- fs/cifs/cifssmb.c | 10 ++++++++-- fs/cifs/smb2pdu.c | 18 ++++++++++++------ 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 8632380d2b94..63aea21e6298 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -150,8 +150,14 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command) * greater than cifs socket timeout which is 7 seconds */ while (server->tcpStatus == CifsNeedReconnect) { - wait_event_interruptible_timeout(server->response_q, - (server->tcpStatus != CifsNeedReconnect), 10 * HZ); + rc = wait_event_interruptible_timeout(server->response_q, + (server->tcpStatus != CifsNeedReconnect), + 10 * HZ); + if (rc < 0) { + cifs_dbg(FYI, "%s: aborting reconnect due to a received" + " signal by the process\n", __func__); + return -ERESTARTSYS; + } /* are we still trying to reconnect? */ if (server->tcpStatus != CifsNeedReconnect) diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 807e989f436a..5f5ba807b414 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -158,7 +158,7 @@ out: static int smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon) { - int rc = 0; + int rc; struct nls_table *nls_codepage; struct cifs_ses *ses; struct TCP_Server_Info *server; @@ -169,10 +169,10 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon) * for those three - in the calling routine. */ if (tcon == NULL) - return rc; + return 0; if (smb2_command == SMB2_TREE_CONNECT) - return rc; + return 0; if (tcon->tidStatus == CifsExiting) { /* @@ -215,8 +215,14 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon) return -EAGAIN; } - wait_event_interruptible_timeout(server->response_q, - (server->tcpStatus != CifsNeedReconnect), 10 * HZ); + rc = wait_event_interruptible_timeout(server->response_q, + (server->tcpStatus != CifsNeedReconnect), + 10 * HZ); + if (rc < 0) { + cifs_dbg(FYI, "%s: aborting reconnect due to a received" + " signal by the process\n", __func__); + return -ERESTARTSYS; + } /* are we still trying to reconnect? */ if (server->tcpStatus != CifsNeedReconnect) @@ -234,7 +240,7 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon) } if (!tcon->ses->need_reconnect && !tcon->need_reconnect) - return rc; + return 0; nls_codepage = load_nls_default(); From 2cd33a53177ce739fe5f68052b2a737f1c40b425 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sat, 16 Jun 2018 20:21:45 -0400 Subject: [PATCH 027/159] jbd2: don't mark block as modified if the handle is out of credits commit e09463f220ca9a1a1ecfda84fcda658f99a1f12a upstream. Do not set the b_modified flag in block's journal head should not until after we're sure that jbd2_journal_dirty_metadat() will not abort with an error due to there not being enough space reserved in the jbd2 handle. Otherwise, future attempts to modify the buffer may lead a large number of spurious errors and warnings. This addresses CVE-2018-10883. https://bugzilla.kernel.org/show_bug.cgi?id=200071 Signed-off-by: Theodore Ts'o Cc: stable@kernel.org Signed-off-by: Greg Kroah-Hartman --- fs/jbd2/transaction.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index f3a31f55f372..bce343febb9e 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c @@ -1363,6 +1363,13 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh) if (jh->b_transaction == transaction && jh->b_jlist != BJ_Metadata) { jbd_lock_bh_state(bh); + if (jh->b_transaction == transaction && + jh->b_jlist != BJ_Metadata) + pr_err("JBD2: assertion failure: h_type=%u " + "h_line_no=%u block_no=%llu jlist=%u\n", + handle->h_type, handle->h_line_no, + (unsigned long long) bh->b_blocknr, + jh->b_jlist); J_ASSERT_JH(jh, jh->b_transaction != transaction || jh->b_jlist == BJ_Metadata); jbd_unlock_bh_state(bh); @@ -1382,11 +1389,11 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh) * of the transaction. This needs to be done * once a transaction -bzzz */ - jh->b_modified = 1; if (handle->h_buffer_credits <= 0) { ret = -ENOSPC; goto out_unlock_bh; } + jh->b_modified = 1; handle->h_buffer_credits--; } From b7d29dc8fe8d23243d3d87109099bdc34a684712 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Wed, 13 Jun 2018 23:08:26 -0400 Subject: [PATCH 028/159] ext4: make sure bitmaps and the inode table don't overlap with bg descriptors commit 77260807d1170a8cf35dbb06e07461a655f67eee upstream. It's really bad when the allocation bitmaps and the inode table overlap with the block group descriptors, since it causes random corruption of the bg descriptors. So we really want to head those off at the pass. https://bugzilla.kernel.org/show_bug.cgi?id=199865 Signed-off-by: Theodore Ts'o Cc: stable@kernel.org Signed-off-by: Greg Kroah-Hartman --- fs/ext4/super.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 0e0438b5ddbe..88409168cc1e 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -2102,6 +2102,7 @@ static int ext4_check_descriptors(struct super_block *sb, struct ext4_sb_info *sbi = EXT4_SB(sb); ext4_fsblk_t first_block = le32_to_cpu(sbi->s_es->s_first_data_block); ext4_fsblk_t last_block; + ext4_fsblk_t last_bg_block = sb_block + ext4_bg_num_gdb(sb, 0) + 1; ext4_fsblk_t block_bitmap; ext4_fsblk_t inode_bitmap; ext4_fsblk_t inode_table; @@ -2134,6 +2135,14 @@ static int ext4_check_descriptors(struct super_block *sb, if (!(sb->s_flags & MS_RDONLY)) return 0; } + if (block_bitmap >= sb_block + 1 && + block_bitmap <= last_bg_block) { + ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " + "Block bitmap for group %u overlaps " + "block group descriptors", i); + if (!(sb->s_flags & MS_RDONLY)) + return 0; + } if (block_bitmap < first_block || block_bitmap > last_block) { ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " "Block bitmap for group %u not in group " @@ -2148,6 +2157,14 @@ static int ext4_check_descriptors(struct super_block *sb, if (!(sb->s_flags & MS_RDONLY)) return 0; } + if (inode_bitmap >= sb_block + 1 && + inode_bitmap <= last_bg_block) { + ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " + "Inode bitmap for group %u overlaps " + "block group descriptors", i); + if (!(sb->s_flags & MS_RDONLY)) + return 0; + } if (inode_bitmap < first_block || inode_bitmap > last_block) { ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " "Inode bitmap for group %u not in group " @@ -2162,6 +2179,14 @@ static int ext4_check_descriptors(struct super_block *sb, if (!(sb->s_flags & MS_RDONLY)) return 0; } + if (inode_table >= sb_block + 1 && + inode_table <= last_bg_block) { + ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " + "Inode table for group %u overlaps " + "block group descriptors", i); + if (!(sb->s_flags & MS_RDONLY)) + return 0; + } if (inode_table < first_block || inode_table + sbi->s_itb_per_group - 1 > last_block) { ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " From afa9c75025bd1e24ccdc56fa331e865b626769e6 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Wed, 13 Jun 2018 23:00:48 -0400 Subject: [PATCH 029/159] ext4: always check block group bounds in ext4_init_block_bitmap() commit 819b23f1c501b17b9694325471789e6b5cc2d0d2 upstream. Regardless of whether the flex_bg feature is set, we should always check to make sure the bits we are setting in the block bitmap are within the block group bounds. https://bugzilla.kernel.org/show_bug.cgi?id=199865 Signed-off-by: Theodore Ts'o Cc: stable@kernel.org Signed-off-by: Greg Kroah-Hartman --- fs/ext4/balloc.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index c57a94f1c198..7d3451808bf3 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c @@ -183,7 +183,6 @@ static int ext4_init_block_bitmap(struct super_block *sb, unsigned int bit, bit_max; struct ext4_sb_info *sbi = EXT4_SB(sb); ext4_fsblk_t start, tmp; - int flex_bg = 0; struct ext4_group_info *grp; J_ASSERT_BH(bh, buffer_locked(bh)); @@ -216,22 +215,19 @@ static int ext4_init_block_bitmap(struct super_block *sb, start = ext4_group_first_block_no(sb, block_group); - if (ext4_has_feature_flex_bg(sb)) - flex_bg = 1; - /* Set bits for block and inode bitmaps, and inode table */ tmp = ext4_block_bitmap(sb, gdp); - if (!flex_bg || ext4_block_in_group(sb, tmp, block_group)) + if (ext4_block_in_group(sb, tmp, block_group)) ext4_set_bit(EXT4_B2C(sbi, tmp - start), bh->b_data); tmp = ext4_inode_bitmap(sb, gdp); - if (!flex_bg || ext4_block_in_group(sb, tmp, block_group)) + if (ext4_block_in_group(sb, tmp, block_group)) ext4_set_bit(EXT4_B2C(sbi, tmp - start), bh->b_data); tmp = ext4_inode_table(sb, gdp); for (; tmp < ext4_inode_table(sb, gdp) + sbi->s_itb_per_group; tmp++) { - if (!flex_bg || ext4_block_in_group(sb, tmp, block_group)) + if (ext4_block_in_group(sb, tmp, block_group)) ext4_set_bit(EXT4_B2C(sbi, tmp - start), bh->b_data); } From db3b00e3f392e9f879f7fd202437e68f90f35765 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Thu, 14 Jun 2018 00:58:00 -0400 Subject: [PATCH 030/159] ext4: only look at the bg_flags field if it is valid commit 8844618d8aa7a9973e7b527d038a2a589665002c upstream. The bg_flags field in the block group descripts is only valid if the uninit_bg or metadata_csum feature is enabled. We were not consistently looking at this field; fix this. Also block group #0 must never have uninitialized allocation bitmaps, or need to be zeroed, since that's where the root inode, and other special inodes are set up. Check for these conditions and mark the file system as corrupted if they are detected. This addresses CVE-2018-10876. https://bugzilla.kernel.org/show_bug.cgi?id=199403 Signed-off-by: Theodore Ts'o Cc: stable@kernel.org Signed-off-by: Greg Kroah-Hartman --- fs/ext4/balloc.c | 11 ++++++++++- fs/ext4/ialloc.c | 14 ++++++++++++-- fs/ext4/mballoc.c | 6 ++++-- fs/ext4/super.c | 11 ++++++++++- 4 files changed, 36 insertions(+), 6 deletions(-) diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index 7d3451808bf3..092da164bdc0 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c @@ -450,7 +450,16 @@ ext4_read_block_bitmap_nowait(struct super_block *sb, ext4_group_t block_group) goto verify; } ext4_lock_group(sb, block_group); - if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { + if (ext4_has_group_desc_csum(sb) && + (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))) { + if (block_group == 0) { + ext4_unlock_group(sb, block_group); + unlock_buffer(bh); + ext4_error(sb, "Block bitmap for bg 0 marked " + "uninitialized"); + err = -EFSCORRUPTED; + goto out; + } err = ext4_init_block_bitmap(sb, bh, block_group, desc); set_bitmap_uptodate(bh); set_buffer_uptodate(bh); diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 9fe55b7d4c2c..48d818eba9c3 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -152,7 +152,16 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group) } ext4_lock_group(sb, block_group); - if (desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) { + if (ext4_has_group_desc_csum(sb) && + (desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT))) { + if (block_group == 0) { + ext4_unlock_group(sb, block_group); + unlock_buffer(bh); + ext4_error(sb, "Inode bitmap for bg 0 marked " + "uninitialized"); + err = -EFSCORRUPTED; + goto out; + } memset(bh->b_data, 0, (EXT4_INODES_PER_GROUP(sb) + 7) / 8); ext4_mark_bitmap_end(EXT4_INODES_PER_GROUP(sb), sb->s_blocksize * 8, bh->b_data); @@ -919,7 +928,8 @@ got: /* recheck and clear flag under lock if we still need to */ ext4_lock_group(sb, group); - if (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { + if (ext4_has_group_desc_csum(sb) && + (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))) { gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT); ext4_free_group_clusters_set(sb, gdp, ext4_free_clusters_after_init(sb, group, gdp)); diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index d98ff184d94a..75f79ff29ce0 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -2445,7 +2445,8 @@ int ext4_mb_add_groupinfo(struct super_block *sb, ext4_group_t group, * initialize bb_free to be able to skip * empty groups without initialization */ - if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { + if (ext4_has_group_desc_csum(sb) && + (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))) { meta_group_info[i]->bb_free = ext4_free_clusters_after_init(sb, group, desc); } else { @@ -2966,7 +2967,8 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac, #endif ext4_set_bits(bitmap_bh->b_data, ac->ac_b_ex.fe_start, ac->ac_b_ex.fe_len); - if (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { + if (ext4_has_group_desc_csum(sb) && + (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))) { gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT); ext4_free_group_clusters_set(sb, gdp, ext4_free_clusters_after_init(sb, diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 88409168cc1e..4cff3ff7b9e0 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -2867,13 +2867,22 @@ static ext4_group_t ext4_has_uninit_itable(struct super_block *sb) ext4_group_t group, ngroups = EXT4_SB(sb)->s_groups_count; struct ext4_group_desc *gdp = NULL; + if (!ext4_has_group_desc_csum(sb)) + return ngroups; + for (group = 0; group < ngroups; group++) { gdp = ext4_get_group_desc(sb, group, NULL); if (!gdp) continue; - if (!(gdp->bg_flags & cpu_to_le16(EXT4_BG_INODE_ZEROED))) + if (gdp->bg_flags & cpu_to_le16(EXT4_BG_INODE_ZEROED)) + continue; + if (group != 0) break; + ext4_error(sb, "Inode table for bg 0 marked as " + "needing zeroing"); + if (sb->s_flags & MS_RDONLY) + return ngroups; } return group; From 353ebd3e98869b50ed47364d05acdf679c2c05c6 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Thu, 14 Jun 2018 12:55:10 -0400 Subject: [PATCH 031/159] ext4: verify the depth of extent tree in ext4_find_extent() commit bc890a60247171294acc0bd67d211fa4b88d40ba upstream. If there is a corupted file system where the claimed depth of the extent tree is -1, this can cause a massive buffer overrun leading to sadness. This addresses CVE-2018-10877. https://bugzilla.kernel.org/show_bug.cgi?id=199417 Signed-off-by: Theodore Ts'o Cc: stable@kernel.org Signed-off-by: Greg Kroah-Hartman --- fs/ext4/ext4_extents.h | 1 + fs/ext4/extents.c | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/fs/ext4/ext4_extents.h b/fs/ext4/ext4_extents.h index 3c9381547094..2d8e73793512 100644 --- a/fs/ext4/ext4_extents.h +++ b/fs/ext4/ext4_extents.h @@ -103,6 +103,7 @@ struct ext4_extent_header { }; #define EXT4_EXT_MAGIC cpu_to_le16(0xf30a) +#define EXT4_MAX_EXTENT_DEPTH 5 #define EXT4_EXTENT_TAIL_OFFSET(hdr) \ (sizeof(struct ext4_extent_header) + \ diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 4705c21f9d03..1708597659a1 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -876,6 +876,12 @@ ext4_find_extent(struct inode *inode, ext4_lblk_t block, eh = ext_inode_hdr(inode); depth = ext_depth(inode); + if (depth < 0 || depth > EXT4_MAX_EXTENT_DEPTH) { + EXT4_ERROR_INODE(inode, "inode has invalid extent depth: %d", + depth); + ret = -EFSCORRUPTED; + goto err; + } if (path) { ext4_ext_drop_refs(path); From faf01457010eb68009fba45dcad2232138c34164 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Fri, 15 Jun 2018 12:27:16 -0400 Subject: [PATCH 032/159] ext4: include the illegal physical block in the bad map ext4_error msg commit bdbd6ce01a70f02e9373a584d0ae9538dcf0a121 upstream. Signed-off-by: Theodore Ts'o Cc: stable@kernel.org Signed-off-by: Greg Kroah-Hartman --- fs/ext4/inode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 30efeb656c1e..b8f4394971c8 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -380,9 +380,9 @@ static int __check_block_validity(struct inode *inode, const char *func, if (!ext4_data_block_valid(EXT4_SB(inode->i_sb), map->m_pblk, map->m_len)) { ext4_error_inode(inode, func, line, map->m_pblk, - "lblock %lu mapped to illegal pblock " + "lblock %lu mapped to illegal pblock %llu " "(length %d)", (unsigned long) map->m_lblk, - map->m_len); + map->m_pblk, map->m_len); return -EFSCORRUPTED; } return 0; From b88fc699a023e0ef86f647c3d48a17d7cfff1f2a Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Fri, 15 Jun 2018 12:28:16 -0400 Subject: [PATCH 033/159] ext4: clear i_data in ext4_inode_info when removing inline data commit 6e8ab72a812396996035a37e5ca4b3b99b5d214b upstream. When converting from an inode from storing the data in-line to a data block, ext4_destroy_inline_data_nolock() was only clearing the on-disk copy of the i_blocks[] array. It was not clearing copy of the i_blocks[] in ext4_inode_info, in i_data[], which is the copy actually used by ext4_map_blocks(). This didn't matter much if we are using extents, since the extents header would be invalid and thus the extents could would re-initialize the extents tree. But if we are using indirect blocks, the previous contents of the i_blocks array will be treated as block numbers, with potentially catastrophic results to the file system integrity and/or user data. This gets worse if the file system is using a 1k block size and s_first_data is zero, but even without this, the file system can get quite badly corrupted. This addresses CVE-2018-10881. https://bugzilla.kernel.org/show_bug.cgi?id=200015 Signed-off-by: Theodore Ts'o Cc: stable@kernel.org Signed-off-by: Greg Kroah-Hartman --- fs/ext4/inline.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c index 3006b81c107f..e72f53a89764 100644 --- a/fs/ext4/inline.c +++ b/fs/ext4/inline.c @@ -434,6 +434,7 @@ static int ext4_destroy_inline_data_nolock(handle_t *handle, memset((void *)ext4_raw_inode(&is.iloc)->i_block, 0, EXT4_MIN_INLINE_DATA_SIZE); + memset(ei->i_data, 0, EXT4_MIN_INLINE_DATA_SIZE); if (ext4_has_feature_extents(inode->i_sb)) { if (S_ISDIR(inode->i_mode) || From ff6c96461be35381399466ad58f02b8d78ab480a Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sun, 17 Jun 2018 00:41:14 -0400 Subject: [PATCH 034/159] ext4: add more inode number paranoia checks commit c37e9e013469521d9adb932d17a1795c139b36db upstream. If there is a directory entry pointing to a system inode (such as a journal inode), complain and declare the file system to be corrupted. Also, if the superblock's first inode number field is too small, refuse to mount the file system. This addresses CVE-2018-10882. https://bugzilla.kernel.org/show_bug.cgi?id=200069 Signed-off-by: Theodore Ts'o Cc: stable@kernel.org Signed-off-by: Greg Kroah-Hartman --- fs/ext4/ext4.h | 5 ----- fs/ext4/inode.c | 3 ++- fs/ext4/super.c | 5 +++++ 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index c8ad14c697c4..f5d9f82b173a 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -1468,11 +1468,6 @@ static inline struct timespec ext4_current_time(struct inode *inode) static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino) { return ino == EXT4_ROOT_INO || - ino == EXT4_USR_QUOTA_INO || - ino == EXT4_GRP_QUOTA_INO || - ino == EXT4_BOOT_LOADER_INO || - ino == EXT4_JOURNAL_INO || - ino == EXT4_RESIZE_INO || (ino >= EXT4_FIRST_INO(sb) && ino <= le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count)); } diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index b8f4394971c8..b507de0e4bbf 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -3991,7 +3991,8 @@ static int __ext4_get_inode_loc(struct inode *inode, int inodes_per_block, inode_offset; iloc->bh = NULL; - if (!ext4_valid_inum(sb, inode->i_ino)) + if (inode->i_ino < EXT4_ROOT_INO || + inode->i_ino > le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count)) return -EFSCORRUPTED; iloc->block_group = (inode->i_ino - 1) / EXT4_INODES_PER_GROUP(sb); diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 4cff3ff7b9e0..9762fde91fb5 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -3549,6 +3549,11 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) } else { sbi->s_inode_size = le16_to_cpu(es->s_inode_size); sbi->s_first_ino = le32_to_cpu(es->s_first_ino); + if (sbi->s_first_ino < EXT4_GOOD_OLD_FIRST_INO) { + ext4_msg(sb, KERN_ERR, "invalid first ino: %u", + sbi->s_first_ino); + goto failed_mount; + } if ((sbi->s_inode_size < EXT4_GOOD_OLD_INODE_SIZE) || (!is_power_of_2(sbi->s_inode_size)) || (sbi->s_inode_size > blocksize)) { From 9ccad874bedabcc2fde0c1ea44a9b9f8afed5194 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sun, 17 Jun 2018 18:11:20 -0400 Subject: [PATCH 035/159] ext4: add more mount time checks of the superblock commit bfe0a5f47ada40d7984de67e59a7d3390b9b9ecc upstream. The kernel's ext4 mount-time checks were more permissive than e2fsprogs's libext2fs checks when opening a file system. The superblock is considered too insane for debugfs or e2fsck to operate on it, the kernel has no business trying to mount it. This will make file system fuzzing tools work harder, but the failure cases that they find will be more useful and be easier to evaluate. Signed-off-by: Theodore Ts'o Cc: stable@kernel.org Signed-off-by: Greg Kroah-Hartman --- fs/ext4/super.c | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 9762fde91fb5..fc8686afd6ec 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -3485,6 +3485,13 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) le32_to_cpu(es->s_log_block_size)); goto failed_mount; } + if (le32_to_cpu(es->s_log_cluster_size) > + (EXT4_MAX_CLUSTER_LOG_SIZE - EXT4_MIN_BLOCK_LOG_SIZE)) { + ext4_msg(sb, KERN_ERR, + "Invalid log cluster size: %u", + le32_to_cpu(es->s_log_cluster_size)); + goto failed_mount; + } if (le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks) > (blocksize / 4)) { ext4_msg(sb, KERN_ERR, @@ -3630,13 +3637,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) "block size (%d)", clustersize, blocksize); goto failed_mount; } - if (le32_to_cpu(es->s_log_cluster_size) > - (EXT4_MAX_CLUSTER_LOG_SIZE - EXT4_MIN_BLOCK_LOG_SIZE)) { - ext4_msg(sb, KERN_ERR, - "Invalid log cluster size: %u", - le32_to_cpu(es->s_log_cluster_size)); - goto failed_mount; - } sbi->s_cluster_bits = le32_to_cpu(es->s_log_cluster_size) - le32_to_cpu(es->s_log_block_size); sbi->s_clusters_per_group = @@ -3657,10 +3657,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) } } else { if (clustersize != blocksize) { - ext4_warning(sb, "fragment/cluster size (%d) != " - "block size (%d)", clustersize, - blocksize); - clustersize = blocksize; + ext4_msg(sb, KERN_ERR, + "fragment/cluster size (%d) != " + "block size (%d)", clustersize, blocksize); + goto failed_mount; } if (sbi->s_blocks_per_group > blocksize * 8) { ext4_msg(sb, KERN_ERR, @@ -3714,6 +3714,13 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) ext4_blocks_count(es)); goto failed_mount; } + if ((es->s_first_data_block == 0) && (es->s_log_block_size == 0) && + (sbi->s_cluster_ratio == 1)) { + ext4_msg(sb, KERN_WARNING, "bad geometry: first data " + "block is 0 with a 1k block and cluster size"); + goto failed_mount; + } + blocks_count = (ext4_blocks_count(es) - le32_to_cpu(es->s_first_data_block) + EXT4_BLOCKS_PER_GROUP(sb) - 1); @@ -3749,6 +3756,14 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) ret = -ENOMEM; goto failed_mount; } + if (((u64)sbi->s_groups_count * sbi->s_inodes_per_group) != + le32_to_cpu(es->s_inodes_count)) { + ext4_msg(sb, KERN_ERR, "inodes count not valid: %u vs %llu", + le32_to_cpu(es->s_inodes_count), + ((u64)sbi->s_groups_count * sbi->s_inodes_per_group)); + ret = -EINVAL; + goto failed_mount; + } bgl_lock_init(sbi->s_blockgroup_lock); From 9611051641837be394d2c2d7ba795dc279176fad Mon Sep 17 00:00:00 2001 From: Jon Derrick Date: Mon, 2 Jul 2018 18:45:18 -0400 Subject: [PATCH 036/159] ext4: check superblock mapped prior to committing commit a17712c8e4be4fa5404d20e9cd3b2b21eae7bc56 upstream. This patch attempts to close a hole leading to a BUG seen with hot removals during writes [1]. A block device (NVME namespace in this test case) is formatted to EXT4 without partitions. It's mounted and write I/O is run to a file, then the device is hot removed from the slot. The superblock attempts to be written to the drive which is no longer present. The typical chain of events leading to the BUG: ext4_commit_super() __sync_dirty_buffer() submit_bh() submit_bh_wbc() BUG_ON(!buffer_mapped(bh)); This fix checks for the superblock's buffer head being mapped prior to syncing. [1] https://www.spinics.net/lists/linux-ext4/msg56527.html Signed-off-by: Jon Derrick Signed-off-by: Theodore Ts'o Cc: stable@kernel.org Signed-off-by: Greg Kroah-Hartman --- fs/ext4/super.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index fc8686afd6ec..49af3c50b263 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -4442,6 +4442,14 @@ static int ext4_commit_super(struct super_block *sb, int sync) if (!sbh || block_device_ejected(sb)) return error; + + /* + * The superblock bh should be mapped, but it might not be if the + * device was hot-removed. Not much we can do but fail the I/O. + */ + if (!buffer_mapped(sbh)) + return error; + if (buffer_write_io_error(sbh)) { /* * Oh, dear. A previous attempt to write the From dc3f661542a18e2cf2a3f410aadb6593b095a9b8 Mon Sep 17 00:00:00 2001 From: Jason Andryuk Date: Fri, 22 Jun 2018 12:25:49 -0400 Subject: [PATCH 037/159] HID: i2c-hid: Fix "incomplete report" noise commit ef6eaf27274c0351f7059163918f3795da13199c upstream. Commit ac75a041048b ("HID: i2c-hid: fix size check and type usage") started writing messages when the ret_size is <= 2 from i2c_master_recv. However, my device i2c-DLL07D1 returns 2 for a short period of time (~0.5s) after I stop moving the pointing stick or touchpad. It varies, but you get ~50 messages each time which spams the log hard. [ 95.925055] i2c_hid i2c-DLL07D1:01: i2c_hid_get_input: incomplete report (83/2) This has also been observed with a i2c-ALP0017. [ 1781.266353] i2c_hid i2c-ALP0017:00: i2c_hid_get_input: incomplete report (30/2) Only print the message when ret_size is totally invalid and less than 2 to cut down on the log spam. Fixes: ac75a041048b ("HID: i2c-hid: fix size check and type usage") Reported-by: John Smith Cc: stable@vger.kernel.org Signed-off-by: Jason Andryuk Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/hid/i2c-hid/i2c-hid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c index 4c3ed078c6b9..a5fed668fde1 100644 --- a/drivers/hid/i2c-hid/i2c-hid.c +++ b/drivers/hid/i2c-hid/i2c-hid.c @@ -413,7 +413,7 @@ static void i2c_hid_get_input(struct i2c_hid *ihid) return; } - if ((ret_size > size) || (ret_size <= 2)) { + if ((ret_size > size) || (ret_size < 2)) { dev_err(&ihid->client->dev, "%s: incomplete report (%d/%d)\n", __func__, size, ret_size); return; From c0b166a64eef92a410a50f71b12b1b63cc5f32db Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Fri, 29 Jun 2018 17:08:44 -0500 Subject: [PATCH 038/159] HID: hiddev: fix potential Spectre v1 commit 4f65245f2d178b9cba48350620d76faa4a098841 upstream. uref->field_index, uref->usage_index, finfo.field_index and cinfo.index can be indirectly controlled by user-space, hence leading to a potential exploitation of the Spectre variant 1 vulnerability. This issue was detected with the help of Smatch: drivers/hid/usbhid/hiddev.c:473 hiddev_ioctl_usage() warn: potential spectre issue 'report->field' (local cap) drivers/hid/usbhid/hiddev.c:477 hiddev_ioctl_usage() warn: potential spectre issue 'field->usage' (local cap) drivers/hid/usbhid/hiddev.c:757 hiddev_ioctl() warn: potential spectre issue 'report->field' (local cap) drivers/hid/usbhid/hiddev.c:801 hiddev_ioctl() warn: potential spectre issue 'hid->collection' (local cap) Fix this by sanitizing such structure fields before using them to index report->field, field->usage and hid->collection Notice that given that speculation windows are large, the policy is to kill the speculation on the first load and not worry if it can be completed with a dependent load/store [1]. [1] https://marc.info/?l=linux-kernel&m=152449131114778&w=2 Cc: stable@vger.kernel.org Signed-off-by: Gustavo A. R. Silva Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/hid/usbhid/hiddev.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index 700145b15088..b59b15d4caa9 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c @@ -35,6 +35,7 @@ #include #include #include +#include #include "usbhid.h" #ifdef CONFIG_USB_DYNAMIC_MINORS @@ -478,10 +479,14 @@ static noinline int hiddev_ioctl_usage(struct hiddev *hiddev, unsigned int cmd, if (uref->field_index >= report->maxfield) goto inval; + uref->field_index = array_index_nospec(uref->field_index, + report->maxfield); field = report->field[uref->field_index]; if (uref->usage_index >= field->maxusage) goto inval; + uref->usage_index = array_index_nospec(uref->usage_index, + field->maxusage); uref->usage_code = field->usage[uref->usage_index].hid; @@ -508,6 +513,8 @@ static noinline int hiddev_ioctl_usage(struct hiddev *hiddev, unsigned int cmd, if (uref->field_index >= report->maxfield) goto inval; + uref->field_index = array_index_nospec(uref->field_index, + report->maxfield); field = report->field[uref->field_index]; @@ -761,6 +768,8 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) if (finfo.field_index >= report->maxfield) break; + finfo.field_index = array_index_nospec(finfo.field_index, + report->maxfield); field = report->field[finfo.field_index]; memset(&finfo, 0, sizeof(finfo)); @@ -801,6 +810,8 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) if (cinfo.index >= hid->maxcollection) break; + cinfo.index = array_index_nospec(cinfo.index, + hid->maxcollection); cinfo.type = hid->collection[cinfo.index].type; cinfo.usage = hid->collection[cinfo.index].usage; From ef111ea31575bdc50c0c914fe036a1d0ad0cae4e Mon Sep 17 00:00:00 2001 From: Daniel Rosenberg Date: Mon, 2 Jul 2018 16:59:37 -0700 Subject: [PATCH 039/159] HID: debug: check length before copy_to_user() commit 717adfdaf14704fd3ec7fa2c04520c0723247eac upstream. If our length is greater than the size of the buffer, we overflow the buffer Cc: stable@vger.kernel.org Signed-off-by: Daniel Rosenberg Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/hid/hid-debug.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c index 2886b645ced7..6c60f4b63d21 100644 --- a/drivers/hid/hid-debug.c +++ b/drivers/hid/hid-debug.c @@ -1152,6 +1152,8 @@ copy_rest: goto out; if (list->tail > list->head) { len = list->tail - list->head; + if (len > count) + len = count; if (copy_to_user(buffer + ret, &list->hid_debug_buf[list->head], len)) { ret = -EFAULT; @@ -1161,6 +1163,8 @@ copy_rest: list->head += len; } else { len = HID_DEBUG_BUFSIZE - list->head; + if (len > count) + len = count; if (copy_to_user(buffer, &list->hid_debug_buf[list->head], len)) { ret = -EFAULT; @@ -1168,7 +1172,9 @@ copy_rest: } list->head = 0; ret += len; - goto copy_rest; + count -= len; + if (count > 0) + goto copy_rest; } } From e462d226fbb3fd36fc2425970b17108ad3b5bb9d Mon Sep 17 00:00:00 2001 From: Yazen Ghannam Date: Sat, 30 Apr 2016 14:33:57 +0200 Subject: [PATCH 040/159] x86/mce: Detect local MCEs properly commit fead35c68926682c90c995f22b48f1c8d78865c1 upstream. Check the MCG_STATUS_LMCES bit on Intel to verify that current MCE is local. It is always local on AMD. Signed-off-by: Yazen Ghannam [ Massaged it a bit. Reflowed comments. Shut up -Wmaybe-uninitialized. ] Signed-off-by: Borislav Petkov Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Tony Luck Cc: linux-edac Link: http://lkml.kernel.org/r/1462019637-16474-8-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/mcheck/mce.c | 33 +++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index 6edb9530d7e9..474526a57284 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c @@ -980,11 +980,12 @@ void do_machine_check(struct pt_regs *regs, long error_code) int i; int worst = 0; int severity; + /* * Establish sequential order between the CPUs entering the machine * check handler. */ - int order; + int order = -1; /* * If no_way_out gets set, there is no safe way to recover from this * MCE. If mca_cfg.tolerant is cranked up, we'll try anyway. @@ -1000,7 +1001,12 @@ void do_machine_check(struct pt_regs *regs, long error_code) char *msg = "Unknown"; u64 recover_paddr = ~0ull; int flags = MF_ACTION_REQUIRED; - int lmce = 0; + + /* + * MCEs are always local on AMD. Same is determined by MCG_STATUS_LMCES + * on Intel. + */ + int lmce = 1; /* If this CPU is offline, just bail out. */ if (cpu_is_offline(smp_processor_id())) { @@ -1039,19 +1045,20 @@ void do_machine_check(struct pt_regs *regs, long error_code) kill_it = 1; /* - * Check if this MCE is signaled to only this logical processor + * Check if this MCE is signaled to only this logical processor, + * on Intel only. */ - if (m.mcgstatus & MCG_STATUS_LMCES) - lmce = 1; - else { - /* - * Go through all the banks in exclusion of the other CPUs. - * This way we don't report duplicated events on shared banks - * because the first one to see it will clear it. - * If this is a Local MCE, then no need to perform rendezvous. - */ + if (m.cpuvendor == X86_VENDOR_INTEL) + lmce = m.mcgstatus & MCG_STATUS_LMCES; + + /* + * Go through all banks in exclusion of the other CPUs. This way we + * don't report duplicated events on shared banks because the first one + * to see it will clear it. If this is a Local MCE, then no need to + * perform rendezvous. + */ + if (!lmce) order = mce_start(&no_way_out); - } for (i = 0; i < cfg->banks; i++) { __clear_bit(i, toclear); From 99b6d2c3bb7984b9ab5eac50120e0dde53235f2f Mon Sep 17 00:00:00 2001 From: Tony Luck Date: Fri, 22 Jun 2018 11:54:23 +0200 Subject: [PATCH 041/159] x86/mce: Fix incorrect "Machine check from unknown source" message commit 40c36e2741d7fe1e66d6ec55477ba5fd19c9c5d2 upstream. Some injection testing resulted in the following console log: mce: [Hardware Error]: CPU 22: Machine Check Exception: f Bank 1: bd80000000100134 mce: [Hardware Error]: RIP 10: {pmem_do_bvec+0x11d/0x330 [nd_pmem]} mce: [Hardware Error]: TSC c51a63035d52 ADDR 3234bc4000 MISC 88 mce: [Hardware Error]: PROCESSOR 0:50654 TIME 1526502199 SOCKET 0 APIC 38 microcode 2000043 mce: [Hardware Error]: Run the above through 'mcelog --ascii' Kernel panic - not syncing: Machine check from unknown source This confused everybody because the first line quite clearly shows that we found a logged error in "Bank 1", while the last line says "unknown source". The problem is that the Linux code doesn't do the right thing for a local machine check that results in a fatal error. It turns out that we know very early in the handler whether the machine check is fatal. The call to mce_no_way_out() has checked all the banks for the CPU that took the local machine check. If it says we must crash, we can do so right away with the right messages. We do scan all the banks again. This means that we might initially not see a problem, but during the second scan find something fatal. If this happens we print a slightly different message (so I can see if it actually every happens). [ bp: Remove unneeded severity assignment. ] Signed-off-by: Tony Luck Signed-off-by: Borislav Petkov Signed-off-by: Thomas Gleixner Cc: Ashok Raj Cc: Dan Williams Cc: Qiuxu Zhuo Cc: linux-edac Cc: stable@vger.kernel.org # 4.2 Link: http://lkml.kernel.org/r/52e049a497e86fd0b71c529651def8871c804df0.1527283897.git.tony.luck@intel.com Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/mcheck/mce.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index 474526a57284..ddc9b8125918 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c @@ -1052,13 +1052,18 @@ void do_machine_check(struct pt_regs *regs, long error_code) lmce = m.mcgstatus & MCG_STATUS_LMCES; /* + * Local machine check may already know that we have to panic. + * Broadcast machine check begins rendezvous in mce_start() * Go through all banks in exclusion of the other CPUs. This way we * don't report duplicated events on shared banks because the first one - * to see it will clear it. If this is a Local MCE, then no need to - * perform rendezvous. + * to see it will clear it. */ - if (!lmce) + if (lmce) { + if (no_way_out) + mce_panic("Fatal local machine check", &m, msg); + } else { order = mce_start(&no_way_out); + } for (i = 0; i < cfg->banks; i++) { __clear_bit(i, toclear); @@ -1135,12 +1140,17 @@ void do_machine_check(struct pt_regs *regs, long error_code) no_way_out = worst >= MCE_PANIC_SEVERITY; } else { /* - * Local MCE skipped calling mce_reign() - * If we found a fatal error, we need to panic here. + * If there was a fatal machine check we should have + * already called mce_panic earlier in this function. + * Since we re-read the banks, we might have found + * something new. Check again to see if we found a + * fatal error. We call "mce_severity()" again to + * make sure we have the right "msg". */ - if (worst >= MCE_PANIC_SEVERITY && mca_cfg.tolerant < 3) - mce_panic("Machine check from unknown source", - NULL, NULL); + if (worst >= MCE_PANIC_SEVERITY && mca_cfg.tolerant < 3) { + mce_severity(&m, cfg->tolerant, &msg, true); + mce_panic("Local fatal machine check!", &m, msg); + } } /* From 7f9c65ea59709c5512d05d8c0d5c48be2f9ad478 Mon Sep 17 00:00:00 2001 From: Brad Love Date: Tue, 6 Mar 2018 14:15:34 -0500 Subject: [PATCH 042/159] media: cx25840: Use subdev host data for PLL override commit 3ee9bc12342cf546313d300808ff47d7dbb8e7db upstream. The cx25840 driver currently configures 885, 887, and 888 using default divisors for each chip. This check to see if the cx23885 driver has passed the cx25840 a non-default clock rate for a specific chip. If a cx23885 board has left clk_freq at 0, the clock default values will be used to configure the PLLs. This patch only has effect on 888 boards who set clk_freq to 25M. Signed-off-by: Brad Love Signed-off-by: Mauro Carvalho Chehab Cc: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- drivers/media/i2c/cx25840/cx25840-core.c | 28 +++++++++++++++++++----- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/drivers/media/i2c/cx25840/cx25840-core.c b/drivers/media/i2c/cx25840/cx25840-core.c index a47ab1947cc4..17d217c3585a 100644 --- a/drivers/media/i2c/cx25840/cx25840-core.c +++ b/drivers/media/i2c/cx25840/cx25840-core.c @@ -467,8 +467,13 @@ static void cx23885_initialize(struct i2c_client *client) { DEFINE_WAIT(wait); struct cx25840_state *state = to_state(i2c_get_clientdata(client)); + u32 clk_freq = 0; struct workqueue_struct *q; + /* cx23885 sets hostdata to clk_freq pointer */ + if (v4l2_get_subdev_hostdata(&state->sd)) + clk_freq = *((u32 *)v4l2_get_subdev_hostdata(&state->sd)); + /* * Come out of digital power down * The CX23888, at least, needs this, otherwise registers aside from @@ -504,8 +509,13 @@ static void cx23885_initialize(struct i2c_client *client) * 50.0 MHz * (0xb + 0xe8ba26/0x2000000)/4 = 5 * 28.636363 MHz * 572.73 MHz before post divide */ - /* HVR1850 or 50MHz xtal */ - cx25840_write(client, 0x2, 0x71); + if (clk_freq == 25000000) { + /* 888/ImpactVCBe or 25Mhz xtal */ + ; /* nothing to do */ + } else { + /* HVR1850 or 50MHz xtal */ + cx25840_write(client, 0x2, 0x71); + } cx25840_write4(client, 0x11c, 0x01d1744c); cx25840_write4(client, 0x118, 0x00000416); cx25840_write4(client, 0x404, 0x0010253e); @@ -548,9 +558,15 @@ static void cx23885_initialize(struct i2c_client *client) /* HVR1850 */ switch (state->id) { case CX23888_AV: - /* 888/HVR1250 specific */ - cx25840_write4(client, 0x10c, 0x13333333); - cx25840_write4(client, 0x108, 0x00000515); + if (clk_freq == 25000000) { + /* 888/ImpactVCBe or 25MHz xtal */ + cx25840_write4(client, 0x10c, 0x01b6db7b); + cx25840_write4(client, 0x108, 0x00000512); + } else { + /* 888/HVR1250 or 50MHz xtal */ + cx25840_write4(client, 0x10c, 0x13333333); + cx25840_write4(client, 0x108, 0x00000515); + } break; default: cx25840_write4(client, 0x10c, 0x002be2c9); @@ -577,7 +593,7 @@ static void cx23885_initialize(struct i2c_client *client) * 368.64 MHz before post divide * 122.88 MHz / 0xa = 12.288 MHz */ - /* HVR1850 or 50MHz xtal */ + /* HVR1850 or 50MHz xtal or 25MHz xtal */ cx25840_write4(client, 0x114, 0x017dbf48); cx25840_write4(client, 0x110, 0x000a030e); break; From aaf87537eb46628a8841d02b0fd4a81d1c06161e Mon Sep 17 00:00:00 2001 From: Vlastimil Babka Date: Thu, 7 Jun 2018 17:09:29 -0700 Subject: [PATCH 043/159] mm, page_alloc: do not break __GFP_THISNODE by zonelist reset commit 7810e6781e0fcbca78b91cf65053f895bf59e85f upstream. In __alloc_pages_slowpath() we reset zonelist and preferred_zoneref for allocations that can ignore memory policies. The zonelist is obtained from current CPU's node. This is a problem for __GFP_THISNODE allocations that want to allocate on a different node, e.g. because the allocating thread has been migrated to a different CPU. This has been observed to break SLAB in our 4.4-based kernel, because there it relies on __GFP_THISNODE working as intended. If a slab page is put on wrong node's list, then further list manipulations may corrupt the list because page_to_nid() is used to determine which node's list_lock should be locked and thus we may take a wrong lock and race. Current SLAB implementation seems to be immune by luck thanks to commit 511e3a058812 ("mm/slab: make cache_grow() handle the page allocated on arbitrary node") but there may be others assuming that __GFP_THISNODE works as promised. We can fix it by simply removing the zonelist reset completely. There is actually no reason to reset it, because memory policies and cpusets don't affect the zonelist choice in the first place. This was different when commit 183f6371aac2 ("mm: ignore mempolicies when using ALLOC_NO_WATERMARK") introduced the code, as mempolicies provided their own restricted zonelists. We might consider this for 4.17 although I don't know if there's anything currently broken. SLAB is currently not affected, but in kernels older than 4.7 that don't yet have 511e3a058812 ("mm/slab: make cache_grow() handle the page allocated on arbitrary node") it is. That's at least 4.4 LTS. Older ones I'll have to check. So stable backports should be more important, but will have to be reviewed carefully, as the code went through many changes. BTW I think that also the ac->preferred_zoneref reset is currently useless if we don't also reset ac->nodemask from a mempolicy to NULL first (which we probably should for the OOM victims etc?), but I would leave that for a separate patch. Link: http://lkml.kernel.org/r/20180525130853.13915-1-vbabka@suse.cz Signed-off-by: Vlastimil Babka Fixes: 183f6371aac2 ("mm: ignore mempolicies when using ALLOC_NO_WATERMARK") Acked-by: Mel Gorman Cc: Michal Hocko Cc: David Rientjes Cc: Joonsoo Kim Cc: Vlastimil Babka Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/page_alloc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index a4c9cd80c7b6..fd75e27c9b40 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -3109,8 +3109,6 @@ retry: * the allocation is high priority and these type of * allocations are system rather than user orientated */ - ac->zonelist = node_zonelist(numa_node_id(), gfp_mask); - page = __alloc_pages_high_priority(gfp_mask, order, ac); if (page) { From 7396cb30cbfb379fb9fe715f348f2effe8eb52b7 Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Thu, 17 Nov 2016 11:24:20 -0800 Subject: [PATCH 044/159] dm bufio: avoid sleeping while holding the dm_bufio lock commit 9ea61cac0b1ad0c09022f39fd97e9b99a2cfc2dc upstream. We've seen in-field reports showing _lots_ (18 in one case, 41 in another) of tasks all sitting there blocked on: mutex_lock+0x4c/0x68 dm_bufio_shrink_count+0x38/0x78 shrink_slab.part.54.constprop.65+0x100/0x464 shrink_zone+0xa8/0x198 In the two cases analyzed, we see one task that looks like this: Workqueue: kverityd verity_prefetch_io __switch_to+0x9c/0xa8 __schedule+0x440/0x6d8 schedule+0x94/0xb4 schedule_timeout+0x204/0x27c schedule_timeout_uninterruptible+0x44/0x50 wait_iff_congested+0x9c/0x1f0 shrink_inactive_list+0x3a0/0x4cc shrink_lruvec+0x418/0x5cc shrink_zone+0x88/0x198 try_to_free_pages+0x51c/0x588 __alloc_pages_nodemask+0x648/0xa88 __get_free_pages+0x34/0x7c alloc_buffer+0xa4/0x144 __bufio_new+0x84/0x278 dm_bufio_prefetch+0x9c/0x154 verity_prefetch_io+0xe8/0x10c process_one_work+0x240/0x424 worker_thread+0x2fc/0x424 kthread+0x10c/0x114 ...and that looks to be the one holding the mutex. The problem has been reproduced on fairly easily: 0. Be running Chrome OS w/ verity enabled on the root filesystem 1. Pick test patch: http://crosreview.com/412360 2. Install launchBalloons.sh and balloon.arm from http://crbug.com/468342 ...that's just a memory stress test app. 3. On a 4GB rk3399 machine, run nice ./launchBalloons.sh 4 900 100000 ...that tries to eat 4 * 900 MB of memory and keep accessing. 4. Login to the Chrome web browser and restore many tabs With that, I've seen printouts like: DOUG: long bufio 90758 ms ...and stack trace always show's we're in dm_bufio_prefetch(). The problem is that we try to allocate memory with GFP_NOIO while we're holding the dm_bufio lock. Instead we should be using GFP_NOWAIT. Using GFP_NOIO can cause us to sleep while holding the lock and that causes the above problems. The current behavior explained by David Rientjes: It will still try reclaim initially because __GFP_WAIT (or __GFP_KSWAPD_RECLAIM) is set by GFP_NOIO. This is the cause of contention on dm_bufio_lock() that the thread holds. You want to pass GFP_NOWAIT instead of GFP_NOIO to alloc_buffer() when holding a mutex that can be contended by a concurrent slab shrinker (if count_objects didn't use a trylock, this pattern would trivially deadlock). This change significantly increases responsiveness of the system while in this state. It makes a real difference because it unblocks kswapd. In the bug report analyzed, kswapd was hung: kswapd0 D ffffffc000204fd8 0 72 2 0x00000000 Call trace: [] __switch_to+0x9c/0xa8 [] __schedule+0x440/0x6d8 [] schedule+0x94/0xb4 [] schedule_preempt_disabled+0x28/0x44 [] __mutex_lock_slowpath+0x120/0x1ac [] mutex_lock+0x4c/0x68 [] dm_bufio_shrink_count+0x38/0x78 [] shrink_slab.part.54.constprop.65+0x100/0x464 [] shrink_zone+0xa8/0x198 [] balance_pgdat+0x328/0x508 [] kswapd+0x424/0x51c [] kthread+0x10c/0x114 [] ret_from_fork+0x10/0x40 By unblocking kswapd memory pressure should be reduced. Suggested-by: David Rientjes Reviewed-by: Guenter Roeck Signed-off-by: Douglas Anderson Signed-off-by: Mike Snitzer Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-bufio.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c index 969c815c90b6..d566c32e222a 100644 --- a/drivers/md/dm-bufio.c +++ b/drivers/md/dm-bufio.c @@ -818,7 +818,8 @@ static struct dm_buffer *__alloc_buffer_wait_no_callback(struct dm_bufio_client * dm-bufio is resistant to allocation failures (it just keeps * one buffer reserved in cases all the allocations fail). * So set flags to not try too hard: - * GFP_NOIO: don't recurse into the I/O layer + * GFP_NOWAIT: don't wait; if we need to sleep we'll release our + * mutex and wait ourselves. * __GFP_NORETRY: don't retry and rather return failure * __GFP_NOMEMALLOC: don't use emergency reserves * __GFP_NOWARN: don't print a warning in case of failure @@ -828,7 +829,7 @@ static struct dm_buffer *__alloc_buffer_wait_no_callback(struct dm_bufio_client */ while (1) { if (dm_bufio_cache_size_latch != 1) { - b = alloc_buffer(c, GFP_NOIO | __GFP_NORETRY | __GFP_NOMEMALLOC | __GFP_NOWARN); + b = alloc_buffer(c, GFP_NOWAIT | __GFP_NORETRY | __GFP_NOMEMALLOC | __GFP_NOWARN); if (b) return b; } From 3ce44cad02d3987d71ee69eed1e3b9e59559417c Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Wed, 23 Nov 2016 17:04:00 -0500 Subject: [PATCH 045/159] dm bufio: drop the lock when doing GFP_NOIO allocation commit 41c73a49df31151f4ff868f28fe4f129f113fa2c upstream. If the first allocation attempt using GFP_NOWAIT fails, drop the lock and retry using GFP_NOIO allocation (lock is dropped because the allocation can take some time). Note that we won't do GFP_NOIO allocation when we loop for the second time, because the lock shouldn't be dropped between __wait_for_free_buffer and __get_unclaimed_buffer. Signed-off-by: Mikulas Patocka Signed-off-by: Mike Snitzer Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-bufio.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c index d566c32e222a..767b5c049736 100644 --- a/drivers/md/dm-bufio.c +++ b/drivers/md/dm-bufio.c @@ -813,6 +813,7 @@ enum new_flag { static struct dm_buffer *__alloc_buffer_wait_no_callback(struct dm_bufio_client *c, enum new_flag nf) { struct dm_buffer *b; + bool tried_noio_alloc = false; /* * dm-bufio is resistant to allocation failures (it just keeps @@ -837,6 +838,15 @@ static struct dm_buffer *__alloc_buffer_wait_no_callback(struct dm_bufio_client if (nf == NF_PREFETCH) return NULL; + if (dm_bufio_cache_size_latch != 1 && !tried_noio_alloc) { + dm_bufio_unlock(c); + b = alloc_buffer(c, GFP_NOIO | __GFP_NORETRY | __GFP_NOMEMALLOC | __GFP_NOWARN); + dm_bufio_lock(c); + if (b) + return b; + tried_noio_alloc = true; + } + if (!list_empty(&c->reserved_buffers)) { b = list_entry(c->reserved_buffers.next, struct dm_buffer, lru_list); From bf4e6336ccbc57bb8898c6fadd904139dd9bd927 Mon Sep 17 00:00:00 2001 From: Martin Kaiser Date: Mon, 18 Jun 2018 22:41:03 +0200 Subject: [PATCH 046/159] mtd: rawnand: mxc: set spare area size register explicitly commit 3f77f244d8ec28e3a0a81240ffac7d626390060c upstream. The v21 version of the NAND flash controller contains a Spare Area Size Register (SPAS) at offset 0x10. Its setting defaults to the maximum spare area size of 218 bytes. The size that is set in this register is used by the controller when it calculates the ECC bytes internally in hardware. Usually, this register is updated from settings in the IIM fuses when the system is booting from NAND flash. For other boot media, however, the SPAS register remains at the default setting, which may not work for the particular flash chip on the board. The same goes for flash chips whose configuration cannot be set in the IIM fuses (e.g. chips with 2k sector size and 128 bytes spare area size can't be configured in the IIM fuses on imx25 systems). Set the SPAS register explicitly during the preset operation. Derive the register value from mtd->oobsize that was detected during probe by decoding the flash chip's ID bytes. While at it, rename the define for the spare area register's offset to NFC_V21_RSLTSPARE_AREA. The register at offset 0x10 on v1 controllers is different from the register on v21 controllers. Fixes: d484018 ("mtd: mxc_nand: set NFC registers after reset") Cc: stable@vger.kernel.org Signed-off-by: Martin Kaiser Reviewed-by: Sascha Hauer Reviewed-by: Miquel Raynal Signed-off-by: Boris Brezillon Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/nand/mxc_nand.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 136e73a3e07e..53fe795fd716 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -49,7 +49,7 @@ #define NFC_V1_V2_CONFIG (host->regs + 0x0a) #define NFC_V1_V2_ECC_STATUS_RESULT (host->regs + 0x0c) #define NFC_V1_V2_RSLTMAIN_AREA (host->regs + 0x0e) -#define NFC_V1_V2_RSLTSPARE_AREA (host->regs + 0x10) +#define NFC_V21_RSLTSPARE_AREA (host->regs + 0x10) #define NFC_V1_V2_WRPROT (host->regs + 0x12) #define NFC_V1_UNLOCKSTART_BLKADDR (host->regs + 0x14) #define NFC_V1_UNLOCKEND_BLKADDR (host->regs + 0x16) @@ -1034,6 +1034,9 @@ static void preset_v2(struct mtd_info *mtd) writew(config1, NFC_V1_V2_CONFIG1); /* preset operation */ + /* spare area size in 16-bit half-words */ + writew(mtd->oobsize / 2, NFC_V21_RSLTSPARE_AREA); + /* Unlock the internal RAM Buffer */ writew(0x2, NFC_V1_V2_CONFIG); From 5be6e45d184c8a9dfa35626092b7a71e42ef5ee2 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Wed, 23 Nov 2016 16:52:01 -0500 Subject: [PATCH 047/159] dm bufio: don't take the lock in dm_bufio_shrink_count commit d12067f428c037b4575aaeb2be00847fc214c24a upstream. dm_bufio_shrink_count() is called from do_shrink_slab to find out how many freeable objects are there. The reported value doesn't have to be precise, so we don't need to take the dm-bufio lock. Suggested-by: David Rientjes Signed-off-by: Mikulas Patocka Signed-off-by: Mike Snitzer Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-bufio.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c index 767b5c049736..b1d5fa0bc8f7 100644 --- a/drivers/md/dm-bufio.c +++ b/drivers/md/dm-bufio.c @@ -1574,19 +1574,11 @@ dm_bufio_shrink_scan(struct shrinker *shrink, struct shrink_control *sc) static unsigned long dm_bufio_shrink_count(struct shrinker *shrink, struct shrink_control *sc) { - struct dm_bufio_client *c; - unsigned long count; - unsigned long retain_target; + struct dm_bufio_client *c = container_of(shrink, struct dm_bufio_client, shrinker); + unsigned long count = READ_ONCE(c->n_buffers[LIST_CLEAN]) + + READ_ONCE(c->n_buffers[LIST_DIRTY]); + unsigned long retain_target = get_retain_buffers(c); - c = container_of(shrink, struct dm_bufio_client, shrinker); - if (sc->gfp_mask & __GFP_FS) - dm_bufio_lock(c); - else if (!dm_bufio_trylock(c)) - return 0; - - count = c->n_buffers[LIST_CLEAN] + c->n_buffers[LIST_DIRTY]; - retain_target = get_retain_buffers(c); - dm_bufio_unlock(c); return (count < retain_target) ? 0 : (count - retain_target); } From 100b8c9452cc763b2ab84ce35526eda802afb1e4 Mon Sep 17 00:00:00 2001 From: Tokunori Ikegami Date: Wed, 30 May 2018 18:32:27 +0900 Subject: [PATCH 048/159] mtd: cfi_cmdset_0002: Change definition naming to retry write operation commit 85a82e28b023de9b259a86824afbd6ba07bd6475 upstream. The definition can be used for other program and erase operations also. So change the naming to MAX_RETRIES from MAX_WORD_RETRIES. Signed-off-by: Tokunori Ikegami Reviewed-by: Joakim Tjernlund Cc: Chris Packham Cc: Brian Norris Cc: David Woodhouse Cc: Boris Brezillon Cc: Marek Vasut Cc: Richard Weinberger Cc: Cyrille Pitchen Cc: linux-mtd@lists.infradead.org Cc: stable@vger.kernel.org Signed-off-by: Boris Brezillon Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/chips/cfi_cmdset_0002.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index c484ca8c909c..1a615ea22990 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -42,7 +42,7 @@ #define AMD_BOOTLOC_BUG #define FORCE_WORD_WRITE 0 -#define MAX_WORD_RETRIES 3 +#define MAX_RETRIES 3 #define SST49LF004B 0x0060 #define SST49LF040B 0x0050 @@ -1645,7 +1645,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, map_write( map, CMD(0xF0), chip->start ); /* FIXME - should have reset delay before continuing */ - if (++retry_cnt <= MAX_WORD_RETRIES) + if (++retry_cnt <= MAX_RETRIES) goto retry; ret = -EIO; @@ -2104,7 +2104,7 @@ retry: map_write(map, CMD(0xF0), chip->start); /* FIXME - should have reset delay before continuing */ - if (++retry_cnt <= MAX_WORD_RETRIES) + if (++retry_cnt <= MAX_RETRIES) goto retry; ret = -EIO; From 2e0a09dcb8e08987fd98c3eb298370762b803e6e Mon Sep 17 00:00:00 2001 From: Tokunori Ikegami Date: Wed, 30 May 2018 18:32:28 +0900 Subject: [PATCH 049/159] mtd: cfi_cmdset_0002: Change erase functions to retry for error commit 45f75b8a919a4255f52df454f1ffdee0e42443b2 upstream. For the word write functions it is retried for error. But it is not implemented to retry for the erase functions. To make sure for the erase functions change to retry as same. This is needed to prevent the flash erase error caused only once. It was caused by the error case of chip_good() in the do_erase_oneblock(). Also it was confirmed on the MACRONIX flash device MX29GL512FHT2I-11G. But the error issue behavior is not able to reproduce at this moment. The flash controller is parallel Flash interface integrated on BCM53003. Signed-off-by: Tokunori Ikegami Reviewed-by: Joakim Tjernlund Cc: Chris Packham Cc: Brian Norris Cc: David Woodhouse Cc: Boris Brezillon Cc: Marek Vasut Cc: Richard Weinberger Cc: Cyrille Pitchen Cc: linux-mtd@lists.infradead.org Cc: stable@vger.kernel.org Signed-off-by: Boris Brezillon Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/chips/cfi_cmdset_0002.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index 1a615ea22990..b99e51f778b4 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -2239,6 +2239,7 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip) unsigned long int adr; DECLARE_WAITQUEUE(wait, current); int ret = 0; + int retry_cnt = 0; adr = cfi->addr_unlock1; @@ -2256,6 +2257,7 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip) ENABLE_VPP(map); xip_disable(map, chip, adr); + retry: cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); @@ -2310,6 +2312,9 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip) map_write( map, CMD(0xF0), chip->start ); /* FIXME - should have reset delay before continuing */ + if (++retry_cnt <= MAX_RETRIES) + goto retry; + ret = -EIO; } @@ -2329,6 +2334,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, unsigned long timeo = jiffies + HZ; DECLARE_WAITQUEUE(wait, current); int ret = 0; + int retry_cnt = 0; adr += chip->start; @@ -2346,6 +2352,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, ENABLE_VPP(map); xip_disable(map, chip, adr); + retry: cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); @@ -2403,6 +2410,9 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, map_write( map, CMD(0xF0), chip->start ); /* FIXME - should have reset delay before continuing */ + if (++retry_cnt <= MAX_RETRIES) + goto retry; + ret = -EIO; } From 242dbd2b3df71a42e3bca5fbb2cf1eda161e078f Mon Sep 17 00:00:00 2001 From: Tokunori Ikegami Date: Wed, 30 May 2018 18:32:29 +0900 Subject: [PATCH 050/159] mtd: cfi_cmdset_0002: Change erase functions to check chip good only commit 79ca484b613041ca223f74b34608bb6f5221724b upstream. Currently the functions use to check both chip ready and good. But the chip ready is not enough to check the operation status. So change this to check the chip good instead of this. About the retry functions to make sure the error handling remain it. Signed-off-by: Tokunori Ikegami Reviewed-by: Joakim Tjernlund Cc: Chris Packham Cc: Brian Norris Cc: David Woodhouse Cc: Boris Brezillon Cc: Marek Vasut Cc: Richard Weinberger Cc: Cyrille Pitchen Cc: linux-mtd@lists.infradead.org Cc: stable@vger.kernel.org Signed-off-by: Boris Brezillon Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/chips/cfi_cmdset_0002.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index b99e51f778b4..fb5a3052f144 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -2294,12 +2294,13 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip) chip->erase_suspended = 0; } - if (chip_ready(map, adr)) + if (chip_good(map, adr, map_word_ff(map))) break; if (time_after(jiffies, timeo)) { printk(KERN_WARNING "MTD %s(): software timeout\n", __func__ ); + ret = -EIO; break; } @@ -2307,15 +2308,15 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip) UDELAY(map, chip, adr, 1000000/HZ); } /* Did we succeed? */ - if (!chip_good(map, adr, map_word_ff(map))) { + if (ret) { /* reset on all failures. */ map_write( map, CMD(0xF0), chip->start ); /* FIXME - should have reset delay before continuing */ - if (++retry_cnt <= MAX_RETRIES) + if (++retry_cnt <= MAX_RETRIES) { + ret = 0; goto retry; - - ret = -EIO; + } } chip->state = FL_READY; @@ -2389,7 +2390,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, chip->erase_suspended = 0; } - if (chip_ready(map, adr)) { + if (chip_good(map, adr, map_word_ff(map))) { xip_enable(map, chip, adr); break; } @@ -2398,6 +2399,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, xip_enable(map, chip, adr); printk(KERN_WARNING "MTD %s(): software timeout\n", __func__ ); + ret = -EIO; break; } @@ -2405,15 +2407,15 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, UDELAY(map, chip, adr, 1000000/HZ); } /* Did we succeed? */ - if (!chip_good(map, adr, map_word_ff(map))) { + if (ret) { /* reset on all failures. */ map_write( map, CMD(0xF0), chip->start ); /* FIXME - should have reset delay before continuing */ - if (++retry_cnt <= MAX_RETRIES) + if (++retry_cnt <= MAX_RETRIES) { + ret = 0; goto retry; - - ret = -EIO; + } } chip->state = FL_READY; From 8cff10da50b2f03819567b2ee342dffd9d0eb9eb Mon Sep 17 00:00:00 2001 From: Jann Horn Date: Mon, 25 Jun 2018 17:22:00 +0200 Subject: [PATCH 051/159] netfilter: nf_log: don't hold nf_log_mutex during user access commit ce00bf07cc95a57cd20b208e02b3c2604e532ae8 upstream. The old code would indefinitely block other users of nf_log_mutex if a userspace access in proc_dostring() blocked e.g. due to a userfaultfd region. Fix it by moving proc_dostring() out of the locked region. This is a followup to commit 266d07cb1c9a ("netfilter: nf_log: fix sleeping function called from invalid context"), which changed this code from using rcu_read_lock() to taking nf_log_mutex. Fixes: 266d07cb1c9a ("netfilter: nf_log: fix sleeping function calle[...]") Signed-off-by: Jann Horn Signed-off-by: Pablo Neira Ayuso Signed-off-by: Greg Kroah-Hartman --- net/netfilter/nf_log.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c index 2c89f90cd7bc..f94a2e1172f0 100644 --- a/net/netfilter/nf_log.c +++ b/net/netfilter/nf_log.c @@ -422,14 +422,17 @@ static int nf_log_proc_dostring(struct ctl_table *table, int write, rcu_assign_pointer(net->nf.nf_loggers[tindex], logger); mutex_unlock(&nf_log_mutex); } else { + struct ctl_table tmp = *table; + + tmp.data = buf; mutex_lock(&nf_log_mutex); logger = nft_log_dereference(net->nf.nf_loggers[tindex]); if (!logger) - table->data = "NONE"; + strlcpy(buf, "NONE", sizeof(buf)); else - table->data = logger->name; - r = proc_dostring(table, write, buffer, lenp, ppos); + strlcpy(buf, logger->name, sizeof(buf)); mutex_unlock(&nf_log_mutex); + r = proc_dostring(&tmp, write, buffer, lenp, ppos); } return r; From fecf1ae3e02705275c6e7fe875dd063576fd0d53 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 5 Jun 2018 12:36:30 +0300 Subject: [PATCH 052/159] staging: comedi: quatech_daqp_cs: fix no-op loop daqp_ao_insn_write() commit 1376b0a2160319125c3a2822e8c09bd283cd8141 upstream. There is a '>' vs '<' typo so this loop is a no-op. Fixes: d35dcc89fc93 ("staging: comedi: quatech_daqp_cs: fix daqp_ao_insn_write()") Signed-off-by: Dan Carpenter Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/quatech_daqp_cs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c index e9e43139157d..769a94015117 100644 --- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c +++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c @@ -642,7 +642,7 @@ static int daqp_ao_insn_write(struct comedi_device *dev, /* Make sure D/A update mode is direct update */ outb(0, dev->iobase + DAQP_AUX_REG); - for (i = 0; i > insn->n; i++) { + for (i = 0; i < insn->n; i++) { unsigned val = data[i]; int ret; From d6bc7e610ab98da569362b0b64bb20dafee1fcb9 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 11 Jul 2018 16:03:52 +0200 Subject: [PATCH 053/159] Linux 4.4.140 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 20a11fd36656..b842298a5970 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 4 PATCHLEVEL = 4 -SUBLEVEL = 139 +SUBLEVEL = 140 EXTRAVERSION = NAME = Blurry Fish Butt From 193f8ec5c681bd6da539926928a1ce97c9978ed1 Mon Sep 17 00:00:00 2001 From: Balachandra C S Date: Thu, 26 Apr 2018 18:10:44 +0530 Subject: [PATCH 054/159] drivers: net: can: ignore the data if command byte is 0xFF Ignore the data from spi if data read happens to be 0xFF. Change-Id: Ib1f28b70ee11e99f73a80166df56132371076f86 Signed-off-by: Balachandra C S --- drivers/net/can/spi/qti-can.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/can/spi/qti-can.c b/drivers/net/can/spi/qti-can.c index 7db6ecf8f354..5934512b6e0e 100644 --- a/drivers/net/can/spi/qti-can.c +++ b/drivers/net/can/spi/qti-can.c @@ -445,8 +445,8 @@ static int qti_can_process_rx(struct qti_can *priv_data, char *rx_buf) } else { data = rx_buf + length_processed; resp = (struct spi_miso *)data; - if (resp->cmd == 0) { - /* special case. ignore cmd==0 */ + if (resp->cmd == 0x00 || resp->cmd == 0xFF) { + /* special case. ignore cmd==0x00, 0xFF */ length_processed += 1; continue; } From 9352586542f5db259c9e37fc3c4f792fbf987afc Mon Sep 17 00:00:00 2001 From: Balachandra C S Date: Mon, 7 May 2018 15:08:42 +0530 Subject: [PATCH 055/159] drivers: net: can: Add END_FW_UPDATE_FILE command to qti-can driver Add IOCTL command to indicate the controller that firmware update file end of file is reached. Change-Id: Ib538ff68a4b974234ce541696d38772e7065b7d8 Signed-off-by: Balachandra C S --- drivers/net/can/spi/qti-can.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/can/spi/qti-can.c b/drivers/net/can/spi/qti-can.c index 5934512b6e0e..71a340badf22 100644 --- a/drivers/net/can/spi/qti-can.c +++ b/drivers/net/can/spi/qti-can.c @@ -118,6 +118,7 @@ struct spi_miso { /* TLV for MISO line */ #define CMD_BEGIN_BOOT_ROM_UPGRADE 0x99 #define CMD_BOOT_ROM_UPGRADE_DATA 0x9A #define CMD_END_BOOT_ROM_UPGRADE 0x9B +#define CMD_END_FW_UPDATE_FILE 0x9C #define IOCTL_RELEASE_CAN_BUFFER (SIOCDEVPRIVATE + 0) #define IOCTL_ENABLE_BUFFERING (SIOCDEVPRIVATE + 1) @@ -132,6 +133,7 @@ struct spi_miso { /* TLV for MISO line */ #define IOCTL_BEGIN_BOOT_ROM_UPGRADE (SIOCDEVPRIVATE + 11) #define IOCTL_BOOT_ROM_UPGRADE_DATA (SIOCDEVPRIVATE + 12) #define IOCTL_END_BOOT_ROM_UPGRADE (SIOCDEVPRIVATE + 13) +#define IOCTL_END_FW_UPDATE_FILE (SIOCDEVPRIVATE + 14) #define IFR_DATA_OFFSET 0x100 struct can_fw_resp { @@ -983,6 +985,8 @@ static int qti_can_convert_ioctl_cmd_to_spi_cmd(int ioctl_cmd) return CMD_BOOT_ROM_UPGRADE_DATA; case IOCTL_END_BOOT_ROM_UPGRADE: return CMD_END_BOOT_ROM_UPGRADE; + case IOCTL_END_FW_UPDATE_FILE: + return CMD_END_FW_UPDATE_FILE; } return -EINVAL; } @@ -1119,6 +1123,7 @@ static int qti_can_netdev_do_ioctl(struct net_device *netdev, case IOCTL_BEGIN_BOOT_ROM_UPGRADE: case IOCTL_BOOT_ROM_UPGRADE_DATA: case IOCTL_END_BOOT_ROM_UPGRADE: + case IOCTL_END_FW_UPDATE_FILE: ret = qti_can_do_blocking_ioctl(netdev, ifr, cmd); break; } From ac83e7e52febf872d25a687cda32ea6d8d5d73cb Mon Sep 17 00:00:00 2001 From: Balachandra C S Date: Wed, 4 Jul 2018 16:26:53 +0530 Subject: [PATCH 056/159] drivers: net: can: Use proper device property in qti-can driver Use the proper device tree property in qti-can driver for enabling can-fd feature. Change-Id: I4c59e7037a8e0f4972603aceb65138a190080074 Signed-off-by: Balachandra C S --- drivers/net/can/spi/qti-can.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/can/spi/qti-can.c b/drivers/net/can/spi/qti-can.c index 71a340badf22..58dac2c62307 100644 --- a/drivers/net/can/spi/qti-can.c +++ b/drivers/net/can/spi/qti-can.c @@ -1323,7 +1323,7 @@ static int qti_can_probe(struct spi_device *spi) } priv_data->support_can_fd = of_property_read_bool(spi->dev.of_node, - "support-can-fd"); + "qcom,support-can-fd"); if (of_device_is_compatible(spi->dev.of_node, "qcom,nxp,mpc5746c")) qti_can_bittiming_const = flexcan_bittiming_const; From 6a1dd530efe846d3ffabfe7bc65506377e52e226 Mon Sep 17 00:00:00 2001 From: Balachandra C S Date: Sun, 8 Jul 2018 22:40:20 +0530 Subject: [PATCH 057/159] drivers: net: can: Use interrupt type from device tree Use proper interrupt type from the device tree for gpio interrupt from CAN controller in qti-can driver as irq type may vary with different targets. Change-Id: If08c3f6d53fc6e8b7a55be47705c5a1841c0c913 Signed-off-by: Balachandra C S --- drivers/net/can/spi/qti-can.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/can/spi/qti-can.c b/drivers/net/can/spi/qti-can.c index 58dac2c62307..27294c74fcd6 100644 --- a/drivers/net/can/spi/qti-can.c +++ b/drivers/net/can/spi/qti-can.c @@ -1247,6 +1247,7 @@ static int qti_can_probe(struct spi_device *spi) int err, retry = 0, query_err = -1, i; struct qti_can *priv_data = NULL; struct device *dev; + u32 irq_type; dev = &spi->dev; dev_info(dev, "qti_can_probe"); @@ -1353,8 +1354,11 @@ static int qti_can_probe(struct spi_device *spi) } } + irq_type = irq_get_trigger_type(spi->irq); + if (irq_type == IRQ_TYPE_NONE) + irq_type = IRQ_TYPE_EDGE_FALLING; err = request_threaded_irq(spi->irq, NULL, qti_can_irq, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + irq_type | IRQF_ONESHOT, "qti-can", priv_data); if (err) { LOGDE("Failed to request irq: %d", err); From ed9bdc8a8fc520059510c1fd2b5ee8f4390be7cc Mon Sep 17 00:00:00 2001 From: Artem Borisov Date: Fri, 13 Jul 2018 14:28:33 +0300 Subject: [PATCH 058/159] cpufreq: Kconfig: Remove CPU_FREQ_DEFAULT_GOV_SCHED Sched governor was removed in df147c9e336cfcb4183db1eb9552b0429060cd0d and this probably was left here by mistake. Remove it to avoid confusion. Signed-off-by: Artem Borisov --- drivers/cpufreq/Kconfig | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index ac1bb26fb158..75ded53a7470 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig @@ -121,14 +121,6 @@ config CPU_FREQ_DEFAULT_GOV_INTERACTIVE loading your cpufreq low-level hardware driver, using the 'interactive' governor for latency-sensitive workloads. -config CPU_FREQ_DEFAULT_GOV_SCHED - bool "sched" - select CPU_FREQ_GOV_SCHED - help - Use the CPUfreq governor 'sched' as default. This scales - cpu frequency using CPU utilization estimates from the - scheduler. - config CPU_FREQ_DEFAULT_GOV_SCHEDUTIL bool "schedutil" depends on SMP From cb60bccda131cb5013e388bc639d2cbdec03e344 Mon Sep 17 00:00:00 2001 From: Lakshmi Narayana Kalavala Date: Fri, 11 May 2018 11:28:12 -0700 Subject: [PATCH 059/159] drm/msm: Fix the format prints in display driver Fix the %p format prints with %pK. Change-Id: I1743bacb76c1db4bfa304146f7d391751b35273c Signed-off-by: Lakshmi Narayana Kalavala Signed-off-by: Navid Bahrani --- drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c | 2 +- drivers/gpu/drm/msm/dsi-staging/dsi_phy.c | 3 ++- drivers/gpu/drm/msm/edp/edp.c | 4 ++-- drivers/gpu/drm/msm/msm_drv.c | 11 ++++++----- drivers/gpu/drm/msm/msm_fb.c | 7 ++++--- drivers/gpu/drm/msm/msm_fbdev.c | 4 ++-- drivers/gpu/drm/msm/msm_gem.c | 4 ++-- drivers/gpu/drm/msm/sde/sde_crtc.c | 2 +- .../gpu/drm/msm/sde/sde_hw_color_processing_v1_7.c | 2 +- drivers/gpu/drm/msm/sde/sde_kms.c | 2 +- 10 files changed, 22 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c index b1cd666f8be4..252a6289881f 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c @@ -484,7 +484,7 @@ static int dsi_ctrl_init_regmap(struct platform_device *pdev, } ctrl->hw.base = ptr; - pr_debug("[%s] map dsi_ctrl registers to %p\n", ctrl->name, + pr_debug("[%s] map dsi_ctrl registers to %pK\n", ctrl->name, ctrl->hw.base); ptr = msm_ioremap(pdev, "mmss_misc", ctrl->name); diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c b/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c index da3b3b548e5f..5bcd0d0634b6 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c @@ -93,7 +93,8 @@ static int dsi_phy_regmap_init(struct platform_device *pdev, phy->hw.base = ptr; - pr_debug("[%s] map dsi_phy registers to %p\n", phy->name, phy->hw.base); + pr_debug("[%s] map dsi_phy registers to %pK\n", + phy->name, phy->hw.base); return rc; } diff --git a/drivers/gpu/drm/msm/edp/edp.c b/drivers/gpu/drm/msm/edp/edp.c index 0940e84b2821..2c9d11638f29 100644 --- a/drivers/gpu/drm/msm/edp/edp.c +++ b/drivers/gpu/drm/msm/edp/edp.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2015,2018 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -54,7 +54,7 @@ static struct msm_edp *edp_init(struct platform_device *pdev) ret = -ENOMEM; goto fail; } - DBG("eDP probed=%p", edp); + DBG("eDP probed=%pK", edp); edp->pdev = pdev; platform_set_drvdata(pdev, edp); diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index b57663013dcb..f1bd9967ba81 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -145,7 +145,8 @@ void __iomem *msm_ioremap(struct platform_device *pdev, const char *name, } if (reglog) - printk(KERN_DEBUG "IO:region %s %p %08lx\n", dbgname, ptr, size); + dev_dbg(&pdev->dev, "IO:region %s %pK %08lx\n", + dbgname, ptr, size); return ptr; } @@ -158,7 +159,7 @@ void msm_iounmap(struct platform_device *pdev, void __iomem *addr) void msm_writel(u32 data, void __iomem *addr) { if (reglog) - printk(KERN_DEBUG "IO:W %p %08x\n", addr, data); + pr_debug("IO:W %pK %08x\n", addr, data); writel(data, addr); } @@ -166,7 +167,7 @@ u32 msm_readl(const void __iomem *addr) { u32 val = readl(addr); if (reglog) - printk(KERN_ERR "IO:R %p %08x\n", addr, val); + pr_err("IO:R %pK %08x\n", addr, val); return val; } @@ -895,7 +896,7 @@ static int msm_enable_vblank(struct drm_device *dev, unsigned int pipe) struct msm_kms *kms = priv->kms; if (!kms) return -ENXIO; - DBG("dev=%p, crtc=%u", dev, pipe); + DBG("dev=%pK, crtc=%u", dev, pipe); return vblank_ctrl_queue_work(priv, pipe, true); } @@ -905,7 +906,7 @@ static void msm_disable_vblank(struct drm_device *dev, unsigned int pipe) struct msm_kms *kms = priv->kms; if (!kms) return; - DBG("dev=%p, crtc=%u", dev, pipe); + DBG("dev=%pK, crtc=%u", dev, pipe); vblank_ctrl_queue_work(priv, pipe, false); } diff --git a/drivers/gpu/drm/msm/msm_fb.c b/drivers/gpu/drm/msm/msm_fb.c index d222fdd69a57..8d6d83bf6540 100644 --- a/drivers/gpu/drm/msm/msm_fb.c +++ b/drivers/gpu/drm/msm/msm_fb.c @@ -1,4 +1,5 @@ /* + * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark * @@ -59,7 +60,7 @@ static void msm_framebuffer_destroy(struct drm_framebuffer *fb) msm_fb = to_msm_framebuffer(fb); n = drm_format_num_planes(fb->pixel_format); - DBG("destroy: FB ID: %d (%p)", fb->base.id, fb); + DBG("destroy: FB ID: %d (%pK)", fb->base.id, fb); drm_framebuffer_cleanup(fb); @@ -239,7 +240,7 @@ struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev, unsigned int hsub, vsub; bool is_modified = false; - DBG("create framebuffer: dev=%p, mode_cmd=%p (%dx%d@%4.4s)", + DBG("create framebuffer: dev=%pK, mode_cmd=%pK (%dx%d@%4.4s)", dev, mode_cmd, mode_cmd->width, mode_cmd->height, (char *)&mode_cmd->pixel_format); @@ -322,7 +323,7 @@ struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev, goto fail; } - DBG("create: FB ID: %d (%p)", fb->base.id, fb); + DBG("create: FB ID: %d (%pK)", fb->base.id, fb); return fb; diff --git a/drivers/gpu/drm/msm/msm_fbdev.c b/drivers/gpu/drm/msm/msm_fbdev.c index 28b98cc1433c..c71e662d0da1 100644 --- a/drivers/gpu/drm/msm/msm_fbdev.c +++ b/drivers/gpu/drm/msm/msm_fbdev.c @@ -144,7 +144,7 @@ static int msm_fbdev_create(struct drm_fb_helper *helper, goto fail_unlock; } - DBG("fbi=%p, dev=%p", fbi, dev); + DBG("fbi=%pK, dev=%pK", fbi, dev); fbdev->fb = fb; helper->fb = fb; @@ -166,7 +166,7 @@ static int msm_fbdev_create(struct drm_fb_helper *helper, fbi->fix.smem_start = lower_32_bits(paddr); fbi->fix.smem_len = fbdev->bo->size; - DBG("par=%p, %dx%d", fbi->par, fbi->var.xres, fbi->var.yres); + DBG("par=%pK, %dx%d", fbi->par, fbi->var.xres, fbi->var.yres); DBG("allocated %dx%d fb", fbdev->fb->width, fbdev->fb->height); mutex_unlock(&dev->struct_mutex); diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index 3610c8fca5f3..ce5adef21a00 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -410,7 +410,7 @@ int msm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) pfn = page_to_pfn(pages[pgoff]); - VERB("Inserting %p pfn %lx, pa %lx", vmf->virtual_address, + VERB("Inserting %pK pfn %lx, pa %lx", vmf->virtual_address, pfn, pfn << PAGE_SHIFT); ret = vm_insert_mixed(vma, (unsigned long)vmf->virtual_address, pfn); @@ -770,7 +770,7 @@ void msm_gem_describe(struct drm_gem_object *obj, struct seq_file *m) uint64_t off = drm_vma_node_start(&obj->vma_node); WARN_ON(!mutex_is_locked(&dev->struct_mutex)); - seq_printf(m, "%08x: %c(r=%u,w=%u) %2d (%2d) %08llx %p\t", + seq_printf(m, "%08x: %c(r=%u,w=%u) %2d (%2d) %08llx %pK\t", msm_obj->flags, is_active(msm_obj) ? 'A' : 'I', msm_obj->read_fence, msm_obj->write_fence, obj->name, obj->refcount.refcount.counter, diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c index 6ad1ce16c20a..01da32ae5958 100644 --- a/drivers/gpu/drm/msm/sde/sde_crtc.c +++ b/drivers/gpu/drm/msm/sde/sde_crtc.c @@ -1563,7 +1563,7 @@ void sde_crtc_cancel_pending_flip(struct drm_crtc *crtc, { struct sde_crtc *sde_crtc = to_sde_crtc(crtc); - SDE_DEBUG("%s: cancel: %p\n", sde_crtc->name, file); + SDE_DEBUG("%s: cancel: %pK\n", sde_crtc->name, file); _sde_crtc_complete_flip(crtc, file); } diff --git a/drivers/gpu/drm/msm/sde/sde_hw_color_processing_v1_7.c b/drivers/gpu/drm/msm/sde/sde_hw_color_processing_v1_7.c index 6a8d9e0cf2e3..76d99c1e8e65 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_color_processing_v1_7.c +++ b/drivers/gpu/drm/msm/sde/sde_hw_color_processing_v1_7.c @@ -367,7 +367,7 @@ void sde_setup_dspp_pcc_v1_7(struct sde_hw_dspp *ctx, void *cfg) void __iomem *base; if (!hw_cfg || (hw_cfg->len != sizeof(*pcc) && hw_cfg->payload)) { - DRM_ERROR("invalid params hw %p payload %p payloadsize %d \"\ + DRM_ERROR("invalid params hw %pK payload %pK payloadsize %d \"\ exp size %zd\n", hw_cfg, ((hw_cfg) ? hw_cfg->payload : NULL), ((hw_cfg) ? hw_cfg->len : 0), sizeof(*pcc)); diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c index 95ab14ffc3ac..a48dc25740f7 100644 --- a/drivers/gpu/drm/msm/sde/sde_kms.c +++ b/drivers/gpu/drm/msm/sde/sde_kms.c @@ -1283,7 +1283,7 @@ static int sde_kms_hw_init(struct msm_kms *kms) SDE_ERROR("mdp register memory map failed\n"); goto error; } - DRM_INFO("mapped mdp address space @%p\n", sde_kms->mmio); + DRM_INFO("mapped mdp address space @%pK\n", sde_kms->mmio); rc = sde_dbg_reg_register_base(SDE_DBG_NAME, sde_kms->mmio, sde_kms->mmio_len); From 225c6e1feeda95ebf2c54e9324a64494c3bc2c2d Mon Sep 17 00:00:00 2001 From: Suprith Malligere Shankaregowda Date: Thu, 5 Jul 2018 17:24:45 +0530 Subject: [PATCH 060/159] drm: msm: add skip_ddc support for hdmi display HDMI display on auto boards has disabled pluggable function and hardcoded 1080p mode for output. So ddc related function should also be skipped. Otherwise, some error messages are printed when accessing ddc. Change-Id: I42694b0586dd870e7881b422cd3d6ee960276b17 Signed-off-by: Suprith Malligere Shankaregowda Signed-off-by: Guchun Chen --- .../devicetree/bindings/drm/msm/hdmi-display.txt | 1 + drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c | 7 +++++++ drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h | 1 + drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_bridge.c | 9 ++++++--- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/drm/msm/hdmi-display.txt b/Documentation/devicetree/bindings/drm/msm/hdmi-display.txt index 9329fb74dea0..762103277593 100644 --- a/Documentation/devicetree/bindings/drm/msm/hdmi-display.txt +++ b/Documentation/devicetree/bindings/drm/msm/hdmi-display.txt @@ -8,6 +8,7 @@ Optional properties: - qcom,display-type: display type of this manager. It could be "primary", "secondary", "tertiary", etc. - qcom,non-pluggable: Boolean to indicate if display is non pluggable. +- qcom,skip_ddc: Boolean to indicate if display skips ddc function. - qcom,customize-modes: Customized modes when it's non pluggable display. - qcom,customize-mode-id: Customized mode node. - qcom,mode-name: String which indicates the mode name which shall be used diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c index 46cc521a09f3..302ed39d9218 100644 --- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c +++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c @@ -3069,6 +3069,8 @@ static int _sde_hdmi_parse_dt(struct device_node *node, { int rc = 0; + struct hdmi *hdmi = display->ctrl.ctrl; + display->name = of_get_property(node, "label", NULL); display->display_type = of_get_property(node, @@ -3079,6 +3081,11 @@ static int _sde_hdmi_parse_dt(struct device_node *node, display->non_pluggable = of_property_read_bool(node, "qcom,non-pluggable"); + display->skip_ddc = of_property_read_bool(node, + "qcom,skip_ddc"); + if (!display->non_pluggable) + hdmi_i2c_destroy(hdmi->i2c); + rc = _sde_hdmi_parse_dt_modes(node, &display->mode_list, &display->num_of_modes); if (rc) diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h index 9cf807e829c7..2aa8d9496c5b 100644 --- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h +++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h @@ -154,6 +154,7 @@ struct sde_hdmi { struct sde_edid_ctrl *edid_ctrl; bool non_pluggable; + bool skip_ddc; u32 num_of_modes; struct list_head mode_list; struct drm_display_mode mode; diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_bridge.c index bae6b1c84420..2d65fc924f07 100644 --- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_bridge.c +++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_bridge.c @@ -512,8 +512,8 @@ static void _sde_hdmi_bridge_pre_enable(struct drm_bridge *bridge) } hdmi->power_on = true; } - - _sde_hdmi_bridge_setup_scrambler(hdmi, &display->mode); + if (!display->skip_ddc) + _sde_hdmi_bridge_setup_scrambler(hdmi, &display->mode); if (phy) phy->funcs->powerup(phy, hdmi->pixclock); @@ -822,6 +822,8 @@ static u32 _sde_hdmi_choose_best_format(struct hdmi *hdmi, */ int dc_format; struct drm_connector *connector = hdmi->connector; + struct sde_connector *c_conn = to_sde_connector(connector); + struct sde_hdmi *display = (struct sde_hdmi *)c_conn->display; dc_format = sde_hdmi_sink_dc_support(connector, mode); if (dc_format & MSM_MODE_FLAG_RGB444_DC_ENABLE) @@ -835,7 +837,8 @@ static u32 _sde_hdmi_choose_best_format(struct hdmi *hdmi, else if (mode->flags & DRM_MODE_FLAG_SUPPORTS_YUV) return MSM_MODE_FLAG_COLOR_FORMAT_YCBCR420; - SDE_ERROR("Can't get available best display format\n"); + if (display && !display->non_pluggable) + SDE_ERROR("Can't get available best display format\n"); return MSM_MODE_FLAG_COLOR_FORMAT_RGB444; } From 6df01b61792a9436d09db64b92849a4383f5321e Mon Sep 17 00:00:00 2001 From: Suprith Malligere Shankaregowda Date: Thu, 5 Jul 2018 18:22:10 +0530 Subject: [PATCH 061/159] ARM: dts: msm: add ddc_skip on auto 8996 boards This change is done to disable the hdmi scrambler related display kernel error messages in the boot logs. Change-Id: I7f9284c3d64e291ef9c6442e7e89f6551cbce8d6 Signed-off-by: Suprith Malligere Shankaregowda --- arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi | 1 + arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi b/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi index 6fe55d14a3c6..4842d3b205e6 100644 --- a/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi @@ -610,6 +610,7 @@ &sde_hdmi { qcom,non-pluggable; + qcom,skip_ddc; qcom,customize-modes { qcom,customize-mode-id@0 { qcom,mode-name = "1920x1080@60Hz"; diff --git a/arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi b/arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi index 848a647e0172..86e9dd72dcad 100644 --- a/arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi @@ -396,6 +396,7 @@ &sde_hdmi { qcom,non-pluggable; + qcom,skip_ddc; qcom,customize-modes { qcom,customize-mode-id@0 { qcom,mode-name = "1920x1080@60Hz"; From bbff7311e9d4cefdc85dd4f3a588d1129466e41e Mon Sep 17 00:00:00 2001 From: Mohammed Javid Date: Fri, 29 Jun 2018 15:06:00 +0530 Subject: [PATCH 062/159] msm: ipa: Error prints are misleading fix it IPC logging is for debugging purpose and it may disabled in kernel anytime. From IPA driver printing the error log on IPC create context is misleading. Instead of error, make it as debug. Change-Id: Icee2b1ad9fcef446f79dfc71f554a24a90ea3d2d Signed-off-by: Mohammed Javid --- drivers/platform/msm/ipa/ipa_v2/ipa.c | 4 ++-- drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c | 2 +- drivers/platform/msm/ipa/ipa_v3/ipa.c | 4 ++-- drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa.c b/drivers/platform/msm/ipa/ipa_v2/ipa.c index b510bbd7d6c7..ad7d2d6175bd 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -3883,7 +3883,7 @@ static int ipa_init(const struct ipa_plat_drv_res *resource_p, ipa_ctx->logbuf = ipc_log_context_create(IPA_IPC_LOG_PAGES, "ipa", 0); if (ipa_ctx->logbuf == NULL) - IPAERR("failed to create IPC log, continue...\n"); + IPADBG("failed to create IPC log, continue...\n"); ipa_ctx->pdev = ipa_dev; ipa_ctx->uc_pdev = ipa_dev; diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c index 1a704ffab07a..e17526e46323 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c @@ -1901,7 +1901,7 @@ static ssize_t ipa_enable_ipc_low(struct file *file, ipc_log_context_create(IPA_IPC_LOG_PAGES, "ipa_low", 0); if (ipa_ipc_low_buff == NULL) - IPAERR("failed to get logbuf_low\n"); + IPADBG("failed to get logbuf_low\n"); } ipa_ctx->logbuf_low = ipa_ipc_low_buff; } else { diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c index a869b6419e5e..681b2d945945 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -4549,7 +4549,7 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p, ipa3_ctx->logbuf = ipc_log_context_create(IPA_IPC_LOG_PAGES, "ipa", 0); if (ipa3_ctx->logbuf == NULL) - IPAERR("failed to create IPC log, continue...\n"); + IPADBG("failed to create IPC log, continue...\n"); ipa3_ctx->pdev = ipa_dev; ipa3_ctx->uc_pdev = ipa_dev; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c index eb9a6877c39f..0dd5b8165ac1 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c @@ -1872,7 +1872,7 @@ static ssize_t ipa3_enable_ipc_low(struct file *file, "ipa_low", 0); } if (ipa_ipc_low_buff == NULL) - IPAERR("failed to get logbuf_low\n"); + IPADBG("failed to get logbuf_low\n"); ipa3_ctx->logbuf_low = ipa_ipc_low_buff; } else { ipa3_ctx->logbuf_low = NULL; From 70a7fe177dbf7ff4755e1de14cfc06f5f067b20e Mon Sep 17 00:00:00 2001 From: Gustavo Solaira Date: Mon, 9 Jul 2018 19:03:00 -0700 Subject: [PATCH 063/159] diag: Disable the code for diag_smux Disable the diag_smux code to fix the build with diagfwd USB enabled since the dependencies for diag_smux are not available it is deprecated in this kernel version. Change-Id: I6a8bc3a34f67ed5b1ca175cad0b3067e2c2df199 Signed-off-by: Gustavo Solaira --- drivers/char/diag/Makefile | 1 - drivers/char/diag/diag_debugfs.c | 3 +-- drivers/char/diag/diagfwd_bridge.c | 12 +----------- 3 files changed, 2 insertions(+), 14 deletions(-) diff --git a/drivers/char/diag/Makefile b/drivers/char/diag/Makefile index c5ec4f081c55..d57ebd8d671e 100644 --- a/drivers/char/diag/Makefile +++ b/drivers/char/diag/Makefile @@ -1,6 +1,5 @@ obj-$(CONFIG_DIAG_CHAR) := diagchar.o obj-$(CONFIG_DIAGFWD_BRIDGE_CODE) += diagfwd_bridge.o obj-$(CONFIG_USB_QCOM_DIAG_BRIDGE) += diagfwd_hsic.o -obj-$(CONFIG_USB_QCOM_DIAG_BRIDGE) += diagfwd_smux.o obj-$(CONFIG_MSM_MHI) += diagfwd_mhi.o diagchar-objs := diagchar_core.o diagchar_hdlc.o diagfwd.o diagfwd_glink.o diagfwd_peripheral.o diagfwd_smd.o diagfwd_socket.o diag_mux.o diag_memorydevice.o diag_usb.o diagmem.o diagfwd_cntl.o diag_dci.o diag_masks.o diag_debugfs.o diff --git a/drivers/char/diag/diag_debugfs.c b/drivers/char/diag/diag_debugfs.c index 5e455878ac3e..ad370ada335f 100644 --- a/drivers/char/diag/diag_debugfs.c +++ b/drivers/char/diag/diag_debugfs.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -23,7 +23,6 @@ #endif #ifdef CONFIG_USB_QCOM_DIAG_BRIDGE #include "diagfwd_hsic.h" -#include "diagfwd_smux.h" #endif #ifdef CONFIG_MSM_MHI #include "diagfwd_mhi.h" diff --git a/drivers/char/diag/diagfwd_bridge.c b/drivers/char/diag/diagfwd_bridge.c index 3342984eb795..d8e7b39eae8b 100644 --- a/drivers/char/diag/diagfwd_bridge.c +++ b/drivers/char/diag/diagfwd_bridge.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -18,14 +18,10 @@ #include #include #include -#ifdef USB_QCOM_DIAG_BRIDGE -#include -#endif #include "diag_mux.h" #include "diagfwd_bridge.h" #ifdef USB_QCOM_DIAG_BRIDGE #include "diagfwd_hsic.h" -#include "diagfwd_smux.h" #endif #include "diagfwd_mhi.h" #include "diag_dci.h" @@ -272,11 +268,6 @@ int diagfwd_bridge_init() err = diag_mdm_init(); if (err) goto fail; - #ifdef USB_QCOM_DIAG_BRIDGE - err = diag_smux_init(); - if (err) - goto fail; - #endif return 0; fail: @@ -288,7 +279,6 @@ void diagfwd_bridge_exit() { #ifdef USB_QCOM_DIAG_BRIDGE diag_hsic_exit(); - diag_smux_exit(); #endif } From d6edcd0fafd854a2adc331fe7f3d05c77a916968 Mon Sep 17 00:00:00 2001 From: Ajay Agarwal Date: Fri, 22 Jun 2018 10:27:06 +0530 Subject: [PATCH 064/159] defconfig: msm-auto: Enable diag_ipc_bridge driver for msm8996 Enable DIAG and IPC bridge driver on msm8996 auto to support interfacing with DIAG and QMI interfaces. Change-Id: I8b32bdfc6aa29c090b21512e202c2822b9752a48 Signed-off-by: Ajay Agarwal --- arch/arm64/configs/msm-auto-perf_defconfig | 1 + arch/arm64/configs/msm-auto_defconfig | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm64/configs/msm-auto-perf_defconfig b/arch/arm64/configs/msm-auto-perf_defconfig index acf8acd6375c..81e18d05b0d0 100644 --- a/arch/arm64/configs/msm-auto-perf_defconfig +++ b/arch/arm64/configs/msm-auto-perf_defconfig @@ -428,6 +428,7 @@ CONFIG_USB_DWC3=y CONFIG_USB_ISP1760=y CONFIG_USB_EHSET_TEST_FIXTURE=y CONFIG_USB_QTI_KS_BRIDGE=y +CONFIG_USB_QCOM_DIAG_BRIDGE=y CONFIG_NOP_USB_XCEIV=y CONFIG_USB_MSM_SSPHY_QMP=y CONFIG_MSM_QUSB_PHY=y diff --git a/arch/arm64/configs/msm-auto_defconfig b/arch/arm64/configs/msm-auto_defconfig index 15b059a621ac..cc1000edbef0 100644 --- a/arch/arm64/configs/msm-auto_defconfig +++ b/arch/arm64/configs/msm-auto_defconfig @@ -432,6 +432,7 @@ CONFIG_USB_DWC3=y CONFIG_USB_ISP1760=y CONFIG_USB_EHSET_TEST_FIXTURE=y CONFIG_USB_QTI_KS_BRIDGE=y +CONFIG_USB_QCOM_DIAG_BRIDGE=y CONFIG_NOP_USB_XCEIV=y CONFIG_USB_MSM_SSPHY_QMP=y CONFIG_MSM_QUSB_PHY=y From 2bd670287772ce6ccd6f154b299e332d6c09df7b Mon Sep 17 00:00:00 2001 From: Gustavo Solaira Date: Mon, 9 Jul 2018 19:06:49 -0700 Subject: [PATCH 065/159] usb: misc: diag_ipc_bridge: Add support for 901D PID Add support for creation of diag traffic channel in case the connected device has 0x05C6 VID and 0x901D PID. 0x901D : DIAG + ADB Change-Id: I6df0aca714f10ea7d854f621e19da1388a7e7d5c Signed-off-by: Gustavo Solaira --- drivers/usb/misc/diag_ipc_bridge.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/misc/diag_ipc_bridge.c b/drivers/usb/misc/diag_ipc_bridge.c index b9ced8d0062d..a652c8f9bab7 100644 --- a/drivers/usb/misc/diag_ipc_bridge.c +++ b/drivers/usb/misc/diag_ipc_bridge.c @@ -730,6 +730,8 @@ static int diag_bridge_resume(struct usb_interface *ifc) static const struct usb_device_id diag_bridge_ids[] = { { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x9001, 0), .driver_info = DEV_ID(0), }, + { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x901D, 0), + .driver_info = DEV_ID(0), }, { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x9034, 0), .driver_info = DEV_ID(0), }, { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x9048, 0), From 146820788aab993081e6dd902d51987e1cf8c855 Mon Sep 17 00:00:00 2001 From: Gustavo Solaira Date: Mon, 9 Jul 2018 19:21:00 -0700 Subject: [PATCH 066/159] diag: Enable diagfwd via USB even when MHI is available Some devices need diag via USB even when MHI is used for rmnet and qmi tethering. This is because of lack of support for diagfwd for mhi_dev in Linux. Change-Id: Ie0ec19ee109d49aa409d1df3ad5ca24b75de7102 Signed-off-by: Gustavo Solaira --- .../bindings/arm/msm/diagfwd_usb.txt | 9 +++++ drivers/char/diag/diagchar_core.c | 38 ++++++++++++++++++- drivers/char/diag/diagfwd_bridge.c | 25 ++++++++---- drivers/char/diag/diagfwd_bridge.h | 4 +- 4 files changed, 65 insertions(+), 11 deletions(-) create mode 100644 Documentation/devicetree/bindings/arm/msm/diagfwd_usb.txt diff --git a/Documentation/devicetree/bindings/arm/msm/diagfwd_usb.txt b/Documentation/devicetree/bindings/arm/msm/diagfwd_usb.txt new file mode 100644 index 000000000000..bb72ffe5fe66 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/msm/diagfwd_usb.txt @@ -0,0 +1,9 @@ +QTI Diag Forward USB Driver + +Required properties: +-compatible : should be "qcom,diagfwd-usb". + +Example: + qcom,diag { + compatible = "qcom,diagfwd-usb"; + }; diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c index 6df597dfa750..32f70fa2d37c 100644 --- a/drivers/char/diag/diagchar_core.c +++ b/drivers/char/diag/diagchar_core.c @@ -1160,7 +1160,7 @@ static void diag_remote_exit(void) return; } -int diagfwd_bridge_init(void) +int diagfwd_bridge_init(bool use_mhi) { return 0; } @@ -3743,7 +3743,7 @@ static int diag_mhi_probe(struct platform_device *pdev) diag_remote_exit(); return ret; } - ret = diagfwd_bridge_init(); + ret = diagfwd_bridge_init(true); if (ret) { diagfwd_bridge_exit(); return ret; @@ -3766,6 +3766,39 @@ static struct platform_driver diag_mhi_driver = { }, }; +static int diagfwd_usb_probe(struct platform_device *pdev) +{ + int ret; + + driver->pdev = pdev; + ret = diag_remote_init(); + if (ret) { + diag_remote_exit(); + return ret; + } + ret = diagfwd_bridge_init(false); + if (ret) { + diagfwd_bridge_exit(); + return ret; + } + pr_debug("diag: usb device is ready\n"); + return 0; +} + +static const struct of_device_id diagfwd_usb_table[] = { + {.compatible = "qcom,diagfwd-usb"}, + {}, +}; + +static struct platform_driver diagfwd_usb_driver = { + .probe = diagfwd_usb_probe, + .driver = { + .name = "DIAGFWD USB Platform", + .owner = THIS_MODULE, + .of_match_table = diagfwd_usb_table, + }, +}; + static int __init diagchar_init(void) { dev_t dev; @@ -3892,6 +3925,7 @@ static int __init diagchar_init(void) pr_debug("diagchar initialized now"); platform_driver_register(&diag_mhi_driver); + platform_driver_register(&diagfwd_usb_driver); return 0; fail: diff --git a/drivers/char/diag/diagfwd_bridge.c b/drivers/char/diag/diagfwd_bridge.c index d8e7b39eae8b..ad6203fe5684 100644 --- a/drivers/char/diag/diagfwd_bridge.c +++ b/drivers/char/diag/diagfwd_bridge.c @@ -20,16 +20,24 @@ #include #include "diag_mux.h" #include "diagfwd_bridge.h" -#ifdef USB_QCOM_DIAG_BRIDGE +#ifdef CONFIG_USB_QCOM_DIAG_BRIDGE #include "diagfwd_hsic.h" #endif #include "diagfwd_mhi.h" #include "diag_dci.h" -#ifdef CONFIG_MSM_MHI -#define diag_mdm_init diag_mhi_init -#else -#define diag_mdm_init diag_hsic_init +#ifndef CONFIG_USB_QCOM_DIAG_BRIDGE +static int diag_hsic_init(void) +{ + return -EINVAL; +} +#endif + +#ifndef CONFIG_MSM_MHI +static int diag_mhi_init(void) +{ + return -EINVAL; +} #endif #define BRIDGE_TO_MUX(x) (x + DIAG_MUX_BRIDGE_BASE) @@ -261,11 +269,14 @@ int diag_remote_dev_write_done(int id, unsigned char *buf, int len, int ctxt) return err; } -int diagfwd_bridge_init() +int diagfwd_bridge_init(bool use_mhi) { int err = 0; - err = diag_mdm_init(); + if (use_mhi) + err = diag_mhi_init(); + else + err = diag_hsic_init(); if (err) goto fail; return 0; diff --git a/drivers/char/diag/diagfwd_bridge.h b/drivers/char/diag/diagfwd_bridge.h index 62d6b08b5b89..250ef07b0b04 100644 --- a/drivers/char/diag/diagfwd_bridge.h +++ b/drivers/char/diag/diagfwd_bridge.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2014, 2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -51,7 +51,7 @@ struct diagfwd_bridge_info { }; extern struct diagfwd_bridge_info bridge_info[NUM_REMOTE_DEV]; -int diagfwd_bridge_init(void); +int diagfwd_bridge_init(bool use_mhi); void diagfwd_bridge_exit(void); int diagfwd_bridge_close(int id); int diagfwd_bridge_write(int id, unsigned char *buf, int len); From dc59c27d8b7d66fca409b3ca3c80d49f4698bf97 Mon Sep 17 00:00:00 2001 From: Gustavo Solaira Date: Mon, 9 Jul 2018 19:24:13 -0700 Subject: [PATCH 067/159] ARM: dts: msm: Enable diagfwd-usb for MSM8996 CV2X boards Enable the diagfwd-usb platform driver for MSM8996 CV2X boards. This is used to forward diag data from MDM via USB. Change-Id: I816e82c25ca623c47c541e4e790e22b90c55da41 Signed-off-by: Gustavo Solaira --- arch/arm/boot/dts/qcom/msm8996-cv2x.dtsi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm/boot/dts/qcom/msm8996-cv2x.dtsi b/arch/arm/boot/dts/qcom/msm8996-cv2x.dtsi index d62fc80640a4..3c72fff11ca5 100644 --- a/arch/arm/boot/dts/qcom/msm8996-cv2x.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-cv2x.dtsi @@ -190,6 +190,11 @@ qcom,mhi = <&mhi>; status = "okay"; }; + + qcom,diagfwd-usb { + compatible = "qcom,diagfwd-usb"; + status = "okay"; + }; }; /delete-node/ &mdss_mdp; From 9177f292073bcb9520fbb990b0cec65beab4b32f Mon Sep 17 00:00:00 2001 From: Vivek Kumar Date: Tue, 3 Jul 2018 20:23:57 +0530 Subject: [PATCH 068/159] drm: msm: Hot plug cpu1 once early domain is finished Early domain services run on cpu1 in LK, so hotplug cpu1 once early domain services are finished. Change-Id: I23b57b8b7460c5740083b27af72251b2fad78ed4 Signed-off-by: Vivek Kumar --- drivers/gpu/drm/msm/sde/sde_connector.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/sde/sde_connector.c b/drivers/gpu/drm/msm/sde/sde_connector.c index 1bc3d0a926eb..a986f5db2c41 100644 --- a/drivers/gpu/drm/msm/sde/sde_connector.c +++ b/drivers/gpu/drm/msm/sde/sde_connector.c @@ -17,6 +17,8 @@ #include "sde_connector.h" #include "sde_backlight.h" #include "sde_splash.h" +#include +#include #define SDE_DEBUG_CONN(c, fmt, ...) SDE_DEBUG("conn%d " fmt,\ (c) ? (c)->base.base.id : -1, ##__VA_ARGS__) @@ -51,6 +53,8 @@ static const struct drm_prop_enum_list hpd_clock_state[] = { {SDE_MODE_HPD_OFF, "OFF"}, }; +static struct work_struct cpu_up_work; + int sde_connector_get_info(struct drm_connector *connector, struct msm_display_info *info) { @@ -568,11 +572,18 @@ void sde_connector_prepare_fence(struct drm_connector *connector) sde_fence_prepare(&to_sde_connector(connector)->retire_fence); } +static void wake_up_cpu(struct work_struct *work) +{ + if (!cpu_up(1)) + pr_info("cpu1 is online\n"); +} + void sde_connector_complete_commit(struct drm_connector *connector) { struct drm_device *dev; struct msm_drm_private *priv; struct sde_connector *c_conn; + static atomic_t cpu_up_scheduled = ATOMIC_INIT(0); if (!connector) { SDE_ERROR("invalid connector\n"); @@ -587,7 +598,8 @@ void sde_connector_complete_commit(struct drm_connector *connector) /* * After LK totally exits, LK's early splash resource - * should be released. + * should be released, cpu1 is hot-plugged in case LK's + * early domain has reserved it. */ if (sde_splash_get_lk_complete_status(priv->kms)) { c_conn = to_sde_connector(connector); @@ -595,8 +607,11 @@ void sde_connector_complete_commit(struct drm_connector *connector) sde_splash_free_resource(priv->kms, &priv->phandle, c_conn->connector_type, c_conn->display); + if (atomic_add_unless(&cpu_up_scheduled, 1, 1)) { + INIT_WORK(&cpu_up_work, wake_up_cpu); + schedule_work(&cpu_up_work); + } } - } static int sde_connector_dpms(struct drm_connector *connector, From dd8f83fee464ae79dd96de3a87b03207a814d81e Mon Sep 17 00:00:00 2001 From: Vijay kumar Tumati Date: Thu, 14 Jun 2018 09:27:24 +0530 Subject: [PATCH 069/159] msm: camera: sensor: Add support for front aux sensor Allow front aux sensor to be connected on device. Change-Id: I0386c23c77b38200c20581cd85b20c96bf074547 Signed-off-by: Vijay kumar Tumati --- include/uapi/media/msm_camera.h | 2 +- include/uapi/media/msm_camsensor_sdk.h | 3 +++ include/uapi/media/msmb_camera.h | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/include/uapi/media/msm_camera.h b/include/uapi/media/msm_camera.h index 8fb69aeef9b4..f8d673f3c03a 100644 --- a/include/uapi/media/msm_camera.h +++ b/include/uapi/media/msm_camera.h @@ -262,7 +262,7 @@ struct msm_mctl_post_proc_cmd { #define MSM_CAMERA_STROBE_FLASH_NONE 0 #define MSM_CAMERA_STROBE_FLASH_XENON 1 -#define MSM_MAX_CAMERA_SENSORS 5 +#define MSM_MAX_CAMERA_SENSORS 6 #define MAX_SENSOR_NAME 32 #define MAX_CAM_NAME_SIZE 32 #define MAX_ACT_MOD_NAME_SIZE 32 diff --git a/include/uapi/media/msm_camsensor_sdk.h b/include/uapi/media/msm_camsensor_sdk.h index 4d348c7bc373..fe411c4e92ca 100644 --- a/include/uapi/media/msm_camsensor_sdk.h +++ b/include/uapi/media/msm_camsensor_sdk.h @@ -50,6 +50,8 @@ #define MSM_SENSOR_BYPASS_VIDEO_NODE 1 +#define FRONT_AUX_SENSOR_SUPPORT + enum msm_sensor_camera_id_t { CAMERA_0, CAMERA_1, @@ -70,6 +72,7 @@ enum camb_position_t { BACK_CAMERA_B, FRONT_CAMERA_B, AUX_CAMERA_B = 0x100, + FRONT_AUX_CAMERA_B, INVALID_CAMERA_B, }; diff --git a/include/uapi/media/msmb_camera.h b/include/uapi/media/msmb_camera.h index 47d5a998e139..0a2dd446ccc4 100644 --- a/include/uapi/media/msmb_camera.h +++ b/include/uapi/media/msmb_camera.h @@ -53,7 +53,7 @@ #define MSM_CAMERA_SUBDEV_EXT 19 #define MSM_CAMERA_SUBDEV_TOF 20 #define MSM_CAMERA_SUBDEV_LASER_LED 21 -#define MSM_MAX_CAMERA_SENSORS 5 +#define MSM_MAX_CAMERA_SENSORS 6 /* The below macro is defined to put an upper limit on maximum * number of buffer requested per stream. In case of extremely From bc20ab941e5e1523198b18943f9ca66e269e20a0 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Thu, 5 Jul 2018 14:37:52 -0700 Subject: [PATCH 070/159] MIPS: Fix ioremap() RAM check commit 523402fa9101090c91d2033b7ebdfdcf65880488 upstream. We currently attempt to check whether a physical address range provided to __ioremap() may be in use by the page allocator by examining the value of PageReserved for each page in the region - lowmem pages not marked reserved are presumed to be in use by the page allocator, and requests to ioremap them fail. The way we check this has been broken since commit 92923ca3aace ("mm: meminit: only set page reserved in the memblock region"), because memblock will typically not have any knowledge of non-RAM pages and therefore those pages will not have the PageReserved flag set. Thus when we attempt to ioremap a region outside of RAM we incorrectly fail believing that the region is RAM that may be in use. In most cases ioremap() on MIPS will take a fast-path to use the unmapped kseg1 or xkphys virtual address spaces and never hit this path, so the only way to hit it is for a MIPS32 system to attempt to ioremap() an address range in lowmem with flags other than _CACHE_UNCACHED. Perhaps the most straightforward way to do this is using ioremap_uncached_accelerated(), which is how the problem was discovered. Fix this by making use of walk_system_ram_range() to test the address range provided to __ioremap() against only RAM pages, rather than all lowmem pages. This means that if we have a lowmem I/O region, which is very common for MIPS systems, we're free to ioremap() address ranges within it. A nice bonus is that the test is no longer limited to lowmem. The approach here matches the way x86 performed the same test after commit c81c8a1eeede ("x86, ioremap: Speed up check for RAM pages") until x86 moved towards a slightly more complicated check using walk_mem_res() for unrelated reasons with commit 0e4c12b45aa8 ("x86/mm, resource: Use PAGE_KERNEL protection for ioremap of memory pages"). Signed-off-by: Paul Burton Reported-by: Serge Semin Tested-by: Serge Semin Fixes: 92923ca3aace ("mm: meminit: only set page reserved in the memblock region") Cc: James Hogan Cc: Ralf Baechle Cc: linux-mips@linux-mips.org Cc: stable@vger.kernel.org # v4.2+ Patchwork: https://patchwork.linux-mips.org/patch/19786/ Signed-off-by: Greg Kroah-Hartman --- arch/mips/mm/ioremap.c | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/arch/mips/mm/ioremap.c b/arch/mips/mm/ioremap.c index 8d5008cbdc0f..a853a83f2944 100644 --- a/arch/mips/mm/ioremap.c +++ b/arch/mips/mm/ioremap.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -97,6 +98,20 @@ static int remap_area_pages(unsigned long address, phys_addr_t phys_addr, return error; } +static int __ioremap_check_ram(unsigned long start_pfn, unsigned long nr_pages, + void *arg) +{ + unsigned long i; + + for (i = 0; i < nr_pages; i++) { + if (pfn_valid(start_pfn + i) && + !PageReserved(pfn_to_page(start_pfn + i))) + return 1; + } + + return 0; +} + /* * Generic mapping function (not visible outside): */ @@ -115,8 +130,8 @@ static int remap_area_pages(unsigned long address, phys_addr_t phys_addr, void __iomem * __ioremap(phys_addr_t phys_addr, phys_addr_t size, unsigned long flags) { + unsigned long offset, pfn, last_pfn; struct vm_struct * area; - unsigned long offset; phys_addr_t last_addr; void * addr; @@ -136,18 +151,16 @@ void __iomem * __ioremap(phys_addr_t phys_addr, phys_addr_t size, unsigned long return (void __iomem *) CKSEG1ADDR(phys_addr); /* - * Don't allow anybody to remap normal RAM that we're using.. + * Don't allow anybody to remap RAM that may be allocated by the page + * allocator, since that could lead to races & data clobbering. */ - if (phys_addr < virt_to_phys(high_memory)) { - char *t_addr, *t_end; - struct page *page; - - t_addr = __va(phys_addr); - t_end = t_addr + (size - 1); - - for(page = virt_to_page(t_addr); page <= virt_to_page(t_end); page++) - if(!PageReserved(page)) - return NULL; + pfn = PFN_DOWN(phys_addr); + last_pfn = PFN_DOWN(last_addr); + if (walk_system_ram_range(pfn, last_pfn - pfn + 1, NULL, + __ioremap_check_ram) == 1) { + WARN_ONCE(1, "ioremap on RAM at %pa - %pa\n", + &phys_addr, &last_addr); + return NULL; } /* From ba20e67aee81bf01dc6154e91bcfee431f1bb678 Mon Sep 17 00:00:00 2001 From: Jann Horn Date: Sat, 7 Jul 2018 04:16:33 +0200 Subject: [PATCH 071/159] ibmasm: don't write out of bounds in read handler commit a0341fc1981a950c1e902ab901e98f60e0e243f3 upstream. This read handler had a lot of custom logic and wrote outside the bounds of the provided buffer. This could lead to kernel and userspace memory corruption. Just use simple_read_from_buffer() with a stack buffer. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Cc: stable@vger.kernel.org Signed-off-by: Jann Horn Signed-off-by: Greg Kroah-Hartman --- drivers/misc/ibmasm/ibmasmfs.c | 27 +++------------------------ 1 file changed, 3 insertions(+), 24 deletions(-) diff --git a/drivers/misc/ibmasm/ibmasmfs.c b/drivers/misc/ibmasm/ibmasmfs.c index e8b933111e0d..92109cadc3fc 100644 --- a/drivers/misc/ibmasm/ibmasmfs.c +++ b/drivers/misc/ibmasm/ibmasmfs.c @@ -507,35 +507,14 @@ static int remote_settings_file_close(struct inode *inode, struct file *file) static ssize_t remote_settings_file_read(struct file *file, char __user *buf, size_t count, loff_t *offset) { void __iomem *address = (void __iomem *)file->private_data; - unsigned char *page; - int retval; int len = 0; unsigned int value; - - if (*offset < 0) - return -EINVAL; - if (count == 0 || count > 1024) - return 0; - if (*offset != 0) - return 0; - - page = (unsigned char *)__get_free_page(GFP_KERNEL); - if (!page) - return -ENOMEM; + char lbuf[20]; value = readl(address); - len = sprintf(page, "%d\n", value); + len = snprintf(lbuf, sizeof(lbuf), "%d\n", value); - if (copy_to_user(buf, page, len)) { - retval = -EFAULT; - goto exit; - } - *offset += len; - retval = len; - -exit: - free_page((unsigned long)page); - return retval; + return simple_read_from_buffer(buf, count, offset, lbuf, len); } static ssize_t remote_settings_file_write(struct file *file, const char __user *ubuff, size_t count, loff_t *offset) From f0a1bf29d821ba724e2cf4813352f11a4597afe4 Mon Sep 17 00:00:00 2001 From: Nadav Amit Date: Mon, 2 Jul 2018 19:27:13 -0700 Subject: [PATCH 072/159] vmw_balloon: fix inflation with batching commit 90d72ce079791399ac255c75728f3c9e747b093d upstream. Embarrassingly, the recent fix introduced worse problem than it solved, causing the balloon not to inflate. The VM informed the hypervisor that the pages for lock/unlock are sitting in the wrong address, as it used the page that is used the uninitialized page variable. Fixes: b23220fe054e9 ("vmw_balloon: fixing double free when batching mode is off") Cc: stable@vger.kernel.org Reviewed-by: Xavier Deguillard Signed-off-by: Nadav Amit Signed-off-by: Greg Kroah-Hartman --- drivers/misc/vmw_balloon.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/misc/vmw_balloon.c b/drivers/misc/vmw_balloon.c index fe90b7e04427..5e047bfc0cc4 100644 --- a/drivers/misc/vmw_balloon.c +++ b/drivers/misc/vmw_balloon.c @@ -467,7 +467,7 @@ static int vmballoon_send_batched_lock(struct vmballoon *b, unsigned int num_pages, bool is_2m_pages, unsigned int *target) { unsigned long status; - unsigned long pfn = page_to_pfn(b->page); + unsigned long pfn = PHYS_PFN(virt_to_phys(b->batch_page)); STATS_INC(b->stats.lock[is_2m_pages]); @@ -515,7 +515,7 @@ static bool vmballoon_send_batched_unlock(struct vmballoon *b, unsigned int num_pages, bool is_2m_pages, unsigned int *target) { unsigned long status; - unsigned long pfn = page_to_pfn(b->page); + unsigned long pfn = PHYS_PFN(virt_to_phys(b->batch_page)); STATS_INC(b->stats.unlock[is_2m_pages]); From 54b594369ae19fc64b45ca045c26005d5de095d8 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 1 Jul 2018 12:15:46 +0200 Subject: [PATCH 073/159] ahci: Disable LPM on Lenovo 50 series laptops with a too old BIOS commit 240630e61870e62e39a97225048f9945848fa5f5 upstream. There have been several reports of LPM related hard freezes about once a day on multiple Lenovo 50 series models. Strange enough these reports where not disk model specific as LPM issues usually are and some users with the exact same disk + laptop where seeing them while other users where not seeing these issues. It turns out that enabling LPM triggers a firmware bug somewhere, which has been fixed in later BIOS versions. This commit adds a new ahci_broken_lpm() function and a new ATA_FLAG_NO_LPM for dealing with this. The ahci_broken_lpm() function contains DMI match info for the 4 models which are known to be affected by this and the DMI BIOS date field for known good BIOS versions. If the BIOS date is older then the one in the table LPM will be disabled and a warning will be printed. Note the BIOS dates are for known good versions, some older versions may work too, but we don't know for sure, the table is using dates from BIOS versions for which users have confirmed that upgrading to that version makes the problem go away. Unfortunately I've been unable to get hold of the reporter who reported that BIOS version 2.35 fixed the problems on the W541 for him. I've been able to verify the DMI_SYS_VENDOR and DMI_PRODUCT_VERSION from an older dmidecode, but I don't know the exact BIOS date as reported in the DMI. Lenovo keeps a changelog with dates in their release notes, but the dates there are the release dates not the build dates which are in DMI. So I've chosen to set the date to which we compare to one day past the release date of the 2.34 BIOS. I plan to fix this with a follow up commit once I've the necessary info. Cc: stable@vger.kernel.org Signed-off-by: Hans de Goede Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- drivers/ata/ahci.c | 59 +++++++++++++++++++++++++++++++++++++++ drivers/ata/libata-core.c | 3 ++ include/linux/libata.h | 1 + 3 files changed, 63 insertions(+) diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 5a6a01135470..34fdaa6e99ba 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -1229,6 +1229,59 @@ static bool ahci_broken_suspend(struct pci_dev *pdev) return strcmp(buf, dmi->driver_data) < 0; } +static bool ahci_broken_lpm(struct pci_dev *pdev) +{ + static const struct dmi_system_id sysids[] = { + /* Various Lenovo 50 series have LPM issues with older BIOSen */ + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X250"), + }, + .driver_data = "20180406", /* 1.31 */ + }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L450"), + }, + .driver_data = "20180420", /* 1.28 */ + }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T450s"), + }, + .driver_data = "20180315", /* 1.33 */ + }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad W541"), + }, + /* + * Note date based on release notes, 2.35 has been + * reported to be good, but I've been unable to get + * a hold of the reporter to get the DMI BIOS date. + * TODO: fix this. + */ + .driver_data = "20180310", /* 2.35 */ + }, + { } /* terminate list */ + }; + const struct dmi_system_id *dmi = dmi_first_match(sysids); + int year, month, date; + char buf[9]; + + if (!dmi) + return false; + + dmi_get_date(DMI_BIOS_DATE, &year, &month, &date); + snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date); + + return strcmp(buf, dmi->driver_data) < 0; +} + static bool ahci_broken_online(struct pci_dev *pdev) { #define ENCODE_BUSDEVFN(bus, slot, func) \ @@ -1588,6 +1641,12 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) "quirky BIOS, skipping spindown on poweroff\n"); } + if (ahci_broken_lpm(pdev)) { + pi.flags |= ATA_FLAG_NO_LPM; + dev_warn(&pdev->dev, + "BIOS update required for Link Power Management support\n"); + } + if (ahci_broken_suspend(pdev)) { hpriv->flags |= AHCI_HFLAG_NO_SUSPEND; dev_warn(&pdev->dev, diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 9afd06ee5b30..ba514fa733de 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -2209,6 +2209,9 @@ int ata_dev_configure(struct ata_device *dev) (id[ATA_ID_SATA_CAPABILITY] & 0xe) == 0x2) dev->horkage |= ATA_HORKAGE_NOLPM; + if (ap->flags & ATA_FLAG_NO_LPM) + dev->horkage |= ATA_HORKAGE_NOLPM; + if (dev->horkage & ATA_HORKAGE_NOLPM) { ata_dev_warn(dev, "LPM support broken, forcing max_power\n"); dev->link->ap->target_lpm_policy = ATA_LPM_MAX_POWER; diff --git a/include/linux/libata.h b/include/linux/libata.h index b20a2752f934..6428ac4746de 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -210,6 +210,7 @@ enum { ATA_FLAG_SLAVE_POSS = (1 << 0), /* host supports slave dev */ /* (doesn't imply presence) */ ATA_FLAG_SATA = (1 << 1), + ATA_FLAG_NO_LPM = (1 << 2), /* host not happy with LPM */ ATA_FLAG_NO_LOG_PAGE = (1 << 5), /* do not issue log page read */ ATA_FLAG_NO_ATAPI = (1 << 6), /* No ATAPI support */ ATA_FLAG_PIO_DMA = (1 << 7), /* PIO cmds via DMA */ From a82597e92e47980261f8cfb37008026730a3a585 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 4 Jul 2018 12:29:38 +0300 Subject: [PATCH 074/159] USB: serial: ch341: fix type promotion bug in ch341_control_in() commit e33eab9ded328ccc14308afa51b5be7cbe78d30b upstream. The "r" variable is an int and "bufsize" is an unsigned int so the comparison is type promoted to unsigned. If usb_control_msg() returns a negative that is treated as a high positive value and the error handling doesn't work. Fixes: 2d5a9c72d0c4 ("USB: serial: ch341: fix control-message error handling") Signed-off-by: Dan Carpenter Cc: stable Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ch341.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index 71133d96f97d..f73ea14e8173 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c @@ -118,7 +118,7 @@ static int ch341_control_in(struct usb_device *dev, r = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), request, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, value, index, buf, bufsize, DEFAULT_TIMEOUT); - if (r < bufsize) { + if (r < (int)bufsize) { if (r >= 0) { dev_err(&dev->dev, "short control message received (%d < %u)\n", From 5bbc393835217e5c1e51dae46ecdb3ef26884c92 Mon Sep 17 00:00:00 2001 From: Olli Salonen Date: Wed, 4 Jul 2018 14:07:42 +0300 Subject: [PATCH 075/159] USB: serial: cp210x: add another USB ID for Qivicon ZigBee stick commit 367b160fe4717c14a2a978b6f9ffb75a7762d3ed upstream. There are two versions of the Qivicon Zigbee stick in circulation. This adds the second USB ID to the cp210x driver. Signed-off-by: Olli Salonen Cc: stable Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp210x.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 73835027a7cc..97382301c393 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -145,6 +145,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x10C4, 0x8977) }, /* CEL MeshWorks DevKit Device */ { USB_DEVICE(0x10C4, 0x8998) }, /* KCF Technologies PRN */ { USB_DEVICE(0x10C4, 0x89A4) }, /* CESINEL FTBC Flexible Thyristor Bridge Controller */ + { USB_DEVICE(0x10C4, 0x89FB) }, /* Qivicon ZigBee USB Radio Stick */ { USB_DEVICE(0x10C4, 0x8A2A) }, /* HubZ dual ZigBee and Z-Wave dongle */ { USB_DEVICE(0x10C4, 0x8A5E) }, /* CEL EM3588 ZigBee USB Stick Long Range */ { USB_DEVICE(0x10C4, 0x8B34) }, /* Qivicon ZigBee USB Radio Stick */ From 5736d7c209bf8090d68a611ec4dba034f3d8b2fe Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 4 Jul 2018 17:02:16 +0200 Subject: [PATCH 076/159] USB: serial: keyspan_pda: fix modem-status error handling commit 01b3cdfca263a17554f7b249d20a247b2a751521 upstream. Fix broken modem-status error handling which could lead to bits of slab data leaking to user space. Fixes: 3b36a8fd6777 ("usb: fix uninitialized variable warning in keyspan_pda") Cc: stable # 2.6.27 Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/keyspan_pda.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index 6b0942428917..8a4047de43dc 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c @@ -373,8 +373,10 @@ static int keyspan_pda_get_modem_info(struct usb_serial *serial, 3, /* get pins */ USB_TYPE_VENDOR|USB_RECIP_INTERFACE|USB_DIR_IN, 0, 0, data, 1, 2000); - if (rc >= 0) + if (rc == 1) *value = *data; + else if (rc >= 0) + rc = -EIO; kfree(data); return rc; From 2638a67a0c50a97e0564491325c24c2c12083dbb Mon Sep 17 00:00:00 2001 From: Jann Horn Date: Fri, 6 Jul 2018 17:12:56 +0200 Subject: [PATCH 077/159] USB: yurex: fix out-of-bounds uaccess in read handler commit f1e255d60ae66a9f672ff9a207ee6cd8e33d2679 upstream. In general, accessing userspace memory beyond the length of the supplied buffer in VFS read/write handlers can lead to both kernel memory corruption (via kernel_read()/kernel_write(), which can e.g. be triggered via sys_splice()) and privilege escalation inside userspace. Fix it by using simple_read_from_buffer() instead of custom logic. Fixes: 6bc235a2e24a ("USB: add driver for Meywa-Denki & Kayac YUREX") Signed-off-by: Jann Horn Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/yurex.c | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/drivers/usb/misc/yurex.c b/drivers/usb/misc/yurex.c index 343fa6ff9f4b..512c84adcace 100644 --- a/drivers/usb/misc/yurex.c +++ b/drivers/usb/misc/yurex.c @@ -414,8 +414,7 @@ static ssize_t yurex_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) { struct usb_yurex *dev; - int retval = 0; - int bytes_read = 0; + int len = 0; char in_buffer[20]; unsigned long flags; @@ -423,26 +422,16 @@ static ssize_t yurex_read(struct file *file, char __user *buffer, size_t count, mutex_lock(&dev->io_mutex); if (!dev->interface) { /* already disconnected */ - retval = -ENODEV; - goto exit; + mutex_unlock(&dev->io_mutex); + return -ENODEV; } spin_lock_irqsave(&dev->lock, flags); - bytes_read = snprintf(in_buffer, 20, "%lld\n", dev->bbu); + len = snprintf(in_buffer, 20, "%lld\n", dev->bbu); spin_unlock_irqrestore(&dev->lock, flags); - - if (*ppos < bytes_read) { - if (copy_to_user(buffer, in_buffer + *ppos, bytes_read - *ppos)) - retval = -EFAULT; - else { - retval = bytes_read - *ppos; - *ppos += bytes_read; - } - } - -exit: mutex_unlock(&dev->io_mutex); - return retval; + + return simple_read_from_buffer(buffer, count, ppos, in_buffer, len); } static ssize_t yurex_write(struct file *file, const char __user *user_buffer, From dd1496f3b50316927b60a1baf4c06853f8c6cbdc Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 4 Jul 2018 17:02:17 +0200 Subject: [PATCH 078/159] USB: serial: mos7840: fix status-register error handling commit 794744abfffef8b1f3c0c8a4896177d6d13d653d upstream. Add missing transfer-length sanity check to the status-register completion handler to avoid leaking bits of uninitialised slab data to user space. Fixes: 3f5429746d91 ("USB: Moschip 7840 USB-Serial Driver") Cc: stable # 2.6.19 Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mos7840.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index ed883a7ad533..58ba6904a087 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -482,6 +482,9 @@ static void mos7840_control_callback(struct urb *urb) } dev_dbg(dev, "%s urb buffer size is %d\n", __func__, urb->actual_length); + if (urb->actual_length < 1) + goto out; + dev_dbg(dev, "%s mos7840_port->MsrLsr is %d port %d\n", __func__, mos7840_port->MsrLsr, mos7840_port->port_num); data = urb->transfer_buffer; From 7f873c236d61ec9e41df12b7544c7f5562c25165 Mon Sep 17 00:00:00 2001 From: Nico Sneck Date: Mon, 2 Jul 2018 19:26:07 +0300 Subject: [PATCH 079/159] usb: quirks: add delay quirks for Corsair Strafe commit bba57eddadda936c94b5dccf73787cb9e159d0a5 upstream. Corsair Strafe appears to suffer from the same issues as the Corsair Strafe RGB. Apply the same quirks (control message delay and init delay) that the RGB version has to 1b1c:1b15. With these quirks in place the keyboard works correctly upon booting the system, and no longer requires reattaching the device. Signed-off-by: Nico Sneck Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/quirks.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index 40ce175655e6..99f67764765f 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -231,6 +231,10 @@ static const struct usb_device_id usb_quirk_list[] = { /* Corsair K70 RGB */ { USB_DEVICE(0x1b1c, 0x1b13), .driver_info = USB_QUIRK_DELAY_INIT }, + /* Corsair Strafe */ + { USB_DEVICE(0x1b1c, 0x1b15), .driver_info = USB_QUIRK_DELAY_INIT | + USB_QUIRK_DELAY_CTRL_MSG }, + /* Corsair Strafe RGB */ { USB_DEVICE(0x1b1c, 0x1b20), .driver_info = USB_QUIRK_DELAY_INIT | USB_QUIRK_DELAY_CTRL_MSG }, From 3cd94f78ef738557145e4fdb07c41efed7a8792c Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 4 Jul 2018 12:48:53 +0300 Subject: [PATCH 080/159] xhci: xhci-mem: off by one in xhci_stream_id_to_ring() commit 313db3d6488bb03b61b99de9dbca061f1fd838e1 upstream. The > should be >= here so that we don't read one element beyond the end of the ep->stream_info->stream_rings[] array. Fixes: e9df17eb1408 ("USB: xhci: Correct assumptions about number of rings per endpoint.") Signed-off-by: Dan Carpenter Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-mem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index e4cf3322bcb3..0ec809a35a3f 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -638,7 +638,7 @@ struct xhci_ring *xhci_stream_id_to_ring( if (!ep->stream_info) return NULL; - if (stream_id > ep->stream_info->num_streams) + if (stream_id >= ep->stream_info->num_streams) return NULL; return ep->stream_info->stream_rings[stream_id]; } From 52558627ceab876ddc8047baf77ea32b5042c5ba Mon Sep 17 00:00:00 2001 From: Tomasz Kramkowski Date: Tue, 14 Feb 2017 23:14:33 +0000 Subject: [PATCH 081/159] HID: usbhid: add quirk for innomedia INNEX GENESIS/ATARI adapter commit 9547837bdccb4af127528b36a73377150658b4ac upstream. The (1292:4745) Innomedia INNEX GENESIS/ATARI adapter needs HID_QUIRK_MULTI_INPUT to split the device up into two controllers instead of inputs from both being merged into one. Signed-off-by: Tomasz Kramkowski Acked-By: Benjamin Tissoires Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/hid/hid-ids.h | 3 +++ drivers/hid/usbhid/hid-quirks.c | 1 + 2 files changed, 4 insertions(+) diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index b316ab7e8996..60e2c9faa95f 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -512,6 +512,9 @@ #define USB_VENDOR_ID_IRTOUCHSYSTEMS 0x6615 #define USB_DEVICE_ID_IRTOUCH_INFRARED_USB 0x0070 +#define USB_VENDOR_ID_INNOMEDIA 0x1292 +#define USB_DEVICE_ID_INNEX_GENESIS_ATARI 0x4745 + #define USB_VENDOR_ID_ITE 0x048d #define USB_DEVICE_ID_ITE_LENOVO_YOGA 0x8386 #define USB_DEVICE_ID_ITE_LENOVO_YOGA2 0x8350 diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index ce1543d69acb..c9a11315493b 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -152,6 +152,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_MULTIPLE_1781, USB_DEVICE_ID_RAPHNET_4NES4SNES_OLD, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_DRACAL_RAPHNET, USB_DEVICE_ID_RAPHNET_2NES2SNES, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_DRACAL_RAPHNET, USB_DEVICE_ID_RAPHNET_4NES4SNES, HID_QUIRK_MULTI_INPUT }, + { USB_VENDOR_ID_INNOMEDIA, USB_DEVICE_ID_INNEX_GENESIS_ATARI, HID_QUIRK_MULTI_INPUT }, { 0, 0 } }; From e71dbad7563db674f91af9e12ef592c107d0c2cd Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 3 Jul 2018 17:10:19 -0700 Subject: [PATCH 082/159] Fix up non-directory creation in SGID directories commit 0fa3ecd87848c9c93c2c828ef4c3a8ca36ce46c7 upstream. sgid directories have special semantics, making newly created files in the directory belong to the group of the directory, and newly created subdirectories will also become sgid. This is historically used for group-shared directories. But group directories writable by non-group members should not imply that such non-group members can magically join the group, so make sure to clear the sgid bit on non-directories for non-members (but remember that sgid without group execute means "mandatory locking", just to confuse things even more). Reported-by: Jann Horn Cc: Andy Lutomirski Cc: Al Viro Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/inode.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fs/inode.c b/fs/inode.c index b95615f3fc50..a39c2724d8a0 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -1937,8 +1937,14 @@ void inode_init_owner(struct inode *inode, const struct inode *dir, inode->i_uid = current_fsuid(); if (dir && dir->i_mode & S_ISGID) { inode->i_gid = dir->i_gid; + + /* Directories are special, and always inherit S_ISGID */ if (S_ISDIR(mode)) mode |= S_ISGID; + else if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP) && + !in_group_p(inode->i_gid) && + !capable_wrt_inode_uidgid(dir, CAP_FSETID)) + mode &= ~S_ISGID; } else inode->i_gid = current_fsgid(); inode->i_mode = mode; From 5956a8e37d66cc0a6e265704564f8314a54d7c97 Mon Sep 17 00:00:00 2001 From: Paul Menzel Date: Tue, 5 Jun 2018 19:00:22 +0200 Subject: [PATCH 083/159] tools build: fix # escaping in .cmd files for future Make commit 9feeb638cde083c737e295c0547f1b4f28e99583 upstream. In 2016 GNU Make made a backwards incompatible change to the way '#' characters were handled in Makefiles when used inside functions or macros: http://git.savannah.gnu.org/cgit/make.git/commit/?id=c6966b323811c37acedff05b57 Due to this change, when attempting to run `make prepare' I get a spurious make syntax error: /home/earnest/linux/tools/objtool/.fixdep.o.cmd:1: *** missing separator. Stop. When inspecting `.fixdep.o.cmd' it includes two lines which use unescaped comment characters at the top: \# cannot find fixdep (/home/earnest/linux/tools/objtool//fixdep) \# using basic dep data This is because `tools/build/Build.include' prints these '\#' characters: printf '\# cannot find fixdep (%s)\n' $(fixdep) > $(dot-target).cmd; \ printf '\# using basic dep data\n\n' >> $(dot-target).cmd; \ This completes commit 9564a8cf422d ("Kbuild: fix # escaping in .cmd files for future Make"). Link: https://bugzilla.kernel.org/show_bug.cgi?id=197847 Cc: Randy Dunlap Cc: Rasmus Villemoes Cc: stable@vger.kernel.org Signed-off-by: Paul Menzel Signed-off-by: Masahiro Yamada Signed-off-by: Greg Kroah-Hartman --- tools/build/Build.include | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/build/Build.include b/tools/build/Build.include index 4d000bc959b4..1c570528baf7 100644 --- a/tools/build/Build.include +++ b/tools/build/Build.include @@ -62,8 +62,8 @@ dep-cmd = $(if $(wildcard $(fixdep)), $(fixdep) $(depfile) $@ '$(make-cmd)' > $(dot-target).tmp; \ rm -f $(depfile); \ mv -f $(dot-target).tmp $(dot-target).cmd, \ - printf '\# cannot find fixdep (%s)\n' $(fixdep) > $(dot-target).cmd; \ - printf '\# using basic dep data\n\n' >> $(dot-target).cmd; \ + printf '$(pound) cannot find fixdep (%s)\n' $(fixdep) > $(dot-target).cmd; \ + printf '$(pound) using basic dep data\n\n' >> $(dot-target).cmd; \ cat $(depfile) >> $(dot-target).cmd; \ printf '%s\n' 'cmd_$@ := $(make-cmd)' >> $(dot-target).cmd) From 455040965e355459392a2d88bd864ae242d7c810 Mon Sep 17 00:00:00 2001 From: Steve Wise Date: Thu, 21 Jun 2018 07:43:21 -0700 Subject: [PATCH 084/159] iw_cxgb4: correctly enforce the max reg_mr depth commit 7b72717a20bba8bdd01b14c0460be7d15061cd6b upstream. The code was mistakenly using the length of the page array memory instead of the depth of the page array. This would cause MR creation to fail in some cases. Fixes: 8376b86de7d3 ("iw_cxgb4: Support the new memory registration API") Cc: stable@vger.kernel.org Signed-off-by: Steve Wise Signed-off-by: Jason Gunthorpe Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/hw/cxgb4/mem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/cxgb4/mem.c b/drivers/infiniband/hw/cxgb4/mem.c index e1629ab58db7..8218d714fa01 100644 --- a/drivers/infiniband/hw/cxgb4/mem.c +++ b/drivers/infiniband/hw/cxgb4/mem.c @@ -926,7 +926,7 @@ static int c4iw_set_page(struct ib_mr *ibmr, u64 addr) { struct c4iw_mr *mhp = to_c4iw_mr(ibmr); - if (unlikely(mhp->mpl_len == mhp->max_mpl_len)) + if (unlikely(mhp->mpl_len == mhp->attr.pbl_size)) return -ENOMEM; mhp->mpl[mhp->mpl_len++] = addr; From 47ff5bc938c8db4f268628c6cddf44cfbb861725 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Sat, 14 Jul 2018 02:26:01 -0700 Subject: [PATCH 085/159] x86/cpufeature: Move some of the scattered feature bits to x86_capability commit 2ccd71f1b278d450a6f8c8c737c7fe237ca06dc6 upstream Turn the CPUID leafs which are proper CPUID feature bit leafs into separate ->x86_capability words. Signed-off-by: Borislav Petkov Link: http://lkml.kernel.org/r/1449481182-27541-2-git-send-email-bp@alien8.de Signed-off-by: Thomas Gleixner Signed-off-by: Srivatsa S. Bhat Reviewed-by: Matt Helsley (VMware) Reviewed-by: Alexey Makhalov Reviewed-by: Bo Gan Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/cpufeature.h | 54 ++++++++++++++++++------------- arch/x86/kernel/cpu/common.c | 5 +++ arch/x86/kernel/cpu/scattered.c | 20 ------------ 3 files changed, 37 insertions(+), 42 deletions(-) diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 232621c5e859..999e166407a7 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -12,7 +12,7 @@ #include #endif -#define NCAPINTS 14 /* N 32-bit words worth of info */ +#define NCAPINTS 16 /* N 32-bit words worth of info */ #define NBUGINTS 1 /* N 32-bit bug flags */ /* @@ -181,23 +181,18 @@ /* * Auxiliary flags: Linux defined - For features scattered in various - * CPUID levels like 0x6, 0xA etc, word 7 + * CPUID levels like 0x6, 0xA etc, word 7. + * + * Reuse free bits when adding new feature flags! */ -#define X86_FEATURE_IDA ( 7*32+ 0) /* Intel Dynamic Acceleration */ -#define X86_FEATURE_ARAT ( 7*32+ 1) /* Always Running APIC Timer */ + #define X86_FEATURE_CPB ( 7*32+ 2) /* AMD Core Performance Boost */ #define X86_FEATURE_EPB ( 7*32+ 3) /* IA32_ENERGY_PERF_BIAS support */ #define X86_FEATURE_INVPCID_SINGLE ( 7*32+ 4) /* Effectively INVPCID && CR4.PCIDE=1 */ -#define X86_FEATURE_PLN ( 7*32+ 5) /* Intel Power Limit Notification */ -#define X86_FEATURE_PTS ( 7*32+ 6) /* Intel Package Thermal Status */ -#define X86_FEATURE_DTHERM ( 7*32+ 7) /* Digital Thermal Sensor */ + #define X86_FEATURE_HW_PSTATE ( 7*32+ 8) /* AMD HW-PState */ #define X86_FEATURE_PROC_FEEDBACK ( 7*32+ 9) /* AMD ProcFeedbackInterface */ -#define X86_FEATURE_HWP ( 7*32+ 10) /* "hwp" Intel HWP */ -#define X86_FEATURE_HWP_NOTIFY ( 7*32+ 11) /* Intel HWP_NOTIFY */ -#define X86_FEATURE_HWP_ACT_WINDOW ( 7*32+ 12) /* Intel HWP_ACT_WINDOW */ -#define X86_FEATURE_HWP_EPP ( 7*32+13) /* Intel HWP_EPP */ -#define X86_FEATURE_HWP_PKG_REQ ( 7*32+14) /* Intel HWP_PKG_REQ */ + #define X86_FEATURE_INTEL_PT ( 7*32+15) /* Intel Processor Trace */ #define X86_FEATURE_RSB_CTXSW ( 7*32+19) /* Fill RSB on context switches */ @@ -212,16 +207,7 @@ #define X86_FEATURE_FLEXPRIORITY ( 8*32+ 2) /* Intel FlexPriority */ #define X86_FEATURE_EPT ( 8*32+ 3) /* Intel Extended Page Table */ #define X86_FEATURE_VPID ( 8*32+ 4) /* Intel Virtual Processor ID */ -#define X86_FEATURE_NPT ( 8*32+ 5) /* AMD Nested Page Table support */ -#define X86_FEATURE_LBRV ( 8*32+ 6) /* AMD LBR Virtualization support */ -#define X86_FEATURE_SVML ( 8*32+ 7) /* "svm_lock" AMD SVM locking MSR */ -#define X86_FEATURE_NRIPS ( 8*32+ 8) /* "nrip_save" AMD SVM next_rip save */ -#define X86_FEATURE_TSCRATEMSR ( 8*32+ 9) /* "tsc_scale" AMD TSC scaling support */ -#define X86_FEATURE_VMCBCLEAN ( 8*32+10) /* "vmcb_clean" AMD VMCB clean bits support */ -#define X86_FEATURE_FLUSHBYASID ( 8*32+11) /* AMD flush-by-ASID support */ -#define X86_FEATURE_DECODEASSISTS ( 8*32+12) /* AMD Decode Assists support */ -#define X86_FEATURE_PAUSEFILTER ( 8*32+13) /* AMD filtered pause intercept */ -#define X86_FEATURE_PFTHRESHOLD ( 8*32+14) /* AMD pause filter threshold */ + #define X86_FEATURE_VMMCALL ( 8*32+15) /* Prefer vmmcall to vmcall */ #define X86_FEATURE_XENPV ( 8*32+16) /* "" Xen paravirtual guest */ @@ -266,6 +252,30 @@ /* AMD-defined CPU features, CPUID level 0x80000008 (ebx), word 13 */ #define X86_FEATURE_CLZERO (13*32+0) /* CLZERO instruction */ +/* Thermal and Power Management Leaf, CPUID level 0x00000006 (eax), word 14 */ +#define X86_FEATURE_DTHERM (14*32+ 0) /* Digital Thermal Sensor */ +#define X86_FEATURE_IDA (14*32+ 1) /* Intel Dynamic Acceleration */ +#define X86_FEATURE_ARAT (14*32+ 2) /* Always Running APIC Timer */ +#define X86_FEATURE_PLN (14*32+ 4) /* Intel Power Limit Notification */ +#define X86_FEATURE_PTS (14*32+ 6) /* Intel Package Thermal Status */ +#define X86_FEATURE_HWP (14*32+ 7) /* Intel Hardware P-states */ +#define X86_FEATURE_HWP_NOTIFY (14*32+ 8) /* HWP Notification */ +#define X86_FEATURE_HWP_ACT_WINDOW (14*32+ 9) /* HWP Activity Window */ +#define X86_FEATURE_HWP_EPP (14*32+10) /* HWP Energy Perf. Preference */ +#define X86_FEATURE_HWP_PKG_REQ (14*32+11) /* HWP Package Level Request */ + +/* AMD SVM Feature Identification, CPUID level 0x8000000a (edx), word 15 */ +#define X86_FEATURE_NPT (15*32+ 0) /* Nested Page Table support */ +#define X86_FEATURE_LBRV (15*32+ 1) /* LBR Virtualization support */ +#define X86_FEATURE_SVML (15*32+ 2) /* "svm_lock" SVM locking MSR */ +#define X86_FEATURE_NRIPS (15*32+ 3) /* "nrip_save" SVM next_rip save */ +#define X86_FEATURE_TSCRATEMSR (15*32+ 4) /* "tsc_scale" TSC scaling support */ +#define X86_FEATURE_VMCBCLEAN (15*32+ 5) /* "vmcb_clean" VMCB clean bits support */ +#define X86_FEATURE_FLUSHBYASID (15*32+ 6) /* flush-by-ASID support */ +#define X86_FEATURE_DECODEASSISTS (15*32+ 7) /* Decode Assists support */ +#define X86_FEATURE_PAUSEFILTER (15*32+10) /* filtered pause intercept */ +#define X86_FEATURE_PFTHRESHOLD (15*32+12) /* pause filter threshold */ + /* * BUG word(s) */ diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 0498ad3702f5..2007dfc5b999 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -695,6 +695,8 @@ void get_cpu_cap(struct cpuinfo_x86 *c) cpuid_count(0x00000007, 0, &eax, &ebx, &ecx, &edx); c->x86_capability[9] = ebx; + + c->x86_capability[14] = cpuid_eax(0x00000006); } /* Extended state features: level 0x0000000d */ @@ -756,6 +758,9 @@ void get_cpu_cap(struct cpuinfo_x86 *c) if (c->extended_cpuid_level >= 0x80000007) c->x86_power = cpuid_edx(0x80000007); + if (c->extended_cpuid_level >= 0x8000000a) + c->x86_capability[15] = cpuid_edx(0x8000000a); + init_scattered_cpuid_features(c); } diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c index 608fb26c7254..8cb57df9398d 100644 --- a/arch/x86/kernel/cpu/scattered.c +++ b/arch/x86/kernel/cpu/scattered.c @@ -31,32 +31,12 @@ void init_scattered_cpuid_features(struct cpuinfo_x86 *c) const struct cpuid_bit *cb; static const struct cpuid_bit cpuid_bits[] = { - { X86_FEATURE_DTHERM, CR_EAX, 0, 0x00000006, 0 }, - { X86_FEATURE_IDA, CR_EAX, 1, 0x00000006, 0 }, - { X86_FEATURE_ARAT, CR_EAX, 2, 0x00000006, 0 }, - { X86_FEATURE_PLN, CR_EAX, 4, 0x00000006, 0 }, - { X86_FEATURE_PTS, CR_EAX, 6, 0x00000006, 0 }, - { X86_FEATURE_HWP, CR_EAX, 7, 0x00000006, 0 }, - { X86_FEATURE_HWP_NOTIFY, CR_EAX, 8, 0x00000006, 0 }, - { X86_FEATURE_HWP_ACT_WINDOW, CR_EAX, 9, 0x00000006, 0 }, - { X86_FEATURE_HWP_EPP, CR_EAX,10, 0x00000006, 0 }, - { X86_FEATURE_HWP_PKG_REQ, CR_EAX,11, 0x00000006, 0 }, { X86_FEATURE_INTEL_PT, CR_EBX,25, 0x00000007, 0 }, { X86_FEATURE_APERFMPERF, CR_ECX, 0, 0x00000006, 0 }, { X86_FEATURE_EPB, CR_ECX, 3, 0x00000006, 0 }, { X86_FEATURE_HW_PSTATE, CR_EDX, 7, 0x80000007, 0 }, { X86_FEATURE_CPB, CR_EDX, 9, 0x80000007, 0 }, { X86_FEATURE_PROC_FEEDBACK, CR_EDX,11, 0x80000007, 0 }, - { X86_FEATURE_NPT, CR_EDX, 0, 0x8000000a, 0 }, - { X86_FEATURE_LBRV, CR_EDX, 1, 0x8000000a, 0 }, - { X86_FEATURE_SVML, CR_EDX, 2, 0x8000000a, 0 }, - { X86_FEATURE_NRIPS, CR_EDX, 3, 0x8000000a, 0 }, - { X86_FEATURE_TSCRATEMSR, CR_EDX, 4, 0x8000000a, 0 }, - { X86_FEATURE_VMCBCLEAN, CR_EDX, 5, 0x8000000a, 0 }, - { X86_FEATURE_FLUSHBYASID, CR_EDX, 6, 0x8000000a, 0 }, - { X86_FEATURE_DECODEASSISTS, CR_EDX, 7, 0x8000000a, 0 }, - { X86_FEATURE_PAUSEFILTER, CR_EDX,10, 0x8000000a, 0 }, - { X86_FEATURE_PFTHRESHOLD, CR_EDX,12, 0x8000000a, 0 }, { 0, 0, 0, 0, 0 } }; From 0f66fae5d614efedac967ab010faa3f6bf44a347 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Sat, 14 Jul 2018 02:26:09 -0700 Subject: [PATCH 086/159] x86/cpufeature: Cleanup get_cpu_cap() commit 39c06df4dc10a41de5fe706f4378ee5f09beba73 upstream Add an enum for the ->x86_capability array indices and cleanup get_cpu_cap() by killing some redundant local vars. Signed-off-by: Borislav Petkov Link: http://lkml.kernel.org/r/1449481182-27541-3-git-send-email-bp@alien8.de Signed-off-by: Thomas Gleixner Signed-off-by: Srivatsa S. Bhat Reviewed-by: Matt Helsley (VMware) Reviewed-by: Alexey Makhalov Reviewed-by: Bo Gan Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/cpufeature.h | 20 +++++++++++++ arch/x86/kernel/cpu/centaur.c | 2 +- arch/x86/kernel/cpu/common.c | 47 +++++++++++++++---------------- arch/x86/kernel/cpu/transmeta.c | 4 +-- 4 files changed, 45 insertions(+), 28 deletions(-) diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 999e166407a7..54c7a0b9662a 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -299,6 +299,26 @@ #include #include +enum cpuid_leafs +{ + CPUID_1_EDX = 0, + CPUID_8000_0001_EDX, + CPUID_8086_0001_EDX, + CPUID_LNX_1, + CPUID_1_ECX, + CPUID_C000_0001_EDX, + CPUID_8000_0001_ECX, + CPUID_LNX_2, + CPUID_LNX_3, + CPUID_7_0_EBX, + CPUID_D_1_EAX, + CPUID_F_0_EDX, + CPUID_F_1_EDX, + CPUID_8000_0008_EBX, + CPUID_6_EAX, + CPUID_8000_000A_EDX, +}; + #ifdef CONFIG_X86_FEATURE_NAMES extern const char * const x86_cap_flags[NCAPINTS*32]; extern const char * const x86_power_flags[32]; diff --git a/arch/x86/kernel/cpu/centaur.c b/arch/x86/kernel/cpu/centaur.c index d8fba5c15fbd..ae20be6e483c 100644 --- a/arch/x86/kernel/cpu/centaur.c +++ b/arch/x86/kernel/cpu/centaur.c @@ -43,7 +43,7 @@ static void init_c3(struct cpuinfo_x86 *c) /* store Centaur Extended Feature Flags as * word 5 of the CPU capability bit array */ - c->x86_capability[5] = cpuid_edx(0xC0000001); + c->x86_capability[CPUID_C000_0001_EDX] = cpuid_edx(0xC0000001); } #ifdef CONFIG_X86_32 /* Cyrix III family needs CX8 & PGE explicitly enabled. */ diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 2007dfc5b999..5b6e43b4c329 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -676,52 +676,47 @@ static void apply_forced_caps(struct cpuinfo_x86 *c) void get_cpu_cap(struct cpuinfo_x86 *c) { - u32 tfms, xlvl; - u32 ebx; + u32 eax, ebx, ecx, edx; /* Intel-defined flags: level 0x00000001 */ if (c->cpuid_level >= 0x00000001) { - u32 capability, excap; + cpuid(0x00000001, &eax, &ebx, &ecx, &edx); - cpuid(0x00000001, &tfms, &ebx, &excap, &capability); - c->x86_capability[0] = capability; - c->x86_capability[4] = excap; + c->x86_capability[CPUID_1_ECX] = ecx; + c->x86_capability[CPUID_1_EDX] = edx; } /* Additional Intel-defined flags: level 0x00000007 */ if (c->cpuid_level >= 0x00000007) { - u32 eax, ebx, ecx, edx; - cpuid_count(0x00000007, 0, &eax, &ebx, &ecx, &edx); - c->x86_capability[9] = ebx; + c->x86_capability[CPUID_7_0_EBX] = ebx; - c->x86_capability[14] = cpuid_eax(0x00000006); + c->x86_capability[CPUID_6_EAX] = cpuid_eax(0x00000006); } /* Extended state features: level 0x0000000d */ if (c->cpuid_level >= 0x0000000d) { - u32 eax, ebx, ecx, edx; - cpuid_count(0x0000000d, 1, &eax, &ebx, &ecx, &edx); - c->x86_capability[10] = eax; + c->x86_capability[CPUID_D_1_EAX] = eax; } /* Additional Intel-defined flags: level 0x0000000F */ if (c->cpuid_level >= 0x0000000F) { - u32 eax, ebx, ecx, edx; /* QoS sub-leaf, EAX=0Fh, ECX=0 */ cpuid_count(0x0000000F, 0, &eax, &ebx, &ecx, &edx); - c->x86_capability[11] = edx; + c->x86_capability[CPUID_F_0_EDX] = edx; + if (cpu_has(c, X86_FEATURE_CQM_LLC)) { /* will be overridden if occupancy monitoring exists */ c->x86_cache_max_rmid = ebx; /* QoS sub-leaf, EAX=0Fh, ECX=1 */ cpuid_count(0x0000000F, 1, &eax, &ebx, &ecx, &edx); - c->x86_capability[12] = edx; + c->x86_capability[CPUID_F_1_EDX] = edx; + if (cpu_has(c, X86_FEATURE_CQM_OCCUP_LLC)) { c->x86_cache_max_rmid = ecx; c->x86_cache_occ_scale = ebx; @@ -733,22 +728,24 @@ void get_cpu_cap(struct cpuinfo_x86 *c) } /* AMD-defined flags: level 0x80000001 */ - xlvl = cpuid_eax(0x80000000); - c->extended_cpuid_level = xlvl; + eax = cpuid_eax(0x80000000); + c->extended_cpuid_level = eax; - if ((xlvl & 0xffff0000) == 0x80000000) { - if (xlvl >= 0x80000001) { - c->x86_capability[1] = cpuid_edx(0x80000001); - c->x86_capability[6] = cpuid_ecx(0x80000001); + if ((eax & 0xffff0000) == 0x80000000) { + if (eax >= 0x80000001) { + cpuid(0x80000001, &eax, &ebx, &ecx, &edx); + + c->x86_capability[CPUID_8000_0001_ECX] = ecx; + c->x86_capability[CPUID_8000_0001_EDX] = edx; } } if (c->extended_cpuid_level >= 0x80000008) { - u32 eax = cpuid_eax(0x80000008); + cpuid(0x80000008, &eax, &ebx, &ecx, &edx); c->x86_virt_bits = (eax >> 8) & 0xff; c->x86_phys_bits = eax & 0xff; - c->x86_capability[13] = cpuid_ebx(0x80000008); + c->x86_capability[CPUID_8000_0008_EBX] = ebx; } #ifdef CONFIG_X86_32 else if (cpu_has(c, X86_FEATURE_PAE) || cpu_has(c, X86_FEATURE_PSE36)) @@ -759,7 +756,7 @@ void get_cpu_cap(struct cpuinfo_x86 *c) c->x86_power = cpuid_edx(0x80000007); if (c->extended_cpuid_level >= 0x8000000a) - c->x86_capability[15] = cpuid_edx(0x8000000a); + c->x86_capability[CPUID_8000_000A_EDX] = cpuid_edx(0x8000000a); init_scattered_cpuid_features(c); } diff --git a/arch/x86/kernel/cpu/transmeta.c b/arch/x86/kernel/cpu/transmeta.c index 3fa0e5ad86b4..252da7aceca6 100644 --- a/arch/x86/kernel/cpu/transmeta.c +++ b/arch/x86/kernel/cpu/transmeta.c @@ -12,7 +12,7 @@ static void early_init_transmeta(struct cpuinfo_x86 *c) xlvl = cpuid_eax(0x80860000); if ((xlvl & 0xffff0000) == 0x80860000) { if (xlvl >= 0x80860001) - c->x86_capability[2] = cpuid_edx(0x80860001); + c->x86_capability[CPUID_8086_0001_EDX] = cpuid_edx(0x80860001); } } @@ -82,7 +82,7 @@ static void init_transmeta(struct cpuinfo_x86 *c) /* Unhide possibly hidden capability flags */ rdmsr(0x80860004, cap_mask, uk); wrmsr(0x80860004, ~0, uk); - c->x86_capability[0] = cpuid_edx(0x00000001); + c->x86_capability[CPUID_1_EDX] = cpuid_edx(0x00000001); wrmsr(0x80860004, cap_mask, uk); /* All Transmeta CPUs have a constant TSC */ From 8c9814143e58cc34d29dbf187d0ffe04680e17f9 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Sat, 14 Jul 2018 02:26:17 -0700 Subject: [PATCH 087/159] x86/cpu: Provide a config option to disable static_cpu_has commit 6e1315fe82308cd29e7550eab967262e8bbc71a3 upstream This brings .text savings of about ~1.6K when building a tinyconfig. It is off by default so nothing changes for the default. Kconfig help text from Josh. Signed-off-by: Borislav Petkov Reviewed-by: Josh Triplett Link: http://lkml.kernel.org/r/1449481182-27541-5-git-send-email-bp@alien8.de Signed-off-by: Thomas Gleixner Signed-off-by: Srivatsa S. Bhat Reviewed-by: Matt Helsley (VMware) Reviewed-by: Alexey Makhalov Reviewed-by: Bo Gan Signed-off-by: Greg Kroah-Hartman --- arch/x86/Kconfig | 11 +++++++++++ arch/x86/include/asm/cpufeature.h | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index eab1ef25eecd..d9afe6d40550 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -346,6 +346,17 @@ config X86_FEATURE_NAMES If in doubt, say Y. +config X86_FAST_FEATURE_TESTS + bool "Fast CPU feature tests" if EMBEDDED + default y + ---help--- + Some fast-paths in the kernel depend on the capabilities of the CPU. + Say Y here for the kernel to patch in the appropriate code at runtime + based on the capabilities of the CPU. The infrastructure for patching + code at runtime takes up some additional space; space-constrained + embedded systems may wish to say N here to produce smaller, slightly + slower code. + config X86_X2APIC bool "Support x2apic" depends on X86_LOCAL_APIC && X86_64 && (IRQ_REMAP || HYPERVISOR_GUEST) diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 54c7a0b9662a..67f917b96651 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -422,7 +422,7 @@ extern const char * const x86_bug_flags[NBUGINTS*32]; * fast paths and boot_cpu_has() otherwise! */ -#if __GNUC__ >= 4 +#if __GNUC__ >= 4 && defined(CONFIG_X86_FAST_FEATURE_TESTS) extern void warn_pre_alternatives(void); extern bool __static_cpu_has_safe(u16 bit); From 11473585ba6e4102c31da6e5ed8b6f57b9761f3e Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Sat, 14 Jul 2018 02:26:25 -0700 Subject: [PATCH 088/159] x86/fpu: Add an XSTATE_OP() macro commit b74a0cf1b3db30173eefa00c411775d2b1697700 upstream Add an XSTATE_OP() macro which contains the XSAVE* fault handling and replace all non-alternatives users of xstate_fault() with it. This fixes also the buglet in copy_xregs_to_user() and copy_user_to_xregs() where the inline asm didn't have @xstate as memory reference and thus potentially causing unwanted reordering of accesses to the extended state. Signed-off-by: Borislav Petkov Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Dave Hansen Cc: Denys Vlasenko Cc: Fenghua Yu Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Oleg Nesterov Cc: Peter Zijlstra Cc: Quentin Casasnovas Cc: Rik van Riel Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1447932326-4371-2-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar Signed-off-by: Srivatsa S. Bhat Reviewed-by: Matt Helsley (VMware) Reviewed-by: Alexey Makhalov Reviewed-by: Bo Gan Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/fpu/internal.h | 68 +++++++++++++---------------- 1 file changed, 31 insertions(+), 37 deletions(-) diff --git a/arch/x86/include/asm/fpu/internal.h b/arch/x86/include/asm/fpu/internal.h index 146d838e6ee7..839e7b649070 100644 --- a/arch/x86/include/asm/fpu/internal.h +++ b/arch/x86/include/asm/fpu/internal.h @@ -238,6 +238,20 @@ static inline void copy_fxregs_to_kernel(struct fpu *fpu) _ASM_EXTABLE(1b, 3b) \ : [_err] "=r" (__err) +#define XSTATE_OP(op, st, lmask, hmask, err) \ + asm volatile("1:" op "\n\t" \ + "xor %[err], %[err]\n" \ + "2:\n\t" \ + ".pushsection .fixup,\"ax\"\n\t" \ + "3: movl $-2,%[err]\n\t" \ + "jmp 2b\n\t" \ + ".popsection\n\t" \ + _ASM_EXTABLE(1b, 3b) \ + : [err] "=r" (err) \ + : "D" (st), "m" (*st), "a" (lmask), "d" (hmask) \ + : "memory") + + /* * This function is called only during boot time when x86 caps are not set * up and alternative can not be used yet. @@ -247,22 +261,14 @@ static inline void copy_xregs_to_kernel_booting(struct xregs_state *xstate) u64 mask = -1; u32 lmask = mask; u32 hmask = mask >> 32; - int err = 0; + int err; WARN_ON(system_state != SYSTEM_BOOTING); - if (boot_cpu_has(X86_FEATURE_XSAVES)) - asm volatile("1:"XSAVES"\n\t" - "2:\n\t" - xstate_fault(err) - : "D" (xstate), "m" (*xstate), "a" (lmask), "d" (hmask), "0" (err) - : "memory"); + if (static_cpu_has_safe(X86_FEATURE_XSAVES)) + XSTATE_OP(XSAVES, xstate, lmask, hmask, err); else - asm volatile("1:"XSAVE"\n\t" - "2:\n\t" - xstate_fault(err) - : "D" (xstate), "m" (*xstate), "a" (lmask), "d" (hmask), "0" (err) - : "memory"); + XSTATE_OP(XSAVE, xstate, lmask, hmask, err); /* We should never fault when copying to a kernel buffer: */ WARN_ON_FPU(err); @@ -277,22 +283,14 @@ static inline void copy_kernel_to_xregs_booting(struct xregs_state *xstate) u64 mask = -1; u32 lmask = mask; u32 hmask = mask >> 32; - int err = 0; + int err; WARN_ON(system_state != SYSTEM_BOOTING); - if (boot_cpu_has(X86_FEATURE_XSAVES)) - asm volatile("1:"XRSTORS"\n\t" - "2:\n\t" - xstate_fault(err) - : "D" (xstate), "m" (*xstate), "a" (lmask), "d" (hmask), "0" (err) - : "memory"); + if (static_cpu_has_safe(X86_FEATURE_XSAVES)) + XSTATE_OP(XRSTORS, xstate, lmask, hmask, err); else - asm volatile("1:"XRSTOR"\n\t" - "2:\n\t" - xstate_fault(err) - : "D" (xstate), "m" (*xstate), "a" (lmask), "d" (hmask), "0" (err) - : "memory"); + XSTATE_OP(XRSTOR, xstate, lmask, hmask, err); /* We should never fault when copying from a kernel buffer: */ WARN_ON_FPU(err); @@ -389,12 +387,10 @@ static inline int copy_xregs_to_user(struct xregs_state __user *buf) if (unlikely(err)) return -EFAULT; - __asm__ __volatile__(ASM_STAC "\n" - "1:"XSAVE"\n" - "2: " ASM_CLAC "\n" - xstate_fault(err) - : "D" (buf), "a" (-1), "d" (-1), "0" (err) - : "memory"); + stac(); + XSTATE_OP(XSAVE, buf, -1, -1, err); + clac(); + return err; } @@ -406,14 +402,12 @@ static inline int copy_user_to_xregs(struct xregs_state __user *buf, u64 mask) struct xregs_state *xstate = ((__force struct xregs_state *)buf); u32 lmask = mask; u32 hmask = mask >> 32; - int err = 0; + int err; + + stac(); + XSTATE_OP(XRSTOR, xstate, lmask, hmask, err); + clac(); - __asm__ __volatile__(ASM_STAC "\n" - "1:"XRSTOR"\n" - "2: " ASM_CLAC "\n" - xstate_fault(err) - : "D" (xstate), "a" (lmask), "d" (hmask), "0" (err) - : "memory"); /* memory required? */ return err; } From d9028f9c58a9ae66ec5d5aebf870d531e62b7ed4 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Sat, 14 Jul 2018 02:26:34 -0700 Subject: [PATCH 089/159] x86/fpu: Get rid of xstate_fault() commit b7106fa0f29f9fd83d2d1905ab690d334ef855c1 upstream Add macros for the alternative XSAVE*/XRSTOR* operations which contain the fault handling and use them. Kill xstate_fault(). Also, copy_xregs_to_kernel() didn't have the extended state as memory reference in the asm. Signed-off-by: Borislav Petkov Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Dave Hansen Cc: Denys Vlasenko Cc: Fenghua Yu Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Oleg Nesterov Cc: Peter Zijlstra Cc: Quentin Casasnovas Cc: Rik van Riel Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1447932326-4371-3-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar Signed-off-by: Srivatsa S. Bhat Reviewed-by: Matt Helsley (VMware) Reviewed-by: Alexey Makhalov Reviewed-by: Bo Gan Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/fpu/internal.h | 105 ++++++++++++++-------------- 1 file changed, 52 insertions(+), 53 deletions(-) diff --git a/arch/x86/include/asm/fpu/internal.h b/arch/x86/include/asm/fpu/internal.h index 839e7b649070..60c984ab526a 100644 --- a/arch/x86/include/asm/fpu/internal.h +++ b/arch/x86/include/asm/fpu/internal.h @@ -225,19 +225,6 @@ static inline void copy_fxregs_to_kernel(struct fpu *fpu) #define XRSTOR ".byte " REX_PREFIX "0x0f,0xae,0x2f" #define XRSTORS ".byte " REX_PREFIX "0x0f,0xc7,0x1f" -/* xstate instruction fault handler: */ -#define xstate_fault(__err) \ - \ - ".section .fixup,\"ax\"\n" \ - \ - "3: movl $-2,%[_err]\n" \ - " jmp 2b\n" \ - \ - ".previous\n" \ - \ - _ASM_EXTABLE(1b, 3b) \ - : [_err] "=r" (__err) - #define XSTATE_OP(op, st, lmask, hmask, err) \ asm volatile("1:" op "\n\t" \ "xor %[err], %[err]\n" \ @@ -251,6 +238,54 @@ static inline void copy_fxregs_to_kernel(struct fpu *fpu) : "D" (st), "m" (*st), "a" (lmask), "d" (hmask) \ : "memory") +/* + * If XSAVES is enabled, it replaces XSAVEOPT because it supports a compact + * format and supervisor states in addition to modified optimization in + * XSAVEOPT. + * + * Otherwise, if XSAVEOPT is enabled, XSAVEOPT replaces XSAVE because XSAVEOPT + * supports modified optimization which is not supported by XSAVE. + * + * We use XSAVE as a fallback. + * + * The 661 label is defined in the ALTERNATIVE* macros as the address of the + * original instruction which gets replaced. We need to use it here as the + * address of the instruction where we might get an exception at. + */ +#define XSTATE_XSAVE(st, lmask, hmask, err) \ + asm volatile(ALTERNATIVE_2(XSAVE, \ + XSAVEOPT, X86_FEATURE_XSAVEOPT, \ + XSAVES, X86_FEATURE_XSAVES) \ + "\n" \ + "xor %[err], %[err]\n" \ + "3:\n" \ + ".pushsection .fixup,\"ax\"\n" \ + "4: movl $-2, %[err]\n" \ + "jmp 3b\n" \ + ".popsection\n" \ + _ASM_EXTABLE(661b, 4b) \ + : [err] "=r" (err) \ + : "D" (st), "m" (*st), "a" (lmask), "d" (hmask) \ + : "memory") + +/* + * Use XRSTORS to restore context if it is enabled. XRSTORS supports compact + * XSAVE area format. + */ +#define XSTATE_XRESTORE(st, lmask, hmask, err) \ + asm volatile(ALTERNATIVE(XRSTOR, \ + XRSTORS, X86_FEATURE_XSAVES) \ + "\n" \ + "xor %[err], %[err]\n" \ + "3:\n" \ + ".pushsection .fixup,\"ax\"\n" \ + "4: movl $-2, %[err]\n" \ + "jmp 3b\n" \ + ".popsection\n" \ + _ASM_EXTABLE(661b, 4b) \ + : [err] "=r" (err) \ + : "D" (st), "m" (*st), "a" (lmask), "d" (hmask) \ + : "memory") /* * This function is called only during boot time when x86 caps are not set @@ -304,33 +339,11 @@ static inline void copy_xregs_to_kernel(struct xregs_state *xstate) u64 mask = -1; u32 lmask = mask; u32 hmask = mask >> 32; - int err = 0; + int err; WARN_ON(!alternatives_patched); - /* - * If xsaves is enabled, xsaves replaces xsaveopt because - * it supports compact format and supervisor states in addition to - * modified optimization in xsaveopt. - * - * Otherwise, if xsaveopt is enabled, xsaveopt replaces xsave - * because xsaveopt supports modified optimization which is not - * supported by xsave. - * - * If none of xsaves and xsaveopt is enabled, use xsave. - */ - alternative_input_2( - "1:"XSAVE, - XSAVEOPT, - X86_FEATURE_XSAVEOPT, - XSAVES, - X86_FEATURE_XSAVES, - [xstate] "D" (xstate), "a" (lmask), "d" (hmask) : - "memory"); - asm volatile("2:\n\t" - xstate_fault(err) - : "0" (err) - : "memory"); + XSTATE_XSAVE(xstate, lmask, hmask, err); /* We should never fault when copying to a kernel buffer: */ WARN_ON_FPU(err); @@ -343,23 +356,9 @@ static inline void copy_kernel_to_xregs(struct xregs_state *xstate, u64 mask) { u32 lmask = mask; u32 hmask = mask >> 32; - int err = 0; + int err; - /* - * Use xrstors to restore context if it is enabled. xrstors supports - * compacted format of xsave area which is not supported by xrstor. - */ - alternative_input( - "1: " XRSTOR, - XRSTORS, - X86_FEATURE_XSAVES, - "D" (xstate), "m" (*xstate), "a" (lmask), "d" (hmask) - : "memory"); - - asm volatile("2:\n" - xstate_fault(err) - : "0" (err) - : "memory"); + XSTATE_XRESTORE(xstate, lmask, hmask, err); /* We should never fault when copying from a kernel buffer: */ WARN_ON_FPU(err); From 4307cf43911180477e15c6f1cceed0460428efae Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Sat, 14 Jul 2018 02:26:43 -0700 Subject: [PATCH 090/159] x86/headers: Don't include asm/processor.h in asm/atomic.h commit 153a4334c439cfb62e1d31cee0c790ba4157813d upstream asm/atomic.h doesn't really need asm/processor.h anymore. Everything it uses has moved to other header files. So remove that include. processor.h is a nasty header that includes lots of other headers and makes it prone to include loops. Removing the include here makes asm/atomic.h a "leaf" header that can be safely included in most other headers. The only fallout is in the lib/atomic tester which relied on this implicit include. Give it an explicit include. (the include is in ifdef because the user is also in ifdef) Signed-off-by: Andi Kleen Signed-off-by: Peter Zijlstra (Intel) Cc: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: Linus Torvalds Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Thomas Gleixner Cc: Vince Weaver Cc: rostedt@goodmis.org Link: http://lkml.kernel.org/r/1449018060-1742-1-git-send-email-andi@firstfloor.org Signed-off-by: Ingo Molnar Signed-off-by: Srivatsa S. Bhat Reviewed-by: Matt Helsley (VMware) Reviewed-by: Alexey Makhalov Reviewed-by: Bo Gan Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/atomic.h | 1 - arch/x86/include/asm/atomic64_32.h | 1 - lib/atomic64_test.c | 4 ++++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/atomic.h b/arch/x86/include/asm/atomic.h index ae5fb83e6d91..3e8674288198 100644 --- a/arch/x86/include/asm/atomic.h +++ b/arch/x86/include/asm/atomic.h @@ -3,7 +3,6 @@ #include #include -#include #include #include #include diff --git a/arch/x86/include/asm/atomic64_32.h b/arch/x86/include/asm/atomic64_32.h index a11c30b77fb5..a984111135b1 100644 --- a/arch/x86/include/asm/atomic64_32.h +++ b/arch/x86/include/asm/atomic64_32.h @@ -3,7 +3,6 @@ #include #include -#include //#include /* An 64bit atomic type */ diff --git a/lib/atomic64_test.c b/lib/atomic64_test.c index 83c33a5bcffb..d51e25aa5f1d 100644 --- a/lib/atomic64_test.c +++ b/lib/atomic64_test.c @@ -16,6 +16,10 @@ #include #include +#ifdef CONFIG_X86 +#include /* for boot_cpu_has below */ +#endif + #define TEST(bit, op, c_op, val) \ do { \ atomic##bit##_set(&v, v0); \ From 7b2330a33983f103327f929189ef9c8f935d9f0c Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Sat, 14 Jul 2018 02:26:52 -0700 Subject: [PATCH 091/159] x86/cpufeature: Carve out X86_FEATURE_* commit cd4d09ec6f6c12a2cc3db5b7d8876a325a53545b upstream Move them to a separate header and have the following dependency: x86/cpufeatures.h <- x86/processor.h <- x86/cpufeature.h This makes it easier to use the header in asm code and not include the whole cpufeature.h and add guards for asm. Suggested-by: H. Peter Anvin Signed-off-by: Borislav Petkov Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1453842730-28463-5-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar Signed-off-by: Srivatsa S. Bhat Reviewed-by: Matt Helsley (VMware) Reviewed-by: Alexey Makhalov Reviewed-by: Bo Gan Signed-off-by: Greg Kroah-Hartman --- Documentation/kernel-parameters.txt | 2 +- arch/x86/boot/cpuflags.h | 2 +- arch/x86/boot/mkcpustr.c | 2 +- arch/x86/crypto/crc32-pclmul_glue.c | 2 +- arch/x86/crypto/crc32c-intel_glue.c | 2 +- arch/x86/crypto/crct10dif-pclmul_glue.c | 2 +- arch/x86/entry/common.c | 1 + arch/x86/entry/entry_32.S | 2 +- arch/x86/entry/vdso/vdso32-setup.c | 1 - arch/x86/entry/vdso/vdso32/system_call.S | 2 +- arch/x86/entry/vdso/vma.c | 1 + arch/x86/include/asm/alternative.h | 6 - arch/x86/include/asm/apic.h | 1 - arch/x86/include/asm/arch_hweight.h | 2 + arch/x86/include/asm/cmpxchg.h | 1 + arch/x86/include/asm/cpufeature.h | 293 +--------------------- arch/x86/include/asm/cpufeatures.h | 297 +++++++++++++++++++++++ arch/x86/include/asm/fpu/internal.h | 1 + arch/x86/include/asm/irq_work.h | 2 +- arch/x86/include/asm/mwait.h | 2 + arch/x86/include/asm/nospec-branch.h | 2 +- arch/x86/include/asm/processor.h | 3 +- arch/x86/include/asm/smap.h | 2 +- arch/x86/include/asm/smp.h | 1 - arch/x86/include/asm/thread_info.h | 2 +- arch/x86/include/asm/tlbflush.h | 1 + arch/x86/include/asm/uaccess_64.h | 2 +- arch/x86/kernel/cpu/Makefile | 2 +- arch/x86/kernel/cpu/centaur.c | 2 +- arch/x86/kernel/cpu/cyrix.c | 1 + arch/x86/kernel/cpu/intel.c | 2 +- arch/x86/kernel/cpu/intel_cacheinfo.c | 2 +- arch/x86/kernel/cpu/match.c | 2 +- arch/x86/kernel/cpu/mkcapflags.sh | 6 +- arch/x86/kernel/cpu/mtrr/main.c | 2 +- arch/x86/kernel/cpu/transmeta.c | 2 +- arch/x86/kernel/e820.c | 1 + arch/x86/kernel/head_32.S | 2 +- arch/x86/kernel/hpet.c | 1 + arch/x86/kernel/msr.c | 2 +- arch/x86/kernel/verify_cpu.S | 2 +- arch/x86/lib/clear_page_64.S | 2 +- arch/x86/lib/copy_page_64.S | 2 +- arch/x86/lib/copy_user_64.S | 2 +- arch/x86/lib/memcpy_64.S | 2 +- arch/x86/lib/memmove_64.S | 2 +- arch/x86/lib/memset_64.S | 2 +- arch/x86/lib/retpoline.S | 2 +- arch/x86/mm/setup_nx.c | 1 + arch/x86/oprofile/op_model_amd.c | 1 - arch/x86/um/asm/barrier.h | 2 +- lib/atomic64_test.c | 2 +- 52 files changed, 347 insertions(+), 339 deletions(-) create mode 100644 arch/x86/include/asm/cpufeatures.h diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 4df6bd7d01ed..e60d0b5809c1 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -652,7 +652,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted. clearcpuid=BITNUM [X86] Disable CPUID feature X for the kernel. See - arch/x86/include/asm/cpufeature.h for the valid bit + arch/x86/include/asm/cpufeatures.h for the valid bit numbers. Note the Linux specific bits are not necessarily stable over kernel options, but the vendor specific ones should be. diff --git a/arch/x86/boot/cpuflags.h b/arch/x86/boot/cpuflags.h index ea97697e51e4..4cb404fd45ce 100644 --- a/arch/x86/boot/cpuflags.h +++ b/arch/x86/boot/cpuflags.h @@ -1,7 +1,7 @@ #ifndef BOOT_CPUFLAGS_H #define BOOT_CPUFLAGS_H -#include +#include #include struct cpu_features { diff --git a/arch/x86/boot/mkcpustr.c b/arch/x86/boot/mkcpustr.c index 637097e66a62..f72498dc90d2 100644 --- a/arch/x86/boot/mkcpustr.c +++ b/arch/x86/boot/mkcpustr.c @@ -17,7 +17,7 @@ #include "../include/asm/required-features.h" #include "../include/asm/disabled-features.h" -#include "../include/asm/cpufeature.h" +#include "../include/asm/cpufeatures.h" #include "../kernel/cpu/capflags.c" int main(void) diff --git a/arch/x86/crypto/crc32-pclmul_glue.c b/arch/x86/crypto/crc32-pclmul_glue.c index 07d2c6c86a54..27226df3f7d8 100644 --- a/arch/x86/crypto/crc32-pclmul_glue.c +++ b/arch/x86/crypto/crc32-pclmul_glue.c @@ -33,7 +33,7 @@ #include #include -#include +#include #include #include diff --git a/arch/x86/crypto/crc32c-intel_glue.c b/arch/x86/crypto/crc32c-intel_glue.c index 15f5c7675d42..715399b14ed7 100644 --- a/arch/x86/crypto/crc32c-intel_glue.c +++ b/arch/x86/crypto/crc32c-intel_glue.c @@ -30,7 +30,7 @@ #include #include -#include +#include #include #include diff --git a/arch/x86/crypto/crct10dif-pclmul_glue.c b/arch/x86/crypto/crct10dif-pclmul_glue.c index a3fcfc97a311..cd4df9322501 100644 --- a/arch/x86/crypto/crct10dif-pclmul_glue.c +++ b/arch/x86/crypto/crct10dif-pclmul_glue.c @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include asmlinkage __u16 crc_t10dif_pcl(__u16 crc, const unsigned char *buf, diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c index b5eb1cca70a0..071582a3b5c0 100644 --- a/arch/x86/entry/common.c +++ b/arch/x86/entry/common.c @@ -27,6 +27,7 @@ #include #include #include +#include #define CREATE_TRACE_POINTS #include diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S index d437f3871e53..49a8c9f7a379 100644 --- a/arch/x86/entry/entry_32.S +++ b/arch/x86/entry/entry_32.S @@ -40,7 +40,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/x86/entry/vdso/vdso32-setup.c b/arch/x86/entry/vdso/vdso32-setup.c index a7508d7e20b7..3f9d1a83891a 100644 --- a/arch/x86/entry/vdso/vdso32-setup.c +++ b/arch/x86/entry/vdso/vdso32-setup.c @@ -11,7 +11,6 @@ #include #include -#include #include #include diff --git a/arch/x86/entry/vdso/vdso32/system_call.S b/arch/x86/entry/vdso/vdso32/system_call.S index 3a1d9297074b..0109ac6cb79c 100644 --- a/arch/x86/entry/vdso/vdso32/system_call.S +++ b/arch/x86/entry/vdso/vdso32/system_call.S @@ -3,7 +3,7 @@ */ #include -#include +#include #include /* diff --git a/arch/x86/entry/vdso/vma.c b/arch/x86/entry/vdso/vma.c index b8f69e264ac4..5471ac362147 100644 --- a/arch/x86/entry/vdso/vma.c +++ b/arch/x86/entry/vdso/vma.c @@ -20,6 +20,7 @@ #include #include #include +#include #if defined(CONFIG_X86_64) unsigned int __read_mostly vdso64_enabled = 1; diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h index 215ea9214215..002fcd901f07 100644 --- a/arch/x86/include/asm/alternative.h +++ b/arch/x86/include/asm/alternative.h @@ -153,12 +153,6 @@ static inline int alternatives_text_reserved(void *start, void *end) ALTINSTR_REPLACEMENT(newinstr2, feature2, 2) \ ".popsection\n" -/* - * This must be included *after* the definition of ALTERNATIVE due to - * - */ -#include - /* * Alternative instructions for different CPU types or capabilities. * diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index 163769d82475..fd810a57ab1b 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -6,7 +6,6 @@ #include #include -#include #include #include #include diff --git a/arch/x86/include/asm/arch_hweight.h b/arch/x86/include/asm/arch_hweight.h index 44f825c80ed5..e7cd63175de4 100644 --- a/arch/x86/include/asm/arch_hweight.h +++ b/arch/x86/include/asm/arch_hweight.h @@ -1,6 +1,8 @@ #ifndef _ASM_X86_HWEIGHT_H #define _ASM_X86_HWEIGHT_H +#include + #ifdef CONFIG_64BIT /* popcnt %edi, %eax */ #define POPCNT32 ".byte 0xf3,0x0f,0xb8,0xc7" diff --git a/arch/x86/include/asm/cmpxchg.h b/arch/x86/include/asm/cmpxchg.h index ad19841eddfe..9733361fed6f 100644 --- a/arch/x86/include/asm/cmpxchg.h +++ b/arch/x86/include/asm/cmpxchg.h @@ -2,6 +2,7 @@ #define ASM_X86_CMPXCHG_H #include +#include #include /* Provides LOCK_PREFIX */ /* diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 67f917b96651..f62e872e670e 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -1,298 +1,7 @@ -/* - * Defines x86 CPU feature bits - */ #ifndef _ASM_X86_CPUFEATURE_H #define _ASM_X86_CPUFEATURE_H -#ifndef _ASM_X86_REQUIRED_FEATURES_H -#include -#endif - -#ifndef _ASM_X86_DISABLED_FEATURES_H -#include -#endif - -#define NCAPINTS 16 /* N 32-bit words worth of info */ -#define NBUGINTS 1 /* N 32-bit bug flags */ - -/* - * Note: If the comment begins with a quoted string, that string is used - * in /proc/cpuinfo instead of the macro name. If the string is "", - * this feature bit is not displayed in /proc/cpuinfo at all. - */ - -/* Intel-defined CPU features, CPUID level 0x00000001 (edx), word 0 */ -#define X86_FEATURE_FPU ( 0*32+ 0) /* Onboard FPU */ -#define X86_FEATURE_VME ( 0*32+ 1) /* Virtual Mode Extensions */ -#define X86_FEATURE_DE ( 0*32+ 2) /* Debugging Extensions */ -#define X86_FEATURE_PSE ( 0*32+ 3) /* Page Size Extensions */ -#define X86_FEATURE_TSC ( 0*32+ 4) /* Time Stamp Counter */ -#define X86_FEATURE_MSR ( 0*32+ 5) /* Model-Specific Registers */ -#define X86_FEATURE_PAE ( 0*32+ 6) /* Physical Address Extensions */ -#define X86_FEATURE_MCE ( 0*32+ 7) /* Machine Check Exception */ -#define X86_FEATURE_CX8 ( 0*32+ 8) /* CMPXCHG8 instruction */ -#define X86_FEATURE_APIC ( 0*32+ 9) /* Onboard APIC */ -#define X86_FEATURE_SEP ( 0*32+11) /* SYSENTER/SYSEXIT */ -#define X86_FEATURE_MTRR ( 0*32+12) /* Memory Type Range Registers */ -#define X86_FEATURE_PGE ( 0*32+13) /* Page Global Enable */ -#define X86_FEATURE_MCA ( 0*32+14) /* Machine Check Architecture */ -#define X86_FEATURE_CMOV ( 0*32+15) /* CMOV instructions */ - /* (plus FCMOVcc, FCOMI with FPU) */ -#define X86_FEATURE_PAT ( 0*32+16) /* Page Attribute Table */ -#define X86_FEATURE_PSE36 ( 0*32+17) /* 36-bit PSEs */ -#define X86_FEATURE_PN ( 0*32+18) /* Processor serial number */ -#define X86_FEATURE_CLFLUSH ( 0*32+19) /* CLFLUSH instruction */ -#define X86_FEATURE_DS ( 0*32+21) /* "dts" Debug Store */ -#define X86_FEATURE_ACPI ( 0*32+22) /* ACPI via MSR */ -#define X86_FEATURE_MMX ( 0*32+23) /* Multimedia Extensions */ -#define X86_FEATURE_FXSR ( 0*32+24) /* FXSAVE/FXRSTOR, CR4.OSFXSR */ -#define X86_FEATURE_XMM ( 0*32+25) /* "sse" */ -#define X86_FEATURE_XMM2 ( 0*32+26) /* "sse2" */ -#define X86_FEATURE_SELFSNOOP ( 0*32+27) /* "ss" CPU self snoop */ -#define X86_FEATURE_HT ( 0*32+28) /* Hyper-Threading */ -#define X86_FEATURE_ACC ( 0*32+29) /* "tm" Automatic clock control */ -#define X86_FEATURE_IA64 ( 0*32+30) /* IA-64 processor */ -#define X86_FEATURE_PBE ( 0*32+31) /* Pending Break Enable */ - -/* AMD-defined CPU features, CPUID level 0x80000001, word 1 */ -/* Don't duplicate feature flags which are redundant with Intel! */ -#define X86_FEATURE_SYSCALL ( 1*32+11) /* SYSCALL/SYSRET */ -#define X86_FEATURE_MP ( 1*32+19) /* MP Capable. */ -#define X86_FEATURE_NX ( 1*32+20) /* Execute Disable */ -#define X86_FEATURE_MMXEXT ( 1*32+22) /* AMD MMX extensions */ -#define X86_FEATURE_FXSR_OPT ( 1*32+25) /* FXSAVE/FXRSTOR optimizations */ -#define X86_FEATURE_GBPAGES ( 1*32+26) /* "pdpe1gb" GB pages */ -#define X86_FEATURE_RDTSCP ( 1*32+27) /* RDTSCP */ -#define X86_FEATURE_LM ( 1*32+29) /* Long Mode (x86-64) */ -#define X86_FEATURE_3DNOWEXT ( 1*32+30) /* AMD 3DNow! extensions */ -#define X86_FEATURE_3DNOW ( 1*32+31) /* 3DNow! */ - -/* Transmeta-defined CPU features, CPUID level 0x80860001, word 2 */ -#define X86_FEATURE_RECOVERY ( 2*32+ 0) /* CPU in recovery mode */ -#define X86_FEATURE_LONGRUN ( 2*32+ 1) /* Longrun power control */ -#define X86_FEATURE_LRTI ( 2*32+ 3) /* LongRun table interface */ - -/* Other features, Linux-defined mapping, word 3 */ -/* This range is used for feature bits which conflict or are synthesized */ -#define X86_FEATURE_CXMMX ( 3*32+ 0) /* Cyrix MMX extensions */ -#define X86_FEATURE_K6_MTRR ( 3*32+ 1) /* AMD K6 nonstandard MTRRs */ -#define X86_FEATURE_CYRIX_ARR ( 3*32+ 2) /* Cyrix ARRs (= MTRRs) */ -#define X86_FEATURE_CENTAUR_MCR ( 3*32+ 3) /* Centaur MCRs (= MTRRs) */ -/* cpu types for specific tunings: */ -#define X86_FEATURE_K8 ( 3*32+ 4) /* "" Opteron, Athlon64 */ -#define X86_FEATURE_K7 ( 3*32+ 5) /* "" Athlon */ -#define X86_FEATURE_P3 ( 3*32+ 6) /* "" P3 */ -#define X86_FEATURE_P4 ( 3*32+ 7) /* "" P4 */ -#define X86_FEATURE_CONSTANT_TSC ( 3*32+ 8) /* TSC ticks at a constant rate */ -#define X86_FEATURE_UP ( 3*32+ 9) /* smp kernel running on up */ -/* free, was #define X86_FEATURE_FXSAVE_LEAK ( 3*32+10) * "" FXSAVE leaks FOP/FIP/FOP */ -#define X86_FEATURE_ARCH_PERFMON ( 3*32+11) /* Intel Architectural PerfMon */ -#define X86_FEATURE_PEBS ( 3*32+12) /* Precise-Event Based Sampling */ -#define X86_FEATURE_BTS ( 3*32+13) /* Branch Trace Store */ -#define X86_FEATURE_SYSCALL32 ( 3*32+14) /* "" syscall in ia32 userspace */ -#define X86_FEATURE_SYSENTER32 ( 3*32+15) /* "" sysenter in ia32 userspace */ -#define X86_FEATURE_REP_GOOD ( 3*32+16) /* rep microcode works well */ -#define X86_FEATURE_MFENCE_RDTSC ( 3*32+17) /* "" Mfence synchronizes RDTSC */ -#define X86_FEATURE_LFENCE_RDTSC ( 3*32+18) /* "" Lfence synchronizes RDTSC */ -/* free, was #define X86_FEATURE_11AP ( 3*32+19) * "" Bad local APIC aka 11AP */ -#define X86_FEATURE_NOPL ( 3*32+20) /* The NOPL (0F 1F) instructions */ -#define X86_FEATURE_ALWAYS ( 3*32+21) /* "" Always-present feature */ -#define X86_FEATURE_XTOPOLOGY ( 3*32+22) /* cpu topology enum extensions */ -#define X86_FEATURE_TSC_RELIABLE ( 3*32+23) /* TSC is known to be reliable */ -#define X86_FEATURE_NONSTOP_TSC ( 3*32+24) /* TSC does not stop in C states */ -/* free, was #define X86_FEATURE_CLFLUSH_MONITOR ( 3*32+25) * "" clflush reqd with monitor */ -#define X86_FEATURE_EXTD_APICID ( 3*32+26) /* has extended APICID (8 bits) */ -#define X86_FEATURE_AMD_DCM ( 3*32+27) /* multi-node processor */ -#define X86_FEATURE_APERFMPERF ( 3*32+28) /* APERFMPERF */ -/* free, was #define X86_FEATURE_EAGER_FPU ( 3*32+29) * "eagerfpu" Non lazy FPU restore */ -#define X86_FEATURE_NONSTOP_TSC_S3 ( 3*32+30) /* TSC doesn't stop in S3 state */ - -/* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */ -#define X86_FEATURE_XMM3 ( 4*32+ 0) /* "pni" SSE-3 */ -#define X86_FEATURE_PCLMULQDQ ( 4*32+ 1) /* PCLMULQDQ instruction */ -#define X86_FEATURE_DTES64 ( 4*32+ 2) /* 64-bit Debug Store */ -#define X86_FEATURE_MWAIT ( 4*32+ 3) /* "monitor" Monitor/Mwait support */ -#define X86_FEATURE_DSCPL ( 4*32+ 4) /* "ds_cpl" CPL Qual. Debug Store */ -#define X86_FEATURE_VMX ( 4*32+ 5) /* Hardware virtualization */ -#define X86_FEATURE_SMX ( 4*32+ 6) /* Safer mode */ -#define X86_FEATURE_EST ( 4*32+ 7) /* Enhanced SpeedStep */ -#define X86_FEATURE_TM2 ( 4*32+ 8) /* Thermal Monitor 2 */ -#define X86_FEATURE_SSSE3 ( 4*32+ 9) /* Supplemental SSE-3 */ -#define X86_FEATURE_CID ( 4*32+10) /* Context ID */ -#define X86_FEATURE_SDBG ( 4*32+11) /* Silicon Debug */ -#define X86_FEATURE_FMA ( 4*32+12) /* Fused multiply-add */ -#define X86_FEATURE_CX16 ( 4*32+13) /* CMPXCHG16B */ -#define X86_FEATURE_XTPR ( 4*32+14) /* Send Task Priority Messages */ -#define X86_FEATURE_PDCM ( 4*32+15) /* Performance Capabilities */ -#define X86_FEATURE_PCID ( 4*32+17) /* Process Context Identifiers */ -#define X86_FEATURE_DCA ( 4*32+18) /* Direct Cache Access */ -#define X86_FEATURE_XMM4_1 ( 4*32+19) /* "sse4_1" SSE-4.1 */ -#define X86_FEATURE_XMM4_2 ( 4*32+20) /* "sse4_2" SSE-4.2 */ -#define X86_FEATURE_X2APIC ( 4*32+21) /* x2APIC */ -#define X86_FEATURE_MOVBE ( 4*32+22) /* MOVBE instruction */ -#define X86_FEATURE_POPCNT ( 4*32+23) /* POPCNT instruction */ -#define X86_FEATURE_TSC_DEADLINE_TIMER ( 4*32+24) /* Tsc deadline timer */ -#define X86_FEATURE_AES ( 4*32+25) /* AES instructions */ -#define X86_FEATURE_XSAVE ( 4*32+26) /* XSAVE/XRSTOR/XSETBV/XGETBV */ -#define X86_FEATURE_OSXSAVE ( 4*32+27) /* "" XSAVE enabled in the OS */ -#define X86_FEATURE_AVX ( 4*32+28) /* Advanced Vector Extensions */ -#define X86_FEATURE_F16C ( 4*32+29) /* 16-bit fp conversions */ -#define X86_FEATURE_RDRAND ( 4*32+30) /* The RDRAND instruction */ -#define X86_FEATURE_HYPERVISOR ( 4*32+31) /* Running on a hypervisor */ - -/* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word 5 */ -#define X86_FEATURE_XSTORE ( 5*32+ 2) /* "rng" RNG present (xstore) */ -#define X86_FEATURE_XSTORE_EN ( 5*32+ 3) /* "rng_en" RNG enabled */ -#define X86_FEATURE_XCRYPT ( 5*32+ 6) /* "ace" on-CPU crypto (xcrypt) */ -#define X86_FEATURE_XCRYPT_EN ( 5*32+ 7) /* "ace_en" on-CPU crypto enabled */ -#define X86_FEATURE_ACE2 ( 5*32+ 8) /* Advanced Cryptography Engine v2 */ -#define X86_FEATURE_ACE2_EN ( 5*32+ 9) /* ACE v2 enabled */ -#define X86_FEATURE_PHE ( 5*32+10) /* PadLock Hash Engine */ -#define X86_FEATURE_PHE_EN ( 5*32+11) /* PHE enabled */ -#define X86_FEATURE_PMM ( 5*32+12) /* PadLock Montgomery Multiplier */ -#define X86_FEATURE_PMM_EN ( 5*32+13) /* PMM enabled */ - -/* More extended AMD flags: CPUID level 0x80000001, ecx, word 6 */ -#define X86_FEATURE_LAHF_LM ( 6*32+ 0) /* LAHF/SAHF in long mode */ -#define X86_FEATURE_CMP_LEGACY ( 6*32+ 1) /* If yes HyperThreading not valid */ -#define X86_FEATURE_SVM ( 6*32+ 2) /* Secure virtual machine */ -#define X86_FEATURE_EXTAPIC ( 6*32+ 3) /* Extended APIC space */ -#define X86_FEATURE_CR8_LEGACY ( 6*32+ 4) /* CR8 in 32-bit mode */ -#define X86_FEATURE_ABM ( 6*32+ 5) /* Advanced bit manipulation */ -#define X86_FEATURE_SSE4A ( 6*32+ 6) /* SSE-4A */ -#define X86_FEATURE_MISALIGNSSE ( 6*32+ 7) /* Misaligned SSE mode */ -#define X86_FEATURE_3DNOWPREFETCH ( 6*32+ 8) /* 3DNow prefetch instructions */ -#define X86_FEATURE_OSVW ( 6*32+ 9) /* OS Visible Workaround */ -#define X86_FEATURE_IBS ( 6*32+10) /* Instruction Based Sampling */ -#define X86_FEATURE_XOP ( 6*32+11) /* extended AVX instructions */ -#define X86_FEATURE_SKINIT ( 6*32+12) /* SKINIT/STGI instructions */ -#define X86_FEATURE_WDT ( 6*32+13) /* Watchdog timer */ -#define X86_FEATURE_LWP ( 6*32+15) /* Light Weight Profiling */ -#define X86_FEATURE_FMA4 ( 6*32+16) /* 4 operands MAC instructions */ -#define X86_FEATURE_TCE ( 6*32+17) /* translation cache extension */ -#define X86_FEATURE_NODEID_MSR ( 6*32+19) /* NodeId MSR */ -#define X86_FEATURE_TBM ( 6*32+21) /* trailing bit manipulations */ -#define X86_FEATURE_TOPOEXT ( 6*32+22) /* topology extensions CPUID leafs */ -#define X86_FEATURE_PERFCTR_CORE ( 6*32+23) /* core performance counter extensions */ -#define X86_FEATURE_PERFCTR_NB ( 6*32+24) /* NB performance counter extensions */ -#define X86_FEATURE_BPEXT (6*32+26) /* data breakpoint extension */ -#define X86_FEATURE_PERFCTR_L2 ( 6*32+28) /* L2 performance counter extensions */ -#define X86_FEATURE_MWAITX ( 6*32+29) /* MWAIT extension (MONITORX/MWAITX) */ - -/* - * Auxiliary flags: Linux defined - For features scattered in various - * CPUID levels like 0x6, 0xA etc, word 7. - * - * Reuse free bits when adding new feature flags! - */ - -#define X86_FEATURE_CPB ( 7*32+ 2) /* AMD Core Performance Boost */ -#define X86_FEATURE_EPB ( 7*32+ 3) /* IA32_ENERGY_PERF_BIAS support */ -#define X86_FEATURE_INVPCID_SINGLE ( 7*32+ 4) /* Effectively INVPCID && CR4.PCIDE=1 */ - -#define X86_FEATURE_HW_PSTATE ( 7*32+ 8) /* AMD HW-PState */ -#define X86_FEATURE_PROC_FEEDBACK ( 7*32+ 9) /* AMD ProcFeedbackInterface */ - -#define X86_FEATURE_INTEL_PT ( 7*32+15) /* Intel Processor Trace */ -#define X86_FEATURE_RSB_CTXSW ( 7*32+19) /* Fill RSB on context switches */ - -#define X86_FEATURE_RETPOLINE ( 7*32+29) /* Generic Retpoline mitigation for Spectre variant 2 */ -#define X86_FEATURE_RETPOLINE_AMD ( 7*32+30) /* AMD Retpoline mitigation for Spectre variant 2 */ -/* Because the ALTERNATIVE scheme is for members of the X86_FEATURE club... */ -#define X86_FEATURE_KAISER ( 7*32+31) /* CONFIG_PAGE_TABLE_ISOLATION w/o nokaiser */ - -/* 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 */ -#define X86_FEATURE_FLEXPRIORITY ( 8*32+ 2) /* Intel FlexPriority */ -#define X86_FEATURE_EPT ( 8*32+ 3) /* Intel Extended Page Table */ -#define X86_FEATURE_VPID ( 8*32+ 4) /* Intel Virtual Processor ID */ - -#define X86_FEATURE_VMMCALL ( 8*32+15) /* Prefer vmmcall to vmcall */ -#define X86_FEATURE_XENPV ( 8*32+16) /* "" Xen paravirtual guest */ - - -/* Intel-defined CPU features, CPUID level 0x00000007:0 (ebx), word 9 */ -#define X86_FEATURE_FSGSBASE ( 9*32+ 0) /* {RD/WR}{FS/GS}BASE instructions*/ -#define X86_FEATURE_TSC_ADJUST ( 9*32+ 1) /* TSC adjustment MSR 0x3b */ -#define X86_FEATURE_BMI1 ( 9*32+ 3) /* 1st group bit manipulation extensions */ -#define X86_FEATURE_HLE ( 9*32+ 4) /* Hardware Lock Elision */ -#define X86_FEATURE_AVX2 ( 9*32+ 5) /* AVX2 instructions */ -#define X86_FEATURE_SMEP ( 9*32+ 7) /* Supervisor Mode Execution Protection */ -#define X86_FEATURE_BMI2 ( 9*32+ 8) /* 2nd group bit manipulation extensions */ -#define X86_FEATURE_ERMS ( 9*32+ 9) /* Enhanced REP MOVSB/STOSB */ -#define X86_FEATURE_INVPCID ( 9*32+10) /* Invalidate Processor Context ID */ -#define X86_FEATURE_RTM ( 9*32+11) /* Restricted Transactional Memory */ -#define X86_FEATURE_CQM ( 9*32+12) /* Cache QoS Monitoring */ -#define X86_FEATURE_MPX ( 9*32+14) /* Memory Protection Extension */ -#define X86_FEATURE_AVX512F ( 9*32+16) /* AVX-512 Foundation */ -#define X86_FEATURE_RDSEED ( 9*32+18) /* The RDSEED instruction */ -#define X86_FEATURE_ADX ( 9*32+19) /* The ADCX and ADOX instructions */ -#define X86_FEATURE_SMAP ( 9*32+20) /* Supervisor Mode Access Prevention */ -#define X86_FEATURE_PCOMMIT ( 9*32+22) /* PCOMMIT instruction */ -#define X86_FEATURE_CLFLUSHOPT ( 9*32+23) /* CLFLUSHOPT instruction */ -#define X86_FEATURE_CLWB ( 9*32+24) /* CLWB instruction */ -#define X86_FEATURE_AVX512PF ( 9*32+26) /* AVX-512 Prefetch */ -#define X86_FEATURE_AVX512ER ( 9*32+27) /* AVX-512 Exponential and Reciprocal */ -#define X86_FEATURE_AVX512CD ( 9*32+28) /* AVX-512 Conflict Detection */ -#define X86_FEATURE_SHA_NI ( 9*32+29) /* SHA1/SHA256 Instruction Extensions */ - -/* Extended state features, CPUID level 0x0000000d:1 (eax), word 10 */ -#define X86_FEATURE_XSAVEOPT (10*32+ 0) /* XSAVEOPT */ -#define X86_FEATURE_XSAVEC (10*32+ 1) /* XSAVEC */ -#define X86_FEATURE_XGETBV1 (10*32+ 2) /* XGETBV with ECX = 1 */ -#define X86_FEATURE_XSAVES (10*32+ 3) /* XSAVES/XRSTORS */ - -/* Intel-defined CPU QoS Sub-leaf, CPUID level 0x0000000F:0 (edx), word 11 */ -#define X86_FEATURE_CQM_LLC (11*32+ 1) /* LLC QoS if 1 */ - -/* Intel-defined CPU QoS Sub-leaf, CPUID level 0x0000000F:1 (edx), word 12 */ -#define X86_FEATURE_CQM_OCCUP_LLC (12*32+ 0) /* LLC occupancy monitoring if 1 */ - -/* AMD-defined CPU features, CPUID level 0x80000008 (ebx), word 13 */ -#define X86_FEATURE_CLZERO (13*32+0) /* CLZERO instruction */ - -/* Thermal and Power Management Leaf, CPUID level 0x00000006 (eax), word 14 */ -#define X86_FEATURE_DTHERM (14*32+ 0) /* Digital Thermal Sensor */ -#define X86_FEATURE_IDA (14*32+ 1) /* Intel Dynamic Acceleration */ -#define X86_FEATURE_ARAT (14*32+ 2) /* Always Running APIC Timer */ -#define X86_FEATURE_PLN (14*32+ 4) /* Intel Power Limit Notification */ -#define X86_FEATURE_PTS (14*32+ 6) /* Intel Package Thermal Status */ -#define X86_FEATURE_HWP (14*32+ 7) /* Intel Hardware P-states */ -#define X86_FEATURE_HWP_NOTIFY (14*32+ 8) /* HWP Notification */ -#define X86_FEATURE_HWP_ACT_WINDOW (14*32+ 9) /* HWP Activity Window */ -#define X86_FEATURE_HWP_EPP (14*32+10) /* HWP Energy Perf. Preference */ -#define X86_FEATURE_HWP_PKG_REQ (14*32+11) /* HWP Package Level Request */ - -/* AMD SVM Feature Identification, CPUID level 0x8000000a (edx), word 15 */ -#define X86_FEATURE_NPT (15*32+ 0) /* Nested Page Table support */ -#define X86_FEATURE_LBRV (15*32+ 1) /* LBR Virtualization support */ -#define X86_FEATURE_SVML (15*32+ 2) /* "svm_lock" SVM locking MSR */ -#define X86_FEATURE_NRIPS (15*32+ 3) /* "nrip_save" SVM next_rip save */ -#define X86_FEATURE_TSCRATEMSR (15*32+ 4) /* "tsc_scale" TSC scaling support */ -#define X86_FEATURE_VMCBCLEAN (15*32+ 5) /* "vmcb_clean" VMCB clean bits support */ -#define X86_FEATURE_FLUSHBYASID (15*32+ 6) /* flush-by-ASID support */ -#define X86_FEATURE_DECODEASSISTS (15*32+ 7) /* Decode Assists support */ -#define X86_FEATURE_PAUSEFILTER (15*32+10) /* filtered pause intercept */ -#define X86_FEATURE_PFTHRESHOLD (15*32+12) /* pause filter threshold */ - -/* - * BUG word(s) - */ -#define X86_BUG(x) (NCAPINTS*32 + (x)) - -#define X86_BUG_F00F X86_BUG(0) /* Intel F00F */ -#define X86_BUG_FDIV X86_BUG(1) /* FPU FDIV */ -#define X86_BUG_COMA X86_BUG(2) /* Cyrix 6x86 coma */ -#define X86_BUG_AMD_TLB_MMATCH X86_BUG(3) /* "tlb_mmatch" AMD Erratum 383 */ -#define X86_BUG_AMD_APIC_C1E X86_BUG(4) /* "apic_c1e" AMD Erratum 400 */ -#define X86_BUG_11AP X86_BUG(5) /* Bad local APIC aka 11AP */ -#define X86_BUG_FXSAVE_LEAK X86_BUG(6) /* FXSAVE leaks FOP/FIP/FOP */ -#define X86_BUG_CLFLUSH_MONITOR X86_BUG(7) /* AAI65, CLFLUSH required before MONITOR */ -#define X86_BUG_SYSRET_SS_ATTRS X86_BUG(8) /* SYSRET doesn't fix up SS attrs */ -#define X86_BUG_CPU_MELTDOWN X86_BUG(14) /* CPU is affected by meltdown attack and needs kernel page table isolation */ -#define X86_BUG_SPECTRE_V1 X86_BUG(15) /* CPU is affected by Spectre variant 1 attack with conditional branches */ -#define X86_BUG_SPECTRE_V2 X86_BUG(16) /* CPU is affected by Spectre variant 2 attack with indirect branches */ +#include #if defined(__KERNEL__) && !defined(__ASSEMBLY__) diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h new file mode 100644 index 000000000000..255ea74c52e8 --- /dev/null +++ b/arch/x86/include/asm/cpufeatures.h @@ -0,0 +1,297 @@ +#ifndef _ASM_X86_CPUFEATURES_H +#define _ASM_X86_CPUFEATURES_H + +#ifndef _ASM_X86_REQUIRED_FEATURES_H +#include +#endif + +#ifndef _ASM_X86_DISABLED_FEATURES_H +#include +#endif + +/* + * Defines x86 CPU feature bits + */ +#define NCAPINTS 16 /* N 32-bit words worth of info */ +#define NBUGINTS 1 /* N 32-bit bug flags */ + +/* + * Note: If the comment begins with a quoted string, that string is used + * in /proc/cpuinfo instead of the macro name. If the string is "", + * this feature bit is not displayed in /proc/cpuinfo at all. + */ + +/* Intel-defined CPU features, CPUID level 0x00000001 (edx), word 0 */ +#define X86_FEATURE_FPU ( 0*32+ 0) /* Onboard FPU */ +#define X86_FEATURE_VME ( 0*32+ 1) /* Virtual Mode Extensions */ +#define X86_FEATURE_DE ( 0*32+ 2) /* Debugging Extensions */ +#define X86_FEATURE_PSE ( 0*32+ 3) /* Page Size Extensions */ +#define X86_FEATURE_TSC ( 0*32+ 4) /* Time Stamp Counter */ +#define X86_FEATURE_MSR ( 0*32+ 5) /* Model-Specific Registers */ +#define X86_FEATURE_PAE ( 0*32+ 6) /* Physical Address Extensions */ +#define X86_FEATURE_MCE ( 0*32+ 7) /* Machine Check Exception */ +#define X86_FEATURE_CX8 ( 0*32+ 8) /* CMPXCHG8 instruction */ +#define X86_FEATURE_APIC ( 0*32+ 9) /* Onboard APIC */ +#define X86_FEATURE_SEP ( 0*32+11) /* SYSENTER/SYSEXIT */ +#define X86_FEATURE_MTRR ( 0*32+12) /* Memory Type Range Registers */ +#define X86_FEATURE_PGE ( 0*32+13) /* Page Global Enable */ +#define X86_FEATURE_MCA ( 0*32+14) /* Machine Check Architecture */ +#define X86_FEATURE_CMOV ( 0*32+15) /* CMOV instructions */ + /* (plus FCMOVcc, FCOMI with FPU) */ +#define X86_FEATURE_PAT ( 0*32+16) /* Page Attribute Table */ +#define X86_FEATURE_PSE36 ( 0*32+17) /* 36-bit PSEs */ +#define X86_FEATURE_PN ( 0*32+18) /* Processor serial number */ +#define X86_FEATURE_CLFLUSH ( 0*32+19) /* CLFLUSH instruction */ +#define X86_FEATURE_DS ( 0*32+21) /* "dts" Debug Store */ +#define X86_FEATURE_ACPI ( 0*32+22) /* ACPI via MSR */ +#define X86_FEATURE_MMX ( 0*32+23) /* Multimedia Extensions */ +#define X86_FEATURE_FXSR ( 0*32+24) /* FXSAVE/FXRSTOR, CR4.OSFXSR */ +#define X86_FEATURE_XMM ( 0*32+25) /* "sse" */ +#define X86_FEATURE_XMM2 ( 0*32+26) /* "sse2" */ +#define X86_FEATURE_SELFSNOOP ( 0*32+27) /* "ss" CPU self snoop */ +#define X86_FEATURE_HT ( 0*32+28) /* Hyper-Threading */ +#define X86_FEATURE_ACC ( 0*32+29) /* "tm" Automatic clock control */ +#define X86_FEATURE_IA64 ( 0*32+30) /* IA-64 processor */ +#define X86_FEATURE_PBE ( 0*32+31) /* Pending Break Enable */ + +/* AMD-defined CPU features, CPUID level 0x80000001, word 1 */ +/* Don't duplicate feature flags which are redundant with Intel! */ +#define X86_FEATURE_SYSCALL ( 1*32+11) /* SYSCALL/SYSRET */ +#define X86_FEATURE_MP ( 1*32+19) /* MP Capable. */ +#define X86_FEATURE_NX ( 1*32+20) /* Execute Disable */ +#define X86_FEATURE_MMXEXT ( 1*32+22) /* AMD MMX extensions */ +#define X86_FEATURE_FXSR_OPT ( 1*32+25) /* FXSAVE/FXRSTOR optimizations */ +#define X86_FEATURE_GBPAGES ( 1*32+26) /* "pdpe1gb" GB pages */ +#define X86_FEATURE_RDTSCP ( 1*32+27) /* RDTSCP */ +#define X86_FEATURE_LM ( 1*32+29) /* Long Mode (x86-64) */ +#define X86_FEATURE_3DNOWEXT ( 1*32+30) /* AMD 3DNow! extensions */ +#define X86_FEATURE_3DNOW ( 1*32+31) /* 3DNow! */ + +/* Transmeta-defined CPU features, CPUID level 0x80860001, word 2 */ +#define X86_FEATURE_RECOVERY ( 2*32+ 0) /* CPU in recovery mode */ +#define X86_FEATURE_LONGRUN ( 2*32+ 1) /* Longrun power control */ +#define X86_FEATURE_LRTI ( 2*32+ 3) /* LongRun table interface */ + +/* Other features, Linux-defined mapping, word 3 */ +/* This range is used for feature bits which conflict or are synthesized */ +#define X86_FEATURE_CXMMX ( 3*32+ 0) /* Cyrix MMX extensions */ +#define X86_FEATURE_K6_MTRR ( 3*32+ 1) /* AMD K6 nonstandard MTRRs */ +#define X86_FEATURE_CYRIX_ARR ( 3*32+ 2) /* Cyrix ARRs (= MTRRs) */ +#define X86_FEATURE_CENTAUR_MCR ( 3*32+ 3) /* Centaur MCRs (= MTRRs) */ +/* cpu types for specific tunings: */ +#define X86_FEATURE_K8 ( 3*32+ 4) /* "" Opteron, Athlon64 */ +#define X86_FEATURE_K7 ( 3*32+ 5) /* "" Athlon */ +#define X86_FEATURE_P3 ( 3*32+ 6) /* "" P3 */ +#define X86_FEATURE_P4 ( 3*32+ 7) /* "" P4 */ +#define X86_FEATURE_CONSTANT_TSC ( 3*32+ 8) /* TSC ticks at a constant rate */ +#define X86_FEATURE_UP ( 3*32+ 9) /* smp kernel running on up */ +/* free, was #define X86_FEATURE_FXSAVE_LEAK ( 3*32+10) * "" FXSAVE leaks FOP/FIP/FOP */ +#define X86_FEATURE_ARCH_PERFMON ( 3*32+11) /* Intel Architectural PerfMon */ +#define X86_FEATURE_PEBS ( 3*32+12) /* Precise-Event Based Sampling */ +#define X86_FEATURE_BTS ( 3*32+13) /* Branch Trace Store */ +#define X86_FEATURE_SYSCALL32 ( 3*32+14) /* "" syscall in ia32 userspace */ +#define X86_FEATURE_SYSENTER32 ( 3*32+15) /* "" sysenter in ia32 userspace */ +#define X86_FEATURE_REP_GOOD ( 3*32+16) /* rep microcode works well */ +#define X86_FEATURE_MFENCE_RDTSC ( 3*32+17) /* "" Mfence synchronizes RDTSC */ +#define X86_FEATURE_LFENCE_RDTSC ( 3*32+18) /* "" Lfence synchronizes RDTSC */ +/* free, was #define X86_FEATURE_11AP ( 3*32+19) * "" Bad local APIC aka 11AP */ +#define X86_FEATURE_NOPL ( 3*32+20) /* The NOPL (0F 1F) instructions */ +#define X86_FEATURE_ALWAYS ( 3*32+21) /* "" Always-present feature */ +#define X86_FEATURE_XTOPOLOGY ( 3*32+22) /* cpu topology enum extensions */ +#define X86_FEATURE_TSC_RELIABLE ( 3*32+23) /* TSC is known to be reliable */ +#define X86_FEATURE_NONSTOP_TSC ( 3*32+24) /* TSC does not stop in C states */ +/* free, was #define X86_FEATURE_CLFLUSH_MONITOR ( 3*32+25) * "" clflush reqd with monitor */ +#define X86_FEATURE_EXTD_APICID ( 3*32+26) /* has extended APICID (8 bits) */ +#define X86_FEATURE_AMD_DCM ( 3*32+27) /* multi-node processor */ +#define X86_FEATURE_APERFMPERF ( 3*32+28) /* APERFMPERF */ +/* free, was #define X86_FEATURE_EAGER_FPU ( 3*32+29) * "eagerfpu" Non lazy FPU restore */ +#define X86_FEATURE_NONSTOP_TSC_S3 ( 3*32+30) /* TSC doesn't stop in S3 state */ + +/* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */ +#define X86_FEATURE_XMM3 ( 4*32+ 0) /* "pni" SSE-3 */ +#define X86_FEATURE_PCLMULQDQ ( 4*32+ 1) /* PCLMULQDQ instruction */ +#define X86_FEATURE_DTES64 ( 4*32+ 2) /* 64-bit Debug Store */ +#define X86_FEATURE_MWAIT ( 4*32+ 3) /* "monitor" Monitor/Mwait support */ +#define X86_FEATURE_DSCPL ( 4*32+ 4) /* "ds_cpl" CPL Qual. Debug Store */ +#define X86_FEATURE_VMX ( 4*32+ 5) /* Hardware virtualization */ +#define X86_FEATURE_SMX ( 4*32+ 6) /* Safer mode */ +#define X86_FEATURE_EST ( 4*32+ 7) /* Enhanced SpeedStep */ +#define X86_FEATURE_TM2 ( 4*32+ 8) /* Thermal Monitor 2 */ +#define X86_FEATURE_SSSE3 ( 4*32+ 9) /* Supplemental SSE-3 */ +#define X86_FEATURE_CID ( 4*32+10) /* Context ID */ +#define X86_FEATURE_SDBG ( 4*32+11) /* Silicon Debug */ +#define X86_FEATURE_FMA ( 4*32+12) /* Fused multiply-add */ +#define X86_FEATURE_CX16 ( 4*32+13) /* CMPXCHG16B */ +#define X86_FEATURE_XTPR ( 4*32+14) /* Send Task Priority Messages */ +#define X86_FEATURE_PDCM ( 4*32+15) /* Performance Capabilities */ +#define X86_FEATURE_PCID ( 4*32+17) /* Process Context Identifiers */ +#define X86_FEATURE_DCA ( 4*32+18) /* Direct Cache Access */ +#define X86_FEATURE_XMM4_1 ( 4*32+19) /* "sse4_1" SSE-4.1 */ +#define X86_FEATURE_XMM4_2 ( 4*32+20) /* "sse4_2" SSE-4.2 */ +#define X86_FEATURE_X2APIC ( 4*32+21) /* x2APIC */ +#define X86_FEATURE_MOVBE ( 4*32+22) /* MOVBE instruction */ +#define X86_FEATURE_POPCNT ( 4*32+23) /* POPCNT instruction */ +#define X86_FEATURE_TSC_DEADLINE_TIMER ( 4*32+24) /* Tsc deadline timer */ +#define X86_FEATURE_AES ( 4*32+25) /* AES instructions */ +#define X86_FEATURE_XSAVE ( 4*32+26) /* XSAVE/XRSTOR/XSETBV/XGETBV */ +#define X86_FEATURE_OSXSAVE ( 4*32+27) /* "" XSAVE enabled in the OS */ +#define X86_FEATURE_AVX ( 4*32+28) /* Advanced Vector Extensions */ +#define X86_FEATURE_F16C ( 4*32+29) /* 16-bit fp conversions */ +#define X86_FEATURE_RDRAND ( 4*32+30) /* The RDRAND instruction */ +#define X86_FEATURE_HYPERVISOR ( 4*32+31) /* Running on a hypervisor */ + +/* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word 5 */ +#define X86_FEATURE_XSTORE ( 5*32+ 2) /* "rng" RNG present (xstore) */ +#define X86_FEATURE_XSTORE_EN ( 5*32+ 3) /* "rng_en" RNG enabled */ +#define X86_FEATURE_XCRYPT ( 5*32+ 6) /* "ace" on-CPU crypto (xcrypt) */ +#define X86_FEATURE_XCRYPT_EN ( 5*32+ 7) /* "ace_en" on-CPU crypto enabled */ +#define X86_FEATURE_ACE2 ( 5*32+ 8) /* Advanced Cryptography Engine v2 */ +#define X86_FEATURE_ACE2_EN ( 5*32+ 9) /* ACE v2 enabled */ +#define X86_FEATURE_PHE ( 5*32+10) /* PadLock Hash Engine */ +#define X86_FEATURE_PHE_EN ( 5*32+11) /* PHE enabled */ +#define X86_FEATURE_PMM ( 5*32+12) /* PadLock Montgomery Multiplier */ +#define X86_FEATURE_PMM_EN ( 5*32+13) /* PMM enabled */ + +/* More extended AMD flags: CPUID level 0x80000001, ecx, word 6 */ +#define X86_FEATURE_LAHF_LM ( 6*32+ 0) /* LAHF/SAHF in long mode */ +#define X86_FEATURE_CMP_LEGACY ( 6*32+ 1) /* If yes HyperThreading not valid */ +#define X86_FEATURE_SVM ( 6*32+ 2) /* Secure virtual machine */ +#define X86_FEATURE_EXTAPIC ( 6*32+ 3) /* Extended APIC space */ +#define X86_FEATURE_CR8_LEGACY ( 6*32+ 4) /* CR8 in 32-bit mode */ +#define X86_FEATURE_ABM ( 6*32+ 5) /* Advanced bit manipulation */ +#define X86_FEATURE_SSE4A ( 6*32+ 6) /* SSE-4A */ +#define X86_FEATURE_MISALIGNSSE ( 6*32+ 7) /* Misaligned SSE mode */ +#define X86_FEATURE_3DNOWPREFETCH ( 6*32+ 8) /* 3DNow prefetch instructions */ +#define X86_FEATURE_OSVW ( 6*32+ 9) /* OS Visible Workaround */ +#define X86_FEATURE_IBS ( 6*32+10) /* Instruction Based Sampling */ +#define X86_FEATURE_XOP ( 6*32+11) /* extended AVX instructions */ +#define X86_FEATURE_SKINIT ( 6*32+12) /* SKINIT/STGI instructions */ +#define X86_FEATURE_WDT ( 6*32+13) /* Watchdog timer */ +#define X86_FEATURE_LWP ( 6*32+15) /* Light Weight Profiling */ +#define X86_FEATURE_FMA4 ( 6*32+16) /* 4 operands MAC instructions */ +#define X86_FEATURE_TCE ( 6*32+17) /* translation cache extension */ +#define X86_FEATURE_NODEID_MSR ( 6*32+19) /* NodeId MSR */ +#define X86_FEATURE_TBM ( 6*32+21) /* trailing bit manipulations */ +#define X86_FEATURE_TOPOEXT ( 6*32+22) /* topology extensions CPUID leafs */ +#define X86_FEATURE_PERFCTR_CORE ( 6*32+23) /* core performance counter extensions */ +#define X86_FEATURE_PERFCTR_NB ( 6*32+24) /* NB performance counter extensions */ +#define X86_FEATURE_BPEXT (6*32+26) /* data breakpoint extension */ +#define X86_FEATURE_PERFCTR_L2 ( 6*32+28) /* L2 performance counter extensions */ +#define X86_FEATURE_MWAITX ( 6*32+29) /* MWAIT extension (MONITORX/MWAITX) */ + +/* + * Auxiliary flags: Linux defined - For features scattered in various + * CPUID levels like 0x6, 0xA etc, word 7. + * + * Reuse free bits when adding new feature flags! + */ + +#define X86_FEATURE_CPB ( 7*32+ 2) /* AMD Core Performance Boost */ +#define X86_FEATURE_EPB ( 7*32+ 3) /* IA32_ENERGY_PERF_BIAS support */ +#define X86_FEATURE_INVPCID_SINGLE ( 7*32+ 4) /* Effectively INVPCID && CR4.PCIDE=1 */ + +#define X86_FEATURE_HW_PSTATE ( 7*32+ 8) /* AMD HW-PState */ +#define X86_FEATURE_PROC_FEEDBACK ( 7*32+ 9) /* AMD ProcFeedbackInterface */ + +#define X86_FEATURE_INTEL_PT ( 7*32+15) /* Intel Processor Trace */ +#define X86_FEATURE_RSB_CTXSW ( 7*32+19) /* Fill RSB on context switches */ + +#define X86_FEATURE_RETPOLINE ( 7*32+29) /* Generic Retpoline mitigation for Spectre variant 2 */ +#define X86_FEATURE_RETPOLINE_AMD ( 7*32+30) /* AMD Retpoline mitigation for Spectre variant 2 */ +/* Because the ALTERNATIVE scheme is for members of the X86_FEATURE club... */ +#define X86_FEATURE_KAISER ( 7*32+31) /* CONFIG_PAGE_TABLE_ISOLATION w/o nokaiser */ + +/* 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 */ +#define X86_FEATURE_FLEXPRIORITY ( 8*32+ 2) /* Intel FlexPriority */ +#define X86_FEATURE_EPT ( 8*32+ 3) /* Intel Extended Page Table */ +#define X86_FEATURE_VPID ( 8*32+ 4) /* Intel Virtual Processor ID */ + +#define X86_FEATURE_VMMCALL ( 8*32+15) /* Prefer vmmcall to vmcall */ +#define X86_FEATURE_XENPV ( 8*32+16) /* "" Xen paravirtual guest */ + + +/* Intel-defined CPU features, CPUID level 0x00000007:0 (ebx), word 9 */ +#define X86_FEATURE_FSGSBASE ( 9*32+ 0) /* {RD/WR}{FS/GS}BASE instructions*/ +#define X86_FEATURE_TSC_ADJUST ( 9*32+ 1) /* TSC adjustment MSR 0x3b */ +#define X86_FEATURE_BMI1 ( 9*32+ 3) /* 1st group bit manipulation extensions */ +#define X86_FEATURE_HLE ( 9*32+ 4) /* Hardware Lock Elision */ +#define X86_FEATURE_AVX2 ( 9*32+ 5) /* AVX2 instructions */ +#define X86_FEATURE_SMEP ( 9*32+ 7) /* Supervisor Mode Execution Protection */ +#define X86_FEATURE_BMI2 ( 9*32+ 8) /* 2nd group bit manipulation extensions */ +#define X86_FEATURE_ERMS ( 9*32+ 9) /* Enhanced REP MOVSB/STOSB */ +#define X86_FEATURE_INVPCID ( 9*32+10) /* Invalidate Processor Context ID */ +#define X86_FEATURE_RTM ( 9*32+11) /* Restricted Transactional Memory */ +#define X86_FEATURE_CQM ( 9*32+12) /* Cache QoS Monitoring */ +#define X86_FEATURE_MPX ( 9*32+14) /* Memory Protection Extension */ +#define X86_FEATURE_AVX512F ( 9*32+16) /* AVX-512 Foundation */ +#define X86_FEATURE_RDSEED ( 9*32+18) /* The RDSEED instruction */ +#define X86_FEATURE_ADX ( 9*32+19) /* The ADCX and ADOX instructions */ +#define X86_FEATURE_SMAP ( 9*32+20) /* Supervisor Mode Access Prevention */ +#define X86_FEATURE_PCOMMIT ( 9*32+22) /* PCOMMIT instruction */ +#define X86_FEATURE_CLFLUSHOPT ( 9*32+23) /* CLFLUSHOPT instruction */ +#define X86_FEATURE_CLWB ( 9*32+24) /* CLWB instruction */ +#define X86_FEATURE_AVX512PF ( 9*32+26) /* AVX-512 Prefetch */ +#define X86_FEATURE_AVX512ER ( 9*32+27) /* AVX-512 Exponential and Reciprocal */ +#define X86_FEATURE_AVX512CD ( 9*32+28) /* AVX-512 Conflict Detection */ +#define X86_FEATURE_SHA_NI ( 9*32+29) /* SHA1/SHA256 Instruction Extensions */ + +/* Extended state features, CPUID level 0x0000000d:1 (eax), word 10 */ +#define X86_FEATURE_XSAVEOPT (10*32+ 0) /* XSAVEOPT */ +#define X86_FEATURE_XSAVEC (10*32+ 1) /* XSAVEC */ +#define X86_FEATURE_XGETBV1 (10*32+ 2) /* XGETBV with ECX = 1 */ +#define X86_FEATURE_XSAVES (10*32+ 3) /* XSAVES/XRSTORS */ + +/* Intel-defined CPU QoS Sub-leaf, CPUID level 0x0000000F:0 (edx), word 11 */ +#define X86_FEATURE_CQM_LLC (11*32+ 1) /* LLC QoS if 1 */ + +/* Intel-defined CPU QoS Sub-leaf, CPUID level 0x0000000F:1 (edx), word 12 */ +#define X86_FEATURE_CQM_OCCUP_LLC (12*32+ 0) /* LLC occupancy monitoring if 1 */ + +/* AMD-defined CPU features, CPUID level 0x80000008 (ebx), word 13 */ +#define X86_FEATURE_CLZERO (13*32+0) /* CLZERO instruction */ + +/* Thermal and Power Management Leaf, CPUID level 0x00000006 (eax), word 14 */ +#define X86_FEATURE_DTHERM (14*32+ 0) /* Digital Thermal Sensor */ +#define X86_FEATURE_IDA (14*32+ 1) /* Intel Dynamic Acceleration */ +#define X86_FEATURE_ARAT (14*32+ 2) /* Always Running APIC Timer */ +#define X86_FEATURE_PLN (14*32+ 4) /* Intel Power Limit Notification */ +#define X86_FEATURE_PTS (14*32+ 6) /* Intel Package Thermal Status */ +#define X86_FEATURE_HWP (14*32+ 7) /* Intel Hardware P-states */ +#define X86_FEATURE_HWP_NOTIFY (14*32+ 8) /* HWP Notification */ +#define X86_FEATURE_HWP_ACT_WINDOW (14*32+ 9) /* HWP Activity Window */ +#define X86_FEATURE_HWP_EPP (14*32+10) /* HWP Energy Perf. Preference */ +#define X86_FEATURE_HWP_PKG_REQ (14*32+11) /* HWP Package Level Request */ + +/* AMD SVM Feature Identification, CPUID level 0x8000000a (edx), word 15 */ +#define X86_FEATURE_NPT (15*32+ 0) /* Nested Page Table support */ +#define X86_FEATURE_LBRV (15*32+ 1) /* LBR Virtualization support */ +#define X86_FEATURE_SVML (15*32+ 2) /* "svm_lock" SVM locking MSR */ +#define X86_FEATURE_NRIPS (15*32+ 3) /* "nrip_save" SVM next_rip save */ +#define X86_FEATURE_TSCRATEMSR (15*32+ 4) /* "tsc_scale" TSC scaling support */ +#define X86_FEATURE_VMCBCLEAN (15*32+ 5) /* "vmcb_clean" VMCB clean bits support */ +#define X86_FEATURE_FLUSHBYASID (15*32+ 6) /* flush-by-ASID support */ +#define X86_FEATURE_DECODEASSISTS (15*32+ 7) /* Decode Assists support */ +#define X86_FEATURE_PAUSEFILTER (15*32+10) /* filtered pause intercept */ +#define X86_FEATURE_PFTHRESHOLD (15*32+12) /* pause filter threshold */ + +/* + * BUG word(s) + */ +#define X86_BUG(x) (NCAPINTS*32 + (x)) + +#define X86_BUG_F00F X86_BUG(0) /* Intel F00F */ +#define X86_BUG_FDIV X86_BUG(1) /* FPU FDIV */ +#define X86_BUG_COMA X86_BUG(2) /* Cyrix 6x86 coma */ +#define X86_BUG_AMD_TLB_MMATCH X86_BUG(3) /* "tlb_mmatch" AMD Erratum 383 */ +#define X86_BUG_AMD_APIC_C1E X86_BUG(4) /* "apic_c1e" AMD Erratum 400 */ +#define X86_BUG_11AP X86_BUG(5) /* Bad local APIC aka 11AP */ +#define X86_BUG_FXSAVE_LEAK X86_BUG(6) /* FXSAVE leaks FOP/FIP/FOP */ +#define X86_BUG_CLFLUSH_MONITOR X86_BUG(7) /* AAI65, CLFLUSH required before MONITOR */ +#define X86_BUG_SYSRET_SS_ATTRS X86_BUG(8) /* SYSRET doesn't fix up SS attrs */ +#define X86_BUG_CPU_MELTDOWN X86_BUG(14) /* CPU is affected by meltdown attack and needs kernel page table isolation */ +#define X86_BUG_SPECTRE_V1 X86_BUG(15) /* CPU is affected by Spectre variant 1 attack with conditional branches */ +#define X86_BUG_SPECTRE_V2 X86_BUG(16) /* CPU is affected by Spectre variant 2 attack with indirect branches */ + +#endif /* _ASM_X86_CPUFEATURES_H */ diff --git a/arch/x86/include/asm/fpu/internal.h b/arch/x86/include/asm/fpu/internal.h index 60c984ab526a..94e7570b1e1c 100644 --- a/arch/x86/include/asm/fpu/internal.h +++ b/arch/x86/include/asm/fpu/internal.h @@ -17,6 +17,7 @@ #include #include #include +#include /* * High level FPU state handling functions: diff --git a/arch/x86/include/asm/irq_work.h b/arch/x86/include/asm/irq_work.h index 78162f8e248b..d0afb05c84fc 100644 --- a/arch/x86/include/asm/irq_work.h +++ b/arch/x86/include/asm/irq_work.h @@ -1,7 +1,7 @@ #ifndef _ASM_IRQ_WORK_H #define _ASM_IRQ_WORK_H -#include +#include static inline bool arch_irq_work_has_interrupt(void) { diff --git a/arch/x86/include/asm/mwait.h b/arch/x86/include/asm/mwait.h index c70689b5e5aa..0deeb2d26df7 100644 --- a/arch/x86/include/asm/mwait.h +++ b/arch/x86/include/asm/mwait.h @@ -3,6 +3,8 @@ #include +#include + #define MWAIT_SUBSTATE_MASK 0xf #define MWAIT_CSTATE_MASK 0xf #define MWAIT_SUBSTATE_SIZE 4 diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h index 249f1c769f21..8b910416243c 100644 --- a/arch/x86/include/asm/nospec-branch.h +++ b/arch/x86/include/asm/nospec-branch.h @@ -5,7 +5,7 @@ #include #include -#include +#include /* * Fill the CPU return stack buffer. diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 9e77cea2a8ef..8e415cf65457 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -13,7 +13,7 @@ struct vm86; #include #include #include -#include +#include #include #include #include @@ -24,7 +24,6 @@ struct vm86; #include #include -#include #include #include #include diff --git a/arch/x86/include/asm/smap.h b/arch/x86/include/asm/smap.h index ba665ebd17bb..db333300bd4b 100644 --- a/arch/x86/include/asm/smap.h +++ b/arch/x86/include/asm/smap.h @@ -15,7 +15,7 @@ #include #include -#include +#include /* "Raw" instruction opcodes */ #define __ASM_CLAC .byte 0x0f,0x01,0xca diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h index a438c5598a90..04d6eef5f8a5 100644 --- a/arch/x86/include/asm/smp.h +++ b/arch/x86/include/asm/smp.h @@ -16,7 +16,6 @@ #endif #include #include -#include extern int smp_num_siblings; extern unsigned int num_processors; diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h index 9b028204685d..18c9aaa8c043 100644 --- a/arch/x86/include/asm/thread_info.h +++ b/arch/x86/include/asm/thread_info.h @@ -49,7 +49,7 @@ */ #ifndef __ASSEMBLY__ struct task_struct; -#include +#include #include struct thread_info { diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h index a691b66cc40a..e2a89d2577fb 100644 --- a/arch/x86/include/asm/tlbflush.h +++ b/arch/x86/include/asm/tlbflush.h @@ -5,6 +5,7 @@ #include #include +#include #include #include diff --git a/arch/x86/include/asm/uaccess_64.h b/arch/x86/include/asm/uaccess_64.h index f2f9b39b274a..d83a55b95a48 100644 --- a/arch/x86/include/asm/uaccess_64.h +++ b/arch/x86/include/asm/uaccess_64.h @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include /* diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile index 8f184615053b..924b65794abd 100644 --- a/arch/x86/kernel/cpu/Makefile +++ b/arch/x86/kernel/cpu/Makefile @@ -62,7 +62,7 @@ ifdef CONFIG_X86_FEATURE_NAMES quiet_cmd_mkcapflags = MKCAP $@ cmd_mkcapflags = $(CONFIG_SHELL) $(srctree)/$(src)/mkcapflags.sh $< $@ -cpufeature = $(src)/../../include/asm/cpufeature.h +cpufeature = $(src)/../../include/asm/cpufeatures.h targets += capflags.c $(obj)/capflags.c: $(cpufeature) $(src)/mkcapflags.sh FORCE diff --git a/arch/x86/kernel/cpu/centaur.c b/arch/x86/kernel/cpu/centaur.c index ae20be6e483c..6608c03c2126 100644 --- a/arch/x86/kernel/cpu/centaur.c +++ b/arch/x86/kernel/cpu/centaur.c @@ -1,7 +1,7 @@ #include #include -#include +#include #include #include #include diff --git a/arch/x86/kernel/cpu/cyrix.c b/arch/x86/kernel/cpu/cyrix.c index aaf152e79637..15e47c1cd412 100644 --- a/arch/x86/kernel/cpu/cyrix.c +++ b/arch/x86/kernel/cpu/cyrix.c @@ -8,6 +8,7 @@ #include #include #include +#include #include "cpu.h" diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index 565648bc1a0a..9299e3bdfad6 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -8,7 +8,7 @@ #include #include -#include +#include #include #include #include diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index 3fa72317ad78..3557b3ceab14 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c @@ -14,7 +14,7 @@ #include #include -#include +#include #include #include diff --git a/arch/x86/kernel/cpu/match.c b/arch/x86/kernel/cpu/match.c index afa9f0d487ea..fbb5e90557a5 100644 --- a/arch/x86/kernel/cpu/match.c +++ b/arch/x86/kernel/cpu/match.c @@ -1,5 +1,5 @@ #include -#include +#include #include #include #include diff --git a/arch/x86/kernel/cpu/mkcapflags.sh b/arch/x86/kernel/cpu/mkcapflags.sh index 3f20710a5b23..6988c74409a8 100644 --- a/arch/x86/kernel/cpu/mkcapflags.sh +++ b/arch/x86/kernel/cpu/mkcapflags.sh @@ -1,6 +1,6 @@ #!/bin/sh # -# Generate the x86_cap/bug_flags[] arrays from include/asm/cpufeature.h +# Generate the x86_cap/bug_flags[] arrays from include/asm/cpufeatures.h # IN=$1 @@ -49,8 +49,8 @@ dump_array() trap 'rm "$OUT"' EXIT ( - echo "#ifndef _ASM_X86_CPUFEATURE_H" - echo "#include " + echo "#ifndef _ASM_X86_CPUFEATURES_H" + echo "#include " echo "#endif" echo "" diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c index f924f41af89a..49bd700d9b7f 100644 --- a/arch/x86/kernel/cpu/mtrr/main.c +++ b/arch/x86/kernel/cpu/mtrr/main.c @@ -47,7 +47,7 @@ #include #include -#include +#include #include #include #include diff --git a/arch/x86/kernel/cpu/transmeta.c b/arch/x86/kernel/cpu/transmeta.c index 252da7aceca6..a19a663282b5 100644 --- a/arch/x86/kernel/cpu/transmeta.c +++ b/arch/x86/kernel/cpu/transmeta.c @@ -1,6 +1,6 @@ #include #include -#include +#include #include #include "cpu.h" diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index 52a2526c3fbe..19bc19d5e174 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c @@ -24,6 +24,7 @@ #include #include #include +#include /* * The e820 map is the map that gets modified e.g. with command line parameters diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S index 70284d38fdc2..1c0b49fd6365 100644 --- a/arch/x86/kernel/head_32.S +++ b/arch/x86/kernel/head_32.S @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index f48eb8eeefe2..3fdc1e53aaac 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c @@ -12,6 +12,7 @@ #include #include +#include #include #include #include diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c index 113e70784854..f95ac5d435aa 100644 --- a/arch/x86/kernel/msr.c +++ b/arch/x86/kernel/msr.c @@ -40,7 +40,7 @@ #include #include -#include +#include #include static struct class *msr_class; diff --git a/arch/x86/kernel/verify_cpu.S b/arch/x86/kernel/verify_cpu.S index 4cf401f581e7..b7c9db5deebe 100644 --- a/arch/x86/kernel/verify_cpu.S +++ b/arch/x86/kernel/verify_cpu.S @@ -30,7 +30,7 @@ * appropriately. Either display a message or halt. */ -#include +#include #include verify_cpu: diff --git a/arch/x86/lib/clear_page_64.S b/arch/x86/lib/clear_page_64.S index a2fe51b00cce..65be7cfaf947 100644 --- a/arch/x86/lib/clear_page_64.S +++ b/arch/x86/lib/clear_page_64.S @@ -1,5 +1,5 @@ #include -#include +#include #include /* diff --git a/arch/x86/lib/copy_page_64.S b/arch/x86/lib/copy_page_64.S index 009f98216b7e..24ef1c2104d4 100644 --- a/arch/x86/lib/copy_page_64.S +++ b/arch/x86/lib/copy_page_64.S @@ -1,7 +1,7 @@ /* Written 2003 by Andi Kleen, based on a kernel by Evandro Menezes */ #include -#include +#include #include /* diff --git a/arch/x86/lib/copy_user_64.S b/arch/x86/lib/copy_user_64.S index 423644c230e7..accf7f2f557f 100644 --- a/arch/x86/lib/copy_user_64.S +++ b/arch/x86/lib/copy_user_64.S @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/x86/lib/memcpy_64.S b/arch/x86/lib/memcpy_64.S index 16698bba87de..a0de849435ad 100644 --- a/arch/x86/lib/memcpy_64.S +++ b/arch/x86/lib/memcpy_64.S @@ -1,7 +1,7 @@ /* Copyright 2002 Andi Kleen */ #include -#include +#include #include /* diff --git a/arch/x86/lib/memmove_64.S b/arch/x86/lib/memmove_64.S index ca2afdd6d98e..90ce01bee00c 100644 --- a/arch/x86/lib/memmove_64.S +++ b/arch/x86/lib/memmove_64.S @@ -6,7 +6,7 @@ * - Copyright 2011 Fenghua Yu */ #include -#include +#include #include #undef memmove diff --git a/arch/x86/lib/memset_64.S b/arch/x86/lib/memset_64.S index 2661fad05827..c9c81227ea37 100644 --- a/arch/x86/lib/memset_64.S +++ b/arch/x86/lib/memset_64.S @@ -1,7 +1,7 @@ /* Copyright 2002 Andi Kleen, SuSE Labs */ #include -#include +#include #include .weak memset diff --git a/arch/x86/lib/retpoline.S b/arch/x86/lib/retpoline.S index 3d06b482ebc7..7bbb853e36bd 100644 --- a/arch/x86/lib/retpoline.S +++ b/arch/x86/lib/retpoline.S @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/x86/mm/setup_nx.c b/arch/x86/mm/setup_nx.c index 92e2eacb3321..f65a33f505b6 100644 --- a/arch/x86/mm/setup_nx.c +++ b/arch/x86/mm/setup_nx.c @@ -4,6 +4,7 @@ #include #include +#include static int disable_nx; diff --git a/arch/x86/oprofile/op_model_amd.c b/arch/x86/oprofile/op_model_amd.c index 50d86c0e9ba4..660a83c8287b 100644 --- a/arch/x86/oprofile/op_model_amd.c +++ b/arch/x86/oprofile/op_model_amd.c @@ -24,7 +24,6 @@ #include #include #include -#include #include "op_x86_model.h" #include "op_counter.h" diff --git a/arch/x86/um/asm/barrier.h b/arch/x86/um/asm/barrier.h index 755481f14d90..764ac2fc53fe 100644 --- a/arch/x86/um/asm/barrier.h +++ b/arch/x86/um/asm/barrier.h @@ -3,7 +3,7 @@ #include #include -#include +#include #include #include diff --git a/lib/atomic64_test.c b/lib/atomic64_test.c index d51e25aa5f1d..de67fea3cf46 100644 --- a/lib/atomic64_test.c +++ b/lib/atomic64_test.c @@ -17,7 +17,7 @@ #include #ifdef CONFIG_X86 -#include /* for boot_cpu_has below */ +#include /* for boot_cpu_has below */ #endif #define TEST(bit, op, c_op, val) \ From 2d45dae0af88a2602e37e596fdc69f66497f3bb0 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Sat, 14 Jul 2018 02:27:01 -0700 Subject: [PATCH 092/159] x86/cpufeature: Replace the old static_cpu_has() with safe variant commit bc696ca05f5a8927329ec276a892341e006b00ba upstream So the old one didn't work properly before alternatives had run. And it was supposed to provide an optimized JMP because the assumption was that the offset it is jumping to is within a signed byte and thus a two-byte JMP. So I did an x86_64 allyesconfig build and dumped all possible sites where static_cpu_has() was used. The optimization amounted to all in all 12(!) places where static_cpu_has() had generated a 2-byte JMP. Which has saved us a whopping 36 bytes! This clearly is not worth the trouble so we can remove it. The only place where the optimization might count - in __switch_to() - we will handle differently. But that's not subject of this patch. Signed-off-by: Borislav Petkov Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1453842730-28463-6-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar Signed-off-by: Srivatsa S. Bhat Reviewed-by: Matt Helsley (VMware) Reviewed-by: Alexey Makhalov Reviewed-by: Bo Gan Signed-off-by: Greg Kroah-Hartman --- arch/x86/Kconfig.debug | 10 --- arch/x86/include/asm/cpufeature.h | 100 ++------------------------- arch/x86/include/asm/fpu/internal.h | 12 ++-- arch/x86/kernel/apic/apic_numachip.c | 4 +- arch/x86/kernel/cpu/common.c | 12 +--- arch/x86/kernel/vm86_32.c | 2 +- fs/btrfs/disk-io.c | 2 +- 7 files changed, 19 insertions(+), 123 deletions(-) diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug index da00fe1f48f4..2aa212fb0faf 100644 --- a/arch/x86/Kconfig.debug +++ b/arch/x86/Kconfig.debug @@ -367,16 +367,6 @@ config DEBUG_IMR_SELFTEST If unsure say N here. -config X86_DEBUG_STATIC_CPU_HAS - bool "Debug alternatives" - depends on DEBUG_KERNEL - ---help--- - This option causes additional code to be generated which - fails if static_cpu_has() is used before alternatives have - run. - - If unsure, say N. - config X86_DEBUG_FPU bool "Debug the x86 FPU code" depends on DEBUG_KERNEL diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index f62e872e670e..b60598cd8d6a 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -127,103 +127,19 @@ extern const char * const x86_bug_flags[NBUGINTS*32]; #define cpu_has_osxsave boot_cpu_has(X86_FEATURE_OSXSAVE) #define cpu_has_hypervisor boot_cpu_has(X86_FEATURE_HYPERVISOR) /* - * Do not add any more of those clumsy macros - use static_cpu_has_safe() for + * Do not add any more of those clumsy macros - use static_cpu_has() for * fast paths and boot_cpu_has() otherwise! */ #if __GNUC__ >= 4 && defined(CONFIG_X86_FAST_FEATURE_TESTS) -extern void warn_pre_alternatives(void); -extern bool __static_cpu_has_safe(u16 bit); +extern bool __static_cpu_has(u16 bit); /* * Static testing of CPU features. Used the same as boot_cpu_has(). * These are only valid after alternatives have run, but will statically * patch the target code for additional performance. */ -static __always_inline __pure bool __static_cpu_has(u16 bit) -{ -#ifdef CC_HAVE_ASM_GOTO - -#ifdef CONFIG_X86_DEBUG_STATIC_CPU_HAS - - /* - * Catch too early usage of this before alternatives - * have run. - */ - asm_volatile_goto("1: jmp %l[t_warn]\n" - "2:\n" - ".section .altinstructions,\"a\"\n" - " .long 1b - .\n" - " .long 0\n" /* no replacement */ - " .word %P0\n" /* 1: do replace */ - " .byte 2b - 1b\n" /* source len */ - " .byte 0\n" /* replacement len */ - " .byte 0\n" /* pad len */ - ".previous\n" - /* skipping size check since replacement size = 0 */ - : : "i" (X86_FEATURE_ALWAYS) : : t_warn); - -#endif - - asm_volatile_goto("1: jmp %l[t_no]\n" - "2:\n" - ".section .altinstructions,\"a\"\n" - " .long 1b - .\n" - " .long 0\n" /* no replacement */ - " .word %P0\n" /* feature bit */ - " .byte 2b - 1b\n" /* source len */ - " .byte 0\n" /* replacement len */ - " .byte 0\n" /* pad len */ - ".previous\n" - /* skipping size check since replacement size = 0 */ - : : "i" (bit) : : t_no); - return true; - t_no: - return false; - -#ifdef CONFIG_X86_DEBUG_STATIC_CPU_HAS - t_warn: - warn_pre_alternatives(); - return false; -#endif - -#else /* CC_HAVE_ASM_GOTO */ - - u8 flag; - /* Open-coded due to __stringify() in ALTERNATIVE() */ - asm volatile("1: movb $0,%0\n" - "2:\n" - ".section .altinstructions,\"a\"\n" - " .long 1b - .\n" - " .long 3f - .\n" - " .word %P1\n" /* feature bit */ - " .byte 2b - 1b\n" /* source len */ - " .byte 4f - 3f\n" /* replacement len */ - " .byte 0\n" /* pad len */ - ".previous\n" - ".section .discard,\"aw\",@progbits\n" - " .byte 0xff + (4f-3f) - (2b-1b)\n" /* size check */ - ".previous\n" - ".section .altinstr_replacement,\"ax\"\n" - "3: movb $1,%0\n" - "4:\n" - ".previous\n" - : "=qm" (flag) : "i" (bit)); - return flag; - -#endif /* CC_HAVE_ASM_GOTO */ -} - -#define static_cpu_has(bit) \ -( \ - __builtin_constant_p(boot_cpu_has(bit)) ? \ - boot_cpu_has(bit) : \ - __builtin_constant_p(bit) ? \ - __static_cpu_has(bit) : \ - boot_cpu_has(bit) \ -) - -static __always_inline __pure bool _static_cpu_has_safe(u16 bit) +static __always_inline __pure bool _static_cpu_has(u16 bit) { #ifdef CC_HAVE_ASM_GOTO asm_volatile_goto("1: jmp %l[t_dynamic]\n" @@ -257,7 +173,7 @@ static __always_inline __pure bool _static_cpu_has_safe(u16 bit) t_no: return false; t_dynamic: - return __static_cpu_has_safe(bit); + return __static_cpu_has(bit); #else u8 flag; /* Open-coded due to __stringify() in ALTERNATIVE() */ @@ -295,22 +211,21 @@ static __always_inline __pure bool _static_cpu_has_safe(u16 bit) ".previous\n" : "=qm" (flag) : "i" (bit), "i" (X86_FEATURE_ALWAYS)); - return (flag == 2 ? __static_cpu_has_safe(bit) : flag); + return (flag == 2 ? __static_cpu_has(bit) : flag); #endif /* CC_HAVE_ASM_GOTO */ } -#define static_cpu_has_safe(bit) \ +#define static_cpu_has(bit) \ ( \ __builtin_constant_p(boot_cpu_has(bit)) ? \ boot_cpu_has(bit) : \ - _static_cpu_has_safe(bit) \ + _static_cpu_has(bit) \ ) #else /* * gcc 3.x is too stupid to do the static test; fall back to dynamic. */ #define static_cpu_has(bit) boot_cpu_has(bit) -#define static_cpu_has_safe(bit) boot_cpu_has(bit) #endif #define cpu_has_bug(c, bit) cpu_has(c, (bit)) @@ -318,7 +233,6 @@ static __always_inline __pure bool _static_cpu_has_safe(u16 bit) #define clear_cpu_bug(c, bit) clear_cpu_cap(c, (bit)) #define static_cpu_has_bug(bit) static_cpu_has((bit)) -#define static_cpu_has_bug_safe(bit) static_cpu_has_safe((bit)) #define boot_cpu_has_bug(bit) cpu_has_bug(&boot_cpu_data, (bit)) #define MAX_CPU_FEATURES (NCAPINTS * 32) diff --git a/arch/x86/include/asm/fpu/internal.h b/arch/x86/include/asm/fpu/internal.h index 94e7570b1e1c..ec2aedb6f92a 100644 --- a/arch/x86/include/asm/fpu/internal.h +++ b/arch/x86/include/asm/fpu/internal.h @@ -64,17 +64,17 @@ static __always_inline __pure bool use_eager_fpu(void) static __always_inline __pure bool use_xsaveopt(void) { - return static_cpu_has_safe(X86_FEATURE_XSAVEOPT); + return static_cpu_has(X86_FEATURE_XSAVEOPT); } static __always_inline __pure bool use_xsave(void) { - return static_cpu_has_safe(X86_FEATURE_XSAVE); + return static_cpu_has(X86_FEATURE_XSAVE); } static __always_inline __pure bool use_fxsr(void) { - return static_cpu_has_safe(X86_FEATURE_FXSR); + return static_cpu_has(X86_FEATURE_FXSR); } /* @@ -301,7 +301,7 @@ static inline void copy_xregs_to_kernel_booting(struct xregs_state *xstate) WARN_ON(system_state != SYSTEM_BOOTING); - if (static_cpu_has_safe(X86_FEATURE_XSAVES)) + if (static_cpu_has(X86_FEATURE_XSAVES)) XSTATE_OP(XSAVES, xstate, lmask, hmask, err); else XSTATE_OP(XSAVE, xstate, lmask, hmask, err); @@ -323,7 +323,7 @@ static inline void copy_kernel_to_xregs_booting(struct xregs_state *xstate) WARN_ON(system_state != SYSTEM_BOOTING); - if (static_cpu_has_safe(X86_FEATURE_XSAVES)) + if (static_cpu_has(X86_FEATURE_XSAVES)) XSTATE_OP(XRSTORS, xstate, lmask, hmask, err); else XSTATE_OP(XRSTOR, xstate, lmask, hmask, err); @@ -461,7 +461,7 @@ static inline void copy_kernel_to_fpregs(union fpregs_state *fpstate) * pending. Clear the x87 state here by setting it to fixed values. * "m" is a random variable that should be in L1. */ - if (unlikely(static_cpu_has_bug_safe(X86_BUG_FXSAVE_LEAK))) { + if (unlikely(static_cpu_has_bug(X86_BUG_FXSAVE_LEAK))) { asm volatile( "fnclex\n\t" "emms\n\t" diff --git a/arch/x86/kernel/apic/apic_numachip.c b/arch/x86/kernel/apic/apic_numachip.c index 2bd2292a316d..bac0805ea1d9 100644 --- a/arch/x86/kernel/apic/apic_numachip.c +++ b/arch/x86/kernel/apic/apic_numachip.c @@ -30,7 +30,7 @@ static unsigned int numachip1_get_apic_id(unsigned long x) unsigned long value; unsigned int id = (x >> 24) & 0xff; - if (static_cpu_has_safe(X86_FEATURE_NODEID_MSR)) { + if (static_cpu_has(X86_FEATURE_NODEID_MSR)) { rdmsrl(MSR_FAM10H_NODE_ID, value); id |= (value << 2) & 0xff00; } @@ -178,7 +178,7 @@ static void fixup_cpu_id(struct cpuinfo_x86 *c, int node) this_cpu_write(cpu_llc_id, node); /* Account for nodes per socket in multi-core-module processors */ - if (static_cpu_has_safe(X86_FEATURE_NODEID_MSR)) { + if (static_cpu_has(X86_FEATURE_NODEID_MSR)) { rdmsrl(MSR_FAM10H_NODE_ID, val); nodes = ((val >> 3) & 7) + 1; } diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 5b6e43b4c329..f31b26befca1 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -1576,19 +1576,11 @@ void cpu_init(void) } #endif -#ifdef CONFIG_X86_DEBUG_STATIC_CPU_HAS -void warn_pre_alternatives(void) -{ - WARN(1, "You're using static_cpu_has before alternatives have run!\n"); -} -EXPORT_SYMBOL_GPL(warn_pre_alternatives); -#endif - -inline bool __static_cpu_has_safe(u16 bit) +inline bool __static_cpu_has(u16 bit) { return boot_cpu_has(bit); } -EXPORT_SYMBOL_GPL(__static_cpu_has_safe); +EXPORT_SYMBOL_GPL(__static_cpu_has); static void bsp_resume(void) { diff --git a/arch/x86/kernel/vm86_32.c b/arch/x86/kernel/vm86_32.c index d6d64a519559..7f4839ef3608 100644 --- a/arch/x86/kernel/vm86_32.c +++ b/arch/x86/kernel/vm86_32.c @@ -358,7 +358,7 @@ static long do_sys_vm86(struct vm86plus_struct __user *user_vm86, bool plus) /* make room for real-mode segments */ tsk->thread.sp0 += 16; - if (static_cpu_has_safe(X86_FEATURE_SEP)) + if (static_cpu_has(X86_FEATURE_SEP)) tsk->thread.sysenter_cs = 0; load_sp0(tss, &tsk->thread); diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 7efd70bfeaf7..d106b981d86f 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -923,7 +923,7 @@ static int check_async_write(struct inode *inode, unsigned long bio_flags) if (bio_flags & EXTENT_BIO_TREE_LOG) return 0; #ifdef CONFIG_X86 - if (static_cpu_has_safe(X86_FEATURE_XMM4_2)) + if (static_cpu_has(X86_FEATURE_XMM4_2)) return 0; #endif return 1; From 3f3d81317036b17f2fcdf1d76e55915d4c5b771d Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Sat, 14 Jul 2018 02:27:10 -0700 Subject: [PATCH 093/159] x86/cpufeature: Get rid of the non-asm goto variant commit a362bf9f5e7dd659b96d01382da7b855f4e5a7a1 upstream I can simply quote hpa from the mail: "Get rid of the non-asm goto variant and just fall back to dynamic if asm goto is unavailable. It doesn't make any sense, really, if it is supposed to be safe, and by now the asm goto-capable gcc is in more wide use. (Originally the gcc 3.x fallback to pure dynamic didn't exist, either.)" Booy, am I lazy. Cleanup the whole CC_HAVE_ASM_GOTO ifdeffery too, while at it. Suggested-by: H. Peter Anvin Signed-off-by: Borislav Petkov Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/20160127084325.GB30712@pd.tnic Signed-off-by: Ingo Molnar Signed-off-by: Srivatsa S. Bhat Reviewed-by: Matt Helsley (VMware) Reviewed-by: Alexey Makhalov Reviewed-by: Bo Gan Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/cpufeature.h | 49 ++++--------------------------- 1 file changed, 5 insertions(+), 44 deletions(-) diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index b60598cd8d6a..53de4615e6ba 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -131,17 +131,16 @@ extern const char * const x86_bug_flags[NBUGINTS*32]; * fast paths and boot_cpu_has() otherwise! */ -#if __GNUC__ >= 4 && defined(CONFIG_X86_FAST_FEATURE_TESTS) +#if defined(CC_HAVE_ASM_GOTO) && defined(CONFIG_X86_FAST_FEATURE_TESTS) extern bool __static_cpu_has(u16 bit); /* * Static testing of CPU features. Used the same as boot_cpu_has(). - * These are only valid after alternatives have run, but will statically - * patch the target code for additional performance. + * These will statically patch the target code for additional + * performance. */ static __always_inline __pure bool _static_cpu_has(u16 bit) { -#ifdef CC_HAVE_ASM_GOTO asm_volatile_goto("1: jmp %l[t_dynamic]\n" "2:\n" ".skip -(((5f-4f) - (2b-1b)) > 0) * " @@ -174,45 +173,6 @@ static __always_inline __pure bool _static_cpu_has(u16 bit) return false; t_dynamic: return __static_cpu_has(bit); -#else - u8 flag; - /* Open-coded due to __stringify() in ALTERNATIVE() */ - asm volatile("1: movb $2,%0\n" - "2:\n" - ".section .altinstructions,\"a\"\n" - " .long 1b - .\n" /* src offset */ - " .long 3f - .\n" /* repl offset */ - " .word %P2\n" /* always replace */ - " .byte 2b - 1b\n" /* source len */ - " .byte 4f - 3f\n" /* replacement len */ - " .byte 0\n" /* pad len */ - ".previous\n" - ".section .discard,\"aw\",@progbits\n" - " .byte 0xff + (4f-3f) - (2b-1b)\n" /* size check */ - ".previous\n" - ".section .altinstr_replacement,\"ax\"\n" - "3: movb $0,%0\n" - "4:\n" - ".previous\n" - ".section .altinstructions,\"a\"\n" - " .long 1b - .\n" /* src offset */ - " .long 5f - .\n" /* repl offset */ - " .word %P1\n" /* feature bit */ - " .byte 4b - 3b\n" /* src len */ - " .byte 6f - 5f\n" /* repl len */ - " .byte 0\n" /* pad len */ - ".previous\n" - ".section .discard,\"aw\",@progbits\n" - " .byte 0xff + (6f-5f) - (4b-3b)\n" /* size check */ - ".previous\n" - ".section .altinstr_replacement,\"ax\"\n" - "5: movb $1,%0\n" - "6:\n" - ".previous\n" - : "=qm" (flag) - : "i" (bit), "i" (X86_FEATURE_ALWAYS)); - return (flag == 2 ? __static_cpu_has(bit) : flag); -#endif /* CC_HAVE_ASM_GOTO */ } #define static_cpu_has(bit) \ @@ -223,7 +183,8 @@ static __always_inline __pure bool _static_cpu_has(u16 bit) ) #else /* - * gcc 3.x is too stupid to do the static test; fall back to dynamic. + * Fall back to dynamic for gcc versions which don't support asm goto. Should be + * a minority now anyway. */ #define static_cpu_has(bit) boot_cpu_has(bit) #endif From 33f90c87190830f23c52531322268cd97e28d71e Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Sat, 14 Jul 2018 02:27:19 -0700 Subject: [PATCH 094/159] x86/alternatives: Add an auxilary section commit 337e4cc84021212a87b04b77b65cccc49304909e upstream Add .altinstr_aux for additional instructions which will be used before and/or during patching. All stuff which needs more sophisticated patching should go there. See next patch. Signed-off-by: Borislav Petkov Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1453842730-28463-8-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar Signed-off-by: Srivatsa S. Bhat Reviewed-by: Matt Helsley (VMware) Reviewed-by: Alexey Makhalov Reviewed-by: Bo Gan Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/vmlinux.lds.S | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S index e065065a4dfb..a703842b54de 100644 --- a/arch/x86/kernel/vmlinux.lds.S +++ b/arch/x86/kernel/vmlinux.lds.S @@ -202,6 +202,17 @@ SECTIONS :init #endif + /* + * Section for code used exclusively before alternatives are run. All + * references to such code must be patched out by alternatives, normally + * by using X86_FEATURE_ALWAYS CPU feature bit. + * + * See static_cpu_has() for an example. + */ + .altinstr_aux : AT(ADDR(.altinstr_aux) - LOAD_OFFSET) { + *(.altinstr_aux) + } + INIT_DATA_SECTION(16) .x86_cpu_dev.init : AT(ADDR(.x86_cpu_dev.init) - LOAD_OFFSET) { From e23a6fee67677b5c6f9a9d65254d01b7b39b747b Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Sat, 14 Jul 2018 02:27:28 -0700 Subject: [PATCH 095/159] x86/alternatives: Discard dynamic check after init commit 2476f2fa20568bd5d9e09cd35bcd73e99a6f4cc6 upstream Move the code to do the dynamic check to the altinstr_aux section so that it is discarded after alternatives have run and a static branch has been chosen. This way we're changing the dynamic branch from C code to assembly, which makes it *substantially* smaller while avoiding a completely unnecessary call to an out of line function. Signed-off-by: Brian Gerst [ Changed it to do TESTB, as hpa suggested. ] Signed-off-by: Borislav Petkov Cc: Andrew Morton Cc: Andy Lutomirski Cc: Andy Lutomirski Cc: Boris Ostrovsky Cc: Borislav Petkov Cc: Dave Young Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Kristen Carlson Accardi Cc: Laura Abbott Cc: Linus Torvalds Cc: Peter Zijlstra (Intel) Cc: Peter Zijlstra Cc: Prarit Bhargava Cc: Ross Zwisler Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1452972124-7380-1-git-send-email-brgerst@gmail.com Link: http://lkml.kernel.org/r/20160127084525.GC30712@pd.tnic Signed-off-by: Ingo Molnar Signed-off-by: Srivatsa S. Bhat Reviewed-by: Matt Helsley (VMware) Reviewed-by: Alexey Makhalov Reviewed-by: Bo Gan Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/cpufeature.h | 19 ++++++++++++------- arch/x86/kernel/cpu/common.c | 6 ------ 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 53de4615e6ba..1c9d6c5d6d8c 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -132,8 +132,6 @@ extern const char * const x86_bug_flags[NBUGINTS*32]; */ #if defined(CC_HAVE_ASM_GOTO) && defined(CONFIG_X86_FAST_FEATURE_TESTS) -extern bool __static_cpu_has(u16 bit); - /* * Static testing of CPU features. Used the same as boot_cpu_has(). * These will statically patch the target code for additional @@ -141,7 +139,7 @@ extern bool __static_cpu_has(u16 bit); */ static __always_inline __pure bool _static_cpu_has(u16 bit) { - asm_volatile_goto("1: jmp %l[t_dynamic]\n" + asm_volatile_goto("1: jmp 6f\n" "2:\n" ".skip -(((5f-4f) - (2b-1b)) > 0) * " "((5f-4f) - (2b-1b)),0x90\n" @@ -166,13 +164,20 @@ static __always_inline __pure bool _static_cpu_has(u16 bit) " .byte 0\n" /* repl len */ " .byte 0\n" /* pad len */ ".previous\n" - : : "i" (bit), "i" (X86_FEATURE_ALWAYS) - : : t_dynamic, t_no); + ".section .altinstr_aux,\"ax\"\n" + "6:\n" + " testb %[bitnum],%[cap_byte]\n" + " jnz %l[t_yes]\n" + " jmp %l[t_no]\n" + ".previous\n" + : : "i" (bit), "i" (X86_FEATURE_ALWAYS), + [bitnum] "i" (1 << (bit & 7)), + [cap_byte] "m" (((const char *)boot_cpu_data.x86_capability)[bit >> 3]) + : : t_yes, t_no); + t_yes: return true; t_no: return false; - t_dynamic: - return __static_cpu_has(bit); } #define static_cpu_has(bit) \ diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index f31b26befca1..58d56c44d1d8 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -1576,12 +1576,6 @@ void cpu_init(void) } #endif -inline bool __static_cpu_has(u16 bit) -{ - return boot_cpu_has(bit); -} -EXPORT_SYMBOL_GPL(__static_cpu_has); - static void bsp_resume(void) { if (this_cpu->c_bsp_resume) From 7b354f89fd5a538ced93afd5563e77b85eadb669 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Sat, 14 Jul 2018 02:27:37 -0700 Subject: [PATCH 096/159] x86/vdso: Use static_cpu_has() commit 8c725306993198f845038dc9e45a1267099867a6 upstream ... and simplify and speed up a tad. Signed-off-by: Borislav Petkov Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1453842730-28463-10-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar Signed-off-by: Srivatsa S. Bhat Reviewed-by: Matt Helsley (VMware) Reviewed-by: Alexey Makhalov Reviewed-by: Bo Gan Signed-off-by: Greg Kroah-Hartman --- arch/x86/entry/vdso/vma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/entry/vdso/vma.c b/arch/x86/entry/vdso/vma.c index 5471ac362147..6b46648588d8 100644 --- a/arch/x86/entry/vdso/vma.c +++ b/arch/x86/entry/vdso/vma.c @@ -255,7 +255,7 @@ static void vgetcpu_cpu_init(void *arg) #ifdef CONFIG_NUMA node = cpu_to_node(cpu); #endif - if (cpu_has(&cpu_data(cpu), X86_FEATURE_RDTSCP)) + if (static_cpu_has(X86_FEATURE_RDTSCP)) write_rdtscp_aux((node << 12) | cpu); /* From a1b00d57298f013e5213dee6c1a5aba6766108ca Mon Sep 17 00:00:00 2001 From: Alexander Kuleshov Date: Sat, 14 Jul 2018 02:27:46 -0700 Subject: [PATCH 097/159] x86/boot: Simplify kernel load address alignment check commit a4733143085d6c782ac1e6c85778655b6bac1d4e upstream We are using %rax as temporary register to check the kernel address alignment. We don't really have to since the TEST instruction does not clobber the destination operand. Suggested-by: Brian Gerst Signed-off-by: Alexander Kuleshov Signed-off-by: Borislav Petkov Cc: Alexander Popov Cc: Andrey Ryabinin Cc: Andy Lutomirski Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1453531828-19291-1-git-send-email-kuleshovmail@gmail.com Link: http://lkml.kernel.org/r/1453842730-28463-11-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar Signed-off-by: Srivatsa S. Bhat Reviewed-by: Matt Helsley (VMware) Reviewed-by: Alexey Makhalov Reviewed-by: Bo Gan Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/head_64.S | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S index 4034e905741a..734ba1d0f686 100644 --- a/arch/x86/kernel/head_64.S +++ b/arch/x86/kernel/head_64.S @@ -76,9 +76,7 @@ startup_64: subq $_text - __START_KERNEL_map, %rbp /* Is the address not 2M aligned? */ - movq %rbp, %rax - andl $~PMD_PAGE_MASK, %eax - testl %eax, %eax + testl $~PMD_PAGE_MASK, %ebp jnz bad_address /* From 21a4ec5918141be219d977952b8fea7c4db2c827 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Sat, 14 Jul 2018 02:27:55 -0700 Subject: [PATCH 098/159] x86/cpufeature: Speed up cpu_feature_enabled() commit f2cc8e0791c70833758101d9756609a08dd601ec upstream When GCC cannot do constant folding for this macro, it falls back to cpu_has(). But static_cpu_has() is optimal and it works at all times now. So use it and speedup the fallback case. Before we had this: mov 0x99d674(%rip),%rdx # ffffffff81b0d9f4 shr $0x2e,%rdx and $0x1,%edx jne ffffffff811704e9 After alternatives patching, it turns into: jmp 0xffffffff81170390 nopl (%rax) ... callq ffffffff81056e00 ffffffff81170390: mov 0x170(%r12),%rdi Signed-off-by: Borislav Petkov Cc: Joerg Roedel Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1455578358-28347-1-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar Signed-off-by: Srivatsa S. Bhat Reviewed-by: Matt Helsley (VMware) Reviewed-by: Alexey Makhalov Reviewed-by: Bo Gan Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/cpufeature.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 1c9d6c5d6d8c..03ca602821b2 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -88,8 +88,7 @@ extern const char * const x86_bug_flags[NBUGINTS*32]; * is not relevant. */ #define cpu_feature_enabled(bit) \ - (__builtin_constant_p(bit) && DISABLED_MASK_BIT_SET(bit) ? 0 : \ - cpu_has(&boot_cpu_data, bit)) + (__builtin_constant_p(bit) && DISABLED_MASK_BIT_SET(bit) ? 0 : static_cpu_has(bit)) #define boot_cpu_has(bit) cpu_has(&boot_cpu_data, bit) From 747b9cefca27eda29ca76dd3cf95b7fa046cd88b Mon Sep 17 00:00:00 2001 From: Dave Hansen Date: Sat, 14 Jul 2018 02:28:04 -0700 Subject: [PATCH 099/159] x86/cpufeature, x86/mm/pkeys: Add protection keys related CPUID definitions commit dfb4a70f20c5b3880da56ee4c9484bdb4e8f1e65 upstream There are two CPUID bits for protection keys. One is for whether the CPU contains the feature, and the other will appear set once the OS enables protection keys. Specifically: Bit 04: OSPKE. If 1, OS has set CR4.PKE to enable Protection keys (and the RDPKRU/WRPKRU instructions) This is because userspace can not see CR4 contents, but it can see CPUID contents. X86_FEATURE_PKU is referred to as "PKU" in the hardware documentation: CPUID.(EAX=07H,ECX=0H):ECX.PKU [bit 3] X86_FEATURE_OSPKE is "OSPKU": CPUID.(EAX=07H,ECX=0H):ECX.OSPKE [bit 4] These are the first CPU features which need to look at the ECX word in CPUID leaf 0x7, so this patch also includes fetching that word in to the cpuinfo->x86_capability[] array. Add it to the disabled-features mask when its config option is off. Even though we are not using it here, we also extend the REQUIRED_MASK_BIT_SET() macro to keep it mirroring the DISABLED_MASK_BIT_SET() version. This means that in almost all code, you should use: cpu_has(c, X86_FEATURE_PKU) and *not* the CONFIG option. Signed-off-by: Dave Hansen Reviewed-by: Thomas Gleixner Cc: Andrew Morton Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Dave Hansen Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Rik van Riel Cc: linux-mm@kvack.org Link: http://lkml.kernel.org/r/20160212210201.7714C250@viggo.jf.intel.com Signed-off-by: Ingo Molnar Signed-off-by: Srivatsa S. Bhat Reviewed-by: Matt Helsley (VMware) Reviewed-by: Alexey Makhalov Reviewed-by: Bo Gan Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/cpufeature.h | 59 ++++++++++++++++-------- arch/x86/include/asm/cpufeatures.h | 2 +- arch/x86/include/asm/disabled-features.h | 15 ++++++ arch/x86/include/asm/required-features.h | 7 +++ arch/x86/kernel/cpu/common.c | 1 + 5 files changed, 63 insertions(+), 21 deletions(-) diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 03ca602821b2..7fdd7170ac44 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -26,6 +26,7 @@ enum cpuid_leafs CPUID_8000_0008_EBX, CPUID_6_EAX, CPUID_8000_000A_EDX, + CPUID_7_ECX, }; #ifdef CONFIG_X86_FEATURE_NAMES @@ -48,28 +49,42 @@ extern const char * const x86_bug_flags[NBUGINTS*32]; test_bit(bit, (unsigned long *)((c)->x86_capability)) #define REQUIRED_MASK_BIT_SET(bit) \ - ( (((bit)>>5)==0 && (1UL<<((bit)&31) & REQUIRED_MASK0)) || \ - (((bit)>>5)==1 && (1UL<<((bit)&31) & REQUIRED_MASK1)) || \ - (((bit)>>5)==2 && (1UL<<((bit)&31) & REQUIRED_MASK2)) || \ - (((bit)>>5)==3 && (1UL<<((bit)&31) & REQUIRED_MASK3)) || \ - (((bit)>>5)==4 && (1UL<<((bit)&31) & REQUIRED_MASK4)) || \ - (((bit)>>5)==5 && (1UL<<((bit)&31) & REQUIRED_MASK5)) || \ - (((bit)>>5)==6 && (1UL<<((bit)&31) & REQUIRED_MASK6)) || \ - (((bit)>>5)==7 && (1UL<<((bit)&31) & REQUIRED_MASK7)) || \ - (((bit)>>5)==8 && (1UL<<((bit)&31) & REQUIRED_MASK8)) || \ - (((bit)>>5)==9 && (1UL<<((bit)&31) & REQUIRED_MASK9)) ) + ( (((bit)>>5)==0 && (1UL<<((bit)&31) & REQUIRED_MASK0 )) || \ + (((bit)>>5)==1 && (1UL<<((bit)&31) & REQUIRED_MASK1 )) || \ + (((bit)>>5)==2 && (1UL<<((bit)&31) & REQUIRED_MASK2 )) || \ + (((bit)>>5)==3 && (1UL<<((bit)&31) & REQUIRED_MASK3 )) || \ + (((bit)>>5)==4 && (1UL<<((bit)&31) & REQUIRED_MASK4 )) || \ + (((bit)>>5)==5 && (1UL<<((bit)&31) & REQUIRED_MASK5 )) || \ + (((bit)>>5)==6 && (1UL<<((bit)&31) & REQUIRED_MASK6 )) || \ + (((bit)>>5)==7 && (1UL<<((bit)&31) & REQUIRED_MASK7 )) || \ + (((bit)>>5)==8 && (1UL<<((bit)&31) & REQUIRED_MASK8 )) || \ + (((bit)>>5)==9 && (1UL<<((bit)&31) & REQUIRED_MASK9 )) || \ + (((bit)>>5)==10 && (1UL<<((bit)&31) & REQUIRED_MASK10)) || \ + (((bit)>>5)==11 && (1UL<<((bit)&31) & REQUIRED_MASK11)) || \ + (((bit)>>5)==12 && (1UL<<((bit)&31) & REQUIRED_MASK12)) || \ + (((bit)>>5)==13 && (1UL<<((bit)&31) & REQUIRED_MASK13)) || \ + (((bit)>>5)==13 && (1UL<<((bit)&31) & REQUIRED_MASK14)) || \ + (((bit)>>5)==13 && (1UL<<((bit)&31) & REQUIRED_MASK15)) || \ + (((bit)>>5)==14 && (1UL<<((bit)&31) & REQUIRED_MASK16)) ) #define DISABLED_MASK_BIT_SET(bit) \ - ( (((bit)>>5)==0 && (1UL<<((bit)&31) & DISABLED_MASK0)) || \ - (((bit)>>5)==1 && (1UL<<((bit)&31) & DISABLED_MASK1)) || \ - (((bit)>>5)==2 && (1UL<<((bit)&31) & DISABLED_MASK2)) || \ - (((bit)>>5)==3 && (1UL<<((bit)&31) & DISABLED_MASK3)) || \ - (((bit)>>5)==4 && (1UL<<((bit)&31) & DISABLED_MASK4)) || \ - (((bit)>>5)==5 && (1UL<<((bit)&31) & DISABLED_MASK5)) || \ - (((bit)>>5)==6 && (1UL<<((bit)&31) & DISABLED_MASK6)) || \ - (((bit)>>5)==7 && (1UL<<((bit)&31) & DISABLED_MASK7)) || \ - (((bit)>>5)==8 && (1UL<<((bit)&31) & DISABLED_MASK8)) || \ - (((bit)>>5)==9 && (1UL<<((bit)&31) & DISABLED_MASK9)) ) + ( (((bit)>>5)==0 && (1UL<<((bit)&31) & DISABLED_MASK0 )) || \ + (((bit)>>5)==1 && (1UL<<((bit)&31) & DISABLED_MASK1 )) || \ + (((bit)>>5)==2 && (1UL<<((bit)&31) & DISABLED_MASK2 )) || \ + (((bit)>>5)==3 && (1UL<<((bit)&31) & DISABLED_MASK3 )) || \ + (((bit)>>5)==4 && (1UL<<((bit)&31) & DISABLED_MASK4 )) || \ + (((bit)>>5)==5 && (1UL<<((bit)&31) & DISABLED_MASK5 )) || \ + (((bit)>>5)==6 && (1UL<<((bit)&31) & DISABLED_MASK6 )) || \ + (((bit)>>5)==7 && (1UL<<((bit)&31) & DISABLED_MASK7 )) || \ + (((bit)>>5)==8 && (1UL<<((bit)&31) & DISABLED_MASK8 )) || \ + (((bit)>>5)==9 && (1UL<<((bit)&31) & DISABLED_MASK9 )) || \ + (((bit)>>5)==10 && (1UL<<((bit)&31) & DISABLED_MASK10)) || \ + (((bit)>>5)==11 && (1UL<<((bit)&31) & DISABLED_MASK11)) || \ + (((bit)>>5)==12 && (1UL<<((bit)&31) & DISABLED_MASK12)) || \ + (((bit)>>5)==13 && (1UL<<((bit)&31) & DISABLED_MASK13)) || \ + (((bit)>>5)==13 && (1UL<<((bit)&31) & DISABLED_MASK14)) || \ + (((bit)>>5)==13 && (1UL<<((bit)&31) & DISABLED_MASK15)) || \ + (((bit)>>5)==14 && (1UL<<((bit)&31) & DISABLED_MASK16)) ) #define cpu_has(c, bit) \ (__builtin_constant_p(bit) && REQUIRED_MASK_BIT_SET(bit) ? 1 : \ @@ -79,6 +94,10 @@ extern const char * const x86_bug_flags[NBUGINTS*32]; (__builtin_constant_p(bit) && REQUIRED_MASK_BIT_SET(bit) ? 1 : \ x86_this_cpu_test_bit(bit, (unsigned long *)&cpu_info.x86_capability)) +/* Intel-defined CPU features, CPUID level 0x00000007:0 (ecx), word 16 */ +#define X86_FEATURE_PKU (16*32+ 3) /* Protection Keys for Userspace */ +#define X86_FEATURE_OSPKE (16*32+ 4) /* OS Protection Keys Enable */ + /* * This macro is for detection of features which need kernel * infrastructure to be used. It may *not* directly test the CPU diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h index 255ea74c52e8..6ebb4c2dad84 100644 --- a/arch/x86/include/asm/cpufeatures.h +++ b/arch/x86/include/asm/cpufeatures.h @@ -12,7 +12,7 @@ /* * Defines x86 CPU feature bits */ -#define NCAPINTS 16 /* N 32-bit words worth of info */ +#define NCAPINTS 17 /* N 32-bit words worth of info */ #define NBUGINTS 1 /* N 32-bit bug flags */ /* diff --git a/arch/x86/include/asm/disabled-features.h b/arch/x86/include/asm/disabled-features.h index 8b17c2ad1048..522a069c9abd 100644 --- a/arch/x86/include/asm/disabled-features.h +++ b/arch/x86/include/asm/disabled-features.h @@ -30,6 +30,14 @@ # define DISABLE_PCID (1<<(X86_FEATURE_PCID & 31)) #endif /* CONFIG_X86_64 */ +#ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS +# define DISABLE_PKU (1<<(X86_FEATURE_PKU)) +# define DISABLE_OSPKE (1<<(X86_FEATURE_OSPKE)) +#else +# define DISABLE_PKU 0 +# define DISABLE_OSPKE 0 +#endif /* CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS */ + /* * Make sure to add features to the correct mask */ @@ -43,5 +51,12 @@ #define DISABLED_MASK7 0 #define DISABLED_MASK8 0 #define DISABLED_MASK9 (DISABLE_MPX) +#define DISABLED_MASK10 0 +#define DISABLED_MASK11 0 +#define DISABLED_MASK12 0 +#define DISABLED_MASK13 0 +#define DISABLED_MASK14 0 +#define DISABLED_MASK15 0 +#define DISABLED_MASK16 (DISABLE_PKU|DISABLE_OSPKE) #endif /* _ASM_X86_DISABLED_FEATURES_H */ diff --git a/arch/x86/include/asm/required-features.h b/arch/x86/include/asm/required-features.h index 5c6e4fb370f5..4916144e3c42 100644 --- a/arch/x86/include/asm/required-features.h +++ b/arch/x86/include/asm/required-features.h @@ -92,5 +92,12 @@ #define REQUIRED_MASK7 0 #define REQUIRED_MASK8 0 #define REQUIRED_MASK9 0 +#define REQUIRED_MASK10 0 +#define REQUIRED_MASK11 0 +#define REQUIRED_MASK12 0 +#define REQUIRED_MASK13 0 +#define REQUIRED_MASK14 0 +#define REQUIRED_MASK15 0 +#define REQUIRED_MASK16 0 #endif /* _ASM_X86_REQUIRED_FEATURES_H */ diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 58d56c44d1d8..d6a7b6f214d4 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -693,6 +693,7 @@ void get_cpu_cap(struct cpuinfo_x86 *c) c->x86_capability[CPUID_7_0_EBX] = ebx; c->x86_capability[CPUID_6_EAX] = cpuid_eax(0x00000006); + c->x86_capability[CPUID_7_ECX] = ecx; } /* Extended state features: level 0x0000000d */ From e5918939e57133967a23612012fed4440809456a Mon Sep 17 00:00:00 2001 From: Dave Hansen Date: Sat, 14 Jul 2018 02:28:13 -0700 Subject: [PATCH 100/159] x86/mm/pkeys: Fix mismerge of protection keys CPUID bits commit 0d47638f80a02b15869f1fe1fc09e5bf996750fd upstream Kirill Shutemov pointed this out to me. The tip tree currently has commit: dfb4a70f2 [x86/cpufeature, x86/mm/pkeys: Add protection keys related CPUID definitions] whioch added support for two new CPUID bits: X86_FEATURE_PKU and X86_FEATURE_OSPKE. But, those bits were mis-merged and put in cpufeature.h instead of cpufeatures.h. This didn't cause any breakage *except* it keeps the "ospke" and "pku" bits from showing up in cpuinfo. Now cpuinfo has the two new flags: flags : ... pku ospke BTW, is it really wise to have cpufeature.h and cpufeatures.h? It seems like they can only cause confusion and mahem with tab completion. Reported-by: Kirill A. Shutemov Signed-off-by: Dave Hansen Acked-by: Borislav Petkov Cc: Andy Lutomirski Cc: Dave Hansen Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/20160310221213.06F9DB53@viggo.jf.intel.com Signed-off-by: Ingo Molnar Signed-off-by: Srivatsa S. Bhat Reviewed-by: Matt Helsley (VMware) Reviewed-by: Alexey Makhalov Reviewed-by: Bo Gan Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/cpufeature.h | 4 ---- arch/x86/include/asm/cpufeatures.h | 4 ++++ 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 7fdd7170ac44..b953fb74aba6 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -94,10 +94,6 @@ extern const char * const x86_bug_flags[NBUGINTS*32]; (__builtin_constant_p(bit) && REQUIRED_MASK_BIT_SET(bit) ? 1 : \ x86_this_cpu_test_bit(bit, (unsigned long *)&cpu_info.x86_capability)) -/* Intel-defined CPU features, CPUID level 0x00000007:0 (ecx), word 16 */ -#define X86_FEATURE_PKU (16*32+ 3) /* Protection Keys for Userspace */ -#define X86_FEATURE_OSPKE (16*32+ 4) /* OS Protection Keys Enable */ - /* * This macro is for detection of features which need kernel * infrastructure to be used. It may *not* directly test the CPU diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h index 6ebb4c2dad84..f19b9010764f 100644 --- a/arch/x86/include/asm/cpufeatures.h +++ b/arch/x86/include/asm/cpufeatures.h @@ -276,6 +276,10 @@ #define X86_FEATURE_PAUSEFILTER (15*32+10) /* filtered pause intercept */ #define X86_FEATURE_PFTHRESHOLD (15*32+12) /* pause filter threshold */ +/* Intel-defined CPU features, CPUID level 0x00000007:0 (ecx), word 16 */ +#define X86_FEATURE_PKU (16*32+ 3) /* Protection Keys for Userspace */ +#define X86_FEATURE_OSPKE (16*32+ 4) /* OS Protection Keys Enable */ + /* * BUG word(s) */ From 9cc52d168fcb4152132b0ba067db4c1da1bdca67 Mon Sep 17 00:00:00 2001 From: Yazen Ghannam Date: Sat, 14 Jul 2018 02:28:21 -0700 Subject: [PATCH 101/159] x86/cpu: Add detection of AMD RAS Capabilities commit 71faad43060d3d2040583635fbf7d1bdb3d04118 upstream Add a new CPUID leaf to hold the contents of CPUID 0x80000007_EBX (RasCap). Define bits that are currently in use: Bit 0: McaOverflowRecov Bit 1: SUCCOR Bit 3: ScalableMca Signed-off-by: Yazen Ghannam [ Shorten comment. ] Signed-off-by: Borislav Petkov Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Tony Luck Cc: linux-edac Link: http://lkml.kernel.org/r/1462971509-3856-5-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar Signed-off-by: Srivatsa S. Bhat Reviewed-by: Matt Helsley (VMware) Reviewed-by: Alexey Makhalov Reviewed-by: Bo Gan Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/cpufeature.h | 1 + arch/x86/include/asm/cpufeatures.h | 7 ++++++- arch/x86/kernel/cpu/common.c | 10 +++++++--- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index b953fb74aba6..1d02ad682b20 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -27,6 +27,7 @@ enum cpuid_leafs CPUID_6_EAX, CPUID_8000_000A_EDX, CPUID_7_ECX, + CPUID_8000_0007_EBX, }; #ifdef CONFIG_X86_FEATURE_NAMES diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h index f19b9010764f..205ce70c1d6c 100644 --- a/arch/x86/include/asm/cpufeatures.h +++ b/arch/x86/include/asm/cpufeatures.h @@ -12,7 +12,7 @@ /* * Defines x86 CPU feature bits */ -#define NCAPINTS 17 /* N 32-bit words worth of info */ +#define NCAPINTS 18 /* N 32-bit words worth of info */ #define NBUGINTS 1 /* N 32-bit bug flags */ /* @@ -280,6 +280,11 @@ #define X86_FEATURE_PKU (16*32+ 3) /* Protection Keys for Userspace */ #define X86_FEATURE_OSPKE (16*32+ 4) /* OS Protection Keys Enable */ +/* AMD-defined CPU features, CPUID level 0x80000007 (ebx), word 17 */ +#define X86_FEATURE_OVERFLOW_RECOV (17*32+0) /* MCA overflow recovery support */ +#define X86_FEATURE_SUCCOR (17*32+1) /* Uncorrectable error containment and recovery */ +#define X86_FEATURE_SMCA (17*32+3) /* Scalable MCA */ + /* * BUG word(s) */ diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index d6a7b6f214d4..814276d0eed1 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -741,6 +741,13 @@ void get_cpu_cap(struct cpuinfo_x86 *c) } } + if (c->extended_cpuid_level >= 0x80000007) { + cpuid(0x80000007, &eax, &ebx, &ecx, &edx); + + c->x86_capability[CPUID_8000_0007_EBX] = ebx; + c->x86_power = edx; + } + if (c->extended_cpuid_level >= 0x80000008) { cpuid(0x80000008, &eax, &ebx, &ecx, &edx); @@ -753,9 +760,6 @@ void get_cpu_cap(struct cpuinfo_x86 *c) c->x86_phys_bits = 36; #endif - if (c->extended_cpuid_level >= 0x80000007) - c->x86_power = cpuid_edx(0x80000007); - if (c->extended_cpuid_level >= 0x8000000a) c->x86_capability[CPUID_8000_000A_EDX] = cpuid_edx(0x8000000a); From 793ea13ecc8d46668c0d24d6e5d4487a25eab877 Mon Sep 17 00:00:00 2001 From: Dave Hansen Date: Sat, 14 Jul 2018 02:28:30 -0700 Subject: [PATCH 102/159] x86/cpufeature, x86/mm/pkeys: Fix broken compile-time disabling of pkeys commit e8df1a95b685af84a81698199ee206e0e66a8b44 upstream When I added support for the Memory Protection Keys processor feature, I had to reindent the REQUIRED/DISABLED_MASK macros, and also consult the later cpufeature words. I'm not quite sure how I bungled it, but I consulted the wrong word at the end. This only affected required or disabled cpu features in cpufeature words 14, 15 and 16. So, only Protection Keys itself was screwed over here. The result was that if you disabled pkeys in your .config, you might still see some code show up that should have been compiled out. There should be no functional problems, though. In verifying this patch I also realized that the DISABLE_PKU/OSPKE macros were defined backwards and that the cpu_has() check in setup_pku() was not doing the compile-time disabled checks. So also fix the macro for DISABLE_PKU/OSPKE and add a compile-time check for pkeys being enabled in setup_pku(). Signed-off-by: Dave Hansen Cc: Cc: Alexander Shishkin Cc: Arnaldo Carvalho de Melo Cc: Dave Hansen Cc: Jiri Olsa Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Thomas Gleixner Cc: Vince Weaver Fixes: dfb4a70f20c5 ("x86/cpufeature, x86/mm/pkeys: Add protection keys related CPUID definitions") Link: http://lkml.kernel.org/r/20160513221328.C200930B@viggo.jf.intel.com Signed-off-by: Ingo Molnar Signed-off-by: Srivatsa S. Bhat Reviewed-by: Matt Helsley (VMware) Reviewed-by: Alexey Makhalov Reviewed-by: Bo Gan Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/cpufeature.h | 12 ++++++------ arch/x86/include/asm/disabled-features.h | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 1d02ad682b20..aa7785ec3403 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -64,9 +64,9 @@ extern const char * const x86_bug_flags[NBUGINTS*32]; (((bit)>>5)==11 && (1UL<<((bit)&31) & REQUIRED_MASK11)) || \ (((bit)>>5)==12 && (1UL<<((bit)&31) & REQUIRED_MASK12)) || \ (((bit)>>5)==13 && (1UL<<((bit)&31) & REQUIRED_MASK13)) || \ - (((bit)>>5)==13 && (1UL<<((bit)&31) & REQUIRED_MASK14)) || \ - (((bit)>>5)==13 && (1UL<<((bit)&31) & REQUIRED_MASK15)) || \ - (((bit)>>5)==14 && (1UL<<((bit)&31) & REQUIRED_MASK16)) ) + (((bit)>>5)==14 && (1UL<<((bit)&31) & REQUIRED_MASK14)) || \ + (((bit)>>5)==15 && (1UL<<((bit)&31) & REQUIRED_MASK15)) || \ + (((bit)>>5)==16 && (1UL<<((bit)&31) & REQUIRED_MASK16)) ) #define DISABLED_MASK_BIT_SET(bit) \ ( (((bit)>>5)==0 && (1UL<<((bit)&31) & DISABLED_MASK0 )) || \ @@ -83,9 +83,9 @@ extern const char * const x86_bug_flags[NBUGINTS*32]; (((bit)>>5)==11 && (1UL<<((bit)&31) & DISABLED_MASK11)) || \ (((bit)>>5)==12 && (1UL<<((bit)&31) & DISABLED_MASK12)) || \ (((bit)>>5)==13 && (1UL<<((bit)&31) & DISABLED_MASK13)) || \ - (((bit)>>5)==13 && (1UL<<((bit)&31) & DISABLED_MASK14)) || \ - (((bit)>>5)==13 && (1UL<<((bit)&31) & DISABLED_MASK15)) || \ - (((bit)>>5)==14 && (1UL<<((bit)&31) & DISABLED_MASK16)) ) + (((bit)>>5)==14 && (1UL<<((bit)&31) & DISABLED_MASK14)) || \ + (((bit)>>5)==15 && (1UL<<((bit)&31) & DISABLED_MASK15)) || \ + (((bit)>>5)==16 && (1UL<<((bit)&31) & DISABLED_MASK16)) ) #define cpu_has(c, bit) \ (__builtin_constant_p(bit) && REQUIRED_MASK_BIT_SET(bit) ? 1 : \ diff --git a/arch/x86/include/asm/disabled-features.h b/arch/x86/include/asm/disabled-features.h index 522a069c9abd..0403b224a944 100644 --- a/arch/x86/include/asm/disabled-features.h +++ b/arch/x86/include/asm/disabled-features.h @@ -31,11 +31,11 @@ #endif /* CONFIG_X86_64 */ #ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS -# define DISABLE_PKU (1<<(X86_FEATURE_PKU)) -# define DISABLE_OSPKE (1<<(X86_FEATURE_OSPKE)) -#else # define DISABLE_PKU 0 # define DISABLE_OSPKE 0 +#else +# define DISABLE_PKU (1<<(X86_FEATURE_PKU & 31)) +# define DISABLE_OSPKE (1<<(X86_FEATURE_OSPKE & 31)) #endif /* CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS */ /* From febdf817e79b51ff13118bac7c48cb2108366d4b Mon Sep 17 00:00:00 2001 From: Dave Hansen Date: Sat, 14 Jul 2018 02:28:40 -0700 Subject: [PATCH 103/159] x86/cpufeature: Update cpufeaure macros commit 6e17cb9c2d5efd8fcc3934e983733302b9912ff8 upstream We had a new CPUID "NCAPINT" word added, but the REQUIRED_MASK and DISABLED_MASK macros did not get updated. Update them. None of the features was needed in these masks, so there was no harm, but we should keep them updated anyway. Signed-off-by: Dave Hansen Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Dave Hansen Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Josh Poimboeuf Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/20160629200107.8D3C9A31@viggo.jf.intel.com Signed-off-by: Ingo Molnar Signed-off-by: Srivatsa S. Bhat Reviewed-by: Matt Helsley (VMware) Reviewed-by: Alexey Makhalov Reviewed-by: Bo Gan Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/cpufeature.h | 6 ++++-- arch/x86/include/asm/disabled-features.h | 1 + arch/x86/include/asm/required-features.h | 1 + 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index aa7785ec3403..c7e38daae4f4 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -66,7 +66,8 @@ extern const char * const x86_bug_flags[NBUGINTS*32]; (((bit)>>5)==13 && (1UL<<((bit)&31) & REQUIRED_MASK13)) || \ (((bit)>>5)==14 && (1UL<<((bit)&31) & REQUIRED_MASK14)) || \ (((bit)>>5)==15 && (1UL<<((bit)&31) & REQUIRED_MASK15)) || \ - (((bit)>>5)==16 && (1UL<<((bit)&31) & REQUIRED_MASK16)) ) + (((bit)>>5)==16 && (1UL<<((bit)&31) & REQUIRED_MASK16)) || \ + (((bit)>>5)==17 && (1UL<<((bit)&31) & REQUIRED_MASK17))) #define DISABLED_MASK_BIT_SET(bit) \ ( (((bit)>>5)==0 && (1UL<<((bit)&31) & DISABLED_MASK0 )) || \ @@ -85,7 +86,8 @@ extern const char * const x86_bug_flags[NBUGINTS*32]; (((bit)>>5)==13 && (1UL<<((bit)&31) & DISABLED_MASK13)) || \ (((bit)>>5)==14 && (1UL<<((bit)&31) & DISABLED_MASK14)) || \ (((bit)>>5)==15 && (1UL<<((bit)&31) & DISABLED_MASK15)) || \ - (((bit)>>5)==16 && (1UL<<((bit)&31) & DISABLED_MASK16)) ) + (((bit)>>5)==16 && (1UL<<((bit)&31) & DISABLED_MASK16)) || \ + (((bit)>>5)==17 && (1UL<<((bit)&31) & DISABLED_MASK17))) #define cpu_has(c, bit) \ (__builtin_constant_p(bit) && REQUIRED_MASK_BIT_SET(bit) ? 1 : \ diff --git a/arch/x86/include/asm/disabled-features.h b/arch/x86/include/asm/disabled-features.h index 0403b224a944..ab6b05ccb3f9 100644 --- a/arch/x86/include/asm/disabled-features.h +++ b/arch/x86/include/asm/disabled-features.h @@ -58,5 +58,6 @@ #define DISABLED_MASK14 0 #define DISABLED_MASK15 0 #define DISABLED_MASK16 (DISABLE_PKU|DISABLE_OSPKE) +#define DISABLED_MASK17 0 #endif /* _ASM_X86_DISABLED_FEATURES_H */ diff --git a/arch/x86/include/asm/required-features.h b/arch/x86/include/asm/required-features.h index 4916144e3c42..fad4277d582e 100644 --- a/arch/x86/include/asm/required-features.h +++ b/arch/x86/include/asm/required-features.h @@ -99,5 +99,6 @@ #define REQUIRED_MASK14 0 #define REQUIRED_MASK15 0 #define REQUIRED_MASK16 0 +#define REQUIRED_MASK17 0 #endif /* _ASM_X86_REQUIRED_FEATURES_H */ From 8ebab07946fa77c89b2603c7febcbdf2d42ed346 Mon Sep 17 00:00:00 2001 From: Dave Hansen Date: Sat, 14 Jul 2018 02:28:49 -0700 Subject: [PATCH 104/159] x86/cpufeature: Make sure DISABLED/REQUIRED macros are updated commit 1e61f78baf893c7eb49f633d23ccbb420c8f808e upstream x86 has two macros which allow us to evaluate some CPUID-based features at compile time: REQUIRED_MASK_BIT_SET() DISABLED_MASK_BIT_SET() They're both defined by having the compiler check the bit argument against some constant masks of features. But, when adding new CPUID leaves, we need to check new words for these macros. So make sure that those macros and the REQUIRED_MASK* and DISABLED_MASK* get updated when necessary. This looks kinda silly to have an open-coded value ("18" in this case) open-coded in 5 places in the code. But, we really do need 5 places updated when NCAPINTS gets bumped, so now we just force the issue. Signed-off-by: Dave Hansen Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Dave Hansen Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Josh Poimboeuf Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/20160629200108.92466F6F@viggo.jf.intel.com Signed-off-by: Ingo Molnar Signed-off-by: Srivatsa S. Bhat Reviewed-by: Matt Helsley (VMware) Reviewed-by: Alexey Makhalov Reviewed-by: Bo Gan Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/cpufeature.h | 8 ++++++-- arch/x86/include/asm/disabled-features.h | 1 + arch/x86/include/asm/required-features.h | 1 + 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index c7e38daae4f4..3d5a6b563251 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -67,7 +67,9 @@ extern const char * const x86_bug_flags[NBUGINTS*32]; (((bit)>>5)==14 && (1UL<<((bit)&31) & REQUIRED_MASK14)) || \ (((bit)>>5)==15 && (1UL<<((bit)&31) & REQUIRED_MASK15)) || \ (((bit)>>5)==16 && (1UL<<((bit)&31) & REQUIRED_MASK16)) || \ - (((bit)>>5)==17 && (1UL<<((bit)&31) & REQUIRED_MASK17))) + (((bit)>>5)==17 && (1UL<<((bit)&31) & REQUIRED_MASK17)) || \ + REQUIRED_MASK_CHECK || \ + BUILD_BUG_ON_ZERO(NCAPINTS != 18)) #define DISABLED_MASK_BIT_SET(bit) \ ( (((bit)>>5)==0 && (1UL<<((bit)&31) & DISABLED_MASK0 )) || \ @@ -87,7 +89,9 @@ extern const char * const x86_bug_flags[NBUGINTS*32]; (((bit)>>5)==14 && (1UL<<((bit)&31) & DISABLED_MASK14)) || \ (((bit)>>5)==15 && (1UL<<((bit)&31) & DISABLED_MASK15)) || \ (((bit)>>5)==16 && (1UL<<((bit)&31) & DISABLED_MASK16)) || \ - (((bit)>>5)==17 && (1UL<<((bit)&31) & DISABLED_MASK17))) + (((bit)>>5)==17 && (1UL<<((bit)&31) & DISABLED_MASK17)) || \ + DISABLED_MASK_CHECK || \ + BUILD_BUG_ON_ZERO(NCAPINTS != 18)) #define cpu_has(c, bit) \ (__builtin_constant_p(bit) && REQUIRED_MASK_BIT_SET(bit) ? 1 : \ diff --git a/arch/x86/include/asm/disabled-features.h b/arch/x86/include/asm/disabled-features.h index ab6b05ccb3f9..21c5ac15657b 100644 --- a/arch/x86/include/asm/disabled-features.h +++ b/arch/x86/include/asm/disabled-features.h @@ -59,5 +59,6 @@ #define DISABLED_MASK15 0 #define DISABLED_MASK16 (DISABLE_PKU|DISABLE_OSPKE) #define DISABLED_MASK17 0 +#define DISABLED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 18) #endif /* _ASM_X86_DISABLED_FEATURES_H */ diff --git a/arch/x86/include/asm/required-features.h b/arch/x86/include/asm/required-features.h index fad4277d582e..fac9a5c0abe9 100644 --- a/arch/x86/include/asm/required-features.h +++ b/arch/x86/include/asm/required-features.h @@ -100,5 +100,6 @@ #define REQUIRED_MASK15 0 #define REQUIRED_MASK16 0 #define REQUIRED_MASK17 0 +#define REQUIRED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 18) #endif /* _ASM_X86_REQUIRED_FEATURES_H */ From b7e37d9a907bff7b2cc1c4d5be9c6bedc9479422 Mon Sep 17 00:00:00 2001 From: Dave Hansen Date: Sat, 14 Jul 2018 02:28:57 -0700 Subject: [PATCH 105/159] x86/cpufeature: Add helper macro for mask check macros commit 8eda072e9d7c3429a372e3635dc5851f4a42dee1 upstream Every time we add a word to our cpu features, we need to add something like this in two places: (((bit)>>5)==16 && (1UL<<((bit)&31) & REQUIRED_MASK16)) The trick is getting the "16" in this case in both places. I've now screwed this up twice, so as pennance, I've come up with this patch to keep me and other poor souls from doing the same. I also commented the logic behind the bit manipulation showcased above. Signed-off-by: Dave Hansen Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Dave Hansen Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Josh Poimboeuf Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/20160629200110.1BA8949E@viggo.jf.intel.com Signed-off-by: Ingo Molnar Signed-off-by: Srivatsa S. Bhat Reviewed-by: Matt Helsley (VMware) Reviewed-by: Alexey Makhalov Reviewed-by: Bo Gan Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/cpufeature.h | 90 +++++++++++++++++-------------- 1 file changed, 50 insertions(+), 40 deletions(-) diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 3d5a6b563251..dd0089841a0f 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -49,48 +49,58 @@ extern const char * const x86_bug_flags[NBUGINTS*32]; #define test_cpu_cap(c, bit) \ test_bit(bit, (unsigned long *)((c)->x86_capability)) -#define REQUIRED_MASK_BIT_SET(bit) \ - ( (((bit)>>5)==0 && (1UL<<((bit)&31) & REQUIRED_MASK0 )) || \ - (((bit)>>5)==1 && (1UL<<((bit)&31) & REQUIRED_MASK1 )) || \ - (((bit)>>5)==2 && (1UL<<((bit)&31) & REQUIRED_MASK2 )) || \ - (((bit)>>5)==3 && (1UL<<((bit)&31) & REQUIRED_MASK3 )) || \ - (((bit)>>5)==4 && (1UL<<((bit)&31) & REQUIRED_MASK4 )) || \ - (((bit)>>5)==5 && (1UL<<((bit)&31) & REQUIRED_MASK5 )) || \ - (((bit)>>5)==6 && (1UL<<((bit)&31) & REQUIRED_MASK6 )) || \ - (((bit)>>5)==7 && (1UL<<((bit)&31) & REQUIRED_MASK7 )) || \ - (((bit)>>5)==8 && (1UL<<((bit)&31) & REQUIRED_MASK8 )) || \ - (((bit)>>5)==9 && (1UL<<((bit)&31) & REQUIRED_MASK9 )) || \ - (((bit)>>5)==10 && (1UL<<((bit)&31) & REQUIRED_MASK10)) || \ - (((bit)>>5)==11 && (1UL<<((bit)&31) & REQUIRED_MASK11)) || \ - (((bit)>>5)==12 && (1UL<<((bit)&31) & REQUIRED_MASK12)) || \ - (((bit)>>5)==13 && (1UL<<((bit)&31) & REQUIRED_MASK13)) || \ - (((bit)>>5)==14 && (1UL<<((bit)&31) & REQUIRED_MASK14)) || \ - (((bit)>>5)==15 && (1UL<<((bit)&31) & REQUIRED_MASK15)) || \ - (((bit)>>5)==16 && (1UL<<((bit)&31) & REQUIRED_MASK16)) || \ - (((bit)>>5)==17 && (1UL<<((bit)&31) & REQUIRED_MASK17)) || \ - REQUIRED_MASK_CHECK || \ +/* + * There are 32 bits/features in each mask word. The high bits + * (selected with (bit>>5) give us the word number and the low 5 + * bits give us the bit/feature number inside the word. + * (1UL<<((bit)&31) gives us a mask for the feature_bit so we can + * see if it is set in the mask word. + */ +#define CHECK_BIT_IN_MASK_WORD(maskname, word, bit) \ + (((bit)>>5)==(word) && (1UL<<((bit)&31) & maskname##word )) + +#define REQUIRED_MASK_BIT_SET(feature_bit) \ + ( CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 0, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 1, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 2, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 3, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 4, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 5, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 6, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 7, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 8, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 9, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 10, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 11, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 12, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 13, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 14, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 15, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 16, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 17, feature_bit) || \ + REQUIRED_MASK_CHECK || \ BUILD_BUG_ON_ZERO(NCAPINTS != 18)) -#define DISABLED_MASK_BIT_SET(bit) \ - ( (((bit)>>5)==0 && (1UL<<((bit)&31) & DISABLED_MASK0 )) || \ - (((bit)>>5)==1 && (1UL<<((bit)&31) & DISABLED_MASK1 )) || \ - (((bit)>>5)==2 && (1UL<<((bit)&31) & DISABLED_MASK2 )) || \ - (((bit)>>5)==3 && (1UL<<((bit)&31) & DISABLED_MASK3 )) || \ - (((bit)>>5)==4 && (1UL<<((bit)&31) & DISABLED_MASK4 )) || \ - (((bit)>>5)==5 && (1UL<<((bit)&31) & DISABLED_MASK5 )) || \ - (((bit)>>5)==6 && (1UL<<((bit)&31) & DISABLED_MASK6 )) || \ - (((bit)>>5)==7 && (1UL<<((bit)&31) & DISABLED_MASK7 )) || \ - (((bit)>>5)==8 && (1UL<<((bit)&31) & DISABLED_MASK8 )) || \ - (((bit)>>5)==9 && (1UL<<((bit)&31) & DISABLED_MASK9 )) || \ - (((bit)>>5)==10 && (1UL<<((bit)&31) & DISABLED_MASK10)) || \ - (((bit)>>5)==11 && (1UL<<((bit)&31) & DISABLED_MASK11)) || \ - (((bit)>>5)==12 && (1UL<<((bit)&31) & DISABLED_MASK12)) || \ - (((bit)>>5)==13 && (1UL<<((bit)&31) & DISABLED_MASK13)) || \ - (((bit)>>5)==14 && (1UL<<((bit)&31) & DISABLED_MASK14)) || \ - (((bit)>>5)==15 && (1UL<<((bit)&31) & DISABLED_MASK15)) || \ - (((bit)>>5)==16 && (1UL<<((bit)&31) & DISABLED_MASK16)) || \ - (((bit)>>5)==17 && (1UL<<((bit)&31) & DISABLED_MASK17)) || \ - DISABLED_MASK_CHECK || \ +#define DISABLED_MASK_BIT_SET(feature_bit) \ + ( CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 0, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 1, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 2, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 3, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 4, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 5, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 6, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 7, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 8, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 9, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 10, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 11, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 12, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 13, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 14, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 15, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 16, feature_bit) || \ + CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 17, feature_bit) || \ + DISABLED_MASK_CHECK || \ BUILD_BUG_ON_ZERO(NCAPINTS != 18)) #define cpu_has(c, bit) \ From e353bf5f4c949044d840bd3466cc98cfc37b5222 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Fri, 18 May 2018 18:27:39 +0200 Subject: [PATCH 106/159] uprobes/x86: Remove incorrect WARN_ON() in uprobe_init_insn() commit 90718e32e1dcc2479acfa208ccfc6442850b594c upstream. insn_get_length() has the side-effect of processing the entire instruction but only if it was decoded successfully, otherwise insn_complete() can fail and in this case we need to just return an error without warning. Reported-by: syzbot+30d675e3ca03c1c351e7@syzkaller.appspotmail.com Signed-off-by: Oleg Nesterov Reviewed-by: Masami Hiramatsu Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: syzkaller-bugs@googlegroups.com Link: https://lkml.kernel.org/lkml/20180518162739.GA5559@redhat.com Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/uprobes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c index c6aace2bbe08..b8105289c60b 100644 --- a/arch/x86/kernel/uprobes.c +++ b/arch/x86/kernel/uprobes.c @@ -290,7 +290,7 @@ static int uprobe_init_insn(struct arch_uprobe *auprobe, struct insn *insn, bool insn_init(insn, auprobe->insn, sizeof(auprobe->insn), x86_64); /* has the side-effect of processing the entire instruction */ insn_get_length(insn); - if (WARN_ON_ONCE(!insn_complete(insn))) + if (!insn_complete(insn)) return -ENOEXEC; if (is_prefix_bad(insn)) From 2e8001533068752e0fe161cbfc6a8154c1ad3fac Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 13 Jun 2018 09:13:39 -0700 Subject: [PATCH 107/159] netfilter: nf_queue: augment nfqa_cfg_policy commit ba062ebb2cd561d404e0fba8ee4b3f5ebce7cbfc upstream. Three attributes are currently not verified, thus can trigger KMSAN warnings such as : BUG: KMSAN: uninit-value in __arch_swab32 arch/x86/include/uapi/asm/swab.h:10 [inline] BUG: KMSAN: uninit-value in __fswab32 include/uapi/linux/swab.h:59 [inline] BUG: KMSAN: uninit-value in nfqnl_recv_config+0x939/0x17d0 net/netfilter/nfnetlink_queue.c:1268 CPU: 1 PID: 4521 Comm: syz-executor120 Not tainted 4.17.0+ #5 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0x185/0x1d0 lib/dump_stack.c:113 kmsan_report+0x188/0x2a0 mm/kmsan/kmsan.c:1117 __msan_warning_32+0x70/0xc0 mm/kmsan/kmsan_instr.c:620 __arch_swab32 arch/x86/include/uapi/asm/swab.h:10 [inline] __fswab32 include/uapi/linux/swab.h:59 [inline] nfqnl_recv_config+0x939/0x17d0 net/netfilter/nfnetlink_queue.c:1268 nfnetlink_rcv_msg+0xb2e/0xc80 net/netfilter/nfnetlink.c:212 netlink_rcv_skb+0x37e/0x600 net/netlink/af_netlink.c:2448 nfnetlink_rcv+0x2fe/0x680 net/netfilter/nfnetlink.c:513 netlink_unicast_kernel net/netlink/af_netlink.c:1310 [inline] netlink_unicast+0x1680/0x1750 net/netlink/af_netlink.c:1336 netlink_sendmsg+0x104f/0x1350 net/netlink/af_netlink.c:1901 sock_sendmsg_nosec net/socket.c:629 [inline] sock_sendmsg net/socket.c:639 [inline] ___sys_sendmsg+0xec8/0x1320 net/socket.c:2117 __sys_sendmsg net/socket.c:2155 [inline] __do_sys_sendmsg net/socket.c:2164 [inline] __se_sys_sendmsg net/socket.c:2162 [inline] __x64_sys_sendmsg+0x331/0x460 net/socket.c:2162 do_syscall_64+0x15b/0x230 arch/x86/entry/common.c:287 entry_SYSCALL_64_after_hwframe+0x44/0xa9 RIP: 0033:0x43fd59 RSP: 002b:00007ffde0e30d28 EFLAGS: 00000213 ORIG_RAX: 000000000000002e RAX: ffffffffffffffda RBX: 00000000004002c8 RCX: 000000000043fd59 RDX: 0000000000000000 RSI: 0000000020000080 RDI: 0000000000000003 RBP: 00000000006ca018 R08: 00000000004002c8 R09: 00000000004002c8 R10: 00000000004002c8 R11: 0000000000000213 R12: 0000000000401680 R13: 0000000000401710 R14: 0000000000000000 R15: 0000000000000000 Uninit was created at: kmsan_save_stack_with_flags mm/kmsan/kmsan.c:279 [inline] kmsan_internal_poison_shadow+0xb8/0x1b0 mm/kmsan/kmsan.c:189 kmsan_kmalloc+0x94/0x100 mm/kmsan/kmsan.c:315 kmsan_slab_alloc+0x10/0x20 mm/kmsan/kmsan.c:322 slab_post_alloc_hook mm/slab.h:446 [inline] slab_alloc_node mm/slub.c:2753 [inline] __kmalloc_node_track_caller+0xb35/0x11b0 mm/slub.c:4395 __kmalloc_reserve net/core/skbuff.c:138 [inline] __alloc_skb+0x2cb/0x9e0 net/core/skbuff.c:206 alloc_skb include/linux/skbuff.h:988 [inline] netlink_alloc_large_skb net/netlink/af_netlink.c:1182 [inline] netlink_sendmsg+0x76e/0x1350 net/netlink/af_netlink.c:1876 sock_sendmsg_nosec net/socket.c:629 [inline] sock_sendmsg net/socket.c:639 [inline] ___sys_sendmsg+0xec8/0x1320 net/socket.c:2117 __sys_sendmsg net/socket.c:2155 [inline] __do_sys_sendmsg net/socket.c:2164 [inline] __se_sys_sendmsg net/socket.c:2162 [inline] __x64_sys_sendmsg+0x331/0x460 net/socket.c:2162 do_syscall_64+0x15b/0x230 arch/x86/entry/common.c:287 entry_SYSCALL_64_after_hwframe+0x44/0xa9 Fixes: fdb694a01f1f ("netfilter: Add fail-open support") Fixes: 829e17a1a602 ("[NETFILTER]: nfnetlink_queue: allow changing queue length through netlink") Signed-off-by: Eric Dumazet Reported-by: syzbot Signed-off-by: Pablo Neira Ayuso Signed-off-by: Greg Kroah-Hartman --- net/netfilter/nfnetlink_queue.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index 7edcfda288c4..54cde78c2718 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c @@ -1106,6 +1106,9 @@ nfqnl_recv_unsupp(struct sock *ctnl, struct sk_buff *skb, static const struct nla_policy nfqa_cfg_policy[NFQA_CFG_MAX+1] = { [NFQA_CFG_CMD] = { .len = sizeof(struct nfqnl_msg_config_cmd) }, [NFQA_CFG_PARAMS] = { .len = sizeof(struct nfqnl_msg_config_params) }, + [NFQA_CFG_QUEUE_MAXLEN] = { .type = NLA_U32 }, + [NFQA_CFG_MASK] = { .type = NLA_U32 }, + [NFQA_CFG_FLAGS] = { .type = NLA_U32 }, }; static const struct nf_queue_handler nfqh = { From 0319892f56fedd687c24dba6cd2094ff5bf58b39 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Thu, 7 Jun 2018 21:34:43 +0200 Subject: [PATCH 108/159] netfilter: x_tables: initialise match/target check parameter struct commit c568503ef02030f169c9e19204def610a3510918 upstream. syzbot reports following splat: BUG: KMSAN: uninit-value in ebt_stp_mt_check+0x24b/0x450 net/bridge/netfilter/ebt_stp.c:162 ebt_stp_mt_check+0x24b/0x450 net/bridge/netfilter/ebt_stp.c:162 xt_check_match+0x1438/0x1650 net/netfilter/x_tables.c:506 ebt_check_match net/bridge/netfilter/ebtables.c:372 [inline] ebt_check_entry net/bridge/netfilter/ebtables.c:702 [inline] The uninitialised access is xt_mtchk_param->nft_compat ... which should be set to 0. Fix it by zeroing the struct beforehand, same for tgchk. ip(6)tables targetinfo uses c99-style initialiser, so no change needed there. Reported-by: syzbot+da4494182233c23a5fcf@syzkaller.appspotmail.com Fixes: 55917a21d0cc0 ("netfilter: x_tables: add context to know if extension runs from nft_compat") Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso Signed-off-by: Greg Kroah-Hartman --- net/bridge/netfilter/ebtables.c | 2 ++ net/ipv4/netfilter/ip_tables.c | 1 + net/ipv6/netfilter/ip6_tables.c | 1 + 3 files changed, 4 insertions(+) diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 9f70c267a7a5..665fd87cc105 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -701,6 +701,8 @@ ebt_check_entry(struct ebt_entry *e, struct net *net, } i = 0; + memset(&mtpar, 0, sizeof(mtpar)); + memset(&tgpar, 0, sizeof(tgpar)); mtpar.net = tgpar.net = net; mtpar.table = tgpar.table = name; mtpar.entryinfo = tgpar.entryinfo = e; diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index dac62b5e7fe3..9363c1a70f16 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -663,6 +663,7 @@ find_check_entry(struct ipt_entry *e, struct net *net, const char *name, return -ENOMEM; j = 0; + memset(&mtpar, 0, sizeof(mtpar)); mtpar.net = net; mtpar.table = name; mtpar.entryinfo = &e->ip; diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 795c343347ec..6cb9e35d23ac 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -676,6 +676,7 @@ find_check_entry(struct ip6t_entry *e, struct net *net, const char *name, return -ENOMEM; j = 0; + memset(&mtpar, 0, sizeof(mtpar)); mtpar.net = net; mtpar.table = name; mtpar.entryinfo = &e->ipv6; From 2250809623141f969531692c2629dffd463dbaa6 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Mon, 7 May 2018 11:37:58 -0400 Subject: [PATCH 109/159] loop: add recursion validation to LOOP_CHANGE_FD commit d2ac838e4cd7e5e9891ecc094d626734b0245c99 upstream. Refactor the validation code used in LOOP_SET_FD so it is also used in LOOP_CHANGE_FD. Otherwise it is possible to construct a set of loop devices that all refer to each other. This can lead to a infinite loop in starting with "while (is_loop_device(f)) .." in loop_set_fd(). Fix this by refactoring out the validation code and using it for LOOP_CHANGE_FD as well as LOOP_SET_FD. Reported-by: syzbot+4349872271ece473a7c91190b68b4bac7c5dbc87@syzkaller.appspotmail.com Reported-by: syzbot+40bd32c4d9a3cc12a339@syzkaller.appspotmail.com Reported-by: syzbot+769c54e66f994b041be7@syzkaller.appspotmail.com Reported-by: syzbot+0a89a9ce473936c57065@syzkaller.appspotmail.com Signed-off-by: Theodore Ts'o Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- drivers/block/loop.c | 68 +++++++++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 30 deletions(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index e8165ec55e6f..aaa7000a4342 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -651,6 +651,36 @@ static void loop_reread_partitions(struct loop_device *lo, __func__, lo->lo_number, lo->lo_file_name, rc); } +static inline int is_loop_device(struct file *file) +{ + struct inode *i = file->f_mapping->host; + + return i && S_ISBLK(i->i_mode) && MAJOR(i->i_rdev) == LOOP_MAJOR; +} + +static int loop_validate_file(struct file *file, struct block_device *bdev) +{ + struct inode *inode = file->f_mapping->host; + struct file *f = file; + + /* Avoid recursion */ + while (is_loop_device(f)) { + struct loop_device *l; + + if (f->f_mapping->host->i_bdev == bdev) + return -EBADF; + + l = f->f_mapping->host->i_bdev->bd_disk->private_data; + if (l->lo_state == Lo_unbound) { + return -EINVAL; + } + f = l->lo_backing_file; + } + if (!S_ISREG(inode->i_mode) && !S_ISBLK(inode->i_mode)) + return -EINVAL; + return 0; +} + /* * loop_change_fd switched the backing store of a loopback device to * a new file. This is useful for operating system installers to free up @@ -680,14 +710,15 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev, if (!file) goto out; + error = loop_validate_file(file, bdev); + if (error) + goto out_putf; + inode = file->f_mapping->host; old_file = lo->lo_backing_file; error = -EINVAL; - if (!S_ISREG(inode->i_mode) && !S_ISBLK(inode->i_mode)) - goto out_putf; - /* size of the new backing store needs to be the same */ if (get_loop_size(lo, file) != get_loop_size(lo, old_file)) goto out_putf; @@ -708,13 +739,6 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev, return error; } -static inline int is_loop_device(struct file *file) -{ - struct inode *i = file->f_mapping->host; - - return i && S_ISBLK(i->i_mode) && MAJOR(i->i_rdev) == LOOP_MAJOR; -} - /* loop sysfs attributes */ static ssize_t loop_attr_show(struct device *dev, char *page, @@ -872,7 +896,7 @@ static int loop_prepare_queue(struct loop_device *lo) static int loop_set_fd(struct loop_device *lo, fmode_t mode, struct block_device *bdev, unsigned int arg) { - struct file *file, *f; + struct file *file; struct inode *inode; struct address_space *mapping; unsigned lo_blocksize; @@ -892,29 +916,13 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode, if (lo->lo_state != Lo_unbound) goto out_putf; - /* Avoid recursion */ - f = file; - while (is_loop_device(f)) { - struct loop_device *l; - - if (f->f_mapping->host->i_bdev == bdev) - goto out_putf; - - l = f->f_mapping->host->i_bdev->bd_disk->private_data; - if (l->lo_state == Lo_unbound) { - error = -EINVAL; - goto out_putf; - } - f = l->lo_backing_file; - } + error = loop_validate_file(file, bdev); + if (error) + goto out_putf; mapping = file->f_mapping; inode = mapping->host; - error = -EINVAL; - if (!S_ISREG(inode->i_mode) && !S_ISBLK(inode->i_mode)) - goto out_putf; - if (!(file->f_mode & FMODE_WRITE) || !(mode & FMODE_WRITE) || !file->f_op->write_iter) lo_flags |= LO_FLAGS_READ_ONLY; From a4ae35d6789d187e2763db87fee4d118c576f907 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Sat, 26 May 2018 09:59:36 +0900 Subject: [PATCH 110/159] PM / hibernate: Fix oops at snapshot_write() commit fc14eebfc20854a38fd9f1d93a42b1783dad4d17 upstream. syzbot is reporting NULL pointer dereference at snapshot_write() [1]. This is because data->handle is zero-cleared by ioctl(SNAPSHOT_FREE). Fix this by checking data_of(data->handle) != NULL before using it. [1] https://syzkaller.appspot.com/bug?id=828a3c71bd344a6de8b6a31233d51a72099f27fd Signed-off-by: Tetsuo Handa Reported-by: syzbot Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- kernel/power/user.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/kernel/power/user.c b/kernel/power/user.c index 526e8911460a..f83c1876b39c 100644 --- a/kernel/power/user.c +++ b/kernel/power/user.c @@ -184,6 +184,11 @@ static ssize_t snapshot_write(struct file *filp, const char __user *buf, res = PAGE_SIZE - pg_offp; } + if (!data_of(data->handle)) { + res = -EINVAL; + goto unlock; + } + res = simple_write_to_buffer(data_of(data->handle), res, &pg_offp, buf, count); if (res > 0) From 28db2b23f44c4a15e431327e488fc0680c4aceb0 Mon Sep 17 00:00:00 2001 From: Leon Romanovsky Date: Wed, 23 May 2018 08:22:11 +0300 Subject: [PATCH 111/159] RDMA/ucm: Mark UCM interface as BROKEN commit 7a8690ed6f5346f6738971892205e91d39b6b901 upstream. In commit 357d23c811a7 ("Remove the obsolete libibcm library") in rdma-core [1], we removed obsolete library which used the /dev/infiniband/ucmX interface. Following multiple syzkaller reports about non-sanitized user input in the UCMA module, the short audit reveals the same issues in UCM module too. It is better to disable this interface in the kernel, before syzkaller team invests time and energy to harden this unused interface. [1] https://github.com/linux-rdma/rdma-core/pull/279 Signed-off-by: Leon Romanovsky Signed-off-by: Jason Gunthorpe Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/Kconfig | 12 ++++++++++++ drivers/infiniband/core/Makefile | 4 ++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/infiniband/Kconfig b/drivers/infiniband/Kconfig index aa26f3c3416b..c151bb625179 100644 --- a/drivers/infiniband/Kconfig +++ b/drivers/infiniband/Kconfig @@ -33,6 +33,18 @@ config INFINIBAND_USER_ACCESS libibverbs, libibcm and a hardware driver library from . +config INFINIBAND_USER_ACCESS_UCM + bool "Userspace CM (UCM, DEPRECATED)" + depends on BROKEN + depends on INFINIBAND_USER_ACCESS + help + The UCM module has known security flaws, which no one is + interested to fix. The user-space part of this code was + dropped from the upstream a long time ago. + + This option is DEPRECATED and planned to be removed. + + config INFINIBAND_USER_MEM bool depends on INFINIBAND_USER_ACCESS != n diff --git a/drivers/infiniband/core/Makefile b/drivers/infiniband/core/Makefile index d43a8994ac5c..737612a442be 100644 --- a/drivers/infiniband/core/Makefile +++ b/drivers/infiniband/core/Makefile @@ -5,8 +5,8 @@ obj-$(CONFIG_INFINIBAND) += ib_core.o ib_mad.o ib_sa.o \ ib_cm.o iw_cm.o ib_addr.o \ $(infiniband-y) obj-$(CONFIG_INFINIBAND_USER_MAD) += ib_umad.o -obj-$(CONFIG_INFINIBAND_USER_ACCESS) += ib_uverbs.o ib_ucm.o \ - $(user_access-y) +obj-$(CONFIG_INFINIBAND_USER_ACCESS) += ib_uverbs.o $(user_access-y) +obj-$(CONFIG_INFINIBAND_USER_ACCESS_UCM) += ib_ucm.o $(user_access-y) ib_core-y := packer.o ud_header.o verbs.o sysfs.o \ device.o fmr_pool.o cache.o netlink.o \ From 43991e916eb9eac9ea0ef0317f9bfd3c491972cb Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Fri, 4 May 2018 10:58:09 -0600 Subject: [PATCH 112/159] loop: remember whether sysfs_create_group() was done commit d3349b6b3c373ac1fbfb040b810fcee5e2adc7e0 upstream. syzbot is hitting WARN() triggered by memory allocation fault injection [1] because loop module is calling sysfs_remove_group() when sysfs_create_group() failed. Fix this by remembering whether sysfs_create_group() succeeded. [1] https://syzkaller.appspot.com/bug?id=3f86c0edf75c86d2633aeb9dd69eccc70bc7e90b Signed-off-by: Tetsuo Handa Reported-by: syzbot Reviewed-by: Greg Kroah-Hartman Renamed sysfs_ready -> sysfs_inited. Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- drivers/block/loop.c | 11 ++++++----- drivers/block/loop.h | 1 + 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index aaa7000a4342..da3902ac16c8 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -835,16 +835,17 @@ static struct attribute_group loop_attribute_group = { .attrs= loop_attrs, }; -static int loop_sysfs_init(struct loop_device *lo) +static void loop_sysfs_init(struct loop_device *lo) { - return sysfs_create_group(&disk_to_dev(lo->lo_disk)->kobj, - &loop_attribute_group); + lo->sysfs_inited = !sysfs_create_group(&disk_to_dev(lo->lo_disk)->kobj, + &loop_attribute_group); } static void loop_sysfs_exit(struct loop_device *lo) { - sysfs_remove_group(&disk_to_dev(lo->lo_disk)->kobj, - &loop_attribute_group); + if (lo->sysfs_inited) + sysfs_remove_group(&disk_to_dev(lo->lo_disk)->kobj, + &loop_attribute_group); } static void loop_config_discard(struct loop_device *lo) diff --git a/drivers/block/loop.h b/drivers/block/loop.h index fb2237c73e61..60f0fd2c0c65 100644 --- a/drivers/block/loop.h +++ b/drivers/block/loop.h @@ -59,6 +59,7 @@ struct loop_device { struct kthread_worker worker; struct task_struct *worker_task; bool use_dio; + bool sysfs_inited; struct request_queue *lo_queue; struct blk_mq_tag_set tag_set; From b3c6be58aa1056418198c893d8a15ea4e79c8bf1 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 17 Jul 2018 11:31:46 +0200 Subject: [PATCH 113/159] Linux 4.4.141 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index b842298a5970..3fc39e41dbde 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 4 PATCHLEVEL = 4 -SUBLEVEL = 140 +SUBLEVEL = 141 EXTRAVERSION = NAME = Blurry Fish Butt From 8be65bee667c18fdccdc185ab8135a66d5b6004e Mon Sep 17 00:00:00 2001 From: Tim Murray Date: Thu, 20 Oct 2016 13:53:58 -0700 Subject: [PATCH 114/159] firmware_class: make firmware caching configurable Because firmware caching generates uevent messages that are sent over a netlink socket, it can prevent suspend on many platforms. It's also not always useful, so make it a configurable option. bug 32180327 Change-Id: I1250512b27edb56caa78d536e5ccf1fb669476ad Signed-off-by: Tim Murray Git-repo: https://source.codeaurora.org/quic/la/kernel/msm-4.4 Git-commit: e3198d51be98ec5606e2a2c5112a8a974d354fbc Signed-off-by: Chintan Pandya Signed-off-by: Srinivasarao P --- drivers/base/Kconfig | 5 +++++ drivers/base/firmware_class.c | 8 ++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig index 59992788966c..602cbb04bee8 100644 --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig @@ -165,6 +165,11 @@ config FW_LOADER_USER_HELPER_FALLBACK If you are unsure about this, say N here. +config FW_CACHE + bool "Enable firmware caching during suspend" + depends on PM_SLEEP + default n + config WANT_DEV_COREDUMP bool help diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index a1696e1d199f..c1093c0d4dea 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -1148,7 +1148,7 @@ static int fw_load_from_user_helper(struct firmware *firmware, return _request_firmware_load(fw_priv, desc->opt_flags, timeout); } -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_FW_CACHE /* kill pending requests without uevent to avoid blocking suspend */ static void kill_requests_without_uevent(void) { @@ -1626,7 +1626,7 @@ request_firmware_nowait_into_buf( } EXPORT_SYMBOL_GPL(request_firmware_nowait_into_buf); -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_FW_CACHE static ASYNC_DOMAIN_EXCLUSIVE(fw_cache_domain); /** @@ -1972,7 +1972,7 @@ static void __init fw_cache_init(void) INIT_LIST_HEAD(&fw_cache.head); fw_cache.state = FW_LOADER_NO_CACHE; -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_FW_CACHE spin_lock_init(&fw_cache.name_lock); INIT_LIST_HEAD(&fw_cache.fw_names); @@ -1999,7 +1999,7 @@ static int __init firmware_class_init(void) static void __exit firmware_class_exit(void) { -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_FW_CACHE unregister_syscore_ops(&fw_syscore_ops); unregister_pm_notifier(&fw_cache.pm_notify); #endif From 72c7b7b08e2fc3a28fd69fbae4de98a48acfaaa0 Mon Sep 17 00:00:00 2001 From: Atul Raut Date: Fri, 11 May 2018 18:31:04 -0700 Subject: [PATCH 115/159] ARM: dts: msm: Change thermal configuration settings for msm8996. msm-core(EA in kernel part) is enabled for thermal monitoring feature. It sets cpu tsens threshold independent of thermal SW but not really using any thermal info in driver. So redundant threshold get sets which causes wakable irq to fire in hibernation restore phase. That abort's system wide suspend transition which eventually fail to restore hibernation image. To fix, set thermal configuration to new threshold. Change-Id: I38cad5217c1196d3a804fa78570984e60427a94e Signed-off-by: Atul Raut --- arch/arm/boot/dts/qcom/msm8996.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/qcom/msm8996.dtsi b/arch/arm/boot/dts/qcom/msm8996.dtsi index c77d7fd9869c..95b100e10e5b 100644 --- a/arch/arm/boot/dts/qcom/msm8996.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996.dtsi @@ -2983,8 +2983,8 @@ qcom,msm-core@70000 { compatible = "qcom,apss-core-ea"; reg = <0x70000 0x1000>; - qcom,low-hyst-temp = <10>; - qcom,high-hyst-temp = <5>; + qcom,low-hyst-temp = <100>; + qcom,high-hyst-temp = <100>; qcom,polling-interval = <50>; ea0: ea0 { From faa4206fb7241a3ff1ceba48d6cd29e92d312f7f Mon Sep 17 00:00:00 2001 From: Rahul Sharma Date: Mon, 9 Jul 2018 23:48:12 +0530 Subject: [PATCH 116/159] drm/sde: bridge chip error and smmu fault handling for recovery This implementation adds the following support: 1. handle bridge chip error reported by driver to DBA. error reported to DBA will be send to recovery manager to recover the faulty bridge chip by performing a power cycle. 2. smmu fault error notification. 3. detection on errors in bridge chip driver. Change-Id: I86cc491e3cd25fdcf9b998a0d687baba0a06d836 Signed-off-by: Rahul Sharma --- drivers/gpu/drm/msm/dba_bridge.c | 74 +++++++++++++++++++ drivers/gpu/drm/msm/msm_mmu.h | 4 + drivers/gpu/drm/msm/msm_smmu.c | 12 +++ drivers/gpu/drm/msm/sde/sde_kms.c | 21 +++++- .../gpu/drm/msm/sde/sde_recovery_manager.h | 8 +- drivers/video/fbdev/msm/msm_dba/adv7533.c | 4 + include/video/msm_dba.h | 7 +- 7 files changed, 127 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/msm/dba_bridge.c b/drivers/gpu/drm/msm/dba_bridge.c index 62294ddf8034..cfab8c73a1ad 100644 --- a/drivers/gpu/drm/msm/dba_bridge.c +++ b/drivers/gpu/drm/msm/dba_bridge.c @@ -16,6 +16,7 @@ #include "drm_edid.h" #include "sde_kms.h" #include "dba_bridge.h" +#include "sde/sde_recovery_manager.h" #undef pr_fmt #define pr_fmt(fmt) "dba_bridge:[%s] " fmt, __func__ @@ -36,6 +37,7 @@ * @num_of_input_lanes: Number of input lanes in case of DSI/LVDS * @pluggable: If it's pluggable * @panel_count: Number of panels attached to this display + * @client_info: bridge chip specific information for recovery manager */ struct dba_bridge { struct drm_bridge base; @@ -52,12 +54,17 @@ struct dba_bridge { bool pluggable; u32 panel_count; bool cont_splash_enabled; + struct recovery_client_info client_info; }; #define to_dba_bridge(x) container_of((x), struct dba_bridge, base) +static int _dba_bridge_recovery_callback(int err_code, + struct recovery_client_info *client_info); + static void _dba_bridge_cb(void *data, enum msm_dba_callback_event event) { struct dba_bridge *d_bridge = data; + int chip_err; if (!d_bridge) { SDE_ERROR("Invalid data\n"); @@ -73,6 +80,12 @@ static void _dba_bridge_cb(void *data, enum msm_dba_callback_event event) case MSM_DBA_CB_HPD_DISCONNECT: DRM_DEBUG("HPD DISCONNECT\n"); break; + case MSM_DBA_CB_DDC_I2C_ERROR: + case MSM_DBA_CB_DDC_TIMEOUT: + DRM_DEBUG("DDC FAILURE\n"); + chip_err = DBA_BRIDGE_CRITICAL_ERR + d_bridge->id; + sde_recovery_set_events(chip_err); + break; default: DRM_DEBUG("event:%d is not supported\n", event); break; @@ -83,6 +96,7 @@ static int _dba_bridge_attach(struct drm_bridge *bridge) { struct dba_bridge *d_bridge = to_dba_bridge(bridge); struct msm_dba_reg_info info; + struct recovery_client_info *client_info = &d_bridge->client_info; int ret = 0; if (!bridge) { @@ -115,6 +129,25 @@ static int _dba_bridge_attach(struct drm_bridge *bridge) goto error; } + snprintf(client_info->name, MAX_REC_NAME_LEN, "%s_%d", + d_bridge->chip_name, d_bridge->id); + + client_info->recovery_cb = _dba_bridge_recovery_callback; + + /* Identify individual chip by different error codes */ + client_info->err_supported[0].reported_err_code = + DBA_BRIDGE_CRITICAL_ERR + d_bridge->id; + client_info->err_supported[0].pre_err_code = 0; + client_info->err_supported[0].post_err_code = 0; + client_info->no_of_err = 1; + /* bridge chip context */ + client_info->pdata = d_bridge; + + ret = sde_recovery_client_register(client_info); + if (ret) + SDE_ERROR("%s recovery mgr register failed %d\n", + __func__, ret); + DRM_INFO("client:%s bridge:[%s:%d] attached\n", d_bridge->client_name, d_bridge->chip_name, d_bridge->id); @@ -239,6 +272,44 @@ static void _dba_bridge_post_disable(struct drm_bridge *bridge) } } +static int _dba_bridge_recovery_callback(int err_code, + struct recovery_client_info *client_info) +{ + int rc = 0; + struct dba_bridge *d_bridge; + + if (!client_info) { + SDE_ERROR("Invalid client info\n"); + rc = -EINVAL; + return rc; + } + + d_bridge = client_info->pdata; + + err_code = err_code - d_bridge->id; + + switch (err_code) { + case DBA_BRIDGE_CRITICAL_ERR: + SDE_DEBUG("%s critical bridge chip error\n", __func__); + + /* Power OFF */ + _dba_bridge_disable(&d_bridge->base); + _dba_bridge_post_disable(&d_bridge->base); + + /* settle power rails */ + msleep(100); + + /* Power On */ + _dba_bridge_pre_enable(&d_bridge->base); + _dba_bridge_enable(&d_bridge->base); + + break; + default: + SDE_ERROR("%s error %d undefined\n", __func__, err_code); + } + return rc; +} + static void _dba_bridge_mode_set(struct drm_bridge *bridge, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) @@ -369,6 +440,9 @@ void dba_bridge_cleanup(struct drm_bridge *bridge) if (!bridge) return; + sde_recovery_client_unregister(d_bridge->client_info.handle); + d_bridge->client_info.handle = NULL; + if (IS_ENABLED(CONFIG_MSM_DBA)) { if (!IS_ERR_OR_NULL(d_bridge->dba_ctx)) msm_dba_deregister_client(d_bridge->dba_ctx); diff --git a/drivers/gpu/drm/msm/msm_mmu.h b/drivers/gpu/drm/msm/msm_mmu.h index 74dea95d90de..03f8a55255c9 100644 --- a/drivers/gpu/drm/msm/msm_mmu.h +++ b/drivers/gpu/drm/msm/msm_mmu.h @@ -93,4 +93,8 @@ static inline void msm_mmu_disable(struct msm_mmu *mmu) int __init msm_smmu_driver_init(void); void __exit msm_smmu_driver_cleanup(void); +/* register custom fault handler for a specific domain */ +void msm_smmu_register_fault_handler(struct msm_mmu *mmu, + iommu_fault_handler_t handler); + #endif /* __MSM_MMU_H__ */ diff --git a/drivers/gpu/drm/msm/msm_smmu.c b/drivers/gpu/drm/msm/msm_smmu.c index aefbe0988fe5..eed3cfcb99ee 100644 --- a/drivers/gpu/drm/msm/msm_smmu.c +++ b/drivers/gpu/drm/msm/msm_smmu.c @@ -335,6 +335,18 @@ static struct device *msm_smmu_device_create(struct device *dev, return &pdev->dev; } +void msm_smmu_register_fault_handler(struct msm_mmu *mmu, + iommu_fault_handler_t handler) +{ + struct msm_smmu *smmu = to_msm_smmu(mmu); + struct msm_smmu_client *client = msm_smmu_to_client(smmu); + + if (client) + iommu_set_fault_handler(client->mmu_mapping->domain, + handler, client->dev); + +} + struct msm_mmu *msm_smmu_new(struct device *dev, enum msm_mmu_domain_type domain) { diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c index bd8f3701a282..5247ec51cabf 100644 --- a/drivers/gpu/drm/msm/sde/sde_kms.c +++ b/drivers/gpu/drm/msm/sde/sde_kms.c @@ -67,7 +67,8 @@ static struct recovery_client_info info = { .recovery_cb = sde_kms_recovery_callback, .err_supported[0] = {SDE_UNDERRUN, 0, 0}, .err_supported[1] = {SDE_VSYNC_MISS, 0, 0}, - .no_of_err = 2, + .err_supported[2] = {SDE_SMMU_FAULT, 0, 0}, + .no_of_err = 3, .handle = NULL, .pdata = NULL, }; @@ -1140,6 +1141,18 @@ static int _sde_kms_mmu_destroy(struct sde_kms *sde_kms) return 0; } +static int sde_smmu_fault_handler(struct iommu_domain *iommu, + struct device *dev, unsigned long iova, int flags, void *arg) +{ + + dev_info(dev, "%s: iova=0x%08lx, flags=0x%x, iommu=%pK\n", __func__, + iova, flags, iommu); + + sde_recovery_set_events(SDE_SMMU_FAULT); + + return 0; +} + static int _sde_kms_mmu_init(struct sde_kms *sde_kms) { struct msm_mmu *mmu; @@ -1158,6 +1171,8 @@ static int _sde_kms_mmu_init(struct sde_kms *sde_kms) continue; } + msm_smmu_register_fault_handler(mmu, sde_smmu_fault_handler); + /* Attaching smmu means IOMMU HW starts to work immediately. * However, display HW in LK is still accessing memory * while the memory map is not done yet. @@ -1523,6 +1538,10 @@ static int sde_kms_recovery_callback(int err_code, pr_debug("%s [SDE_VSYNC_MISS] trigger soft reset\n", __func__); break; + case SDE_SMMU_FAULT: + pr_debug("%s [SDE_SMMU_FAULT] trigger soft reset\n", __func__); + break; + default: pr_err("%s error %d undefined\n", __func__, err_code); diff --git a/drivers/gpu/drm/msm/sde/sde_recovery_manager.h b/drivers/gpu/drm/msm/sde/sde_recovery_manager.h index 32fe17a187a0..aeaecbd194f4 100644 --- a/drivers/gpu/drm/msm/sde/sde_recovery_manager.h +++ b/drivers/gpu/drm/msm/sde/sde_recovery_manager.h @@ -29,11 +29,17 @@ #define MAX_REC_NAME_LEN (16) #define MAX_REC_UEVENT_LEN (64) -#define MAX_REC_ERR_SUPPORT (2) +#define MAX_REC_ERR_SUPPORT (3) /* MSM Recovery Manager Error Code */ +#define SDE_SMMU_FAULT 111 #define SDE_UNDERRUN 222 #define SDE_VSYNC_MISS 333 +/* + * instance id of bridge chip is added to make error code + * unique to individual bridge chip instance + */ +#define DBA_BRIDGE_CRITICAL_ERR 444 /** * struct recovery_mgr_info - Recovery manager information diff --git a/drivers/video/fbdev/msm/msm_dba/adv7533.c b/drivers/video/fbdev/msm/msm_dba/adv7533.c index 15fe77d05091..a21b6db85ed8 100644 --- a/drivers/video/fbdev/msm/msm_dba/adv7533.c +++ b/drivers/video/fbdev/msm/msm_dba/adv7533.c @@ -885,9 +885,13 @@ static void adv7533_handle_hdcp_intr(struct adv7533 *pdata, u8 hdcp_status) break; case 4: pr_err("%s: DDC: I2C ERROR\n", __func__); + adv7533_notify_clients(&pdata->dev_info, + MSM_DBA_CB_DDC_I2C_ERROR); break; case 5: pr_err("%s: DDC: TIMED OUT DS DONE\n", __func__); + adv7533_notify_clients(&pdata->dev_info, + MSM_DBA_CB_DDC_TIMEOUT); break; case 6: pr_err("%s: DDC: MAX CAS EXC\n", __func__); diff --git a/include/video/msm_dba.h b/include/video/msm_dba.h index 3d20fd8d65eb..8ce2138044c3 100644 --- a/include/video/msm_dba.h +++ b/include/video/msm_dba.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2015,2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -53,6 +53,9 @@ * @MSM_DBA_CB_POST_RESET: This callback is called after device reset is * complete and the driver has applied back all the * properties. + * @MSM_DBA_CB_DDC_I2C_ERROR: Detected a failure in DDC block for i2c error. + * @MSM_DBA_CB_DDC_TIMEOUT: Detected a failure in DDC block for timed out + * waiting for downstream receiver. * * Clients for this driver can register for receiving callbacks for specific * events. This enum defines the type of events supported by the driver. An @@ -71,6 +74,8 @@ enum msm_dba_callback_event { MSM_DBA_CB_CEC_READ_PENDING = BIT(9), MSM_DBA_CB_PRE_RESET = BIT(10), MSM_DBA_CB_POST_RESET = BIT(11), + MSM_DBA_CB_DDC_I2C_ERROR = BIT(12), + MSM_DBA_CB_DDC_TIMEOUT = BIT(13), }; /** From 4b97647dc2b02b986c9de17eaf7ac7d6dc09831d Mon Sep 17 00:00:00 2001 From: Mohit Aggarwal Date: Mon, 9 Jul 2018 16:03:37 +0530 Subject: [PATCH 117/159] diag: Featurize IPC logging Currently, in case IPC logging related config is disabled then there are some unwanted error logs in kernel logs. Featurize IPC logging to get rid of error logs. Change-Id: I8455f5e3a13cf58b4d65d1e1a5c4f1ec0adedabf Signed-off-by: Mohit Aggarwal --- drivers/char/diag/diag_debugfs.c | 7 ++++++- drivers/char/diag/diag_ipc_logging.h | 4 +--- drivers/char/diag/diagchar_core.c | 4 ++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/char/diag/diag_debugfs.c b/drivers/char/diag/diag_debugfs.c index ad370ada335f..3d916e790814 100644 --- a/drivers/char/diag/diag_debugfs.c +++ b/drivers/char/diag/diag_debugfs.c @@ -800,6 +800,7 @@ static ssize_t diag_dbgfs_read_glinkinfo(struct file *file, char __user *ubuf, return ret; } +#ifdef CONFIG_IPC_LOGGING static ssize_t diag_dbgfs_write_debug(struct file *fp, const char __user *buf, size_t count, loff_t *ppos) { @@ -830,6 +831,7 @@ static ssize_t diag_dbgfs_write_debug(struct file *fp, const char __user *buf, diag_debug_mask = (uint16_t)value; return count; } +#endif #ifdef CONFIG_DIAGFWD_BRIDGE_CODE #ifdef CONFIG_USB_QCOM_DIAG_BRIDGE @@ -1087,9 +1089,11 @@ const struct file_operations diag_dbgfs_power_ops = { .read = diag_dbgfs_read_power, }; +#ifdef CONFIG_IPC_LOGGING const struct file_operations diag_dbgfs_debug_ops = { .write = diag_dbgfs_write_debug }; +#endif int diag_debugfs_init(void) { @@ -1144,11 +1148,12 @@ int diag_debugfs_init(void) if (!entry) goto err; +#ifdef CONFIG_IPC_LOGGING entry = debugfs_create_file("debug", 0444, diag_dbgfs_dent, 0, &diag_dbgfs_debug_ops); if (!entry) goto err; - +#endif #ifdef CONFIG_DIAGFWD_BRIDGE_CODE entry = debugfs_create_file("bridge", 0444, diag_dbgfs_dent, 0, &diag_dbgfs_bridge_ops); diff --git a/drivers/char/diag/diag_ipc_logging.h b/drivers/char/diag/diag_ipc_logging.h index 4b8dd1b12c1c..839c8ca02e7c 100644 --- a/drivers/char/diag/diag_ipc_logging.h +++ b/drivers/char/diag/diag_ipc_logging.h @@ -26,9 +26,7 @@ #define DIAG_DEBUG_BRIDGE 0x0040 #define DIAG_DEBUG_CONTROL 0x0080 -#define DIAG_DEBUG - -#ifdef DIAG_DEBUG +#ifdef CONFIG_IPC_LOGGING extern uint16_t diag_debug_mask; extern void *diag_ipc_log; diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c index 32f70fa2d37c..2bac98117c03 100644 --- a/drivers/char/diag/diagchar_core.c +++ b/drivers/char/diag/diagchar_core.c @@ -165,7 +165,7 @@ static struct mutex apps_data_mutex; #define DIAGPKT_MAX_DELAYED_RSP 0xFFFF -#ifdef DIAG_DEBUG +#ifdef CONFIG_IPC_LOGGING uint16_t diag_debug_mask; void *diag_ipc_log; #endif @@ -3626,7 +3626,7 @@ void diag_ws_release() pm_relax(driver->diag_dev); } -#ifdef DIAG_DEBUG +#ifdef CONFIG_IPC_LOGGING static void diag_debug_init(void) { diag_ipc_log = ipc_log_context_create(DIAG_IPC_LOG_PAGES, "diag", 0); From 5dda52d4de3d6552d8c3eec39ee70de0f83dbc12 Mon Sep 17 00:00:00 2001 From: Nirmal Abraham Date: Tue, 17 Jul 2018 15:49:19 +0530 Subject: [PATCH 118/159] msm: mdss: cleanup used pipes during overlay off During overlay off, cleanup pipes which are currently active in used pipes list. This is to avoid to a race condition wherein the pipe params gets changed in prepare cycle, but the commit cylce has not executed to queue the buffers associated with the pipe and the same pipe which has old buffer(stale content) gets used from overlay_off flow. Change-Id: I117e6ee9854ff287f7bb1055ca745760db980bed Signed-off-by: Nirmal Abraham --- drivers/video/fbdev/msm/mdss_mdp_overlay.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c index 2f5b45638cdb..f3d125af4830 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c +++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c @@ -5815,6 +5815,7 @@ static int mdss_mdp_overlay_off(struct msm_fb_data_type *mfd) int rc; struct mdss_overlay_private *mdp5_data; struct mdss_mdp_mixer *mixer; + struct mdss_mdp_pipe *pipe, *tmp; int need_cleanup; int retire_cnt; bool destroy_ctl = false; @@ -5870,6 +5871,13 @@ static int mdss_mdp_overlay_off(struct msm_fb_data_type *mfd) mixer->cursor_enabled = 0; mutex_lock(&mdp5_data->list_lock); + if (!list_empty(&mdp5_data->pipes_used)) { + list_for_each_entry_safe( + pipe, tmp, &mdp5_data->pipes_used, list) { + pipe->file = NULL; + list_move(&pipe->list, &mdp5_data->pipes_cleanup); + } + } need_cleanup = !list_empty(&mdp5_data->pipes_cleanup); mutex_unlock(&mdp5_data->list_lock); mutex_unlock(&mdp5_data->ov_lock); From eb119bcb2aa86a2847efe3bc43e9af59db8059ed Mon Sep 17 00:00:00 2001 From: Balachandra C S Date: Thu, 24 May 2018 19:46:25 +0530 Subject: [PATCH 119/159] drivers: net: can: Add timestamp adjustment for frames in qti-can Correct the frame timestamp based on the controller and host time difference. Change-Id: I6c60b943d18779a9bd9f221a2344dcea90b9fb5a Signed-off-by: Balachandra C S --- drivers/net/can/spi/qti-can.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/drivers/net/can/spi/qti-can.c b/drivers/net/can/spi/qti-can.c index 27294c74fcd6..7083d0011b18 100644 --- a/drivers/net/can/spi/qti-can.c +++ b/drivers/net/can/spi/qti-can.c @@ -70,6 +70,7 @@ struct qti_can { bool can_fw_cmd_timeout_req; u32 rem_all_buffering_timeout_ms; u32 can_fw_cmd_timeout_ms; + s64 time_diff; }; struct qti_can_netdev_privdata { @@ -119,6 +120,7 @@ struct spi_miso { /* TLV for MISO line */ #define CMD_BOOT_ROM_UPGRADE_DATA 0x9A #define CMD_END_BOOT_ROM_UPGRADE 0x9B #define CMD_END_FW_UPDATE_FILE 0x9C +#define CMD_UPDATE_TIME_INFO 0x9D #define IOCTL_RELEASE_CAN_BUFFER (SIOCDEVPRIVATE + 0) #define IOCTL_ENABLE_BUFFERING (SIOCDEVPRIVATE + 1) @@ -165,7 +167,7 @@ struct can_add_filter_resp { struct can_receive_frame { u8 can_if; - u32 ts; + __le64 ts; u32 mid; u8 dlc; u8 data[8]; @@ -180,6 +182,10 @@ struct can_config_bit_timing { u32 brp; } __packed; +struct can_time_info { + __le64 time; +} __packed; + static struct can_bittiming_const rh850_bittiming_const = { .name = "qti_can", .tseg1_min = 1, @@ -293,7 +299,7 @@ static void qti_can_receive_frame(struct qti_can *priv_data, return; } - LOGDI("rcv frame %d %d %x %d %x %x %x %x %x %x %x %x\n", + LOGDI("rcv frame %d %llu %x %d %x %x %x %x %x %x %x %x\n", frame->can_if, frame->ts, frame->mid, frame->dlc, frame->data[0], frame->data[1], frame->data[2], frame->data[3], frame->data[4], frame->data[5], frame->data[6], frame->data[7]); @@ -303,7 +309,8 @@ static void qti_can_receive_frame(struct qti_can *priv_data, for (i = 0; i < cf->can_dlc; i++) cf->data[i] = frame->data[i]; - nsec = ms_to_ktime(le32_to_cpu(frame->ts)); + nsec = ms_to_ktime(le64_to_cpu(frame->ts) + priv_data->time_diff); + skt = skb_hwtstamps(skb); skt->hwtstamp = nsec; LOGDI(" hwtstamp %lld\n", ktime_to_ms(skt->hwtstamp)); @@ -356,6 +363,8 @@ static int qti_can_process_response(struct qti_can *priv_data, struct spi_miso *resp, int length) { int ret = 0; + u64 mstime; + ktime_t ktime_now; LOGDI("<%x %2d [%d]\n", resp->cmd, resp->len, resp->seq); if (resp->cmd == CMD_CAN_RECEIVE_FRAME) { @@ -404,6 +413,12 @@ static int qti_can_process_response(struct qti_can *priv_data, ret |= (fw_resp->br_min & 0xFF) << 16; ret |= (fw_resp->maj & 0xF) << 8; ret |= (fw_resp->min & 0xFF); + } else if (resp->cmd == CMD_UPDATE_TIME_INFO) { + struct can_time_info *time_data = + (struct can_time_info *)resp->data; + ktime_now = ktime_get_boottime(); + mstime = ktime_to_ms(ktime_now); + priv_data->time_diff = mstime - (le64_to_cpu(time_data->time)); } if (resp->cmd == priv_data->wait_cmd) { From fc93ec766ea3e9413f999ac1e4763ad41e44d07e Mon Sep 17 00:00:00 2001 From: Balachandra C S Date: Mon, 9 Jul 2018 17:24:41 +0530 Subject: [PATCH 120/159] drivers: net: can: Inform power states to CAN controller CAN controller needs to be aware of host power state to decide if a timestamp message can be sent to host or not. Change-Id: I89a570a2fb38336c38d0105bbb3df8b89d7e3035 Signed-off-by: Balachandra C S --- drivers/net/can/spi/qti-can.c | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/drivers/net/can/spi/qti-can.c b/drivers/net/can/spi/qti-can.c index 7083d0011b18..f7ba4510d1bc 100644 --- a/drivers/net/can/spi/qti-can.c +++ b/drivers/net/can/spi/qti-can.c @@ -121,6 +121,8 @@ struct spi_miso { /* TLV for MISO line */ #define CMD_END_BOOT_ROM_UPGRADE 0x9B #define CMD_END_FW_UPDATE_FILE 0x9C #define CMD_UPDATE_TIME_INFO 0x9D +#define CMD_UPDATE_SUSPEND_EVENT 0x9E +#define CMD_UPDATE_RESUME_EVENT 0x9F #define IOCTL_RELEASE_CAN_BUFFER (SIOCDEVPRIVATE + 0) #define IOCTL_ENABLE_BUFFERING (SIOCDEVPRIVATE + 1) @@ -580,6 +582,30 @@ static int qti_can_query_firmware_version(struct qti_can *priv_data) return ret; } +static int qti_can_notify_power_events(struct qti_can *priv_data, u8 event_type) +{ + char *tx_buf, *rx_buf; + int ret; + struct spi_mosi *req; + + mutex_lock(&priv_data->spi_lock); + tx_buf = priv_data->tx_buf; + rx_buf = priv_data->rx_buf; + memset(tx_buf, 0, XFER_BUFFER_SIZE); + memset(rx_buf, 0, XFER_BUFFER_SIZE); + priv_data->xfer_length = XFER_BUFFER_SIZE; + + req = (struct spi_mosi *)tx_buf; + req->cmd = event_type; + req->len = 0; + req->seq = atomic_inc_return(&priv_data->msg_seq); + + ret = qti_can_do_spi_transaction(priv_data); + mutex_unlock(&priv_data->spi_lock); + + return ret; +} + static int qti_can_set_bitrate(struct net_device *netdev) { char *tx_buf, *rx_buf; @@ -1439,6 +1465,10 @@ static int qti_can_remove(struct spi_device *spi) static int qti_can_suspend(struct device *dev) { struct spi_device *spi = to_spi_device(dev); + struct qti_can *priv_data = spi_get_drvdata(spi); + u8 power_event = CMD_UPDATE_SUSPEND_EVENT; + + qti_can_notify_power_events(priv_data, power_event); enable_irq_wake(spi->irq); return 0; @@ -1448,9 +1478,10 @@ static int qti_can_resume(struct device *dev) { struct spi_device *spi = to_spi_device(dev); struct qti_can *priv_data = spi_get_drvdata(spi); + u8 power_event = CMD_UPDATE_RESUME_EVENT; disable_irq_wake(spi->irq); - qti_can_rx_message(priv_data); + qti_can_notify_power_events(priv_data, power_event); return 0; } From 967528c6c62a61d9f5ab964f417c9f0fcafc5f2d Mon Sep 17 00:00:00 2001 From: Balachandra C S Date: Fri, 13 Jul 2018 16:32:28 +0530 Subject: [PATCH 121/159] ARM: dts: msm: Add proper irq type in device tree for msm device Use proper irq type for gpio interrupt in qti-can controller. This interrupt type may vary among different targets. Change-Id: I32679cbdc29dbda49769dcb455589da64527f3cc Signed-off-by: Balachandra C S --- arch/arm/boot/dts/qcom/msm8996-cv2x.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/qcom/msm8996-cv2x.dtsi b/arch/arm/boot/dts/qcom/msm8996-cv2x.dtsi index 3d57b5792161..c0a1606945d8 100644 --- a/arch/arm/boot/dts/qcom/msm8996-cv2x.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-cv2x.dtsi @@ -225,7 +225,7 @@ reg = <0>; spi-max-frequency = <9600000>; interrupt-parent = <&tlmm>; - interrupts = <78 0>; + interrupts = <78 2>; qcom,reset-gpio = <&tlmm 71 GPIO_ACTIVE_LOW>; qcom,clk-freq-mhz = <20000000>; qcom,max-can-channels = <2>; From 98f28d031d1b594c4d8feb8745d49920daf4ed7c Mon Sep 17 00:00:00 2001 From: Paras Nagda Date: Thu, 19 Jul 2018 18:51:14 +0530 Subject: [PATCH 122/159] msm: vidc: Addition of enums for HLG and HDR10 Add HLG and ST2084 Transfer characteristics enum values as specified in the latest HEVC spec. Change-Id: Iff19ff5c13c4861f4d97ab0433214fe95fa84459 Signed-off-by: Paras Nagda --- drivers/media/platform/msm/vidc/msm_venc.c | 4 ++-- include/uapi/media/msm_vidc.h | 9 +++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c index ebdafd66e590..3f06dd6ac4b5 100644 --- a/drivers/media/platform/msm/vidc/msm_venc.c +++ b/drivers/media/platform/msm/vidc/msm_venc.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1394,7 +1394,7 @@ static struct msm_vidc_ctrl msm_venc_ctrls[] = { .name = "Set Color space transfer characterstics", .type = V4L2_CTRL_TYPE_INTEGER, .minimum = MSM_VIDC_TRANSFER_BT709_5, - .maximum = MSM_VIDC_TRANSFER_BT_2020_12, + .maximum = MSM_VIDC_TRANSFER_HLG, .default_value = MSM_VIDC_TRANSFER_601_6_625, .step = 1, .qmenu = NULL, diff --git a/include/uapi/media/msm_vidc.h b/include/uapi/media/msm_vidc.h index e9370cb660b2..95b6bab382bb 100644 --- a/include/uapi/media/msm_vidc.h +++ b/include/uapi/media/msm_vidc.h @@ -345,6 +345,15 @@ enum msm_vidc_h264_transfer_chars_values { MSM_VIDC_TRANSFER_SRGB = 13, MSM_VIDC_TRANSFER_BT_2020_10 = 14, MSM_VIDC_TRANSFER_BT_2020_12 = 15, +#define MSM_VIDC_TRANSFER_SMPTE_ST2084 \ + MSM_VIDC_TRANSFER_SMPTE_ST2084 + MSM_VIDC_TRANSFER_SMPTE_ST2084 = 16, +#define MSM_VIDC_TRANSFER_SMPTE_ST428_1 \ + MSM_VIDC_TRANSFER_SMPTE_ST428_1 + MSM_VIDC_TRANSFER_SMPTE_ST428_1 = 17, +#define MSM_VIDC_TRANSFER_HLG \ + MSM_VIDC_TRANSFER_HLG + MSM_VIDC_TRANSFER_HLG = 18, }; enum msm_vidc_pixel_depth { From 98732ea029e84eb023ec4e8f0569f99cf0beb437 Mon Sep 17 00:00:00 2001 From: Rahul Shahare Date: Thu, 19 Jul 2018 17:39:32 +0530 Subject: [PATCH 123/159] defconfig: sdm660: align with android config requirement Align with android-base.cfg which is android kernel config requirement for sdm660_defconfig. Change-Id: I41566f96efe441f06986a1b4bfc6d034b2255062 Signed-off-by: Rahul Shahare --- arch/arm64/configs/sdm660_defconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/configs/sdm660_defconfig b/arch/arm64/configs/sdm660_defconfig index ef0e1d6e69b7..6946c1ae970b 100644 --- a/arch/arm64/configs/sdm660_defconfig +++ b/arch/arm64/configs/sdm660_defconfig @@ -1,4 +1,5 @@ # CONFIG_LOCALVERSION_AUTO is not set +# CONFIG_USELIB is not set CONFIG_AUDIT=y # CONFIG_AUDITSYSCALL is not set CONFIG_NO_HZ=y @@ -316,6 +317,8 @@ CONFIG_INPUT_STMVL53L0=y # CONFIG_SERIO_SERPORT is not set # CONFIG_VT is not set # CONFIG_LEGACY_PTYS is not set +# CONFIG_DEVMEM is not set +# CONFIG_DEVKMEM is not set CONFIG_SERIAL_MSM=y CONFIG_SERIAL_MSM_CONSOLE=y CONFIG_SERIAL_MSM_HS=y From 3a3c7c7bb198c87204bbcd272c46c594bbc030f9 Mon Sep 17 00:00:00 2001 From: Srikanth Uyyala Date: Fri, 4 May 2018 14:23:10 +0530 Subject: [PATCH 124/159] msm: camera: Dont call recovery for inactive streams During Stream-off is in progress and all active streams are zero and that instant if we cause pingpong mismatch, recovery is not expected. Change-Id: Ibdaeb4308f33772fcd330712b0a866aedb7a9486 Signed-off-by: Srikanth Uyyala --- drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c index 925a89601636..07defdd76922 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c @@ -1699,6 +1699,10 @@ void msm_isp_halt_send_error(struct vfe_device *vfe_dev, uint32_t event) /* Recovery is already in Progress */ return; + /* if there are no active streams - do not start recovery */ + if (!vfe_dev->axi_data.num_active_stream) + return; + if (event == ISP_EVENT_PING_PONG_MISMATCH && vfe_dev->axi_data.recovery_count < MAX_RECOVERY_THRESHOLD) { pr_err("%s: ping pong mismatch on vfe%d recovery count %d\n", From ba2d60830c95b4728b634940d24fccbbf56efb62 Mon Sep 17 00:00:00 2001 From: xianzhu Date: Tue, 10 Jul 2018 16:03:58 +0800 Subject: [PATCH 125/159] power: wakeup_reason: send uevent to user space Sends uevent to user space when enter or out of suspend, the modules of user space can use it to do some necessary operation. For example, in order to reduce power consumption, we can use this mechanism to send instructions which can reduce unnecessary wake-up sources of modem to modem driver. Any module except modem can also monitor this event for power consumption purpose. Change-Id: I62ca3ed02ea78e06735355a2c8b6d515e36dc7e6 Signed-off-by: xianzhu --- kernel/power/wakeup_reason.c | 62 +++++++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/kernel/power/wakeup_reason.c b/kernel/power/wakeup_reason.c index 252611fad2fe..54697e28ba38 100644 --- a/kernel/power/wakeup_reason.c +++ b/kernel/power/wakeup_reason.c @@ -3,8 +3,14 @@ * * Logs the reasons which caused the kernel to resume from * the suspend mode. + * Sends uevent to user space when enter or out of suspend, + * the modules of user space can use it to do some necessary + * operation. for example, sending a special signal to modem + * or controling the brightness of a lamp before or after suspend. * * Copyright (C) 2014 Google, Inc. + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and * may be copied, distributed, and modified under those terms. @@ -26,7 +32,8 @@ #include #include #include - +#include +#include #define MAX_WAKEUP_REASON_IRQS 32 static int irq_list[MAX_WAKEUP_REASON_IRQS]; @@ -41,6 +48,9 @@ static ktime_t curr_monotime; /* monotonic time after last suspend */ static ktime_t last_stime; /* monotonic boottime offset before last suspend */ static ktime_t curr_stime; /* monotonic boottime offset after last suspend */ +static struct class *wake_uevent_class; +static struct device *wake_uevent_device; + static ssize_t last_resume_reason_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { @@ -168,12 +178,22 @@ void log_suspend_abort_reason(const char *fmt, ...) static int wakeup_reason_pm_event(struct notifier_block *notifier, unsigned long pm_event, void *unused) { + int ret = 0; + static char envp[32] = {0}; + static const char * const evp[] = {envp, NULL}; + switch (pm_event) { case PM_SUSPEND_PREPARE: spin_lock(&resume_reason_lock); irqcount = 0; suspend_abort = false; spin_unlock(&resume_reason_lock); + /* send the uevent to userspace */ + snprintf(envp, 32, "STATE=%s", "suspend start"); + ret = kobject_uevent_env(&wake_uevent_device->kobj, + KOBJ_CHANGE, (char **)evp); + if (ret) + pr_warn("Send uevent failed"); /* monotonic time since boot */ last_monotime = ktime_get(); /* monotonic time since boot including the time spent in suspend */ @@ -184,6 +204,12 @@ static int wakeup_reason_pm_event(struct notifier_block *notifier, curr_monotime = ktime_get(); /* monotonic time since boot including the time spent in suspend */ curr_stime = ktime_get_boottime(); + /* send the uevent to userspace */ + snprintf(envp, 32, "STATE=%s", "resume complete"); + ret = kobject_uevent_env(&wake_uevent_device->kobj, + KOBJ_CHANGE, (char **)evp); + if (ret) + pr_warn("Send uevent failed"); break; default: break; @@ -195,12 +221,18 @@ static struct notifier_block wakeup_reason_pm_notifier_block = { .notifier_call = wakeup_reason_pm_event, }; +static const struct file_operations wakeup_uevent = { + .owner = THIS_MODULE, +}; + /* Initializes the sysfs parameter * registers the pm_event notifier + * register the wake_uevent device */ int __init wakeup_reason_init(void) { int retval; + int major; retval = register_pm_notifier(&wakeup_reason_pm_notifier_block); if (retval) @@ -218,8 +250,36 @@ int __init wakeup_reason_init(void) kobject_put(wakeup_reason); printk(KERN_WARNING "[%s] failed to create a sysfs group %d\n", __func__, retval); + return retval; } + major = register_chrdev(0, "wake_uevent", &wakeup_uevent); + if (major < 0) { + sysfs_remove_group(wakeup_reason, &attr_group); + kobject_put(wakeup_reason); + return major; + } + wake_uevent_class = class_create(THIS_MODULE, "wake_uevent"); + if (IS_ERR(wake_uevent_class)) { + retval = PTR_ERR(wake_uevent_class); + goto fail_class; + } + wake_uevent_device = device_create(wake_uevent_class, NULL, + MKDEV(major, 0), + NULL, "wake_uevent"); + if (IS_ERR(wake_uevent_device)) { + retval = PTR_ERR(wake_uevent_device); + goto fail_device; + } + return 0; + +fail_device: + class_destroy(wake_uevent_class); +fail_class: + unregister_chrdev(major, "wake_uevent"); + sysfs_remove_group(wakeup_reason, &attr_group); + kobject_put(wakeup_reason); + return retval; } late_initcall(wakeup_reason_init); From d0097debb3e40c403d40e1c5e739cc3461af7ada Mon Sep 17 00:00:00 2001 From: Srikanth Uyyala Date: Fri, 4 May 2018 14:30:53 +0530 Subject: [PATCH 126/159] msm: camera: skip recovery during stream off in dual vfe in dual vfe usecase, skip pingpong mismatch recovery if one of the vfe's active stream count is zero. Change-Id: I1b4dce66ad6665e41c4185d3ac510204d40131da Signed-off-by: Srikanth Uyyala --- .../msm/camera_v2/isp/msm_isp_axi_util.c | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c index 07defdd76922..3aefd2ccbde6 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c @@ -1693,6 +1693,9 @@ void msm_isp_halt_send_error(struct vfe_device *vfe_dev, uint32_t event) struct msm_vfe_axi_halt_cmd halt_cmd; struct vfe_device *temp_dev = NULL; uint32_t irq_status0 = 0, irq_status1 = 0; + struct vfe_device *vfe_dev_other = NULL; + uint32_t vfe_id_other = 0; + unsigned long flags; if (atomic_read(&vfe_dev->error_info.overflow_state) != NO_OVERFLOW) @@ -1700,7 +1703,28 @@ void msm_isp_halt_send_error(struct vfe_device *vfe_dev, uint32_t event) return; /* if there are no active streams - do not start recovery */ - if (!vfe_dev->axi_data.num_active_stream) + if (vfe_dev->is_split) { + if (vfe_dev->pdev->id == ISP_VFE0) + vfe_id_other = ISP_VFE1; + else + vfe_id_other = ISP_VFE0; + + spin_lock_irqsave( + &vfe_dev->common_data->common_dev_data_lock, flags); + vfe_dev_other = vfe_dev->common_data->dual_vfe_res-> + vfe_dev[vfe_id_other]; + if (!vfe_dev->axi_data.num_active_stream || + !vfe_dev_other->axi_data.num_active_stream) { + spin_unlock_irqrestore( + &vfe_dev->common_data->common_dev_data_lock, + flags); + pr_err("%s:skip the recovery as no active streams\n", + __func__); + return; + } + spin_unlock_irqrestore( + &vfe_dev->common_data->common_dev_data_lock, flags); + } else if (!vfe_dev->axi_data.num_active_stream) return; if (event == ISP_EVENT_PING_PONG_MISMATCH && From 769a58cd28a6bc2449d9a7fe9b833aab9a356941 Mon Sep 17 00:00:00 2001 From: Yong Ding Date: Fri, 20 Jul 2018 15:23:43 +0800 Subject: [PATCH 127/159] soc: qcom: hab: change the unregistration to be dummy HAB service should be kept available as long as possible since it is very fundamental. It can possibly be used in the GVM(Guest Virtual Machine) shutdown procedure to talk with the hypervisor. And the unregistration function will only be left to give a log message. Change-Id: I0cbc153a68a0fb496d14fc49db6cfee211a01722 Signed-off-by: Yong Ding --- drivers/soc/qcom/hab/hab_qvm.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/soc/qcom/hab/hab_qvm.c b/drivers/soc/qcom/hab/hab_qvm.c index 129d1deeb2f0..df60e5c1b07d 100644 --- a/drivers/soc/qcom/hab/hab_qvm.c +++ b/drivers/soc/qcom/hab/hab_qvm.c @@ -314,10 +314,7 @@ int hab_hypervisor_register(void) void hab_hypervisor_unregister(void) { - hab_hypervisor_unregister_common(); - - qvm_priv_info.probe_cnt = 0; - qvm_priv_info.curr = 0; + pr_info("unregistration is called, but do nothing\n"); } /* this happens before hypervisor register */ From bf9dde89b8b843bfe27232307380c4a30b00bd28 Mon Sep 17 00:00:00 2001 From: Rahul Sharma Date: Thu, 19 Jul 2018 15:15:55 +0530 Subject: [PATCH 128/159] drm/sde: report MDP underrun error only if not stabilized MDP underrun error is being reported to recovery manager as and when they are detected by the interrupt handler. Since most of the times errors are recovered successfully and stabilizes and hence we do not need to report in those scenarios. This implementation uses a delayed work to figure out if the error is stabilized. In case if error is still persists then it would be reported to the recovery manager. Change-Id: I3509484867d86dc946dd4be856d85de444c0aa60 Signed-off-by: Rahul Sharma --- drivers/gpu/drm/msm/sde/sde_encoder.c | 65 ++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c index 77fdcd86c920..dde742014125 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder.c @@ -44,6 +44,13 @@ /* timeout in frames waiting for frame done */ #define SDE_ENCODER_FRAME_DONE_TIMEOUT 60 +/* timeout in msecs */ +#define SDE_ENCODER_UNDERRUN_TIMEOUT 200 +/* underrun count threshold value */ +#define SDE_ENCODER_UNDERRUN_CNT_MAX 10 +/* 3 vsync time period in msec, report underrun */ +#define SDE_ENCODER_UNDERRUN_DELTA 50 + #define MISR_BUFF_SIZE 256 /* @@ -155,6 +162,11 @@ static struct sde_csc_cfg sde_csc_10bit_convert[SDE_MAX_CSC] = { * @crtc_frame_event: callback event * @frame_done_timeout: frame done timeout in Hz * @frame_done_timer: watchdog timer for frame done event + * @last_underrun_ts: variable to hold the last occurred underrun + * timestamp + * @underrun_cnt_dwork: underrun counter for delayed work + * @dwork: delayed work for deferring the reporting + * of underrun error */ struct sde_encoder_virt { struct drm_encoder base; @@ -181,6 +193,9 @@ struct sde_encoder_virt { u32 crtc_frame_event; atomic_t frame_done_timeout; struct timer_list frame_done_timer; + atomic_t last_underrun_ts; + atomic_t underrun_cnt_dwork; + struct delayed_work dwork; }; #define to_sde_encoder_virt(x) container_of(x, struct sde_encoder_virt, base) @@ -597,14 +612,28 @@ static void sde_encoder_vblank_callback(struct drm_encoder *drm_enc, static void sde_encoder_underrun_callback(struct drm_encoder *drm_enc, struct sde_encoder_phys *phy_enc) { + struct sde_encoder_virt *sde_enc = NULL; + if (!phy_enc) return; + sde_enc = to_sde_encoder_virt(drm_enc); + SDE_ATRACE_BEGIN("encoder_underrun_callback"); atomic_inc(&phy_enc->underrun_cnt); SDE_EVT32(DRMID(drm_enc), atomic_read(&phy_enc->underrun_cnt)); - sde_recovery_set_events(SDE_UNDERRUN); + /* schedule delayed work if it has not scheduled or executed earlier */ + if ((!atomic_read(&sde_enc->last_underrun_ts)) && + (!atomic_read(&sde_enc->underrun_cnt_dwork))) { + schedule_delayed_work(&sde_enc->dwork, + msecs_to_jiffies(SDE_ENCODER_UNDERRUN_TIMEOUT)); + } + + /* take snapshot of current underrun and increment the count */ + atomic_set(&sde_enc->last_underrun_ts, jiffies); + atomic_inc(&sde_enc->underrun_cnt_dwork); + trace_sde_encoder_underrun(DRMID(drm_enc), atomic_read(&phy_enc->underrun_cnt)); SDE_DBG_CTRL("stop_ftrace"); @@ -1391,6 +1420,37 @@ static void sde_encoder_frame_done_timeout(unsigned long data) SDE_ENCODER_FRAME_EVENT_ERROR); } +static void sde_encoder_underrun_work_func(struct work_struct *work) +{ + struct sde_encoder_virt *sde_enc = + container_of(work, struct sde_encoder_virt, dwork.work); + + unsigned long delta, time; + + if (!sde_enc) { + SDE_ERROR("invalid parameters\n"); + return; + } + + delta = jiffies - atomic_read(&sde_enc->last_underrun_ts); + time = jiffies_to_msecs(delta); + + /* + * report underrun error when it exceeds the threshold count + * and the occurrence of last underrun error is less than 3 + * vsync period. + */ + if (atomic_read(&sde_enc->underrun_cnt_dwork) > + SDE_ENCODER_UNDERRUN_CNT_MAX && + time < SDE_ENCODER_UNDERRUN_DELTA) { + sde_recovery_set_events(SDE_UNDERRUN); + } + + /* reset underrun last timestamp and counter */ + atomic_set(&sde_enc->last_underrun_ts, 0); + atomic_set(&sde_enc->underrun_cnt_dwork, 0); +} + struct drm_encoder *sde_encoder_init( struct drm_device *dev, struct msm_display_info *disp_info) @@ -1421,8 +1481,11 @@ struct drm_encoder *sde_encoder_init( drm_encoder_helper_add(drm_enc, &sde_encoder_helper_funcs); atomic_set(&sde_enc->frame_done_timeout, 0); + atomic_set(&sde_enc->last_underrun_ts, 0); + atomic_set(&sde_enc->underrun_cnt_dwork, 0); setup_timer(&sde_enc->frame_done_timer, sde_encoder_frame_done_timeout, (unsigned long) sde_enc); + INIT_DELAYED_WORK(&sde_enc->dwork, sde_encoder_underrun_work_func); _sde_encoder_init_debugfs(drm_enc, sde_enc, sde_kms); From c9eb396da5b8a9d28ed141e1780efc2aa079a3d6 Mon Sep 17 00:00:00 2001 From: Srikanth Uyyala Date: Tue, 17 Apr 2018 13:12:52 +0530 Subject: [PATCH 129/159] msm: camera: isp : Fix race condition in close sequence Serializing reset_hw and reset_irq, to avoid race condition Change-Id: I8f21cb816748129bde7f0f1455b203b42603d244 Signed-off-by: Srikanth Uyyala --- .../media/platform/msm/camera_v2/isp/msm_isp.c | 5 +++-- .../media/platform/msm/camera_v2/isp/msm_isp.h | 3 ++- .../platform/msm/camera_v2/isp/msm_isp40.c | 18 +++++++++++++++++- .../platform/msm/camera_v2/isp/msm_isp47.c | 14 ++++++++++---- 4 files changed, 32 insertions(+), 8 deletions(-) diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp.c index 23e27e1179d1..18961e69aadc 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -712,7 +712,8 @@ int vfe_hw_probe(struct platform_device *pdev) spin_lock_init(&vfe_dev->shared_data_lock); spin_lock_init(&vfe_dev->reg_update_lock); spin_lock_init(&req_history_lock); - spin_lock_init(&vfe_dev->completion_lock); + spin_lock_init(&vfe_dev->reset_completion_lock); + spin_lock_init(&vfe_dev->halt_completion_lock); media_entity_init(&vfe_dev->subdev.sd.entity, 0, NULL, 0); vfe_dev->subdev.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV; vfe_dev->subdev.sd.entity.group_id = MSM_CAMERA_SUBDEV_VFE; diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h index acf0a90ed93d..da8fbb3cd5b9 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h @@ -804,7 +804,8 @@ struct vfe_device { struct mutex core_mutex; spinlock_t shared_data_lock; spinlock_t reg_update_lock; - spinlock_t completion_lock; + spinlock_t reset_completion_lock; + spinlock_t halt_completion_lock; /* Tasklet info */ atomic_t irq_cnt; diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c index 850f1b032a8a..f4e4ca6cb6dc 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c @@ -370,15 +370,24 @@ static void msm_vfe40_clear_status_reg(struct vfe_device *vfe_dev) static void msm_vfe40_process_reset_irq(struct vfe_device *vfe_dev, uint32_t irq_status0, uint32_t irq_status1) { - if (irq_status0 & (1 << 31)) + unsigned long flags; + + if (irq_status0 & (1 << 31)) { + spin_lock_irqsave(&vfe_dev->reset_completion_lock, flags); complete(&vfe_dev->reset_complete); + spin_unlock_irqrestore(&vfe_dev->reset_completion_lock, flags); + } } static void msm_vfe40_process_halt_irq(struct vfe_device *vfe_dev, uint32_t irq_status0, uint32_t irq_status1) { + unsigned long flags; + if (irq_status1 & (1 << 8)) { + spin_lock_irqsave(&vfe_dev->halt_completion_lock, flags); complete(&vfe_dev->halt_complete); + spin_unlock_irqrestore(&vfe_dev->halt_completion_lock, flags); msm_camera_io_w(0x0, vfe_dev->vfe_base + 0x2C0); } } @@ -767,7 +776,11 @@ static long msm_vfe40_reset_hardware(struct vfe_device *vfe_dev, uint32_t first_start, uint32_t blocking_call) { long rc = 0; + unsigned long flags; + + spin_lock_irqsave(&vfe_dev->reset_completion_lock, flags); init_completion(&vfe_dev->reset_complete); + spin_unlock_irqrestore(&vfe_dev->reset_completion_lock, flags); if (first_start) { msm_camera_io_w_mb(0x1FF, vfe_dev->vfe_base + 0xC); @@ -1780,6 +1793,7 @@ static int msm_vfe40_axi_halt(struct vfe_device *vfe_dev, int rc = 0; enum msm_vfe_input_src i; struct msm_isp_timestamp ts; + unsigned long flags; /* Keep only halt and restart mask */ msm_vfe40_config_irq(vfe_dev, (1 << 31), (1 << 8), @@ -1796,7 +1810,9 @@ static int msm_vfe40_axi_halt(struct vfe_device *vfe_dev, msm_isp_stats_stream_update(vfe_dev); if (blocking) { + spin_lock_irqsave(&vfe_dev->halt_completion_lock, flags); init_completion(&vfe_dev->halt_complete); + spin_unlock_irqrestore(&vfe_dev->halt_completion_lock, flags); /* Halt AXI Bus Bridge */ msm_camera_io_w_mb(0x1, vfe_dev->vfe_base + 0x2C0); rc = wait_for_completion_interruptible_timeout( diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c index 0a969cc897b0..ecf0b36e345d 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c @@ -443,10 +443,10 @@ void msm_vfe47_process_reset_irq(struct vfe_device *vfe_dev, unsigned long flags; if (irq_status0 & (1 << 31)) { - spin_lock_irqsave(&vfe_dev->completion_lock, flags); + spin_lock_irqsave(&vfe_dev->reset_completion_lock, flags); complete(&vfe_dev->reset_complete); vfe_dev->reset_pending = 0; - spin_unlock_irqrestore(&vfe_dev->completion_lock, flags); + spin_unlock_irqrestore(&vfe_dev->reset_completion_lock, flags); } } @@ -454,9 +454,12 @@ void msm_vfe47_process_halt_irq(struct vfe_device *vfe_dev, uint32_t irq_status0, uint32_t irq_status1) { uint32_t val = 0; + unsigned long flags; if (irq_status1 & (1 << 8)) { + spin_lock_irqsave(&vfe_dev->halt_completion_lock, flags); complete(&vfe_dev->halt_complete); + spin_unlock_irqrestore(&vfe_dev->halt_completion_lock, flags); msm_camera_io_w(0x0, vfe_dev->vfe_base + 0x400); } @@ -774,9 +777,9 @@ long msm_vfe47_reset_hardware(struct vfe_device *vfe_dev, uint32_t reset; unsigned long flags; - spin_lock_irqsave(&vfe_dev->completion_lock, flags); + spin_lock_irqsave(&vfe_dev->reset_completion_lock, flags); init_completion(&vfe_dev->reset_complete); - spin_unlock_irqrestore(&vfe_dev->completion_lock, flags); + spin_unlock_irqrestore(&vfe_dev->reset_completion_lock, flags); if (blocking_call) vfe_dev->reset_pending = 1; @@ -1996,6 +1999,7 @@ int msm_vfe47_axi_halt(struct vfe_device *vfe_dev, enum msm_vfe_input_src i; uint32_t val = 0; struct msm_isp_timestamp ts; + unsigned long flags; val = msm_camera_io_r(vfe_dev->vfe_vbif_base + VFE47_VBIF_CLK_OFFSET); val |= 0x1; @@ -2012,7 +2016,9 @@ int msm_vfe47_axi_halt(struct vfe_device *vfe_dev, __func__, vfe_dev->pdev->id, blocking); if (blocking) { + spin_lock_irqsave(&vfe_dev->halt_completion_lock, flags); init_completion(&vfe_dev->halt_complete); + spin_unlock_irqrestore(&vfe_dev->halt_completion_lock, flags); /* Halt AXI Bus Bridge */ msm_camera_io_w_mb(0x1, vfe_dev->vfe_base + 0x400); rc = wait_for_completion_interruptible_timeout( From a1655ade5d9303479d552a7d271d2ace58abbdbd Mon Sep 17 00:00:00 2001 From: Nirmal Abraham Date: Mon, 23 Jul 2018 17:11:05 +0530 Subject: [PATCH 130/159] msm: mdss: use uaccess routines to access user space buffers Use routines defined in uaccess.h (like put_user, get_user) while accessing user space buffers. Otherwise this leads to userspace access violation when PAN is enabled. Change-Id: Iea16e347ee71f0845711a21b6b9b01e16a6ab619 Signed-off-by: Nirmal Abraham --- drivers/video/fbdev/msm/mdss_compat_utils.c | 150 ++++++++++++-------- 1 file changed, 87 insertions(+), 63 deletions(-) diff --git a/drivers/video/fbdev/msm/mdss_compat_utils.c b/drivers/video/fbdev/msm/mdss_compat_utils.c index 2f5aad8ed801..8c28fbf8fbc2 100644 --- a/drivers/video/fbdev/msm/mdss_compat_utils.c +++ b/drivers/video/fbdev/msm/mdss_compat_utils.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. * Copyright (C) 1994 Martin Schaller * * 2001 - Documented with DocBook @@ -2853,26 +2853,28 @@ static int __pp_compat_alloc(struct msmfb_mdp_pp32 __user *pp32, *pp = compat_alloc_user_space(alloc_size); if (NULL == *pp) return -ENOMEM; - memset(*pp, 0, alloc_size); - - (*pp)->data.lut_cfg_data.data.pgc_lut_data.r_data = - (struct mdp_ar_gc_lut_data *) - ((unsigned long) *pp + - sizeof(struct msmfb_mdp_pp)); - (*pp)->data.lut_cfg_data.data.pgc_lut_data.g_data = - (struct mdp_ar_gc_lut_data *) + if (clear_user(*pp, alloc_size)) + return -EFAULT; + if (put_user((struct mdp_ar_gc_lut_data *) + ((unsigned long) *pp + + sizeof(struct msmfb_mdp_pp)), + &(*pp)->data.lut_cfg_data.data.pgc_lut_data.r_data) || + put_user((struct mdp_ar_gc_lut_data *) ((unsigned long) *pp + sizeof(struct msmfb_mdp_pp) + - pgc_size); - (*pp)->data.lut_cfg_data.data.pgc_lut_data.b_data = - (struct mdp_ar_gc_lut_data *) + pgc_size), + &(*pp)->data.lut_cfg_data.data.pgc_lut_data.g_data) || + put_user((struct mdp_ar_gc_lut_data *) ((unsigned long) *pp + sizeof(struct msmfb_mdp_pp) + - (2 * pgc_size)); - (*pp)->data.lut_cfg_data.data.pgc_lut_data.cfg_payload - = (void *)((unsigned long) *pp + + (2 * pgc_size)), + &(*pp)->data.lut_cfg_data.data.pgc_lut_data.b_data) || + put_user((void *)((unsigned long) *pp + sizeof(struct msmfb_mdp_pp) + - (3 * pgc_size)); + (3 * pgc_size)), + &(*pp)->data.lut_cfg_data.data. + pgc_lut_data.cfg_payload)) + return -EFAULT; break; case mdp_lut_igc: alloc_size += __pp_compat_size_igc(); @@ -2882,10 +2884,13 @@ static int __pp_compat_alloc(struct msmfb_mdp_pp32 __user *pp32, alloc_size); return -ENOMEM; } - memset(*pp, 0, alloc_size); - (*pp)->data.lut_cfg_data.data.igc_lut_data.cfg_payload - = (void *)((unsigned long)(*pp) + - sizeof(struct msmfb_mdp_pp)); + if (clear_user(*pp, alloc_size)) + return -EFAULT; + if (put_user((void *)((unsigned long)(*pp) + + sizeof(struct msmfb_mdp_pp)), + &(*pp)->data.lut_cfg_data.data. + igc_lut_data.cfg_payload)) + return -EFAULT; break; case mdp_lut_hist: alloc_size += __pp_compat_size_hist_lut(); @@ -2895,10 +2900,13 @@ static int __pp_compat_alloc(struct msmfb_mdp_pp32 __user *pp32, alloc_size); return -ENOMEM; } - memset(*pp, 0, alloc_size); - (*pp)->data.lut_cfg_data.data.hist_lut_data.cfg_payload - = (void *)((unsigned long)(*pp) + - sizeof(struct msmfb_mdp_pp)); + if (clear_user(*pp, alloc_size)) + return -EFAULT; + if (put_user((void *)((unsigned long)(*pp) + + sizeof(struct msmfb_mdp_pp)), + &(*pp)->data.lut_cfg_data.data. + hist_lut_data.cfg_payload)) + return -EFAULT; break; default: *pp = compat_alloc_user_space(alloc_size); @@ -2907,7 +2915,8 @@ static int __pp_compat_alloc(struct msmfb_mdp_pp32 __user *pp32, alloc_size, lut_type); return -ENOMEM; } - memset(*pp, 0, alloc_size); + if (clear_user(*pp, alloc_size)) + return -EFAULT; break; } break; @@ -2919,10 +2928,12 @@ static int __pp_compat_alloc(struct msmfb_mdp_pp32 __user *pp32, alloc_size); return -ENOMEM; } - memset(*pp, 0, alloc_size); - (*pp)->data.pcc_cfg_data.cfg_payload = - (void *)((unsigned long)(*pp) + - sizeof(struct msmfb_mdp_pp)); + if (clear_user(*pp, alloc_size)) + return -EFAULT; + if (put_user((void *)((unsigned long)(*pp) + + sizeof(struct msmfb_mdp_pp)), + &(*pp)->data.pcc_cfg_data.cfg_payload)) + return -EFAULT; break; case mdp_op_gamut_cfg: alloc_size += __pp_compat_size_gamut(); @@ -2932,10 +2943,12 @@ static int __pp_compat_alloc(struct msmfb_mdp_pp32 __user *pp32, alloc_size); return -ENOMEM; } - memset(*pp, 0, alloc_size); - (*pp)->data.gamut_cfg_data.cfg_payload = - (void *)((unsigned long)(*pp) + - sizeof(struct msmfb_mdp_pp)); + if (clear_user(*pp, alloc_size)) + return -EFAULT; + if (put_user((void *)((unsigned long)(*pp) + + sizeof(struct msmfb_mdp_pp)), + &(*pp)->data.gamut_cfg_data.cfg_payload)) + return -EFAULT; break; case mdp_op_pa_v2_cfg: alloc_size += __pp_compat_size_pa(); @@ -2945,16 +2958,19 @@ static int __pp_compat_alloc(struct msmfb_mdp_pp32 __user *pp32, alloc_size); return -ENOMEM; } - memset(*pp, 0, alloc_size); - (*pp)->data.pa_v2_cfg_data.cfg_payload = - (void *)((unsigned long)(*pp) + - sizeof(struct msmfb_mdp_pp)); + if (clear_user(*pp, alloc_size)) + return -EFAULT; + if (put_user((void *)((unsigned long)(*pp) + + sizeof(struct msmfb_mdp_pp)), + &(*pp)->data.pa_v2_cfg_data.cfg_payload)) + return -EFAULT; break; default: *pp = compat_alloc_user_space(alloc_size); if (NULL == *pp) return -ENOMEM; - memset(*pp, 0, alloc_size); + if (clear_user(*pp, alloc_size)) + return -EFAULT; break; } return 0; @@ -3372,7 +3388,9 @@ static int mdss_histo_compat_ioctl(struct fb_info *info, unsigned int cmd, sizeof(struct mdp_histogram_start_req)); return -EINVAL; } - memset(hist_req, 0, sizeof(struct mdp_histogram_start_req)); + if (clear_user(hist_req, + sizeof(struct mdp_histogram_start_req))) + return -EFAULT; ret = __from_user_hist_start_req(hist_req32, hist_req); if (ret) goto histo_compat_err; @@ -3392,7 +3410,8 @@ static int mdss_histo_compat_ioctl(struct fb_info *info, unsigned int cmd, sizeof(struct mdp_histogram_data)); return -EINVAL; } - memset(hist, 0, sizeof(struct mdp_histogram_data)); + if (clear_user(hist, sizeof(struct mdp_histogram_data))) + return -EFAULT; ret = __from_user_hist_data(hist32, hist); if (ret) goto histo_compat_err; @@ -3895,7 +3914,7 @@ static int __to_user_mdp_overlay(struct mdp_overlay32 __user *ov32, } -static int __from_user_mdp_overlay(struct mdp_overlay *ov, +static int __from_user_mdp_overlay(struct mdp_overlay __user *ov, struct mdp_overlay32 __user *ov32) { __u32 data; @@ -3954,12 +3973,12 @@ static int __from_user_mdp_overlay(struct mdp_overlay *ov, return 0; } -static int __from_user_mdp_overlaylist(struct mdp_overlay_list *ovlist, - struct mdp_overlay_list32 *ovlist32, +static int __from_user_mdp_overlaylist(struct mdp_overlay_list __user *ovlist, + struct mdp_overlay_list32 __user *ovlist32, struct mdp_overlay **to_list_head) { __u32 i, ret; - unsigned long data, from_list_head; + unsigned long data, from_list_head, num_overlays; struct mdp_overlay32 *iter; if (!to_list_head || !ovlist32 || !ovlist) { @@ -3980,11 +3999,13 @@ static int __from_user_mdp_overlaylist(struct mdp_overlay_list *ovlist, sizeof(ovlist32->processed_overlays))) return -EFAULT; - if (get_user(data, &ovlist32->overlay_list)) { + if (get_user(data, &ovlist32->overlay_list) || + get_user(num_overlays, &ovlist32->num_overlays)) { ret = -EFAULT; goto validate_exit; } - for (i = 0; i < ovlist32->num_overlays; i++) { + + for (i = 0; i < num_overlays; i++) { if (get_user(from_list_head, (__u32 *)data + i)) { ret = -EFAULT; goto validate_exit; @@ -3997,7 +4018,8 @@ static int __from_user_mdp_overlaylist(struct mdp_overlay_list *ovlist, goto validate_exit; } } - ovlist->overlay_list = to_list_head; + if (put_user(to_list_head, &ovlist->overlay_list)) + return -EFAULT; return 0; @@ -4006,8 +4028,8 @@ validate_exit: return -EFAULT; } -static int __to_user_mdp_overlaylist(struct mdp_overlay_list32 *ovlist32, - struct mdp_overlay_list *ovlist, +static int __to_user_mdp_overlaylist(struct mdp_overlay_list32 __user *ovlist32, + struct mdp_overlay_list __user *ovlist, struct mdp_overlay **l_ptr) { __u32 i, ret; @@ -4080,31 +4102,33 @@ static u32 __pp_sspp_size(void) return size; } -static int __pp_sspp_set_offsets(struct mdp_overlay *ov) +static int __pp_sspp_set_offsets(struct mdp_overlay __user *ov) { if (!ov) { pr_err("invalid overlay pointer\n"); return -EFAULT; } - ov->overlay_pp_cfg.igc_cfg.cfg_payload = (void *)((unsigned long)ov + - sizeof(struct mdp_overlay)); - ov->overlay_pp_cfg.pa_v2_cfg_data.cfg_payload = - ov->overlay_pp_cfg.igc_cfg.cfg_payload + - sizeof(struct mdp_igc_lut_data_v1_7); - ov->overlay_pp_cfg.pcc_cfg_data.cfg_payload = - ov->overlay_pp_cfg.pa_v2_cfg_data.cfg_payload + - sizeof(struct mdp_pa_data_v1_7); - ov->overlay_pp_cfg.hist_lut_cfg.cfg_payload = - ov->overlay_pp_cfg.pcc_cfg_data.cfg_payload + - sizeof(struct mdp_pcc_data_v1_7); + if (put_user((void *)((unsigned long)ov + sizeof(struct mdp_overlay)), + &(ov->overlay_pp_cfg.igc_cfg.cfg_payload)) || + put_user(ov->overlay_pp_cfg.igc_cfg.cfg_payload + + sizeof(struct mdp_igc_lut_data_v1_7), + &(ov->overlay_pp_cfg.pa_v2_cfg_data.cfg_payload)) || + put_user(ov->overlay_pp_cfg.pa_v2_cfg_data.cfg_payload + + sizeof(struct mdp_pa_data_v1_7), + &(ov->overlay_pp_cfg.pcc_cfg_data.cfg_payload)) || + put_user(ov->overlay_pp_cfg.pcc_cfg_data.cfg_payload + + sizeof(struct mdp_pcc_data_v1_7), + &(ov->overlay_pp_cfg.hist_lut_cfg.cfg_payload))) + return -EFAULT; return 0; } int mdss_compat_overlay_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg, struct file *file) { - struct mdp_overlay *ov, **layers_head; - struct mdp_overlay32 *ov32; + struct mdp_overlay **layers_head; + struct mdp_overlay __user *ov; + struct mdp_overlay32 __user *ov32; struct mdp_overlay_list __user *ovlist; struct mdp_overlay_list32 __user *ovlist32; size_t layers_refs_sz, layers_sz, prepare_sz; From 43af76ad096644a650c9b4b165636fb498297f1d Mon Sep 17 00:00:00 2001 From: Animesh Kishore Date: Tue, 24 Jul 2018 11:59:14 +0530 Subject: [PATCH 131/159] msm: mdss: Constant fetch across dfps Timing engine HW restricts changing programmable fetch start when off. Program constant fetch start in SW drivers. Fix fetch start is calculated based on panel DT timings. Change-Id: I2124c92b2f83d9c963e05c14421f61a08878d63b Signed-off-by: Animesh Kishore --- drivers/video/fbdev/msm/mdss_mdp.h | 4 ++-- drivers/video/fbdev/msm/mdss_mdp_ctl.c | 8 ++++++-- drivers/video/fbdev/msm/mdss_mdp_intf_video.c | 15 ++++++++------ drivers/video/fbdev/msm/mdss_mdp_overlay.c | 10 +--------- drivers/video/fbdev/msm/mdss_panel.c | 3 ++- drivers/video/fbdev/msm/mdss_panel.h | 20 +++++++++++++++++-- 6 files changed, 38 insertions(+), 22 deletions(-) diff --git a/drivers/video/fbdev/msm/mdss_mdp.h b/drivers/video/fbdev/msm/mdss_mdp.h index 54b792305eb5..43fc5eafb047 100644 --- a/drivers/video/fbdev/msm/mdss_mdp.h +++ b/drivers/video/fbdev/msm/mdss_mdp.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1762,7 +1762,7 @@ int mdss_mdp_ctl_start(struct mdss_mdp_ctl *ctl, bool handoff); int mdss_mdp_ctl_stop(struct mdss_mdp_ctl *ctl, int panel_power_mode); int mdss_mdp_ctl_intf_event(struct mdss_mdp_ctl *ctl, int event, void *arg, u32 flags); -int mdss_mdp_get_prefetch_lines(struct mdss_panel_info *pinfo); +int mdss_mdp_get_prefetch_lines(struct mdss_panel_info *pinfo, bool is_fixed); int mdss_mdp_perf_bw_check(struct mdss_mdp_ctl *ctl, struct mdss_mdp_pipe **left_plist, int left_cnt, struct mdss_mdp_pipe **right_plist, int right_cnt); diff --git a/drivers/video/fbdev/msm/mdss_mdp_ctl.c b/drivers/video/fbdev/msm/mdss_mdp_ctl.c index 632d73e909a3..ec56bcf6e64e 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_ctl.c +++ b/drivers/video/fbdev/msm/mdss_mdp_ctl.c @@ -1525,7 +1525,7 @@ static bool is_mdp_prefetch_needed(struct mdss_panel_info *pinfo) * the mdp fetch lines as the last (25 - vbp - vpw) lines of vertical * front porch. */ -int mdss_mdp_get_prefetch_lines(struct mdss_panel_info *pinfo) +int mdss_mdp_get_prefetch_lines(struct mdss_panel_info *pinfo, bool is_fixed) { int prefetch_avail = 0; int v_total, vfp_start; @@ -1534,7 +1534,11 @@ int mdss_mdp_get_prefetch_lines(struct mdss_panel_info *pinfo) if (!is_mdp_prefetch_needed(pinfo)) return 0; - v_total = mdss_panel_get_vtotal(pinfo); + if (is_fixed) + v_total = mdss_panel_get_vtotal_fixed(pinfo); + else + v_total = mdss_panel_get_vtotal(pinfo); + vfp_start = (pinfo->lcdc.v_back_porch + pinfo->lcdc.v_pulse_width + pinfo->yres); diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c index 607c0647b505..e27f6bc49892 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c +++ b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c @@ -1120,6 +1120,7 @@ static void mdss_mdp_video_vsync_intr_done(void *arg) struct mdss_mdp_video_ctx *ctx = ctl->intf_ctx[MASTER_CTX]; struct mdss_mdp_vsync_handler *tmp; ktime_t vsync_time; + u32 ctl_flush_bits = 0; if (!ctx) { pr_err("invalid ctx\n"); @@ -1129,10 +1130,13 @@ static void mdss_mdp_video_vsync_intr_done(void *arg) vsync_time = ktime_get(); ctl->vsync_cnt++; - MDSS_XLOG(ctl->num, ctl->vsync_cnt, ctl->vsync_cnt); + ctl_flush_bits = mdss_mdp_ctl_read(ctl, MDSS_MDP_REG_CTL_FLUSH); - pr_debug("intr ctl=%d vsync cnt=%u vsync_time=%d\n", - ctl->num, ctl->vsync_cnt, (int)ktime_to_ms(vsync_time)); + MDSS_XLOG(ctl->num, ctl->vsync_cnt, ctl_flush_bits); + + pr_debug("intr ctl=%d vsync cnt=%u vsync_time=%d ctl_flush=%d\n", + ctl->num, ctl->vsync_cnt, (int)ktime_to_ms(vsync_time), + ctl_flush_bits); ctx->polling_en = false; complete_all(&ctx->vsync_comp); @@ -1901,6 +1905,7 @@ static void mdss_mdp_fetch_start_config(struct mdss_mdp_video_ctx *ctx, mdata = ctl->mdata; + pinfo->prg_fet = mdss_mdp_get_prefetch_lines(pinfo, true); if (!pinfo->prg_fet) { pr_debug("programmable fetch is not needed/supported\n"); @@ -1919,7 +1924,7 @@ static void mdss_mdp_fetch_start_config(struct mdss_mdp_video_ctx *ctx, * Fetch should always be outside the active lines. If the fetching * is programmed within active region, hardware behavior is unknown. */ - v_total = mdss_panel_get_vtotal(pinfo); + v_total = mdss_panel_get_vtotal_fixed(pinfo); h_total = mdss_panel_get_htotal(pinfo, true); fetch_start = (v_total - pinfo->prg_fet) * h_total + 1; @@ -2206,8 +2211,6 @@ static int mdss_mdp_video_ctx_setup(struct mdss_mdp_ctl *ctl, ctx->intf_num); return -EINVAL; } - - pinfo->prg_fet = mdss_mdp_get_prefetch_lines(pinfo); mdss_mdp_fetch_start_config(ctx, ctl); if (test_bit(MDSS_QOS_VBLANK_PANIC_CTRL, mdata->mdss_qos_map)) diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c index 2f5b45638cdb..0000a1fec459 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c +++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c @@ -3367,9 +3367,6 @@ static void cache_initial_timings(struct mdss_panel_data *pdata) { if (!pdata->panel_info.default_fps) { - pdata->panel_info.default_prg_fet = - mdss_mdp_get_prefetch_lines(&pdata->panel_info); - /* * This value will change dynamically once the * actual dfps update happen in hw. @@ -3442,13 +3439,8 @@ static void dfps_update_panel_params(struct mdss_panel_data *pdata, dfps_update_fps(&pdata->panel_info, new_fps); - /* - * Fetch start is pinned to default fps. - * Adjust programmable fetch accordingly. - */ pdata->panel_info.prg_fet = - (pdata->panel_info.default_prg_fet) ? - (pdata->panel_info.default_prg_fet + add_v_lines) : 0; + mdss_mdp_get_prefetch_lines(&pdata->panel_info, false); } else if (pdata->panel_info.dfps_update == DFPS_IMMEDIATE_PORCH_UPDATE_MODE_HFP) { diff --git a/drivers/video/fbdev/msm/mdss_panel.c b/drivers/video/fbdev/msm/mdss_panel.c index 31cf74274131..ffe9b19c3859 100644 --- a/drivers/video/fbdev/msm/mdss_panel.c +++ b/drivers/video/fbdev/msm/mdss_panel.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2016, 2018 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -630,6 +630,7 @@ void mdss_panel_info_from_timing(struct mdss_panel_timing *pt, pinfo->yres = pt->yres; pinfo->lcdc.v_front_porch = pt->v_front_porch; + pinfo->lcdc.v_front_porch_fixed = pt->v_front_porch; pinfo->lcdc.v_back_porch = pt->v_back_porch; pinfo->lcdc.v_pulse_width = pt->v_pulse_width; diff --git a/drivers/video/fbdev/msm/mdss_panel.h b/drivers/video/fbdev/msm/mdss_panel.h index 7085a9fd7200..acac672662c1 100644 --- a/drivers/video/fbdev/msm/mdss_panel.h +++ b/drivers/video/fbdev/msm/mdss_panel.h @@ -392,6 +392,7 @@ struct lcd_panel_info { u32 h_active_low; u32 v_back_porch; u32 v_front_porch; + u32 v_front_porch_fixed; u32 v_pulse_width; u32 v_active_low; u32 border_clr; @@ -814,8 +815,6 @@ struct mdss_panel_info { int new_fps; /* stores initial fps after boot */ u32 default_fps; - /* store programmable fetch corresponding to default fps */ - u32 default_prg_fet; /* stores initial vtotal (vfp-method) or htotal (hfp-method) */ u32 saved_total; /* stores initial vfp (vfp-method) or hfp (hfp-method) */ @@ -1062,6 +1061,23 @@ static inline u32 mdss_panel_get_framerate(struct mdss_panel_info *panel_info) return frame_rate; } +/* + * mdss_panel_get_vtotal_fixed() - return panel device tree vertical height + * @pinfo: Pointer to panel info containing all panel information + * + * Returns the total height as defined in panel device tree including any + * blanking regions which are not visible to user but used to calculate + * panel clock. + */ +static inline int mdss_panel_get_vtotal_fixed(struct mdss_panel_info *pinfo) +{ + return pinfo->yres + pinfo->lcdc.v_back_porch + + pinfo->lcdc.v_front_porch_fixed + + pinfo->lcdc.v_pulse_width+ + pinfo->lcdc.border_top + + pinfo->lcdc.border_bottom; +} + /* * mdss_panel_get_vtotal() - return panel vertical height * @pinfo: Pointer to panel info containing all panel information From fb1d9f0accb78d50c614a426c28e7f8255cc3f8f Mon Sep 17 00:00:00 2001 From: Suprith Malligere Shankaregowda Date: Wed, 27 Jun 2018 11:40:22 +0530 Subject: [PATCH 132/159] drm: msm: fix variable initialization This change initializes variable i and j value to 0 in dsi_display_prepare() as it was used uninitialized earlier. Change-Id: I84ed753cfa64a719ec2f1b44a8ef24d5331b0fbc Signed-off-by: Suprith Malligere Shankaregowda --- drivers/gpu/drm/msm/dsi-staging/dsi_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c index 4bf694e2e7fa..0277fd3b3831 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c @@ -2577,7 +2577,7 @@ error: int dsi_display_prepare(struct dsi_display *display) { - int rc = 0, i, j; + int rc = 0, i = 0, j = 0; if (!display) { pr_err("Invalid params\n"); From 29d287ad01364fdf09779e02fc65976555896725 Mon Sep 17 00:00:00 2001 From: Trishansh Bhardwaj Date: Fri, 6 Jul 2018 16:08:12 +0530 Subject: [PATCH 133/159] msm: camera: Fix out-of-bounds read in string class name. jpeg driver is calling class_create with stack variable, which can be overwritten by other stack variables. Change-Id: I3c22a5b3375b970ff6b1c6de983dd5833f4e11d0 Signed-off-by: Trishansh Bhardwaj Signed-off-by: VijayaKumar T M --- drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_dev.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_dev.c b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_dev.c index 06e3ee4c353b..5ef08cbe9aee 100644 --- a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_dev.c +++ b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_dev.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -32,6 +32,8 @@ #define MSM_JPEG_NAME "jpeg" #define DEV_NAME_LEN 10 +static char devname[DEV_NAME_LEN]; + static int msm_jpeg_open(struct inode *inode, struct file *filp) { int rc = 0; @@ -185,7 +187,6 @@ static int msm_jpeg_init_dev(struct platform_device *pdev) struct msm_jpeg_device *msm_jpeg_device_p; const struct of_device_id *device_id; const struct msm_jpeg_priv_data *priv_data; - char devname[DEV_NAME_LEN]; msm_jpeg_device_p = kzalloc(sizeof(struct msm_jpeg_device), GFP_ATOMIC); if (!msm_jpeg_device_p) { @@ -328,6 +329,7 @@ static struct platform_driver msm_jpeg_driver = { static int __init msm_jpeg_driver_init(void) { int rc; + rc = platform_driver_register(&msm_jpeg_driver); return rc; } From 4d4a179e76a105a67746d6119a5417414bf009ce Mon Sep 17 00:00:00 2001 From: Mark Salyzyn Date: Tue, 16 Jan 2018 13:42:30 -0800 Subject: [PATCH 134/159] ANDROID: Bluetooth: hidp: buffer overflow in hidp_process_report The buffer length is unsigned at all layers, but gets cast to int and checked in hidp_process_report and can lead to a buffer overflow. Switch len parameter to unsigned int to resolve issue. Signed-off-by: Mark Salyzyn Fixes: 678af93e46ac10318b54f2f0c9abbdfe75c4e078 ("HID: Bluetooth: hidp: make sure input buffers are big enough") Bug: 65853588 Change-Id: I779ce783ae7c3bce8c5a66c0954ef31347e42cfc Git-repo: https://android.googlesource.com/kernel/msm Git-commit: 34c56d552bffcaefa84975bea0e55fb4481964fd Signed-off-by: Srinivasa Rao Kuppala --- net/bluetooth/hidp/core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index f64de569175a..a295b5ec9d4a 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c @@ -431,8 +431,8 @@ static void hidp_del_timer(struct hidp_session *session) del_timer(&session->timer); } -static void hidp_process_report(struct hidp_session *session, - int type, const u8 *data, int len, int intr) +static void hidp_process_report(struct hidp_session *session, int type, + const u8 *data, unsigned int len, int intr) { if (len > HID_MAX_BUFFER_SIZE) len = HID_MAX_BUFFER_SIZE; From 23412e401c5e46fd4fd7a6d1af119037b369a3e0 Mon Sep 17 00:00:00 2001 From: Mohammed Javid Date: Wed, 25 Jul 2018 19:16:16 +0530 Subject: [PATCH 135/159] ARM: dts: msm: Enable Apps shutdown feature in IPA driver for 8996HQX In order to support GVM restart functionality where apps VM can alone shutdown, IPA apps driver need to reset IPA HW. So make a change to enable the DT node to support apps shutdown feature. Change-Id: I6076d4914a62004b06f5b555e64e22ed49e2551f Signed-off-by: Mohammed Javid --- arch/arm/boot/dts/qcom/vplatform-lfv-msm8996-modem.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/qcom/vplatform-lfv-msm8996-modem.dtsi b/arch/arm/boot/dts/qcom/vplatform-lfv-msm8996-modem.dtsi index 9fb33950541c..2cc02a5aea1a 100644 --- a/arch/arm/boot/dts/qcom/vplatform-lfv-msm8996-modem.dtsi +++ b/arch/arm/boot/dts/qcom/vplatform-lfv-msm8996-modem.dtsi @@ -72,6 +72,7 @@ qcom,ee = <0>; qcom,use-ipa-tethering-bridge; qcom,ipa-bam-remote-mode; + qcom,apps-shutdown-support; qcom,modem-cfg-emb-pipe-flt; clocks = <&clock_virt clk_ipa_clk>; clock-names = "core_clk"; From 596aa5c28ae21cda5b813c09093003ab137b33ef Mon Sep 17 00:00:00 2001 From: Arun Kumar Neelakantam Date: Thu, 19 Jul 2018 14:25:22 +0530 Subject: [PATCH 136/159] net: ipc_router: Initialize the sockaddr in recvmsg() handler sockaddr structure is filled with required information only which results in few memory locations of structure with uninitialized data. Memset complete structure before using it to remove uninitialized data. CRs-Fixed: 2274853 Change-Id: I181710bde100fb1553b925d9fdf227af35ff38b5 Signed-off-by: Arun Kumar Neelakantam --- net/ipc_router/ipc_router_socket.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/ipc_router/ipc_router_socket.c b/net/ipc_router/ipc_router_socket.c index 23e4443fc1b2..7c82f7ff8874 100644 --- a/net/ipc_router/ipc_router_socket.c +++ b/net/ipc_router/ipc_router_socket.c @@ -143,6 +143,7 @@ static int msm_ipc_router_extract_msg(struct msghdr *m, return -EINVAL; } ctl_msg = (union rr_control_msg *)(temp->data); + memset(addr, 0x0, sizeof(*addr)); addr->family = AF_MSM_IPC; addr->address.addrtype = MSM_IPC_ADDR_ID; addr->address.addr.port_addr.node_id = ctl_msg->cli.node_id; @@ -151,6 +152,7 @@ static int msm_ipc_router_extract_msg(struct msghdr *m, return offset; } if (addr && (hdr->type == IPC_ROUTER_CTRL_CMD_DATA)) { + memset(addr, 0x0, sizeof(*addr)); addr->family = AF_MSM_IPC; addr->address.addrtype = MSM_IPC_ADDR_ID; addr->address.addr.port_addr.node_id = hdr->src_node_id; From 08431ef0acd5b79259d626dc36bebef59b5a4439 Mon Sep 17 00:00:00 2001 From: Veerabhadrarao Badiganti Date: Thu, 26 Jul 2018 18:05:31 +0530 Subject: [PATCH 137/159] mmc: core: Use mmc_get_cd_gpio to get cd gpio status in resume path The change a4d7728mmc(core: Update SD card removal logic based on cd- gpio state), has introduced logic to read the card presence status in resume path of mmc_pm_notify(), for forcing card detection if card is removed. But the API being used for getting gpio status invoking sleep calls from resume context which shouldn't have any sleep calls. So updated the resume path with different API for getting cd-gpio state. This chagne is not needed 4.9 kernel onwards since the there the sdhci_get_cd() API has different implementation. Change-Id: I5e7e760c6345a6fcdc873849d11f0bb32af09295 Signed-off-by: Veerabhadrarao Badiganti --- drivers/mmc/core/core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index e4e4e04e1d0c..76dbbbde884b 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -4572,8 +4572,8 @@ int mmc_pm_notify(struct notifier_block *notify_block, spin_lock_irqsave(&host->lock, flags); host->rescan_disable = 0; - if (host->ops->get_cd) - present = host->ops->get_cd(host); + if (mmc_card_is_removable(host)) + present = !!mmc_gpio_get_cd(host); if (mmc_bus_manual_resume(host) && !host->ignore_bus_resume_flags && From 058355d2bf48c043291d0a0763dce79d238a841b Mon Sep 17 00:00:00 2001 From: Siva Kumar Akkireddi Date: Thu, 5 Jul 2018 10:55:32 +0530 Subject: [PATCH 138/159] msm: sps: Suppress bind/unbind attributes SPS driver does not support manual bind/unbind operations through sysfs. Suppress the bind/unbind nodes. Do not free SPS struct in sps_device_de_init since it is being done in sps_exit, and also to avoid use-after-free. Change-Id: If6da6c5fb9d1a44d0420c6151f7f9d0a33cb2d04 Signed-off-by: Siva Kumar Akkireddi --- drivers/platform/msm/sps/sps.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/platform/msm/sps/sps.c b/drivers/platform/msm/sps/sps.c index 59a9b911553c..0f6b66719ef2 100644 --- a/drivers/platform/msm/sps/sps.c +++ b/drivers/platform/msm/sps/sps.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1006,8 +1006,6 @@ static void sps_device_de_init(void) "sps:%s:BAMs are still registered", __func__); sps_map_de_init(); - - kfree(sps); } sps_mem_de_init(); @@ -2993,6 +2991,7 @@ static struct platform_driver msm_sps_driver = { .name = SPS_DRV_NAME, .owner = THIS_MODULE, .of_match_table = msm_sps_match, + .suppress_bind_attrs = true, }, .remove = msm_sps_remove, }; From 9e9de34171da75c1489a3ace16bcfc63071d7340 Mon Sep 17 00:00:00 2001 From: Gustavo Solaira Date: Wed, 25 Jul 2018 19:14:10 -0700 Subject: [PATCH 139/159] diag: Read the HSIC data in a work queue Add a new work queue to process the HSIC diag data instead of processing it in the interrupt context. Change-Id: I8c546cd608c662d1c3133194f70af4953d734b08 Signed-off-by: Gustavo Solaira --- drivers/char/diag/diagfwd_hsic.c | 92 ++++++++++++++++++++++++++++++-- drivers/char/diag/diagfwd_hsic.h | 12 ++++- 2 files changed, 98 insertions(+), 6 deletions(-) diff --git a/drivers/char/diag/diagfwd_hsic.c b/drivers/char/diag/diagfwd_hsic.c index 5fed1f88382d..1f161777aca5 100644 --- a/drivers/char/diag/diagfwd_hsic.c +++ b/drivers/char/diag/diagfwd_hsic.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2014, 2016 The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2014,2016,2018 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -50,10 +50,68 @@ struct diag_hsic_info diag_hsic[NUM_HSIC_DEV] = { } }; +static int hsic_buf_tbl_push(struct diag_hsic_info *ch, void *buf, int len) +{ + unsigned long flags; + struct diag_hsic_buf_tbl_t *item; + + if (!ch || !buf || len < 0) + return -EINVAL; + + item = kzalloc(sizeof(struct diag_hsic_buf_tbl_t), GFP_ATOMIC); + if (!item) + return -ENOMEM; + kmemleak_not_leak(item); + + spin_lock_irqsave(&ch->lock, flags); + item->buf = buf; + item->len = len; + list_add_tail(&item->link, &ch->buf_tbl); + spin_unlock_irqrestore(&ch->lock, flags); + + return 0; +} + +static struct diag_hsic_buf_tbl_t *hsic_buf_tbl_pop(struct diag_hsic_info *ch) +{ + unsigned long flags; + struct diag_hsic_buf_tbl_t *item = NULL; + + if (!ch || list_empty(&ch->buf_tbl)) + return NULL; + + spin_lock_irqsave(&ch->lock, flags); + item = list_first_entry(&ch->buf_tbl, struct diag_hsic_buf_tbl_t, link); + list_del(&item->link); + spin_unlock_irqrestore(&ch->lock, flags); + + return item; +} + +static void hsic_buf_tbl_clear(struct diag_hsic_info *ch) +{ + unsigned long flags; + struct list_head *start, *temp; + struct diag_hsic_buf_tbl_t *item = NULL; + + if (!ch) + return; + + /* At this point, the channel should already by closed */ + spin_lock_irqsave(&ch->lock, flags); + list_for_each_safe(start, temp, &ch->buf_tbl) { + item = list_entry(start, struct diag_hsic_buf_tbl_t, + link); + list_del(&item->link); + kfree(item); + + } + spin_unlock_irqrestore(&ch->lock, flags); +} + static void diag_hsic_read_complete(void *ctxt, char *buf, int len, int actual_size) { - int err = 0; int index = (int)(uintptr_t)ctxt; struct diag_hsic_info *ch = NULL; @@ -71,9 +129,8 @@ static void diag_hsic_read_complete(void *ctxt, char *buf, int len, */ if (!ch->opened || actual_size <= 0) goto fail; - err = diag_remote_dev_read_done(ch->dev_id, buf, actual_size); - if (err) - goto fail; + hsic_buf_tbl_push(ch, buf, actual_size); + queue_work(ch->hsic_wq, &ch->read_complete_work); return; fail: @@ -185,6 +242,7 @@ static int hsic_open(int id) diagmem_init(driver, ch->mempool); /* Notify the bridge that the channel is open */ diag_remote_dev_open(ch->dev_id); + INIT_LIST_HEAD(&ch->buf_tbl); queue_work(ch->hsic_wq, &(ch->read_work)); return 0; } @@ -222,6 +280,7 @@ static int hsic_close(int id) diag_bridge_close(ch->id); diagmem_exit(driver, ch->mempool); diag_remote_dev_close(ch->dev_id); + hsic_buf_tbl_clear(ch); return 0; } @@ -263,6 +322,27 @@ static void hsic_read_work_fn(struct work_struct *work) queue_work(ch->hsic_wq, &ch->read_work); } +static void hsic_read_complete_work_fn(struct work_struct *work) +{ + struct diag_hsic_info *ch = container_of(work, struct diag_hsic_info, + read_complete_work); + struct diag_hsic_buf_tbl_t *item; + + item = hsic_buf_tbl_pop(ch); + if (item) { + if (diag_remote_dev_read_done(ch->dev_id, item->buf, item->len)) + goto fail; + } + + kfree(item); + return; + +fail: + diagmem_free(driver, item->buf, ch->mempool); + queue_work(ch->hsic_wq, &ch->read_work); + kfree(item); +} + static int diag_hsic_probe(struct platform_device *pdev) { unsigned long flags; @@ -407,6 +487,8 @@ int diag_hsic_init() ch = &diag_hsic[i]; spin_lock_init(&ch->lock); INIT_WORK(&(ch->read_work), hsic_read_work_fn); + INIT_WORK(&(ch->read_complete_work), + hsic_read_complete_work_fn); INIT_WORK(&(ch->open_work), hsic_open_work_fn); INIT_WORK(&(ch->close_work), hsic_close_work_fn); strlcpy(wq_name, "DIAG_HSIC_", DIAG_HSIC_STRING_SZ); diff --git a/drivers/char/diag/diagfwd_hsic.h b/drivers/char/diag/diagfwd_hsic.h index c4d87a223105..618bc4e1939d 100644 --- a/drivers/char/diag/diagfwd_hsic.h +++ b/drivers/char/diag/diagfwd_hsic.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2014, 2018 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -12,6 +12,8 @@ #ifndef DIAGFWD_HSIC_H #define DIAGFWD_HSIC_H + +#include #ifdef CONFIG_DIAG_OVER_USB #include #endif @@ -23,6 +25,12 @@ #define DIAG_HSIC_NAME_SZ 24 +struct diag_hsic_buf_tbl_t { + struct list_head link; + unsigned char *buf; + int len; +}; + struct diag_hsic_info { int id; int dev_id; @@ -32,10 +40,12 @@ struct diag_hsic_info { uint8_t suspended; char name[DIAG_HSIC_NAME_SZ]; struct work_struct read_work; + struct work_struct read_complete_work; struct work_struct open_work; struct work_struct close_work; struct workqueue_struct *hsic_wq; spinlock_t lock; + struct list_head buf_tbl; }; extern struct diag_hsic_info diag_hsic[NUM_HSIC_DEV]; From b77f7d2943c32fe942bd0defbbc399e7074294f9 Mon Sep 17 00:00:00 2001 From: Ajay Agarwal Date: Wed, 25 Jul 2018 13:00:15 +0530 Subject: [PATCH 140/159] ARM: dts: msm: Disable runtime PM in host mode for automotive Add "qcom,disable-host-mode-pm" flag to the USB nodes of automotive targets to disable runtime PM in host mode. Change-Id: I45949b92e7199b3ee9a95a7e0a3a584f813d0deb Signed-off-by: Ajay Agarwal --- arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi | 2 ++ arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi | 2 ++ arch/arm/boot/dts/qcom/vplatform-lfv-msm8996-usb.dtsi | 1 + 3 files changed, 5 insertions(+) diff --git a/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi b/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi index 4842d3b205e6..12af84e66330 100644 --- a/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi @@ -1416,6 +1416,7 @@ &usb2s { status = "ok"; qcom,no-wakeup-src-in-hostmode; + qcom,disable-host-mode-pm; }; &usb3 { @@ -1424,6 +1425,7 @@ vdda33-supply = <&pm8994_l24>; vdda18-supply = <&pm8994_l12>; qcom,no-wakeup-src-in-hostmode; + qcom,disable-host-mode-pm; }; &blsp1_uart2 { diff --git a/arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi b/arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi index 86e9dd72dcad..b69f7ab7e32c 100644 --- a/arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi @@ -1246,6 +1246,7 @@ status = "ok"; vbus_dwc3-supply = <&usb2_otg_switch>; qcom,no-wakeup-src-in-hostmode; + qcom,disable-host-mode-pm; dwc3@7600000 { dr_mode = "host"; }; @@ -1257,6 +1258,7 @@ vdda33-supply = <&pm8994_l24>; vdda18-supply = <&pm8994_l12>; qcom,no-wakeup-src-in-hostmode; + qcom,disable-host-mode-pm; }; &blsp1_uart2 { diff --git a/arch/arm/boot/dts/qcom/vplatform-lfv-msm8996-usb.dtsi b/arch/arm/boot/dts/qcom/vplatform-lfv-msm8996-usb.dtsi index b7505743986e..faaf00b6ac25 100644 --- a/arch/arm/boot/dts/qcom/vplatform-lfv-msm8996-usb.dtsi +++ b/arch/arm/boot/dts/qcom/vplatform-lfv-msm8996-usb.dtsi @@ -88,6 +88,7 @@ resets = <&clock_virt USB_30_BCR>; reset-names = "core_reset"; + qcom,disable-host-mode-pm; dwc3@6a00000 { compatible = "snps,dwc3"; From b36879a9e939de671779604d9489bfb85d48a33f Mon Sep 17 00:00:00 2001 From: Mayank Rana Date: Mon, 25 Sep 2017 16:48:39 -0700 Subject: [PATCH 141/159] dwc3: Check USB LPM status before accessing any register USB debugfs entries can be accessed when USB session is not active or USB is in low power mode. This results into unclocked register access. Fix this issue by checking USB LPM status. debugfs_create_regset32() fops related APIs are used to get USB dwc3 register dump. These fops don't have support to query device status before accessing registers. Hence by default disabling creation of regdump debugfs entry. Change-Id: I67b00532eca159e000c848cb056d9759c47aefe9 Signed-off-by: Mayank Rana --- drivers/usb/dwc3/core.h | 2 ++ drivers/usb/dwc3/debugfs.c | 43 ++++++++++++++++++++++++++++++++++---- 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 8f36f3df55eb..9f73ec68a23b 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -852,6 +852,7 @@ struct dwc3_scratchpad_array { * @vbus_draw: current to be drawn from USB * @imod_interval: set the interrupt moderation interval in 250ns * increments or 0 to disable. + * @create_reg_debugfs: create debugfs entry to allow dwc3 register dump */ struct dwc3 { struct usb_ctrlrequest *ctrl_req; @@ -1048,6 +1049,7 @@ struct dwc3 { unsigned long l1_remote_wakeup_cnt; wait_queue_head_t wait_linkstate; + bool create_reg_debugfs; }; /* -------------------------------------------------------------------------- */ diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c index 4a18847983f7..2c00b3596055 100644 --- a/drivers/usb/dwc3/debugfs.c +++ b/drivers/usb/dwc3/debugfs.c @@ -368,6 +368,11 @@ static int dwc3_mode_show(struct seq_file *s, void *unused) unsigned long flags; u32 reg; + if (atomic_read(&dwc->in_lpm)) { + seq_puts(s, "USB device is powered off\n"); + return 0; + } + spin_lock_irqsave(&dwc->lock, flags); reg = dwc3_readl(dwc->regs, DWC3_GCTL); spin_unlock_irqrestore(&dwc->lock, flags); @@ -403,6 +408,11 @@ static ssize_t dwc3_mode_write(struct file *file, u32 mode = 0; char buf[32] = {}; + if (atomic_read(&dwc->in_lpm)) { + dev_err(dwc->dev, "USB device is powered off\n"); + return count; + } + if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) return -EFAULT; @@ -437,6 +447,12 @@ static int dwc3_testmode_show(struct seq_file *s, void *unused) unsigned long flags; u32 reg; + + if (atomic_read(&dwc->in_lpm)) { + seq_puts(s, "USB device is powered off\n"); + return 0; + } + spin_lock_irqsave(&dwc->lock, flags); reg = dwc3_readl(dwc->regs, DWC3_DCTL); reg &= DWC3_DCTL_TSTCTRL_MASK; @@ -483,6 +499,11 @@ static ssize_t dwc3_testmode_write(struct file *file, u32 testmode = 0; char buf[32] = {}; + if (atomic_read(&dwc->in_lpm)) { + seq_puts(s, "USB device is powered off\n"); + return count; + } + if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) return -EFAULT; @@ -521,6 +542,11 @@ static int dwc3_link_state_show(struct seq_file *s, void *unused) enum dwc3_link_state state; u32 reg; + if (atomic_read(&dwc->in_lpm)) { + seq_puts(s, "USB device is powered off\n"); + return 0; + } + spin_lock_irqsave(&dwc->lock, flags); reg = dwc3_readl(dwc->regs, DWC3_DSTS); state = DWC3_DSTS_USBLNKST(reg); @@ -590,6 +616,11 @@ static ssize_t dwc3_link_state_write(struct file *file, enum dwc3_link_state state = 0; char buf[32] = {}; + if (atomic_read(&dwc->in_lpm)) { + seq_puts(s, "USB device is powered off\n"); + return count; + } + if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) return -EFAULT; @@ -1241,10 +1272,14 @@ int dwc3_debugfs_init(struct dwc3 *dwc) dwc->regset->nregs = ARRAY_SIZE(dwc3_regs); dwc->regset->base = dwc->regs; - file = debugfs_create_regset32("regdump", S_IRUGO, root, dwc->regset); - if (!file) { - ret = -ENOMEM; - goto err1; + if (dwc->create_reg_debugfs) { + file = debugfs_create_regset32("regdump", 0444, + root, dwc->regset); + if (!file) { + dev_dbg(dwc->dev, "Can't create debugfs regdump\n"); + ret = -ENOMEM; + goto err1; + } } if (IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)) { From 16683815e822a139ee467bf0a3aa758cf9888bdb Mon Sep 17 00:00:00 2001 From: Vijayavardhan Vennapusa Date: Tue, 3 Jul 2018 15:47:18 +0530 Subject: [PATCH 142/159] USB: pd: Send PS_RDY within tNewSrc after PS_RDY received USBPD spec mentions max time within which device that transitions from sink power role to source needs to send PS_RDY message after PS_RDY received from other device as part of PR_SWAP. Currently USB PD driver is taking time around 380msec i.e greater than tNewSrc (275msec) and resulting in USB PD complaince test "2.2.3.1.2 Procedure/Checks for Tester (Source) Originated Swap" failure. Fix it by waiting only till VBUS voltage reaches VSafe5Vmin. Change-Id: I3138e6d31ba964507230fe5f914aaaf2e261647d Signed-off-by: Vijayavardhan Vennapusa --- drivers/usb/pd/policy_engine.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c index aef8de046b8e..d9508dba2f83 100644 --- a/drivers/usb/pd/policy_engine.c +++ b/drivers/usb/pd/policy_engine.c @@ -1826,6 +1826,22 @@ enable_reg: else pd->vbus_enabled = true; + count = 10; + /* + * Check to make sure VBUS voltage reaches above Vsafe5Vmin (4.75v) + * before proceeding. + */ + while (count--) { + ret = power_supply_get_property(pd->usb_psy, + POWER_SUPPLY_PROP_VOLTAGE_NOW, &val); + if (ret || val.intval >= 4750000) /*vsafe5Vmin*/ + break; + usleep_range(10000, 12000); /* Delay between two reads */ + } + + if (ret) + msleep(100); /* Delay to wait for VBUS ramp up if read fails */ + return ret; } @@ -2747,7 +2763,6 @@ static void usbpd_sm(struct work_struct *w) case PE_PRS_SNK_SRC_SOURCE_ON: enable_vbus(pd); - msleep(200); /* allow time VBUS ramp-up, must be < tNewSrc */ ret = pd_send_msg(pd, MSG_PS_RDY, NULL, 0, SOP_MSG); if (ret) { From 6a36454b0a35e4ec57fce4f80602dc008750ea49 Mon Sep 17 00:00:00 2001 From: Camus Wong Date: Fri, 16 Mar 2018 17:02:55 -0400 Subject: [PATCH 143/159] defconfig: msm: Define common hypervisor flag Define common flag for hypervisor platforms and make use of it to: 1. Enable drm/msm-hyp 2. Disable drm/msm Change-Id: I6eb6a7cd2a1128ed8d2bf6efd96c4829556eb876 Signed-off-by: Camus Wong --- arch/arm64/Kconfig | 9 +++++++++ arch/arm64/configs/msm-auto-gvm-perf_defconfig | 2 +- arch/arm64/configs/msm-auto-gvm_defconfig | 2 +- drivers/gpu/drm/msm-hyp/Kconfig | 2 +- drivers/gpu/drm/msm/Kconfig | 1 + 5 files changed, 13 insertions(+), 3 deletions(-) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index a025138b0992..be21fb8ebb04 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -260,6 +260,15 @@ config PGTABLE_LEVELS default 3 if ARM64_16K_PAGES && ARM64_VA_BITS_47 default 4 if !ARM64_64K_PAGES && ARM64_VA_BITS_48 +config MSM_GVM + bool "Enable virtualization Support for MSM kernel" + help + This enables support for MSM Kernel based virtual + machine for any platform. + This helps to enable virtual driver support. + This should work on 64bit machine. + If you don't know what to do here, say N. + config MSM_GVM_QUIN bool "Enable virtualization Support for MSM kernel required for QUIN platform" help diff --git a/arch/arm64/configs/msm-auto-gvm-perf_defconfig b/arch/arm64/configs/msm-auto-gvm-perf_defconfig index d93941991c01..dda4a86c89f4 100644 --- a/arch/arm64/configs/msm-auto-gvm-perf_defconfig +++ b/arch/arm64/configs/msm-auto-gvm-perf_defconfig @@ -1,3 +1,4 @@ +CONFIG_MSM_GVM=y CONFIG_LOCALVERSION="-perf" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_SYSVIPC=y @@ -267,7 +268,6 @@ CONFIG_MEDIA_CONTROLLER=y CONFIG_VIDEO_V4L2_SUBDEV_API=y CONFIG_V4L_PLATFORM_DRIVERS=y CONFIG_DRM=y -# CONFIG_DRM_MSM is not set CONFIG_SOUND=y CONFIG_SND=y CONFIG_SND_SOC=y diff --git a/arch/arm64/configs/msm-auto-gvm_defconfig b/arch/arm64/configs/msm-auto-gvm_defconfig index 30a163c9743b..640083b94a22 100644 --- a/arch/arm64/configs/msm-auto-gvm_defconfig +++ b/arch/arm64/configs/msm-auto-gvm_defconfig @@ -1,3 +1,4 @@ +CONFIG_MSM_GVM=y CONFIG_SYSVIPC=y CONFIG_AUDIT=y CONFIG_NO_HZ=y @@ -259,7 +260,6 @@ CONFIG_MEDIA_CONTROLLER=y CONFIG_VIDEO_V4L2_SUBDEV_API=y CONFIG_V4L_PLATFORM_DRIVERS=y CONFIG_DRM=y -# CONFIG_DRM_MSM is not set CONFIG_SOUND=y CONFIG_SND=y CONFIG_SND_SOC=y diff --git a/drivers/gpu/drm/msm-hyp/Kconfig b/drivers/gpu/drm/msm-hyp/Kconfig index 676c0174c0ee..2a40a4bf036a 100644 --- a/drivers/gpu/drm/msm-hyp/Kconfig +++ b/drivers/gpu/drm/msm-hyp/Kconfig @@ -6,7 +6,7 @@ config DRM_MSM_HYP tristate "MSM DRM HYP" depends on DRM - depends on MSM_GVM_QUIN + depends on MSM_GVM depends on OF default y help diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig index cb3b25ddd0da..5d390abef6bd 100644 --- a/drivers/gpu/drm/msm/Kconfig +++ b/drivers/gpu/drm/msm/Kconfig @@ -4,6 +4,7 @@ config DRM_MSM depends on DRM depends on ARCH_QCOM || (ARM && COMPILE_TEST) depends on OF + depends on !MSM_GVM select REGULATOR select DRM_KMS_HELPER select DRM_PANEL From 34096f2db5fcb23dc71be5c238bff032b54398ae Mon Sep 17 00:00:00 2001 From: Devi Sandeep Endluri V V Date: Thu, 26 Jul 2018 02:43:38 +0530 Subject: [PATCH 144/159] defconfig: sdm660: Enable VTI config for v4 and v6 Enable VTI to give userspace (netd) the ability to create and update virtual interfaces. Change-Id: Ia32c78a8675757f4b600c6e4211f42afdb8249d4 CRs-Fixed: 2214527 Signed-off-by: Devi Sandeep Endluri V V --- arch/arm64/configs/sdm660-perf_defconfig | 2 ++ arch/arm64/configs/sdm660_defconfig | 2 ++ 2 files changed, 4 insertions(+) diff --git a/arch/arm64/configs/sdm660-perf_defconfig b/arch/arm64/configs/sdm660-perf_defconfig index d8eeb6f53286..340e0a207726 100644 --- a/arch/arm64/configs/sdm660-perf_defconfig +++ b/arch/arm64/configs/sdm660-perf_defconfig @@ -102,6 +102,7 @@ CONFIG_IP_MULTIPLE_TABLES=y CONFIG_IP_ROUTE_VERBOSE=y CONFIG_IP_PNP=y CONFIG_IP_PNP_DHCP=y +CONFIG_NET_IPVTI=y CONFIG_INET_AH=y CONFIG_INET_ESP=y CONFIG_INET_IPCOMP=y @@ -114,6 +115,7 @@ CONFIG_INET6_AH=y CONFIG_INET6_ESP=y CONFIG_INET6_IPCOMP=y CONFIG_IPV6_MIP6=y +CONFIG_IPV6_VTI=y CONFIG_IPV6_MULTIPLE_TABLES=y CONFIG_IPV6_SUBTREES=y CONFIG_NETFILTER=y diff --git a/arch/arm64/configs/sdm660_defconfig b/arch/arm64/configs/sdm660_defconfig index 6946c1ae970b..03435e186de5 100644 --- a/arch/arm64/configs/sdm660_defconfig +++ b/arch/arm64/configs/sdm660_defconfig @@ -102,6 +102,7 @@ CONFIG_IP_MULTIPLE_TABLES=y CONFIG_IP_ROUTE_VERBOSE=y CONFIG_IP_PNP=y CONFIG_IP_PNP_DHCP=y +CONFIG_NET_IPVTI=y CONFIG_INET_AH=y CONFIG_INET_ESP=y CONFIG_INET_IPCOMP=y @@ -114,6 +115,7 @@ CONFIG_INET6_AH=y CONFIG_INET6_ESP=y CONFIG_INET6_IPCOMP=y CONFIG_IPV6_MIP6=y +CONFIG_IPV6_VTI=y CONFIG_IPV6_MULTIPLE_TABLES=y CONFIG_IPV6_SUBTREES=y CONFIG_NETFILTER=y From 48771935e615cbcb7bde407b21756ab7b4daff32 Mon Sep 17 00:00:00 2001 From: Devi Sandeep Endluri V V Date: Thu, 26 Jul 2018 02:29:54 +0530 Subject: [PATCH 145/159] defconfig: msm8998: Enable VTI config for v4 and v6 Enable VTI to give userspace (netd) the ability to create and update virtual interfaces. CRs-Fixed: 2214527 Change-Id: I5076d59230538c0b88fbd8d3c9188141a600526b Signed-off-by: Devi Sandeep Endluri V V --- arch/arm64/configs/msmcortex-perf_defconfig | 2 ++ arch/arm64/configs/msmcortex_defconfig | 2 ++ 2 files changed, 4 insertions(+) diff --git a/arch/arm64/configs/msmcortex-perf_defconfig b/arch/arm64/configs/msmcortex-perf_defconfig index ad8600c38a28..548831ddb181 100644 --- a/arch/arm64/configs/msmcortex-perf_defconfig +++ b/arch/arm64/configs/msmcortex-perf_defconfig @@ -101,6 +101,7 @@ CONFIG_IP_MULTIPLE_TABLES=y CONFIG_IP_ROUTE_VERBOSE=y CONFIG_IP_PNP=y CONFIG_IP_PNP_DHCP=y +CONFIG_NET_IPVTI=y CONFIG_INET_AH=y CONFIG_INET_ESP=y CONFIG_INET_IPCOMP=y @@ -114,6 +115,7 @@ CONFIG_INET6_AH=y CONFIG_INET6_ESP=y CONFIG_INET6_IPCOMP=y CONFIG_IPV6_MIP6=y +CONFIG_IPV6_VTI=y CONFIG_IPV6_MULTIPLE_TABLES=y CONFIG_IPV6_SUBTREES=y CONFIG_NETFILTER=y diff --git a/arch/arm64/configs/msmcortex_defconfig b/arch/arm64/configs/msmcortex_defconfig index 5cd5eb4d3bca..b4d11587f3fc 100644 --- a/arch/arm64/configs/msmcortex_defconfig +++ b/arch/arm64/configs/msmcortex_defconfig @@ -100,6 +100,7 @@ CONFIG_IP_MULTIPLE_TABLES=y CONFIG_IP_ROUTE_VERBOSE=y CONFIG_IP_PNP=y CONFIG_IP_PNP_DHCP=y +CONFIG_NET_IPVTI=y CONFIG_INET_AH=y CONFIG_INET_ESP=y CONFIG_INET_IPCOMP=y @@ -112,6 +113,7 @@ CONFIG_INET6_AH=y CONFIG_INET6_ESP=y CONFIG_INET6_IPCOMP=y CONFIG_IPV6_MIP6=y +CONFIG_IPV6_VTI=y CONFIG_IPV6_MULTIPLE_TABLES=y CONFIG_IPV6_SUBTREES=y CONFIG_NETFILTER=y From 21564edd0d3a3b66faac0ca384f2d5f75586f8d5 Mon Sep 17 00:00:00 2001 From: Srikanth Uyyala Date: Tue, 24 Jul 2018 14:27:38 +0530 Subject: [PATCH 146/159] mm-camera2:isp2: Add NULL check for stream_info pointer The function msm_isp_get_stream_common_data could return a NULL, add check to avoid NULL pointer dereference. Change-Id: I157a74189b581d8ba90ef31f71c3be9b8369a764 Signed-off-by: Srikanth Uyyala --- .../platform/msm/camera_v2/isp/msm_isp47.c | 4 ++ .../msm/camera_v2/isp/msm_isp_axi_util.c | 53 ++++++++++++++++++- 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c index 0a969cc897b0..1f7dec8daaee 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c @@ -1904,6 +1904,10 @@ void msm_vfe47_cfg_axi_ub_equal_default( stream_info = msm_isp_get_stream_common_data(vfe_dev, HANDLE_TO_IDX(axi_data->free_wm[i])); + if (!stream_info) { + pr_err("%s: stream_info is NULL!", __func__); + return; + } vfe_idx = msm_isp_get_vfe_idx_for_stream(vfe_dev, stream_info); for (plane = 0; plane < stream_info->num_planes; diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c index c69bdbf191c6..661850d6d7c6 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c @@ -2830,6 +2830,10 @@ static int msm_isp_axi_update_cgc_override(struct vfe_device *vfe_dev_ioctl, } stream_info = msm_isp_get_stream_common_data(vfe_dev_ioctl, HANDLE_TO_IDX(stream_cfg_cmd->stream_handle[i])); + if (!stream_info) { + pr_err("%s: stream_info is NULL", __func__); + return -EINVAL; + } for (j = 0; j < stream_info->num_planes; j++) { for (k = 0; k < stream_info->num_isp; k++) { vfe_dev = stream_info->vfe_dev[k]; @@ -3289,7 +3293,10 @@ static int msm_isp_stop_axi_stream(struct vfe_device *vfe_dev_ioctl, continue; stream_info = msm_isp_get_stream_common_data(vfe_dev_ioctl, HANDLE_TO_IDX(stream_cfg_cmd->stream_handle[i])); - + if (!stream_info) { + pr_err("%s: stream_info is NULL", __func__); + return -EINVAL; + } spin_lock_irqsave(&stream_info->lock, flags); rc = __msm_isp_check_stream_state(stream_info, 0); spin_unlock_irqrestore(&stream_info->lock, flags); @@ -3326,6 +3333,10 @@ int msm_isp_cfg_axi_stream(struct vfe_device *vfe_dev, void *arg) return -EINVAL; stream_info = msm_isp_get_stream_common_data(vfe_dev, HANDLE_TO_IDX(stream_cfg_cmd->stream_handle[i])); + if (!stream_info) { + pr_err("%s: stream_info is NULL", __func__); + return -EINVAL; + } vfe_idx = msm_isp_get_vfe_idx_for_stream_user(vfe_dev, stream_info); if (vfe_idx == -ENOTTY || stream_info->stream_handle[vfe_idx] != @@ -3845,6 +3856,11 @@ int msm_isp_update_axi_stream(struct vfe_device *vfe_dev, void *arg) } stream_info = msm_isp_get_stream_common_data(vfe_dev, HANDLE_TO_IDX(update_info->stream_handle)); + if (!stream_info) { + pr_err("%s:%d: stream_info is null", + __func__, __LINE__); + return -EINVAL; + } if (SRC_TO_INTF(stream_info->stream_src) >= VFE_SRC_MAX) continue; if (stream_info->state != ACTIVE && @@ -3885,6 +3901,11 @@ int msm_isp_update_axi_stream(struct vfe_device *vfe_dev, void *arg) &update_cmd->update_info[i]; stream_info = msm_isp_get_stream_common_data(vfe_dev, HANDLE_TO_IDX(update_info->stream_handle)); + if (!stream_info) { + pr_err("%s:%d: stream_info is null", + __func__, __LINE__); + return -EINVAL; + } stream_info->buf_divert = 0; msm_isp_get_timestamp(×tamp, vfe_dev); frame_id = vfe_dev->axi_data.src_info[ @@ -3919,6 +3940,11 @@ int msm_isp_update_axi_stream(struct vfe_device *vfe_dev, void *arg) &update_cmd->update_info[i]; stream_info = msm_isp_get_stream_common_data(vfe_dev, HANDLE_TO_IDX(update_info->stream_handle)); + if (!stream_info) { + pr_err("%s:%d: stream_info is null", + __func__, __LINE__); + return -EINVAL; + } spin_lock_irqsave(&stream_info->lock, flags); /* no change then break early */ if (stream_info->current_framedrop_period == @@ -3952,6 +3978,11 @@ int msm_isp_update_axi_stream(struct vfe_device *vfe_dev, void *arg) &update_cmd->update_info[i]; stream_info = msm_isp_get_stream_common_data(vfe_dev, HANDLE_TO_IDX(update_info->stream_handle)); + if (!stream_info) { + pr_err("%s:%d: stream_info is null", + __func__, __LINE__); + return -EINVAL; + } sw_skip_info = &update_info->sw_skip_info; if (sw_skip_info->stream_src_mask != 0) { /* SW image buffer drop */ @@ -3976,6 +4007,11 @@ int msm_isp_update_axi_stream(struct vfe_device *vfe_dev, void *arg) &update_cmd->update_info[i]; stream_info = msm_isp_get_stream_common_data(vfe_dev, HANDLE_TO_IDX(update_info->stream_handle)); + if (!stream_info) { + pr_err("%s:%d: stream_info is null", + __func__, __LINE__); + return -EINVAL; + } rc = msm_isp_stream_axi_cfg_update(vfe_dev, stream_info, update_info); if (rc) @@ -4009,6 +4045,11 @@ int msm_isp_update_axi_stream(struct vfe_device *vfe_dev, void *arg) &update_cmd->update_info[i]; stream_info = msm_isp_get_stream_common_data(vfe_dev, HANDLE_TO_IDX(update_info->stream_handle)); + if (!stream_info) { + pr_err("%s:%d: stream_info is null", + __func__, __LINE__); + return -EINVAL; + } rc = msm_isp_add_buf_queue(vfe_dev, stream_info, update_info->user_stream_id); if (rc) @@ -4023,6 +4064,11 @@ int msm_isp_update_axi_stream(struct vfe_device *vfe_dev, void *arg) &update_cmd->update_info[i]; stream_info = msm_isp_get_stream_common_data(vfe_dev, HANDLE_TO_IDX(update_info->stream_handle)); + if (!stream_info) { + pr_err("%s:%d: stream_info is null", + __func__, __LINE__); + return -EINVAL; + } msm_isp_remove_buf_queue(vfe_dev, stream_info, update_info->user_stream_id); pr_debug("%s, Remove bufq for Stream 0x%x\n", @@ -4059,6 +4105,11 @@ int msm_isp_update_axi_stream(struct vfe_device *vfe_dev, void *arg) &update_cmd->update_info[i]; stream_info = msm_isp_get_stream_common_data(vfe_dev, HANDLE_TO_IDX(update_info->stream_handle)); + if (!stream_info) { + pr_err("%s:%d: stream_info is null", + __func__, __LINE__); + return -EINVAL; + } vfe_idx = msm_isp_get_vfe_idx_for_stream( vfe_dev, stream_info); msm_isp_stream_axi_cfg_update(vfe_dev, stream_info, From 45d853997fa177bcedc07d3eddf4774483e48ac8 Mon Sep 17 00:00:00 2001 From: Venkata Rao Kakani Date: Thu, 19 Jul 2018 15:04:57 +0530 Subject: [PATCH 147/159] defconfig: msm: Enable QUOTA encryption support Add sdcardfs support and QUOTA encryption support for CTS issue fixes. Change-Id: Ie7120b21bf5b6b00432cc79302a3cf740a2cc710 Signed-off-by: Venkata Rao Kakani --- arch/arm64/configs/msm-auto-perf_defconfig | 4 ++++ arch/arm64/configs/msm-auto_defconfig | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/arch/arm64/configs/msm-auto-perf_defconfig b/arch/arm64/configs/msm-auto-perf_defconfig index 81e18d05b0d0..fcebb93d2b30 100644 --- a/arch/arm64/configs/msm-auto-perf_defconfig +++ b/arch/arm64/configs/msm-auto-perf_defconfig @@ -585,12 +585,16 @@ CONFIG_EXT4_FS_SECURITY=y CONFIG_EXT4_ENCRYPTION=y CONFIG_EXT4_FS_ENCRYPTION=y CONFIG_EXT4_FS_ICE_ENCRYPTION=y +CONFIG_QUOTA=y +CONFIG_QUOTA_NETLINK_INTERFACE=y +CONFIG_QFMT_V2=y CONFIG_FUSE_FS=y CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y CONFIG_TMPFS_POSIX_ACL=y CONFIG_ECRYPT_FS=y CONFIG_ECRYPT_FS_MESSAGING=y +CONFIG_SDCARD_FS=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y CONFIG_PRINTK_TIME=y diff --git a/arch/arm64/configs/msm-auto_defconfig b/arch/arm64/configs/msm-auto_defconfig index cc1000edbef0..34edf61fb5a3 100644 --- a/arch/arm64/configs/msm-auto_defconfig +++ b/arch/arm64/configs/msm-auto_defconfig @@ -594,12 +594,16 @@ CONFIG_EXT4_FS_SECURITY=y CONFIG_EXT4_ENCRYPTION=y CONFIG_EXT4_FS_ENCRYPTION=y CONFIG_EXT4_FS_ICE_ENCRYPTION=y +CONFIG_QUOTA=y +CONFIG_QUOTA_NETLINK_INTERFACE=y +CONFIG_QFMT_V2=y CONFIG_FUSE_FS=y CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y CONFIG_TMPFS_POSIX_ACL=y CONFIG_ECRYPT_FS=y CONFIG_ECRYPT_FS_MESSAGING=y +CONFIG_SDCARD_FS=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y CONFIG_PRINTK_TIME=y From f6b9625a3eab3bd854d84c2ea2e6fe03126630df Mon Sep 17 00:00:00 2001 From: Mohammed Javid Date: Fri, 13 Jul 2018 15:47:51 +0530 Subject: [PATCH 148/159] msm: ipa3: Update holb config on USB DPL ep Once USB DPL consumer ep is configured, there is a chance of IPA hardware getting stalled, if DPL client is not pulling the data over other end. so, set holb discard over USB DPL cons ep to avoid this stall. Change-Id: I520b8c1ec84e03b783677c43670cbb9f904a4b4f Signed-off-by: Mohammed Javid --- drivers/platform/msm/ipa/ipa_v3/ipa_client.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c index 69dda048f2bb..0f86194488c0 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -62,8 +62,16 @@ int ipa3_enable_data_path(u32 clnt_hdl) IPADBG("Enabling data path\n"); if (IPA_CLIENT_IS_CONS(ep->client)) { - memset(&holb_cfg, 0 , sizeof(holb_cfg)); - holb_cfg.en = IPA_HOLB_TMR_DIS; + memset(&holb_cfg, 0, sizeof(holb_cfg)); + /* + * Set HOLB on USB DPL CONS to avoid IPA stall + * if DPL client is not pulling the data + * on other end from IPA hw. + */ + if (ep->client == IPA_CLIENT_USB_DPL_CONS) + holb_cfg.en = IPA_HOLB_TMR_EN; + else + holb_cfg.en = IPA_HOLB_TMR_DIS; holb_cfg.tmr_val = 0; res = ipa3_cfg_ep_holb(clnt_hdl, &holb_cfg); } From ac27bafd6ea23c9982528f1ba707aba100e9fd6c Mon Sep 17 00:00:00 2001 From: Mohammed Javid Date: Mon, 2 Jul 2018 12:47:41 +0530 Subject: [PATCH 149/159] msm: ipa: Add support to IPA platform shutdown cleanup Add support for platform reboot from IPA APPS driver perspective. Change-Id: Id65336da06a59a28944bfd51d9482d3d82a9cc3e Signed-off-by: Mohammed Javid --- .../devicetree/bindings/platform/msm/ipa.txt | 2 + drivers/platform/msm/ipa/ipa_api.c | 39 ++++- drivers/platform/msm/ipa/ipa_api.h | 17 +- drivers/platform/msm/ipa/ipa_v2/ipa.c | 155 ++++++++++++++++++ drivers/platform/msm/ipa/ipa_v2/ipa_client.c | 78 ++++++++- drivers/platform/msm/ipa/ipa_v2/ipa_i.h | 11 +- drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c | 56 ++++++- include/uapi/linux/msm_ipa.h | 5 + 8 files changed, 345 insertions(+), 18 deletions(-) diff --git a/Documentation/devicetree/bindings/platform/msm/ipa.txt b/Documentation/devicetree/bindings/platform/msm/ipa.txt index ed784f7f58a5..c9f099b49e7d 100644 --- a/Documentation/devicetree/bindings/platform/msm/ipa.txt +++ b/Documentation/devicetree/bindings/platform/msm/ipa.txt @@ -59,6 +59,8 @@ memory allocation over a PCIe bridge a pipe reset via the IPA uC is required - qcom,ipa-wdi2: Boolean context flag to indicate whether using wdi-2.0 or not +- qcom,apps-shutdown-support: Boolean context flag to indicate whether + apps shutdown support is there or not. - qcom,use-64-bit-dma-mask: Boolean context flag to indicate whether using 64bit dma mask or not - qcom,use-dma-zone: Boolean context flag to indicate whether memory diff --git a/drivers/platform/msm/ipa/ipa_api.c b/drivers/platform/msm/ipa/ipa_api.c index bc0263c371a1..719a1ec5360f 100644 --- a/drivers/platform/msm/ipa/ipa_api.c +++ b/drivers/platform/msm/ipa/ipa_api.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -2672,6 +2672,42 @@ static int ipa_generic_plat_drv_probe(struct platform_device *pdev_p) return result; } +static void ipa_generic_plat_drv_shutdown(struct platform_device *pdev_p) +{ + int result; + + pr_info("ipa: IPA driver shutdown started for %s\n", + pdev_p->dev.of_node->name); + + if (!ipa_api_ctrl) { + pr_err("ipa: invalid ipa_api_ctrl\n"); + return; + } + + /* call probe based on IPA HW version */ + switch (ipa_api_hw_type) { + case IPA_HW_v2_0: + case IPA_HW_v2_1: + case IPA_HW_v2_5: + case IPA_HW_v2_6L: + result = ipa_plat_drv_shutdown(pdev_p, ipa_api_ctrl, + ipa_plat_drv_match); + break; + case IPA_HW_v3_0: + case IPA_HW_v3_1: + case IPA_HW_v3_5: + case IPA_HW_v3_5_1: + default: + pr_err("ipa: ipa_generic_plat_drv_shutdown, unsupported version %d\n", + ipa_api_hw_type); + return; + } + + if (result) + pr_err("ipa: ipa_generic_plat_drv_shutdown failed\n"); +} + + static int ipa_ap_suspend(struct device *dev) { int ret; @@ -2975,6 +3011,7 @@ static struct platform_driver ipa_plat_drv = { .pm = &ipa_pm_ops, .of_match_table = ipa_plat_drv_match, }, + .shutdown = ipa_generic_plat_drv_shutdown, }; static int __init ipa_module_init(void) diff --git a/drivers/platform/msm/ipa/ipa_api.h b/drivers/platform/msm/ipa/ipa_api.h index 1fb0e7122042..33e0f469d0d2 100644 --- a/drivers/platform/msm/ipa/ipa_api.h +++ b/drivers/platform/msm/ipa/ipa_api.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -384,12 +384,27 @@ struct ipa_api_controller { #ifdef CONFIG_IPA int ipa_plat_drv_probe(struct platform_device *pdev_p, struct ipa_api_controller *api_ctrl, struct of_device_id *pdrv_match); +int ipa_plat_drv_shutdown(struct platform_device *pdev_p, + struct ipa_api_controller *api_ctrl, + const struct of_device_id *pdrv_match); +void ipa_platform_shutdown(void); #else static inline int ipa_plat_drv_probe(struct platform_device *pdev_p, struct ipa_api_controller *api_ctrl, struct of_device_id *pdrv_match) { return -ENODEV; } +static inline int ipa_plat_drv_shutdown(struct platform_device *pdev_p, + struct ipa_api_controller *api_ctrl, + const struct of_device_id *pdrv_match) +{ + return -ENODEV; +} +static inline int ipa_platform_shutdown(void) +{ + return -ENODEV; +} + #endif /* (CONFIG_IPA) */ #ifdef CONFIG_IPA3 diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa.c b/drivers/platform/msm/ipa/ipa_v2/ipa.c index ad7d2d6175bd..bf46ea860fef 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa.c @@ -1752,6 +1752,31 @@ int ipa_q6_pipe_delay(bool zip_pipes) return 0; } +/* Remove delay only for IPA consumer pipes */ +static void ipa_pipe_delay(bool set_reset) +{ + u32 reg_val = 0; + int client_idx; + int ep_idx; + + for (client_idx = 0; client_idx < IPA_CLIENT_MAX; client_idx++) { + /* Break the processing for IPA PROD pipes and avoid looping. */ + if (IPA_CLIENT_IS_CONS(client_idx)) + break; + + ep_idx = ipa2_get_ep_mapping(client_idx); + if (ep_idx == -1) + continue; + + IPA_SETFIELD_IN_REG(reg_val, set_reset, + IPA_ENDP_INIT_CTRL_N_ENDP_DELAY_SHFT, + IPA_ENDP_INIT_CTRL_N_ENDP_DELAY_BMSK); + + ipa_write_reg(ipa_ctx->mmio, + IPA_ENDP_INIT_CTRL_N_OFST(ep_idx), reg_val); + } +} + int ipa_q6_monitor_holb_mitigation(bool enable) { int ep_idx; @@ -1830,6 +1855,51 @@ static int ipa_q6_avoid_holb(bool zip_pipes) return 0; } +/* + * Set HOLB drop on all IPA producer/client cons pipes, + * do not set suspend + */ +static void ipa_avoid_holb(void) +{ + u32 reg_val; + int ep_idx; + int client_idx = IPA_CLIENT_MAX - 1; + + for (; client_idx >= 0; client_idx--) { + /* Break the processing for IPA CONS pipes and avoid looping. */ + if (IPA_CLIENT_IS_PROD(client_idx)) + break; + + ep_idx = ipa2_get_ep_mapping(client_idx); + if (ep_idx == -1) + continue; + + /* + * ipa2_cfg_ep_holb is not used here because we are + * also setting HOLB on Q6 pipes, and from APPS perspective + * they are not valid, therefore, the above function + * will fail. + */ + reg_val = 0; + IPA_SETFIELD_IN_REG(reg_val, 0, + IPA_ENDP_INIT_HOL_BLOCK_TIMER_N_TIMER_SHFT, + IPA_ENDP_INIT_HOL_BLOCK_TIMER_N_TIMER_BMSK); + + ipa_write_reg(ipa_ctx->mmio, + IPA_ENDP_INIT_HOL_BLOCK_TIMER_N_OFST_v2_0(ep_idx), + reg_val); + + reg_val = 0; + IPA_SETFIELD_IN_REG(reg_val, 1, + IPA_ENDP_INIT_HOL_BLOCK_EN_N_EN_SHFT, + IPA_ENDP_INIT_HOL_BLOCK_EN_N_EN_BMSK); + + ipa_write_reg(ipa_ctx->mmio, + IPA_ENDP_INIT_HOL_BLOCK_EN_N_OFST_v2_0(ep_idx), + reg_val); + } +} + static u32 ipa_get_max_flt_rt_cmds(u32 num_pipes) { u32 max_cmds = 0; @@ -2089,6 +2159,49 @@ static int ipa_q6_set_ex_path_dis_agg(void) return retval; } +int register_ipa_platform_cb(int (*q6_cleanup_cb)(void)) +{ + IPAERR("In register_ipa_platform_cb\n"); + if (ipa_ctx) { + if (ipa_ctx->q6_cleanup_cb == NULL) { + IPAERR("reg q6_cleanup_cb\n"); + ipa_ctx->q6_cleanup_cb = q6_cleanup_cb; + } else + IPAERR("Already registered\n"); + } else { + IPAERR("IPA driver not initialized, retry\n"); + return -EAGAIN; + } + return 0; +} + +/** +* ipa_apps_shutdown_cleanup() - Take care Apps ep's cleanup +* 1) Set HOLB drop on all IPA producer pipes. +* 2) Remove delay for all IPA consumer pipes. +* 3) Wait for all IPA consumer pipes to go empty and +* reset it. +* 4) Do aggregation force close for all pipes. +* 5) Reset all IPA producer pipes + +* 0: success +*/ + +int ipa_apps_shutdown_cleanup(void) +{ + IPA_ACTIVE_CLIENTS_INC_SPECIAL("APPS_SHUTDOWN"); + + ipa_avoid_holb(); + + ipa_pipe_delay(false); + + ipa2_apps_shutdown_apps_ep_reset(); + + IPA_ACTIVE_CLIENTS_DEC_SPECIAL("APPS_SHUTDOWN"); + + return 0; +} + /** * ipa_q6_pre_shutdown_cleanup() - A cleanup for all Q6 related configuration * in IPA HW before modem shutdown. This is performed in @@ -3907,6 +4020,8 @@ static int ipa_init(const struct ipa_plat_drv_res *resource_p, ipa_ctx->skip_uc_pipe_reset = resource_p->skip_uc_pipe_reset; ipa_ctx->use_dma_zone = resource_p->use_dma_zone; ipa_ctx->tethered_flow_control = resource_p->tethered_flow_control; + ipa_ctx->is_apps_shutdown_support = + resource_p->is_apps_shutdown_support; /* Setting up IPA RX Polling Timeout Seconds */ ipa_rx_timeout_min_max_calc(&ipa_ctx->ipa_rx_min_timeout_usec, @@ -4447,6 +4562,7 @@ static int get_ipa_dts_configuration(struct platform_device *pdev, ipa_drv_res->ipa_wdi2 = false; ipa_drv_res->wan_rx_ring_size = IPA_GENERIC_RX_POOL_SZ; ipa_drv_res->lan_rx_ring_size = IPA_GENERIC_RX_POOL_SZ; + ipa_drv_res->is_apps_shutdown_support = false; /* Get IPA HW Version */ result = of_property_read_u32(pdev->dev.of_node, "qcom,ipa-hw-ver", @@ -4474,6 +4590,14 @@ static int get_ipa_dts_configuration(struct platform_device *pdev, ipa_drv_res->ipa_uc_monitor_holb ? "Enabled" : "Disabled"); + /* Check apps_shutdown_support enabled or disabled */ + ipa_drv_res->is_apps_shutdown_support = + of_property_read_bool(pdev->dev.of_node, + "qcom,apps-shutdown-support"); + IPAERR(": apps shutdown support = %s\n", + ipa_drv_res->is_apps_shutdown_support + ? "Enabled" : "Disabled"); + /* Get IPA WAN / LAN RX pool sizes */ result = of_property_read_u32(pdev->dev.of_node, "qcom,wan-rx-ring-size", @@ -4918,6 +5042,37 @@ static int ipa_smmu_ap_cb_probe(struct device *dev) return result; } +/** +* ipa_platform_shutdown() - Ensure Q6 ep cleanup is done and +* followed by APPS ep's cleanup. +*/ +void ipa_platform_shutdown(void) +{ + IPADBG("****************ipa_platform_shutdown****************\n"); + if (ipa_ctx->q6_cleanup_cb) + ipa_ctx->q6_cleanup_cb(); + else + IPADBG("No Q6 cleanup callback registered\n"); + ipa_apps_shutdown_cleanup(); +} + +int ipa_plat_drv_shutdown(struct platform_device *pdev_p, + struct ipa_api_controller *api_ctrl, + const struct of_device_id *pdrv_match) +{ + if (!ipa_ctx) { + pr_err("IPA driver not initialized\n"); + return -EOPNOTSUPP; + } + if (ipa_ctx->is_apps_shutdown_support) + ipa_platform_shutdown(); + else { + pr_err("There is no apps IPA driver shutdown support\n"); + return -EOPNOTSUPP; + } + return 0; +} + int ipa_plat_drv_probe(struct platform_device *pdev_p, struct ipa_api_controller *api_ctrl, struct of_device_id *pdrv_match) { diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_client.c b/drivers/platform/msm/ipa/ipa_v2/ipa_client.c index 74e7394a80b1..b1eb67dbf02c 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_client.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_client.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -84,11 +84,20 @@ int ipa_disable_data_path(u32 clnt_hdl) IPA_ENDP_INIT_AGGR_N_OFST_v2_0(clnt_hdl)); if (((aggr_init & IPA_ENDP_INIT_AGGR_N_AGGR_EN_BMSK) >> IPA_ENDP_INIT_AGGR_N_AGGR_EN_SHFT) == IPA_ENABLE_AGGR) { - res = ipa_tag_aggr_force_close(clnt_hdl); - if (res) { - IPAERR("tag process timeout, client:%d err:%d\n", - clnt_hdl, res); - BUG(); + /* + * Tag process will not work for, + * APPS CMD PROD --> Uses the same for IMM cmd over tag + * APPS LAN CONS --> Already suspend is set + */ + if (!(ep->client == IPA_CLIENT_APPS_CMD_PROD || + ep->client == IPA_CLIENT_APPS_LAN_CONS)) { + res = ipa_tag_aggr_force_close(clnt_hdl); + if (res) { + IPAERR("tag process timeout"); + IPAERR("client:%d err:%d\n", + clnt_hdl, res); + ipa_assert(); + } } } @@ -764,6 +773,63 @@ bail: return res; } +/** +* ipa2_apps_shutdown_apps_ep_reset() - +* reset an endpoints from BAM perspective. +* +* Q6 ep reset is not handled here +*/ +void ipa2_apps_shutdown_apps_ep_reset(void) +{ + struct ipa_ep_context *ep; + int ep_idx, client_idx; + + if (unlikely(!ipa_ctx)) { + IPAERR("IPA driver was not initialized\n"); + return; + } + + for (client_idx = 0; client_idx < IPA_CLIENT_MAX; client_idx++) { + + ep_idx = ipa2_get_ep_mapping(client_idx); + if (ep_idx == -1) + continue; + + ep = &ipa_ctx->ep[ep_idx]; + if (ep->valid && (IPA_CLIENT_IS_APPS_PROD(client_idx) || + IPA_CLIENT_IS_APPS_CONS(client_idx))) { + /* + * we shouldn't reset APPS CMD PROD + * and LAN CONS in for loop + * these 2 ep's should be resetted at last, + * since it is used in Tag Process + */ + if (!(client_idx == IPA_CLIENT_APPS_CMD_PROD || + client_idx == IPA_CLIENT_APPS_LAN_CONS)) { + IPADBG("teardown ep (%d)\n", ep_idx); + ipa2_teardown_sys_pipe(ep_idx); + } + } + } + ep_idx = ipa2_get_ep_mapping(IPA_CLIENT_APPS_LAN_CONS); + if (ep_idx != -1) { + ep = &ipa_ctx->ep[ep_idx]; + if (ep->valid) { + IPADBG("teardown ep (%d)\n", ep_idx); + ipa2_teardown_sys_pipe(ep_idx); + } + } + + ep_idx = ipa2_get_ep_mapping(IPA_CLIENT_APPS_CMD_PROD); + if (ep_idx != -1) { + ep = &ipa_ctx->ep[ep_idx]; + if (ep->valid) { + IPADBG("teardown ep (%d)\n", ep_idx); + ipa2_teardown_sys_pipe(ep_idx); + } + } +} + /** * ipa2_clear_endpoint_delay() - Remove ep delay set on the IPA pipe before * client disconnect. diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h index 28689eb83d4e..1986dc2af097 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1207,6 +1207,8 @@ struct ipa_context { struct ipa_cne_evt ipa_cne_evt_req_cache[IPA_MAX_NUM_REQ_CACHE]; int num_ipa_cne_evt_req; struct mutex ipa_cne_evt_lock; + int (*q6_cleanup_cb)(void); + bool is_apps_shutdown_support; }; /** @@ -1263,6 +1265,7 @@ struct ipa_plat_drv_res { u32 ipa_rx_polling_sleep_msec; u32 ipa_polling_iteration; bool ipa_uc_monitor_holb; + bool is_apps_shutdown_support; }; struct ipa_mem_partition { @@ -1388,6 +1391,8 @@ int ipa2_disconnect(u32 clnt_hdl); */ int ipa2_reset_endpoint(u32 clnt_hdl); +void ipa2_apps_shutdown_apps_ep_reset(void); + /* * Remove ep delay */ @@ -1781,7 +1786,7 @@ static inline u32 ipa_read_reg_field(void *base, u32 offset, return (ipa_read_reg(base, offset) & mask) >> shift; } -static inline void ipa_write_reg(void *base, u32 offset, u32 val) +static inline void ipa_write_reg(void __iomem *base, u32 offset, u32 val) { iowrite32(val, base + offset); } @@ -1868,6 +1873,8 @@ int ipa_tag_process(struct ipa_desc *desc, int num_descs, unsigned long timeout); int ipa_q6_pre_shutdown_cleanup(void); +int ipa_apps_shutdown_cleanup(void); +int register_ipa_platform_cb(int (*cb)(void)); int ipa_q6_post_shutdown_cleanup(void); int ipa_init_q6_smem(void); int ipa_q6_monitor_holb_mitigation(bool enable); diff --git a/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c index 3defc03c2571..c79978038668 100644 --- a/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c +++ b/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c @@ -76,6 +76,8 @@ static bool egress_set, a7_ul_flt_set; static struct workqueue_struct *ipa_rm_q6_workqueue; /* IPA_RM workqueue*/ static atomic_t is_initialized; static atomic_t is_ssr; +static atomic_t is_after_powerup_cmpltd; +static struct completion is_after_shutdown_cmpltd; static void *subsys_notify_handle; u32 apps_to_ipa_hdl, ipa_to_apps_hdl; /* get handler from ipa */ @@ -135,6 +137,14 @@ struct wwan_private { struct napi_struct napi; }; +static int ssr_notifier_cb(struct notifier_block *this, + unsigned long code, + void *data); + +static struct notifier_block ssr_notifier = { + .notifier_call = ssr_notifier_cb, +}; + /** * ipa_setup_a7_qmap_hdr() - Setup default a7 qmap hdr * @@ -1958,16 +1968,35 @@ static void ipa_rm_notify(void *dev, enum ipa_rm_event event, } } +/** +* q6_cleanup_cb() - IPA q6 cleanup +* +* This function is called in the sequence +* of ipa platform shutdown +*/ + +static int q6_cleanup_cb(void) +{ + int ret = 0; + + IPAWANERR("Start\n"); + if (atomic_read(&is_initialized) && + atomic_read(&is_after_powerup_cmpltd)) { + pr_info("Wait for q6 cleanup\n"); + wait_for_completion(&is_after_shutdown_cmpltd); + pr_info("q6_cleanup_cb: Q6 SSR cleanup is taken care\n"); + } else { + if (!atomic_read(&is_initialized)) + pr_info("RmNET IPA driver is not inited\n"); + if (!atomic_read(&is_after_powerup_cmpltd)) + pr_info("Modem is not up\n"); + } + IPAWANERR("END\n"); + return ret; +} + /* IPA_RM related functions end*/ -static int ssr_notifier_cb(struct notifier_block *this, - unsigned long code, - void *data); - -static struct notifier_block ssr_notifier = { - .notifier_call = ssr_notifier_cb, -}; - static int get_ipa_rmnet_dts_configuration(struct platform_device *pdev, struct ipa_rmnet_plat_drv_res *ipa_rmnet_drv_res) { @@ -2179,6 +2208,8 @@ static int ipa_wwan_probe(struct platform_device *pdev) ipa2_proxy_clk_unvote(); } atomic_set(&is_ssr, 0); + atomic_set(&is_after_powerup_cmpltd, 0); + init_completion(&is_after_shutdown_cmpltd); pr_info("rmnet_ipa completed initialization\n"); return 0; @@ -2221,6 +2252,7 @@ setup_dflt_wan_rt_tables_err: setup_a7_qmap_hdr_err: ipa_qmi_service_exit(); atomic_set(&is_ssr, 0); + atomic_set(&is_after_powerup_cmpltd, 0); return ret; } @@ -2409,6 +2441,7 @@ static int ssr_notifier_cb(struct notifier_block *this, if (atomic_read(&is_ssr)) ipa_q6_post_shutdown_cleanup(); pr_info("IPA AFTER_SHUTDOWN handling is complete\n"); + complete(&is_after_shutdown_cmpltd); return NOTIFY_DONE; } if (SUBSYS_AFTER_POWERUP == code) { @@ -2416,6 +2449,7 @@ static int ssr_notifier_cb(struct notifier_block *this, if (!atomic_read(&is_initialized) && atomic_read(&is_ssr)) platform_driver_register(&rmnet_ipa_driver); + atomic_set(&is_after_powerup_cmpltd, 1); pr_info("IPA AFTER_POWERUP handling is complete\n"); return NOTIFY_DONE; } @@ -3222,6 +3256,7 @@ void ipa_q6_handshake_complete(bool ssr_bootup) static int __init ipa_wwan_init(void) { + int ret = 0; atomic_set(&is_initialized, 0); atomic_set(&is_ssr, 0); @@ -3231,6 +3266,11 @@ static int __init ipa_wwan_init(void) ipa_qmi_init(); + IPAWANERR("Registering for q6_cleanup_cb\n"); + ret = register_ipa_platform_cb(&q6_cleanup_cb); + if (ret == -EAGAIN) + IPAWANERR("Register for q6_cleanup_cb is un-successful\n"); + /* Register for Modem SSR */ subsys_notify_handle = subsys_notif_register_notifier(SUBSYS_MODEM, &ssr_notifier); diff --git a/include/uapi/linux/msm_ipa.h b/include/uapi/linux/msm_ipa.h index 6a471c955d91..001ef390e288 100644 --- a/include/uapi/linux/msm_ipa.h +++ b/include/uapi/linux/msm_ipa.h @@ -261,6 +261,11 @@ enum ipa_client_type { ((client) == IPA_CLIENT_APPS_LAN_CONS || \ (client) == IPA_CLIENT_APPS_WAN_CONS) +#define IPA_CLIENT_IS_APPS_PROD(client) \ + ((client) == IPA_CLIENT_APPS_LAN_PROD || \ + (client) == IPA_CLIENT_APPS_WAN_PROD || \ + (client) == IPA_CLIENT_APPS_CMD_PROD) + #define IPA_CLIENT_IS_USB_CONS(client) \ ((client) == IPA_CLIENT_USB_CONS || \ (client) == IPA_CLIENT_USB2_CONS || \ From b69cba7b7ccb03b240525212f98ccd5a902e7820 Mon Sep 17 00:00:00 2001 From: Neeraj Upadhyay Date: Mon, 16 Apr 2018 15:02:03 +0530 Subject: [PATCH 150/159] arch: arm64: Reenable HW breakpoint HW breakpoint was disabled in 'commit f2a3f3ef8e73 ("arch: arm64: disable HW breakpoint")'. However, it is required for setting breakpoints using ptrace syscall, which is required for certain userspace applications to work. So, reenable it. Change-Id: Ib2a49488b92b0f77d13871d151778b3f0feab273 Signed-off-by: Neeraj Upadhyay --- arch/arm64/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index be21fb8ebb04..b6f3d353e1f9 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -77,6 +77,7 @@ config ARM64 select HAVE_FUNCTION_TRACER select HAVE_FUNCTION_GRAPH_TRACER select HAVE_GENERIC_DMA_COHERENT + select HAVE_HW_BREAKPOINT if PERF_EVENTS select HAVE_IRQ_TIME_ACCOUNTING select HAVE_MEMBLOCK select HAVE_PATA_PLATFORM From 4faca7cde511cfb74ea9fe55cde7933bcd751987 Mon Sep 17 00:00:00 2001 From: Yong Ding Date: Tue, 31 Jul 2018 14:16:16 +0800 Subject: [PATCH 151/159] soc: qcom: hab: add hab statistics support This allows user to read back hab runtime information. Change-Id: Id266dd17b9c9d38f0e93aa600510ae1c6b12cca5 Signed-off-by: Yong Ding --- drivers/soc/qcom/hab/Makefile | 3 +- drivers/soc/qcom/hab/hab.c | 9 +- drivers/soc/qcom/hab/hab.h | 16 ++- drivers/soc/qcom/hab/hab_mem_linux.c | 19 +++ drivers/soc/qcom/hab/hab_mimex.c | 7 +- drivers/soc/qcom/hab/hab_qvm.h | 2 +- drivers/soc/qcom/hab/hab_stat.c | 167 +++++++++++++++++++++++++++ drivers/soc/qcom/hab/hab_vchan.c | 49 ++++++++ drivers/soc/qcom/hab/khab_test.c | 124 ++++++++++++++++++-- drivers/soc/qcom/hab/qvm_comm.c | 13 ++- 10 files changed, 387 insertions(+), 22 deletions(-) create mode 100644 drivers/soc/qcom/hab/hab_stat.c diff --git a/drivers/soc/qcom/hab/Makefile b/drivers/soc/qcom/hab/Makefile index 945ae52de196..9dbe77bfc23d 100644 --- a/drivers/soc/qcom/hab/Makefile +++ b/drivers/soc/qcom/hab/Makefile @@ -9,7 +9,8 @@ msm_hab-objs = \ hab_mem_linux.o \ hab_pipe.o \ hab_parser.o \ - khab_test.o + khab_test.o \ + hab_stat.o ifdef CONFIG_GHS_VMM msm_hab_hyp-objs = \ diff --git a/drivers/soc/qcom/hab/hab.c b/drivers/soc/qcom/hab/hab.c index ef249bcba68c..b4ce657edae0 100644 --- a/drivers/soc/qcom/hab/hab.c +++ b/drivers/soc/qcom/hab/hab.c @@ -21,7 +21,7 @@ .openlock = __SPIN_LOCK_UNLOCKED(&hab_devices[__num__].openlock)\ } -static const char hab_info_str[] = "Change: 16239527 Revision: #65"; +static const char hab_info_str[] = "Change: 16764735 Revision: #76"; /* * The following has to match habmm definitions, order does not matter if @@ -283,7 +283,7 @@ struct virtual_channel *frontend_open(struct uhab_context *ctx, pr_err("vchan alloc failed\n"); ret = -ENOMEM; goto err; - } else + } /* Send Init sequence */ hab_open_request_init(&request, HAB_PAYLOAD_TYPE_INIT, pchan, @@ -667,6 +667,7 @@ int hab_vchan_open(struct uhab_context *ctx, } } else { pr_err("failed to find device, mmid %d\n", mmid); + return -ENODEV; } } @@ -1368,6 +1369,9 @@ static int __init hab_init(void) } else set_dma_ops(hab_driver.dev, &hab_dma_ops); } + + hab_stat_init(&hab_driver); + return result; err: @@ -1387,6 +1391,7 @@ static void __exit hab_exit(void) dev_t dev; hab_hypervisor_unregister(); + hab_stat_deinit(&hab_driver); hab_ctx_put(hab_driver.kctx); dev = MKDEV(MAJOR(hab_driver.major), 0); device_destroy(hab_driver.class, dev); diff --git a/drivers/soc/qcom/hab/hab.h b/drivers/soc/qcom/hab/hab.h index d1aa88e3978e..f381303f3ca8 100644 --- a/drivers/soc/qcom/hab/hab.h +++ b/drivers/soc/qcom/hab/hab.h @@ -43,6 +43,8 @@ #include #include #include +#include +#include enum hab_payload_type { HAB_PAYLOAD_TYPE_MSG = 0x0, @@ -338,6 +340,8 @@ struct hab_driver { int b_loopback; void *hyp_priv; /* hypervisor plug-in storage */ + + void *hab_vmm_handle; }; struct virtual_channel { @@ -412,6 +416,7 @@ int hab_vchan_recv(struct uhab_context *ctx, void hab_vchan_stop(struct virtual_channel *vchan); void hab_vchans_stop(struct physical_channel *pchan); void hab_vchan_stop_notify(struct virtual_channel *vchan); +void hab_vchans_empty_wait(int vmid); int hab_mem_export(struct uhab_context *ctx, struct hab_export *param, int kernel); @@ -456,7 +461,7 @@ int habmm_imp_hyp_unmap(void *imp_ctx, struct export_desc *exp, int kernel); int habmem_imp_hyp_mmap(struct file *flip, struct vm_area_struct *vma); - +int habmm_imp_hyp_map_check(void *imp_ctx, struct export_desc *exp); void hab_msg_free(struct hab_message *message); int hab_msg_dequeue(struct virtual_channel *vchan, @@ -563,6 +568,15 @@ int hab_open_cancel_notify(struct hab_open_request *request); int hab_open_receive_cancel(struct physical_channel *pchan, size_t sizebytes); +int hab_stat_init(struct hab_driver *drv); +int hab_stat_deinit(struct hab_driver *drv); +int hab_stat_show_vchan(struct hab_driver *drv, char *buf, int sz); +int hab_stat_show_ctx(struct hab_driver *drv, char *buf, int sz); +int hab_stat_show_expimp(struct hab_driver *drv, int pid, char *buf, int sz); + +int hab_stat_init_sub(struct hab_driver *drv); +int hab_stat_deinit_sub(struct hab_driver *drv); + /* Global singleton HAB instance */ extern struct hab_driver hab_driver; diff --git a/drivers/soc/qcom/hab/hab_mem_linux.c b/drivers/soc/qcom/hab/hab_mem_linux.c index e9e42554cbe2..da41536205a5 100644 --- a/drivers/soc/qcom/hab/hab_mem_linux.c +++ b/drivers/soc/qcom/hab/hab_mem_linux.c @@ -751,3 +751,22 @@ int habmem_imp_hyp_mmap(struct file *filp, struct vm_area_struct *vma) return 0; } + +int habmm_imp_hyp_map_check(void *imp_ctx, struct export_desc *exp) +{ + struct importer_context *priv = imp_ctx; + struct pages_list *pglist; + int found = 0; + + read_lock(&priv->implist_lock); + list_for_each_entry(pglist, &priv->imp_list, list) { + if (pglist->export_id == exp->export_id && + pglist->vcid == exp->vcid_remote) { + found = 1; + break; + } + } + read_unlock(&priv->implist_lock); + + return found; +} diff --git a/drivers/soc/qcom/hab/hab_mimex.c b/drivers/soc/qcom/hab/hab_mimex.c index 3e9046381b12..23087680c690 100644 --- a/drivers/soc/qcom/hab/hab_mimex.c +++ b/drivers/soc/qcom/hab/hab_mimex.c @@ -104,8 +104,8 @@ static struct export_desc *habmem_add_export(struct virtual_channel *vchan, exp->vchan = vchan; exp->vcid_local = vchan->id; exp->vcid_remote = vchan->otherend_id; - exp->domid_local = -1; /* dom id, provided on the importer */ - exp->domid_remote = vchan->pchan->dom_id; + exp->domid_local = vchan->pchan->vmid_local; + exp->domid_remote = vchan->pchan->vmid_remote; exp->ctx = vchan->ctx; exp->pchan = vchan->pchan; @@ -124,7 +124,8 @@ void habmem_remove_export(struct export_desc *exp) struct uhab_context *ctx; if (!exp || !exp->ctx || !exp->pchan) { - pr_err("failed to find valid info in exp %pK\n", exp); + pr_err("failed to find valid info in exp %pK ctx %pK pchan %pK\n", + exp, exp->ctx, exp->pchan); return; } diff --git a/drivers/soc/qcom/hab/hab_qvm.h b/drivers/soc/qcom/hab/hab_qvm.h index fe7cb0bbda0a..6ff699c6f2ec 100644 --- a/drivers/soc/qcom/hab/hab_qvm.h +++ b/drivers/soc/qcom/hab/hab_qvm.h @@ -49,5 +49,5 @@ struct qvm_channel { void *qnx_hyp_rx_dispatch(void *data); void hab_pipe_reset(struct physical_channel *pchan); - +void habhyp_notify(void *commdev); #endif /* __HAB_QNX_H */ diff --git a/drivers/soc/qcom/hab/hab_stat.c b/drivers/soc/qcom/hab/hab_stat.c new file mode 100644 index 000000000000..f0a4207bc871 --- /dev/null +++ b/drivers/soc/qcom/hab/hab_stat.c @@ -0,0 +1,167 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#include "hab.h" +#include "hab_grantable.h" + +#define MAX_LINE_SIZE 128 + +int hab_stat_init(struct hab_driver *driver) +{ + return hab_stat_init_sub(driver); +} + +int hab_stat_deinit(struct hab_driver *driver) +{ + return hab_stat_deinit_sub(driver); +} + +/* + * If all goes well the return value is the formated print and concatenated + * original dest string. + */ +static int hab_stat_buffer_print(char *dest, + int dest_size, const char *fmt, ...) +{ + va_list args; + char line[MAX_LINE_SIZE]; + int ret; + + va_start(args, fmt); + ret = vsnprintf(line, sizeof(line), fmt, args); + va_end(args); + if (ret > 0) + ret = strlcat(dest, line, dest_size); + return ret; +} + +int hab_stat_show_vchan(struct hab_driver *driver, + char *buf, int size) +{ + int i, ret = 0; + + ret = strlcpy(buf, "", size); + for (i = 0; i < driver->ndevices; i++) { + struct hab_device *dev = &driver->devp[i]; + struct physical_channel *pchan; + struct virtual_channel *vc; + + spin_lock_bh(&dev->pchan_lock); + list_for_each_entry(pchan, &dev->pchannels, node) { + if (!pchan->vcnt) + continue; + + ret = hab_stat_buffer_print(buf, size, + "mmid %s role %d local %d remote %d vcnt %d:\n", + pchan->name, pchan->is_be, pchan->vmid_local, + pchan->vmid_remote, pchan->vcnt); + + read_lock(&pchan->vchans_lock); + list_for_each_entry(vc, &pchan->vchannels, pnode) { + ret = hab_stat_buffer_print(buf, size, + "%08X ", vc->id); + } + ret = hab_stat_buffer_print(buf, size, "\n"); + read_unlock(&pchan->vchans_lock); + } + spin_unlock_bh(&dev->pchan_lock); + } + + return ret; +} + +int hab_stat_show_ctx(struct hab_driver *driver, + char *buf, int size) +{ + int ret = 0; + struct uhab_context *ctx; + + ret = strlcpy(buf, "", size); + + spin_lock_bh(&hab_driver.drvlock); + ret = hab_stat_buffer_print(buf, size, + "Total contexts %d\n", + driver->ctx_cnt); + list_for_each_entry(ctx, &hab_driver.uctx_list, node) { + ret = hab_stat_buffer_print(buf, size, + "ctx %d K %d close %d vc %d exp %d imp %d open %d\n", + ctx->owner, ctx->kernel, ctx->closing, + ctx->vcnt, ctx->export_total, + ctx->import_total, ctx->pending_cnt); + } + spin_unlock_bh(&hab_driver.drvlock); + + return ret; +} + +static int get_pft_tbl_total_size(struct compressed_pfns *pfn_table) +{ + int i, total_size = 0; + + for (i = 0; i < pfn_table->nregions; i++) + total_size += pfn_table->region[i].size * PAGE_SIZE; + + return total_size; +} + +static int print_ctx_total_expimp(struct uhab_context *ctx, + char *buf, int size) +{ + struct compressed_pfns *pfn_table; + int exp_total = 0, imp_total = 0; + int exp_cnt = 0, imp_cnt = 0; + struct export_desc *exp; + + read_lock(&ctx->exp_lock); + list_for_each_entry(exp, &ctx->exp_whse, node) { + pfn_table = (struct compressed_pfns *)exp->payload; + exp_total += get_pft_tbl_total_size(pfn_table); + exp_cnt++; + } + read_unlock(&ctx->exp_lock); + + spin_lock_bh(&ctx->imp_lock); + list_for_each_entry(exp, &ctx->imp_whse, node) { + if (habmm_imp_hyp_map_check(ctx->import_ctx, exp)) { + pfn_table = (struct compressed_pfns *)exp->payload; + imp_total += get_pft_tbl_total_size(pfn_table); + imp_cnt++; + } + } + spin_unlock_bh(&ctx->imp_lock); + + if (exp_cnt || exp_total || imp_cnt || imp_total) + return hab_stat_buffer_print(buf, size, + "ctx %d exp %d size %d imp %d size %d\n", + ctx->owner, exp_cnt, exp_total, + imp_cnt, imp_total); + else + return 0; +} + +int hab_stat_show_expimp(struct hab_driver *driver, + int pid, char *buf, int size) +{ + struct uhab_context *ctx; + int ret; + + ret = strlcpy(buf, "", size); + + spin_lock_bh(&hab_driver.drvlock); + list_for_each_entry(ctx, &hab_driver.uctx_list, node) { + if (pid == ctx->owner) + ret = print_ctx_total_expimp(ctx, buf, size); + } + spin_unlock_bh(&hab_driver.drvlock); + + return ret; +} diff --git a/drivers/soc/qcom/hab/hab_vchan.c b/drivers/soc/qcom/hab/hab_vchan.c index d127bcca19f8..e7b46df3f97e 100644 --- a/drivers/soc/qcom/hab/hab_vchan.c +++ b/drivers/soc/qcom/hab/hab_vchan.c @@ -194,6 +194,55 @@ void hab_vchan_stop_notify(struct virtual_channel *vchan) hab_vchan_stop(vchan); } +static int hab_vchans_per_pchan_empty(struct physical_channel *pchan) +{ + int empty; + + read_lock(&pchan->vchans_lock); + empty = list_empty(&pchan->vchannels); + read_unlock(&pchan->vchans_lock); + + return empty; +} + +static int hab_vchans_empty(int vmid) +{ + int i, empty = 1; + struct physical_channel *pchan; + struct hab_device *hab_dev; + + for (i = 0; i < hab_driver.ndevices; i++) { + hab_dev = &hab_driver.devp[i]; + + spin_lock_bh(&hab_dev->pchan_lock); + list_for_each_entry(pchan, &hab_dev->pchannels, node) { + if (pchan->vmid_remote == vmid) { + if (!hab_vchans_per_pchan_empty(pchan)) { + empty = 0; + spin_unlock_bh(&hab_dev->pchan_lock); + break; + } + } + } + spin_unlock_bh(&hab_dev->pchan_lock); + } + + return empty; +} + +/* + * block until all vchans of a given GVM are explicitly closed + * with habmm_socket_close() by hab clients themselves + */ +void hab_vchans_empty_wait(int vmid) +{ + pr_info("waiting for GVM%d's sockets closure\n", vmid); + + while (!hab_vchans_empty(vmid)) + schedule(); + + pr_info("all of GVM%d's sockets are closed\n", vmid); +} int hab_vchan_find_domid(struct virtual_channel *vchan) { diff --git a/drivers/soc/qcom/hab/khab_test.c b/drivers/soc/qcom/hab/khab_test.c index 7d6df8861421..bb04815ad35e 100644 --- a/drivers/soc/qcom/hab/khab_test.c +++ b/drivers/soc/qcom/hab/khab_test.c @@ -11,13 +11,12 @@ * */ #include "hab.h" -#include "khab_test.h" -#include "hab_pipe.h" -#ifdef CONFIG_MSM_GVM_QUIN -#include "hab_qvm.h" -#endif +#if !defined CONFIG_GHS_VMM && defined(CONFIG_MSM_GVM_QUIN) #include #include +#include "hab_pipe.h" +#include "hab_qvm.h" +#include "khab_test.h" static char g_perf_test_result[256]; @@ -32,10 +31,8 @@ enum hab_perf_test_type { static int hab_shmm_throughput_test(void) { struct hab_device *habDev; -#ifdef CONFIG_MSM_GVM_QUIN struct qvm_channel *dev; -#endif - struct hab_shared_buf *sh_buf = NULL; + struct hab_shared_buf *sh_buf; struct physical_channel *pchan; struct timeval tv1, tv2; int i, counter; @@ -56,7 +53,6 @@ static int hab_shmm_throughput_test(void) pchan = list_first_entry(&(habDev->pchannels), struct physical_channel, node); -#ifdef CONFIG_MSM_GVM_QUIN dev = pchan->hyp_data; if (!dev) { ret = -EPERM; @@ -64,7 +60,6 @@ static int hab_shmm_throughput_test(void) } sh_buf = dev->pipe_ep->tx_info.sh_buf; -#endif /* pChannel is of 128k, we use 64k to test */ size = 0x10000; @@ -268,3 +263,112 @@ static int get_hab_perf_result(char *buffer, struct kernel_param *kp) return strlcpy(buffer, g_perf_test_result, strlen(g_perf_test_result)+1); } +#endif + +static struct kobject *hab_kobject; + +static int vchan_stat; +static int context_stat; +static int pid_stat; + +static ssize_t vchan_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf) +{ + return hab_stat_show_vchan(&hab_driver, buf, PAGE_SIZE); +} + +static ssize_t vchan_store(struct kobject *kobj, struct kobj_attribute *attr, + char *buf, size_t count) +{ + int ret; + + ret = sscanf(buf, "%du", &vchan_stat); + if (ret < 1) { + pr_err("failed to read anything from input %d", ret); + return 0; + } else + return vchan_stat; +} + +static ssize_t ctx_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf) +{ + return hab_stat_show_ctx(&hab_driver, buf, PAGE_SIZE); +} + +static ssize_t ctx_store(struct kobject *kobj, struct kobj_attribute *attr, + char *buf, size_t count) +{ + int ret; + + ret = sscanf(buf, "%du", &context_stat); + if (ret < 1) { + pr_err("failed to read anything from input %d", ret); + return 0; + } else + return context_stat; +} + +static ssize_t expimp_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf) +{ + return hab_stat_show_expimp(&hab_driver, pid_stat, buf, PAGE_SIZE); +} + +static ssize_t expimp_store(struct kobject *kobj, struct kobj_attribute *attr, + char *buf, size_t count) +{ + int ret; + + ret = sscanf(buf, "%du", &pid_stat); + if (ret < 1) { + pr_err("failed to read anything from input %d", ret); + return 0; + } else + return pid_stat; +} + +static struct kobj_attribute vchan_attribute = __ATTR(vchan_stat, 0660, + vchan_show, + vchan_store); + +static struct kobj_attribute ctx_attribute = __ATTR(context_stat, 0660, + ctx_show, + ctx_store); + +static struct kobj_attribute expimp_attribute = __ATTR(pid_stat, 0660, + expimp_show, + expimp_store); + +int hab_stat_init_sub(struct hab_driver *driver) +{ + int result; + + hab_kobject = kobject_create_and_add("hab", kernel_kobj); + if (!hab_kobject) + return -ENOMEM; + + result = sysfs_create_file(hab_kobject, &vchan_attribute.attr); + if (result) + pr_debug("cannot add vchan in /sys/kernel/hab %d\n", result); + + result = sysfs_create_file(hab_kobject, &ctx_attribute.attr); + if (result) + pr_debug("cannot add ctx in /sys/kernel/hab %d\n", result); + + result = sysfs_create_file(hab_kobject, &expimp_attribute.attr); + if (result) + pr_debug("cannot add expimp in /sys/kernel/hab %d\n", result); + + return result; +} + +int hab_stat_deinit_sub(struct hab_driver *driver) +{ + sysfs_remove_file(hab_kobject, &vchan_attribute.attr); + sysfs_remove_file(hab_kobject, &ctx_attribute.attr); + sysfs_remove_file(hab_kobject, &expimp_attribute.attr); + kobject_put(hab_kobject); + + return 0; +} diff --git a/drivers/soc/qcom/hab/qvm_comm.c b/drivers/soc/qcom/hab/qvm_comm.c index 04381232b26a..cce24d72c28e 100644 --- a/drivers/soc/qcom/hab/qvm_comm.c +++ b/drivers/soc/qcom/hab/qvm_comm.c @@ -13,7 +13,7 @@ #include "hab.h" #include "hab_qvm.h" -static inline void habhyp_notify(void *commdev) +inline void habhyp_notify(void *commdev) { struct qvm_channel *dev = (struct qvm_channel *)commdev; @@ -70,9 +70,14 @@ int physical_channel_send(struct physical_channel *pchan, struct habmm_xing_vm_stat *pstat = (struct habmm_xing_vm_stat *)payload; - do_gettimeofday(&tv); - pstat->tx_sec = tv.tv_sec; - pstat->tx_usec = tv.tv_usec; + if (pstat) { + do_gettimeofday(&tv); + pstat->tx_sec = tv.tv_sec; + pstat->tx_usec = tv.tv_usec; + } else { + spin_unlock_bh(&dev->io_lock); + return -EINVAL; + } } if (sizebytes) { From 3674a33d5de3d453795941e2d3db9248298d6cfb Mon Sep 17 00:00:00 2001 From: Ajay Agarwal Date: Tue, 31 Jul 2018 12:40:10 +0530 Subject: [PATCH 152/159] usb: dwc3-msm: Queue resume_work unconditionally on pm_resume Currently on pm_resume, the driver queues resume_work only if vbus_active is true or id_state is false. So when the system is suspended with host mode cable connected and the cable is disconnected, the port still remains in host mode. Fix this by unconditionally queueing resume_work from pm_resume and adding required pm_relax in B_IDLE branch of sm_work. Also create a freezable workqueue for sm_work so that the work items do not race with pm_resume of child devices. Change-Id: I9b79ddcc44c87111fc85086038361d9140be2af5 Signed-off-by: Ajay Agarwal --- drivers/usb/dwc3/dwc3-msm.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index de6bb295bf67..95e27e097b6b 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -188,6 +188,7 @@ struct dwc3_msm { struct work_struct restart_usb_work; bool in_restart; struct workqueue_struct *dwc3_wq; + struct workqueue_struct *sm_usb_wq; struct delayed_work sm_work; unsigned long inputs; unsigned max_power; @@ -1597,7 +1598,7 @@ static int msm_dwc3_usbdev_notify(struct notifier_block *self, } mdwc->hc_died = true; - schedule_delayed_work(&mdwc->sm_work, 0); + queue_delayed_work(mdwc->sm_usb_wq, &mdwc->sm_work, 0); return 0; } @@ -2358,7 +2359,7 @@ static void dwc3_ext_event_notify(struct dwc3_msm *mdwc) } pm_stay_awake(mdwc->dev); - schedule_delayed_work(&mdwc->sm_work, 0); + queue_delayed_work(mdwc->sm_usb_wq, &mdwc->sm_work, 0); } static void dwc3_resume_work(struct work_struct *w) @@ -2944,6 +2945,12 @@ static int dwc3_msm_probe(struct platform_device *pdev) INIT_DELAYED_WORK(&mdwc->perf_vote_work, msm_dwc3_perf_vote_work); INIT_DELAYED_WORK(&mdwc->sdp_check, check_for_sdp_connection); + mdwc->sm_usb_wq = create_freezable_workqueue("k_sm_usb"); + if (!mdwc->sm_usb_wq) { + pr_err("%s: Failed to create workqueue for sm_usb\n", __func__); + return -ENOMEM; + } + mdwc->dwc3_wq = alloc_ordered_workqueue("dwc3_wq", 0); if (!mdwc->dwc3_wq) { pr_err("%s: Unable to create workqueue dwc3_wq\n", __func__); @@ -3248,7 +3255,7 @@ static int dwc3_msm_probe(struct platform_device *pdev) dwc3_msm_id_notifier(&mdwc->id_nb, true, mdwc->extcon_id); else if (!pval.intval) { /* USB cable is not connected */ - schedule_delayed_work(&mdwc->sm_work, 0); + queue_delayed_work(mdwc->sm_usb_wq, &mdwc->sm_work, 0); } else { if (pval.intval > 0) dev_info(mdwc->dev, "charger detection in progress\n"); @@ -3868,6 +3875,7 @@ static void dwc3_otg_sm_work(struct work_struct *w) break; } else { dwc3_msm_gadget_vbus_draw(mdwc, 0); + pm_relax(mdwc->dev); dev_dbg(mdwc->dev, "Cable disconnected\n"); } break; @@ -3981,7 +3989,7 @@ static void dwc3_otg_sm_work(struct work_struct *w) } if (work) - schedule_delayed_work(&mdwc->sm_work, delay); + queue_delayed_work(mdwc->sm_usb_wq, &mdwc->sm_work, delay); ret: return; @@ -4086,9 +4094,7 @@ static int dwc3_msm_pm_resume(struct device *dev) if (mdwc->no_wakeup_src_in_hostmode && !test_bit(ID, &mdwc->inputs)) dwc3_msm_resume(mdwc); - /* kick in otg state machine */ - if (mdwc->vbus_active || !mdwc->id_state) - queue_work(mdwc->dwc3_wq, &mdwc->resume_work); + queue_work(mdwc->dwc3_wq, &mdwc->resume_work); return 0; } From 53324ddb60cb797ce6cbed007b12cc06865de5a3 Mon Sep 17 00:00:00 2001 From: Ajay Agarwal Date: Wed, 25 Jul 2018 12:25:16 +0530 Subject: [PATCH 153/159] usb: phy-msm-ssusb-qmp: Make vls_clamp_reg as optional Currently the SSUSB QMP PHY driver mandates that vls_clamp_reg be passed from the DTSI. But this register cannot be accessed on a platform on which Linux is a guest OS. This can lead to errors when trying to enable autonomous mode. Work around this situation by making the vls_clamp_reg property as optional. Change-Id: Idb103d9b7bda717a5f12689951a7452c46aa76dd Signed-off-by: Ajay Agarwal --- .../devicetree/bindings/usb/msm-phy.txt | 4 +-- drivers/usb/phy/phy-msm-ssusb-qmp.c | 25 +++++++++++-------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/Documentation/devicetree/bindings/usb/msm-phy.txt b/Documentation/devicetree/bindings/usb/msm-phy.txt index 9b40d44d363b..3793be6511b7 100644 --- a/Documentation/devicetree/bindings/usb/msm-phy.txt +++ b/Documentation/devicetree/bindings/usb/msm-phy.txt @@ -95,8 +95,6 @@ Required properties: - reg: Address and length of the register set for the device Required regs are: "qmp_phy_base" : QMP PHY Base register set. - - "vls_clamp_reg" : top-level CSR register to be written to enable phy vls - clamp which allows phy to detect autonomous mode. - -supply: phandle to the regulator device tree node Required "supply-name" examples are: "vdd" : vdd supply for SSPHY digital circuit operation @@ -125,6 +123,8 @@ Required properties: Optional properties: - reg: Additional register set of address and length to control QMP PHY are: + "vls_clamp_reg" : top-level CSR register to be written to enable phy vls + clamp which allows phy to detect autonomous mode. "tcsr_usb3_dp_phymode" : top-level CSR register to be written to select super speed usb qmp phy. - clocks: a list of phandles to the PHY clocks. Use as per diff --git a/drivers/usb/phy/phy-msm-ssusb-qmp.c b/drivers/usb/phy/phy-msm-ssusb-qmp.c index 3ffb20c4a207..d1b6f1df860d 100644 --- a/drivers/usb/phy/phy-msm-ssusb-qmp.c +++ b/drivers/usb/phy/phy-msm-ssusb-qmp.c @@ -473,11 +473,13 @@ static int msm_ssphy_qmp_set_suspend(struct usb_phy *uphy, int suspend) } if (suspend) { - if (phy->cable_connected) - msm_ssusb_qmp_enable_autonomous(phy, 1); - else + if (phy->cable_connected) { + if (phy->vls_clamp_reg) + msm_ssusb_qmp_enable_autonomous(phy, 1); + } else { writel_relaxed(0x00, phy->base + phy->phy_reg[USB3_PHY_POWER_DOWN_CONTROL]); + } /* Make sure above write completed with PHY */ wmb(); @@ -509,7 +511,8 @@ static int msm_ssphy_qmp_set_suspend(struct usb_phy *uphy, int suspend) writel_relaxed(0x01, phy->base + phy->phy_reg[USB3_PHY_POWER_DOWN_CONTROL]); } else { - msm_ssusb_qmp_enable_autonomous(phy, 0); + if (phy->vls_clamp_reg) + msm_ssusb_qmp_enable_autonomous(phy, 0); } /* Make sure that above write completed with PHY */ @@ -648,13 +651,13 @@ static int msm_ssphy_qmp_probe(struct platform_device *pdev) res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vls_clamp_reg"); if (!res) { - dev_err(dev, "failed getting vls_clamp_reg\n"); - return -ENODEV; - } - phy->vls_clamp_reg = devm_ioremap_resource(dev, res); - if (IS_ERR(phy->vls_clamp_reg)) { - dev_err(dev, "couldn't find vls_clamp_reg address.\n"); - return PTR_ERR(phy->vls_clamp_reg); + dev_dbg(dev, "vls_clamp_reg not passed\n"); + } else { + phy->vls_clamp_reg = devm_ioremap_resource(dev, res); + if (IS_ERR(phy->vls_clamp_reg)) { + dev_err(dev, "couldn't find vls_clamp_reg address.\n"); + return PTR_ERR(phy->vls_clamp_reg); + } } res = platform_get_resource_byname(pdev, IORESOURCE_MEM, From f15aace0bfd38e29769d4250679a41d00dbcfc28 Mon Sep 17 00:00:00 2001 From: Sunil Khatri Date: Mon, 30 Jul 2018 15:18:17 +0530 Subject: [PATCH 154/159] msm: kgsl: Fix the missing IBs from the snapshot We missed updating index for internal IBs like setstate or power-on fixup. The index value was never updated after that, so all the IBs after that index were never parsed, and are missing from the snapshot. Change-Id: I61db75f33630db322fe5ee1adce9f120987d32ee Signed-off-by: Sunil Khatri --- drivers/gpu/msm/adreno_snapshot.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/msm/adreno_snapshot.c b/drivers/gpu/msm/adreno_snapshot.c index 711d7ba83e61..6392ec1f069b 100644 --- a/drivers/gpu/msm/adreno_snapshot.c +++ b/drivers/gpu/msm/adreno_snapshot.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -400,6 +400,8 @@ static void snapshot_rb_ibs(struct kgsl_device *device, ibsize = rbptr[index + 3]; } + index = (index + 1) % KGSL_RB_DWORDS; + /* Don't parse known global IBs */ if (iommu_is_setstate_addr(device, ibaddr, ibsize)) continue; @@ -410,9 +412,8 @@ static void snapshot_rb_ibs(struct kgsl_device *device, parse_ib(device, snapshot, snapshot->process, ibaddr, ibsize); - } - - index = (index + 1) % KGSL_RB_DWORDS; + } else + index = (index + 1) % KGSL_RB_DWORDS; } } From 26eff67153cf547158db519817fb61dfd6e9da30 Mon Sep 17 00:00:00 2001 From: Frank Liu Date: Fri, 27 Jul 2018 14:32:53 +0800 Subject: [PATCH 155/159] cnss2: Add support for PCIe WLAN IPA uc SMMU feature To add support for PCIe WLAN IPA uc SMMU feature, prvoide related platform api for wlan driver to get the smmu map handle and do the mapping. Change-Id: I672b1a48879ada65b3ddb3f16c4bd787dc1b70a6 Signed-off-by: Frank Liu --- drivers/net/wireless/cnss2/pci.c | 66 ++++++++++++++++++++++++++++++++ drivers/net/wireless/cnss2/pci.h | 2 + include/net/cnss2.h | 3 ++ 3 files changed, 71 insertions(+) diff --git a/drivers/net/wireless/cnss2/pci.c b/drivers/net/wireless/cnss2/pci.c index ff053b098c22..0f4ef3712dd7 100644 --- a/drivers/net/wireless/cnss2/pci.c +++ b/drivers/net/wireless/cnss2/pci.c @@ -1414,6 +1414,61 @@ void cnss_pci_fw_boot_timeout_hdlr(struct cnss_pci_data *pci_priv) CNSS_REASON_TIMEOUT); } +struct dma_iommu_mapping *cnss_smmu_get_mapping(struct device *dev) +{ + struct cnss_pci_data *pci_priv = cnss_get_pci_priv(to_pci_dev(dev)); + + if (!pci_priv) + return NULL; + + return pci_priv->smmu_mapping; +} +EXPORT_SYMBOL(cnss_smmu_get_mapping); + +int cnss_smmu_map(struct device *dev, + phys_addr_t paddr, uint32_t *iova_addr, size_t size) +{ + struct cnss_pci_data *pci_priv = cnss_get_pci_priv(to_pci_dev(dev)); + unsigned long iova; + size_t len; + int ret = 0; + + if (!pci_priv) + return -ENODEV; + + if (!iova_addr) { + cnss_pr_err("iova_addr is NULL, paddr %pa, size %zu\n", + &paddr, size); + return -EINVAL; + } + + len = roundup(size + paddr - rounddown(paddr, PAGE_SIZE), PAGE_SIZE); + iova = roundup(pci_priv->smmu_iova_ipa_start, PAGE_SIZE); + + if (iova >= + (pci_priv->smmu_iova_ipa_start + pci_priv->smmu_iova_ipa_len)) { + cnss_pr_err("No IOVA space to map, iova %lx, smmu_iova_ipa_start %pad, smmu_iova_ipa_len %zu\n", + iova, + &pci_priv->smmu_iova_ipa_start, + pci_priv->smmu_iova_ipa_len); + return -ENOMEM; + } + + ret = iommu_map(pci_priv->smmu_mapping->domain, iova, + rounddown(paddr, PAGE_SIZE), len, + IOMMU_READ | IOMMU_WRITE); + if (ret) { + cnss_pr_err("PA to IOVA mapping failed, ret %d\n", ret); + return ret; + } + + pci_priv->smmu_iova_ipa_start = iova + len; + *iova_addr = (uint32_t)(iova + paddr - rounddown(paddr, PAGE_SIZE)); + + return 0; +} +EXPORT_SYMBOL(cnss_smmu_map); + int cnss_get_soc_info(struct device *dev, struct cnss_soc_info *info) { int ret = 0; @@ -2129,6 +2184,17 @@ static int cnss_pci_probe(struct pci_dev *pci_dev, &pci_priv->smmu_iova_start, pci_priv->smmu_iova_len); + res = platform_get_resource_byname(plat_priv->plat_dev, + IORESOURCE_MEM, + "smmu_iova_ipa"); + if (res) { + pci_priv->smmu_iova_ipa_start = res->start; + pci_priv->smmu_iova_ipa_len = resource_size(res); + cnss_pr_dbg("smmu_iova_ipa_start: %pa, smmu_iova_ipa_len: %zu\n", + &pci_priv->smmu_iova_ipa_start, + pci_priv->smmu_iova_ipa_len); + } + ret = cnss_pci_init_smmu(pci_priv); if (ret) { cnss_pr_err("Failed to init SMMU, err = %d\n", ret); diff --git a/drivers/net/wireless/cnss2/pci.h b/drivers/net/wireless/cnss2/pci.h index 182355ae7577..e47f14e8a325 100644 --- a/drivers/net/wireless/cnss2/pci.h +++ b/drivers/net/wireless/cnss2/pci.h @@ -73,6 +73,8 @@ struct cnss_pci_data { struct dma_iommu_mapping *smmu_mapping; dma_addr_t smmu_iova_start; size_t smmu_iova_len; + dma_addr_t smmu_iova_ipa_start; + size_t smmu_iova_ipa_len; void __iomem *bar; struct cnss_msi_config *msi_config; u32 msi_ep_base_data; diff --git a/include/net/cnss2.h b/include/net/cnss2.h index f80d87533a99..53f73d436752 100644 --- a/include/net/cnss2.h +++ b/include/net/cnss2.h @@ -171,6 +171,9 @@ extern int cnss_get_fw_files_for_target(struct device *dev, u32 target_type, u32 target_version); extern int cnss_get_platform_cap(struct device *dev, struct cnss_platform_cap *cap); +extern struct dma_iommu_mapping *cnss_smmu_get_mapping(struct device *dev); +extern int cnss_smmu_map(struct device *dev, + phys_addr_t paddr, uint32_t *iova_addr, size_t size); extern int cnss_get_soc_info(struct device *dev, struct cnss_soc_info *info); extern int cnss_request_bus_bandwidth(struct device *dev, int bandwidth); extern int cnss_power_up(struct device *dev); From d0be0bc1353b84a97b21053d4ebd805efd22de96 Mon Sep 17 00:00:00 2001 From: Manoj Prabhu B Date: Wed, 25 Jul 2018 15:06:11 +0530 Subject: [PATCH 156/159] diag: Modify md_info and diag client map synchronization Extend the scope of protection to md_info till queueing the write to sdcard. Patch adds protection to diag client map synchronizing access by various clients. CRs-Fixed: 2282558 Change-Id: If076af2d09180a282a9077b4ebcda0184e9f67b5 Signed-off-by: Manoj Prabhu B --- drivers/char/diag/diag_memorydevice.c | 2 ++ drivers/char/diag/diagfwd_peripheral.c | 20 ++++++++++++-------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/drivers/char/diag/diag_memorydevice.c b/drivers/char/diag/diag_memorydevice.c index aa45c2e7ec7b..befc015cd7d5 100644 --- a/drivers/char/diag/diag_memorydevice.c +++ b/drivers/char/diag/diag_memorydevice.c @@ -206,6 +206,7 @@ int diag_md_write(int id, unsigned char *buf, int len, int ctx) } found = 0; + mutex_lock(&driver->diagchar_mutex); for (i = 0; i < driver->num_clients && !found; i++) { if ((driver->client_map[i].pid != pid) || (driver->client_map[i].pid == 0)) @@ -219,6 +220,7 @@ int diag_md_write(int id, unsigned char *buf, int len, int ctx) pr_debug("diag: wake up logging process\n"); wake_up_interruptible(&driver->wait_q); } + mutex_unlock(&driver->diagchar_mutex); if (!found) return -EINVAL; diff --git a/drivers/char/diag/diagfwd_peripheral.c b/drivers/char/diag/diagfwd_peripheral.c index bfdce051d405..6c16d80192c6 100644 --- a/drivers/char/diag/diagfwd_peripheral.c +++ b/drivers/char/diag/diagfwd_peripheral.c @@ -357,6 +357,8 @@ static void diagfwd_data_process_done(struct diagfwd_info *fwd_info, goto end; } } + mutex_unlock(&fwd_info->data_mutex); + mutex_unlock(&driver->hdlc_disable_mutex); if (write_len > 0) { err = diag_mux_write(DIAG_LOCAL_PROC, write_buf, write_len, @@ -364,18 +366,18 @@ static void diagfwd_data_process_done(struct diagfwd_info *fwd_info, if (err) { pr_err_ratelimited("diag: In %s, unable to write to mux error: %d\n", __func__, err); - goto end; + goto end_write; } } - mutex_unlock(&fwd_info->data_mutex); - mutex_unlock(&driver->hdlc_disable_mutex); + diagfwd_queue_read(fwd_info); return; end: - diag_ws_release(); mutex_unlock(&fwd_info->data_mutex); mutex_unlock(&driver->hdlc_disable_mutex); +end_write: + diag_ws_release(); if (buf) { DIAG_LOG(DIAG_DEBUG_PERIPHERALS, "Marking buffer as free p: %d, t: %d, buf_num: %d\n", @@ -694,24 +696,26 @@ static void diagfwd_data_read_done(struct diagfwd_info *fwd_info, } } + mutex_unlock(&fwd_info->data_mutex); + mutex_unlock(&driver->hdlc_disable_mutex); + if (write_len > 0) { err = diag_mux_write(DIAG_LOCAL_PROC, write_buf, write_len, temp_buf->ctxt); if (err) { pr_err_ratelimited("diag: In %s, unable to write to mux error: %d\n", __func__, err); - goto end; + goto end_write; } } - mutex_unlock(&fwd_info->data_mutex); - mutex_unlock(&driver->hdlc_disable_mutex); diagfwd_queue_read(fwd_info); return; end: - diag_ws_release(); mutex_unlock(&fwd_info->data_mutex); mutex_unlock(&driver->hdlc_disable_mutex); +end_write: + diag_ws_release(); if (temp_buf) { DIAG_LOG(DIAG_DEBUG_PERIPHERALS, "Marking buffer as free p: %d, t: %d, buf_num: %d\n", From aef2c9f15c4ee1fab0fce00bf2be236d9051206c Mon Sep 17 00:00:00 2001 From: Skylar Chang Date: Sat, 7 Apr 2018 16:42:36 -0700 Subject: [PATCH 157/159] msm: ipa: support ipacm cleanup Support header/filter, routing rules cleanup when user-space module crashed like ipacm and also cached the wlan client connect messages for ipacm to query. Change-Id: Ib09cbe0e9114aa5a5673898ff796de7e7944af35 Acked-by: Pooja Kumari Signed-off-by: Mohammed Javid Signed-off-by: Skylar Chang --- drivers/platform/msm/ipa/ipa_api.c | 248 ++++++++----- drivers/platform/msm/ipa/ipa_api.h | 17 +- drivers/platform/msm/ipa/ipa_common_i.h | 4 +- drivers/platform/msm/ipa/ipa_v2/ipa.c | 65 +++- drivers/platform/msm/ipa/ipa_v2/ipa_flt.c | 83 +++-- drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c | 128 ++++--- drivers/platform/msm/ipa/ipa_v2/ipa_i.h | 32 +- drivers/platform/msm/ipa/ipa_v2/ipa_intf.c | 179 +++++++++- drivers/platform/msm/ipa/ipa_v2/ipa_nat.c | 6 - .../platform/msm/ipa/ipa_v2/ipa_qmi_service.c | 10 +- drivers/platform/msm/ipa/ipa_v2/ipa_rt.c | 102 ++++-- drivers/platform/msm/ipa/ipa_v2/ipa_utils.c | 5 +- drivers/platform/msm/ipa/ipa_v3/ipa.c | 332 ++++++++++-------- drivers/platform/msm/ipa/ipa_v3/ipa_flt.c | 73 ++-- drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c | 127 +++++-- drivers/platform/msm/ipa/ipa_v3/ipa_i.h | 35 +- drivers/platform/msm/ipa/ipa_v3/ipa_intf.c | 179 +++++++++- .../platform/msm/ipa/ipa_v3/ipa_qmi_service.c | 16 + drivers/platform/msm/ipa/ipa_v3/ipa_rt.c | 108 ++++-- drivers/platform/msm/ipa/ipa_v3/ipa_utils.c | 5 +- include/linux/ipa.h | 44 ++- include/uapi/linux/msm_ipa.h | 8 +- 22 files changed, 1329 insertions(+), 477 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_api.c b/drivers/platform/msm/ipa/ipa_api.c index 719a1ec5360f..66dd016e2132 100644 --- a/drivers/platform/msm/ipa/ipa_api.c +++ b/drivers/platform/msm/ipa/ipa_api.c @@ -340,13 +340,13 @@ int ipa_disconnect(u32 clnt_hdl) EXPORT_SYMBOL(ipa_disconnect); /** -* ipa_clear_endpoint_delay() - Clear ep_delay. -* @clnt_hdl: [in] IPA client handle -* -* Returns: 0 on success, negative on failure -* -* Note: Should not be called from atomic context -*/ + * ipa_clear_endpoint_delay() - Clear ep_delay. + * @clnt_hdl: [in] IPA client handle + * + * Returns: 0 on success, negative on failure + * + * Note: Should not be called from atomic context + */ int ipa_clear_endpoint_delay(u32 clnt_hdl) { int ret; @@ -358,13 +358,13 @@ int ipa_clear_endpoint_delay(u32 clnt_hdl) EXPORT_SYMBOL(ipa_clear_endpoint_delay); /** -* ipa_reset_endpoint() - reset an endpoint from BAM perspective -* @clnt_hdl: [in] IPA client handle -* -* Returns: 0 on success, negative on failure -* -* Note: Should not be called from atomic context -*/ + * ipa_reset_endpoint() - reset an endpoint from BAM perspective + * @clnt_hdl: [in] IPA client handle + * + * Returns: 0 on success, negative on failure + * + * Note: Should not be called from atomic context + */ int ipa_reset_endpoint(u32 clnt_hdl) { int ret; @@ -376,13 +376,13 @@ int ipa_reset_endpoint(u32 clnt_hdl) EXPORT_SYMBOL(ipa_reset_endpoint); /** -* ipa_disable_endpoint() - Disable an endpoint from IPA perspective -* @clnt_hdl: [in] IPA client handle -* -* Returns: 0 on success, negative on failure -* -* Note: Should not be called from atomic context -*/ + * ipa_disable_endpoint() - Disable an endpoint from IPA perspective + * @clnt_hdl: [in] IPA client handle + * + * Returns: 0 on success, negative on failure + * + * Note: Should not be called from atomic context + */ int ipa_disable_endpoint(u32 clnt_hdl) { int ret; @@ -676,8 +676,28 @@ int ipa_add_hdr(struct ipa_ioc_add_hdr *hdrs) EXPORT_SYMBOL(ipa_add_hdr); /** - * ipa_del_hdr() - Remove the specified headers from SW and optionally commit them - * to IPA HW + * ipa_add_hdr_usr() - add the specified headers to SW and optionally + * commit them to IPA HW + * @hdrs: [inout] set of headers to add + * @user_only: [in] indicate rules installed by userspace + * + * Returns: 0 on success, negative on failure + * + * Note: Should not be called from atomic context + */ +int ipa_add_hdr_usr(struct ipa_ioc_add_hdr *hdrs, bool user_only) +{ + int ret; + + IPA_API_DISPATCH_RETURN(ipa_add_hdr_usr, hdrs, user_only); + + return ret; +} +EXPORT_SYMBOL(ipa_add_hdr_usr); + +/** + * ipa_del_hdr() - Remove the specified headers from SW and optionally + * commit them to IPA HW * @hdls: [inout] set of headers to delete * * Returns: 0 on success, negative on failure @@ -715,15 +735,16 @@ EXPORT_SYMBOL(ipa_commit_hdr); * ipa_reset_hdr() - reset the current header table in SW (does not commit to * HW) * + * @user_only: [in] indicate delete rules installed by userspace * Returns: 0 on success, negative on failure * * Note: Should not be called from atomic context */ -int ipa_reset_hdr(void) +int ipa_reset_hdr(bool user_only) { int ret; - IPA_API_DISPATCH_RETURN(ipa_reset_hdr); + IPA_API_DISPATCH_RETURN(ipa_reset_hdr, user_only); return ret; } @@ -793,16 +814,18 @@ EXPORT_SYMBOL(ipa_copy_hdr); * ipa_add_hdr_proc_ctx() - add the specified headers to SW * and optionally commit them to IPA HW * @proc_ctxs: [inout] set of processing context headers to add + * @user_only: [in] indicate rules installed by userspace * * Returns: 0 on success, negative on failure * * Note: Should not be called from atomic context */ -int ipa_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs) +int ipa_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs, + bool user_only) { int ret; - IPA_API_DISPATCH_RETURN(ipa_add_hdr_proc_ctx, proc_ctxs); + IPA_API_DISPATCH_RETURN(ipa_add_hdr_proc_ctx, proc_ctxs, user_only); return ret; } @@ -847,6 +870,26 @@ int ipa_add_rt_rule(struct ipa_ioc_add_rt_rule *rules) } EXPORT_SYMBOL(ipa_add_rt_rule); +/** + * ipa_add_rt_rule_usr() - Add the specified routing rules to SW and optionally + * commit to IPA HW + * @rules: [inout] set of routing rules to add + * @user_only: [in] indicate rules installed by userspace + * + * Returns: 0 on success, negative on failure + * + * Note: Should not be called from atomic context + */ +int ipa_add_rt_rule_usr(struct ipa_ioc_add_rt_rule *rules, bool user_only) +{ + int ret; + + IPA_API_DISPATCH_RETURN(ipa_add_rt_rule_usr, rules, user_only); + + return ret; +} +EXPORT_SYMBOL(ipa_add_rt_rule_usr); + /** * ipa_del_rt_rule() - Remove the specified routing rules to SW and optionally * commit to IPA HW @@ -889,16 +932,17 @@ EXPORT_SYMBOL(ipa_commit_rt); * ipa_reset_rt() - reset the current SW routing table of specified type * (does not commit to HW) * @ip: The family of routing tables + * @user_only: [in] indicate delete rules installed by userspace * * Returns: 0 on success, negative on failure * * Note: Should not be called from atomic context */ -int ipa_reset_rt(enum ipa_ip_type ip) +int ipa_reset_rt(enum ipa_ip_type ip, bool user_only) { int ret; - IPA_API_DISPATCH_RETURN(ipa_reset_rt, ip); + IPA_API_DISPATCH_RETURN(ipa_reset_rt, ip, user_only); return ret; } @@ -981,6 +1025,7 @@ EXPORT_SYMBOL(ipa_mdfy_rt_rule); /** * ipa_add_flt_rule() - Add the specified filtering rules to SW and optionally * commit to IPA HW + * @rules: [inout] set of filtering rules to add * * Returns: 0 on success, negative on failure * @@ -996,6 +1041,26 @@ int ipa_add_flt_rule(struct ipa_ioc_add_flt_rule *rules) } EXPORT_SYMBOL(ipa_add_flt_rule); +/** + * ipa_add_flt_rule_usr() - Add the specified filtering rules to + * SW and optionally commit to IPA HW + * @rules: [inout] set of filtering rules to add + * @user_only: [in] indicate rules installed by userspace + * + * Returns: 0 on success, negative on failure + * + * Note: Should not be called from atomic context + */ +int ipa_add_flt_rule_usr(struct ipa_ioc_add_flt_rule *rules, bool user_only) +{ + int ret; + + IPA_API_DISPATCH_RETURN(ipa_add_flt_rule_usr, rules, user_only); + + return ret; +} +EXPORT_SYMBOL(ipa_add_flt_rule_usr); + /** * ipa_del_flt_rule() - Remove the specified filtering rules from SW and * optionally commit to IPA HW @@ -1054,17 +1119,18 @@ EXPORT_SYMBOL(ipa_commit_flt); /** * ipa_reset_flt() - Reset the current SW filtering table of specified type * (does not commit to HW) - * @ip: [in] the family of routing tables + * @ip: [in] the family of routing tables + * @user_only: [in] indicate delete rules installed by userspace * * Returns: 0 on success, negative on failure * * Note: Should not be called from atomic context */ -int ipa_reset_flt(enum ipa_ip_type ip) +int ipa_reset_flt(enum ipa_ip_type ip, bool user_only) { int ret; - IPA_API_DISPATCH_RETURN(ipa_reset_flt, ip); + IPA_API_DISPATCH_RETURN(ipa_reset_flt, ip, user_only); return ret; } @@ -1710,20 +1776,20 @@ int ipa_uc_dereg_rdyCB(void) EXPORT_SYMBOL(ipa_uc_dereg_rdyCB); /** -* teth_bridge_init() - Initialize the Tethering bridge driver -* @params - in/out params for USB initialization API (please look at struct -* definition for more info) -* -* USB driver gets a pointer to a callback function (usb_notify_cb) and an -* associated data. USB driver installs this callback function in the call to -* ipa_connect(). -* -* Builds IPA resource manager dependency graph. -* -* Return codes: 0: success, -* -EINVAL - Bad parameter -* Other negative value - Failure -*/ + * teth_bridge_init() - Initialize the Tethering bridge driver + * @params - in/out params for USB initialization API (please look at struct + * definition for more info) + * + * USB driver gets a pointer to a callback function (usb_notify_cb) and an + * associated data. USB driver installs this callback function in the call to + * ipa_connect(). + * + * Builds IPA resource manager dependency graph. + * + * Return codes: 0: success, + * -EINVAL - Bad parameter + * Other negative value - Failure + */ int teth_bridge_init(struct teth_bridge_init_params *params) { int ret; @@ -1735,8 +1801,8 @@ int teth_bridge_init(struct teth_bridge_init_params *params) EXPORT_SYMBOL(teth_bridge_init); /** -* teth_bridge_disconnect() - Disconnect tethering bridge module -*/ + * teth_bridge_disconnect() - Disconnect tethering bridge module + */ int teth_bridge_disconnect(enum ipa_client_type client) { int ret; @@ -1748,14 +1814,14 @@ int teth_bridge_disconnect(enum ipa_client_type client) EXPORT_SYMBOL(teth_bridge_disconnect); /** -* teth_bridge_connect() - Connect bridge for a tethered Rmnet / MBIM call -* @connect_params: Connection info -* -* Return codes: 0: success -* -EINVAL: invalid parameters -* -EPERM: Operation not permitted as the bridge is already -* connected -*/ + * teth_bridge_connect() - Connect bridge for a tethered Rmnet / MBIM call + * @connect_params: Connection info + * + * Return codes: 0: success + * -EINVAL: invalid parameters + * -EPERM: Operation not permitted as the bridge is already + * connected + */ int teth_bridge_connect(struct teth_bridge_connect_params *connect_params) { int ret; @@ -2232,16 +2298,16 @@ int ipa_write_qmap_id(struct ipa_ioc_write_qmapid *param_in) EXPORT_SYMBOL(ipa_write_qmap_id); /** -* ipa_add_interrupt_handler() - Adds handler to an interrupt type -* @interrupt: Interrupt type -* @handler: The handler to be added -* @deferred_flag: whether the handler processing should be deferred in -* a workqueue -* @private_data: the client's private data -* -* Adds handler to an interrupt type and enable the specific bit -* in IRQ_EN register, associated interrupt in IRQ_STTS register will be enabled -*/ + * ipa_add_interrupt_handler() - Adds handler to an interrupt type + * @interrupt: Interrupt type + * @handler: The handler to be added + * @deferred_flag: whether the handler processing should be deferred in + * a workqueue + * @private_data: the client's private data + * + * Adds handler to an interrupt type and enable the specific bit + * in IRQ_EN register, associated interrupt in IRQ_STTS register will be enabled + */ int ipa_add_interrupt_handler(enum ipa_irq_type interrupt, ipa_irq_handler_t handler, bool deferred_flag, @@ -2257,11 +2323,11 @@ int ipa_add_interrupt_handler(enum ipa_irq_type interrupt, EXPORT_SYMBOL(ipa_add_interrupt_handler); /** -* ipa_remove_interrupt_handler() - Removes handler to an interrupt type -* @interrupt: Interrupt type -* -* Removes the handler and disable the specific bit in IRQ_EN register -*/ + * ipa_remove_interrupt_handler() - Removes handler to an interrupt type + * @interrupt: Interrupt type + * + * Removes the handler and disable the specific bit in IRQ_EN register + */ int ipa_remove_interrupt_handler(enum ipa_irq_type interrupt) { int ret; @@ -2273,12 +2339,12 @@ int ipa_remove_interrupt_handler(enum ipa_irq_type interrupt) EXPORT_SYMBOL(ipa_remove_interrupt_handler); /** -* ipa_restore_suspend_handler() - restores the original suspend IRQ handler -* as it was registered in the IPA init sequence. -* Return codes: -* 0: success -* -EPERM: failed to remove current handler or failed to add original handler -* */ + * ipa_restore_suspend_handler() - restores the original suspend IRQ handler + * as it was registered in the IPA init sequence. + * Return codes: + * 0: success + * -EPERM: failed to remove current handler or failed to add original handler + */ int ipa_restore_suspend_handler(void) { int ret; @@ -2621,10 +2687,10 @@ static int ipa_generic_plat_drv_probe(struct platform_device *pdev_p) { int result; - /* - * IPA probe function can be called for multiple times as the same probe - * function handles multiple compatibilities - */ +/** + * IPA probe function can be called for multiple times as the same probe + * function handles multiple compatibilities + */ pr_debug("ipa: IPA driver probing started for %s\n", pdev_p->dev.of_node->name); @@ -2747,7 +2813,7 @@ EXPORT_SYMBOL(ipa_register_ipa_ready_cb); * * Return codes: * None -*/ + */ void ipa_inc_client_enable_clks(struct ipa_active_client_logging_info *id) { IPA_API_DISPATCH(ipa_inc_client_enable_clks, id); @@ -2763,7 +2829,7 @@ EXPORT_SYMBOL(ipa_inc_client_enable_clks); * * Return codes: * None -*/ + */ void ipa_dec_client_disable_clks(struct ipa_active_client_logging_info *id) { IPA_API_DISPATCH(ipa_dec_client_disable_clks, id); @@ -2793,14 +2859,14 @@ int ipa_inc_client_enable_clks_no_block( EXPORT_SYMBOL(ipa_inc_client_enable_clks_no_block); /** -* ipa_suspend_resource_no_block() - suspend client endpoints related to the -* IPA_RM resource and decrement active clients counter. This function is -* guaranteed to avoid sleeping. -* -* @resource: [IN] IPA Resource Manager resource -* -* Return codes: 0 on success, negative on failure. -*/ + * ipa_suspend_resource_no_block() - suspend client endpoints related to the + * IPA_RM resource and decrement active clients counter. This function is + * guaranteed to avoid sleeping. + * + * @resource: [IN] IPA Resource Manager resource + * + * Return codes: 0 on success, negative on failure. + */ int ipa_suspend_resource_no_block(enum ipa_rm_resource_name resource) { int ret; diff --git a/drivers/platform/msm/ipa/ipa_api.h b/drivers/platform/msm/ipa/ipa_api.h index 33e0f469d0d2..72db83c6e69d 100644 --- a/drivers/platform/msm/ipa/ipa_api.h +++ b/drivers/platform/msm/ipa/ipa_api.h @@ -69,11 +69,13 @@ struct ipa_api_controller { int (*ipa_add_hdr)(struct ipa_ioc_add_hdr *hdrs); + int (*ipa_add_hdr_usr)(struct ipa_ioc_add_hdr *hdrs, bool user_only); + int (*ipa_del_hdr)(struct ipa_ioc_del_hdr *hdls); int (*ipa_commit_hdr)(void); - int (*ipa_reset_hdr)(void); + int (*ipa_reset_hdr)(bool user_only); int (*ipa_get_hdr)(struct ipa_ioc_get_hdr *lookup); @@ -81,17 +83,21 @@ struct ipa_api_controller { int (*ipa_copy_hdr)(struct ipa_ioc_copy_hdr *copy); - int (*ipa_add_hdr_proc_ctx)(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs); + int (*ipa_add_hdr_proc_ctx)(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs, + bool user_only); int (*ipa_del_hdr_proc_ctx)(struct ipa_ioc_del_hdr_proc_ctx *hdls); int (*ipa_add_rt_rule)(struct ipa_ioc_add_rt_rule *rules); + int (*ipa_add_rt_rule_usr)(struct ipa_ioc_add_rt_rule *rules, + bool user_only); + int (*ipa_del_rt_rule)(struct ipa_ioc_del_rt_rule *hdls); int (*ipa_commit_rt)(enum ipa_ip_type ip); - int (*ipa_reset_rt)(enum ipa_ip_type ip); + int (*ipa_reset_rt)(enum ipa_ip_type ip, bool user_only); int (*ipa_get_rt_tbl)(struct ipa_ioc_get_rt_tbl *lookup); @@ -103,13 +109,16 @@ struct ipa_api_controller { int (*ipa_add_flt_rule)(struct ipa_ioc_add_flt_rule *rules); + int (*ipa_add_flt_rule_usr)(struct ipa_ioc_add_flt_rule *rules, + bool user_only); + int (*ipa_del_flt_rule)(struct ipa_ioc_del_flt_rule *hdls); int (*ipa_mdfy_flt_rule)(struct ipa_ioc_mdfy_flt_rule *rules); int (*ipa_commit_flt)(enum ipa_ip_type ip); - int (*ipa_reset_flt)(enum ipa_ip_type ip); + int (*ipa_reset_flt)(enum ipa_ip_type ip, bool user_only); int (*allocate_nat_device)(struct ipa_ioc_nat_alloc_mem *mem); diff --git a/drivers/platform/msm/ipa/ipa_common_i.h b/drivers/platform/msm/ipa/ipa_common_i.h index 911db0b19079..00c3515bae30 100644 --- a/drivers/platform/msm/ipa/ipa_common_i.h +++ b/drivers/platform/msm/ipa/ipa_common_i.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -296,11 +296,13 @@ struct ipa_mhi_connect_params_internal { * @link: entry's link in global header offset entries list * @offset: the offset * @bin: bin + * @ipacm_installed: indicate if installed by ipacm */ struct ipa_hdr_offset_entry { struct list_head link; u32 offset; u32 bin; + bool ipacm_installed; }; extern const char *ipa_clients_strings[]; diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa.c b/drivers/platform/msm/ipa/ipa_v2/ipa.c index bf46ea860fef..d9f8912c0514 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa.c @@ -279,6 +279,28 @@ int ipa2_active_clients_log_print_table(char *buf, int size) return cnt; } + +static int ipa2_clean_modem_rule(void) +{ + struct ipa_install_fltr_rule_req_msg_v01 *req; + int val = 0; + + req = kzalloc( + sizeof(struct ipa_install_fltr_rule_req_msg_v01), + GFP_KERNEL); + if (!req) { + IPAERR("mem allocated failed!\n"); + return -ENOMEM; + } + req->filter_spec_list_valid = false; + req->filter_spec_list_len = 0; + req->source_pipe_index_valid = 0; + val = qmi_filter_request_send(req); + kfree(req); + + return val; +} + static int ipa2_active_clients_panic_notifier(struct notifier_block *this, unsigned long event, void *ptr) { @@ -531,7 +553,8 @@ static void ipa_wan_msg_free_cb(void *buff, u32 len, u32 type) kfree(buff); } -static int ipa_send_wan_msg(unsigned long usr_param, uint8_t msg_type, bool is_cache) +static int ipa_send_wan_msg(unsigned long usr_param, uint8_t msg_type, + bool is_cache) { int retval; struct ipa_wan_msg *wan_msg; @@ -716,7 +739,8 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) retval = -EFAULT; break; } - if (ipa2_add_hdr((struct ipa_ioc_add_hdr *)param)) { + if (ipa2_add_hdr_usr((struct ipa_ioc_add_hdr *)param, + true)) { retval = -EFAULT; break; } @@ -796,7 +820,8 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) retval = -EFAULT; break; } - if (ipa2_add_rt_rule((struct ipa_ioc_add_rt_rule *)param)) { + if (ipa2_add_rt_rule_usr((struct ipa_ioc_add_rt_rule *)param, + true)) { retval = -EFAULT; break; } @@ -915,7 +940,8 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) retval = -EFAULT; break; } - if (ipa2_add_flt_rule((struct ipa_ioc_add_flt_rule *)param)) { + if (ipa2_add_flt_rule_usr((struct ipa_ioc_add_flt_rule *)param, + true)) { retval = -EFAULT; break; } @@ -1009,19 +1035,19 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) retval = ipa2_commit_hdr(); break; case IPA_IOC_RESET_HDR: - retval = ipa2_reset_hdr(); + retval = ipa2_reset_hdr(false); break; case IPA_IOC_COMMIT_RT: retval = ipa2_commit_rt(arg); break; case IPA_IOC_RESET_RT: - retval = ipa2_reset_rt(arg); + retval = ipa2_reset_rt(arg, false); break; case IPA_IOC_COMMIT_FLT: retval = ipa2_commit_flt(arg); break; case IPA_IOC_RESET_FLT: - retval = ipa2_reset_flt(arg); + retval = ipa2_reset_flt(arg, false); break; case IPA_IOC_GET_RT_TBL: if (copy_from_user(header, (u8 *)arg, @@ -1401,7 +1427,7 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) break; } if (ipa2_add_hdr_proc_ctx( - (struct ipa_ioc_add_hdr_proc_ctx *)param)) { + (struct ipa_ioc_add_hdr_proc_ctx *)param, true)) { retval = -EFAULT; break; } @@ -1465,7 +1491,22 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) } break; - default: /* redundant, as cmd was checked against MAXNR */ + case IPA_IOC_CLEANUP: + /*Route and filter rules will also be clean*/ + IPADBG("Got IPA_IOC_CLEANUP\n"); + retval = ipa2_reset_hdr(true); + memset(&nat_del, 0, sizeof(nat_del)); + nat_del.table_index = 0; + retval = ipa2_nat_del_cmd(&nat_del); + retval = ipa2_clean_modem_rule(); + break; + + case IPA_IOC_QUERY_WLAN_CLIENT: + IPADBG("Got IPA_IOC_QUERY_WLAN_CLIENT\n"); + retval = ipa2_resend_wlan_msg(); + break; + + default: IPA_ACTIVE_CLIENTS_DEC_SIMPLE(); return -ENOTTY; } @@ -1478,7 +1519,7 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) /** * ipa_setup_dflt_rt_tables() - Setup default routing tables -* + * Return codes: * 0: success * -ENOMEM: failed to allocate memory @@ -4301,6 +4342,10 @@ static int ipa_init(const struct ipa_plat_drv_res *resource_p, init_waitqueue_head(&ipa_ctx->msg_waitq); mutex_init(&ipa_ctx->msg_lock); + /* store wlan client-connect-msg-list */ + INIT_LIST_HEAD(&ipa_ctx->msg_wlan_client_list); + mutex_init(&ipa_ctx->msg_wlan_client_lock); + mutex_init(&ipa_ctx->lock); mutex_init(&ipa_ctx->nat_mem.lock); mutex_init(&ipa_ctx->ipa_cne_evt_lock); diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_flt.c b/drivers/platform/msm/ipa/ipa_v2/ipa_flt.c index 834f028d3e48..6392c379b026 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_flt.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_flt.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1008,7 +1008,7 @@ fail_desc: static int __ipa_add_flt_rule(struct ipa_flt_tbl *tbl, enum ipa_ip_type ip, const struct ipa_flt_rule *rule, u8 add_rear, - u32 *rule_hdl) + u32 *rule_hdl, bool user) { struct ipa_flt_entry *entry; struct ipa_rt_tbl *rt_tbl = NULL; @@ -1076,6 +1076,7 @@ static int __ipa_add_flt_rule(struct ipa_flt_tbl *tbl, enum ipa_ip_type ip, } *rule_hdl = id; entry->id = id; + entry->ipacm_installed = user; IPADBG_LOW("add flt rule rule_cnt=%d\n", tbl->rule_cnt); return 0; @@ -1198,12 +1199,12 @@ static int __ipa_add_global_flt_rule(enum ipa_ip_type ip, tbl = &ipa_ctx->glob_flt_tbl[ip]; IPADBG_LOW("add global flt rule ip=%d\n", ip); - return __ipa_add_flt_rule(tbl, ip, rule, add_rear, rule_hdl); + return __ipa_add_flt_rule(tbl, ip, rule, add_rear, rule_hdl, false); } static int __ipa_add_ep_flt_rule(enum ipa_ip_type ip, enum ipa_client_type ep, const struct ipa_flt_rule *rule, u8 add_rear, - u32 *rule_hdl) + u32 *rule_hdl, bool user) { struct ipa_flt_tbl *tbl; int ipa_ep_idx; @@ -1225,18 +1226,34 @@ static int __ipa_add_ep_flt_rule(enum ipa_ip_type ip, enum ipa_client_type ep, tbl = &ipa_ctx->flt_tbl[ipa_ep_idx][ip]; IPADBG_LOW("add ep flt rule ip=%d ep=%d\n", ip, ep); - return __ipa_add_flt_rule(tbl, ip, rule, add_rear, rule_hdl); + return __ipa_add_flt_rule(tbl, ip, rule, add_rear, rule_hdl, user); } /** * ipa2_add_flt_rule() - Add the specified filtering rules to SW and optionally * commit to IPA HW + * @rules: [inout] set of filtering rules to add * * Returns: 0 on success, negative on failure * * Note: Should not be called from atomic context */ int ipa2_add_flt_rule(struct ipa_ioc_add_flt_rule *rules) +{ + return ipa2_add_flt_rule_usr(rules, false); +} + +/** + * ipa2_add_flt_rule_usr() - Add the specified filtering rules + * to SW and optionally commit to IPA HW + * @rules: [inout] set of filtering rules to add + * @user_only: [in] indicate rules installed by userspace + * + * Returns: 0 on success, negative on failure + * + * Note: Should not be called from atomic context + */ +int ipa2_add_flt_rule_usr(struct ipa_ioc_add_flt_rule *rules, bool user_only) { int i; int result; @@ -1259,7 +1276,8 @@ int ipa2_add_flt_rule(struct ipa_ioc_add_flt_rule *rules) result = __ipa_add_ep_flt_rule(rules->ip, rules->ep, &rules->rules[i].rule, rules->rules[i].at_rear, - &rules->rules[i].flt_rule_hdl); + &rules->rules[i].flt_rule_hdl, + user_only); if (result) { IPAERR_RL("failed to add flt rule %d\n", i); rules->rules[i].status = IPA_FLT_STATUS_OF_ADD_FAILED; @@ -1396,13 +1414,14 @@ bail: /** * ipa2_reset_flt() - Reset the current SW filtering table of specified type * (does not commit to HW) - * @ip: [in] the family of routing tables + * @ip: [in] the family of routing tables + * @user_only: [in] indicate rules deleted by userspace * * Returns: 0 on success, negative on failure * * Note: Should not be called from atomic context */ -int ipa2_reset_flt(enum ipa_ip_type ip) +int ipa2_reset_flt(enum ipa_ip_type ip, bool user_only) { struct ipa_flt_tbl *tbl; struct ipa_flt_entry *entry; @@ -1435,16 +1454,19 @@ int ipa2_reset_flt(enum ipa_ip_type ip) IPA_INVALID_L4_PROTOCOL)) continue; - list_del(&entry->link); - entry->tbl->rule_cnt--; - if (entry->rt_tbl) - entry->rt_tbl->ref_cnt--; - entry->cookie = 0; - id = entry->id; - kmem_cache_free(ipa_ctx->flt_rule_cache, entry); + if (!user_only || + entry->ipacm_installed) { + list_del(&entry->link); + entry->tbl->rule_cnt--; + if (entry->rt_tbl) + entry->rt_tbl->ref_cnt--; + entry->cookie = 0; + id = entry->id; + kmem_cache_free(ipa_ctx->flt_rule_cache, entry); - /* remove the handle from the database */ - ipa_id_remove(id); + /* remove the handle from the database */ + ipa_id_remove(id); + } } for (i = 0; i < ipa_ctx->ipa_num_pipes; i++) { @@ -1456,16 +1478,21 @@ int ipa2_reset_flt(enum ipa_ip_type ip) mutex_unlock(&ipa_ctx->lock); return -EFAULT; } - list_del(&entry->link); - entry->tbl->rule_cnt--; - if (entry->rt_tbl) - entry->rt_tbl->ref_cnt--; - entry->cookie = 0; - id = entry->id; - kmem_cache_free(ipa_ctx->flt_rule_cache, entry); - /* remove the handle from the database */ - ipa_id_remove(id); + if (!user_only || + entry->ipacm_installed) { + list_del(&entry->link); + entry->tbl->rule_cnt--; + if (entry->rt_tbl) + entry->rt_tbl->ref_cnt--; + entry->cookie = 0; + id = entry->id; + kmem_cache_free(ipa_ctx->flt_rule_cache, + entry); + + /* remove the handle from the database */ + ipa_id_remove(id); + } } } mutex_unlock(&ipa_ctx->lock); @@ -1485,14 +1512,14 @@ void ipa_install_dflt_flt_rules(u32 ipa_ep_idx) tbl = &ipa_ctx->flt_tbl[ipa_ep_idx][IPA_IP_v4]; rule.action = IPA_PASS_TO_EXCEPTION; __ipa_add_flt_rule(tbl, IPA_IP_v4, &rule, true, - &ep->dflt_flt4_rule_hdl); + &ep->dflt_flt4_rule_hdl, false); ipa_ctx->ctrl->ipa_commit_flt(IPA_IP_v4); tbl->sticky_rear = true; tbl = &ipa_ctx->flt_tbl[ipa_ep_idx][IPA_IP_v6]; rule.action = IPA_PASS_TO_EXCEPTION; __ipa_add_flt_rule(tbl, IPA_IP_v6, &rule, true, - &ep->dflt_flt6_rule_hdl); + &ep->dflt_flt6_rule_hdl, false); ipa_ctx->ctrl->ipa_commit_flt(IPA_IP_v6); tbl->sticky_rear = true; mutex_unlock(&ipa_ctx->lock); diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c b/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c index fbbb3f20b571..15c8f923d4f4 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -543,7 +543,7 @@ int __ipa_commit_hdr_v2_6L(void) } static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, - bool add_ref_hdr) + bool add_ref_hdr, bool user_only) { struct ipa_hdr_entry *hdr_entry; struct ipa_hdr_proc_ctx_entry *entry; @@ -581,6 +581,7 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, if (add_ref_hdr) hdr_entry->ref_cnt++; entry->cookie = IPA_PROC_HDR_COOKIE; + entry->ipacm_installed = user_only; needed_len = (proc_ctx->type == IPA_HDR_PROC_NONE) ? sizeof(struct ipa_hdr_proc_ctx_add_hdr_seq) : @@ -619,6 +620,7 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, */ offset->offset = htbl->end; offset->bin = bin; + offset->ipacm_installed = user_only; htbl->end += ipa_hdr_proc_ctx_bin_sz[bin]; list_add(&offset->link, &htbl->head_offset_list[bin]); @@ -627,6 +629,7 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, offset = list_first_entry(&htbl->head_free_offset_list[bin], struct ipa_hdr_proc_ctx_offset_entry, link); + offset->ipacm_installed = user_only; list_move(&offset->link, &htbl->head_offset_list[bin]); } @@ -664,7 +667,7 @@ bad_len: } -static int __ipa_add_hdr(struct ipa_hdr_add *hdr) +static int __ipa_add_hdr(struct ipa_hdr_add *hdr, bool user) { struct ipa_hdr_entry *entry; struct ipa_hdr_offset_entry *offset = NULL; @@ -700,6 +703,7 @@ static int __ipa_add_hdr(struct ipa_hdr_add *hdr) entry->is_eth2_ofst_valid = hdr->is_eth2_ofst_valid; entry->eth2_ofst = hdr->eth2_ofst; entry->cookie = IPA_HDR_COOKIE; + entry->ipacm_installed = user; if (hdr->hdr_len <= ipa_hdr_bin_sz[IPA_HDR_BIN0]) bin = IPA_HDR_BIN0; @@ -760,6 +764,7 @@ static int __ipa_add_hdr(struct ipa_hdr_add *hdr) list_add(&offset->link, &htbl->head_offset_list[bin]); entry->offset_entry = offset; + offset->ipacm_installed = user; } } else { entry->is_hdr_proc_ctx = false; @@ -769,6 +774,7 @@ static int __ipa_add_hdr(struct ipa_hdr_add *hdr) struct ipa_hdr_offset_entry, link); list_move(&offset->link, &htbl->head_offset_list[bin]); entry->offset_entry = offset; + offset->ipacm_installed = user; } list_add(&entry->link, &htbl->head_hdr_entry_list); @@ -800,7 +806,7 @@ static int __ipa_add_hdr(struct ipa_hdr_add *hdr) IPADBG("adding processing context for header %s\n", hdr->name); proc_ctx.type = IPA_HDR_PROC_NONE; proc_ctx.hdr_hdl = id; - if (__ipa_add_hdr_proc_ctx(&proc_ctx, false)) { + if (__ipa_add_hdr_proc_ctx(&proc_ctx, false, user)) { IPAERR("failed to add hdr proc ctx\n"); goto fail_add_proc_ctx; } @@ -959,6 +965,21 @@ int __ipa_del_hdr(u32 hdr_hdl, bool by_user) * Note: Should not be called from atomic context */ int ipa2_add_hdr(struct ipa_ioc_add_hdr *hdrs) +{ + return ipa2_add_hdr_usr(hdrs, false); +} + +/** + * ipa2_add_hdr_usr() - add the specified headers to SW + * and optionally commit them to IPA HW + * @hdrs: [inout] set of headers to add + * @user_only: [in] indicate installed from user + * + * Returns: 0 on success, negative on failure + * + * Note: Should not be called from atomic context + */ +int ipa2_add_hdr_usr(struct ipa_ioc_add_hdr *hdrs, bool user_only) { int i; int result = -EFAULT; @@ -977,7 +998,7 @@ int ipa2_add_hdr(struct ipa_ioc_add_hdr *hdrs) IPADBG("adding %d headers to IPA driver internal data struct\n", hdrs->num_hdrs); for (i = 0; i < hdrs->num_hdrs; i++) { - if (__ipa_add_hdr(&hdrs->hdr[i])) { + if (__ipa_add_hdr(&hdrs->hdr[i], user_only)) { IPAERR_RL("failed to add hdr %d\n", i); hdrs->hdr[i].status = -1; } else { @@ -997,7 +1018,6 @@ bail: mutex_unlock(&ipa_ctx->lock); return result; } - /** * ipa2_del_hdr_by_user() - Remove the specified headers * from SW and optionally commit them to IPA HW @@ -1063,12 +1083,14 @@ int ipa2_del_hdr(struct ipa_ioc_del_hdr *hdls) * ipa2_add_hdr_proc_ctx() - add the specified headers to SW * and optionally commit them to IPA HW * @proc_ctxs: [inout] set of processing context headers to add + * @user_only: [in] indicate installed by user-space module * * Returns: 0 on success, negative on failure * * Note: Should not be called from atomic context */ -int ipa2_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs) +int ipa2_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs, + bool user_only) { int i; int result = -EFAULT; @@ -1089,7 +1111,8 @@ int ipa2_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs) IPADBG("adding %d header processing contextes to IPA driver\n", proc_ctxs->num_proc_ctxs); for (i = 0; i < proc_ctxs->num_proc_ctxs; i++) { - if (__ipa_add_hdr_proc_ctx(&proc_ctxs->proc_ctx[i], true)) { + if (__ipa_add_hdr_proc_ctx(&proc_ctxs->proc_ctx[i], + true, user_only)) { IPAERR_RL("failed to add hdr pric ctx %d\n", i); proc_ctxs->proc_ctx[i].status = -1; } else { @@ -1211,11 +1234,12 @@ bail: * ipa2_reset_hdr() - reset the current header table in SW (does not commit to * HW) * + * @user_only: [in] indicate delete rules installed by userspace * Returns: 0 on success, negative on failure * * Note: Should not be called from atomic context */ -int ipa2_reset_hdr(void) +int ipa2_reset_hdr(bool user_only) { struct ipa_hdr_entry *entry; struct ipa_hdr_entry *next; @@ -1231,9 +1255,9 @@ int ipa2_reset_hdr(void) * issue a reset on the routing module since routing rules point to * header table entries */ - if (ipa2_reset_rt(IPA_IP_v4)) + if (ipa2_reset_rt(IPA_IP_v4, user_only)) IPAERR("fail to reset v4 rt\n"); - if (ipa2_reset_rt(IPA_IP_v6)) + if (ipa2_reset_rt(IPA_IP_v6, user_only)) IPAERR("fail to reset v4 rt\n"); mutex_lock(&ipa_ctx->lock); @@ -1262,21 +1286,23 @@ int ipa2_reset_hdr(void) WARN_ON(1); return -EFAULT; } - if (entry->is_hdr_proc_ctx) { - dma_unmap_single(ipa_ctx->pdev, - entry->phys_base, - entry->hdr_len, - DMA_TO_DEVICE); - entry->proc_ctx = NULL; + + if (!user_only || entry->ipacm_installed) { + if (entry->is_hdr_proc_ctx) { + dma_unmap_single(ipa_ctx->pdev, + entry->phys_base, + entry->hdr_len, + DMA_TO_DEVICE); + entry->proc_ctx = NULL; + } + list_del(&entry->link); + entry->ref_cnt = 0; + entry->cookie = 0; + + /* remove the handle from the database */ + ipa_id_remove(entry->id); + kmem_cache_free(ipa_ctx->hdr_cache, entry); } - list_del(&entry->link); - entry->ref_cnt = 0; - entry->cookie = 0; - - /* remove the handle from the database */ - ipa_id_remove(entry->id); - kmem_cache_free(ipa_ctx->hdr_cache, entry); - } for (i = 0; i < IPA_HDR_BIN_MAX; i++) { list_for_each_entry_safe(off_entry, off_next, @@ -1290,14 +1316,23 @@ int ipa2_reset_hdr(void) if (off_entry->offset == 0) continue; - list_del(&off_entry->link); - kmem_cache_free(ipa_ctx->hdr_offset_cache, off_entry); + if (!user_only || + off_entry->ipacm_installed) { + list_del(&off_entry->link); + kmem_cache_free(ipa_ctx->hdr_offset_cache, + off_entry); + } } list_for_each_entry_safe(off_entry, off_next, &ipa_ctx->hdr_tbl.head_free_offset_list[i], link) { - list_del(&off_entry->link); - kmem_cache_free(ipa_ctx->hdr_offset_cache, off_entry); + + if (!user_only || + off_entry->ipacm_installed) { + list_del(&off_entry->link); + kmem_cache_free(ipa_ctx->hdr_offset_cache, + off_entry); + } } } /* there is one header of size 8 */ @@ -1316,30 +1351,43 @@ int ipa2_reset_hdr(void) WARN_ON(1); return -EFAULT; } - list_del(&ctx_entry->link); - ctx_entry->ref_cnt = 0; - ctx_entry->cookie = 0; - /* remove the handle from the database */ - ipa_id_remove(ctx_entry->id); - kmem_cache_free(ipa_ctx->hdr_proc_ctx_cache, ctx_entry); + if (!user_only || + ctx_entry->ipacm_installed) { + list_del(&ctx_entry->link); + ctx_entry->ref_cnt = 0; + ctx_entry->cookie = 0; + /* remove the handle from the database */ + ipa_id_remove(ctx_entry->id); + kmem_cache_free(ipa_ctx->hdr_proc_ctx_cache, + ctx_entry); + } } for (i = 0; i < IPA_HDR_PROC_CTX_BIN_MAX; i++) { list_for_each_entry_safe(ctx_off_entry, ctx_off_next, &ipa_ctx->hdr_proc_ctx_tbl.head_offset_list[i], link) { - list_del(&ctx_off_entry->link); - kmem_cache_free(ipa_ctx->hdr_proc_ctx_offset_cache, + if (!user_only || + ctx_off_entry->ipacm_installed) { + list_del(&ctx_off_entry->link); + kmem_cache_free( + ipa_ctx->hdr_proc_ctx_offset_cache, ctx_off_entry); + } } list_for_each_entry_safe(ctx_off_entry, ctx_off_next, &ipa_ctx->hdr_proc_ctx_tbl.head_free_offset_list[i], link) { - list_del(&ctx_off_entry->link); - kmem_cache_free(ipa_ctx->hdr_proc_ctx_offset_cache, - ctx_off_entry); + + if (!user_only || + ctx_off_entry->ipacm_installed) { + list_del(&ctx_off_entry->link); + kmem_cache_free( + ipa_ctx->hdr_proc_ctx_offset_cache, + ctx_off_entry); + } } } ipa_ctx->hdr_proc_ctx_tbl.end = 0; diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h index 1986dc2af097..1d34564664bc 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h @@ -242,6 +242,8 @@ struct ipa_smmu_cb_ctx { * @tbl: filter table * @rt_tbl: routing table * @hw_len: entry's size + * @id: rule handle - globally unique + * @ipacm_installed: indicate if installed by ipacm */ struct ipa_flt_entry { struct list_head link; @@ -251,6 +253,7 @@ struct ipa_flt_entry { struct ipa_rt_tbl *rt_tbl; u32 hw_len; int id; + bool ipacm_installed; }; /** @@ -305,6 +308,7 @@ struct ipa_rt_tbl { * @is_eth2_ofst_valid: is eth2_ofst field valid? * @eth2_ofst: offset to start of Ethernet-II/802.3 header * @user_deleted: is the header deleted by the user? + * @ipacm_installed: indicate if installed by ipacm */ struct ipa_hdr_entry { struct list_head link; @@ -323,6 +327,7 @@ struct ipa_hdr_entry { u8 is_eth2_ofst_valid; u16 eth2_ofst; bool user_deleted; + bool ipacm_installed; }; /** @@ -346,11 +351,13 @@ struct ipa_hdr_tbl { * @link: entry's link in global processing context header offset entries list * @offset: the offset * @bin: bin + * @ipacm_installed: indicate if installed by ipacm */ struct ipa_hdr_proc_ctx_offset_entry { struct list_head link; u32 offset; u32 bin; + bool ipacm_installed; }; /** @@ -387,6 +394,7 @@ struct ipa_hdr_proc_ctx_add_hdr_cmd_seq { * @ref_cnt: reference counter of routing table * @id: processing context header entry id * @user_deleted: is the hdr processing context deleted by the user? + * @ipacm_installed: indicate if installed by ipacm */ struct ipa_hdr_proc_ctx_entry { struct list_head link; @@ -397,6 +405,7 @@ struct ipa_hdr_proc_ctx_entry { u32 ref_cnt; int id; bool user_deleted; + bool ipacm_installed; }; /** @@ -446,6 +455,8 @@ struct ipa_flt_tbl { * @hdr: header table * @proc_ctx: processing context table * @hw_len: the length of the table + * @id: rule handle - globaly unique + * @ipacm_installed: indicate if installed by ipacm */ struct ipa_rt_entry { struct list_head link; @@ -456,6 +467,7 @@ struct ipa_rt_entry { struct ipa_hdr_proc_ctx_entry *proc_ctx; u32 hw_len; int id; + bool ipacm_installed; }; /** @@ -1151,6 +1163,8 @@ struct ipa_context { struct list_head msg_list; struct list_head pull_msg_list; struct mutex msg_lock; + struct list_head msg_wlan_client_list; + struct mutex msg_wlan_client_lock; wait_queue_head_t msg_waitq; enum ipa_hw_type ipa_hw_type; enum ipa_hw_mode ipa_hw_mode; @@ -1441,13 +1455,15 @@ int ipa2_cfg_ep_ctrl(u32 clnt_hdl, const struct ipa_ep_cfg_ctrl *ep_ctrl); */ int ipa2_add_hdr(struct ipa_ioc_add_hdr *hdrs); +int ipa2_add_hdr_usr(struct ipa_ioc_add_hdr *hdrs, bool by_user); + int ipa2_del_hdr(struct ipa_ioc_del_hdr *hdls); int ipa2_del_hdr_by_user(struct ipa_ioc_del_hdr *hdls, bool by_user); int ipa2_commit_hdr(void); -int ipa2_reset_hdr(void); +int ipa2_reset_hdr(bool user_only); int ipa2_get_hdr(struct ipa_ioc_get_hdr *lookup); @@ -1458,7 +1474,8 @@ int ipa2_copy_hdr(struct ipa_ioc_copy_hdr *copy); /* * Header Processing Context */ -int ipa2_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs); +int ipa2_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs, + bool user_only); int ipa2_del_hdr_proc_ctx(struct ipa_ioc_del_hdr_proc_ctx *hdls); @@ -1470,11 +1487,14 @@ int ipa2_del_hdr_proc_ctx_by_user(struct ipa_ioc_del_hdr_proc_ctx *hdls, */ int ipa2_add_rt_rule(struct ipa_ioc_add_rt_rule *rules); +int ipa2_add_rt_rule_usr(struct ipa_ioc_add_rt_rule *rules, + bool user_only); + int ipa2_del_rt_rule(struct ipa_ioc_del_rt_rule *hdls); int ipa2_commit_rt(enum ipa_ip_type ip); -int ipa2_reset_rt(enum ipa_ip_type ip); +int ipa2_reset_rt(enum ipa_ip_type ip, bool user_only); int ipa2_get_rt_tbl(struct ipa_ioc_get_rt_tbl *lookup); @@ -1489,13 +1509,16 @@ int ipa2_mdfy_rt_rule(struct ipa_ioc_mdfy_rt_rule *rules); */ int ipa2_add_flt_rule(struct ipa_ioc_add_flt_rule *rules); +int ipa2_add_flt_rule_usr(struct ipa_ioc_add_flt_rule *rules, + bool user_only); + int ipa2_del_flt_rule(struct ipa_ioc_del_flt_rule *hdls); int ipa2_mdfy_flt_rule(struct ipa_ioc_mdfy_flt_rule *rules); int ipa2_commit_flt(enum ipa_ip_type ip); -int ipa2_reset_flt(enum ipa_ip_type ip); +int ipa2_reset_flt(enum ipa_ip_type ip, bool user_only); /* * NAT @@ -1513,6 +1536,7 @@ int ipa2_nat_del_cmd(struct ipa_ioc_v4_nat_del *del); */ int ipa2_send_msg(struct ipa_msg_meta *meta, void *buff, ipa_msg_free_fn callback); +int ipa2_resend_wlan_msg(void); int ipa2_register_pull_msg(struct ipa_msg_meta *meta, ipa_msg_pull_fn callback); int ipa2_deregister_pull_msg(struct ipa_msg_meta *meta); diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_intf.c b/drivers/platform/msm/ipa/ipa_v2/ipa_intf.c index 9c4fc0ce8cc1..da56a2ed1b8d 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_intf.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_intf.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -13,6 +13,7 @@ #include #include #include "ipa_i.h" +#include struct ipa_intf { char name[IPA_RESOURCE_NAME_MAX]; @@ -377,6 +378,108 @@ static void ipa2_send_msg_free(void *buff, u32 len, u32 type) kfree(buff); } +static int wlan_msg_process(struct ipa_msg_meta *meta, void *buff) +{ + struct ipa_push_msg *msg_dup; + struct ipa_wlan_msg_ex *event_ex_cur_con = NULL; + struct ipa_wlan_msg_ex *event_ex_list = NULL; + struct ipa_wlan_msg *event_ex_cur_discon = NULL; + void *data_dup = NULL; + struct ipa_push_msg *entry; + struct ipa_push_msg *next; + int cnt = 0, total = 0, max = 0; + uint8_t mac[IPA_MAC_ADDR_SIZE]; + uint8_t mac2[IPA_MAC_ADDR_SIZE]; + + if (meta->msg_type == WLAN_CLIENT_CONNECT_EX) { + /* debug print */ + event_ex_cur_con = buff; + for (cnt = 0; cnt < event_ex_cur_con->num_of_attribs; cnt++) { + if (event_ex_cur_con->attribs[cnt].attrib_type == + WLAN_HDR_ATTRIB_MAC_ADDR) { + IPADBG("%02x:%02x:%02x:%02x:%02x:%02x,(%d)\n", + event_ex_cur_con->attribs[cnt].u.mac_addr[0], + event_ex_cur_con->attribs[cnt].u.mac_addr[1], + event_ex_cur_con->attribs[cnt].u.mac_addr[2], + event_ex_cur_con->attribs[cnt].u.mac_addr[3], + event_ex_cur_con->attribs[cnt].u.mac_addr[4], + event_ex_cur_con->attribs[cnt].u.mac_addr[5], + meta->msg_type); + } + } + + mutex_lock(&ipa_ctx->msg_wlan_client_lock); + msg_dup = kzalloc(sizeof(struct ipa_push_msg), GFP_KERNEL); + if (msg_dup == NULL) { + IPAERR("fail to alloc ipa_msg container\n"); + return -ENOMEM; + } + msg_dup->meta = *meta; + if (meta->msg_len > 0 && buff) { + data_dup = kmalloc(meta->msg_len, GFP_KERNEL); + if (data_dup == NULL) { + IPAERR("fail to alloc data_dup container\n"); + kfree(msg_dup); + return -ENOMEM; + } + memcpy(data_dup, buff, meta->msg_len); + msg_dup->buff = data_dup; + msg_dup->callback = ipa2_send_msg_free; + } + list_add_tail(&msg_dup->link, &ipa_ctx->msg_wlan_client_list); + mutex_unlock(&ipa_ctx->msg_wlan_client_lock); + } + + /* remove the cache */ + if (meta->msg_type == WLAN_CLIENT_DISCONNECT) { + /* debug print */ + event_ex_cur_discon = buff; + IPADBG("Mac %02x:%02x:%02x:%02x:%02x:%02x,msg %d\n", + event_ex_cur_discon->mac_addr[0], + event_ex_cur_discon->mac_addr[1], + event_ex_cur_discon->mac_addr[2], + event_ex_cur_discon->mac_addr[3], + event_ex_cur_discon->mac_addr[4], + event_ex_cur_discon->mac_addr[5], + meta->msg_type); + memcpy(mac2, + event_ex_cur_discon->mac_addr, + sizeof(mac2)); + + mutex_lock(&ipa_ctx->msg_wlan_client_lock); + list_for_each_entry_safe(entry, next, + &ipa_ctx->msg_wlan_client_list, + link) { + event_ex_list = entry->buff; + max = event_ex_list->num_of_attribs; + for (cnt = 0; cnt < max; cnt++) { + memcpy(mac, + event_ex_list->attribs[cnt].u.mac_addr, + sizeof(mac)); + if (event_ex_list->attribs[cnt].attrib_type == + WLAN_HDR_ATTRIB_MAC_ADDR) { + pr_debug("%02x:%02x:%02x:%02x:%02x:%02x\n", + mac[0], mac[1], mac[2], + mac[3], mac[4], mac[5]); + + /* compare to delete one*/ + if (memcmp(mac2, + mac, + sizeof(mac)) == 0) { + IPADBG("clean %d\n", total); + list_del(&entry->link); + kfree(entry); + break; + } + } + } + total++; + } + mutex_unlock(&ipa_ctx->msg_wlan_client_lock); + } + return 0; +} + /** * ipa2_send_msg() - Send "message" from kernel client to IPA driver * @meta: [in] message meta-data @@ -404,7 +507,7 @@ int ipa2_send_msg(struct ipa_msg_meta *meta, void *buff, } if (meta == NULL || (buff == NULL && callback != NULL) || - (buff != NULL && callback == NULL)) { + (buff != NULL && callback == NULL) || buff == NULL) { IPAERR_RL("invalid param meta=%p buff=%p, callback=%p\n", meta, buff, callback); return -EINVAL; @@ -436,6 +539,11 @@ int ipa2_send_msg(struct ipa_msg_meta *meta, void *buff, mutex_lock(&ipa_ctx->msg_lock); list_add_tail(&msg->link, &ipa_ctx->msg_list); + /* support for softap client event cache */ + if (wlan_msg_process(meta, buff)) + IPAERR("wlan_msg_process failed\n"); + + /* unlock only after process */ mutex_unlock(&ipa_ctx->msg_lock); IPA_STATS_INC_CNT(ipa_ctx->stats.msg_w[meta->msg_type]); @@ -446,6 +554,73 @@ int ipa2_send_msg(struct ipa_msg_meta *meta, void *buff, return 0; } +/** + * ipa2_resend_wlan_msg() - Resend cached "message" to IPACM + * + * resend wlan client connect events to user-space + * + * Returns: 0 on success, negative on failure + * + * Note: Should not be called from atomic context + */ +int ipa2_resend_wlan_msg(void) +{ + struct ipa_wlan_msg_ex *event_ex_list = NULL; + struct ipa_push_msg *entry; + struct ipa_push_msg *next; + int cnt = 0, total = 0; + struct ipa_push_msg *msg; + void *data = NULL; + + IPADBG("\n"); + + mutex_lock(&ipa_ctx->msg_wlan_client_lock); + list_for_each_entry_safe(entry, next, &ipa_ctx->msg_wlan_client_list, + link) { + + event_ex_list = entry->buff; + for (cnt = 0; cnt < event_ex_list->num_of_attribs; cnt++) { + if (event_ex_list->attribs[cnt].attrib_type == + WLAN_HDR_ATTRIB_MAC_ADDR) { + IPADBG("%d-Mac %02x:%02x:%02x:%02x:%02x:%02x\n", + total, + event_ex_list->attribs[cnt].u.mac_addr[0], + event_ex_list->attribs[cnt].u.mac_addr[1], + event_ex_list->attribs[cnt].u.mac_addr[2], + event_ex_list->attribs[cnt].u.mac_addr[3], + event_ex_list->attribs[cnt].u.mac_addr[4], + event_ex_list->attribs[cnt].u.mac_addr[5]); + } + } + + msg = kzalloc(sizeof(struct ipa_push_msg), GFP_KERNEL); + if (msg == NULL) { + IPAERR("fail to alloc ipa_msg container\n"); + mutex_unlock(&ipa_ctx->msg_wlan_client_lock); + return -ENOMEM; + } + msg->meta = entry->meta; + data = kmalloc(entry->meta.msg_len, GFP_KERNEL); + if (data == NULL) { + IPAERR("fail to alloc data container\n"); + kfree(msg); + mutex_unlock(&ipa_ctx->msg_wlan_client_lock); + return -ENOMEM; + } + memcpy(data, entry->buff, entry->meta.msg_len); + msg->buff = data; + msg->callback = ipa2_send_msg_free; + mutex_lock(&ipa_ctx->msg_lock); + list_add_tail(&msg->link, &ipa_ctx->msg_list); + mutex_unlock(&ipa_ctx->msg_lock); + wake_up(&ipa_ctx->msg_waitq); + + total++; + } + mutex_unlock(&ipa_ctx->msg_wlan_client_lock); + return 0; +} + /** * ipa2_register_pull_msg() - register pull message type * @meta: [in] message meta-data diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_nat.c b/drivers/platform/msm/ipa/ipa_v2/ipa_nat.c index 1be68b31656b..cc3d26764048 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_nat.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_nat.c @@ -785,12 +785,6 @@ int ipa2_nat_del_cmd(struct ipa_ioc_v4_nat_del *del) base_addr = ipa_ctx->nat_mem.tmp_dma_handle; } - if (del->public_ip_addr == 0) { - IPADBG("Bad Parameter\n"); - result = -EPERM; - goto bail; - } - memset(&desc, 0, sizeof(desc)); /* NO-OP IC for ensuring that IPA pipeline is empty */ reg_write_nop = kzalloc(sizeof(*reg_write_nop), flag); diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_qmi_service.c b/drivers/platform/msm/ipa/ipa_v2/ipa_qmi_service.c index e33d0d86ac95..78555729d78a 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_qmi_service.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_qmi_service.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -514,6 +514,14 @@ int qmi_filter_request_send(struct ipa_install_fltr_rule_req_msg_v01 *req) int rc; int i; + /* check if modem up */ + if (!qmi_indication_fin || + !qmi_modem_init_fin || + !ipa_q6_clnt) { + IPAWANDBG("modem QMI haven't up yet\n"); + return -EINVAL; + } + /* check if the filter rules from IPACM is valid */ if (req->filter_spec_list_len == 0) { IPAWANDBG("IPACM pass zero rules to Q6\n"); diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c b/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c index 7cc3c380ee71..e4a3a72ee670 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c @@ -1026,7 +1026,8 @@ static int __ipa_del_rt_tbl(struct ipa_rt_tbl *entry) } static int __ipa_add_rt_rule(enum ipa_ip_type ip, const char *name, - const struct ipa_rt_rule *rule, u8 at_rear, u32 *rule_hdl) + const struct ipa_rt_rule *rule, u8 at_rear, u32 *rule_hdl, + bool user) { struct ipa_rt_tbl *tbl; struct ipa_rt_entry *entry; @@ -1101,6 +1102,7 @@ static int __ipa_add_rt_rule(enum ipa_ip_type ip, const char *name, IPADBG_LOW("rule_cnt=%d\n", tbl->rule_cnt); *rule_hdl = id; entry->id = id; + entry->ipacm_installed = user; return 0; @@ -1125,6 +1127,21 @@ error: * Note: Should not be called from atomic context */ int ipa2_add_rt_rule(struct ipa_ioc_add_rt_rule *rules) +{ + return ipa2_add_rt_rule_usr(rules, false); +} + +/** + * ipa2_add_rt_rule_usr() - Add the specified routing rules to SW and optionally + * commit to IPA HW + * @rules: [inout] set of routing rules to add + * @user_only: [in] indicate installed by userspace module + * + * Returns: 0 on success, negative on failure + * + * Note: Should not be called from atomic context + */ +int ipa2_add_rt_rule_usr(struct ipa_ioc_add_rt_rule *rules, bool user_only) { int i; int ret; @@ -1139,7 +1156,8 @@ int ipa2_add_rt_rule(struct ipa_ioc_add_rt_rule *rules) if (__ipa_add_rt_rule(rules->ip, rules->rt_tbl_name, &rules->rules[i].rule, rules->rules[i].at_rear, - &rules->rules[i].rt_rule_hdl)) { + &rules->rules[i].rt_rule_hdl, + user_only)) { IPAERR_RL("failed to add rt rule %d\n", i); rules->rules[i].status = IPA_RT_STATUS_OF_ADD_FAILED; } else { @@ -1308,13 +1326,14 @@ bail: /** * ipa2_reset_rt() - reset the current SW routing table of specified type * (does not commit to HW) - * @ip: The family of routing tables + * @ip: [in] The family of routing tables + * @user_only: [in] indicate delete rules installed by userspace * * Returns: 0 on success, negative on failure * * Note: Should not be called from atomic context */ -int ipa2_reset_rt(enum ipa_ip_type ip) +int ipa2_reset_rt(enum ipa_ip_type ip, bool user_only) { struct ipa_rt_tbl *tbl; struct ipa_rt_tbl *tbl_next; @@ -1324,6 +1343,7 @@ int ipa2_reset_rt(enum ipa_ip_type ip) struct ipa_rt_tbl_set *rset; u32 apps_start_idx; int id; + bool tbl_user = false; if (ip >= IPA_IP_MAX) { IPAERR_RL("bad parm\n"); @@ -1343,7 +1363,7 @@ int ipa2_reset_rt(enum ipa_ip_type ip) * issue a reset on the filtering module of same IP type since * filtering rules point to routing tables */ - if (ipa2_reset_flt(ip)) + if (ipa2_reset_flt(ip, user_only)) IPAERR_RL("fail to reset flt ip=%d\n", ip); set = &ipa_ctx->rt_tbl_set[ip]; @@ -1351,6 +1371,7 @@ int ipa2_reset_rt(enum ipa_ip_type ip) mutex_lock(&ipa_ctx->lock); IPADBG("reset rt ip=%d\n", ip); list_for_each_entry_safe(tbl, tbl_next, &set->head_rt_tbl_list, link) { + tbl_user = false; list_for_each_entry_safe(rule, rule_next, &tbl->head_rt_rule_list, link) { if (ipa_id_find(rule->id) == NULL) { @@ -1359,25 +1380,34 @@ int ipa2_reset_rt(enum ipa_ip_type ip) return -EFAULT; } + /* indicate if tbl used for user-specified rules*/ + if (rule->ipacm_installed) { + IPADBG("tbl_user %d, tbl-index %d\n", + tbl_user, tbl->id); + tbl_user = true; + } /* * for the "default" routing tbl, remove all but the * last rule */ if (tbl->idx == apps_start_idx && tbl->rule_cnt == 1) continue; + if (!user_only || + rule->ipacm_installed) { + list_del(&rule->link); + tbl->rule_cnt--; + if (rule->hdr) + __ipa_release_hdr(rule->hdr->id); + else if (rule->proc_ctx) + __ipa_release_hdr_proc_ctx( + rule->proc_ctx->id); + rule->cookie = 0; + id = rule->id; + kmem_cache_free(ipa_ctx->rt_rule_cache, rule); - list_del(&rule->link); - tbl->rule_cnt--; - if (rule->hdr) - __ipa_release_hdr(rule->hdr->id); - else if (rule->proc_ctx) - __ipa_release_hdr_proc_ctx(rule->proc_ctx->id); - rule->cookie = 0; - id = rule->id; - kmem_cache_free(ipa_ctx->rt_rule_cache, rule); - - /* remove the handle from the database */ - ipa_id_remove(id); + /* remove the handle from the database */ + ipa_id_remove(id); + } } if (ipa_id_find(tbl->id) == NULL) { @@ -1389,24 +1419,28 @@ int ipa2_reset_rt(enum ipa_ip_type ip) /* do not remove the "default" routing tbl which has index 0 */ if (tbl->idx != apps_start_idx) { - if (!tbl->in_sys) { - list_del(&tbl->link); - set->tbl_cnt--; - clear_bit(tbl->idx, - &ipa_ctx->rt_idx_bitmap[ip]); - IPADBG("rst rt tbl_idx=%d tbl_cnt=%d\n", - tbl->idx, set->tbl_cnt); - kmem_cache_free(ipa_ctx->rt_tbl_cache, tbl); - } else { - list_move(&tbl->link, &rset->head_rt_tbl_list); - clear_bit(tbl->idx, - &ipa_ctx->rt_idx_bitmap[ip]); - set->tbl_cnt--; - IPADBG("rst sys rt tbl_idx=%d tbl_cnt=%d\n", - tbl->idx, set->tbl_cnt); + if (!user_only || tbl_user) { + if (!tbl->in_sys) { + list_del(&tbl->link); + set->tbl_cnt--; + clear_bit(tbl->idx, + &ipa_ctx->rt_idx_bitmap[ip]); + IPADBG("rst rt tbl_idx=%d tbl_cnt=%d\n", + tbl->idx, set->tbl_cnt); + kmem_cache_free(ipa_ctx->rt_tbl_cache, + tbl); + } else { + list_move(&tbl->link, + &rset->head_rt_tbl_list); + clear_bit(tbl->idx, + &ipa_ctx->rt_idx_bitmap[ip]); + set->tbl_cnt--; + IPADBG("rst tbl_idx=%d cnt=%d\n", + tbl->idx, set->tbl_cnt); + } + /* remove the handle from the database */ + ipa_id_remove(id); } - /* remove the handle from the database */ - ipa_id_remove(id); } } mutex_unlock(&ipa_ctx->lock); diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c index 76f74c058c6d..f8d6e68a0d78 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -5078,6 +5078,7 @@ int ipa2_bind_api_controller(enum ipa_hw_type ipa_hw_type, api_ctrl->ipa_cfg_ep_holb_by_client = ipa2_cfg_ep_holb_by_client; api_ctrl->ipa_cfg_ep_ctrl = ipa2_cfg_ep_ctrl; api_ctrl->ipa_add_hdr = ipa2_add_hdr; + api_ctrl->ipa_add_hdr_usr = ipa2_add_hdr_usr; api_ctrl->ipa_del_hdr = ipa2_del_hdr; api_ctrl->ipa_commit_hdr = ipa2_commit_hdr; api_ctrl->ipa_reset_hdr = ipa2_reset_hdr; @@ -5087,6 +5088,7 @@ int ipa2_bind_api_controller(enum ipa_hw_type ipa_hw_type, api_ctrl->ipa_add_hdr_proc_ctx = ipa2_add_hdr_proc_ctx; api_ctrl->ipa_del_hdr_proc_ctx = ipa2_del_hdr_proc_ctx; api_ctrl->ipa_add_rt_rule = ipa2_add_rt_rule; + api_ctrl->ipa_add_rt_rule_usr = ipa2_add_rt_rule_usr; api_ctrl->ipa_del_rt_rule = ipa2_del_rt_rule; api_ctrl->ipa_commit_rt = ipa2_commit_rt; api_ctrl->ipa_reset_rt = ipa2_reset_rt; @@ -5095,6 +5097,7 @@ int ipa2_bind_api_controller(enum ipa_hw_type ipa_hw_type, api_ctrl->ipa_query_rt_index = ipa2_query_rt_index; api_ctrl->ipa_mdfy_rt_rule = ipa2_mdfy_rt_rule; api_ctrl->ipa_add_flt_rule = ipa2_add_flt_rule; + api_ctrl->ipa_add_flt_rule_usr = ipa2_add_flt_rule_usr; api_ctrl->ipa_del_flt_rule = ipa2_del_flt_rule; api_ctrl->ipa_mdfy_flt_rule = ipa2_mdfy_flt_rule; api_ctrl->ipa_commit_flt = ipa2_commit_flt; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c index 681b2d945945..dfff3b422659 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c @@ -345,6 +345,43 @@ int ipa3_active_clients_log_print_table(char *buf, int size) return cnt; } +static int ipa3_clean_modem_rule(void) +{ + struct ipa_install_fltr_rule_req_msg_v01 *req; + struct ipa_install_fltr_rule_req_ex_msg_v01 *req_ex; + int val = 0; + + if (ipa3_ctx->ipa_hw_type < IPA_HW_v3_0) { + req = kzalloc( + sizeof(struct ipa_install_fltr_rule_req_msg_v01), + GFP_KERNEL); + if (!req) { + IPAERR("mem allocated failed!\n"); + return -ENOMEM; + } + req->filter_spec_list_valid = false; + req->filter_spec_list_len = 0; + req->source_pipe_index_valid = 0; + val = ipa3_qmi_filter_request_send(req); + kfree(req); + } else { + req_ex = kzalloc( + sizeof(struct ipa_install_fltr_rule_req_ex_msg_v01), + GFP_KERNEL); + if (!req_ex) { + IPAERR("mem allocated failed!\n"); + return -ENOMEM; + } + req_ex->filter_spec_ex_list_valid = false; + req_ex->filter_spec_ex_list_len = 0; + req_ex->source_pipe_index_valid = 0; + val = ipa3_qmi_filter_request_ex_send(req_ex); + kfree(req_ex); + } + + return val; +} + static int ipa3_active_clients_panic_notifier(struct notifier_block *this, unsigned long event, void *ptr) { @@ -598,7 +635,8 @@ static void ipa3_wan_msg_free_cb(void *buff, u32 len, u32 type) kfree(buff); } -static int ipa3_send_wan_msg(unsigned long usr_param, uint8_t msg_type, bool is_cache) +static int ipa3_send_wan_msg(unsigned long usr_param, uint8_t msg_type, + bool is_cache) { int retval; struct ipa_wan_msg *wan_msg; @@ -906,7 +944,8 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) retval = -EFAULT; break; } - if (ipa3_add_hdr((struct ipa_ioc_add_hdr *)param)) { + if (ipa3_add_hdr_usr((struct ipa_ioc_add_hdr *)param, + true)) { retval = -EFAULT; break; } @@ -986,7 +1025,8 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) retval = -EFAULT; break; } - if (ipa3_add_rt_rule((struct ipa_ioc_add_rt_rule *)param)) { + if (ipa3_add_rt_rule_usr((struct ipa_ioc_add_rt_rule *)param, + true)) { retval = -EFAULT; break; } @@ -1191,7 +1231,8 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) retval = -EFAULT; break; } - if (ipa3_add_flt_rule((struct ipa_ioc_add_flt_rule *)param)) { + if (ipa3_add_flt_rule_usr((struct ipa_ioc_add_flt_rule *)param, + true)) { retval = -EFAULT; break; } @@ -1328,19 +1369,19 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) retval = ipa3_commit_hdr(); break; case IPA_IOC_RESET_HDR: - retval = ipa3_reset_hdr(); + retval = ipa3_reset_hdr(false); break; case IPA_IOC_COMMIT_RT: retval = ipa3_commit_rt(arg); break; case IPA_IOC_RESET_RT: - retval = ipa3_reset_rt(arg); + retval = ipa3_reset_rt(arg, false); break; case IPA_IOC_COMMIT_FLT: retval = ipa3_commit_flt(arg); break; case IPA_IOC_RESET_FLT: - retval = ipa3_reset_flt(arg); + retval = ipa3_reset_flt(arg, false); break; case IPA_IOC_GET_RT_TBL: if (copy_from_user(header, (u8 *)arg, @@ -1720,7 +1761,7 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) break; } if (ipa3_add_hdr_proc_ctx( - (struct ipa_ioc_add_hdr_proc_ctx *)param)) { + (struct ipa_ioc_add_hdr_proc_ctx *)param, true)) { retval = -EFAULT; break; } @@ -1812,7 +1853,22 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) } break; - default: /* redundant, as cmd was checked against MAXNR */ + case IPA_IOC_CLEANUP: + /*Route and filter rules will also be clean*/ + IPADBG("Got IPA_IOC_CLEANUP\n"); + retval = ipa3_reset_hdr(true); + memset(&nat_del, 0, sizeof(nat_del)); + nat_del.table_index = 0; + retval = ipa3_nat_del_cmd(&nat_del); + retval = ipa3_clean_modem_rule(); + break; + + case IPA_IOC_QUERY_WLAN_CLIENT: + IPADBG("Got IPA_IOC_QUERY_WLAN_CLIENT\n"); + retval = ipa3_resend_wlan_msg(); + break; + + default: IPA_ACTIVE_CLIENTS_DEC_SIMPLE(); return -ENOTTY; } @@ -1823,13 +1879,13 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) } /** -* ipa3_setup_dflt_rt_tables() - Setup default routing tables -* -* Return codes: -* 0: success -* -ENOMEM: failed to allocate memory -* -EPERM: failed to add the tables -*/ + * ipa3_setup_dflt_rt_tables() - Setup default routing tables + * + * Return codes: + * 0: success + * -ENOMEM: failed to allocate memory + * -EPERM: failed to add the tables + */ int ipa3_setup_dflt_rt_tables(void) { struct ipa_ioc_add_rt_rule *rt_rule; @@ -2010,14 +2066,14 @@ static int ipa3_init_smem_region(int memory_region_size, } /** -* ipa3_init_q6_smem() - Initialize Q6 general memory and -* header memory regions in IPA. -* -* Return codes: -* 0: success -* -ENOMEM: failed to allocate dma memory -* -EFAULT: failed to send IPA command to initialize the memory -*/ + * ipa3_init_q6_smem() - Initialize Q6 general memory and + * header memory regions in IPA. + * + * Return codes: + * 0: success + * -ENOMEM: failed to allocate dma memory + * -EFAULT: failed to send IPA command to initialize the memory + */ int ipa3_init_q6_smem(void) { int rc; @@ -2546,12 +2602,12 @@ static int ipa3_q6_set_ex_path_to_apps(void) } /** -* ipa3_q6_pre_shutdown_cleanup() - A cleanup for all Q6 related configuration -* in IPA HW. This is performed in case of SSR. -* -* This is a mandatory procedure, in case one of the steps fails, the -* AP needs to restart. -*/ + * ipa3_q6_pre_shutdown_cleanup() - A cleanup for all Q6 related configuration + * in IPA HW. This is performed in case of SSR. + * + * This is a mandatory procedure, in case one of the steps fails, the + * AP needs to restart. + */ void ipa3_q6_pre_shutdown_cleanup(void) { IPADBG_LOW("ENTER\n"); @@ -2569,8 +2625,8 @@ void ipa3_q6_pre_shutdown_cleanup(void) BUG(); } /* Remove delay from Q6 PRODs to avoid pending descriptors - * on pipe reset procedure - */ + * on pipe reset procedure + */ ipa3_q6_pipe_delay(false); IPA_ACTIVE_CLIENTS_DEC_SIMPLE(); @@ -3465,11 +3521,11 @@ static unsigned int ipa3_get_bus_vote(void) } /** -* ipa3_enable_clks() - Turn on IPA clocks -* -* Return codes: -* None -*/ + * ipa3_enable_clks() - Turn on IPA clocks + * + * Return codes: + * None + */ void ipa3_enable_clks(void) { IPADBG("enabling IPA clocks and bus voting\n"); @@ -3498,11 +3554,11 @@ void _ipa_disable_clks_v3_0(void) } /** -* ipa3_disable_clks() - Turn off IPA clocks -* -* Return codes: -* None -*/ + * ipa3_disable_clks() - Turn off IPA clocks + * + * Return codes: + * None + */ void ipa3_disable_clks(void) { IPADBG("disabling IPA clocks and bus voting\n"); @@ -3541,28 +3597,28 @@ static void ipa3_start_tag_process(struct work_struct *work) } /** -* ipa3_active_clients_log_mod() - Log a modification in the active clients -* reference count -* -* This method logs any modification in the active clients reference count: -* It logs the modification in the circular history buffer -* It logs the modification in the hash table - looking for an entry, -* creating one if needed and deleting one if needed. -* -* @id: ipa3_active client logging info struct to hold the log information -* @inc: a boolean variable to indicate whether the modification is an increase -* or decrease -* @int_ctx: a boolean variable to indicate whether this call is being made from -* an interrupt context and therefore should allocate GFP_ATOMIC memory -* -* Method process: -* - Hash the unique identifier string -* - Find the hash in the table -* 1)If found, increase or decrease the reference count -* 2)If not found, allocate a new hash table entry struct and initialize it -* - Remove and deallocate unneeded data structure -* - Log the call in the circular history buffer (unless it is a simple call) -*/ + * ipa3_active_clients_log_mod() - Log a modification in the active clients + * reference count + * + * This method logs any modification in the active clients reference count: + * It logs the modification in the circular history buffer + * It logs the modification in the hash table - looking for an entry, + * creating one if needed and deleting one if needed. + * + * @id: ipa3_active client logging info struct to hold the log information + * @inc: a boolean variable to indicate whether the modification is an increase + * or decrease + * @int_ctx: a boolean variable to indicate whether this call is being made from + * an interrupt context and therefore should allocate GFP_ATOMIC memory + * + * Method process: + * - Hash the unique identifier string + * - Find the hash in the table + * 1)If found, increase or decrease the reference count + * 2)If not found, allocate a new hash table entry struct and initialize it + * - Remove and deallocate unneeded data structure + * - Log the call in the circular history buffer (unless it is a simple call) + */ void ipa3_active_clients_log_mod(struct ipa_active_client_logging_info *id, bool inc, bool int_ctx) { @@ -3632,12 +3688,12 @@ void ipa3_active_clients_log_inc(struct ipa_active_client_logging_info *id, } /** -* ipa3_inc_client_enable_clks() - Increase active clients counter, and -* enable ipa clocks if necessary -* -* Return codes: -* None -*/ + * ipa3_inc_client_enable_clks() - Increase active clients counter, and + * enable ipa clocks if necessary + * + * Return codes: + * None + */ void ipa3_inc_client_enable_clks(struct ipa_active_client_logging_info *id) { ipa3_active_clients_lock(); @@ -3650,13 +3706,13 @@ void ipa3_inc_client_enable_clks(struct ipa_active_client_logging_info *id) } /** -* ipa3_inc_client_enable_clks_no_block() - Only increment the number of active -* clients if no asynchronous actions should be done. Asynchronous actions are -* locking a mutex and waking up IPA HW. -* -* Return codes: 0 for success -* -EPERM if an asynchronous action should have been done -*/ + * ipa3_inc_client_enable_clks_no_block() - Only increment the number of active + * clients if no asynchronous actions should be done. Asynchronous actions are + * locking a mutex and waking up IPA HW. + * + * Return codes: 0 for success + * -EPERM if an asynchronous action should have been done + */ int ipa3_inc_client_enable_clks_no_block(struct ipa_active_client_logging_info *id) { @@ -3718,12 +3774,12 @@ void ipa3_dec_client_disable_clks(struct ipa_active_client_logging_info *id) } /** -* ipa3_inc_acquire_wakelock() - Increase active clients counter, and -* acquire wakelock if necessary -* -* Return codes: -* None -*/ + * ipa3_inc_acquire_wakelock() - Increase active clients counter, and + * acquire wakelock if necessary + * + * Return codes: + * None + */ void ipa3_inc_acquire_wakelock(void) { unsigned long flags; @@ -3835,12 +3891,12 @@ static void ipa3_sps_process_irq_schedule_rel(void) } /** -* ipa3_suspend_handler() - Handles the suspend interrupt: -* wakes up the suspended peripheral by requesting its consumer -* @interrupt: Interrupt type -* @private_data: The client's private data -* @interrupt_data: Interrupt specific information data -*/ + * ipa3_suspend_handler() - Handles the suspend interrupt: + * wakes up the suspended peripheral by requesting its consumer + * @interrupt: Interrupt type + * @private_data: The client's private data + * @interrupt_data: Interrupt specific information data + */ void ipa3_suspend_handler(enum ipa_irq_type interrupt, void *private_data, void *interrupt_data) @@ -3903,12 +3959,12 @@ void ipa3_suspend_handler(enum ipa_irq_type interrupt, } /** -* ipa3_restore_suspend_handler() - restores the original suspend IRQ handler -* as it was registered in the IPA init sequence. -* Return codes: -* 0: success -* -EPERM: failed to remove current handler or failed to add original handler -* */ + * ipa3_restore_suspend_handler() - restores the original suspend IRQ handler + * as it was registered in the IPA init sequence. + * Return codes: + * 0: success + * -EPERM: failed to remove current handler or failed to add original handler + */ int ipa3_restore_suspend_handler(void) { int result = 0; @@ -4497,39 +4553,37 @@ static int ipa3_tz_unlock_reg(struct ipa3_context *ipa3_ctx) } /** -* ipa3_pre_init() - Initialize the IPA Driver. -* This part contains all initialization which doesn't require IPA HW, such -* as structure allocations and initializations, register writes, etc. -* -* @resource_p: contain platform specific values from DST file -* @pdev: The platform device structure representing the IPA driver -* -* Function initialization process: -* - Allocate memory for the driver context data struct -* - Initializing the ipa3_ctx with: -* 1)parsed values from the dts file -* 2)parameters passed to the module initialization -* 3)read HW values(such as core memory size) -* - Map IPA core registers to CPU memory -* - Restart IPA core(HW reset) -* - Set configuration for IPA BAM via BAM_CNFG_BITS -* - Initialize the look-aside caches(kmem_cache/slab) for filter, -* routing and IPA-tree -* - Create memory pool with 4 objects for DMA operations(each object -* is 512Bytes long), this object will be use for tx(A5->IPA) -* - Initialize lists head(routing,filter,hdr,system pipes) -* - Initialize mutexes (for ipa_ctx and NAT memory mutexes) -* - Initialize spinlocks (for list related to A5<->IPA pipes) -* - Initialize 2 single-threaded work-queue named "ipa rx wq" and "ipa tx wq" -* - Initialize Red-Black-Tree(s) for handles of header,routing rule, -* routing table ,filtering rule -* - Initialize the filter block by committing IPV4 and IPV6 default rules -* - Create empty routing table in system memory(no committing) -* - Initialize pipes memory pool with ipa3_pipe_mem_init for supported platforms -* - Create a char-device for IPA -* - Initialize IPA RM (resource manager) -* - Configure GSI registers (in GSI case) -*/ + * ipa3_pre_init() - Initialize the IPA Driver. + * This part contains all initialization which doesn't require IPA HW, such + * as structure allocations and initializations, register writes, etc. + * + * @resource_p: contain platform specific values from DST file + * @pdev: The platform device structure representing the IPA driver + * + * Function initialization process: + * Allocate memory for the driver context data struct + * Initializing the ipa3_ctx with : + * 1)parsed values from the dts file + * 2)parameters passed to the module initialization + * 3)read HW values(such as core memory size) + * Map IPA core registers to CPU memory + * Restart IPA core(HW reset) + * Initialize the look-aside caches(kmem_cache/slab) for filter, + * routing and IPA-tree + * Create memory pool with 4 objects for DMA operations(each object + * is 512Bytes long), this object will be use for tx(A5->IPA) + * Initialize lists head(routing, hdr, system pipes) + * Initialize mutexes (for ipa_ctx and NAT memory mutexes) + * Initialize spinlocks (for list related to A5<->IPA pipes) + * Initialize 2 single-threaded work-queue named "ipa rx wq" and "ipa tx wq" + * Initialize Red-Black-Tree(s) for handles of header,routing rule, + * routing table ,filtering rule + * Initialize the filter block by committing IPV4 and IPV6 default rules + * Create empty routing table in system memory(no committing) + * Create a char-device for IPA + * Initialize IPA RM (resource manager) + * Configure GSI registers (in GSI case) + */ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p, struct device *ipa_dev) { @@ -4887,6 +4941,10 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p, init_waitqueue_head(&ipa3_ctx->msg_waitq); mutex_init(&ipa3_ctx->msg_lock); + /* store wlan client-connect-msg-list */ + INIT_LIST_HEAD(&ipa3_ctx->msg_wlan_client_list); + mutex_init(&ipa3_ctx->msg_wlan_client_lock); + mutex_init(&ipa3_ctx->lock); mutex_init(&ipa3_ctx->nat_mem.lock); mutex_init(&ipa3_ctx->q6_proxy_clk_vote_mutex); @@ -5873,7 +5931,7 @@ int ipa3_plat_drv_probe(struct platform_device *pdev_p, * * Returns -EAGAIN to runtime_pm framework in case IPA is in use by AP. * This will postpone the suspend operation until IPA is no longer used by AP. -*/ + */ int ipa3_ap_suspend(struct device *dev) { int i; @@ -5899,14 +5957,14 @@ int ipa3_ap_suspend(struct device *dev) } /** -* ipa3_ap_resume() - resume callback for runtime_pm -* @dev: pointer to device -* -* This callback will be invoked by the runtime_pm framework when an AP resume -* operation is invoked. -* -* Always returns 0 since resume should always succeed. -*/ + * ipa3_ap_resume() - resume callback for runtime_pm + * @dev: pointer to device + * + * This callback will be invoked by the runtime_pm framework when an AP resume + * operation is invoked. + * + * Always returns 0 since resume should always succeed. + */ int ipa3_ap_resume(struct device *dev) { return 0; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_flt.c b/drivers/platform/msm/ipa/ipa_v3/ipa_flt.c index 128b859ee152..03c846ea9596 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_flt.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_flt.c @@ -784,7 +784,7 @@ error: static int __ipa_create_flt_entry(struct ipa3_flt_entry **entry, const struct ipa_flt_rule *rule, struct ipa3_rt_tbl *rt_tbl, - struct ipa3_flt_tbl *tbl) + struct ipa3_flt_tbl *tbl, bool user) { int id; @@ -809,6 +809,7 @@ static int __ipa_create_flt_entry(struct ipa3_flt_entry **entry, } } (*entry)->rule_id = id; + (*entry)->ipacm_installed = user; return 0; @@ -846,7 +847,7 @@ ipa_insert_failed: static int __ipa_add_flt_rule(struct ipa3_flt_tbl *tbl, enum ipa_ip_type ip, const struct ipa_flt_rule *rule, u8 add_rear, - u32 *rule_hdl) + u32 *rule_hdl, bool user) { struct ipa3_flt_entry *entry; struct ipa3_rt_tbl *rt_tbl = NULL; @@ -854,7 +855,7 @@ static int __ipa_add_flt_rule(struct ipa3_flt_tbl *tbl, enum ipa_ip_type ip, if (__ipa_validate_flt_rule(rule, &rt_tbl, ip)) goto error; - if (__ipa_create_flt_entry(&entry, rule, rt_tbl, tbl)) + if (__ipa_create_flt_entry(&entry, rule, rt_tbl, tbl, user)) goto error; if (add_rear) { @@ -904,7 +905,7 @@ static int __ipa_add_flt_rule_after(struct ipa3_flt_tbl *tbl, if (__ipa_validate_flt_rule(rule, &rt_tbl, ip)) goto error; - if (__ipa_create_flt_entry(&entry, rule, rt_tbl, tbl)) + if (__ipa_create_flt_entry(&entry, rule, rt_tbl, tbl, true)) goto error; list_add(&entry->link, &((*add_after_entry)->link)); @@ -1054,7 +1055,7 @@ static int __ipa_add_flt_get_ep_idx(enum ipa_client_type ep, int *ipa_ep_idx) static int __ipa_add_ep_flt_rule(enum ipa_ip_type ip, enum ipa_client_type ep, const struct ipa_flt_rule *rule, u8 add_rear, - u32 *rule_hdl) + u32 *rule_hdl, bool user) { struct ipa3_flt_tbl *tbl; int ipa_ep_idx; @@ -1072,18 +1073,33 @@ static int __ipa_add_ep_flt_rule(enum ipa_ip_type ip, enum ipa_client_type ep, tbl = &ipa3_ctx->flt_tbl[ipa_ep_idx][ip]; IPADBG_LOW("add ep flt rule ip=%d ep=%d\n", ip, ep); - return __ipa_add_flt_rule(tbl, ip, rule, add_rear, rule_hdl); + return __ipa_add_flt_rule(tbl, ip, rule, add_rear, rule_hdl, user); } /** * ipa3_add_flt_rule() - Add the specified filtering rules to SW and optionally * commit to IPA HW + * @rules: [inout] set of filtering rules to add * * Returns: 0 on success, negative on failure * * Note: Should not be called from atomic context */ int ipa3_add_flt_rule(struct ipa_ioc_add_flt_rule *rules) +{ + return ipa3_add_flt_rule_usr(rules, false); +} +/** + * ipa3_add_flt_rule_usr() - Add the specified filtering rules to + * SW and optionally commit to IPA HW + * @rules: [inout] set of filtering rules to add + * @user_only: [in] indicate rules installed by userspace + * + * Returns: 0 on success, negative on failure + * + * Note: Should not be called from atomic context + */ +int ipa3_add_flt_rule_usr(struct ipa_ioc_add_flt_rule *rules, bool user_only) { int i; int result; @@ -1100,7 +1116,8 @@ int ipa3_add_flt_rule(struct ipa_ioc_add_flt_rule *rules) result = __ipa_add_ep_flt_rule(rules->ip, rules->ep, &rules->rules[i].rule, rules->rules[i].at_rear, - &rules->rules[i].flt_rule_hdl); + &rules->rules[i].flt_rule_hdl, + user_only); else result = -1; @@ -1347,18 +1364,20 @@ bail: * ipa3_reset_flt() - Reset the current SW filtering table of specified type * (does not commit to HW) * @ip: [in] the family of routing tables + * @user_only: [in] indicate rules deleted by userspace * * Returns: 0 on success, negative on failure * * Note: Should not be called from atomic context */ -int ipa3_reset_flt(enum ipa_ip_type ip) +int ipa3_reset_flt(enum ipa_ip_type ip, bool user_only) { struct ipa3_flt_tbl *tbl; struct ipa3_flt_entry *entry; struct ipa3_flt_entry *next; int i; int id; + int rule_id; if (ip >= IPA_IP_MAX) { IPAERR_RL("bad parm\n"); @@ -1378,21 +1397,27 @@ int ipa3_reset_flt(enum ipa_ip_type ip) mutex_unlock(&ipa3_ctx->lock); return -EFAULT; } - list_del(&entry->link); - entry->tbl->rule_cnt--; - if (entry->rt_tbl) - entry->rt_tbl->ref_cnt--; - /* if rule id was allocated from idr, remove it */ - if ((entry->rule_id < ipahal_get_rule_id_hi_bit()) && - (entry->rule_id >= ipahal_get_low_rule_id())) - idr_remove(&entry->tbl->rule_ids, - entry->rule_id); - entry->cookie = 0; - id = entry->id; - kmem_cache_free(ipa3_ctx->flt_rule_cache, entry); - /* remove the handle from the database */ - ipa3_id_remove(id); + if (!user_only || + entry->ipacm_installed) { + list_del(&entry->link); + entry->tbl->rule_cnt--; + if (entry->rt_tbl) + entry->rt_tbl->ref_cnt--; + /* if rule id was allocated from idr, remove */ + rule_id = entry->rule_id; + id = entry->id; + if ((rule_id < ipahal_get_rule_id_hi_bit()) && + (rule_id >= ipahal_get_low_rule_id())) + idr_remove(&entry->tbl->rule_ids, + rule_id); + entry->cookie = 0; + kmem_cache_free(ipa3_ctx->flt_rule_cache, + entry); + + /* remove the handle from the database */ + ipa3_id_remove(id); + } } } mutex_unlock(&ipa3_ctx->lock); @@ -1418,14 +1443,14 @@ void ipa3_install_dflt_flt_rules(u32 ipa_ep_idx) tbl = &ipa3_ctx->flt_tbl[ipa_ep_idx][IPA_IP_v4]; rule.action = IPA_PASS_TO_EXCEPTION; __ipa_add_flt_rule(tbl, IPA_IP_v4, &rule, true, - &ep->dflt_flt4_rule_hdl); + &ep->dflt_flt4_rule_hdl, false); ipa3_ctx->ctrl->ipa3_commit_flt(IPA_IP_v4); tbl->sticky_rear = true; tbl = &ipa3_ctx->flt_tbl[ipa_ep_idx][IPA_IP_v6]; rule.action = IPA_PASS_TO_EXCEPTION; __ipa_add_flt_rule(tbl, IPA_IP_v6, &rule, true, - &ep->dflt_flt6_rule_hdl); + &ep->dflt_flt6_rule_hdl, false); ipa3_ctx->ctrl->ipa3_commit_flt(IPA_IP_v6); tbl->sticky_rear = true; mutex_unlock(&ipa3_ctx->lock); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c b/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c index b5b8643f24a9..f71eb952cde2 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -315,7 +315,7 @@ end: } static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, - bool add_ref_hdr) + bool add_ref_hdr, bool user_only) { struct ipa3_hdr_entry *hdr_entry; struct ipa3_hdr_proc_ctx_entry *entry; @@ -360,6 +360,7 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, if (add_ref_hdr) hdr_entry->ref_cnt++; entry->cookie = IPA_PROC_HDR_COOKIE; + entry->ipacm_installed = user_only; needed_len = ipahal_get_proc_ctx_needed_len(proc_ctx->type); @@ -396,6 +397,7 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, */ offset->offset = htbl->end; offset->bin = bin; + offset->ipacm_installed = user_only; htbl->end += ipa_hdr_proc_ctx_bin_sz[bin]; list_add(&offset->link, &htbl->head_offset_list[bin]); @@ -404,6 +406,7 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, offset = list_first_entry(&htbl->head_free_offset_list[bin], struct ipa3_hdr_proc_ctx_offset_entry, link); + offset->ipacm_installed = user_only; list_move(&offset->link, &htbl->head_offset_list[bin]); } @@ -441,7 +444,7 @@ bad_len: } -static int __ipa_add_hdr(struct ipa_hdr_add *hdr) +static int __ipa_add_hdr(struct ipa_hdr_add *hdr, bool user) { struct ipa3_hdr_entry *entry; struct ipa_hdr_offset_entry *offset = NULL; @@ -476,6 +479,7 @@ static int __ipa_add_hdr(struct ipa_hdr_add *hdr) entry->is_eth2_ofst_valid = hdr->is_eth2_ofst_valid; entry->eth2_ofst = hdr->eth2_ofst; entry->cookie = IPA_HDR_COOKIE; + entry->ipacm_installed = user; if (hdr->hdr_len <= ipa_hdr_bin_sz[IPA_HDR_BIN0]) bin = IPA_HDR_BIN0; @@ -527,6 +531,7 @@ static int __ipa_add_hdr(struct ipa_hdr_add *hdr) list_add(&offset->link, &htbl->head_offset_list[bin]); entry->offset_entry = offset; + offset->ipacm_installed = user; } } else { entry->is_hdr_proc_ctx = false; @@ -535,6 +540,7 @@ static int __ipa_add_hdr(struct ipa_hdr_add *hdr) struct ipa_hdr_offset_entry, link); list_move(&offset->link, &htbl->head_offset_list[bin]); entry->offset_entry = offset; + offset->ipacm_installed = user; } list_add(&entry->link, &htbl->head_hdr_entry_list); @@ -566,7 +572,7 @@ static int __ipa_add_hdr(struct ipa_hdr_add *hdr) IPADBG("adding processing context for header %s\n", hdr->name); proc_ctx.type = IPA_HDR_PROC_NONE; proc_ctx.hdr_hdl = id; - if (__ipa_add_hdr_proc_ctx(&proc_ctx, false)) { + if (__ipa_add_hdr_proc_ctx(&proc_ctx, false, user)) { IPAERR("failed to add hdr proc ctx\n"); goto fail_add_proc_ctx; } @@ -727,6 +733,21 @@ int __ipa3_del_hdr(u32 hdr_hdl, bool by_user) * Note: Should not be called from atomic context */ int ipa3_add_hdr(struct ipa_ioc_add_hdr *hdrs) +{ + return ipa3_add_hdr_usr(hdrs, false); +} + +/** + * ipa3_add_hdr_usr() - add the specified headers to SW + * and optionally commit them to IPA HW + * @hdrs: [inout] set of headers to add + * @user_only: [in] indicate installed from user + * + * Returns: 0 on success, negative on failure + * + * Note: Should not be called from atomic context + */ +int ipa3_add_hdr_usr(struct ipa_ioc_add_hdr *hdrs, bool user_only) { int i; int result = -EFAULT; @@ -740,7 +761,7 @@ int ipa3_add_hdr(struct ipa_ioc_add_hdr *hdrs) IPADBG("adding %d headers to IPA driver internal data struct\n", hdrs->num_hdrs); for (i = 0; i < hdrs->num_hdrs; i++) { - if (__ipa_add_hdr(&hdrs->hdr[i])) { + if (__ipa_add_hdr(&hdrs->hdr[i], user_only)) { IPAERR_RL("failed to add hdr %d\n", i); hdrs->hdr[i].status = -1; } else { @@ -821,12 +842,14 @@ int ipa3_del_hdr(struct ipa_ioc_del_hdr *hdls) * ipa3_add_hdr_proc_ctx() - add the specified headers to SW * and optionally commit them to IPA HW * @proc_ctxs: [inout] set of processing context headers to add + * @user_only: [in] indicate installed by user-space module * * Returns: 0 on success, negative on failure * * Note: Should not be called from atomic context */ -int ipa3_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs) +int ipa3_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs, + bool user_only) { int i; int result = -EFAULT; @@ -840,7 +863,8 @@ int ipa3_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs) IPADBG("adding %d header processing contextes to IPA driver\n", proc_ctxs->num_proc_ctxs); for (i = 0; i < proc_ctxs->num_proc_ctxs; i++) { - if (__ipa_add_hdr_proc_ctx(&proc_ctxs->proc_ctx[i], true)) { + if (__ipa_add_hdr_proc_ctx(&proc_ctxs->proc_ctx[i], + true, user_only)) { IPAERR_RL("failed to add hdr pric ctx %d\n", i); proc_ctxs->proc_ctx[i].status = -1; } else { @@ -955,11 +979,12 @@ bail: * ipa3_reset_hdr() - reset the current header table in SW (does not commit to * HW) * + * @user_only: [in] indicate delete rules installed by userspace * Returns: 0 on success, negative on failure * * Note: Should not be called from atomic context */ -int ipa3_reset_hdr(void) +int ipa3_reset_hdr(bool user_only) { struct ipa3_hdr_entry *entry; struct ipa3_hdr_entry *next; @@ -975,9 +1000,9 @@ int ipa3_reset_hdr(void) * issue a reset on the routing module since routing rules point to * header table entries */ - if (ipa3_reset_rt(IPA_IP_v4)) + if (ipa3_reset_rt(IPA_IP_v4, user_only)) IPAERR("fail to reset v4 rt\n"); - if (ipa3_reset_rt(IPA_IP_v6)) + if (ipa3_reset_rt(IPA_IP_v6, user_only)) IPAERR("fail to reset v4 rt\n"); mutex_lock(&ipa3_ctx->lock); @@ -1006,21 +1031,23 @@ int ipa3_reset_hdr(void) WARN_ON(1); return -EFAULT; } - if (entry->is_hdr_proc_ctx) { - dma_unmap_single(ipa3_ctx->pdev, - entry->phys_base, - entry->hdr_len, - DMA_TO_DEVICE); - entry->proc_ctx = NULL; + + if (!user_only || entry->ipacm_installed) { + if (entry->is_hdr_proc_ctx) { + dma_unmap_single(ipa3_ctx->pdev, + entry->phys_base, + entry->hdr_len, + DMA_TO_DEVICE); + entry->proc_ctx = NULL; + } + list_del(&entry->link); + entry->ref_cnt = 0; + entry->cookie = 0; + + /* remove the handle from the database */ + ipa3_id_remove(entry->id); + kmem_cache_free(ipa3_ctx->hdr_cache, entry); } - list_del(&entry->link); - entry->ref_cnt = 0; - entry->cookie = 0; - - /* remove the handle from the database */ - ipa3_id_remove(entry->id); - kmem_cache_free(ipa3_ctx->hdr_cache, entry); - } for (i = 0; i < IPA_HDR_BIN_MAX; i++) { list_for_each_entry_safe(off_entry, off_next, @@ -1034,14 +1061,23 @@ int ipa3_reset_hdr(void) if (off_entry->offset == 0) continue; - list_del(&off_entry->link); - kmem_cache_free(ipa3_ctx->hdr_offset_cache, off_entry); + if (!user_only || + off_entry->ipacm_installed) { + list_del(&off_entry->link); + kmem_cache_free(ipa3_ctx->hdr_offset_cache, + off_entry); + } } list_for_each_entry_safe(off_entry, off_next, &ipa3_ctx->hdr_tbl.head_free_offset_list[i], link) { - list_del(&off_entry->link); - kmem_cache_free(ipa3_ctx->hdr_offset_cache, off_entry); + + if (!user_only || + off_entry->ipacm_installed) { + list_del(&off_entry->link); + kmem_cache_free(ipa3_ctx->hdr_offset_cache, + off_entry); + } } } /* there is one header of size 8 */ @@ -1060,30 +1096,43 @@ int ipa3_reset_hdr(void) WARN_ON(1); return -EFAULT; } - list_del(&ctx_entry->link); - ctx_entry->ref_cnt = 0; - ctx_entry->cookie = 0; - /* remove the handle from the database */ - ipa3_id_remove(ctx_entry->id); - kmem_cache_free(ipa3_ctx->hdr_proc_ctx_cache, ctx_entry); + if (!user_only || + ctx_entry->ipacm_installed) { + list_del(&ctx_entry->link); + ctx_entry->ref_cnt = 0; + ctx_entry->cookie = 0; + /* remove the handle from the database */ + ipa3_id_remove(ctx_entry->id); + kmem_cache_free(ipa3_ctx->hdr_proc_ctx_cache, + ctx_entry); + } } for (i = 0; i < IPA_HDR_PROC_CTX_BIN_MAX; i++) { list_for_each_entry_safe(ctx_off_entry, ctx_off_next, &ipa3_ctx->hdr_proc_ctx_tbl.head_offset_list[i], link) { - list_del(&ctx_off_entry->link); - kmem_cache_free(ipa3_ctx->hdr_proc_ctx_offset_cache, + if (!user_only || + ctx_off_entry->ipacm_installed) { + list_del(&ctx_off_entry->link); + kmem_cache_free( + ipa3_ctx->hdr_proc_ctx_offset_cache, ctx_off_entry); + } } list_for_each_entry_safe(ctx_off_entry, ctx_off_next, &ipa3_ctx->hdr_proc_ctx_tbl.head_free_offset_list[i], link) { - list_del(&ctx_off_entry->link); - kmem_cache_free(ipa3_ctx->hdr_proc_ctx_offset_cache, - ctx_off_entry); + + if (!user_only || + ctx_off_entry->ipacm_installed) { + list_del(&ctx_off_entry->link); + kmem_cache_free( + ipa3_ctx->hdr_proc_ctx_offset_cache, + ctx_off_entry); + } } } ipa3_ctx->hdr_proc_ctx_tbl.end = 0; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h index 7bf56688a9e7..ea98433bbdf2 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -233,6 +233,7 @@ struct ipa_smmu_cb_ctx { * @prio: rule 10bit priority which defines the order of the rule * among other rules at the same integrated table * @rule_id: rule 10bit ID to be returned in packet status + * @ipacm_installed: indicate if installed by ipacm */ struct ipa3_flt_entry { struct list_head link; @@ -244,6 +245,7 @@ struct ipa3_flt_entry { int id; u16 prio; u16 rule_id; + bool ipacm_installed; }; /** @@ -300,6 +302,7 @@ struct ipa3_rt_tbl { * @is_eth2_ofst_valid: is eth2_ofst field valid? * @eth2_ofst: offset to start of Ethernet-II/802.3 header * @user_deleted: is the header deleted by the user? + * @ipacm_installed: indicate if installed by ipacm */ struct ipa3_hdr_entry { struct list_head link; @@ -318,6 +321,7 @@ struct ipa3_hdr_entry { u8 is_eth2_ofst_valid; u16 eth2_ofst; bool user_deleted; + bool ipacm_installed; }; /** @@ -341,11 +345,13 @@ struct ipa3_hdr_tbl { * @link: entry's link in global processing context header offset entries list * @offset: the offset * @bin: bin + * @ipacm_installed: indicate if installed by ipacm */ struct ipa3_hdr_proc_ctx_offset_entry { struct list_head link; u32 offset; u32 bin; + bool ipacm_installed; }; /** @@ -358,6 +364,7 @@ struct ipa3_hdr_proc_ctx_offset_entry { * @ref_cnt: reference counter of routing table * @id: processing context header entry id * @user_deleted: is the hdr processing context deleted by the user? + * @ipacm_installed: indicate if installed by ipacm */ struct ipa3_hdr_proc_ctx_entry { struct list_head link; @@ -368,6 +375,7 @@ struct ipa3_hdr_proc_ctx_entry { u32 ref_cnt; int id; bool user_deleted; + bool ipacm_installed; }; /** @@ -423,6 +431,8 @@ struct ipa3_flt_tbl { * @prio: rule 10bit priority which defines the order of the rule * among other rules at the integrated same table * @rule_id: rule 10bit ID to be returned in packet status + * @rule_id_valid: indicate if rule_id_valid valid or not? + * @ipacm_installed: indicate if installed by ipacm */ struct ipa3_rt_entry { struct list_head link; @@ -436,6 +446,7 @@ struct ipa3_rt_entry { u16 prio; u16 rule_id; u16 rule_id_valid; + bool ipacm_installed; }; /** @@ -1217,6 +1228,8 @@ struct ipa3_context { struct list_head msg_list; struct list_head pull_msg_list; struct mutex msg_lock; + struct list_head msg_wlan_client_list; + struct mutex msg_wlan_client_lock; wait_queue_head_t msg_waitq; enum ipa_hw_type ipa_hw_type; enum ipa3_hw_mode ipa3_hw_mode; @@ -1591,13 +1604,15 @@ int ipa3_cfg_ep_ctrl(u32 clnt_hdl, const struct ipa_ep_cfg_ctrl *ep_ctrl); */ int ipa3_add_hdr(struct ipa_ioc_add_hdr *hdrs); +int ipa3_add_hdr_usr(struct ipa_ioc_add_hdr *hdrs, bool by_user); + int ipa3_del_hdr(struct ipa_ioc_del_hdr *hdls); int ipa3_del_hdr_by_user(struct ipa_ioc_del_hdr *hdls, bool by_user); int ipa3_commit_hdr(void); -int ipa3_reset_hdr(void); +int ipa3_reset_hdr(bool user_only); int ipa3_get_hdr(struct ipa_ioc_get_hdr *lookup); @@ -1608,7 +1623,8 @@ int ipa3_copy_hdr(struct ipa_ioc_copy_hdr *copy); /* * Header Processing Context */ -int ipa3_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs); +int ipa3_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs, + bool user_only); int ipa3_del_hdr_proc_ctx(struct ipa_ioc_del_hdr_proc_ctx *hdls); @@ -1620,6 +1636,9 @@ int ipa3_del_hdr_proc_ctx_by_user(struct ipa_ioc_del_hdr_proc_ctx *hdls, */ int ipa3_add_rt_rule(struct ipa_ioc_add_rt_rule *rules); +int ipa3_add_rt_rule_usr(struct ipa_ioc_add_rt_rule *rules, + bool user_only); + int ipa3_add_rt_rule_ext(struct ipa_ioc_add_rt_rule_ext *rules); int ipa3_add_rt_rule_after(struct ipa_ioc_add_rt_rule_after *rules); @@ -1628,7 +1647,7 @@ int ipa3_del_rt_rule(struct ipa_ioc_del_rt_rule *hdls); int ipa3_commit_rt(enum ipa_ip_type ip); -int ipa3_reset_rt(enum ipa_ip_type ip); +int ipa3_reset_rt(enum ipa_ip_type ip, bool user_only); int ipa3_get_rt_tbl(struct ipa_ioc_get_rt_tbl *lookup); @@ -1643,6 +1662,9 @@ int ipa3_mdfy_rt_rule(struct ipa_ioc_mdfy_rt_rule *rules); */ int ipa3_add_flt_rule(struct ipa_ioc_add_flt_rule *rules); +int ipa3_add_flt_rule_usr(struct ipa_ioc_add_flt_rule *rules, + bool user_only); + int ipa3_add_flt_rule_after(struct ipa_ioc_add_flt_rule_after *rules); int ipa3_del_flt_rule(struct ipa_ioc_del_flt_rule *hdls); @@ -1651,7 +1673,7 @@ int ipa3_mdfy_flt_rule(struct ipa_ioc_mdfy_flt_rule *rules); int ipa3_commit_flt(enum ipa_ip_type ip); -int ipa3_reset_flt(enum ipa_ip_type ip); +int ipa3_reset_flt(enum ipa_ip_type ip, bool user_only); /* * NAT @@ -1672,6 +1694,7 @@ int ipa3_del_nat_table(struct ipa_ioc_nat_ipv6ct_table_del *del); */ int ipa3_send_msg(struct ipa_msg_meta *meta, void *buff, ipa_msg_free_fn callback); +int ipa3_resend_wlan_msg(void); int ipa3_register_pull_msg(struct ipa_msg_meta *meta, ipa_msg_pull_fn callback); int ipa3_deregister_pull_msg(struct ipa_msg_meta *meta); @@ -1704,7 +1727,7 @@ int ipa3_tx_dp(enum ipa_client_type dst, struct sk_buff *skb, * To transfer multiple data packets * While passing the data descriptor list, the anchor node * should be of type struct ipa_tx_data_desc not list_head -*/ + */ int ipa3_tx_dp_mul(enum ipa_client_type dst, struct ipa_tx_data_desc *data_desc); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c b/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c index 76f37162f495..2039c1ba0a3c 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -13,6 +13,7 @@ #include #include #include "ipa_i.h" +#include struct ipa3_intf { char name[IPA_RESOURCE_NAME_MAX]; @@ -387,6 +388,108 @@ static void ipa3_send_msg_free(void *buff, u32 len, u32 type) kfree(buff); } +static int wlan_msg_process(struct ipa_msg_meta *meta, void *buff) +{ + struct ipa3_push_msg *msg_dup; + struct ipa_wlan_msg_ex *event_ex_cur_con = NULL; + struct ipa_wlan_msg_ex *event_ex_list = NULL; + struct ipa_wlan_msg *event_ex_cur_discon = NULL; + void *data_dup = NULL; + struct ipa3_push_msg *entry; + struct ipa3_push_msg *next; + int cnt = 0, total = 0, max = 0; + uint8_t mac[IPA_MAC_ADDR_SIZE]; + uint8_t mac2[IPA_MAC_ADDR_SIZE]; + + if (meta->msg_type == WLAN_CLIENT_CONNECT_EX) { + /* debug print */ + event_ex_cur_con = buff; + for (cnt = 0; cnt < event_ex_cur_con->num_of_attribs; cnt++) { + if (event_ex_cur_con->attribs[cnt].attrib_type == + WLAN_HDR_ATTRIB_MAC_ADDR) { + IPADBG("%02x:%02x:%02x:%02x:%02x:%02x,(%d)\n", + event_ex_cur_con->attribs[cnt].u.mac_addr[0], + event_ex_cur_con->attribs[cnt].u.mac_addr[1], + event_ex_cur_con->attribs[cnt].u.mac_addr[2], + event_ex_cur_con->attribs[cnt].u.mac_addr[3], + event_ex_cur_con->attribs[cnt].u.mac_addr[4], + event_ex_cur_con->attribs[cnt].u.mac_addr[5], + meta->msg_type); + } + } + + mutex_lock(&ipa3_ctx->msg_wlan_client_lock); + msg_dup = kzalloc(sizeof(struct ipa3_push_msg), GFP_KERNEL); + if (msg_dup == NULL) { + IPAERR("fail to alloc ipa_msg container\n"); + return -ENOMEM; + } + msg_dup->meta = *meta; + if (meta->msg_len > 0 && buff) { + data_dup = kmalloc(meta->msg_len, GFP_KERNEL); + if (data_dup == NULL) { + IPAERR("fail to alloc data_dup container\n"); + kfree(msg_dup); + return -ENOMEM; + } + memcpy(data_dup, buff, meta->msg_len); + msg_dup->buff = data_dup; + msg_dup->callback = ipa3_send_msg_free; + } + list_add_tail(&msg_dup->link, &ipa3_ctx->msg_wlan_client_list); + mutex_unlock(&ipa3_ctx->msg_wlan_client_lock); + } + + /* remove the cache */ + if (meta->msg_type == WLAN_CLIENT_DISCONNECT) { + /* debug print */ + event_ex_cur_discon = buff; + IPADBG("Mac %02x:%02x:%02x:%02x:%02x:%02x,msg %d\n", + event_ex_cur_discon->mac_addr[0], + event_ex_cur_discon->mac_addr[1], + event_ex_cur_discon->mac_addr[2], + event_ex_cur_discon->mac_addr[3], + event_ex_cur_discon->mac_addr[4], + event_ex_cur_discon->mac_addr[5], + meta->msg_type); + memcpy(mac2, + event_ex_cur_discon->mac_addr, + sizeof(mac2)); + + mutex_lock(&ipa3_ctx->msg_wlan_client_lock); + list_for_each_entry_safe(entry, next, + &ipa3_ctx->msg_wlan_client_list, + link) { + event_ex_list = entry->buff; + max = event_ex_list->num_of_attribs; + for (cnt = 0; cnt < max; cnt++) { + memcpy(mac, + event_ex_list->attribs[cnt].u.mac_addr, + sizeof(mac)); + if (event_ex_list->attribs[cnt].attrib_type == + WLAN_HDR_ATTRIB_MAC_ADDR) { + pr_debug("%02x:%02x:%02x:%02x:%02x:%02x\n", + mac[0], mac[1], mac[2], + mac[3], mac[4], mac[5]); + + /* compare to delete one*/ + if (memcmp(mac2, + mac, + sizeof(mac)) == 0) { + IPADBG("clean %d\n", total); + list_del(&entry->link); + kfree(entry); + break; + } + } + } + total++; + } + mutex_unlock(&ipa3_ctx->msg_wlan_client_lock); + } + return 0; +} + /** * ipa3_send_msg() - Send "message" from kernel client to IPA driver * @meta: [in] message meta-data @@ -409,7 +512,7 @@ int ipa3_send_msg(struct ipa_msg_meta *meta, void *buff, void *data = NULL; if (meta == NULL || (buff == NULL && callback != NULL) || - (buff != NULL && callback == NULL)) { + (buff != NULL && callback == NULL) || buff == NULL) { IPAERR_RL("invalid param meta=%p buff=%p, callback=%p\n", meta, buff, callback); return -EINVAL; @@ -441,6 +544,11 @@ int ipa3_send_msg(struct ipa_msg_meta *meta, void *buff, mutex_lock(&ipa3_ctx->msg_lock); list_add_tail(&msg->link, &ipa3_ctx->msg_list); + /* support for softap client event cache */ + if (wlan_msg_process(meta, buff)) + IPAERR("wlan_msg_process failed\n"); + + /* unlock only after process */ mutex_unlock(&ipa3_ctx->msg_lock); IPA_STATS_INC_CNT(ipa3_ctx->stats.msg_w[meta->msg_type]); @@ -451,6 +559,73 @@ int ipa3_send_msg(struct ipa_msg_meta *meta, void *buff, return 0; } +/** + * ipa3_resend_wlan_msg() - Resend cached "message" to IPACM + * + * resend wlan client connect events to user-space + * + * Returns: 0 on success, negative on failure + * + * Note: Should not be called from atomic context + */ +int ipa3_resend_wlan_msg(void) +{ + struct ipa_wlan_msg_ex *event_ex_list = NULL; + struct ipa3_push_msg *entry; + struct ipa3_push_msg *next; + int cnt = 0, total = 0; + struct ipa3_push_msg *msg; + void *data = NULL; + + IPADBG("\n"); + + mutex_lock(&ipa3_ctx->msg_wlan_client_lock); + list_for_each_entry_safe(entry, next, &ipa3_ctx->msg_wlan_client_list, + link) { + + event_ex_list = entry->buff; + for (cnt = 0; cnt < event_ex_list->num_of_attribs; cnt++) { + if (event_ex_list->attribs[cnt].attrib_type == + WLAN_HDR_ATTRIB_MAC_ADDR) { + IPADBG("%d-Mac %02x:%02x:%02x:%02x:%02x:%02x\n", + total, + event_ex_list->attribs[cnt].u.mac_addr[0], + event_ex_list->attribs[cnt].u.mac_addr[1], + event_ex_list->attribs[cnt].u.mac_addr[2], + event_ex_list->attribs[cnt].u.mac_addr[3], + event_ex_list->attribs[cnt].u.mac_addr[4], + event_ex_list->attribs[cnt].u.mac_addr[5]); + } + } + + msg = kzalloc(sizeof(struct ipa3_push_msg), GFP_KERNEL); + if (msg == NULL) { + IPAERR("fail to alloc ipa_msg container\n"); + mutex_unlock(&ipa3_ctx->msg_wlan_client_lock); + return -ENOMEM; + } + msg->meta = entry->meta; + data = kmalloc(entry->meta.msg_len, GFP_KERNEL); + if (data == NULL) { + IPAERR("fail to alloc data container\n"); + kfree(msg); + mutex_unlock(&ipa3_ctx->msg_wlan_client_lock); + return -ENOMEM; + } + memcpy(data, entry->buff, entry->meta.msg_len); + msg->buff = data; + msg->callback = ipa3_send_msg_free; + mutex_lock(&ipa3_ctx->msg_lock); + list_add_tail(&msg->link, &ipa3_ctx->msg_list); + mutex_unlock(&ipa3_ctx->msg_lock); + wake_up(&ipa3_ctx->msg_waitq); + + total++; + } + mutex_unlock(&ipa3_ctx->msg_wlan_client_lock); + return 0; +} + /** * ipa3_register_pull_msg() - register pull message type * @meta: [in] message meta-data diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c index c0aef7e0ce15..6b90abf787b9 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c @@ -605,6 +605,14 @@ int ipa3_qmi_filter_request_send(struct ipa_install_fltr_rule_req_msg_v01 *req) int rc; int i; + /* check if modem up */ + if (!ipa3_qmi_indication_fin || + !ipa3_qmi_modem_init_fin || + !ipa_q6_clnt) { + IPAWANDBG("modem QMI haven't up yet\n"); + return -EINVAL; + } + /* check if the filter rules from IPACM is valid */ if (req->filter_spec_list_len == 0) IPAWANDBG("IPACM pass zero rules to Q6\n"); @@ -688,6 +696,14 @@ int ipa3_qmi_filter_request_ex_send( int rc; int i; + /* check if modem up */ + if (!ipa3_qmi_indication_fin || + !ipa3_qmi_modem_init_fin || + !ipa_q6_clnt) { + IPAWANDBG("modem QMI haven't up yet\n"); + return -EINVAL; + } + /* check if the filter rules from IPACM is valid */ if (req->filter_spec_ex_list_len == 0) { IPAWANDBG("IPACM pass zero rules to Q6\n"); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c index fd455f72e09e..0cfe7f92aff7 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c @@ -940,7 +940,7 @@ static int __ipa_create_rt_entry(struct ipa3_rt_entry **entry, const struct ipa_rt_rule *rule, struct ipa3_rt_tbl *tbl, struct ipa3_hdr_entry *hdr, struct ipa3_hdr_proc_ctx_entry *proc_ctx, - u16 rule_id) + u16 rule_id, bool user) { int id; @@ -967,6 +967,7 @@ static int __ipa_create_rt_entry(struct ipa3_rt_entry **entry, } } (*(entry))->rule_id = id; + (*(entry))->ipacm_installed = user; return 0; @@ -1012,7 +1013,7 @@ ipa_insert_failed: static int __ipa_add_rt_rule(enum ipa_ip_type ip, const char *name, const struct ipa_rt_rule *rule, u8 at_rear, u32 *rule_hdl, - u16 rule_id) + u16 rule_id, bool user) { struct ipa3_rt_tbl *tbl; struct ipa3_rt_entry *entry; @@ -1041,7 +1042,7 @@ static int __ipa_add_rt_rule(enum ipa_ip_type ip, const char *name, } if (__ipa_create_rt_entry(&entry, rule, tbl, hdr, proc_ctx, - rule_id)) + rule_id, user)) goto error; if (at_rear) @@ -1072,7 +1073,7 @@ static int __ipa_add_rt_rule_after(struct ipa3_rt_tbl *tbl, if (__ipa_rt_validate_hndls(rule, &hdr, &proc_ctx)) goto error; - if (__ipa_create_rt_entry(&entry, rule, tbl, hdr, proc_ctx, 0)) + if (__ipa_create_rt_entry(&entry, rule, tbl, hdr, proc_ctx, 0, true)) goto error; list_add(&entry->link, &((*add_after_entry)->link)); @@ -1101,7 +1102,23 @@ error: * * Note: Should not be called from atomic context */ + int ipa3_add_rt_rule(struct ipa_ioc_add_rt_rule *rules) +{ + return ipa3_add_rt_rule_usr(rules, false); +} +/** + * ipa3_add_rt_rule_usr() - Add the specified routing rules to SW and optionally + * commit to IPA HW + * @rules: [inout] set of routing rules to add + * @user_only: [in] indicate installed by userspace module + * + * Returns: 0 on success, negative on failure + * + * Note: Should not be called from atomic context + */ + +int ipa3_add_rt_rule_usr(struct ipa_ioc_add_rt_rule *rules, bool user_only) { int i; int ret; @@ -1117,7 +1134,8 @@ int ipa3_add_rt_rule(struct ipa_ioc_add_rt_rule *rules) &rules->rules[i].rule, rules->rules[i].at_rear, &rules->rules[i].rt_rule_hdl, - 0)) { + 0, + user_only)) { IPAERR("failed to add rt rule %d\n", i); rules->rules[i].status = IPA_RT_STATUS_OF_ADD_FAILED; } else { @@ -1162,7 +1180,7 @@ int ipa3_add_rt_rule_ext(struct ipa_ioc_add_rt_rule_ext *rules) &rules->rules[i].rule, rules->rules[i].at_rear, &rules->rules[i].rt_rule_hdl, - rules->rules[i].rule_id)) { + rules->rules[i].rule_id, true)) { IPAERR("failed to add rt rule %d\n", i); rules->rules[i].status = IPA_RT_STATUS_OF_ADD_FAILED; } else { @@ -1439,13 +1457,14 @@ bail: /** * ipa3_reset_rt() - reset the current SW routing table of specified type * (does not commit to HW) - * @ip: The family of routing tables + * @ip: [in] The family of routing tables + * @user_only: [in] indicate delete rules installed by userspace * * Returns: 0 on success, negative on failure * * Note: Should not be called from atomic context */ -int ipa3_reset_rt(enum ipa_ip_type ip) +int ipa3_reset_rt(enum ipa_ip_type ip, bool user_only) { struct ipa3_rt_tbl *tbl; struct ipa3_rt_tbl *tbl_next; @@ -1455,6 +1474,7 @@ int ipa3_reset_rt(enum ipa_ip_type ip) struct ipa3_rt_tbl_set *rset; u32 apps_start_idx; int id; + bool tbl_user = false; if (ip >= IPA_IP_MAX) { IPAERR_RL("bad parm\n"); @@ -1472,7 +1492,7 @@ int ipa3_reset_rt(enum ipa_ip_type ip) * issue a reset on the filtering module of same IP type since * filtering rules point to routing tables */ - if (ipa3_reset_flt(ip)) + if (ipa3_reset_flt(ip, user_only)) IPAERR_RL("fail to reset flt ip=%d\n", ip); set = &ipa3_ctx->rt_tbl_set[ip]; @@ -1480,6 +1500,7 @@ int ipa3_reset_rt(enum ipa_ip_type ip) mutex_lock(&ipa3_ctx->lock); IPADBG("reset rt ip=%d\n", ip); list_for_each_entry_safe(tbl, tbl_next, &set->head_rt_tbl_list, link) { + tbl_user = false; list_for_each_entry_safe(rule, rule_next, &tbl->head_rt_rule_list, link) { if (ipa3_id_find(rule->id) == NULL) { @@ -1488,6 +1509,12 @@ int ipa3_reset_rt(enum ipa_ip_type ip) return -EFAULT; } + /* indicate if tbl used for user-specified rules*/ + if (rule->ipacm_installed) { + IPADBG("tbl_user %d, tbl-index %d\n", + tbl_user, tbl->id); + tbl_user = true; + } /* * for the "default" routing tbl, remove all but the * last rule @@ -1495,19 +1522,23 @@ int ipa3_reset_rt(enum ipa_ip_type ip) if (tbl->idx == apps_start_idx && tbl->rule_cnt == 1) continue; - list_del(&rule->link); - tbl->rule_cnt--; - if (rule->hdr) - __ipa3_release_hdr(rule->hdr->id); - else if (rule->proc_ctx) - __ipa3_release_hdr_proc_ctx(rule->proc_ctx->id); - rule->cookie = 0; - idr_remove(&tbl->rule_ids, rule->rule_id); - id = rule->id; - kmem_cache_free(ipa3_ctx->rt_rule_cache, rule); + if (!user_only || + rule->ipacm_installed) { + list_del(&rule->link); + tbl->rule_cnt--; + if (rule->hdr) + __ipa3_release_hdr(rule->hdr->id); + else if (rule->proc_ctx) + __ipa3_release_hdr_proc_ctx( + rule->proc_ctx->id); + rule->cookie = 0; + idr_remove(&tbl->rule_ids, rule->rule_id); + id = rule->id; + kmem_cache_free(ipa3_ctx->rt_rule_cache, rule); - /* remove the handle from the database */ - ipa3_id_remove(id); + /* remove the handle from the database */ + ipa3_id_remove(id); + } } if (ipa3_id_find(tbl->id) == NULL) { @@ -1519,26 +1550,30 @@ int ipa3_reset_rt(enum ipa_ip_type ip) /* do not remove the "default" routing tbl which has index 0 */ if (tbl->idx != apps_start_idx) { - idr_destroy(&tbl->rule_ids); - if (tbl->in_sys[IPA_RULE_HASHABLE] || - tbl->in_sys[IPA_RULE_NON_HASHABLE]) { - list_move(&tbl->link, &rset->head_rt_tbl_list); - clear_bit(tbl->idx, + if (!user_only || tbl_user) { + idr_destroy(&tbl->rule_ids); + if (tbl->in_sys[IPA_RULE_HASHABLE] || + tbl->in_sys[IPA_RULE_NON_HASHABLE]) { + list_move(&tbl->link, + &rset->head_rt_tbl_list); + clear_bit(tbl->idx, &ipa3_ctx->rt_idx_bitmap[ip]); - set->tbl_cnt--; - IPADBG("rst sys rt tbl_idx=%d tbl_cnt=%d\n", + set->tbl_cnt--; + IPADBG("rst tbl_idx=%d cnt=%d\n", tbl->idx, set->tbl_cnt); - } else { - list_del(&tbl->link); - set->tbl_cnt--; - clear_bit(tbl->idx, + } else { + list_del(&tbl->link); + set->tbl_cnt--; + clear_bit(tbl->idx, &ipa3_ctx->rt_idx_bitmap[ip]); - IPADBG("rst rt tbl_idx=%d tbl_cnt=%d\n", + IPADBG("rst rt tbl_idx=%d tbl_cnt=%d\n", tbl->idx, set->tbl_cnt); - kmem_cache_free(ipa3_ctx->rt_tbl_cache, tbl); + kmem_cache_free(ipa3_ctx->rt_tbl_cache, + tbl); + } + /* remove the handle from the database */ + ipa3_id_remove(id); } - /* remove the handle from the database */ - ipa3_id_remove(id); } } mutex_unlock(&ipa3_ctx->lock); @@ -1653,6 +1688,7 @@ static int __ipa_mdfy_rt_rule(struct ipa_rt_rule_mdfy *rtrule) struct ipa3_hdr_proc_ctx_entry *proc_ctx = NULL; struct ipa3_hdr_entry *hdr_entry; struct ipa3_hdr_proc_ctx_entry *hdr_proc_entry; + if (rtrule->rule.hdr_hdl) { hdr = ipa3_id_find(rtrule->rule.hdr_hdl); if ((hdr == NULL) || (hdr->cookie != IPA_HDR_COOKIE)) { diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c index 74176d1aa47a..f4bce295311c 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -3153,6 +3153,7 @@ int ipa3_bind_api_controller(enum ipa_hw_type ipa_hw_type, api_ctrl->ipa_cfg_ep_holb_by_client = ipa3_cfg_ep_holb_by_client; api_ctrl->ipa_cfg_ep_ctrl = ipa3_cfg_ep_ctrl; api_ctrl->ipa_add_hdr = ipa3_add_hdr; + api_ctrl->ipa_add_hdr_usr = ipa3_add_hdr_usr; api_ctrl->ipa_del_hdr = ipa3_del_hdr; api_ctrl->ipa_commit_hdr = ipa3_commit_hdr; api_ctrl->ipa_reset_hdr = ipa3_reset_hdr; @@ -3162,6 +3163,7 @@ int ipa3_bind_api_controller(enum ipa_hw_type ipa_hw_type, api_ctrl->ipa_add_hdr_proc_ctx = ipa3_add_hdr_proc_ctx; api_ctrl->ipa_del_hdr_proc_ctx = ipa3_del_hdr_proc_ctx; api_ctrl->ipa_add_rt_rule = ipa3_add_rt_rule; + api_ctrl->ipa_add_rt_rule_usr = ipa3_add_rt_rule_usr; api_ctrl->ipa_del_rt_rule = ipa3_del_rt_rule; api_ctrl->ipa_commit_rt = ipa3_commit_rt; api_ctrl->ipa_reset_rt = ipa3_reset_rt; @@ -3170,6 +3172,7 @@ int ipa3_bind_api_controller(enum ipa_hw_type ipa_hw_type, api_ctrl->ipa_query_rt_index = ipa3_query_rt_index; api_ctrl->ipa_mdfy_rt_rule = ipa3_mdfy_rt_rule; api_ctrl->ipa_add_flt_rule = ipa3_add_flt_rule; + api_ctrl->ipa_add_flt_rule_usr = ipa3_add_flt_rule_usr; api_ctrl->ipa_del_flt_rule = ipa3_del_flt_rule; api_ctrl->ipa_mdfy_flt_rule = ipa3_mdfy_flt_rule; api_ctrl->ipa_commit_flt = ipa3_commit_flt; diff --git a/include/linux/ipa.h b/include/linux/ipa.h index a4b817c5e4fc..623d0f08cdf9 100644 --- a/include/linux/ipa.h +++ b/include/linux/ipa.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1226,11 +1226,13 @@ int ipa_cfg_ep_ctrl(u32 clnt_hdl, const struct ipa_ep_cfg_ctrl *ep_ctrl); */ int ipa_add_hdr(struct ipa_ioc_add_hdr *hdrs); +int ipa_add_hdr_usr(struct ipa_ioc_add_hdr *hdrs, bool user_only); + int ipa_del_hdr(struct ipa_ioc_del_hdr *hdls); int ipa_commit_hdr(void); -int ipa_reset_hdr(void); +int ipa_reset_hdr(bool user_only); int ipa_get_hdr(struct ipa_ioc_get_hdr *lookup); @@ -1241,7 +1243,8 @@ int ipa_copy_hdr(struct ipa_ioc_copy_hdr *copy); /* * Header Processing Context */ -int ipa_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs); +int ipa_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs, + bool user_only); int ipa_del_hdr_proc_ctx(struct ipa_ioc_del_hdr_proc_ctx *hdls); @@ -1250,11 +1253,13 @@ int ipa_del_hdr_proc_ctx(struct ipa_ioc_del_hdr_proc_ctx *hdls); */ int ipa_add_rt_rule(struct ipa_ioc_add_rt_rule *rules); +int ipa_add_rt_rule_usr(struct ipa_ioc_add_rt_rule *rules, bool user_only); + int ipa_del_rt_rule(struct ipa_ioc_del_rt_rule *hdls); int ipa_commit_rt(enum ipa_ip_type ip); -int ipa_reset_rt(enum ipa_ip_type ip); +int ipa_reset_rt(enum ipa_ip_type ip, bool user_only); int ipa_get_rt_tbl(struct ipa_ioc_get_rt_tbl *lookup); @@ -1269,13 +1274,15 @@ int ipa_mdfy_rt_rule(struct ipa_ioc_mdfy_rt_rule *rules); */ int ipa_add_flt_rule(struct ipa_ioc_add_flt_rule *rules); +int ipa_add_flt_rule_usr(struct ipa_ioc_add_flt_rule *rules, bool user_only); + int ipa_del_flt_rule(struct ipa_ioc_del_flt_rule *hdls); int ipa_mdfy_flt_rule(struct ipa_ioc_mdfy_flt_rule *rules); int ipa_commit_flt(enum ipa_ip_type ip); -int ipa_reset_flt(enum ipa_ip_type ip); +int ipa_reset_flt(enum ipa_ip_type ip, bool user_only); /* * NAT @@ -1648,6 +1655,12 @@ static inline int ipa_add_hdr(struct ipa_ioc_add_hdr *hdrs) return -EPERM; } +static inline int ipa_add_hdr_usr(struct ipa_ioc_add_hdr *hdrs, + bool user_only) +{ + return -EPERM; +} + static inline int ipa_del_hdr(struct ipa_ioc_del_hdr *hdls) { return -EPERM; @@ -1658,7 +1671,7 @@ static inline int ipa_commit_hdr(void) return -EPERM; } -static inline int ipa_reset_hdr(void) +static inline int ipa_reset_hdr(bool user_only) { return -EPERM; } @@ -1682,7 +1695,8 @@ static inline int ipa_copy_hdr(struct ipa_ioc_copy_hdr *copy) * Header Processing Context */ static inline int ipa_add_hdr_proc_ctx( - struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs) + struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs, + bool user_only) { return -EPERM; } @@ -1699,6 +1713,12 @@ static inline int ipa_add_rt_rule(struct ipa_ioc_add_rt_rule *rules) return -EPERM; } +static inline int ipa_add_rt_rule_usr(struct ipa_ioc_add_rt_rule *rules, + bool user_only) +{ + return -EPERM; +} + static inline int ipa_del_rt_rule(struct ipa_ioc_del_rt_rule *hdls) { return -EPERM; @@ -1709,7 +1729,7 @@ static inline int ipa_commit_rt(enum ipa_ip_type ip) return -EPERM; } -static inline int ipa_reset_rt(enum ipa_ip_type ip) +static inline int ipa_reset_rt(enum ipa_ip_type ip, bool user_only) { return -EPERM; } @@ -1742,6 +1762,12 @@ static inline int ipa_add_flt_rule(struct ipa_ioc_add_flt_rule *rules) return -EPERM; } +static inline int ipa_add_flt_rule_usr(struct ipa_ioc_add_flt_rule *rules, + bool user_only) +{ + return -EPERM; +} + static inline int ipa_del_flt_rule(struct ipa_ioc_del_flt_rule *hdls) { return -EPERM; @@ -1757,7 +1783,7 @@ static inline int ipa_commit_flt(enum ipa_ip_type ip) return -EPERM; } -static inline int ipa_reset_flt(enum ipa_ip_type ip) +static inline int ipa_reset_flt(enum ipa_ip_type ip, bool user_only) { return -EPERM; } diff --git a/include/uapi/linux/msm_ipa.h b/include/uapi/linux/msm_ipa.h index 001ef390e288..33090dd4489f 100644 --- a/include/uapi/linux/msm_ipa.h +++ b/include/uapi/linux/msm_ipa.h @@ -95,7 +95,9 @@ #define IPA_IOCTL_DEL_VLAN_IFACE 53 #define IPA_IOCTL_ADD_L2TP_VLAN_MAPPING 54 #define IPA_IOCTL_DEL_L2TP_VLAN_MAPPING 55 -#define IPA_IOCTL_MAX 56 +#define IPA_IOCTL_CLEANUP 56 +#define IPA_IOCTL_QUERY_WLAN_CLIENT 57 +#define IPA_IOCTL_MAX 58 /** * max size of the header to be inserted @@ -1912,6 +1914,10 @@ struct ipa_tether_device_info { #define IPA_IOC_DEL_L2TP_VLAN_MAPPING _IOWR(IPA_IOC_MAGIC, \ IPA_IOCTL_DEL_L2TP_VLAN_MAPPING, \ struct ipa_ioc_l2tp_vlan_mapping_info *) +#define IPA_IOC_CLEANUP _IO(IPA_IOC_MAGIC,\ + IPA_IOCTL_CLEANUP) +#define IPA_IOC_QUERY_WLAN_CLIENT _IO(IPA_IOC_MAGIC,\ + IPA_IOCTL_QUERY_WLAN_CLIENT) /* * unique magic number of the Tethering bridge ioctls */ From 88955d3b16c475332d0894f88c82c04426de46bb Mon Sep 17 00:00:00 2001 From: Paras Nagda Date: Tue, 29 May 2018 17:50:35 +0530 Subject: [PATCH 158/159] msm: vidc: Increase minimum input buffer count for HEVC decode Increase minimum input buffer count for HEVC decode to 5 to avoid hang when the DPB is not full and FW keeps waiting for FTB although sufficient ETB are being queued. CRs-Fixed: 2252419 Change-Id: Id344cd896aeac46765e250e715d14a6c835b4221 Signed-off-by: Paras Nagda --- drivers/media/platform/msm/vidc/msm_vdec.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c index 691fd2b89b5c..fc8da8dc0c2c 100644 --- a/drivers/media/platform/msm/vidc/msm_vdec.c +++ b/drivers/media/platform/msm/vidc/msm_vdec.c @@ -23,6 +23,7 @@ #define MSM_VDEC_DVC_NAME "msm_vdec_8974" #define MIN_NUM_OUTPUT_BUFFERS 4 +#define MIN_NUM_OUTPUT_BUFFERS_HEVC 5 #define MIN_NUM_CAPTURE_BUFFERS 6 #define MIN_NUM_THUMBNAIL_MODE_CAPTURE_BUFFERS 1 #define MAX_NUM_OUTPUT_BUFFERS VB2_MAX_FRAME @@ -1471,6 +1472,12 @@ static int msm_vdec_queue_setup(struct vb2_queue *q, if (*num_buffers < MIN_NUM_OUTPUT_BUFFERS || *num_buffers > MAX_NUM_OUTPUT_BUFFERS) *num_buffers = MIN_NUM_OUTPUT_BUFFERS; + + if (inst->fmts[OUTPUT_PORT].fourcc == + V4L2_PIX_FMT_HEVC && + *num_buffers < MIN_NUM_OUTPUT_BUFFERS_HEVC) + *num_buffers = MIN_NUM_OUTPUT_BUFFERS_HEVC; + for (i = 0; i < *num_planes; i++) { sizes[i] = get_frame_size(inst, &inst->fmts[OUTPUT_PORT], q->type, i); From 949999a18dad3b599da84995638765c4e3dfb7d7 Mon Sep 17 00:00:00 2001 From: Yong Ding Date: Tue, 17 Jul 2018 16:36:43 +0800 Subject: [PATCH 159/159] soc: qcom: hab: fix some NULL pointer dereference issues With this patch, some potential NULL pointer dereference issues are resolved. For example, if an invalid MMID (MultiMedia ID defined by HAB driver) is gotten but we fail to directly return with an error, the vchan variable as NULL pointer will be dereferenced. Change-Id: I92f9c5d08f99ef9db3e6a8b2ecdc0f074c8e8bff Signed-off-by: Yong Ding --- drivers/soc/qcom/hab/hab.c | 3 ++- drivers/soc/qcom/hab/qvm_comm.c | 11 ++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/soc/qcom/hab/hab.c b/drivers/soc/qcom/hab/hab.c index ef249bcba68c..53045fc601cb 100644 --- a/drivers/soc/qcom/hab/hab.c +++ b/drivers/soc/qcom/hab/hab.c @@ -283,7 +283,7 @@ struct virtual_channel *frontend_open(struct uhab_context *ctx, pr_err("vchan alloc failed\n"); ret = -ENOMEM; goto err; - } else + } /* Send Init sequence */ hab_open_request_init(&request, HAB_PAYLOAD_TYPE_INIT, pchan, @@ -667,6 +667,7 @@ int hab_vchan_open(struct uhab_context *ctx, } } else { pr_err("failed to find device, mmid %d\n", mmid); + return -ENODEV; } } diff --git a/drivers/soc/qcom/hab/qvm_comm.c b/drivers/soc/qcom/hab/qvm_comm.c index 04381232b26a..2257be007882 100644 --- a/drivers/soc/qcom/hab/qvm_comm.c +++ b/drivers/soc/qcom/hab/qvm_comm.c @@ -70,9 +70,14 @@ int physical_channel_send(struct physical_channel *pchan, struct habmm_xing_vm_stat *pstat = (struct habmm_xing_vm_stat *)payload; - do_gettimeofday(&tv); - pstat->tx_sec = tv.tv_sec; - pstat->tx_usec = tv.tv_usec; + if (pstat) { + do_gettimeofday(&tv); + pstat->tx_sec = tv.tv_sec; + pstat->tx_usec = tv.tv_usec; + } else { + spin_unlock_bh(&dev->io_lock); + return -EINVAL; + } } if (sizebytes) {