Linux v4.14
This commit is contained in:
parent
d83c4aa672
commit
8d54d185ff
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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, ®);
|
||||
+ 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, ®);
|
||||
+ 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
|
||||
|
|
@ -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)
|
|
@ -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
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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)
|
|
@ -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;
|
|
@ -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;
|
||||
|
|
@ -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 = <®_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 = <®_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 = <®_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
|
||||
|
|
|
@ -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);
|
|
@ -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
|
||||
|
|
@ -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
|
@ -0,0 +1 @@
|
|||
CONFIG_ALLOW_LOCKDOWN_LIFT_BY_SYSRQ=y
|
|
@ -0,0 +1 @@
|
|||
CONFIG_ALTERA_MSGDMA=m
|
|
@ -0,0 +1 @@
|
|||
CONFIG_ATH10K_USB=m
|
|
@ -0,0 +1 @@
|
|||
# CONFIG_BATTERY_MAX1721X is not set
|
|
@ -1 +0,0 @@
|
|||
CONFIG_BLK_CPQ_CISS_DA=m
|
|
@ -1 +0,0 @@
|
|||
# CONFIG_BLK_DEV_UB is not set
|
|
@ -0,0 +1 @@
|
|||
CONFIG_BNXT_FLOWER_OFFLOAD=y
|
|
@ -0,0 +1 @@
|
|||
CONFIG_BPF_STREAM_PARSER=y
|
|
@ -1 +0,0 @@
|
|||
CONFIG_BT_SCO=y
|
|
@ -0,0 +1 @@
|
|||
# CONFIG_CCS811 is not set
|
|
@ -0,0 +1 @@
|
|||
CONFIG_CEC_PIN=y
|
|
@ -1 +0,0 @@
|
|||
# CONFIG_CHARGER_QCOM_SMBB is not set
|
|
@ -1 +0,0 @@
|
|||
CONFIG_CISS_SCSI_TAPE=y
|
|
@ -0,0 +1 @@
|
|||
# CONFIG_CLK_HSDK is not set
|
|
@ -0,0 +1 @@
|
|||
# CONFIG_CLOCK_THERMAL is not set
|
|
@ -0,0 +1 @@
|
|||
# CONFIG_CRYPTO_DEV_SP_CCP is not set
|
|
@ -1 +1 @@
|
|||
CONFIG_CRYPTO_GCM=m
|
||||
CONFIG_CRYPTO_GCM=y
|
||||
|
|
|
@ -1 +1 @@
|
|||
CONFIG_CRYPTO_GHASH=m
|
||||
CONFIG_CRYPTO_GHASH=y
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
# CONFIG_DEVFREQ_THERMAL is not set
|
|
@ -1 +1 @@
|
|||
CONFIG_DP83867_PHY=m
|
||||
# CONFIG_DP83867_PHY is not set
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
# CONFIG_DVB_DDBRIDGE_MSIENABLE is not set
|
|
@ -1 +0,0 @@
|
|||
CONFIG_EXPERIMENTAL=y
|
|
@ -0,0 +1 @@
|
|||
CONFIG_GPIO_BD9571MWV=m
|
|
@ -0,0 +1 @@
|
|||
CONFIG_GPIO_TPS68470=y
|
|
@ -1 +1 @@
|
|||
CONFIG_HID_ASUS=m
|
||||
# CONFIG_HID_ASUS is not set
|
||||
|
|
|
@ -1 +1 @@
|
|||
CONFIG_I2C_PARPORT_LIGHT=m
|
||||
# CONFIG_I2C_PARPORT_LIGHT is not set
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
# CONFIG_INFINIBAND_EXP_USER_ACCESS is not set
|
|
@ -1 +0,0 @@
|
|||
CONFIG_INOTIFY=y
|
|
@ -0,0 +1 @@
|
|||
# CONFIG_INPUT_PWM_VIBRA is not set
|
|
@ -0,0 +1 @@
|
|||
CONFIG_INPUT_RK805_PWRKEY=m
|
|
@ -1 +1 @@
|
|||
CONFIG_IP_DCCP=m
|
||||
# CONFIG_IP_DCCP is not set
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
CONFIG_IR_GPIO_TX=m
|
|
@ -0,0 +1 @@
|
|||
CONFIG_IR_PWM_TX=m
|
|
@ -0,0 +1 @@
|
|||
CONFIG_LEDS_AS3645A=m
|
|
@ -1 +1 @@
|
|||
# CONFIG_LEDS_IS31FL32XX is not set
|
||||
CONFIG_LEDS_IS31FL32XX=m
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
# CONFIG_LOCK_DOWN_IN_EFI_SECURE_BOOT is not set
|
|
@ -0,0 +1 @@
|
|||
# CONFIG_LTC2471 is not set
|
|
@ -0,0 +1 @@
|
|||
CONFIG_MDIO_I2C=m
|
|
@ -0,0 +1 @@
|
|||
CONFIG_MFD_BD9571MWV=m
|
|
@ -0,0 +1 @@
|
|||
CONFIG_MFD_TPS68470=y
|
|
@ -0,0 +1 @@
|
|||
CONFIG_MLX5_ESWITCH=y
|
|
@ -0,0 +1 @@
|
|||
CONFIG_MLX5_MPFS=y
|
|
@ -1 +0,0 @@
|
|||
CONFIG_MMC_BLOCK_BOUNCE=y
|
|
@ -1 +1 @@
|
|||
CONFIG_MMC_TOSHIBA_PCI=m
|
||||
# CONFIG_MMC_TOSHIBA_PCI is not set
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
CONFIG_NET_NSH=m
|
|
@ -0,0 +1 @@
|
|||
# CONFIG_NET_VENDOR_HUAWEI is not set
|
|
@ -0,0 +1 @@
|
|||
# CONFIG_NET_VENDOR_SNI is not set
|
|
@ -0,0 +1 @@
|
|||
CONFIG_NFT_FIB_NETDEV=m
|
|
@ -1 +1 @@
|
|||
CONFIG_PARPORT=m
|
||||
# CONFIG_PARPORT is not set
|
||||
|
|
|
@ -1 +1 @@
|
|||
CONFIG_PARPORT_PC=m
|
||||
# CONFIG_PARPORT_PC is not set
|
||||
|
|
|
@ -1 +1 @@
|
|||
CONFIG_PATA_ARASAN_CF=m
|
||||
# CONFIG_PATA_ARASAN_CF is not set
|
||||
|
|
|
@ -1 +1 @@
|
|||
CONFIG_PATA_ATIIXP=m
|
||||
# CONFIG_PATA_ATIIXP is not set
|
||||
|
|
|
@ -1 +1 @@
|
|||
CONFIG_PATA_CYPRESS=m
|
||||
# CONFIG_PATA_CYPRESS is not set
|
||||
|
|
|
@ -1 +1 @@
|
|||
CONFIG_PATA_MPIIX=m
|
||||
# CONFIG_PATA_MPIIX is not set
|
||||
|
|
|
@ -1 +1 @@
|
|||
CONFIG_PATA_OLDPIIX=m
|
||||
# CONFIG_PATA_OLDPIIX is not set
|
||||
|
|
|
@ -1 +1 @@
|
|||
CONFIG_PATA_RDC=m
|
||||
# CONFIG_PATA_RDC is not set
|
||||
|
|
|
@ -1 +1 @@
|
|||
CONFIG_PATA_SCH=m
|
||||
# CONFIG_PATA_SCH is not set
|
||||
|
|
|
@ -1 +1 @@
|
|||
CONFIG_PATA_TOSHIBA=m
|
||||
# CONFIG_PATA_TOSHIBA is not set
|
||||
|
|
|
@ -1 +1 @@
|
|||
CONFIG_PATA_TRIFLEX=m
|
||||
# CONFIG_PATA_TRIFLEX is not set
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
# CONFIG_PCIE_DW_HOST_ECAM is not set
|
|
@ -0,0 +1 @@
|
|||
CONFIG_PHYLINK=m
|
|
@ -0,0 +1 @@
|
|||
# CONFIG_PHY_MVEBU_CP110_COMPHY is not set
|
|
@ -0,0 +1 @@
|
|||
# CONFIG_PI433 is not set
|
|
@ -1 +0,0 @@
|
|||
# CONFIG_PINCTRL_MSM8994 is not set
|
|
@ -0,0 +1 @@
|
|||
CONFIG_PINCTRL_RK805=m
|
|
@ -0,0 +1 @@
|
|||
# CONFIG_PINCTRL_SPRD is not set
|
|
@ -0,0 +1 @@
|
|||
# CONFIG_PINCTRL_SPRD_SC9860 is not set
|
|
@ -1 +1 @@
|
|||
# CONFIG_PM_OPP is not set
|
||||
CONFIG_PM_OPP=y
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
CONFIG_PPS_GENERATOR_PARPORT=m
|
|
@ -0,0 +1 @@
|
|||
# CONFIG_QCOM_GLINK_SSR is not set
|
|
@ -0,0 +1 @@
|
|||
CONFIG_R8822BE=m
|
|
@ -0,0 +1 @@
|
|||
CONFIG_REGULATOR_BD9571MWV=m
|
|
@ -0,0 +1 @@
|
|||
CONFIG_RESET_ATTACK_MITIGATION=y
|
|
@ -0,0 +1 @@
|
|||
# CONFIG_RESET_HSDK_V1 is not set
|
|
@ -0,0 +1 @@
|
|||
# CONFIG_RMNET is not set
|
|
@ -0,0 +1 @@
|
|||
# CONFIG_ROCKCHIP_PHY is not set
|
|
@ -0,0 +1 @@
|
|||
# CONFIG_RPMSG_QCOM_GLINK_SMEM is not set
|
|
@ -0,0 +1 @@
|
|||
# CONFIG_SENSORS_IBM_CFFPS is not set
|
|
@ -0,0 +1 @@
|
|||
CONFIG_SENSORS_TPS53679=m
|
|
@ -0,0 +1 @@
|
|||
# CONFIG_SERIO_GPIO_PS2 is not set
|
|
@ -0,0 +1 @@
|
|||
CONFIG_SFP=m
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue