| From 0874ed2d8f47be3b05c13c2847dd023e47f1a663 Mon Sep 17 00:00:00 2001 |
| From: =?UTF-8?q?Kornel=20Dul=C4=99ba?= <korneld@google.com> |
| Date: Thu, 2 Feb 2023 14:41:17 +0000 |
| Subject: [PATCH] CHROMIUM: net: wwan: t7xx: Add support for cold reboot |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| This allows us to recover from a state where the device doesn't respond |
| to any commands. It calls the FHRF and SHRF ACPI methods, essentially |
| performing a cold reboot. |
| The reset can be triggered using a dedicated sysfs file - "cold_reboot". |
| For example: |
| "echo 1 > /sys/devices/pci0000:00/0000:00:1c.0/0000:57:00.0/cold_reboot" |
| |
| BUG=b:241850118, b:302552686 |
| TEST=Trigger the reboot and verify that the modem is working |
| UPSTREAM-TASK=b:269405297 |
| |
| Signed-off-by: Kornel Dulęba <korneld@google.com> |
| Change-Id: I25b3afc9d4e96a1c65bd44cc8611a48b942e722b |
| Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/4218573 |
| Reviewed-by: Radoslaw Biernacki <biernacki@google.com> |
| Commit-Queue: Radoslaw Biernacki <biernacki@google.com> |
| (cherry picked from commit c9f39b9e95117e74b4fac5c704ffd8032779abcc) |
| Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/4903302 |
| Reviewed-by: Rukun Mao <rmao@google.com> |
| Reviewed-by: Daniel Winkler <danielwinkler@google.com> |
| Tested-by: Rukun Mao <rmao@google.com> |
| --- |
| drivers/net/wwan/t7xx/t7xx_pci.c | 32 +++++++++++++++++++++++ |
| drivers/net/wwan/t7xx/t7xx_port_devlink.c | 2 +- |
| 2 files changed, 33 insertions(+), 1 deletion(-) |
| |
| diff --git a/drivers/net/wwan/t7xx/t7xx_pci.c b/drivers/net/wwan/t7xx/t7xx_pci.c |
| index 02d27c1cf7e42df407f8352762b15da8e2fdd71f..6dc133cbd1776a624ebd3c3b9c7384c44c3fc9d9 100644 |
| --- a/drivers/net/wwan/t7xx/t7xx_pci.c |
| +++ b/drivers/net/wwan/t7xx/t7xx_pci.c |
| @@ -146,6 +146,26 @@ enum t7xx_pm_state { |
| MTK_PM_RESUMED, |
| }; |
| |
| +static ssize_t cold_reboot_store(struct device *dev, struct device_attribute *attr, |
| + const char *buf, size_t count) |
| +{ |
| + struct pci_dev *pdev = to_pci_dev(dev); |
| + |
| + t7xx_rescan_queue_work(pdev, true); |
| + return count; |
| +} |
| + |
| +static DEVICE_ATTR_WO(cold_reboot); |
| + |
| +static struct attribute *cold_reboot_attr[] = { |
| + &dev_attr_cold_reboot.attr, |
| + NULL |
| +}; |
| + |
| +static const struct attribute_group cold_reboot_attribute_group = { |
| + .attrs = cold_reboot_attr, |
| +}; |
| + |
| static void t7xx_dev_set_sleep_capability(struct t7xx_pci_dev *t7xx_dev, bool enable) |
| { |
| void __iomem *ctrl_reg = IREG_BASE(t7xx_dev) + T7XX_PCIE_MISC_CTRL; |
| @@ -843,6 +863,13 @@ static int t7xx_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) |
| |
| t7xx_pcie_mac_interrupts_dis(t7xx_dev); |
| |
| + ret = sysfs_create_group(&t7xx_dev->pdev->dev.kobj, |
| + &cold_reboot_attribute_group); |
| + if (ret) { |
| + t7xx_md_exit(t7xx_dev); |
| + goto err_devlink_unregister; |
| + } |
| + |
| ret = sysfs_create_group(&t7xx_dev->pdev->dev.kobj, |
| &t7xx_mode_attribute_group); |
| if (ret) |
| @@ -861,6 +888,8 @@ static int t7xx_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) |
| err_remove_group: |
| sysfs_remove_group(&t7xx_dev->pdev->dev.kobj, |
| &t7xx_mode_attribute_group); |
| + sysfs_remove_group(&t7xx_dev->pdev->dev.kobj, |
| + &cold_reboot_attribute_group); |
| |
| err_md_exit: |
| t7xx_md_exit(t7xx_dev); |
| @@ -884,6 +913,9 @@ static void t7xx_pci_remove(struct pci_dev *pdev) |
| t7xx_md_exit(t7xx_dev); |
| t7xx_devlink_unregister(t7xx_dev); |
| |
| + sysfs_remove_group(&t7xx_dev->pdev->dev.kobj, |
| + &cold_reboot_attribute_group); |
| + |
| for (i = 0; i < EXT_INT_NUM; i++) { |
| if (!t7xx_dev->intr_handler[i]) |
| continue; |
| diff --git a/drivers/net/wwan/t7xx/t7xx_port_devlink.c b/drivers/net/wwan/t7xx/t7xx_port_devlink.c |
| index 8de2ee65fe0cb94bf6dfb476e767ccf831882d92..fa0c7d7e35302187d4db8e8e2e4c91ac54b7e553 100644 |
| --- a/drivers/net/wwan/t7xx/t7xx_port_devlink.c |
| +++ b/drivers/net/wwan/t7xx/t7xx_port_devlink.c |
| @@ -442,7 +442,7 @@ static int t7xx_devlink_reload_up(struct devlink *devlink, |
| switch (action) { |
| case DEVLINK_RELOAD_ACTION_DRIVER_REINIT: |
| case DEVLINK_RELOAD_ACTION_FW_ACTIVATE: |
| - t7xx_rescan_queue_work(dl->t7xx_dev->pdev); |
| + t7xx_rescan_queue_work(dl->t7xx_dev->pdev, false); |
| return 0; |
| default: |
| /* Unsupported action should not get to this function */ |
| -- |
| 2.46.0.792.g87dc391469-goog |
| |