summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHoward Yen <howardyen@google.com>2021-12-13 22:48:09 +0800
committerHoward Yen <howardyen@google.com>2021-12-23 02:18:45 +0000
commit758b6c92bb9ddb8d4745cc9c41be21ab7a34df1a (patch)
tree5521f2baf894110dbbc6c7450eafbc3c0db64185
parent099098334e7b6a33ee412e9f14c8813ba561be6b (diff)
downloadaoc-758b6c92bb9ddb8d4745cc9c41be21ab7a34df1a.tar.gz
aoc: usb: notify AoC if xhci driver is active
Notify AoC if xhci driver is active when aoc_usb_dev module is reload by AoC SSR. Bug: 201670940 Change-Id: Ic7c49ed4d6f97a55026550b66216620375b19033 Signed-off-by: Howard Yen <howardyen@google.com>
-rw-r--r--usb/aoc_usb.h2
-rw-r--r--usb/aoc_usb_dev.c50
-rw-r--r--usb/xhci_hooks_impl_whi.c7
3 files changed, 58 insertions, 1 deletions
diff --git a/usb/aoc_usb.h b/usb/aoc_usb.h
index e9ebcfc..8574bc2 100644
--- a/usb/aoc_usb.h
+++ b/usb/aoc_usb.h
@@ -119,6 +119,8 @@ extern void xhci_update_erst_dequeue(struct xhci_hcd *xhci,
union xhci_trb *event_ring_deq);
extern int xhci_exynos_register_vendor_ops(struct xhci_vendor_ops *vendor_ops);
+int usb_host_mode_state_notify(enum aoc_usb_state usb_state);
+
int register_aoc_usb_notifier(struct notifier_block *nb);
int unregister_aoc_usb_notifier(struct notifier_block *nb);
diff --git a/usb/aoc_usb_dev.c b/usb/aoc_usb_dev.c
index 0eff9e1..97693db 100644
--- a/usb/aoc_usb_dev.c
+++ b/usb/aoc_usb_dev.c
@@ -10,6 +10,8 @@
#include <linux/init.h>
#include <linux/jiffies.h>
#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
#include <linux/slab.h>
#include "aoc.h"
@@ -355,6 +357,51 @@ static void usb_recovery_work(struct work_struct *ws)
return;
}
+static int aoc_usb_match(struct device *dev, void *data)
+{
+ if (sysfs_streq(dev_driver_string(dev), "xhci-hcd-exynos"))
+ return 1;
+
+ return 0;
+}
+
+static bool aoc_usb_is_hcd_working()
+{
+ struct device_node *np;
+ struct platform_device *pdev;
+ struct device *udev;
+ int ret;
+
+ np = of_find_node_by_name(NULL, "dwc3");
+ if (!np || !of_device_is_available(np)) {
+ pr_err("Cannot find dwc3 device node\n");
+ return false;
+ }
+
+ pdev = of_find_device_by_node(np);
+ if (!pdev)
+ return false;
+
+ udev = device_find_child(&pdev->dev, NULL, aoc_usb_match);
+ if (!udev)
+ return false;
+
+ ret = usb_host_mode_state_notify(USB_CONNECTED);
+ if (ret)
+ dev_err(udev, "Notifying AoC for xhci driver status is failed.\n");
+
+ return true;
+}
+
+static struct work_struct usb_host_mode_checking_ws;
+static void usb_host_mode_checking_work(struct work_struct *ws)
+{
+ if (aoc_usb_is_hcd_working())
+ pr_info("USB HCD is working, send notification to AoC\n");
+
+ return;
+}
+
bool aoc_usb_probe_done;
static int aoc_usb_probe(struct aoc_service_dev *adev)
{
@@ -391,6 +438,8 @@ static int aoc_usb_probe(struct aoc_service_dev *adev)
recover_state = NONE;
}
+ schedule_work(&usb_host_mode_checking_ws);
+
return 0;
}
@@ -439,6 +488,7 @@ static int __init aoc_usb_init(void)
xhci_vendor_helper_init();
usb_vendor_helper_init();
INIT_WORK(&usb_recovery_ws, usb_recovery_work);
+ INIT_WORK(&usb_host_mode_checking_ws, usb_host_mode_checking_work);
return aoc_driver_register(&aoc_usb_driver);
}
diff --git a/usb/xhci_hooks_impl_whi.c b/usb/xhci_hooks_impl_whi.c
index 5a8f131..6c51275 100644
--- a/usb/xhci_hooks_impl_whi.c
+++ b/usb/xhci_hooks_impl_whi.c
@@ -129,6 +129,11 @@ static int xhci_sync_conn_stat(unsigned int bus_id, unsigned int dev_num, unsign
return 0;
}
+int usb_host_mode_state_notify(enum aoc_usb_state usb_state)
+{
+ return xhci_sync_conn_stat(0, 0, 0, usb_state);
+}
+
static int xhci_get_isoc_tr_info(u16 ep_id, u16 dir, struct xhci_ring *ep_ring)
{
struct get_isoc_tr_info_args tr_info;
@@ -595,7 +600,7 @@ static void usb_audio_offload_cleanup(struct xhci_hcd *xhci)
usb_unregister_notify(&xhci_udev_nb);
/* Notification for xhci driver removing */
- xhci_sync_conn_stat(0, 0, 0, 0);
+ usb_host_mode_state_notify(USB_DISCONNECTED);
mutex_destroy(&vendor_data->lock);