From 43c85a09b12cd3e782ae237be9903fef4559cc0d Mon Sep 17 00:00:00 2001 From: Philip Yang Date: Sat, 23 Jul 2016 05:48:14 +0800 Subject: [PATCH] greybus: HID: Add runtime pm support Modify HID greybus driver to support runtime PM framework. The suspend and resume fucntion have been test with tutorial-hid, e-ink-display and gpbridge-test image by sysfs resume, all HID buttons work well on suspend/resume. Testing Done: Compiled and verified on EVT2, DB3.5, GPB test module with daughter board, Red module. Signed-off-by: Philip Yang Reviewed-by: David Lin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/hid.c | 51 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/drivers/staging/greybus/hid.c b/drivers/staging/greybus/hid.c index ca0c949..b558c81 100644 --- a/drivers/staging/greybus/hid.c +++ b/drivers/staging/greybus/hid.c @@ -18,6 +18,7 @@ /* Greybus HID device's structure */ struct gb_hid { + struct gb_bundle *bundle; struct gb_connection *connection; struct hid_device *hid; @@ -44,26 +45,55 @@ static int gb_hid_get_desc(struct gb_hid *ghid) static int gb_hid_get_report_desc(struct gb_hid *ghid, char *rdesc) { - return gb_operation_sync(ghid->connection, GB_HID_TYPE_GET_REPORT_DESC, + int ret; + + ret = gb_pm_runtime_get_sync(ghid->bundle); + if (ret) + return ret; + + ret = gb_operation_sync(ghid->connection, GB_HID_TYPE_GET_REPORT_DESC, NULL, 0, rdesc, le16_to_cpu(ghid->hdesc.wReportDescLength)); + + gb_pm_runtime_put_autosuspend(ghid->bundle); + + return ret; } static int gb_hid_set_power(struct gb_hid *ghid, int type) { - return gb_operation_sync(ghid->connection, type, NULL, 0, NULL, 0); + int ret; + + ret = gb_pm_runtime_get_sync(ghid->bundle); + if (ret) + return ret; + + ret = gb_operation_sync(ghid->connection, type, NULL, 0, NULL, 0); + + gb_pm_runtime_put_autosuspend(ghid->bundle); + + return ret; } static int gb_hid_get_report(struct gb_hid *ghid, u8 report_type, u8 report_id, unsigned char *buf, int len) { struct gb_hid_get_report_request request; + int ret; + + ret = gb_pm_runtime_get_sync(ghid->bundle); + if (ret) + return ret; request.report_type = report_type; request.report_id = report_id; - return gb_operation_sync(ghid->connection, GB_HID_TYPE_GET_REPORT, + ret = gb_operation_sync(ghid->connection, GB_HID_TYPE_GET_REPORT, &request, sizeof(request), buf, len); + + gb_pm_runtime_put_autosuspend(ghid->bundle); + + return ret; } static int gb_hid_set_report(struct gb_hid *ghid, u8 report_type, u8 report_id, @@ -73,11 +103,17 @@ static int gb_hid_set_report(struct gb_hid *ghid, u8 report_type, u8 report_id, struct gb_operation *operation; int ret, size = sizeof(*request) + len - 1; + ret = gb_pm_runtime_get_sync(ghid->bundle); + if (ret) + return ret; + operation = gb_operation_create(ghid->connection, GB_HID_TYPE_SET_REPORT, size, 0, GFP_KERNEL); - if (!operation) + if (!operation) { + gb_pm_runtime_put_autosuspend(ghid->bundle); return -ENOMEM; + } request = operation->request->payload; request->report_type = report_type; @@ -93,6 +129,7 @@ static int gb_hid_set_report(struct gb_hid *ghid, u8 report_type, u8 report_id, } gb_operation_put(operation); + gb_pm_runtime_put_autosuspend(ghid->bundle); return ret; } @@ -458,6 +495,7 @@ static int gb_hid_probe(struct gb_bundle *bundle, } ghid->hid = hid; + ghid->bundle = bundle; greybus_set_drvdata(bundle, ghid); @@ -475,6 +513,8 @@ static int gb_hid_probe(struct gb_bundle *bundle, goto err_connection_disable; } + gb_pm_runtime_put_autosuspend(bundle); + return 0; err_connection_disable: @@ -493,6 +533,9 @@ static void gb_hid_disconnect(struct gb_bundle *bundle) { struct gb_hid *ghid = greybus_get_drvdata(bundle); + if (gb_pm_runtime_get_sync(bundle)) + gb_pm_runtime_get_noresume(bundle); + hid_destroy_device(ghid->hid); gb_connection_disable(ghid->connection); gb_connection_destroy(ghid->connection); -- 2.7.4