Linux v4.14

This commit is contained in:
Justin M. Forbes 2017-11-15 11:50:50 -06:00
parent d83c4aa672
commit 8d54d185ff
360 changed files with 7606 additions and 19944 deletions

View File

@ -0,0 +1,46 @@
From 37af97ef14c201b1db8dd341aabd262da23e48aa Mon Sep 17 00:00:00 2001
From: Fedora Kernel Team <kernel-team@fedoraproject.org>
Date: Mon, 30 Oct 2017 11:38:27 -0500
Subject: [PATCH] [PATCH] staging: rtl8822be: fix wrong dma unmap len
Patch fixes splat:
r8822be 0000:04:00.0: DMA-API: device driver frees DMA memory with different size
[device address=0x0000000078477000] [map size=4096 bytes] [unmap size=424 bytes]
<snip>
Call Trace:
debug_dma_unmap_page+0xa5/0xb0
? unmap_single+0x2f/0x40
_rtl8822be_send_bcn_or_cmd_packet+0x2c5/0x300 [r8822be]
? _rtl8822be_send_bcn_or_cmd_packet+0x2c5/0x300 [r8822be]
rtl8822b_halmac_cb_write_data_rsvd_page+0x51/0xc0 [r8822be]
_halmac_write_data_rsvd_page+0x22/0x30 [r8822be]
halmac_download_rsvd_page_88xx+0xee/0x1f0 [r8822be]
halmac_dlfw_to_mem_88xx+0x80/0x120 [r8822be]
halmac_download_firmware_88xx.part.47+0x477/0x600 [r8822be]
halmac_download_firmware_88xx+0x32/0x40 [r8822be]
rtl_halmac_dlfw+0x70/0x120 [r8822be]
rtl_halmac_init_hal+0x5f/0x1b0 [r8822be]
rtl8822be_hw_init+0x8a2/0x1040 [r8822be]
Signed-off-by: Stanislaw Gruszka <sgruszka at redhat.com>
---
drivers/staging/rtlwifi/rtl8822be/fw.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/staging/rtlwifi/rtl8822be/fw.c b/drivers/staging/rtlwifi/rtl8822be/fw.c
index 8e24da1..a2cc548 100644
--- a/drivers/staging/rtlwifi/rtl8822be/fw.c
+++ b/drivers/staging/rtlwifi/rtl8822be/fw.c
@@ -419,7 +419,7 @@ static bool _rtl8822be_send_bcn_or_cmd_packet(struct ieee80211_hw *hw,
dma_addr = rtlpriv->cfg->ops->get_desc(
hw, (u8 *)pbd_desc, true, HW_DESC_TXBUFF_ADDR);
- pci_unmap_single(rtlpci->pdev, dma_addr, skb->len,
+ pci_unmap_single(rtlpci->pdev, dma_addr, pskb->len,
PCI_DMA_TODEVICE);
kfree_skb(pskb);
--
2.13.6

View File

@ -0,0 +1,72 @@
From 0e9df6a74f9573409e5a2fbe29c1389188280bfc Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Thu, 5 Oct 2017 16:02:33 +0200
Subject: [PATCH] platform/x86: peaq-wmi: Add DMI check before binding to the
WMI interface
It seems that the WMI GUID used by the PEAQ 2-in-1 WMI hotkeys is not
as unique as a GUID should be and is used on some other devices too.
This is causing spurious key-press reports on these other devices.
This commits adds a DMI check to the PEAQ 2-in-1 WMI hotkeys driver to
ensure that it is actually running on a PEAQ 2-in-1, fixing the
spurious key-presses on these other devices.
BugLink: https://bugzilla.redhat.com/show_bug.cgi?id=1497861
BugLink: https://bugzilla.suse.com/attachment.cgi?id=743182
Cc: stable@vger.kernel.org
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/platform/x86/peaq-wmi.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/drivers/platform/x86/peaq-wmi.c b/drivers/platform/x86/peaq-wmi.c
index bc98ef95514a..67fa3fa32011 100644
--- a/drivers/platform/x86/peaq-wmi.c
+++ b/drivers/platform/x86/peaq-wmi.c
@@ -8,6 +8,7 @@
*/
#include <linux/acpi.h>
+#include <linux/dmi.h>
#include <linux/input-polldev.h>
#include <linux/kernel.h>
#include <linux/module.h>
@@ -64,8 +65,23 @@ static void peaq_wmi_poll(struct input_polled_dev *dev)
}
}
+/* Some other devices (Shuttle XS35) use the same WMI GUID for other purposes */
+static const struct dmi_system_id peaq_dmi_table[] = {
+ {
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "PEAQ"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "PEAQ PMM C1010 MD99187"),
+ },
+ },
+ {}
+};
+
static int __init peaq_wmi_init(void)
{
+ /* WMI GUID is not unique, also check for a DMI match */
+ if (!dmi_check_system(peaq_dmi_table))
+ return -ENODEV;
+
if (!wmi_has_guid(PEAQ_DOLBY_BUTTON_GUID))
return -ENODEV;
@@ -86,6 +101,9 @@ static int __init peaq_wmi_init(void)
static void __exit peaq_wmi_exit(void)
{
+ if (!dmi_check_system(peaq_dmi_table))
+ return;
+
if (!wmi_has_guid(PEAQ_DOLBY_BUTTON_GUID))
return;
--
2.14.2

View File

@ -1,78 +0,0 @@
From 075bb90dbb4d894938c5859e3850987238db9cd8 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Fri, 11 Aug 2017 22:30:55 +0200
Subject: [PATCH 1/2] power: supply: max17042_battery: Add support for ACPI
enumeration
Some x86 devices enumerate a max17047 fuel-gauge through a MAX17047
ACPI firmware-node, add support for this.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/power/supply/max17042_battery.c | 22 +++++++++++++++++++++-
1 file changed, 21 insertions(+), 1 deletion(-)
diff --git a/drivers/power/supply/max17042_battery.c b/drivers/power/supply/max17042_battery.c
index aecaaa2b0586..b2ddb7eb69c6 100644
--- a/drivers/power/supply/max17042_battery.c
+++ b/drivers/power/supply/max17042_battery.c
@@ -22,6 +22,7 @@
* This driver is based on max17040_battery.c
*/
+#include <linux/acpi.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
@@ -982,6 +983,8 @@ static int max17042_probe(struct i2c_client *client,
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
const struct power_supply_desc *max17042_desc = &max17042_psy_desc;
struct power_supply_config psy_cfg = {};
+ const struct acpi_device_id *acpi_id;
+ struct device *dev = &client->dev;
struct max17042_chip *chip;
int ret;
int i;
@@ -995,7 +998,15 @@ static int max17042_probe(struct i2c_client *client,
return -ENOMEM;
chip->client = client;
- chip->chip_type = id->driver_data;
+ if (id) {
+ chip->chip_type = id->driver_data;
+ } else {
+ acpi_id = acpi_match_device(dev->driver->acpi_match_table, dev);
+ if (!acpi_id)
+ return -ENODEV;
+
+ chip->chip_type = acpi_id->driver_data;
+ }
chip->regmap = devm_regmap_init_i2c(client, &max17042_regmap_config);
if (IS_ERR(chip->regmap)) {
dev_err(&client->dev, "Failed to initialize regmap\n");
@@ -1104,6 +1115,14 @@ static int max17042_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(max17042_pm_ops, max17042_suspend,
max17042_resume);
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id max17042_acpi_match[] = {
+ { "MAX17047", MAXIM_DEVICE_TYPE_MAX17047 },
+ { }
+};
+MODULE_DEVICE_TABLE(acpi, max17042_acpi_match);
+#endif
+
#ifdef CONFIG_OF
static const struct of_device_id max17042_dt_match[] = {
{ .compatible = "maxim,max17042" },
@@ -1125,6 +1144,7 @@ MODULE_DEVICE_TABLE(i2c, max17042_id);
static struct i2c_driver max17042_i2c_driver = {
.driver = {
.name = "max17042",
+ .acpi_match_table = ACPI_PTR(max17042_acpi_match),
.of_match_table = of_match_ptr(max17042_dt_match),
.pm = &max17042_pm_ops,
},
--
2.13.4

View File

@ -0,0 +1,118 @@
From 3b40f521aa2f42862203497a94ae77536f41ade2 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Thu, 12 Oct 2017 19:44:48 +0200
Subject: [PATCH] staging: vboxvideo: Fix reporting invalid
suggested-offset-properties
The x and y hints receives from the host are unsigned 32 bit integers and
they get set to -1 (0xffffffff) when invalid. Before this commit the
vboxvideo driver was storing them in an u16 causing the -1 to be truncated
to 65535 which, once reported to userspace, was breaking gnome 3.26+
in Wayland mode.
This commit stores the host values in 32 bit variables, removing the
truncation and checks for -1, replacing it with 0 as -1 is not a valid
suggested-offset-property value. Likewise the properties are now
initialized to 0 instead of -1, since -1 is not a valid value.
This fixes gnome 3.26+ in Wayland mode not working with the vboxvideo
driver.
Reported-by: Gianfranco Costamagna <locutusofborg@debian.org>
Cc: stable@vger.kernel.org
Cc: Michael Thayer <michael.thayer@oracle.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/staging/vboxvideo/vbox_drv.h | 8 ++++----
drivers/staging/vboxvideo/vbox_irq.c | 4 ++--
drivers/staging/vboxvideo/vbox_mode.c | 26 ++++++++++++++++++--------
3 files changed, 24 insertions(+), 14 deletions(-)
diff --git a/drivers/staging/vboxvideo/vbox_drv.h b/drivers/staging/vboxvideo/vbox_drv.h
index 4b9302703b36..eeac4f0cb2c6 100644
--- a/drivers/staging/vboxvideo/vbox_drv.h
+++ b/drivers/staging/vboxvideo/vbox_drv.h
@@ -137,8 +137,8 @@ struct vbox_connector {
char name[32];
struct vbox_crtc *vbox_crtc;
struct {
- u16 width;
- u16 height;
+ u32 width;
+ u32 height;
bool disconnected;
} mode_hint;
};
@@ -150,8 +150,8 @@ struct vbox_crtc {
unsigned int crtc_id;
u32 fb_offset;
bool cursor_enabled;
- u16 x_hint;
- u16 y_hint;
+ u32 x_hint;
+ u32 y_hint;
};
struct vbox_encoder {
diff --git a/drivers/staging/vboxvideo/vbox_irq.c b/drivers/staging/vboxvideo/vbox_irq.c
index 3ca8bec62ac4..74abdf02d9fd 100644
--- a/drivers/staging/vboxvideo/vbox_irq.c
+++ b/drivers/staging/vboxvideo/vbox_irq.c
@@ -150,8 +150,8 @@ static void vbox_update_mode_hints(struct vbox_private *vbox)
disconnected = !(hints->enabled);
crtc_id = vbox_conn->vbox_crtc->crtc_id;
- vbox_conn->mode_hint.width = hints->cx & 0x8fff;
- vbox_conn->mode_hint.height = hints->cy & 0x8fff;
+ vbox_conn->mode_hint.width = hints->cx;
+ vbox_conn->mode_hint.height = hints->cy;
vbox_conn->vbox_crtc->x_hint = hints->dx;
vbox_conn->vbox_crtc->y_hint = hints->dy;
vbox_conn->mode_hint.disconnected = disconnected;
diff --git a/drivers/staging/vboxvideo/vbox_mode.c b/drivers/staging/vboxvideo/vbox_mode.c
index 257a77830410..6f08dc966719 100644
--- a/drivers/staging/vboxvideo/vbox_mode.c
+++ b/drivers/staging/vboxvideo/vbox_mode.c
@@ -553,12 +553,22 @@ static int vbox_get_modes(struct drm_connector *connector)
++num_modes;
}
vbox_set_edid(connector, preferred_width, preferred_height);
- drm_object_property_set_value(
- &connector->base, vbox->dev->mode_config.suggested_x_property,
- vbox_connector->vbox_crtc->x_hint);
- drm_object_property_set_value(
- &connector->base, vbox->dev->mode_config.suggested_y_property,
- vbox_connector->vbox_crtc->y_hint);
+
+ if (vbox_connector->vbox_crtc->x_hint != -1)
+ drm_object_property_set_value(&connector->base,
+ vbox->dev->mode_config.suggested_x_property,
+ vbox_connector->vbox_crtc->x_hint);
+ else
+ drm_object_property_set_value(&connector->base,
+ vbox->dev->mode_config.suggested_x_property, 0);
+
+ if (vbox_connector->vbox_crtc->y_hint != -1)
+ drm_object_property_set_value(&connector->base,
+ vbox->dev->mode_config.suggested_y_property,
+ vbox_connector->vbox_crtc->y_hint);
+ else
+ drm_object_property_set_value(&connector->base,
+ vbox->dev->mode_config.suggested_y_property, 0);
return num_modes;
}
@@ -640,9 +650,9 @@ static int vbox_connector_init(struct drm_device *dev,
drm_mode_create_suggested_offset_properties(dev);
drm_object_attach_property(&connector->base,
- dev->mode_config.suggested_x_property, -1);
+ dev->mode_config.suggested_x_property, 0);
drm_object_attach_property(&connector->base,
- dev->mode_config.suggested_y_property, -1);
+ dev->mode_config.suggested_y_property, 0);
drm_connector_register(connector);
drm_mode_connector_attach_encoder(connector, encoder);
--
2.14.2

View File

@ -1,80 +0,0 @@
From 27b9d46d25c873b351757c44ce523bf0ede1d08e Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Mon, 14 Aug 2017 11:02:59 +0200
Subject: [PATCH 2/2] power: supply: max17042_battery: Fix ACPI interrupt
issues
On some x86/ACPI boards the DSDT defines an ACPI event handler for
the max17047 IRQ, this causes several problems:
1) We need to share the IRQ to avoid an error getting it
2) Even of we are willing to share, we may fail to share because some
DSDTs claim it exclusivly
3) If we are unable to share the IRQ, or the IRQ is only listed as an
ACPI event source and not in the max1704 firmware node, then the
charge threshold IRQ (which is used to give an IRQ every 1 percent
charge change) becomes a problem, the ACPI event handler will not
update this to the next 1 percent threshold, so the IRQ keeps firing
and we get an IRQ storm pegging 1 CPU core.
This happens despite the max17042 driver not setting the charge
threshold because Windows uses it and leaves it set on reboot.
So if we are unable to get the IRQ we need to reprogram the
charge threshold to its disabled setting.
This commit fixes al of the above, while at it it also makes the error
msg when being unable to get the IRQ consistent with other messages.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/power/supply/max17042_battery.c | 20 +++++++++++++++-----
1 file changed, 15 insertions(+), 5 deletions(-)
diff --git a/drivers/power/supply/max17042_battery.c b/drivers/power/supply/max17042_battery.c
index b2ddb7eb69c6..18a44e4ed6ff 100644
--- a/drivers/power/supply/max17042_battery.c
+++ b/drivers/power/supply/max17042_battery.c
@@ -1050,11 +1050,18 @@ static int max17042_probe(struct i2c_client *client,
}
if (client->irq) {
+ unsigned int flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
+
+ /*
+ * On ACPI systems the IRQ may be handled by ACPI-event code,
+ * so we need to share (if the ACPI code is willing to share).
+ */
+ if (acpi_id)
+ flags |= IRQF_SHARED | IRQF_PROBE_SHARED;
+
ret = devm_request_threaded_irq(&client->dev, client->irq,
NULL,
- max17042_thread_handler,
- IRQF_TRIGGER_FALLING |
- IRQF_ONESHOT,
+ max17042_thread_handler, flags,
chip->battery->desc->name,
chip);
if (!ret) {
@@ -1064,10 +1071,13 @@ static int max17042_probe(struct i2c_client *client,
max17042_set_soc_threshold(chip, 1);
} else {
client->irq = 0;
- dev_err(&client->dev, "%s(): cannot get IRQ\n",
- __func__);
+ if (ret != -EBUSY)
+ dev_err(&client->dev, "Failed to get IRQ\n");
}
}
+ /* Not able to update the charge threshold when exceeded? -> disable */
+ if (!client->irq)
+ regmap_write(chip->regmap, MAX17042_SALRT_Th, 0xff00);
regmap_read(chip->regmap, MAX17042_STATUS, &val);
if (val & STATUS_POR_BIT) {
--
2.13.4

View File

@ -1,53 +0,0 @@
From 2a99775c336303d2efc43eab4f24b34722a28faa Mon Sep 17 00:00:00 2001
From: "Sergei A. Trusov" <sergei.a.trusov@ya.ru>
Date: Tue, 20 Jun 2017 18:08:35 +0200
Subject: [PATCH 11/16] Input: goodix: Add support for capacitive home button
On some x86 tablets with a Goodix touchscreen, the Windows logo on the
front is a capacitive home button. Touching this button results in a touch
with bit 4 of the first byte set, while only the lower 4 bits (0-3) are
used to indicate the number of touches.
Report a KEY_LEFTMETA press when this happens.
Note that the hardware might support more than one button, in which
case the "id" byte of coor_data would identify the button in question.
This is not implemented as we don't have access to hardware with
multiple buttons.
Signed-off-by: Sergei A. Trusov <sergei.a.trusov@ya.ru>
Acked-by: Bastien Nocera <hadess@hadess.net>
---
drivers/input/touchscreen/goodix.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c
index 240b16f3ee97..903137d9cf7d 100644
--- a/drivers/input/touchscreen/goodix.c
+++ b/drivers/input/touchscreen/goodix.c
@@ -267,6 +267,12 @@ static void goodix_process_events(struct goodix_ts_data *ts)
if (touch_num < 0)
return;
+ /*
+ * Bit 4 of the first byte reports the status of the capacitive
+ * Windows/Home button.
+ */
+ input_report_key(ts->input_dev, KEY_LEFTMETA, !!(point_data[0] & BIT(4)));
+
for (i = 0; i < touch_num; i++)
goodix_ts_report_touch(ts,
&point_data[1 + GOODIX_CONTACT_SIZE * i]);
@@ -612,6 +618,9 @@ static int goodix_request_input_dev(struct goodix_ts_data *ts)
ts->input_dev->id.product = ts->id;
ts->input_dev->id.version = ts->version;
+ /* Capacitive Windows/Home button on some devices */
+ input_set_capability(ts->input_dev, EV_KEY, KEY_LEFTMETA);
+
error = input_register_device(ts->input_dev);
if (error) {
dev_err(&ts->client->dev,
--
2.13.0

View File

@ -1,32 +0,0 @@
From bf3e9581e10a19b2ce77a45fe001116d269b4c7f Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Sun, 18 Jun 2017 12:47:38 +0200
Subject: [PATCH 13/16] iio: accel: bmc150: Add support for BOSC0200 ACPI
device id
Add support for the BOSC0200 ACPI device id used on some x86 tablets.
note driver_data is not set to a specific model, driver_data is not
used anyways (instead detection is done on the chip_id reg) and the
2 tablets with a BOSC0200 ACPI device id I've have 2 different chips,
one has a BMA250E, the other a BMA222E.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/iio/accel/bmc150-accel-i2c.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/iio/accel/bmc150-accel-i2c.c b/drivers/iio/accel/bmc150-accel-i2c.c
index 8ca8041267ef..f85014fbaa12 100644
--- a/drivers/iio/accel/bmc150-accel-i2c.c
+++ b/drivers/iio/accel/bmc150-accel-i2c.c
@@ -64,6 +64,7 @@ static const struct acpi_device_id bmc150_accel_acpi_match[] = {
{"BMA250E", bma250e},
{"BMA222E", bma222e},
{"BMA0280", bma280},
+ {"BOSC0200"},
{ },
};
MODULE_DEVICE_TABLE(acpi, bmc150_accel_acpi_match);
--
2.13.0

View File

@ -1,410 +0,0 @@
From bd0d7169342e47919f68e75d659968f02b62f84b Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Fri, 3 Mar 2017 23:48:50 +0100
Subject: [PATCH 15/16] i2c-cht-wc: Add Intel Cherry Trail Whiskey Cove SMBUS
controller driver
The Intel Cherry Trail Whiskey Cove PMIC does not contain a builtin
battery charger, instead boards with this PMIC use an external TI
bq24292i charger IC, which is connected to a SMBUS controller built into
the PMIC.
This commit adds an i2c-bus driver for the PMIC's builtin SMBUS
controller. The probe function for this i2c-bus will also register an
i2c-client for the TI bq24292i charger after the i2c-bus has been
registered.
Note that several device-properties are set on the client-device to
tell the bq24190 power-supply driver to integrate the Whiskey Cove PMIC
and e.g. use the PMIC's BC1.2 detection (through extcon) to determine
the maximum input current.
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
Changes in v2:
-Various style (mostly captialization and variable name) fixes
-Use device-properties instead of platform_data for the i2c_board_info
---
drivers/i2c/busses/Kconfig | 8 +
drivers/i2c/busses/Makefile | 1 +
drivers/i2c/busses/i2c-cht-wc.c | 336 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 345 insertions(+)
create mode 100644 drivers/i2c/busses/i2c-cht-wc.c
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 144cbadc7c72..18c96178b177 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -187,6 +187,14 @@ config I2C_PIIX4
This driver can also be built as a module. If so, the module
will be called i2c-piix4.
+config I2C_CHT_WC
+ tristate "Intel Cherry Trail Whiskey Cove PMIC smbus controller"
+ depends on INTEL_SOC_PMIC_CHTWC
+ help
+ If you say yes to this option, support will be included for the
+ SMBus controller found in the Intel Cherry Trail Whiskey Cove PMIC
+ found on some Intel Cherry Trail systems.
+
config I2C_NFORCE2
tristate "Nvidia nForce2, nForce3 and nForce4"
depends on PCI
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 30b60855fbcd..f6443fa44f61 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_I2C_ALI15X3) += i2c-ali15x3.o
obj-$(CONFIG_I2C_AMD756) += i2c-amd756.o
obj-$(CONFIG_I2C_AMD756_S4882) += i2c-amd756-s4882.o
obj-$(CONFIG_I2C_AMD8111) += i2c-amd8111.o
+obj-$(CONFIG_I2C_CHT_WC) += i2c-cht-wc.o
obj-$(CONFIG_I2C_I801) += i2c-i801.o
obj-$(CONFIG_I2C_ISCH) += i2c-isch.o
obj-$(CONFIG_I2C_ISMT) += i2c-ismt.o
diff --git a/drivers/i2c/busses/i2c-cht-wc.c b/drivers/i2c/busses/i2c-cht-wc.c
new file mode 100644
index 000000000000..ccf0785bcb75
--- /dev/null
+++ b/drivers/i2c/busses/i2c-cht-wc.c
@@ -0,0 +1,336 @@
+/*
+ * Intel CHT Whiskey Cove PMIC I2C Master driver
+ * Copyright (C) 2017 Hans de Goede <hdegoede@redhat.com>
+ *
+ * Based on various non upstream patches to support the CHT Whiskey Cove PMIC:
+ * Copyright (C) 2011 - 2014 Intel Corporation. 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 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 <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/mfd/intel_soc_pmic.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#define CHT_WC_I2C_CTRL 0x5e24
+#define CHT_WC_I2C_CTRL_WR BIT(0)
+#define CHT_WC_I2C_CTRL_RD BIT(1)
+#define CHT_WC_I2C_CLIENT_ADDR 0x5e25
+#define CHT_WC_I2C_REG_OFFSET 0x5e26
+#define CHT_WC_I2C_WRDATA 0x5e27
+#define CHT_WC_I2C_RDDATA 0x5e28
+
+#define CHT_WC_EXTCHGRIRQ 0x6e0a
+#define CHT_WC_EXTCHGRIRQ_CLIENT_IRQ BIT(0)
+#define CHT_WC_EXTCHGRIRQ_WRITE_IRQ BIT(1)
+#define CHT_WC_EXTCHGRIRQ_READ_IRQ BIT(2)
+#define CHT_WC_EXTCHGRIRQ_NACK_IRQ BIT(3)
+#define CHT_WC_EXTCHGRIRQ_ADAP_IRQMASK ((u8)GENMASK(3, 1))
+#define CHT_WC_EXTCHGRIRQ_MSK 0x6e17
+
+struct cht_wc_i2c_adap {
+ struct i2c_adapter adapter;
+ wait_queue_head_t wait;
+ struct irq_chip irqchip;
+ struct mutex irqchip_lock;
+ struct regmap *regmap;
+ struct irq_domain *irq_domain;
+ struct i2c_client *client;
+ int client_irq;
+ u8 irq_mask;
+ u8 old_irq_mask;
+ bool nack;
+ bool done;
+};
+
+static irqreturn_t cht_wc_i2c_adap_thread_handler(int id, void *data)
+{
+ struct cht_wc_i2c_adap *adap = data;
+ int ret, reg;
+
+ /* Read IRQs */
+ ret = regmap_read(adap->regmap, CHT_WC_EXTCHGRIRQ, &reg);
+ if (ret) {
+ dev_err(&adap->adapter.dev, "Error reading extchgrirq reg\n");
+ return IRQ_NONE;
+ }
+
+ reg &= ~adap->irq_mask;
+
+ /*
+ * Immediately ack IRQs, so that if new IRQs arrives while we're
+ * handling the previous ones our irq will re-trigger when we're done.
+ */
+ ret = regmap_write(adap->regmap, CHT_WC_EXTCHGRIRQ, reg);
+ if (ret)
+ dev_err(&adap->adapter.dev, "Error writing extchgrirq reg\n");
+
+ /*
+ * Do NOT use handle_nested_irq here, the client irq handler will
+ * likely want to do i2c transfers and the i2c controller uses this
+ * interrupt handler as well, so running the client irq handler from
+ * this thread will cause things to lock up.
+ */
+ if (reg & CHT_WC_EXTCHGRIRQ_CLIENT_IRQ) {
+ /*
+ * generic_handle_irq expects local IRQs to be disabled
+ * as normally it is called from interrupt context.
+ */
+ local_irq_disable();
+ generic_handle_irq(adap->client_irq);
+ local_irq_enable();
+ }
+
+ if (reg & CHT_WC_EXTCHGRIRQ_ADAP_IRQMASK) {
+ adap->nack = !!(reg & CHT_WC_EXTCHGRIRQ_NACK_IRQ);
+ adap->done = true;
+ wake_up(&adap->wait);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static u32 cht_wc_i2c_adap_master_func(struct i2c_adapter *adap)
+{
+ /* This i2c adapter only supports SMBUS byte transfers */
+ return I2C_FUNC_SMBUS_BYTE_DATA;
+}
+
+static int cht_wc_i2c_adap_smbus_xfer(struct i2c_adapter *_adap, u16 addr,
+ unsigned short flags, char read_write,
+ u8 command, int size,
+ union i2c_smbus_data *data)
+{
+ struct cht_wc_i2c_adap *adap = i2c_get_adapdata(_adap);
+ int ret, reg;
+
+ adap->nack = false;
+ adap->done = false;
+
+ ret = regmap_write(adap->regmap, CHT_WC_I2C_CLIENT_ADDR, addr);
+ if (ret)
+ return ret;
+
+ if (read_write == I2C_SMBUS_WRITE) {
+ ret = regmap_write(adap->regmap, CHT_WC_I2C_WRDATA, data->byte);
+ if (ret)
+ return ret;
+ }
+
+ ret = regmap_write(adap->regmap, CHT_WC_I2C_REG_OFFSET, command);
+ if (ret)
+ return ret;
+
+ ret = regmap_write(adap->regmap, CHT_WC_I2C_CTRL,
+ (read_write == I2C_SMBUS_WRITE) ?
+ CHT_WC_I2C_CTRL_WR : CHT_WC_I2C_CTRL_RD);
+ if (ret)
+ return ret;
+
+ /* 3 second timeout, during cable plug the PMIC responds quite slow */
+ ret = wait_event_timeout(adap->wait, adap->done, 3 * HZ);
+ if (ret == 0)
+ return -ETIMEDOUT;
+ if (adap->nack)
+ return -EIO;
+
+ if (read_write == I2C_SMBUS_READ) {
+ ret = regmap_read(adap->regmap, CHT_WC_I2C_RDDATA, &reg);
+ if (ret)
+ return ret;
+
+ data->byte = reg;
+ }
+
+ return 0;
+}
+
+static const struct i2c_algorithm cht_wc_i2c_adap_algo = {
+ .functionality = cht_wc_i2c_adap_master_func,
+ .smbus_xfer = cht_wc_i2c_adap_smbus_xfer,
+};
+
+/**** irqchip for the client connected to the extchgr i2c adapter ****/
+static void cht_wc_i2c_irq_lock(struct irq_data *data)
+{
+ struct cht_wc_i2c_adap *adap = irq_data_get_irq_chip_data(data);
+
+ mutex_lock(&adap->irqchip_lock);
+}
+
+static void cht_wc_i2c_irq_sync_unlock(struct irq_data *data)
+{
+ struct cht_wc_i2c_adap *adap = irq_data_get_irq_chip_data(data);
+ int ret;
+
+ if (adap->irq_mask != adap->old_irq_mask) {
+ ret = regmap_write(adap->regmap, CHT_WC_EXTCHGRIRQ_MSK,
+ adap->irq_mask);
+ if (ret == 0)
+ adap->old_irq_mask = adap->irq_mask;
+ else
+ dev_err(&adap->adapter.dev, "Error writing EXTCHGRIRQ_MSK\n");
+ }
+
+ mutex_unlock(&adap->irqchip_lock);
+}
+
+static void cht_wc_i2c_irq_enable(struct irq_data *data)
+{
+ struct cht_wc_i2c_adap *adap = irq_data_get_irq_chip_data(data);
+
+ adap->irq_mask &= ~CHT_WC_EXTCHGRIRQ_CLIENT_IRQ;
+}
+
+static void cht_wc_i2c_irq_disable(struct irq_data *data)
+{
+ struct cht_wc_i2c_adap *adap = irq_data_get_irq_chip_data(data);
+
+ adap->irq_mask |= CHT_WC_EXTCHGRIRQ_CLIENT_IRQ;
+}
+
+static const struct irq_chip cht_wc_i2c_irq_chip = {
+ .irq_bus_lock = cht_wc_i2c_irq_lock,
+ .irq_bus_sync_unlock = cht_wc_i2c_irq_sync_unlock,
+ .irq_disable = cht_wc_i2c_irq_disable,
+ .irq_enable = cht_wc_i2c_irq_enable,
+ .name = "cht_wc_ext_chrg_irq_chip",
+};
+
+static const struct property_entry bq24190_props[] = {
+ PROPERTY_ENTRY_STRING("extcon-name", "cht_wcove_pwrsrc"),
+ PROPERTY_ENTRY_BOOL("omit-battery-class"),
+ PROPERTY_ENTRY_BOOL("disable-reset"),
+ { }
+};
+
+static int cht_wc_i2c_adap_i2c_probe(struct platform_device *pdev)
+{
+ struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent);
+ struct cht_wc_i2c_adap *adap;
+ struct i2c_board_info board_info = {
+ .type = "bq24190",
+ .addr = 0x6b,
+ .properties = bq24190_props,
+ };
+ int ret, irq;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(&pdev->dev, "Error missing irq resource\n");
+ return -EINVAL;
+ }
+
+ adap = devm_kzalloc(&pdev->dev, sizeof(*adap), GFP_KERNEL);
+ if (!adap)
+ return -ENOMEM;
+
+ init_waitqueue_head(&adap->wait);
+ mutex_init(&adap->irqchip_lock);
+ adap->irqchip = cht_wc_i2c_irq_chip;
+ adap->regmap = pmic->regmap;
+ adap->adapter.owner = THIS_MODULE;
+ adap->adapter.class = I2C_CLASS_HWMON;
+ adap->adapter.algo = &cht_wc_i2c_adap_algo;
+ strlcpy(adap->adapter.name, "PMIC I2C Adapter",
+ sizeof(adap->adapter.name));
+ adap->adapter.dev.parent = &pdev->dev;
+
+ /* Clear and activate i2c-adapter interrupts, disable client IRQ */
+ adap->old_irq_mask = adap->irq_mask = ~CHT_WC_EXTCHGRIRQ_ADAP_IRQMASK;
+ ret = regmap_write(adap->regmap, CHT_WC_EXTCHGRIRQ, ~adap->irq_mask);
+ if (ret)
+ return ret;
+
+ ret = regmap_write(adap->regmap, CHT_WC_EXTCHGRIRQ_MSK, adap->irq_mask);
+ if (ret)
+ return ret;
+
+ /* Alloc and register client IRQ */
+ adap->irq_domain = irq_domain_add_linear(pdev->dev.of_node, 1,
+ &irq_domain_simple_ops, NULL);
+ if (!adap->irq_domain)
+ return -ENOMEM;
+
+ adap->client_irq = irq_create_mapping(adap->irq_domain, 0);
+ if (!adap->client_irq) {
+ ret = -ENOMEM;
+ goto remove_irq_domain;
+ }
+
+ irq_set_chip_data(adap->client_irq, adap);
+ irq_set_chip_and_handler(adap->client_irq, &adap->irqchip,
+ handle_simple_irq);
+
+ ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+ cht_wc_i2c_adap_thread_handler,
+ IRQF_ONESHOT, "PMIC I2C Adapter", adap);
+ if (ret)
+ goto remove_irq_domain;
+
+ i2c_set_adapdata(&adap->adapter, adap);
+ ret = i2c_add_adapter(&adap->adapter);
+ if (ret)
+ goto remove_irq_domain;
+
+ board_info.irq = adap->client_irq;
+ adap->client = i2c_new_device(&adap->adapter, &board_info);
+ if (!adap->client) {
+ ret = -ENOMEM;
+ goto del_adapter;
+ }
+
+ platform_set_drvdata(pdev, adap);
+ return 0;
+
+del_adapter:
+ i2c_del_adapter(&adap->adapter);
+remove_irq_domain:
+ irq_domain_remove(adap->irq_domain);
+ return ret;
+}
+
+static int cht_wc_i2c_adap_i2c_remove(struct platform_device *pdev)
+{
+ struct cht_wc_i2c_adap *adap = platform_get_drvdata(pdev);
+
+ i2c_unregister_device(adap->client);
+ i2c_del_adapter(&adap->adapter);
+ irq_domain_remove(adap->irq_domain);
+
+ return 0;
+}
+
+static struct platform_device_id cht_wc_i2c_adap_id_table[] = {
+ { .name = "cht_wcove_ext_chgr" },
+ {},
+};
+MODULE_DEVICE_TABLE(platform, cht_wc_i2c_adap_id_table);
+
+struct platform_driver cht_wc_i2c_adap_driver = {
+ .probe = cht_wc_i2c_adap_i2c_probe,
+ .remove = cht_wc_i2c_adap_i2c_remove,
+ .driver = {
+ .name = "cht_wcove_ext_chgr",
+ },
+ .id_table = cht_wc_i2c_adap_id_table,
+};
+module_platform_driver(cht_wc_i2c_adap_driver);
+
+MODULE_DESCRIPTION("Intel CHT Whiskey Cove PMIC I2C Master driver");
+MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
+MODULE_LICENSE("GPL");
--
2.13.0

View File

@ -0,0 +1,296 @@
From patchwork Mon Nov 6 12:31:12 2017
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: [1/2] kvm: vmx: Reinstate support for CPUs without virtual NMI
From: Paolo Bonzini <pbonzini@redhat.com>
X-Patchwork-Id: 10043403
Message-Id: <1509971473-74491-2-git-send-email-pbonzini@redhat.com>
To: linux-kernel@vger.kernel.org, kvm@vger.kernel.org
Cc: rkrcmar@redhat.com, stable@vger.kernel.org
Date: Mon, 6 Nov 2017 13:31:12 +0100
This is more or less a revert of commit 2c82878b0cb3 ("KVM: VMX: require
virtual NMI support", 2017-03-27); it turns out that Core 2 Duo machines
only had virtual NMIs in some SKUs.
The revert is not trivial because in the meanwhile there have been several
fixes to nested NMI injection. Therefore, the entire vNMI state is moved
to struct loaded_vmcs.
Another change compared to before the patch is a simplification here:
if (unlikely(!cpu_has_virtual_nmis() && vmx->soft_vnmi_blocked &&
!(is_guest_mode(vcpu) && nested_cpu_has_virtual_nmis(
get_vmcs12(vcpu))))) {
The final condition here is always true (because nested_cpu_has_virtual_nmis
is always false) and is removed.
Fixes: 2c82878b0cb38fd516fd612c67852a6bbf282003
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1490803
Cc: stable@vger.kernel.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
arch/x86/kvm/vmx.c | 150 +++++++++++++++++++++++++++++++++++++----------------
1 file changed, 106 insertions(+), 44 deletions(-)
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index e6c8ffa84968..d6b3b12ae1e2 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -202,6 +202,10 @@ struct loaded_vmcs {
bool nmi_known_unmasked;
unsigned long vmcs_host_cr3; /* May not match real cr3 */
unsigned long vmcs_host_cr4; /* May not match real cr4 */
+ /* Support for vnmi-less CPUs */
+ int soft_vnmi_blocked;
+ ktime_t entry_time;
+ s64 vnmi_blocked_time;
struct list_head loaded_vmcss_on_cpu_link;
};
@@ -1291,6 +1295,11 @@ static inline bool cpu_has_vmx_invpcid(void)
SECONDARY_EXEC_ENABLE_INVPCID;
}
+static inline bool cpu_has_virtual_nmis(void)
+{
+ return vmcs_config.pin_based_exec_ctrl & PIN_BASED_VIRTUAL_NMIS;
+}
+
static inline bool cpu_has_vmx_wbinvd_exit(void)
{
return vmcs_config.cpu_based_2nd_exec_ctrl &
@@ -1348,11 +1357,6 @@ static inline bool nested_cpu_has2(struct vmcs12 *vmcs12, u32 bit)
(vmcs12->secondary_vm_exec_control & bit);
}
-static inline bool nested_cpu_has_virtual_nmis(struct vmcs12 *vmcs12)
-{
- return vmcs12->pin_based_vm_exec_control & PIN_BASED_VIRTUAL_NMIS;
-}
-
static inline bool nested_cpu_has_preemption_timer(struct vmcs12 *vmcs12)
{
return vmcs12->pin_based_vm_exec_control &
@@ -3712,9 +3716,9 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf)
&_vmexit_control) < 0)
return -EIO;
- min = PIN_BASED_EXT_INTR_MASK | PIN_BASED_NMI_EXITING |
- PIN_BASED_VIRTUAL_NMIS;
- opt = PIN_BASED_POSTED_INTR | PIN_BASED_VMX_PREEMPTION_TIMER;
+ min = PIN_BASED_EXT_INTR_MASK | PIN_BASED_NMI_EXITING;
+ opt = PIN_BASED_VIRTUAL_NMIS | PIN_BASED_POSTED_INTR |
+ PIN_BASED_VMX_PREEMPTION_TIMER;
if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_PINBASED_CTLS,
&_pin_based_exec_control) < 0)
return -EIO;
@@ -5669,7 +5673,8 @@ static void enable_irq_window(struct kvm_vcpu *vcpu)
static void enable_nmi_window(struct kvm_vcpu *vcpu)
{
- if (vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & GUEST_INTR_STATE_STI) {
+ if (!cpu_has_virtual_nmis() ||
+ vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & GUEST_INTR_STATE_STI) {
enable_irq_window(vcpu);
return;
}
@@ -5709,6 +5714,19 @@ static void vmx_inject_nmi(struct kvm_vcpu *vcpu)
{
struct vcpu_vmx *vmx = to_vmx(vcpu);
+ if (!cpu_has_virtual_nmis()) {
+ /*
+ * Tracking the NMI-blocked state in software is built upon
+ * finding the next open IRQ window. This, in turn, depends on
+ * well-behaving guests: They have to keep IRQs disabled at
+ * least as long as the NMI handler runs. Otherwise we may
+ * cause NMI nesting, maybe breaking the guest. But as this is
+ * highly unlikely, we can live with the residual risk.
+ */
+ vmx->loaded_vmcs->soft_vnmi_blocked = 1;
+ vmx->loaded_vmcs->vnmi_blocked_time = 0;
+ }
+
++vcpu->stat.nmi_injections;
vmx->loaded_vmcs->nmi_known_unmasked = false;
@@ -5727,6 +5745,8 @@ static bool vmx_get_nmi_mask(struct kvm_vcpu *vcpu)
struct vcpu_vmx *vmx = to_vmx(vcpu);
bool masked;
+ if (!cpu_has_virtual_nmis())
+ return vmx->loaded_vmcs->soft_vnmi_blocked;
if (vmx->loaded_vmcs->nmi_known_unmasked)
return false;
masked = vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & GUEST_INTR_STATE_NMI;
@@ -5738,13 +5758,20 @@ static void vmx_set_nmi_mask(struct kvm_vcpu *vcpu, bool masked)
{
struct vcpu_vmx *vmx = to_vmx(vcpu);
- vmx->loaded_vmcs->nmi_known_unmasked = !masked;
- if (masked)
- vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO,
- GUEST_INTR_STATE_NMI);
- else
- vmcs_clear_bits(GUEST_INTERRUPTIBILITY_INFO,
- GUEST_INTR_STATE_NMI);
+ if (!cpu_has_virtual_nmis()) {
+ if (vmx->loaded_vmcs->soft_vnmi_blocked != masked) {
+ vmx->loaded_vmcs->soft_vnmi_blocked = masked;
+ vmx->loaded_vmcs->vnmi_blocked_time = 0;
+ }
+ } else {
+ vmx->loaded_vmcs->nmi_known_unmasked = !masked;
+ if (masked)
+ vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO,
+ GUEST_INTR_STATE_NMI);
+ else
+ vmcs_clear_bits(GUEST_INTERRUPTIBILITY_INFO,
+ GUEST_INTR_STATE_NMI);
+ }
}
static int vmx_nmi_allowed(struct kvm_vcpu *vcpu)
@@ -5752,6 +5779,10 @@ static int vmx_nmi_allowed(struct kvm_vcpu *vcpu)
if (to_vmx(vcpu)->nested.nested_run_pending)
return 0;
+ if (!cpu_has_virtual_nmis() &&
+ to_vmx(vcpu)->loaded_vmcs->soft_vnmi_blocked)
+ return 0;
+
return !(vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) &
(GUEST_INTR_STATE_MOV_SS | GUEST_INTR_STATE_STI
| GUEST_INTR_STATE_NMI));
@@ -6479,6 +6510,7 @@ static int handle_ept_violation(struct kvm_vcpu *vcpu)
* AAK134, BY25.
*/
if (!(to_vmx(vcpu)->idt_vectoring_info & VECTORING_INFO_VALID_MASK) &&
+ cpu_has_virtual_nmis() &&
(exit_qualification & INTR_INFO_UNBLOCK_NMI))
vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO, GUEST_INTR_STATE_NMI);
@@ -6965,7 +6997,7 @@ static struct loaded_vmcs *nested_get_current_vmcs02(struct vcpu_vmx *vmx)
}
/* Create a new VMCS */
- item = kmalloc(sizeof(struct vmcs02_list), GFP_KERNEL);
+ item = kzalloc(sizeof(struct vmcs02_list), GFP_KERNEL);
if (!item)
return NULL;
item->vmcs02.vmcs = alloc_vmcs();
@@ -7982,6 +8014,7 @@ static int handle_pml_full(struct kvm_vcpu *vcpu)
* "blocked by NMI" bit has to be set before next VM entry.
*/
if (!(to_vmx(vcpu)->idt_vectoring_info & VECTORING_INFO_VALID_MASK) &&
+ cpu_has_virtual_nmis() &&
(exit_qualification & INTR_INFO_UNBLOCK_NMI))
vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO,
GUEST_INTR_STATE_NMI);
@@ -8826,6 +8859,25 @@ static int vmx_handle_exit(struct kvm_vcpu *vcpu)
return 0;
}
+ if (unlikely(!cpu_has_virtual_nmis() &&
+ vmx->loaded_vmcs->soft_vnmi_blocked)) {
+ if (vmx_interrupt_allowed(vcpu)) {
+ vmx->loaded_vmcs->soft_vnmi_blocked = 0;
+ } else if (vmx->loaded_vmcs->vnmi_blocked_time > 1000000000LL &&
+ vcpu->arch.nmi_pending) {
+ /*
+ * This CPU don't support us in finding the end of an
+ * NMI-blocked window if the guest runs with IRQs
+ * disabled. So we pull the trigger after 1 s of
+ * futile waiting, but inform the user about this.
+ */
+ printk(KERN_WARNING "%s: Breaking out of NMI-blocked "
+ "state on VCPU %d after 1 s timeout\n",
+ __func__, vcpu->vcpu_id);
+ vmx->loaded_vmcs->soft_vnmi_blocked = 0;
+ }
+ }
+
if (exit_reason < kvm_vmx_max_exit_handlers
&& kvm_vmx_exit_handlers[exit_reason])
return kvm_vmx_exit_handlers[exit_reason](vcpu);
@@ -9108,33 +9160,38 @@ static void vmx_recover_nmi_blocking(struct vcpu_vmx *vmx)
idtv_info_valid = vmx->idt_vectoring_info & VECTORING_INFO_VALID_MASK;
- if (vmx->loaded_vmcs->nmi_known_unmasked)
- return;
- /*
- * Can't use vmx->exit_intr_info since we're not sure what
- * the exit reason is.
- */
- exit_intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
- unblock_nmi = (exit_intr_info & INTR_INFO_UNBLOCK_NMI) != 0;
- vector = exit_intr_info & INTR_INFO_VECTOR_MASK;
- /*
- * SDM 3: 27.7.1.2 (September 2008)
- * Re-set bit "block by NMI" before VM entry if vmexit caused by
- * a guest IRET fault.
- * SDM 3: 23.2.2 (September 2008)
- * Bit 12 is undefined in any of the following cases:
- * If the VM exit sets the valid bit in the IDT-vectoring
- * information field.
- * If the VM exit is due to a double fault.
- */
- if ((exit_intr_info & INTR_INFO_VALID_MASK) && unblock_nmi &&
- vector != DF_VECTOR && !idtv_info_valid)
- vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO,
- GUEST_INTR_STATE_NMI);
- else
- vmx->loaded_vmcs->nmi_known_unmasked =
- !(vmcs_read32(GUEST_INTERRUPTIBILITY_INFO)
- & GUEST_INTR_STATE_NMI);
+ if (cpu_has_virtual_nmis()) {
+ if (vmx->loaded_vmcs->nmi_known_unmasked)
+ return;
+ /*
+ * Can't use vmx->exit_intr_info since we're not sure what
+ * the exit reason is.
+ */
+ exit_intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
+ unblock_nmi = (exit_intr_info & INTR_INFO_UNBLOCK_NMI) != 0;
+ vector = exit_intr_info & INTR_INFO_VECTOR_MASK;
+ /*
+ * SDM 3: 27.7.1.2 (September 2008)
+ * Re-set bit "block by NMI" before VM entry if vmexit caused by
+ * a guest IRET fault.
+ * SDM 3: 23.2.2 (September 2008)
+ * Bit 12 is undefined in any of the following cases:
+ * If the VM exit sets the valid bit in the IDT-vectoring
+ * information field.
+ * If the VM exit is due to a double fault.
+ */
+ if ((exit_intr_info & INTR_INFO_VALID_MASK) && unblock_nmi &&
+ vector != DF_VECTOR && !idtv_info_valid)
+ vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO,
+ GUEST_INTR_STATE_NMI);
+ else
+ vmx->loaded_vmcs->nmi_known_unmasked =
+ !(vmcs_read32(GUEST_INTERRUPTIBILITY_INFO)
+ & GUEST_INTR_STATE_NMI);
+ } else if (unlikely(vmx->loaded_vmcs->soft_vnmi_blocked))
+ vmx->loaded_vmcs->vnmi_blocked_time +=
+ ktime_to_ns(ktime_sub(ktime_get(),
+ vmx->loaded_vmcs->entry_time));
}
static void __vmx_complete_interrupts(struct kvm_vcpu *vcpu,
@@ -9251,6 +9308,11 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
struct vcpu_vmx *vmx = to_vmx(vcpu);
unsigned long debugctlmsr, cr3, cr4;
+ /* Record the guest's net vcpu time for enforced NMI injections. */
+ if (unlikely(!cpu_has_virtual_nmis() &&
+ vmx->loaded_vmcs->soft_vnmi_blocked))
+ vmx->loaded_vmcs->entry_time = ktime_get();
+
/* Don't enter VMX if guest state is invalid, let the exit handler
start emulation until we arrive back to a valid state */
if (vmx->emulation_required)

View File

@ -1,73 +0,0 @@
From 4d6fa57b4dab0d77f4d8e9d9c73d1e63f6fe8fee Mon Sep 17 00:00:00 2001
From: "Jason A. Donenfeld" <Jason@zx2c4.com>
Date: Fri, 21 Apr 2017 23:14:48 +0200
Subject: macsec: avoid heap overflow in skb_to_sgvec
While this may appear as a humdrum one line change, it's actually quite
important. An sk_buff stores data in three places:
1. A linear chunk of allocated memory in skb->data. This is the easiest
one to work with, but it precludes using scatterdata since the memory
must be linear.
2. The array skb_shinfo(skb)->frags, which is of maximum length
MAX_SKB_FRAGS. This is nice for scattergather, since these fragments
can point to different pages.
3. skb_shinfo(skb)->frag_list, which is a pointer to another sk_buff,
which in turn can have data in either (1) or (2).
The first two are rather easy to deal with, since they're of a fixed
maximum length, while the third one is not, since there can be
potentially limitless chains of fragments. Fortunately dealing with
frag_list is opt-in for drivers, so drivers don't actually have to deal
with this mess. For whatever reason, macsec decided it wanted pain, and
so it explicitly specified NETIF_F_FRAGLIST.
Because dealing with (1), (2), and (3) is insane, most users of sk_buff
doing any sort of crypto or paging operation calls a convenient function
called skb_to_sgvec (which happens to be recursive if (3) is in use!).
This takes a sk_buff as input, and writes into its output pointer an
array of scattergather list items. Sometimes people like to declare a
fixed size scattergather list on the stack; othertimes people like to
allocate a fixed size scattergather list on the heap. However, if you're
doing it in a fixed-size fashion, you really shouldn't be using
NETIF_F_FRAGLIST too (unless you're also ensuring the sk_buff and its
frag_list children arent't shared and then you check the number of
fragments in total required.)
Macsec specifically does this:
size += sizeof(struct scatterlist) * (MAX_SKB_FRAGS + 1);
tmp = kmalloc(size, GFP_ATOMIC);
*sg = (struct scatterlist *)(tmp + sg_offset);
...
sg_init_table(sg, MAX_SKB_FRAGS + 1);
skb_to_sgvec(skb, sg, 0, skb->len);
Specifying MAX_SKB_FRAGS + 1 is the right answer usually, but not if you're
using NETIF_F_FRAGLIST, in which case the call to skb_to_sgvec will
overflow the heap, and disaster ensues.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Cc: stable@vger.kernel.org
Cc: security@kernel.org
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/macsec.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
index ff0a5ed..dbab05a 100644
--- a/drivers/net/macsec.c
+++ b/drivers/net/macsec.c
@@ -2716,7 +2716,7 @@ static netdev_tx_t macsec_start_xmit(struct sk_buff *skb,
}
#define MACSEC_FEATURES \
- (NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST)
+ (NETIF_F_SG | NETIF_F_HIGHDMA)
static struct lock_class_key macsec_netdev_addr_lock_key;
static int macsec_dev_init(struct net_device *dev)
--
cgit v1.1

View File

@ -1,74 +0,0 @@
From patchwork Sun Jul 23 01:15:09 2017
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: HID: rmi: Make sure the HID device is opened on resume
From: Lyude <lyude@redhat.com>
X-Patchwork-Id: 9858267
Message-Id: <20170723011509.23651-1-lyude@redhat.com>
To: linux-input@vger.kernel.org
Cc: Lyude <lyude@redhat.com>, Andrew Duggan <aduggan@synaptics.com>,
stable@vger.kernel.org, Jiri Kosina <jikos@kernel.org>,
Benjamin Tissoires <benjamin.tissoires@redhat.com>,
linux-kernel@vger.kernel.org
Date: Sat, 22 Jul 2017 21:15:09 -0400
So it looks like that suspend/resume has actually always been broken on
hid-rmi. The fact it worked was a rather silly coincidence that was
relying on the HID device to already be opened upon resume. This means
that so long as anything was reading the /dev/input/eventX node for for
an RMI device, it would suspend and resume correctly. As well, if
nothing happened to be keeping the HID device away it would shut off,
then the RMI driver would get confused on resume when it stopped
responding and explode.
So, call hid_hw_open() in rmi_post_resume() so we make sure that the
device is alive before we try talking to it.
This fixes RMI device suspend/resume over HID.
Signed-off-by: Lyude <lyude@redhat.com>
Cc: Andrew Duggan <aduggan@synaptics.com>
Cc: stable@vger.kernel.org
---
drivers/hid/hid-rmi.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/drivers/hid/hid-rmi.c b/drivers/hid/hid-rmi.c
index 5b40c2614599..e7d124f9a27f 100644
--- a/drivers/hid/hid-rmi.c
+++ b/drivers/hid/hid-rmi.c
@@ -431,22 +431,29 @@ static int rmi_post_resume(struct hid_device *hdev)
{
struct rmi_data *data = hid_get_drvdata(hdev);
struct rmi_device *rmi_dev = data->xport.rmi_dev;
- int ret;
+ int ret = 0;
if (!(data->device_flags & RMI_DEVICE))
return 0;
- ret = rmi_reset_attn_mode(hdev);
+ /* Make sure the HID device is ready to receive events */
+ ret = hid_hw_open(hdev);
if (ret)
return ret;
+ ret = rmi_reset_attn_mode(hdev);
+ if (ret)
+ goto out;
+
ret = rmi_driver_resume(rmi_dev, false);
if (ret) {
hid_warn(hdev, "Failed to resume device: %d\n", ret);
- return ret;
+ goto out;
}
- return 0;
+out:
+ hid_hw_close(hdev);
+ return ret;
}
#endif /* CONFIG_PM */

View File

@ -1,88 +0,0 @@
From patchwork Mon Sep 18 18:37:23 2017
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: KEYS: prevent KEYCTL_READ on negative key
From: Eric Biggers <ebiggers3@gmail.com>
X-Patchwork-Id: 9957387
Message-Id: <20170918183723.114253-1-ebiggers3@gmail.com>
To: keyrings@vger.kernel.org
Cc: David Howells <dhowells@redhat.com>, Michael Halcrow <mhalcrow@google.com>,
linux-security-module@vger.kernel.org,
linux-kernel@vger.kernel.org, Eric Biggers <ebiggers@google.com>,
stable@vger.kernel.org
Date: Mon, 18 Sep 2017 11:37:23 -0700
From: Eric Biggers <ebiggers@google.com>
Because keyctl_read_key() looks up the key with no permissions
requested, it may find a negatively instantiated key. If the key is
also possessed, we went ahead and called ->read() on the key. But the
key payload will actually contain the ->reject_error rather than the
normal payload. Thus, the kernel oopses trying to read the
user_key_payload from memory address (int)-ENOKEY = 0x00000000ffffff82.
Fortunately the payload data is stored inline, so it shouldn't be
possible to abuse this as an arbitrary memory read primitive...
Reproducer:
keyctl new_session
keyctl request2 user desc '' @s
keyctl read $(keyctl show | awk '/user: desc/ {print $1}')
It causes a crash like the following:
BUG: unable to handle kernel paging request at 00000000ffffff92
IP: user_read+0x33/0xa0
PGD 36a54067 P4D 36a54067 PUD 0
Oops: 0000 [#1] SMP
CPU: 0 PID: 211 Comm: keyctl Not tainted 4.14.0-rc1 #337
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-20170228_101828-anatol 04/01/2014
task: ffff90aa3b74c3c0 task.stack: ffff9878c0478000
RIP: 0010:user_read+0x33/0xa0
RSP: 0018:ffff9878c047bee8 EFLAGS: 00010246
RAX: 0000000000000001 RBX: ffff90aa3d7da340 RCX: 0000000000000017
RDX: 0000000000000000 RSI: 00000000ffffff82 RDI: ffff90aa3d7da340
RBP: ffff9878c047bf00 R08: 00000024f95da94f R09: 0000000000000000
R10: 0000000000000001 R11: 0000000000000000 R12: 0000000000000000
R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000
FS: 00007f58ece69740(0000) GS:ffff90aa3e200000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00000000ffffff92 CR3: 0000000036adc001 CR4: 00000000003606f0
Call Trace:
keyctl_read_key+0xac/0xe0
SyS_keyctl+0x99/0x120
entry_SYSCALL_64_fastpath+0x1f/0xbe
RIP: 0033:0x7f58ec787bb9
RSP: 002b:00007ffc8d401678 EFLAGS: 00000206 ORIG_RAX: 00000000000000fa
RAX: ffffffffffffffda RBX: 00007ffc8d402800 RCX: 00007f58ec787bb9
RDX: 0000000000000000 RSI: 00000000174a63ac RDI: 000000000000000b
RBP: 0000000000000004 R08: 00007ffc8d402809 R09: 0000000000000020
R10: 0000000000000000 R11: 0000000000000206 R12: 00007ffc8d402800
R13: 00007ffc8d4016e0 R14: 0000000000000000 R15: 0000000000000000
Code: e5 41 55 49 89 f5 41 54 49 89 d4 53 48 89 fb e8 a4 b4 ad ff 85 c0 74 09 80 3d b9 4c 96 00 00 74 43 48 8b b3 20 01 00 00 4d 85 ed <0f> b7 5e 10 74 29 4d 85 e4 74 24 4c 39 e3 4c 89 e2 4c 89 ef 48
RIP: user_read+0x33/0xa0 RSP: ffff9878c047bee8
CR2: 00000000ffffff92
Fixes: 61ea0c0ba904 ("KEYS: Skip key state checks when checking for possession")
Cc: <stable@vger.kernel.org> [v3.13+]
Signed-off-by: Eric Biggers <ebiggers@google.com>
---
security/keys/keyctl.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index ab0b337c84b4..6a82090c7fc1 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -766,6 +766,11 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen)
key = key_ref_to_ptr(key_ref);
+ if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) {
+ ret = -ENOKEY;
+ goto error2;
+ }
+
/* see if we can read it directly */
ret = key_permission(key_ref, KEY_NEED_READ);
if (ret == 0)

View File

@ -0,0 +1,55 @@
From patchwork Mon Oct 2 14:08:40 2017
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: PCI: aspm: deal with missing root ports in link state handling
From: Ard Biesheuvel <ard.biesheuvel@linaro.org>
X-Patchwork-Id: 9980861
Message-Id: <20171002140840.7767-1-ard.biesheuvel@linaro.org>
To: linux-pci@vger.kernel.org, bhelgaas@google.com
Cc: graeme.gregory@linaro.org, leif.lindholm@linaro.org,
daniel.thompson@Linaro.org, Ard Biesheuvel <ard.biesheuvel@linaro.org>
Date: Mon, 2 Oct 2017 15:08:40 +0100
Even though it is unconventional, some PCIe host implementations omit
the root ports entirely, and simply consist of a host bridge (which
is not modeled as a device in the PCI hierarchy) and a link.
When the downstream device is an endpoint, our current code does not
seem to mind this unusual configuration. However, when PCIe switches
are involved, the ASPM code assumes that any downstream switch port
has a parent, and blindly derefences the bus->parent->self field of
the pci_dev struct to chain the downstream link state to the link
state of the root port. Given that the root port is missing, the link
is not modeled at all, and nor is the link state, and attempting to
access it results in a NULL pointer dereference and a crash.
So let's avoid this by allowing the link state chain to terminate at
the downstream port if no root port exists.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
drivers/pci/pcie/aspm.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
index 1dfa10cc566b..0bea8498b5a5 100644
--- a/drivers/pci/pcie/aspm.c
+++ b/drivers/pci/pcie/aspm.c
@@ -802,10 +802,14 @@ static struct pcie_link_state *alloc_pcie_link_state(struct pci_dev *pdev)
/*
* Root Ports and PCI/PCI-X to PCIe Bridges are roots of PCIe
- * hierarchies.
+ * hierarchies. Note that some PCIe host implementations omit
+ * the root ports entirely, in which case a downstream port on
+ * a switch may become the root of the link state chain for all
+ * its subordinate endpoints.
*/
if (pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT ||
- pci_pcie_type(pdev) == PCI_EXP_TYPE_PCIE_BRIDGE) {
+ pci_pcie_type(pdev) == PCI_EXP_TYPE_PCIE_BRIDGE ||
+ !pdev->bus->parent->self) {
link->root = link;
} else {
struct pcie_link_state *parent;

View File

@ -0,0 +1,48 @@
From patchwork Sat Nov 11 15:31:18 2017
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: USB: ulpi: fix bus-node lookup
From: Johan Hovold <johan@kernel.org>
X-Patchwork-Id: 10054387
Message-Id: <20171111153118.16038-1-johan@kernel.org>
To: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-arm-msm@vger.kernel.org, Rob Clark <robdclark@gmail.com>,
Peter Robinson <pbrobinson@gmail.com>, Johan Hovold <johan@kernel.org>,
stable <stable@vger.kernel.org>
Date: Sat, 11 Nov 2017 16:31:18 +0100
Fix bus-node lookup during registration, which ended up searching the whole
device tree depth-first starting at the parent (or grand parent) rather
than just matching on its children.
To make things worse, the parent (or grand-parent) node could end being
prematurely freed as well.
Fixes: ef6a7bcfb01c ("usb: ulpi: Support device discovery via DT")
Reported-by: Peter Robinson <pbrobinson@gmail.com>
Reported-by: Stephen Boyd <sboyd@codeaurora.org>
Cc: stable <stable@vger.kernel.org> # 4.10
Signed-off-by: Johan Hovold <johan@kernel.org>
---
drivers/usb/common/ulpi.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c
index 8b351444cc40..9a2ab6751a23 100644
--- a/drivers/usb/common/ulpi.c
+++ b/drivers/usb/common/ulpi.c
@@ -180,9 +180,9 @@ static int ulpi_of_register(struct ulpi *ulpi)
/* Find a ulpi bus underneath the parent or the grandparent */
parent = ulpi->dev.parent;
if (parent->of_node)
- np = of_find_node_by_name(parent->of_node, "ulpi");
+ np = of_get_child_by_name(parent->of_node, "ulpi");
else if (parent->parent && parent->parent->of_node)
- np = of_find_node_by_name(parent->parent->of_node, "ulpi");
+ np = of_get_child_by_name(parent->parent->of_node, "ulpi");
if (!np)
return 0;

View File

@ -332,314 +332,6 @@ index 11240a8313c2..d38282b9e5d4 100644
--
2.13.5
From 4aba5ca95496899165ee7ceef5d9c60a6e7b15dd Mon Sep 17 00:00:00 2001
From: Peter Robinson <pbrobinson@gmail.com>
Date: Mon, 4 Sep 2017 13:04:47 +0100
Subject: [PATCH 3/4] Revert "arm64: dts: allwinner: Revert EMAC changes"
This reverts commit 87e1f5e8bb4bd584de0a8f3b1e42196dca221d02.
---
.../boot/dts/allwinner/sun50i-a64-bananapi-m64.dts | 16 ++++++++++++++++
.../boot/dts/allwinner/sun50i-a64-pine64-plus.dts | 15 +++++++++++++++
arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts | 17 +++++++++++++++++
.../dts/allwinner/sun50i-a64-sopine-baseboard.dts | 16 ++++++++++++++++
arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 20 ++++++++++++++++++++
.../boot/dts/allwinner/sun50i-h5-nanopi-neo2.dts | 17 +++++++++++++++++
.../boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts | 17 +++++++++++++++++
.../boot/dts/allwinner/sun50i-h5-orangepi-prime.dts | 17 +++++++++++++++++
8 files changed, 135 insertions(+)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts
index 6872135d7f84..ba2fde2909f9 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts
@@ -51,6 +51,7 @@
compatible = "sinovoip,bananapi-m64", "allwinner,sun50i-a64";
aliases {
+ ethernet0 = &emac;
serial0 = &uart0;
serial1 = &uart1;
};
@@ -67,6 +68,14 @@
};
};
+&emac {
+ pinctrl-names = "default";
+ pinctrl-0 = <&rgmii_pins>;
+ phy-mode = "rgmii";
+ phy-handle = <&ext_rgmii_phy>;
+ status = "okay";
+};
+
&i2c1 {
pinctrl-names = "default";
pinctrl-0 = <&i2c1_pins>;
@@ -77,6 +86,13 @@
bias-pull-up;
};
+&mdio {
+ ext_rgmii_phy: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ };
+};
+
&mmc0 {
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins>;
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts
index f82ccf332c0f..24f1aac366d6 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts
@@ -48,3 +48,18 @@
/* TODO: Camera, touchscreen, etc. */
};
+
+&emac {
+ pinctrl-names = "default";
+ pinctrl-0 = <&rgmii_pins>;
+ phy-mode = "rgmii";
+ phy-handle = <&ext_rgmii_phy>;
+ status = "okay";
+};
+
+&mdio {
+ ext_rgmii_phy: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ };
+};
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts
index 7c533b6d4ba9..827168bc22ed 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts
@@ -51,6 +51,7 @@
compatible = "pine64,pine64", "allwinner,sun50i-a64";
aliases {
+ ethernet0 = &emac;
serial0 = &uart0;
serial1 = &uart1;
serial2 = &uart2;
@@ -78,6 +79,15 @@
status = "okay";
};
+&emac {
+ pinctrl-names = "default";
+ pinctrl-0 = <&rmii_pins>;
+ phy-mode = "rmii";
+ phy-handle = <&ext_rmii_phy1>;
+ status = "okay";
+
+};
+
&i2c1 {
pinctrl-names = "default";
pinctrl-0 = <&i2c1_pins>;
@@ -88,6 +98,13 @@
bias-pull-up;
};
+&mdio {
+ ext_rmii_phy1: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ };
+};
+
&mmc0 {
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins>;
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts
index d891a1a27f6c..216e3a5dafae 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts
@@ -53,6 +53,7 @@
"allwinner,sun50i-a64";
aliases {
+ ethernet0 = &emac;
serial0 = &uart0;
};
@@ -76,6 +77,21 @@
status = "okay";
};
+&emac {
+ pinctrl-names = "default";
+ pinctrl-0 = <&rgmii_pins>;
+ phy-mode = "rgmii";
+ phy-handle = <&ext_rgmii_phy>;
+ status = "okay";
+};
+
+&mdio {
+ ext_rgmii_phy: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ };
+};
+
&mmc2 {
pinctrl-names = "default";
pinctrl-0 = <&mmc2_pins>;
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
index 68aadc9b96dc..bd0f33b77f57 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
@@ -449,6 +449,26 @@
#size-cells = <0>;
};
+ emac: ethernet@1c30000 {
+ compatible = "allwinner,sun50i-a64-emac";
+ syscon = <&syscon>;
+ reg = <0x01c30000 0x10000>;
+ interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "macirq";
+ resets = <&ccu RST_BUS_EMAC>;
+ reset-names = "stmmaceth";
+ clocks = <&ccu CLK_BUS_EMAC>;
+ clock-names = "stmmaceth";
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ mdio: mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+
gic: interrupt-controller@1c81000 {
compatible = "arm,gic-400";
reg = <0x01c81000 0x1000>,
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5-nanopi-neo2.dts b/arch/arm64/boot/dts/allwinner/sun50i-h5-nanopi-neo2.dts
index 1c2387bd5df6..968908761194 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h5-nanopi-neo2.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h5-nanopi-neo2.dts
@@ -50,6 +50,7 @@
compatible = "friendlyarm,nanopi-neo2", "allwinner,sun50i-h5";
aliases {
+ ethernet0 = &emac;
serial0 = &uart0;
};
@@ -108,6 +109,22 @@
status = "okay";
};
+&emac {
+ pinctrl-names = "default";
+ pinctrl-0 = <&emac_rgmii_pins>;
+ phy-supply = <&reg_gmac_3v3>;
+ phy-handle = <&ext_rgmii_phy>;
+ phy-mode = "rgmii";
+ status = "okay";
+};
+
+&mdio {
+ ext_rgmii_phy: ethernet-phy@7 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <7>;
+ };
+};
+
&mmc0 {
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>;
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts b/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts
index 4f77c8470f6c..a8296feee884 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts
@@ -59,6 +59,7 @@
};
aliases {
+ ethernet0 = &emac;
serial0 = &uart0;
};
@@ -136,12 +137,28 @@
status = "okay";
};
+&emac {
+ pinctrl-names = "default";
+ pinctrl-0 = <&emac_rgmii_pins>;
+ phy-supply = <&reg_gmac_3v3>;
+ phy-handle = <&ext_rgmii_phy>;
+ phy-mode = "rgmii";
+ status = "okay";
+};
+
&ir {
pinctrl-names = "default";
pinctrl-0 = <&ir_pins_a>;
status = "okay";
};
+&mdio {
+ ext_rgmii_phy: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ };
+};
+
&mmc0 {
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>;
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-prime.dts b/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-prime.dts
index 6be06873e5af..d906b302cbcd 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-prime.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-prime.dts
@@ -54,6 +54,7 @@
compatible = "xunlong,orangepi-prime", "allwinner,sun50i-h5";
aliases {
+ ethernet0 = &emac;
serial0 = &uart0;
};
@@ -143,12 +144,28 @@
status = "okay";
};
+&emac {
+ pinctrl-names = "default";
+ pinctrl-0 = <&emac_rgmii_pins>;
+ phy-supply = <&reg_gmac_3v3>;
+ phy-handle = <&ext_rgmii_phy>;
+ phy-mode = "rgmii";
+ status = "okay";
+};
+
&ir {
pinctrl-names = "default";
pinctrl-0 = <&ir_pins_a>;
status = "okay";
};
+&mdio {
+ ext_rgmii_phy: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ };
+};
+
&mmc0 {
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>;
--
2.13.5
From 11190f020b948ccdf15061b6df8cc2836a2afcb1 Mon Sep 17 00:00:00 2001
From: Peter Robinson <pbrobinson@gmail.com>
Date: Mon, 4 Sep 2017 13:04:55 +0100

411
arm-exynos-fix-usb3.patch Normal file
View File

@ -0,0 +1,411 @@
From patchwork Mon Oct 9 12:00:50 2017
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: [PATCHv4,1/2] drivers: phy: add calibrate method
From: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
X-Patchwork-Id: 9992829
Message-Id: <1507550451-21324-2-git-send-email-andrzej.p@samsung.com>
To: linux-samsung-soc@vger.kernel.org, linux-usb@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org
Cc: Mark Rutland <mark.rutland@arm.com>, Felipe Balbi <balbi@kernel.org>,
Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Russell King <linux@armlinux.org.uk>,
Krzysztof Kozlowski <krzk@kernel.org>,
Kishon Vijay Abraham I <kishon@ti.com>,
Rob Herring <robh+dt@kernel.org>, Kukjin Kim <kgene@kernel.org>,
Andrzej Pietrasiewicz <andrzej.p@samsung.com>,
Marek Szyprowski <m.szyprowski@samsung.com>
Date: Mon, 09 Oct 2017 14:00:50 +0200
Some quirky UDCs (like dwc3 on Exynos) need to have their phys calibrated e.g.
for using super speed. This patch adds a new phy_calibrate() method.
When the calibration should be used is dependent on actual chip.
In case of dwc3 on Exynos the calibration must happen after usb_add_hcd()
(while in host mode), because certain phy parameters like Tx LOS levels
and boost levels need to be calibrated further post initialization of xHCI
controller, to get SuperSpeed operations working. But an hcd must be
prepared first in order to pass it to usb_add_hcd(), so, in particular, dwc3
registers must be available first, and in order for the latter to happen
the phys must be initialized. This poses a chicken and egg problem if
the calibration were to be performed in phy_init(). To break the circular
dependency a separate method is added which can be called at a desired
moment after phy intialization.
Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
---
drivers/phy/phy-core.c | 15 +++++++++++++++
include/linux/phy/phy.h | 10 ++++++++++
2 files changed, 25 insertions(+)
diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
index a268f4d..b4964b0 100644
--- a/drivers/phy/phy-core.c
+++ b/drivers/phy/phy-core.c
@@ -372,6 +372,21 @@ int phy_reset(struct phy *phy)
}
EXPORT_SYMBOL_GPL(phy_reset);
+int phy_calibrate(struct phy *phy)
+{
+ int ret;
+
+ if (!phy || !phy->ops->calibrate)
+ return 0;
+
+ mutex_lock(&phy->mutex);
+ ret = phy->ops->calibrate(phy);
+ mutex_unlock(&phy->mutex);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(phy_calibrate);
+
/**
* _of_phy_get() - lookup and obtain a reference to a phy by phandle
* @np: device_node for which to get the phy
diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h
index e694d40..87580c8 100644
--- a/include/linux/phy/phy.h
+++ b/include/linux/phy/phy.h
@@ -39,6 +39,7 @@ enum phy_mode {
* @power_off: powering off the phy
* @set_mode: set the mode of the phy
* @reset: resetting the phy
+ * @calibrate: calibrate the phy
* @owner: the module owner containing the ops
*/
struct phy_ops {
@@ -48,6 +49,7 @@ struct phy_ops {
int (*power_off)(struct phy *phy);
int (*set_mode)(struct phy *phy, enum phy_mode mode);
int (*reset)(struct phy *phy);
+ int (*calibrate)(struct phy *phy);
struct module *owner;
};
@@ -141,6 +143,7 @@ static inline void *phy_get_drvdata(struct phy *phy)
int phy_power_off(struct phy *phy);
int phy_set_mode(struct phy *phy, enum phy_mode mode);
int phy_reset(struct phy *phy);
+int phy_calibrate(struct phy *phy);
static inline int phy_get_bus_width(struct phy *phy)
{
return phy->attrs.bus_width;
@@ -262,6 +265,13 @@ static inline int phy_reset(struct phy *phy)
return -ENOSYS;
}
+static inline int phy_calibrate(struct phy *phy)
+{
+ if (!phy)
+ return 0;
+ return -ENOSYS;
+}
+
static inline int phy_get_bus_width(struct phy *phy)
{
return -ENOSYS;
From patchwork Mon Oct 9 12:00:51 2017
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: [PATCHv4,
2/2] phy: exynos5-usbdrd: Calibrate LOS levels for exynos5420/5800
From: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
X-Patchwork-Id: 9992809
Message-Id: <1507550451-21324-3-git-send-email-andrzej.p@samsung.com>
To: linux-samsung-soc@vger.kernel.org, linux-usb@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org
Cc: Mark Rutland <mark.rutland@arm.com>, Felipe Balbi <balbi@kernel.org>,
Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Russell King <linux@armlinux.org.uk>,
Krzysztof Kozlowski <krzk@kernel.org>,
Kishon Vijay Abraham I <kishon@ti.com>,
Rob Herring <robh+dt@kernel.org>, Kukjin Kim <kgene@kernel.org>,
Andrzej Pietrasiewicz <andrzej.p@samsung.com>,
Marek Szyprowski <m.szyprowski@samsung.com>
Date: Mon, 09 Oct 2017 14:00:51 +0200
From: Vivek Gautam <gautam.vivek@samsung.com>
Adding phy calibration sequence for USB 3.0 DRD PHY present on
Exynos5420/5800 systems.
This calibration facilitates setting certain PHY parameters viz.
the Loss-of-Signal (LOS) Detector Threshold Level, as well as
Tx-Vboost-Level for Super-Speed operations.
Additionally we also set proper time to wait for RxDetect measurement,
for desired PHY reference clock, so as to solve issue with enumeration
of few USB 3.0 devices, like Samsung SUM-TSB16S 3.0 USB drive
on the controller.
We are using CR_port for this purpose to send required data
to override the LOS values.
On testing with USB 3.0 devices on USB 3.0 port present on
SMDK5420, and peach-pit boards should see following message:
usb 2-1: new SuperSpeed USB device number 2 using xhci-hcd
and without this patch, should see below shown message:
usb 1-1: new high-speed USB device number 2 using xhci-hcd
[Also removed unnecessary extra lines in the register macro definitions]
Signed-off-by: Vivek Gautam <gautam.vivek@samsung.com>
[adapted to use phy_calibrate as entry point]
Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
---
drivers/phy/samsung/phy-exynos5-usbdrd.c | 183 +++++++++++++++++++++++++++++++
drivers/usb/dwc3/core.c | 7 +-
2 files changed, 188 insertions(+), 2 deletions(-)
diff --git a/drivers/phy/samsung/phy-exynos5-usbdrd.c b/drivers/phy/samsung/phy-exynos5-usbdrd.c
index 22c68f5..9e83c15 100644
--- a/drivers/phy/samsung/phy-exynos5-usbdrd.c
+++ b/drivers/phy/samsung/phy-exynos5-usbdrd.c
@@ -90,7 +90,17 @@
#define PHYCLKRST_COMMONONN BIT(0)
#define EXYNOS5_DRD_PHYREG0 0x14
+#define PHYREG0_SSC_REF_CLK_SEL BIT(21)
+#define PHYREG0_SSC_RANGE BIT(20)
+#define PHYREG0_CR_WRITE BIT(19)
+#define PHYREG0_CR_READ BIT(18)
+#define PHYREG0_CR_DATA_IN(_x) ((_x) << 2)
+#define PHYREG0_CR_CAP_DATA BIT(1)
+#define PHYREG0_CR_CAP_ADDR BIT(0)
+
#define EXYNOS5_DRD_PHYREG1 0x18
+#define PHYREG1_CR_DATA_OUT(_x) ((_x) << 1)
+#define PHYREG1_CR_ACK BIT(0)
#define EXYNOS5_DRD_PHYPARAM0 0x1c
@@ -119,6 +129,25 @@
#define EXYNOS5_DRD_PHYRESUME 0x34
#define EXYNOS5_DRD_LINKPORT 0x44
+/* USB 3.0 DRD PHY SS Function Control Reg; accessed by CR_PORT */
+#define EXYNOS5_DRD_PHYSS_LOSLEVEL_OVRD_IN (0x15)
+#define LOSLEVEL_OVRD_IN_LOS_BIAS_5420 (0x5 << 13)
+#define LOSLEVEL_OVRD_IN_LOS_BIAS_DEFAULT (0x0 << 13)
+#define LOSLEVEL_OVRD_IN_EN (0x1 << 10)
+#define LOSLEVEL_OVRD_IN_LOS_LEVEL_DEFAULT (0x9 << 0)
+
+#define EXYNOS5_DRD_PHYSS_TX_VBOOSTLEVEL_OVRD_IN (0x12)
+#define TX_VBOOSTLEVEL_OVRD_IN_VBOOST_5420 (0x5 << 13)
+#define TX_VBOOSTLEVEL_OVRD_IN_VBOOST_DEFAULT (0x4 << 13)
+
+#define EXYNOS5_DRD_PHYSS_LANE0_TX_DEBUG (0x1010)
+#define LANE0_TX_DEBUG_RXDET_MEAS_TIME_19M2_20M (0x4 << 4)
+#define LANE0_TX_DEBUG_RXDET_MEAS_TIME_24M (0x8 << 4)
+#define LANE0_TX_DEBUG_RXDET_MEAS_TIME_25M_26M (0x8 << 4)
+#define LANE0_TX_DEBUG_RXDET_MEAS_TIME_48M_50M_52M (0x20 << 4)
+#define LANE0_TX_DEBUG_RXDET_MEAS_TIME_62M5 (0x20 << 4)
+#define LANE0_TX_DEBUG_RXDET_MEAS_TIME_96M_100M (0x40 << 4)
+
#define KHZ 1000
#define MHZ (KHZ * KHZ)
@@ -527,6 +556,151 @@ static int exynos5_usbdrd_phy_power_off(struct phy *phy)
return 0;
}
+static int crport_handshake(struct exynos5_usbdrd_phy *phy_drd,
+ u32 val, u32 cmd)
+{
+ u32 usec = 100;
+ unsigned int result;
+
+ writel(val | cmd, phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);
+
+ do {
+ result = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYREG1);
+ if (result & PHYREG1_CR_ACK)
+ break;
+
+ udelay(1);
+ } while (usec-- > 0);
+
+ if (!usec) {
+ dev_err(phy_drd->dev,
+ "CRPORT handshake timeout1 (0x%08x)\n", val);
+ return -ETIME;
+ }
+
+ usec = 100;
+
+ writel(val, phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);
+
+ do {
+ result = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYREG1);
+ if (!(result & PHYREG1_CR_ACK))
+ break;
+
+ udelay(1);
+ } while (usec-- > 0);
+
+ if (!usec) {
+ dev_err(phy_drd->dev,
+ "CRPORT handshake timeout2 (0x%08x)\n", val);
+ return -ETIME;
+ }
+
+ return 0;
+}
+
+static int crport_ctrl_write(struct exynos5_usbdrd_phy *phy_drd,
+ u32 addr, u32 data)
+{
+ int ret;
+
+ /* Write Address */
+ writel(PHYREG0_CR_DATA_IN(addr),
+ phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);
+ ret = crport_handshake(phy_drd, PHYREG0_CR_DATA_IN(addr),
+ PHYREG0_CR_CAP_ADDR);
+ if (ret)
+ return ret;
+
+ /* Write Data */
+ writel(PHYREG0_CR_DATA_IN(data),
+ phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);
+ ret = crport_handshake(phy_drd, PHYREG0_CR_DATA_IN(data),
+ PHYREG0_CR_CAP_DATA);
+ if (ret)
+ return ret;
+
+ ret = crport_handshake(phy_drd, PHYREG0_CR_DATA_IN(data),
+ PHYREG0_CR_WRITE);
+
+ return ret;
+}
+
+/*
+ * Calibrate few PHY parameters using CR_PORT register to meet
+ * SuperSpeed requirements on Exynos5420 and Exynos5800 systems,
+ * which have 28nm USB 3.0 DRD PHY.
+ */
+static int exynos5420_usbdrd_phy_calibrate(struct exynos5_usbdrd_phy *phy_drd)
+{
+ unsigned int temp;
+ int ret = 0;
+
+ /*
+ * Change los_bias to (0x5) for 28nm PHY from a
+ * default value (0x0); los_level is set as default
+ * (0x9) as also reflected in los_level[30:26] bits
+ * of PHYPARAM0 register.
+ */
+ temp = LOSLEVEL_OVRD_IN_LOS_BIAS_5420 |
+ LOSLEVEL_OVRD_IN_EN |
+ LOSLEVEL_OVRD_IN_LOS_LEVEL_DEFAULT;
+ ret = crport_ctrl_write(phy_drd,
+ EXYNOS5_DRD_PHYSS_LOSLEVEL_OVRD_IN,
+ temp);
+ if (ret) {
+ dev_err(phy_drd->dev,
+ "Failed setting Loss-of-Signal level for SuperSpeed\n");
+ return ret;
+ }
+
+ /*
+ * Set tx_vboost_lvl to (0x5) for 28nm PHY Tuning,
+ * to raise Tx signal level from its default value of (0x4)
+ */
+ temp = TX_VBOOSTLEVEL_OVRD_IN_VBOOST_5420;
+ ret = crport_ctrl_write(phy_drd,
+ EXYNOS5_DRD_PHYSS_TX_VBOOSTLEVEL_OVRD_IN,
+ temp);
+ if (ret) {
+ dev_err(phy_drd->dev,
+ "Failed setting Tx-Vboost-Level for SuperSpeed\n");
+ return ret;
+ }
+
+ /*
+ * Set proper time to wait for RxDetect measurement, for
+ * desired reference clock of PHY, by tuning the CR_PORT
+ * register LANE0.TX_DEBUG which is internal to PHY.
+ * This fixes issue with few USB 3.0 devices, which are
+ * not detected (not even generate interrupts on the bus
+ * on insertion) without this change.
+ * e.g. Samsung SUM-TSB16S 3.0 USB drive.
+ */
+ switch (phy_drd->extrefclk) {
+ case EXYNOS5_FSEL_50MHZ:
+ temp = LANE0_TX_DEBUG_RXDET_MEAS_TIME_48M_50M_52M;
+ break;
+ case EXYNOS5_FSEL_20MHZ:
+ case EXYNOS5_FSEL_19MHZ2:
+ temp = LANE0_TX_DEBUG_RXDET_MEAS_TIME_19M2_20M;
+ break;
+ case EXYNOS5_FSEL_24MHZ:
+ default:
+ temp = LANE0_TX_DEBUG_RXDET_MEAS_TIME_24M;
+ break;
+ }
+
+ ret = crport_ctrl_write(phy_drd,
+ EXYNOS5_DRD_PHYSS_LANE0_TX_DEBUG,
+ temp);
+ if (ret)
+ dev_err(phy_drd->dev,
+ "Failed setting RxDetect measurement time for SuperSpeed\n");
+
+ return ret;
+}
+
static struct phy *exynos5_usbdrd_phy_xlate(struct device *dev,
struct of_phandle_args *args)
{
@@ -538,11 +712,20 @@ static struct phy *exynos5_usbdrd_phy_xlate(struct device *dev,
return phy_drd->phys[args->args[0]].phy;
}
+static int exynos5_usbdrd_phy_calibrate(struct phy *phy)
+{
+ struct phy_usb_instance *inst = phy_get_drvdata(phy);
+ struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
+
+ return exynos5420_usbdrd_phy_calibrate(phy_drd);
+}
+
static const struct phy_ops exynos5_usbdrd_phy_ops = {
.init = exynos5_usbdrd_phy_init,
.exit = exynos5_usbdrd_phy_exit,
.power_on = exynos5_usbdrd_phy_power_on,
.power_off = exynos5_usbdrd_phy_power_off,
+ .calibrate = exynos5_usbdrd_phy_calibrate,
.owner = THIS_MODULE,
};
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 03474d3..224e0dd 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -156,9 +156,10 @@ static void __dwc3_set_mode(struct work_struct *work)
} else {
if (dwc->usb2_phy)
otg_set_vbus(dwc->usb2_phy->otg, true);
- if (dwc->usb2_generic_phy)
+ if (dwc->usb2_generic_phy) {
phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_HOST);
-
+ phy_calibrate(dwc->usb2_generic_phy);
+ }
}
break;
case DWC3_GCTL_PRTCAP_DEVICE:
@@ -955,6 +956,8 @@ static int dwc3_core_init_mode(struct dwc3 *dwc)
dev_err(dev, "failed to initialize host\n");
return ret;
}
+ if (dwc->usb2_generic_phy)
+ phy_calibrate(dwc->usb2_generic_phy);
break;
case USB_DR_MODE_OTG:
INIT_WORK(&dwc->drd_work, __dwc3_set_mode);

View File

@ -1,121 +0,0 @@
From 723288836628bc1c0855f3bb7b64b1803e4b9e4a Mon Sep 17 00:00:00 2001
From: Robin Murphy <robin.murphy@arm.com>
Date: Thu, 31 Aug 2017 11:32:54 +0100
Subject: of: restrict DMA configuration
Moving DMA configuration to happen later at driver probe time had the
unnoticed side-effect that we now perform DMA configuration for *every*
device represented in DT, rather than only those explicitly created by
the of_platform and PCI code.
As Christoph points out, this is not really the best thing to do. Whilst
there may well be other DMA-capable buses that can benefit from having
their children automatically configured after the bridge has probed,
there are also plenty of others like USB, MDIO, etc. that definitely do
not support DMA and should not be indiscriminately processed.
The good news is that in most cases the DT "dma-ranges" property serves
as an appropriate indicator - per a strict interpretation of the spec,
anything lacking a "dma-ranges" property should be considered not to
have a mapping of DMA address space from its children to its parent,
thus anything for which of_dma_get_range() does not succeed does not
need DMA configuration. Certain bus types have a general expectation of
DMA capability and carry a well-established precedent that an absent
"dma-ranges" implies the same as the empty property, so we automatically
opt those in to DMA configuration regardless, to avoid regressing most
existing platforms.
Fixes: 09515ef5ddad ("of/acpi: Configure dma operations at probe time for platform/amba/pci bus devices")
Reported-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
drivers/of/device.c | 48 ++++++++++++++++++++++++++++++++----------------
1 file changed, 32 insertions(+), 16 deletions(-)
diff --git a/drivers/of/device.c b/drivers/of/device.c
index e0a28ea..04c4c95 100644
--- a/drivers/of/device.c
+++ b/drivers/of/device.c
@@ -9,6 +9,9 @@
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/amba/bus.h>
#include <asm/errno.h>
#include "of_private.h"
@@ -84,31 +87,28 @@ int of_device_add(struct platform_device *ofdev)
*/
int of_dma_configure(struct device *dev, struct device_node *np)
{
- u64 dma_addr, paddr, size;
+ u64 dma_addr, paddr, size = 0;
int ret;
bool coherent;
unsigned long offset;
const struct iommu_ops *iommu;
u64 mask;
- /*
- * Set default coherent_dma_mask to 32 bit. Drivers are expected to
- * setup the correct supported mask.
- */
- if (!dev->coherent_dma_mask)
- dev->coherent_dma_mask = DMA_BIT_MASK(32);
-
- /*
- * Set it to coherent_dma_mask by default if the architecture
- * code has not set it.
- */
- if (!dev->dma_mask)
- dev->dma_mask = &dev->coherent_dma_mask;
-
ret = of_dma_get_range(np, &dma_addr, &paddr, &size);
if (ret < 0) {
+ /*
+ * For legacy reasons, we have to assume some devices need
+ * DMA configuration regardless of whether "dma-ranges" is
+ * correctly specified or not.
+ */
+ if (!dev_is_pci(dev) &&
+#ifdef CONFIG_ARM_AMBA
+ dev->bus != &amba_bustype &&
+#endif
+ dev->bus != &platform_bus_type)
+ return ret == -ENODEV ? 0 : ret;
+
dma_addr = offset = 0;
- size = max(dev->coherent_dma_mask, dev->coherent_dma_mask + 1);
} else {
offset = PFN_DOWN(paddr - dma_addr);
@@ -129,6 +129,22 @@ int of_dma_configure(struct device *dev, struct device_node *np)
dev_dbg(dev, "dma_pfn_offset(%#08lx)\n", offset);
}
+ /*
+ * Set default coherent_dma_mask to 32 bit. Drivers are expected to
+ * setup the correct supported mask.
+ */
+ if (!dev->coherent_dma_mask)
+ dev->coherent_dma_mask = DMA_BIT_MASK(32);
+ /*
+ * Set it to coherent_dma_mask by default if the architecture
+ * code has not set it.
+ */
+ if (!dev->dma_mask)
+ dev->dma_mask = &dev->coherent_dma_mask;
+
+ if (!size)
+ size = max(dev->coherent_dma_mask, dev->coherent_dma_mask + 1);
+
dev->dma_pfn_offset = offset;
/*
--
cgit v1.1

View File

@ -1,39 +0,0 @@
From patchwork Sun Jul 9 16:36:14 2017
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: ARM: tegra: Register host1x node with iommu binding on tegra124
From: Paul Kocialkowski <contact@paulk.fr>
X-Patchwork-Id: 9831825
Message-Id: <20170709163614.6746-1-contact@paulk.fr>
To: linux-arm-kernel@lists.infradead.org, linux-tegra@vger.kernel.org,
linux-kernel@vger.kernel.org
Cc: Thierry Reding <thierry.reding@gmail.com>,
Stephen Warren <swarren@wwwdotorg.org>,
Mikko Perttunen <mperttunen@nvidia.com>,
Paul Kocialkowski <contact@paulk.fr>,
Jonathan Hunter <jonathanh@nvidia.com>
Date: Sun, 9 Jul 2017 19:36:14 +0300
This registers the host1x node with the SMMU (as HC swgroup) to allow
the host1x code to attach to it. It avoid failing the probe sequence,
which resulted in the tegra drm driver not probing and thus nothing
being displayed on-screen.
Signed-off-by: Paul Kocialkowski <contact@paulk.fr>
---
arch/arm/boot/dts/tegra124.dtsi | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm/boot/dts/tegra124.dtsi b/arch/arm/boot/dts/tegra124.dtsi
index 187a36c6d0fc..b3b89befffeb 100644
--- a/arch/arm/boot/dts/tegra124.dtsi
+++ b/arch/arm/boot/dts/tegra124.dtsi
@@ -85,6 +85,7 @@
clocks = <&tegra_car TEGRA124_CLK_HOST1X>;
resets = <&tegra_car 28>;
reset-names = "host1x";
+ iommus = <&mc TEGRA_SWGROUP_HC>;
#address-cells = <2>;
#size-cells = <2>;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
CONFIG_ALLOW_LOCKDOWN_LIFT_BY_SYSRQ=y

View File

@ -0,0 +1 @@
CONFIG_ALTERA_MSGDMA=m

View File

@ -0,0 +1 @@
CONFIG_ATH10K_USB=m

View File

@ -0,0 +1 @@
# CONFIG_BATTERY_MAX1721X is not set

View File

@ -1 +0,0 @@
CONFIG_BLK_CPQ_CISS_DA=m

View File

@ -1 +0,0 @@
# CONFIG_BLK_DEV_UB is not set

View File

@ -0,0 +1 @@
CONFIG_BNXT_FLOWER_OFFLOAD=y

View File

@ -0,0 +1 @@
CONFIG_BPF_STREAM_PARSER=y

View File

@ -1 +0,0 @@
CONFIG_BT_SCO=y

1
baseconfig/CONFIG_CCS811 Normal file
View File

@ -0,0 +1 @@
# CONFIG_CCS811 is not set

View File

@ -0,0 +1 @@
CONFIG_CEC_PIN=y

View File

@ -1 +0,0 @@
# CONFIG_CHARGER_QCOM_SMBB is not set

View File

@ -1 +0,0 @@
CONFIG_CISS_SCSI_TAPE=y

View File

@ -0,0 +1 @@
# CONFIG_CLK_HSDK is not set

View File

@ -0,0 +1 @@
# CONFIG_CLOCK_THERMAL is not set

View File

@ -0,0 +1 @@
# CONFIG_CRYPTO_DEV_SP_CCP is not set

View File

@ -1 +1 @@
CONFIG_CRYPTO_GCM=m
CONFIG_CRYPTO_GCM=y

View File

@ -1 +1 @@
CONFIG_CRYPTO_GHASH=m
CONFIG_CRYPTO_GHASH=y

View File

@ -0,0 +1 @@
# CONFIG_DEVFREQ_THERMAL is not set

View File

@ -1 +1 @@
CONFIG_DP83867_PHY=m
# CONFIG_DP83867_PHY is not set

View File

@ -0,0 +1 @@
# CONFIG_DVB_DDBRIDGE_MSIENABLE is not set

View File

@ -1 +0,0 @@
CONFIG_EXPERIMENTAL=y

View File

@ -0,0 +1 @@
CONFIG_GPIO_BD9571MWV=m

View File

@ -0,0 +1 @@
CONFIG_GPIO_TPS68470=y

View File

@ -1 +1 @@
CONFIG_HID_ASUS=m
# CONFIG_HID_ASUS is not set

View File

@ -1 +1 @@
CONFIG_I2C_PARPORT_LIGHT=m
# CONFIG_I2C_PARPORT_LIGHT is not set

View File

@ -0,0 +1 @@
# CONFIG_INFINIBAND_EXP_USER_ACCESS is not set

View File

@ -1 +0,0 @@
CONFIG_INOTIFY=y

View File

@ -0,0 +1 @@
# CONFIG_INPUT_PWM_VIBRA is not set

View File

@ -0,0 +1 @@
CONFIG_INPUT_RK805_PWRKEY=m

View File

@ -1 +1 @@
CONFIG_IP_DCCP=m
# CONFIG_IP_DCCP is not set

View File

@ -0,0 +1 @@
CONFIG_IR_GPIO_TX=m

View File

@ -0,0 +1 @@
CONFIG_IR_PWM_TX=m

View File

@ -0,0 +1 @@
CONFIG_LEDS_AS3645A=m

View File

@ -1 +1 @@
# CONFIG_LEDS_IS31FL32XX is not set
CONFIG_LEDS_IS31FL32XX=m

View File

@ -0,0 +1 @@
# CONFIG_LOCK_DOWN_IN_EFI_SECURE_BOOT is not set

View File

@ -0,0 +1 @@
# CONFIG_LTC2471 is not set

View File

@ -0,0 +1 @@
CONFIG_MDIO_I2C=m

View File

@ -0,0 +1 @@
CONFIG_MFD_BD9571MWV=m

View File

@ -0,0 +1 @@
CONFIG_MFD_TPS68470=y

View File

@ -0,0 +1 @@
CONFIG_MLX5_ESWITCH=y

View File

@ -0,0 +1 @@
CONFIG_MLX5_MPFS=y

View File

@ -1 +0,0 @@
CONFIG_MMC_BLOCK_BOUNCE=y

View File

@ -1 +1 @@
CONFIG_MMC_TOSHIBA_PCI=m
# CONFIG_MMC_TOSHIBA_PCI is not set

View File

@ -0,0 +1 @@
CONFIG_NET_NSH=m

View File

@ -0,0 +1 @@
# CONFIG_NET_VENDOR_HUAWEI is not set

View File

@ -0,0 +1 @@
# CONFIG_NET_VENDOR_SNI is not set

View File

@ -0,0 +1 @@
CONFIG_NFT_FIB_NETDEV=m

View File

@ -1 +1 @@
CONFIG_PARPORT=m
# CONFIG_PARPORT is not set

View File

@ -1 +1 @@
CONFIG_PARPORT_PC=m
# CONFIG_PARPORT_PC is not set

View File

@ -1 +1 @@
CONFIG_PATA_ARASAN_CF=m
# CONFIG_PATA_ARASAN_CF is not set

View File

@ -1 +1 @@
CONFIG_PATA_ATIIXP=m
# CONFIG_PATA_ATIIXP is not set

View File

@ -1 +1 @@
CONFIG_PATA_CYPRESS=m
# CONFIG_PATA_CYPRESS is not set

View File

@ -1 +1 @@
CONFIG_PATA_MPIIX=m
# CONFIG_PATA_MPIIX is not set

View File

@ -1 +1 @@
CONFIG_PATA_OLDPIIX=m
# CONFIG_PATA_OLDPIIX is not set

View File

@ -1 +1 @@
CONFIG_PATA_RDC=m
# CONFIG_PATA_RDC is not set

View File

@ -1 +1 @@
CONFIG_PATA_SCH=m
# CONFIG_PATA_SCH is not set

View File

@ -1 +1 @@
CONFIG_PATA_TOSHIBA=m
# CONFIG_PATA_TOSHIBA is not set

View File

@ -1 +1 @@
CONFIG_PATA_TRIFLEX=m
# CONFIG_PATA_TRIFLEX is not set

View File

@ -0,0 +1 @@
# CONFIG_PCIE_DW_HOST_ECAM is not set

View File

@ -0,0 +1 @@
CONFIG_PHYLINK=m

View File

@ -0,0 +1 @@
# CONFIG_PHY_MVEBU_CP110_COMPHY is not set

1
baseconfig/CONFIG_PI433 Normal file
View File

@ -0,0 +1 @@
# CONFIG_PI433 is not set

View File

@ -1 +0,0 @@
# CONFIG_PINCTRL_MSM8994 is not set

View File

@ -0,0 +1 @@
CONFIG_PINCTRL_RK805=m

View File

@ -0,0 +1 @@
# CONFIG_PINCTRL_SPRD is not set

View File

@ -0,0 +1 @@
# CONFIG_PINCTRL_SPRD_SC9860 is not set

View File

@ -1 +1 @@
# CONFIG_PM_OPP is not set
CONFIG_PM_OPP=y

View File

@ -1 +0,0 @@
CONFIG_PPS_GENERATOR_PARPORT=m

View File

@ -0,0 +1 @@
# CONFIG_QCOM_GLINK_SSR is not set

View File

@ -0,0 +1 @@
CONFIG_R8822BE=m

View File

@ -0,0 +1 @@
CONFIG_REGULATOR_BD9571MWV=m

View File

@ -0,0 +1 @@
CONFIG_RESET_ATTACK_MITIGATION=y

View File

@ -0,0 +1 @@
# CONFIG_RESET_HSDK_V1 is not set

1
baseconfig/CONFIG_RMNET Normal file
View File

@ -0,0 +1 @@
# CONFIG_RMNET is not set

View File

@ -0,0 +1 @@
# CONFIG_ROCKCHIP_PHY is not set

View File

@ -0,0 +1 @@
# CONFIG_RPMSG_QCOM_GLINK_SMEM is not set

View File

@ -0,0 +1 @@
# CONFIG_SENSORS_IBM_CFFPS is not set

View File

@ -0,0 +1 @@
CONFIG_SENSORS_TPS53679=m

View File

@ -0,0 +1 @@
# CONFIG_SERIO_GPIO_PS2 is not set

1
baseconfig/CONFIG_SFP Normal file
View File

@ -0,0 +1 @@
CONFIG_SFP=m

Some files were not shown because too many files have changed in this diff Show More