--- /dev/null
+From ff3154d1d89a2343fd5f82e65bc0cf1d4e6659b3 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Tue, 10 Dec 2019 10:57:52 +0100
+Subject: ACPI / battery: Deal better with neither design nor full capacity not being reported
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+commit ff3154d1d89a2343fd5f82e65bc0cf1d4e6659b3 upstream.
+
+Commit b41901a2cf06 ("ACPI / battery: Do not export energy_full[_design] on
+devices without full_charge_capacity") added support for some (broken)
+devices which always report 0 for both design_capacity and
+full_charge_capacity.
+
+Since the device that commit was written as a fix for is not reporting any
+form of "full" capacity we cannot calculate the value for the
+POWER_SUPPLY_PROP_CAPACITY, this is worked around by using an alternative
+array of available properties which does not contain this property.
+
+This is necessary because userspace (upower) treats us returning -ENODEV
+as 0 and then typically will trigger an emergency shutdown because of that.
+Userspace does not do this if the capacity sysfs attribute is not present
+at all.
+
+There are two potential problems with that commit:
+ 1) It assumes that both full_charge- and design-capacity are broken at the
+ same time and only checks if full_charge- is broken.
+ 2) It assumes that this only ever happens for devices which report energy
+ units rather then charge units.
+
+This commit fixes both issues by only using the alternative
+array of available properties if both full_charge- and design-capacity are
+broken and by also adding an alternative array of available properties for
+devices using mA units.
+
+Fixes: b41901a2cf06 ("ACPI / battery: Do not export energy_full[_design] on devices without full_charge_capacity")
+Cc: 4.19+ <stable@vger.kernel.org> # 4.19+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/acpi/battery.c | 51 +++++++++++++++++++++++++++++++++++++------------
+ 1 file changed, 39 insertions(+), 12 deletions(-)
+
+--- a/drivers/acpi/battery.c
++++ b/drivers/acpi/battery.c
+@@ -355,6 +355,20 @@ static enum power_supply_property charge
+ POWER_SUPPLY_PROP_SERIAL_NUMBER,
+ };
+
++static enum power_supply_property charge_battery_full_cap_broken_props[] = {
++ POWER_SUPPLY_PROP_STATUS,
++ POWER_SUPPLY_PROP_PRESENT,
++ POWER_SUPPLY_PROP_TECHNOLOGY,
++ POWER_SUPPLY_PROP_CYCLE_COUNT,
++ POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
++ POWER_SUPPLY_PROP_VOLTAGE_NOW,
++ POWER_SUPPLY_PROP_CURRENT_NOW,
++ POWER_SUPPLY_PROP_CHARGE_NOW,
++ POWER_SUPPLY_PROP_MODEL_NAME,
++ POWER_SUPPLY_PROP_MANUFACTURER,
++ POWER_SUPPLY_PROP_SERIAL_NUMBER,
++};
++
+ static enum power_supply_property energy_battery_props[] = {
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_PRESENT,
+@@ -816,21 +830,34 @@ static void __exit battery_hook_exit(voi
+ static int sysfs_add_battery(struct acpi_battery *battery)
+ {
+ struct power_supply_config psy_cfg = { .drv_data = battery, };
++ bool full_cap_broken = false;
++
++ if (!ACPI_BATTERY_CAPACITY_VALID(battery->full_charge_capacity) &&
++ !ACPI_BATTERY_CAPACITY_VALID(battery->design_capacity))
++ full_cap_broken = true;
+
+ if (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA) {
+- battery->bat_desc.properties = charge_battery_props;
+- battery->bat_desc.num_properties =
+- ARRAY_SIZE(charge_battery_props);
+- } else if (!ACPI_BATTERY_CAPACITY_VALID(
+- battery->full_charge_capacity)) {
+- battery->bat_desc.properties =
+- energy_battery_full_cap_broken_props;
+- battery->bat_desc.num_properties =
+- ARRAY_SIZE(energy_battery_full_cap_broken_props);
++ if (full_cap_broken) {
++ battery->bat_desc.properties =
++ charge_battery_full_cap_broken_props;
++ battery->bat_desc.num_properties =
++ ARRAY_SIZE(charge_battery_full_cap_broken_props);
++ } else {
++ battery->bat_desc.properties = charge_battery_props;
++ battery->bat_desc.num_properties =
++ ARRAY_SIZE(charge_battery_props);
++ }
+ } else {
+- battery->bat_desc.properties = energy_battery_props;
+- battery->bat_desc.num_properties =
+- ARRAY_SIZE(energy_battery_props);
++ if (full_cap_broken) {
++ battery->bat_desc.properties =
++ energy_battery_full_cap_broken_props;
++ battery->bat_desc.num_properties =
++ ARRAY_SIZE(energy_battery_full_cap_broken_props);
++ } else {
++ battery->bat_desc.properties = energy_battery_props;
++ battery->bat_desc.num_properties =
++ ARRAY_SIZE(energy_battery_props);
++ }
+ }
+
+ battery->bat_desc.name = acpi_device_bid(battery->device);
--- /dev/null
+From cc99f0ad52467028cb1251160f23ad4bb65baf20 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Tue, 10 Dec 2019 10:57:50 +0100
+Subject: ACPI / battery: Deal with design or full capacity being reported as -1
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+commit cc99f0ad52467028cb1251160f23ad4bb65baf20 upstream.
+
+Commit b41901a2cf06 ("ACPI / battery: Do not export energy_full[_design]
+on devices without full_charge_capacity") added support for some (broken)
+devices which always report 0 for both design- and full_charge-capacity.
+
+This assumes that if the capacity is not being reported it is 0. The
+ThunderSoft TS178 tablet's _BIX implementation falsifies this assumption.
+It reports ACPI_BATTERY_VALUE_UNKNOWN (-1) as full_charge_capacity, which
+we treat as a valid value which causes several problems.
+
+This commit fixes this by adding a new ACPI_BATTERY_CAPACITY_VALID() helper
+which checks that the value is not 0 and not -1; and using this whenever we
+need to test if either design_capacity or full_charge_capacity is valid.
+
+Fixes: b41901a2cf06 ("ACPI / battery: Do not export energy_full[_design] on devices without full_charge_capacity")
+Cc: 4.19+ <stable@vger.kernel.org> # 4.19+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/acpi/battery.c | 19 ++++++++++++-------
+ 1 file changed, 12 insertions(+), 7 deletions(-)
+
+--- a/drivers/acpi/battery.c
++++ b/drivers/acpi/battery.c
+@@ -51,6 +51,8 @@
+ #define PREFIX "ACPI: "
+
+ #define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF
++#define ACPI_BATTERY_CAPACITY_VALID(capacity) \
++ ((capacity) != 0 && (capacity) != ACPI_BATTERY_VALUE_UNKNOWN)
+
+ #define ACPI_BATTERY_DEVICE_NAME "Battery"
+
+@@ -205,7 +207,8 @@ static int acpi_battery_is_charged(struc
+
+ static bool acpi_battery_is_degraded(struct acpi_battery *battery)
+ {
+- return battery->full_charge_capacity && battery->design_capacity &&
++ return ACPI_BATTERY_CAPACITY_VALID(battery->full_charge_capacity) &&
++ ACPI_BATTERY_CAPACITY_VALID(battery->design_capacity) &&
+ battery->full_charge_capacity < battery->design_capacity;
+ }
+
+@@ -276,14 +279,14 @@ static int acpi_battery_get_property(str
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
+ case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
+- if (battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
++ if (!ACPI_BATTERY_CAPACITY_VALID(battery->design_capacity))
+ ret = -ENODEV;
+ else
+ val->intval = battery->design_capacity * 1000;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_FULL:
+ case POWER_SUPPLY_PROP_ENERGY_FULL:
+- if (battery->full_charge_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
++ if (!ACPI_BATTERY_CAPACITY_VALID(battery->full_charge_capacity))
+ ret = -ENODEV;
+ else
+ val->intval = battery->full_charge_capacity * 1000;
+@@ -296,11 +299,12 @@ static int acpi_battery_get_property(str
+ val->intval = battery->capacity_now * 1000;
+ break;
+ case POWER_SUPPLY_PROP_CAPACITY:
+- if (battery->capacity_now && battery->full_charge_capacity)
++ if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN ||
++ !ACPI_BATTERY_CAPACITY_VALID(battery->full_charge_capacity))
++ ret = -ENODEV;
++ else
+ val->intval = battery->capacity_now * 100/
+ battery->full_charge_capacity;
+- else
+- val->intval = 0;
+ break;
+ case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
+ if (battery->state & ACPI_BATTERY_STATE_CRITICAL)
+@@ -812,7 +816,8 @@ static int sysfs_add_battery(struct acpi
+ battery->bat_desc.properties = charge_battery_props;
+ battery->bat_desc.num_properties =
+ ARRAY_SIZE(charge_battery_props);
+- } else if (battery->full_charge_capacity == 0) {
++ } else if (!ACPI_BATTERY_CAPACITY_VALID(
++ battery->full_charge_capacity)) {
+ battery->bat_desc.properties =
+ energy_battery_full_cap_broken_props;
+ battery->bat_desc.num_properties =
--- /dev/null
+From 5b74d1d16e2f5753fcbdecd6771b2d8370dda414 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Tue, 10 Dec 2019 10:57:51 +0100
+Subject: ACPI / battery: Use design-cap for capacity calculations if full-cap is not available
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+commit 5b74d1d16e2f5753fcbdecd6771b2d8370dda414 upstream.
+
+The ThunderSoft TS178 tablet's _BIX implementation reports design_capacity
+but not full_charge_capacity.
+
+Before this commit this would cause us to return -ENODEV for the capacity
+attribute, which userspace does not like. Specifically upower does this:
+
+ if (sysfs_file_exists (native_path, "capacity")) {
+ percentage = sysfs_get_double (native_path, "capacity");
+
+Where the sysfs_get_double() helper returns 0 when we return -ENODEV,
+so the battery always reads 0% if we return -ENODEV.
+
+This commit fixes this by using the design-capacity instead of the
+full-charge-capacity when the full-charge-capacity is not available.
+
+Fixes: b41901a2cf06 ("ACPI / battery: Do not export energy_full[_design] on devices without full_charge_capacity")
+Cc: 4.19+ <stable@vger.kernel.org> # 4.19+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/acpi/battery.c | 11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+--- a/drivers/acpi/battery.c
++++ b/drivers/acpi/battery.c
+@@ -230,7 +230,7 @@ static int acpi_battery_get_property(str
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+ {
+- int ret = 0;
++ int full_capacity = ACPI_BATTERY_VALUE_UNKNOWN, ret = 0;
+ struct acpi_battery *battery = to_acpi_battery(psy);
+
+ if (acpi_battery_present(battery)) {
+@@ -299,12 +299,17 @@ static int acpi_battery_get_property(str
+ val->intval = battery->capacity_now * 1000;
+ break;
+ case POWER_SUPPLY_PROP_CAPACITY:
++ if (ACPI_BATTERY_CAPACITY_VALID(battery->full_charge_capacity))
++ full_capacity = battery->full_charge_capacity;
++ else if (ACPI_BATTERY_CAPACITY_VALID(battery->design_capacity))
++ full_capacity = battery->design_capacity;
++
+ if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN ||
+- !ACPI_BATTERY_CAPACITY_VALID(battery->full_charge_capacity))
++ full_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
+ ret = -ENODEV;
+ else
+ val->intval = battery->capacity_now * 100/
+- battery->full_charge_capacity;
++ full_capacity;
+ break;
+ case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
+ if (battery->state & ACPI_BATTERY_STATE_CRITICAL)
--- /dev/null
+From d21a91629f4b8e794fc4c0e0c17c85cedf1d806c Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Tue, 17 Dec 2019 20:08:11 +0100
+Subject: ACPI: video: Do not export a non working backlight interface on MSI MS-7721 boards
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+commit d21a91629f4b8e794fc4c0e0c17c85cedf1d806c upstream.
+
+Despite our heuristics to not wrongly export a non working ACPI backlight
+interface on desktop machines, we still end up exporting one on desktops
+using a motherboard from the MSI MS-7721 series.
+
+I've looked at improving the heuristics, but in this case a quirk seems
+to be the only way to solve this.
+
+While at it also add a comment to separate the video_detect_force_none
+entries in the video_detect_dmi_table from other type of entries, as we
+already do for the other entry types.
+
+Cc: All applicable <stable@vger.kernel.org>
+BugLink: https://bugzilla.redhat.com/show_bug.cgi?id=1783786
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/acpi/video_detect.c | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+--- a/drivers/acpi/video_detect.c
++++ b/drivers/acpi/video_detect.c
+@@ -328,6 +328,11 @@ static const struct dmi_system_id video_
+ DMI_MATCH(DMI_PRODUCT_NAME, "Precision 7510"),
+ },
+ },
++
++ /*
++ * Desktops which falsely report a backlight and which our heuristics
++ * for this do not catch.
++ */
+ {
+ .callback = video_detect_force_none,
+ .ident = "Dell OptiPlex 9020M",
+@@ -336,6 +341,14 @@ static const struct dmi_system_id video_
+ DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 9020M"),
+ },
+ },
++ {
++ .callback = video_detect_force_none,
++ .ident = "MSI MS-7721",
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "MSI"),
++ DMI_MATCH(DMI_PRODUCT_NAME, "MS-7721"),
++ },
++ },
+ { },
+ };
+
--- /dev/null
+From 6b6d188aae79a630957aefd88ff5c42af6553ee3 Mon Sep 17 00:00:00 2001
+From: Stephen Boyd <swboyd@chromium.org>
+Date: Thu, 9 Jan 2020 07:59:07 -0800
+Subject: alarmtimer: Unregister wakeup source when module get fails
+
+From: Stephen Boyd <swboyd@chromium.org>
+
+commit 6b6d188aae79a630957aefd88ff5c42af6553ee3 upstream.
+
+The alarmtimer_rtc_add_device() function creates a wakeup source and then
+tries to grab a module reference. If that fails the function returns early
+with an error code, but fails to remove the wakeup source.
+
+Cleanup this exit path so there is no dangling wakeup source, which is
+named 'alarmtime' left allocated which will conflict with another RTC
+device that may be registered later.
+
+Fixes: 51218298a25e ("alarmtimer: Ensure RTC module is not unloaded")
+Signed-off-by: Stephen Boyd <swboyd@chromium.org>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Reviewed-by: Douglas Anderson <dianders@chromium.org>
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20200109155910.907-2-swboyd@chromium.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ kernel/time/alarmtimer.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+--- a/kernel/time/alarmtimer.c
++++ b/kernel/time/alarmtimer.c
+@@ -91,6 +91,7 @@ static int alarmtimer_rtc_add_device(str
+ unsigned long flags;
+ struct rtc_device *rtc = to_rtc_device(dev);
+ struct wakeup_source *__ws;
++ int ret = 0;
+
+ if (rtcdev)
+ return -EBUSY;
+@@ -105,8 +106,8 @@ static int alarmtimer_rtc_add_device(str
+ spin_lock_irqsave(&rtcdev_lock, flags);
+ if (!rtcdev) {
+ if (!try_module_get(rtc->owner)) {
+- spin_unlock_irqrestore(&rtcdev_lock, flags);
+- return -1;
++ ret = -1;
++ goto unlock;
+ }
+
+ rtcdev = rtc;
+@@ -115,11 +116,12 @@ static int alarmtimer_rtc_add_device(str
+ ws = __ws;
+ __ws = NULL;
+ }
++unlock:
+ spin_unlock_irqrestore(&rtcdev_lock, flags);
+
+ wakeup_source_unregister(__ws);
+
+- return 0;
++ return ret;
+ }
+
+ static inline void alarmtimer_rtc_timer_init(void)
--- /dev/null
+From 4549f7e5aa27ffc2cba63b5db8842a3b486f5688 Mon Sep 17 00:00:00 2001
+From: Eric Biggers <ebiggers@google.com>
+Date: Thu, 10 Oct 2019 21:51:32 -0700
+Subject: crypto: geode-aes - convert to skcipher API and make thread-safe
+
+From: Eric Biggers <ebiggers@google.com>
+
+commit 4549f7e5aa27ffc2cba63b5db8842a3b486f5688 upstream.
+
+The geode AES driver is heavily broken because it stores per-request
+state in the transform context. So it will crash or produce the wrong
+result if used by any of the many places in the kernel that issue
+concurrent requests for the same transform object.
+
+This driver is also implemented using the deprecated blkcipher API,
+which makes it difficult to fix, and puts it among the drivers
+preventing that API from being removed.
+
+Convert this driver to use the skcipher API, and change it to not store
+per-request state in the transform context.
+
+Fixes: 9fe757b0cfce ("[PATCH] crypto: Add support for the Geode LX AES hardware")
+Signed-off-by: Eric Biggers <ebiggers@google.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Florian Bezdeka <florian@bezdeka.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/crypto/geode-aes.c | 450 +++++++++++++++------------------------------
+ drivers/crypto/geode-aes.h | 15 -
+ 2 files changed, 153 insertions(+), 312 deletions(-)
+
+--- a/drivers/crypto/geode-aes.c
++++ b/drivers/crypto/geode-aes.c
+@@ -14,7 +14,7 @@
+ #include <linux/spinlock.h>
+ #include <crypto/algapi.h>
+ #include <crypto/aes.h>
+-#include <crypto/skcipher.h>
++#include <crypto/internal/skcipher.h>
+
+ #include <linux/io.h>
+ #include <linux/delay.h>
+@@ -28,12 +28,12 @@ static spinlock_t lock;
+
+ /* Write a 128 bit field (either a writable key or IV) */
+ static inline void
+-_writefield(u32 offset, void *value)
++_writefield(u32 offset, const void *value)
+ {
+ int i;
+
+ for (i = 0; i < 4; i++)
+- iowrite32(((u32 *) value)[i], _iobase + offset + (i * 4));
++ iowrite32(((const u32 *) value)[i], _iobase + offset + (i * 4));
+ }
+
+ /* Read a 128 bit field (either a writable key or IV) */
+@@ -47,12 +47,12 @@ _readfield(u32 offset, void *value)
+ }
+
+ static int
+-do_crypt(void *src, void *dst, int len, u32 flags)
++do_crypt(const void *src, void *dst, u32 len, u32 flags)
+ {
+ u32 status;
+ u32 counter = AES_OP_TIMEOUT;
+
+- iowrite32(virt_to_phys(src), _iobase + AES_SOURCEA_REG);
++ iowrite32(virt_to_phys((void *)src), _iobase + AES_SOURCEA_REG);
+ iowrite32(virt_to_phys(dst), _iobase + AES_DSTA_REG);
+ iowrite32(len, _iobase + AES_LENA_REG);
+
+@@ -69,16 +69,14 @@ do_crypt(void *src, void *dst, int len,
+ return counter ? 0 : 1;
+ }
+
+-static unsigned int
+-geode_aes_crypt(struct geode_aes_op *op)
++static void
++geode_aes_crypt(const struct geode_aes_tfm_ctx *tctx, const void *src,
++ void *dst, u32 len, u8 *iv, int mode, int dir)
+ {
+ u32 flags = 0;
+ unsigned long iflags;
+ int ret;
+
+- if (op->len == 0)
+- return 0;
+-
+ /* If the source and destination is the same, then
+ * we need to turn on the coherent flags, otherwise
+ * we don't need to worry
+@@ -86,32 +84,28 @@ geode_aes_crypt(struct geode_aes_op *op)
+
+ flags |= (AES_CTRL_DCA | AES_CTRL_SCA);
+
+- if (op->dir == AES_DIR_ENCRYPT)
++ if (dir == AES_DIR_ENCRYPT)
+ flags |= AES_CTRL_ENCRYPT;
+
+ /* Start the critical section */
+
+ spin_lock_irqsave(&lock, iflags);
+
+- if (op->mode == AES_MODE_CBC) {
++ if (mode == AES_MODE_CBC) {
+ flags |= AES_CTRL_CBC;
+- _writefield(AES_WRITEIV0_REG, op->iv);
++ _writefield(AES_WRITEIV0_REG, iv);
+ }
+
+- if (!(op->flags & AES_FLAGS_HIDDENKEY)) {
+- flags |= AES_CTRL_WRKEY;
+- _writefield(AES_WRITEKEY0_REG, op->key);
+- }
++ flags |= AES_CTRL_WRKEY;
++ _writefield(AES_WRITEKEY0_REG, tctx->key);
+
+- ret = do_crypt(op->src, op->dst, op->len, flags);
++ ret = do_crypt(src, dst, len, flags);
+ BUG_ON(ret);
+
+- if (op->mode == AES_MODE_CBC)
+- _readfield(AES_WRITEIV0_REG, op->iv);
++ if (mode == AES_MODE_CBC)
++ _readfield(AES_WRITEIV0_REG, iv);
+
+ spin_unlock_irqrestore(&lock, iflags);
+-
+- return op->len;
+ }
+
+ /* CRYPTO-API Functions */
+@@ -119,13 +113,13 @@ geode_aes_crypt(struct geode_aes_op *op)
+ static int geode_setkey_cip(struct crypto_tfm *tfm, const u8 *key,
+ unsigned int len)
+ {
+- struct geode_aes_op *op = crypto_tfm_ctx(tfm);
++ struct geode_aes_tfm_ctx *tctx = crypto_tfm_ctx(tfm);
+ unsigned int ret;
+
+- op->keylen = len;
++ tctx->keylen = len;
+
+ if (len == AES_KEYSIZE_128) {
+- memcpy(op->key, key, len);
++ memcpy(tctx->key, key, len);
+ return 0;
+ }
+
+@@ -138,132 +132,93 @@ static int geode_setkey_cip(struct crypt
+ /*
+ * The requested key size is not supported by HW, do a fallback
+ */
+- op->fallback.cip->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK;
+- op->fallback.cip->base.crt_flags |= (tfm->crt_flags & CRYPTO_TFM_REQ_MASK);
++ tctx->fallback.cip->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK;
++ tctx->fallback.cip->base.crt_flags |=
++ (tfm->crt_flags & CRYPTO_TFM_REQ_MASK);
+
+- ret = crypto_cipher_setkey(op->fallback.cip, key, len);
++ ret = crypto_cipher_setkey(tctx->fallback.cip, key, len);
+ if (ret) {
+ tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK;
+- tfm->crt_flags |= (op->fallback.cip->base.crt_flags & CRYPTO_TFM_RES_MASK);
++ tfm->crt_flags |= (tctx->fallback.cip->base.crt_flags &
++ CRYPTO_TFM_RES_MASK);
+ }
+ return ret;
+ }
+
+-static int geode_setkey_blk(struct crypto_tfm *tfm, const u8 *key,
+- unsigned int len)
++static int geode_setkey_skcipher(struct crypto_skcipher *tfm, const u8 *key,
++ unsigned int len)
+ {
+- struct geode_aes_op *op = crypto_tfm_ctx(tfm);
++ struct geode_aes_tfm_ctx *tctx = crypto_skcipher_ctx(tfm);
+ unsigned int ret;
+
+- op->keylen = len;
++ tctx->keylen = len;
+
+ if (len == AES_KEYSIZE_128) {
+- memcpy(op->key, key, len);
++ memcpy(tctx->key, key, len);
+ return 0;
+ }
+
+ if (len != AES_KEYSIZE_192 && len != AES_KEYSIZE_256) {
+ /* not supported at all */
+- tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
++ crypto_skcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
+ return -EINVAL;
+ }
+
+ /*
+ * The requested key size is not supported by HW, do a fallback
+ */
+- crypto_skcipher_clear_flags(op->fallback.blk, CRYPTO_TFM_REQ_MASK);
+- crypto_skcipher_set_flags(op->fallback.blk,
+- tfm->crt_flags & CRYPTO_TFM_REQ_MASK);
+-
+- ret = crypto_skcipher_setkey(op->fallback.blk, key, len);
+- if (ret) {
+- tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK;
+- tfm->crt_flags |= crypto_skcipher_get_flags(op->fallback.blk) &
+- CRYPTO_TFM_RES_MASK;
+- }
++ crypto_skcipher_clear_flags(tctx->fallback.skcipher,
++ CRYPTO_TFM_REQ_MASK);
++ crypto_skcipher_set_flags(tctx->fallback.skcipher,
++ crypto_skcipher_get_flags(tfm) &
++ CRYPTO_TFM_REQ_MASK);
++ ret = crypto_skcipher_setkey(tctx->fallback.skcipher, key, len);
++ crypto_skcipher_set_flags(tfm,
++ crypto_skcipher_get_flags(tctx->fallback.skcipher) &
++ CRYPTO_TFM_RES_MASK);
+ return ret;
+ }
+
+-static int fallback_blk_dec(struct blkcipher_desc *desc,
+- struct scatterlist *dst, struct scatterlist *src,
+- unsigned int nbytes)
+-{
+- struct geode_aes_op *op = crypto_blkcipher_ctx(desc->tfm);
+- SKCIPHER_REQUEST_ON_STACK(req, op->fallback.blk);
+-
+- skcipher_request_set_tfm(req, op->fallback.blk);
+- skcipher_request_set_callback(req, 0, NULL, NULL);
+- skcipher_request_set_crypt(req, src, dst, nbytes, desc->info);
+-
+- return crypto_skcipher_decrypt(req);
+-}
+-
+-static int fallback_blk_enc(struct blkcipher_desc *desc,
+- struct scatterlist *dst, struct scatterlist *src,
+- unsigned int nbytes)
+-{
+- struct geode_aes_op *op = crypto_blkcipher_ctx(desc->tfm);
+- SKCIPHER_REQUEST_ON_STACK(req, op->fallback.blk);
+-
+- skcipher_request_set_tfm(req, op->fallback.blk);
+- skcipher_request_set_callback(req, 0, NULL, NULL);
+- skcipher_request_set_crypt(req, src, dst, nbytes, desc->info);
+-
+- return crypto_skcipher_encrypt(req);
+-}
+-
+ static void
+ geode_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
+ {
+- struct geode_aes_op *op = crypto_tfm_ctx(tfm);
++ const struct geode_aes_tfm_ctx *tctx = crypto_tfm_ctx(tfm);
+
+- if (unlikely(op->keylen != AES_KEYSIZE_128)) {
+- crypto_cipher_encrypt_one(op->fallback.cip, out, in);
++ if (unlikely(tctx->keylen != AES_KEYSIZE_128)) {
++ crypto_cipher_encrypt_one(tctx->fallback.cip, out, in);
+ return;
+ }
+
+- op->src = (void *) in;
+- op->dst = (void *) out;
+- op->mode = AES_MODE_ECB;
+- op->flags = 0;
+- op->len = AES_BLOCK_SIZE;
+- op->dir = AES_DIR_ENCRYPT;
+-
+- geode_aes_crypt(op);
++ geode_aes_crypt(tctx, in, out, AES_BLOCK_SIZE, NULL,
++ AES_MODE_ECB, AES_DIR_ENCRYPT);
+ }
+
+
+ static void
+ geode_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
+ {
+- struct geode_aes_op *op = crypto_tfm_ctx(tfm);
++ const struct geode_aes_tfm_ctx *tctx = crypto_tfm_ctx(tfm);
+
+- if (unlikely(op->keylen != AES_KEYSIZE_128)) {
+- crypto_cipher_decrypt_one(op->fallback.cip, out, in);
++ if (unlikely(tctx->keylen != AES_KEYSIZE_128)) {
++ crypto_cipher_decrypt_one(tctx->fallback.cip, out, in);
+ return;
+ }
+
+- op->src = (void *) in;
+- op->dst = (void *) out;
+- op->mode = AES_MODE_ECB;
+- op->flags = 0;
+- op->len = AES_BLOCK_SIZE;
+- op->dir = AES_DIR_DECRYPT;
+-
+- geode_aes_crypt(op);
++ geode_aes_crypt(tctx, in, out, AES_BLOCK_SIZE, NULL,
++ AES_MODE_ECB, AES_DIR_DECRYPT);
+ }
+
+ static int fallback_init_cip(struct crypto_tfm *tfm)
+ {
+ const char *name = crypto_tfm_alg_name(tfm);
+- struct geode_aes_op *op = crypto_tfm_ctx(tfm);
++ struct geode_aes_tfm_ctx *tctx = crypto_tfm_ctx(tfm);
+
+- op->fallback.cip = crypto_alloc_cipher(name, 0,
+- CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK);
++ tctx->fallback.cip = crypto_alloc_cipher(name, 0,
++ CRYPTO_ALG_NEED_FALLBACK);
+
+- if (IS_ERR(op->fallback.cip)) {
++ if (IS_ERR(tctx->fallback.cip)) {
+ printk(KERN_ERR "Error allocating fallback algo %s\n", name);
+- return PTR_ERR(op->fallback.cip);
++ return PTR_ERR(tctx->fallback.cip);
+ }
+
+ return 0;
+@@ -271,10 +226,9 @@ static int fallback_init_cip(struct cryp
+
+ static void fallback_exit_cip(struct crypto_tfm *tfm)
+ {
+- struct geode_aes_op *op = crypto_tfm_ctx(tfm);
++ struct geode_aes_tfm_ctx *tctx = crypto_tfm_ctx(tfm);
+
+- crypto_free_cipher(op->fallback.cip);
+- op->fallback.cip = NULL;
++ crypto_free_cipher(tctx->fallback.cip);
+ }
+
+ static struct crypto_alg geode_alg = {
+@@ -287,7 +241,7 @@ static struct crypto_alg geode_alg = {
+ .cra_init = fallback_init_cip,
+ .cra_exit = fallback_exit_cip,
+ .cra_blocksize = AES_BLOCK_SIZE,
+- .cra_ctxsize = sizeof(struct geode_aes_op),
++ .cra_ctxsize = sizeof(struct geode_aes_tfm_ctx),
+ .cra_module = THIS_MODULE,
+ .cra_u = {
+ .cipher = {
+@@ -300,222 +254,126 @@ static struct crypto_alg geode_alg = {
+ }
+ };
+
+-static int
+-geode_cbc_decrypt(struct blkcipher_desc *desc,
+- struct scatterlist *dst, struct scatterlist *src,
+- unsigned int nbytes)
+-{
+- struct geode_aes_op *op = crypto_blkcipher_ctx(desc->tfm);
+- struct blkcipher_walk walk;
+- int err, ret;
+-
+- if (nbytes % AES_BLOCK_SIZE)
+- return -EINVAL;
+-
+- if (unlikely(op->keylen != AES_KEYSIZE_128))
+- return fallback_blk_dec(desc, dst, src, nbytes);
+-
+- blkcipher_walk_init(&walk, dst, src, nbytes);
+- err = blkcipher_walk_virt(desc, &walk);
+- op->iv = walk.iv;
+-
+- while ((nbytes = walk.nbytes)) {
+- op->src = walk.src.virt.addr,
+- op->dst = walk.dst.virt.addr;
+- op->mode = AES_MODE_CBC;
+- op->len = nbytes - (nbytes % AES_BLOCK_SIZE);
+- op->dir = AES_DIR_DECRYPT;
+-
+- ret = geode_aes_crypt(op);
+-
+- nbytes -= ret;
+- err = blkcipher_walk_done(desc, &walk, nbytes);
+- }
+-
+- return err;
+-}
+-
+-static int
+-geode_cbc_encrypt(struct blkcipher_desc *desc,
+- struct scatterlist *dst, struct scatterlist *src,
+- unsigned int nbytes)
+-{
+- struct geode_aes_op *op = crypto_blkcipher_ctx(desc->tfm);
+- struct blkcipher_walk walk;
+- int err, ret;
+-
+- if (nbytes % AES_BLOCK_SIZE)
+- return -EINVAL;
+-
+- if (unlikely(op->keylen != AES_KEYSIZE_128))
+- return fallback_blk_enc(desc, dst, src, nbytes);
+-
+- blkcipher_walk_init(&walk, dst, src, nbytes);
+- err = blkcipher_walk_virt(desc, &walk);
+- op->iv = walk.iv;
+-
+- while ((nbytes = walk.nbytes)) {
+- op->src = walk.src.virt.addr,
+- op->dst = walk.dst.virt.addr;
+- op->mode = AES_MODE_CBC;
+- op->len = nbytes - (nbytes % AES_BLOCK_SIZE);
+- op->dir = AES_DIR_ENCRYPT;
+-
+- ret = geode_aes_crypt(op);
+- nbytes -= ret;
+- err = blkcipher_walk_done(desc, &walk, nbytes);
+- }
+-
+- return err;
+-}
+-
+-static int fallback_init_blk(struct crypto_tfm *tfm)
++static int geode_init_skcipher(struct crypto_skcipher *tfm)
+ {
+- const char *name = crypto_tfm_alg_name(tfm);
+- struct geode_aes_op *op = crypto_tfm_ctx(tfm);
+-
+- op->fallback.blk = crypto_alloc_skcipher(name, 0,
+- CRYPTO_ALG_ASYNC |
+- CRYPTO_ALG_NEED_FALLBACK);
++ const char *name = crypto_tfm_alg_name(&tfm->base);
++ struct geode_aes_tfm_ctx *tctx = crypto_skcipher_ctx(tfm);
+
+- if (IS_ERR(op->fallback.blk)) {
++ tctx->fallback.skcipher =
++ crypto_alloc_skcipher(name, 0, CRYPTO_ALG_NEED_FALLBACK |
++ CRYPTO_ALG_ASYNC);
++ if (IS_ERR(tctx->fallback.skcipher)) {
+ printk(KERN_ERR "Error allocating fallback algo %s\n", name);
+- return PTR_ERR(op->fallback.blk);
++ return PTR_ERR(tctx->fallback.skcipher);
+ }
+
++ crypto_skcipher_set_reqsize(tfm, sizeof(struct skcipher_request) +
++ crypto_skcipher_reqsize(tctx->fallback.skcipher));
+ return 0;
+ }
+
+-static void fallback_exit_blk(struct crypto_tfm *tfm)
++static void geode_exit_skcipher(struct crypto_skcipher *tfm)
+ {
+- struct geode_aes_op *op = crypto_tfm_ctx(tfm);
++ struct geode_aes_tfm_ctx *tctx = crypto_skcipher_ctx(tfm);
+
+- crypto_free_skcipher(op->fallback.blk);
+- op->fallback.blk = NULL;
++ crypto_free_skcipher(tctx->fallback.skcipher);
+ }
+
+-static struct crypto_alg geode_cbc_alg = {
+- .cra_name = "cbc(aes)",
+- .cra_driver_name = "cbc-aes-geode",
+- .cra_priority = 400,
+- .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER |
+- CRYPTO_ALG_KERN_DRIVER_ONLY |
+- CRYPTO_ALG_NEED_FALLBACK,
+- .cra_init = fallback_init_blk,
+- .cra_exit = fallback_exit_blk,
+- .cra_blocksize = AES_BLOCK_SIZE,
+- .cra_ctxsize = sizeof(struct geode_aes_op),
+- .cra_alignmask = 15,
+- .cra_type = &crypto_blkcipher_type,
+- .cra_module = THIS_MODULE,
+- .cra_u = {
+- .blkcipher = {
+- .min_keysize = AES_MIN_KEY_SIZE,
+- .max_keysize = AES_MAX_KEY_SIZE,
+- .setkey = geode_setkey_blk,
+- .encrypt = geode_cbc_encrypt,
+- .decrypt = geode_cbc_decrypt,
+- .ivsize = AES_BLOCK_SIZE,
+- }
+- }
+-};
+-
+-static int
+-geode_ecb_decrypt(struct blkcipher_desc *desc,
+- struct scatterlist *dst, struct scatterlist *src,
+- unsigned int nbytes)
+-{
+- struct geode_aes_op *op = crypto_blkcipher_ctx(desc->tfm);
+- struct blkcipher_walk walk;
+- int err, ret;
++static int geode_skcipher_crypt(struct skcipher_request *req, int mode, int dir)
++{
++ struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
++ const struct geode_aes_tfm_ctx *tctx = crypto_skcipher_ctx(tfm);
++ struct skcipher_walk walk;
++ unsigned int nbytes;
++ int err;
+
+- if (nbytes % AES_BLOCK_SIZE)
+- return -EINVAL;
++ if (unlikely(tctx->keylen != AES_KEYSIZE_128)) {
++ struct skcipher_request *subreq = skcipher_request_ctx(req);
+
+- if (unlikely(op->keylen != AES_KEYSIZE_128))
+- return fallback_blk_dec(desc, dst, src, nbytes);
++ *subreq = *req;
++ skcipher_request_set_tfm(subreq, tctx->fallback.skcipher);
++ if (dir == AES_DIR_DECRYPT)
++ return crypto_skcipher_decrypt(subreq);
++ else
++ return crypto_skcipher_encrypt(subreq);
++ }
+
+- blkcipher_walk_init(&walk, dst, src, nbytes);
+- err = blkcipher_walk_virt(desc, &walk);
++ err = skcipher_walk_virt(&walk, req, false);
+
+- while ((nbytes = walk.nbytes)) {
+- op->src = walk.src.virt.addr,
+- op->dst = walk.dst.virt.addr;
+- op->mode = AES_MODE_ECB;
+- op->len = nbytes - (nbytes % AES_BLOCK_SIZE);
+- op->dir = AES_DIR_DECRYPT;
+-
+- ret = geode_aes_crypt(op);
+- nbytes -= ret;
+- err = blkcipher_walk_done(desc, &walk, nbytes);
++ while ((nbytes = walk.nbytes) != 0) {
++ geode_aes_crypt(tctx, walk.src.virt.addr, walk.dst.virt.addr,
++ round_down(nbytes, AES_BLOCK_SIZE),
++ walk.iv, mode, dir);
++ err = skcipher_walk_done(&walk, nbytes % AES_BLOCK_SIZE);
+ }
+
+ return err;
+ }
+
+-static int
+-geode_ecb_encrypt(struct blkcipher_desc *desc,
+- struct scatterlist *dst, struct scatterlist *src,
+- unsigned int nbytes)
+-{
+- struct geode_aes_op *op = crypto_blkcipher_ctx(desc->tfm);
+- struct blkcipher_walk walk;
+- int err, ret;
+-
+- if (nbytes % AES_BLOCK_SIZE)
+- return -EINVAL;
+-
+- if (unlikely(op->keylen != AES_KEYSIZE_128))
+- return fallback_blk_enc(desc, dst, src, nbytes);
+-
+- blkcipher_walk_init(&walk, dst, src, nbytes);
+- err = blkcipher_walk_virt(desc, &walk);
+-
+- while ((nbytes = walk.nbytes)) {
+- op->src = walk.src.virt.addr,
+- op->dst = walk.dst.virt.addr;
+- op->mode = AES_MODE_ECB;
+- op->len = nbytes - (nbytes % AES_BLOCK_SIZE);
+- op->dir = AES_DIR_ENCRYPT;
+-
+- ret = geode_aes_crypt(op);
+- nbytes -= ret;
+- ret = blkcipher_walk_done(desc, &walk, nbytes);
+- }
++static int geode_cbc_encrypt(struct skcipher_request *req)
++{
++ return geode_skcipher_crypt(req, AES_MODE_CBC, AES_DIR_ENCRYPT);
++}
+
+- return err;
++static int geode_cbc_decrypt(struct skcipher_request *req)
++{
++ return geode_skcipher_crypt(req, AES_MODE_CBC, AES_DIR_DECRYPT);
+ }
+
+-static struct crypto_alg geode_ecb_alg = {
+- .cra_name = "ecb(aes)",
+- .cra_driver_name = "ecb-aes-geode",
+- .cra_priority = 400,
+- .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER |
+- CRYPTO_ALG_KERN_DRIVER_ONLY |
+- CRYPTO_ALG_NEED_FALLBACK,
+- .cra_init = fallback_init_blk,
+- .cra_exit = fallback_exit_blk,
+- .cra_blocksize = AES_BLOCK_SIZE,
+- .cra_ctxsize = sizeof(struct geode_aes_op),
+- .cra_alignmask = 15,
+- .cra_type = &crypto_blkcipher_type,
+- .cra_module = THIS_MODULE,
+- .cra_u = {
+- .blkcipher = {
+- .min_keysize = AES_MIN_KEY_SIZE,
+- .max_keysize = AES_MAX_KEY_SIZE,
+- .setkey = geode_setkey_blk,
+- .encrypt = geode_ecb_encrypt,
+- .decrypt = geode_ecb_decrypt,
+- }
+- }
++static int geode_ecb_encrypt(struct skcipher_request *req)
++{
++ return geode_skcipher_crypt(req, AES_MODE_ECB, AES_DIR_ENCRYPT);
++}
++
++static int geode_ecb_decrypt(struct skcipher_request *req)
++{
++ return geode_skcipher_crypt(req, AES_MODE_ECB, AES_DIR_DECRYPT);
++}
++
++static struct skcipher_alg geode_skcipher_algs[] = {
++ {
++ .base.cra_name = "cbc(aes)",
++ .base.cra_driver_name = "cbc-aes-geode",
++ .base.cra_priority = 400,
++ .base.cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY |
++ CRYPTO_ALG_NEED_FALLBACK,
++ .base.cra_blocksize = AES_BLOCK_SIZE,
++ .base.cra_ctxsize = sizeof(struct geode_aes_tfm_ctx),
++ .base.cra_alignmask = 15,
++ .base.cra_module = THIS_MODULE,
++ .init = geode_init_skcipher,
++ .exit = geode_exit_skcipher,
++ .setkey = geode_setkey_skcipher,
++ .encrypt = geode_cbc_encrypt,
++ .decrypt = geode_cbc_decrypt,
++ .min_keysize = AES_MIN_KEY_SIZE,
++ .max_keysize = AES_MAX_KEY_SIZE,
++ .ivsize = AES_BLOCK_SIZE,
++ }, {
++ .base.cra_name = "ecb(aes)",
++ .base.cra_driver_name = "ecb-aes-geode",
++ .base.cra_priority = 400,
++ .base.cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY |
++ CRYPTO_ALG_NEED_FALLBACK,
++ .base.cra_blocksize = AES_BLOCK_SIZE,
++ .base.cra_ctxsize = sizeof(struct geode_aes_tfm_ctx),
++ .base.cra_alignmask = 15,
++ .base.cra_module = THIS_MODULE,
++ .init = geode_init_skcipher,
++ .exit = geode_exit_skcipher,
++ .setkey = geode_setkey_skcipher,
++ .encrypt = geode_ecb_encrypt,
++ .decrypt = geode_ecb_decrypt,
++ .min_keysize = AES_MIN_KEY_SIZE,
++ .max_keysize = AES_MAX_KEY_SIZE,
++ },
+ };
+
+ static void geode_aes_remove(struct pci_dev *dev)
+ {
+ crypto_unregister_alg(&geode_alg);
+- crypto_unregister_alg(&geode_ecb_alg);
+- crypto_unregister_alg(&geode_cbc_alg);
++ crypto_unregister_skciphers(geode_skcipher_algs,
++ ARRAY_SIZE(geode_skcipher_algs));
+
+ pci_iounmap(dev, _iobase);
+ _iobase = NULL;
+@@ -553,20 +411,14 @@ static int geode_aes_probe(struct pci_de
+ if (ret)
+ goto eiomap;
+
+- ret = crypto_register_alg(&geode_ecb_alg);
++ ret = crypto_register_skciphers(geode_skcipher_algs,
++ ARRAY_SIZE(geode_skcipher_algs));
+ if (ret)
+ goto ealg;
+
+- ret = crypto_register_alg(&geode_cbc_alg);
+- if (ret)
+- goto eecb;
+-
+ dev_notice(&dev->dev, "GEODE AES engine enabled.\n");
+ return 0;
+
+- eecb:
+- crypto_unregister_alg(&geode_ecb_alg);
+-
+ ealg:
+ crypto_unregister_alg(&geode_alg);
+
+--- a/drivers/crypto/geode-aes.h
++++ b/drivers/crypto/geode-aes.h
+@@ -50,21 +50,10 @@
+
+ #define AES_OP_TIMEOUT 0x50000
+
+-struct geode_aes_op {
+-
+- void *src;
+- void *dst;
+-
+- u32 mode;
+- u32 dir;
+- u32 flags;
+- int len;
+-
++struct geode_aes_tfm_ctx {
+ u8 key[AES_KEYSIZE_128];
+- u8 *iv;
+-
+ union {
+- struct crypto_skcipher *blk;
++ struct crypto_skcipher *skcipher;
+ struct crypto_cipher *cip;
+ } fallback;
+ u32 keylen;
--- /dev/null
+From af3ed119329cf9690598c5a562d95dfd128e91d6 Mon Sep 17 00:00:00 2001
+From: Linus Walleij <linus.walleij@linaro.org>
+Date: Wed, 4 Dec 2019 16:27:49 +0100
+Subject: mmc: spi: Toggle SPI polarity, do not hardcode it
+
+From: Linus Walleij <linus.walleij@linaro.org>
+
+commit af3ed119329cf9690598c5a562d95dfd128e91d6 upstream.
+
+The code in mmc_spi_initsequence() tries to send a burst with
+high chipselect and for this reason hardcodes the device into
+SPI_CS_HIGH.
+
+This is not good because the SPI_CS_HIGH flag indicates
+logical "asserted" CS not always the physical level. In
+some cases the signal is inverted in the GPIO library and
+in that case SPI_CS_HIGH is already set, and enforcing
+SPI_CS_HIGH again will actually drive it low.
+
+Instead of hard-coding this, toggle the polarity so if the
+default is LOW it goes high to assert chipselect but if it
+is already high then toggle it low instead.
+
+Cc: Phil Elwell <phil@raspberrypi.org>
+Reported-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Reviewed-by: Mark Brown <broonie@kernel.org>
+Link: https://lore.kernel.org/r/20191204152749.12652-1-linus.walleij@linaro.org
+Cc: stable@vger.kernel.org
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/mmc/host/mmc_spi.c | 11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+--- a/drivers/mmc/host/mmc_spi.c
++++ b/drivers/mmc/host/mmc_spi.c
+@@ -1154,17 +1154,22 @@ static void mmc_spi_initsequence(struct
+ * SPI protocol. Another is that when chipselect is released while
+ * the card returns BUSY status, the clock must issue several cycles
+ * with chipselect high before the card will stop driving its output.
++ *
++ * SPI_CS_HIGH means "asserted" here. In some cases like when using
++ * GPIOs for chip select, SPI_CS_HIGH is set but this will be logically
++ * inverted by gpiolib, so if we want to ascertain to drive it high
++ * we should toggle the default with an XOR as we do here.
+ */
+- host->spi->mode |= SPI_CS_HIGH;
++ host->spi->mode ^= SPI_CS_HIGH;
+ if (spi_setup(host->spi) != 0) {
+ /* Just warn; most cards work without it. */
+ dev_warn(&host->spi->dev,
+ "can't change chip-select polarity\n");
+- host->spi->mode &= ~SPI_CS_HIGH;
++ host->spi->mode ^= SPI_CS_HIGH;
+ } else {
+ mmc_spi_readbytes(host, 18);
+
+- host->spi->mode &= ~SPI_CS_HIGH;
++ host->spi->mode ^= SPI_CS_HIGH;
+ if (spi_setup(host->spi) != 0) {
+ /* Wot, we can't get the same setup we had before? */
+ dev_err(&host->spi->dev,
--- /dev/null
+From 885199148442f56b880995d703d2ed03b6481a3c Mon Sep 17 00:00:00 2001
+From: David Engraf <david.engraf@sysgo.com>
+Date: Mon, 16 Dec 2019 12:18:25 +0100
+Subject: PCI: tegra: Fix return value check of pm_runtime_get_sync()
+
+From: David Engraf <david.engraf@sysgo.com>
+
+commit 885199148442f56b880995d703d2ed03b6481a3c upstream.
+
+pm_runtime_get_sync() returns the device's usage counter. This might
+be >0 if the device is already powered up or CONFIG_PM is disabled.
+
+Abort probe function on real error only.
+
+Fixes: da76ba50963b ("PCI: tegra: Add power management support")
+Link: https://lore.kernel.org/r/20191216111825.28136-1-david.engraf@sysgo.com
+Signed-off-by: David Engraf <david.engraf@sysgo.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Acked-by: Andrew Murray <andrew.murray@arm.com>
+Cc: stable@vger.kernel.org # v4.17+
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/pci/controller/pci-tegra.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/pci/controller/pci-tegra.c
++++ b/drivers/pci/controller/pci-tegra.c
+@@ -2398,7 +2398,7 @@ static int tegra_pcie_probe(struct platf
+
+ pm_runtime_enable(pcie->dev);
+ err = pm_runtime_get_sync(pcie->dev);
+- if (err) {
++ if (err < 0) {
+ dev_err(dev, "fail to enable pcie controller: %d\n", err);
+ goto teardown_msi;
+ }
powerpc-xmon-don-t-access-asdr-in-vms.patch
powerpc-pseries-advance-pfn-if-section-is-not-present-in-lmb_is_removable.patch
smb3-fix-signing-verification-of-large-reads.patch
+crypto-geode-aes-convert-to-skcipher-api-and-make-thread-safe.patch
+pci-tegra-fix-return-value-check-of-pm_runtime_get_sync.patch
+mmc-spi-toggle-spi-polarity-do-not-hardcode-it.patch
+acpi-video-do-not-export-a-non-working-backlight-interface-on-msi-ms-7721-boards.patch
+acpi-battery-deal-with-design-or-full-capacity-being-reported-as-1.patch
+acpi-battery-use-design-cap-for-capacity-calculations-if-full-cap-is-not-available.patch
+acpi-battery-deal-better-with-neither-design-nor-full-capacity-not-being-reported.patch
+alarmtimer-unregister-wakeup-source-when-module-get-fails.patch
+ubifs-reject-unsupported-ioctl-flags-explicitly.patch
+ubifs-don-t-trigger-assertion-on-invalid-no-key-filename.patch
+ubifs-fix-fs_ioc_setflags-unexpectedly-clearing-encrypt-flag.patch
+ubifs-fix-deadlock-in-concurrent-bulk-read-and-writepage.patch
Reviewed-by: Ronnie Sahlberg <lsahlber@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
- fs/cifs/smb2pdu.c | 4 ++--
+ fs/cifs/smb2pdu.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
-diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
-index 43f29621e51ff..93ef1d8e82c75 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
-@@ -3130,8 +3130,8 @@ smb2_readv_callback(struct mid_q_entry *mid)
+@@ -3130,8 +3130,8 @@ smb2_readv_callback(struct mid_q_entry *
struct smb2_sync_hdr *shdr =
(struct smb2_sync_hdr *)rdata->iov[0].iov_base;
unsigned int credits_received = 0;
.rq_pages = rdata->pages,
.rq_offset = rdata->page_offset,
.rq_npages = rdata->nr_pages,
---
-2.20.1
-
--- /dev/null
+From f0d07a98a070bb5e443df19c3aa55693cbca9341 Mon Sep 17 00:00:00 2001
+From: Eric Biggers <ebiggers@google.com>
+Date: Mon, 20 Jan 2020 14:31:59 -0800
+Subject: ubifs: don't trigger assertion on invalid no-key filename
+
+From: Eric Biggers <ebiggers@google.com>
+
+commit f0d07a98a070bb5e443df19c3aa55693cbca9341 upstream.
+
+If userspace provides an invalid fscrypt no-key filename which encodes a
+hash value with any of the UBIFS node type bits set (i.e. the high 3
+bits), gracefully report ENOENT rather than triggering ubifs_assert().
+
+Test case with kvm-xfstests shell:
+
+ . fs/ubifs/config
+ . ~/xfstests/common/encrypt
+ dev=$(__blkdev_to_ubi_volume /dev/vdc)
+ ubiupdatevol $dev -t
+ mount $dev /mnt -t ubifs
+ mkdir /mnt/edir
+ xfs_io -c set_encpolicy /mnt/edir
+ rm /mnt/edir/_,,,,,DAAAAAAAAAAAAAAAAAAAAAAAAAA
+
+With the bug, the following assertion fails on the 'rm' command:
+
+ [ 19.066048] UBIFS error (ubi0:0 pid 379): ubifs_assert_failed: UBIFS assert failed: !(hash & ~UBIFS_S_KEY_HASH_MASK), in fs/ubifs/key.h:170
+
+Fixes: f4f61d2cc6d8 ("ubifs: Implement encrypted filenames")
+Cc: <stable@vger.kernel.org> # v4.10+
+Link: https://lore.kernel.org/r/20200120223201.241390-5-ebiggers@kernel.org
+Signed-off-by: Eric Biggers <ebiggers@google.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ubifs/dir.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/fs/ubifs/dir.c
++++ b/fs/ubifs/dir.c
+@@ -242,6 +242,8 @@ static struct dentry *ubifs_lookup(struc
+ if (nm.hash) {
+ ubifs_assert(c, fname_len(&nm) == 0);
+ ubifs_assert(c, fname_name(&nm) == NULL);
++ if (nm.hash & ~UBIFS_S_KEY_HASH_MASK)
++ goto done; /* ENOENT */
+ dent_key_init_hash(c, &key, dir->i_ino, nm.hash);
+ err = ubifs_tnc_lookup_dh(c, &key, dent, nm.minor_hash);
+ } else {
--- /dev/null
+From f5de5b83303e61b1f3fb09bd77ce3ac2d7a475f2 Mon Sep 17 00:00:00 2001
+From: Zhihao Cheng <chengzhihao1@huawei.com>
+Date: Sat, 11 Jan 2020 17:50:36 +0800
+Subject: ubifs: Fix deadlock in concurrent bulk-read and writepage
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Zhihao Cheng <chengzhihao1@huawei.com>
+
+commit f5de5b83303e61b1f3fb09bd77ce3ac2d7a475f2 upstream.
+
+In ubifs, concurrent execution of writepage and bulk read on the same file
+may cause ABBA deadlock, for example (Reproduce method see Link):
+
+Process A(Bulk-read starts from page4) Process B(write page4 back)
+ vfs_read wb_workfn or fsync
+ ... ...
+ generic_file_buffered_read write_cache_pages
+ ubifs_readpage LOCK(page4)
+
+ ubifs_bulk_read ubifs_writepage
+ LOCK(ui->ui_mutex) ubifs_write_inode
+
+ ubifs_do_bulk_read LOCK(ui->ui_mutex)
+ find_or_create_page(alloc page4) ↑
+ LOCK(page4) <-- ABBA deadlock occurs!
+
+In order to ensure the serialization execution of bulk read, we can't
+remove the big lock 'ui->ui_mutex' in ubifs_bulk_read(). Instead, we
+allow ubifs_do_bulk_read() to lock page failed by replacing
+find_or_create_page(FGP_LOCK) with
+pagecache_get_page(FGP_LOCK | FGP_NOWAIT).
+
+Signed-off-by: Zhihao Cheng <chengzhihao1@huawei.com>
+Suggested-by: zhangyi (F) <yi.zhang@huawei.com>
+Cc: <Stable@vger.kernel.org>
+Fixes: 4793e7c5e1c ("UBIFS: add bulk-read facility")
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=206153
+Signed-off-by: Richard Weinberger <richard@nod.at>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ubifs/file.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/fs/ubifs/file.c
++++ b/fs/ubifs/file.c
+@@ -798,7 +798,9 @@ static int ubifs_do_bulk_read(struct ubi
+
+ if (page_offset > end_index)
+ break;
+- page = find_or_create_page(mapping, page_offset, ra_gfp_mask);
++ page = pagecache_get_page(mapping, page_offset,
++ FGP_LOCK|FGP_ACCESSED|FGP_CREAT|FGP_NOWAIT,
++ ra_gfp_mask);
+ if (!page)
+ break;
+ if (!PageUptodate(page))
--- /dev/null
+From 2b57067a7778484c10892fa191997bfda29fea13 Mon Sep 17 00:00:00 2001
+From: Eric Biggers <ebiggers@google.com>
+Date: Mon, 9 Dec 2019 14:23:24 -0800
+Subject: ubifs: Fix FS_IOC_SETFLAGS unexpectedly clearing encrypt flag
+
+From: Eric Biggers <ebiggers@google.com>
+
+commit 2b57067a7778484c10892fa191997bfda29fea13 upstream.
+
+UBIFS's implementation of FS_IOC_SETFLAGS fails to preserve existing
+inode flags that aren't settable by FS_IOC_SETFLAGS, namely the encrypt
+flag. This causes the encrypt flag to be unexpectedly cleared.
+
+Fix it by preserving existing unsettable flags, like ext4 and f2fs do.
+
+Test case with kvm-xfstests shell:
+
+ FSTYP=ubifs KEYCTL_PROG=keyctl
+ . fs/ubifs/config
+ . ~/xfstests/common/encrypt
+ dev=$(__blkdev_to_ubi_volume /dev/vdc)
+ ubiupdatevol -t $dev
+ mount $dev /mnt -t ubifs
+ k=$(_generate_session_encryption_key)
+ mkdir /mnt/edir
+ xfs_io -c "set_encpolicy $k" /mnt/edir
+ echo contents > /mnt/edir/file
+ chattr +i /mnt/edir/file
+ chattr -i /mnt/edir/file
+
+With the bug, the following errors occur on the last command:
+
+ [ 18.081559] fscrypt (ubifs, inode 67): Inconsistent encryption context (parent directory: 65)
+ chattr: Operation not permitted while reading flags on /mnt/edir/file
+
+Fixes: d475a507457b ("ubifs: Add skeleton for fscrypto")
+Cc: <stable@vger.kernel.org> # v4.10+
+Signed-off-by: Eric Biggers <ebiggers@google.com>
+Signed-off-by: Richard Weinberger <richard@nod.at>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ubifs/ioctl.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/fs/ubifs/ioctl.c
++++ b/fs/ubifs/ioctl.c
+@@ -132,7 +132,8 @@ static int setflags(struct inode *inode,
+ }
+ }
+
+- ui->flags = ioctl2ubifs(flags);
++ ui->flags &= ~ioctl2ubifs(UBIFS_SUPPORTED_IOCTL_FLAGS);
++ ui->flags |= ioctl2ubifs(flags);
+ ubifs_set_inode_flags(inode);
+ inode->i_ctime = current_time(inode);
+ release = ui->dirty;
--- /dev/null
+From 2fe8b2d5578d7d142982e3bf62e4c0caf8b8fe02 Mon Sep 17 00:00:00 2001
+From: Hou Tao <houtao1@huawei.com>
+Date: Sat, 9 Feb 2019 16:54:20 +0800
+Subject: ubifs: Reject unsupported ioctl flags explicitly
+
+From: Hou Tao <houtao1@huawei.com>
+
+commit 2fe8b2d5578d7d142982e3bf62e4c0caf8b8fe02 upstream.
+
+Reject unsupported ioctl flags explicitly, so the following command
+on a regular ubifs file will fail:
+ chattr +d ubifs_file
+
+And xfstests generic/424 will pass.
+
+Signed-off-by: Hou Tao <houtao1@huawei.com>
+Signed-off-by: Richard Weinberger <richard@nod.at>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ubifs/ioctl.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/fs/ubifs/ioctl.c
++++ b/fs/ubifs/ioctl.c
+@@ -28,6 +28,11 @@
+ #include <linux/mount.h>
+ #include "ubifs.h"
+
++/* Need to be kept consistent with checked flags in ioctl2ubifs() */
++#define UBIFS_SUPPORTED_IOCTL_FLAGS \
++ (FS_COMPR_FL | FS_SYNC_FL | FS_APPEND_FL | \
++ FS_IMMUTABLE_FL | FS_DIRSYNC_FL)
++
+ /**
+ * ubifs_set_inode_flags - set VFS inode flags.
+ * @inode: VFS inode to set flags for
+@@ -169,6 +174,9 @@ long ubifs_ioctl(struct file *file, unsi
+ if (get_user(flags, (int __user *) arg))
+ return -EFAULT;
+
++ if (flags & ~UBIFS_SUPPORTED_IOCTL_FLAGS)
++ return -EOPNOTSUPP;
++
+ if (!S_ISDIR(inode->i_mode))
+ flags &= ~FS_DIRSYNC_FL;
+