Update Linux to v5.4.2
Change-Id: Idf6911045d9d382da2cfe01b1edff026404ac8fd
diff --git a/drivers/firmware/raspberrypi.c b/drivers/firmware/raspberrypi.c
index a200a21..da26a58 100644
--- a/drivers/firmware/raspberrypi.c
+++ b/drivers/firmware/raspberrypi.c
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Defines interfaces for interacting wtih the Raspberry Pi firmware's
* property channel.
*
* Copyright © 2015 Broadcom
- *
- * 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.
*/
#include <linux/dma-mapping.h>
@@ -14,6 +11,7 @@
#include <linux/module.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
+#include <linux/slab.h>
#include <soc/bcm2835/raspberrypi-firmware.h>
#define MBOX_MSG(chan, data28) (((data28) & ~0xf) | ((chan) & 0xf))
@@ -21,9 +19,8 @@
#define MBOX_DATA28(msg) ((msg) & ~0xf)
#define MBOX_CHAN_PROPERTY 8
-#define MAX_RPI_FW_PROP_BUF_SIZE 32
-
static struct platform_device *rpi_hwmon;
+static struct platform_device *rpi_clk;
struct rpi_firmware {
struct mbox_client cl;
@@ -56,8 +53,12 @@
reinit_completion(&fw->c);
ret = mbox_send_message(fw->chan, &message);
if (ret >= 0) {
- wait_for_completion(&fw->c);
- ret = 0;
+ if (wait_for_completion_timeout(&fw->c, HZ)) {
+ ret = 0;
+ } else {
+ ret = -ETIMEDOUT;
+ WARN_ONCE(1, "Firmware transaction timeout");
+ }
} else {
dev_err(fw->cl.dev, "mbox_send_message returned %d\n", ret);
}
@@ -144,28 +145,30 @@
int rpi_firmware_property(struct rpi_firmware *fw,
u32 tag, void *tag_data, size_t buf_size)
{
- /* Single tags are very small (generally 8 bytes), so the
- * stack should be safe.
- */
- u8 data[sizeof(struct rpi_firmware_property_tag_header) +
- MAX_RPI_FW_PROP_BUF_SIZE];
- struct rpi_firmware_property_tag_header *header =
- (struct rpi_firmware_property_tag_header *)data;
+ struct rpi_firmware_property_tag_header *header;
int ret;
- if (WARN_ON(buf_size > sizeof(data) - sizeof(*header)))
- return -EINVAL;
+ /* Some mailboxes can use over 1k bytes. Rather than checking
+ * size and using stack or kmalloc depending on requirements,
+ * just use kmalloc. Mailboxes don't get called enough to worry
+ * too much about the time taken in the allocation.
+ */
+ void *data = kmalloc(sizeof(*header) + buf_size, GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ header = data;
header->tag = tag;
header->buf_size = buf_size;
header->req_resp_size = 0;
- memcpy(data + sizeof(struct rpi_firmware_property_tag_header),
- tag_data, buf_size);
+ memcpy(data + sizeof(*header), tag_data, buf_size);
- ret = rpi_firmware_property_list(fw, &data, buf_size + sizeof(*header));
- memcpy(tag_data,
- data + sizeof(struct rpi_firmware_property_tag_header),
- buf_size);
+ ret = rpi_firmware_property_list(fw, data, buf_size + sizeof(*header));
+
+ memcpy(tag_data, data + sizeof(*header), buf_size);
+
+ kfree(data);
return ret;
}
@@ -205,6 +208,12 @@
-1, NULL, 0);
}
+static void rpi_register_clk_driver(struct device *dev)
+{
+ rpi_clk = platform_device_register_data(dev, "raspberrypi-clk",
+ -1, NULL, 0);
+}
+
static int rpi_firmware_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -232,16 +241,29 @@
rpi_firmware_print_firmware_revision(fw);
rpi_register_hwmon_driver(dev, fw);
+ rpi_register_clk_driver(dev);
return 0;
}
+static void rpi_firmware_shutdown(struct platform_device *pdev)
+{
+ struct rpi_firmware *fw = platform_get_drvdata(pdev);
+
+ if (!fw)
+ return;
+
+ rpi_firmware_property(fw, RPI_FIRMWARE_NOTIFY_REBOOT, NULL, 0);
+}
+
static int rpi_firmware_remove(struct platform_device *pdev)
{
struct rpi_firmware *fw = platform_get_drvdata(pdev);
platform_device_unregister(rpi_hwmon);
rpi_hwmon = NULL;
+ platform_device_unregister(rpi_clk);
+ rpi_clk = NULL;
mbox_free_channel(fw->chan);
return 0;
@@ -276,6 +298,7 @@
.of_match_table = rpi_firmware_of_match,
},
.probe = rpi_firmware_probe,
+ .shutdown = rpi_firmware_shutdown,
.remove = rpi_firmware_remove,
};
module_platform_driver(rpi_firmware_driver);