From patchwork Tue Oct 7 09:15:44 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Kiran Kumar Raparthy X-Patchwork-Id: 38392 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-wi0-f198.google.com (mail-wi0-f198.google.com [209.85.212.198]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id B2DA8202E7 for ; Tue, 7 Oct 2014 09:16:30 +0000 (UTC) Received: by mail-wi0-f198.google.com with SMTP id hi2sf2621621wib.5 for ; Tue, 07 Oct 2014 02:16:29 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:from:to:cc:subject:date:message-id :mime-version:sender:precedence:list-id:x-original-sender :x-original-authentication-results:mailing-list:list-post:list-help :list-archive:list-unsubscribe:content-type :content-transfer-encoding; bh=QohUlU1+DC9GOD2I4WPHuIIa90FjEbDqWKPK0UtSD8s=; b=ZYMtkFnCdaQTBvqnG6sgW8J34z2orQ/L8DeElOMs9aJP/EhTin1JTzp6dK8E3TZhOf UI7ZhAZoMeGJpYNANY4qlVYnluNVi1awPp78pv6T1bq1znnbsRab93CCD/W9q3lcW0uD RUNNXa1iNjfeEGRNsvK6Hh9ToN3Dk6PZtKV0Becb4aZRoEVpIFfosmW6rBnjlkIPXnLV Ji/j7WUfX+fdnUUnrXyDZM563YsWMiKRiG/4fMXrBoNZPLvM+w4i+KtKfkSJUj6ymWfM CfHBRBlGtfXy9AguyLsY3q0r8FxYs1a+jlQWbEFxYVnHS59LlPcz3wty0+Ry+0B7fiGE pVqw== X-Gm-Message-State: ALoCoQk5lMokRpLNq6c0TTgj4jf86VN3my3M8D5iheCjI7mp833ucmIt7CLExdA1kbPO9Fh3PpWt X-Received: by 10.152.1.136 with SMTP id 8mr380843lam.5.1412673389816; Tue, 07 Oct 2014 02:16:29 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.43.1 with SMTP id s1ls645992lal.30.gmail; Tue, 07 Oct 2014 02:16:29 -0700 (PDT) X-Received: by 10.112.134.229 with SMTP id pn5mr2560591lbb.22.1412673389306; Tue, 07 Oct 2014 02:16:29 -0700 (PDT) Received: from mail-la0-f48.google.com (mail-la0-f48.google.com [209.85.215.48]) by mx.google.com with ESMTPS id lf1si27740350lac.65.2014.10.07.02.16.29 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 07 Oct 2014 02:16:29 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.48 as permitted sender) client-ip=209.85.215.48; Received: by mail-la0-f48.google.com with SMTP id gi9so6004065lab.35 for ; Tue, 07 Oct 2014 02:16:29 -0700 (PDT) X-Received: by 10.112.62.200 with SMTP id a8mr2529830lbs.34.1412673389210; Tue, 07 Oct 2014 02:16:29 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.112.130.169 with SMTP id of9csp318365lbb; Tue, 7 Oct 2014 02:16:28 -0700 (PDT) X-Received: by 10.66.191.41 with SMTP id gv9mr2478845pac.15.1412673387548; Tue, 07 Oct 2014 02:16:27 -0700 (PDT) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id zf7si12362834pab.44.2014.10.07.02.16.26 for ; Tue, 07 Oct 2014 02:16:27 -0700 (PDT) Received-SPF: none (google.com: linux-kernel-owner@vger.kernel.org does not designate permitted sender hosts) client-ip=209.132.180.67; Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753775AbaJGJQX (ORCPT + 27 others); Tue, 7 Oct 2014 05:16:23 -0400 Received: from mail-pa0-f42.google.com ([209.85.220.42]:38352 "EHLO mail-pa0-f42.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753494AbaJGJQR (ORCPT ); Tue, 7 Oct 2014 05:16:17 -0400 Received: by mail-pa0-f42.google.com with SMTP id bj1so6896081pad.1 for ; Tue, 07 Oct 2014 02:16:17 -0700 (PDT) X-Received: by 10.66.219.133 with SMTP id po5mr2442593pac.47.1412673377111; Tue, 07 Oct 2014 02:16:17 -0700 (PDT) Received: from c-krapar-linux.qualcomm.com ([202.46.23.54]) by mx.google.com with ESMTPSA id qf3sm15322577pbc.96.2014.10.07.02.16.13 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Tue, 07 Oct 2014 02:16:16 -0700 (PDT) From: Kiran Kumar Raparthy To: linux-kernel@vger.kernel.org Cc: Todd Poynor , Felipe Balbi , Greg Kroah-Hartman , linux-usb@vger.kernel.org, Android Kernel Team , John Stultz , Sumit Semwal , =?UTF-8?q?Arve=20Hj=F8nnev=E5g?= , Benoit Goby , Kiran Raparthy Subject: [RFC v4] usb: phy: Hold wakeupsource when USB is enumerated in peripheral mode Date: Tue, 7 Oct 2014 14:45:44 +0530 Message-Id: <1412673344-25443-1-git-send-email-kiran.kumar@linaro.org> X-Mailer: git-send-email 1.8.2.1 MIME-Version: 1.0 Sender: linux-kernel-owner@vger.kernel.org Precedence: list List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: kiran.kumar@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.48 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , From: Todd Poynor usb: phy: Hold wakeupsource when USB is enumerated in peripheral mode Purpose of this is to prevent the system to enter into suspend state from USB peripheral traffic by hodling a wakeupsource when USB is connected and enumerated in peripheral mode(say adb). Temporarily hold a timed wakeup source on USB disconnect events, to allow the rest of the system to react to the USB disconnection (dropping host sessions, updating charger status, etc.) prior to re-allowing suspend. Cc: Felipe Balbi Cc: Greg Kroah-Hartman Cc: linux-kernel@vger.kernel.org Cc: linux-usb@vger.kernel.org Cc: Android Kernel Team Cc: John Stultz Cc: Sumit Semwal Cc: Arve Hjřnnevĺg Cc: Benoit Goby Signed-off-by: Todd Poynor [kiran: Added context to commit message, squished build fixes from Benoit Goby and Arve Hjřnnevĺg, changed wakelocks usage to wakeupsource, merged Todd's refactoring logic and simplified the structures and code and addressed community feedback] Signed-off-by: Kiran Raparthy --- v4: * Temporarily hold wakeupsource patch integrated into main patch. * As per feedback,dropped "enabled" module parameter. * Introduced otgws_otg_usb3_notifications function to handle event notifications from usb3 phy. * Handled wakeupsource initialization,spinlock,registration of notifier block per-PHY. * Updated usb_phy structure. v3: * As per the feedback,no global phy pointer used. * called the one-liner wakeupsource handling calls directly instead of indirect functions implemented in v2. * Removed indirect function get_phy_hook and used usb_get_phy to get the phy handle.. v2: * wakeupsource handling implemeted per-PHY * Implemented wakeupsource handling calls in phy * included Todd's refactoring logic. v1: * changed to "disabled by default" from "enable by default". * Kconfig help text modified * Included better commit text * otgws_nb moved to otg_wakeupsource_init function * Introduced get_phy_hook to handle otgws_xceiv per-PHY RFC: * Included build fix from Benoit Goby and Arve Hjřnnevĺg * Removed lock->held field in driver as this mechanism is provided in wakeupsource driver. * wakelock(wl) terminology replaced with wakeup_source(ws). drivers/usb/phy/Kconfig | 8 +++ drivers/usb/phy/Makefile | 1 + drivers/usb/phy/otg-wakeupsource.c | 134 +++++++++++++++++++++++++++++++++++++ include/linux/usb/phy.h | 8 +++ 4 files changed, 151 insertions(+) create mode 100644 drivers/usb/phy/otg-wakeupsource.c diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig index e253fa0..d9ddd85 100644 --- a/drivers/usb/phy/Kconfig +++ b/drivers/usb/phy/Kconfig @@ -6,6 +6,14 @@ menu "USB Physical Layer drivers" config USB_PHY def_bool n +config USB_OTG_WAKEUPSOURCE + bool "Hold wakeupsource when USB is enumerated in peripheral mode" + depends on PM_SLEEP + select USB_PHY + help + Prevent the system going into automatic suspend while + it is attached as a USB peripheral by holding a wakeupsource. + # # USB Transceiver Drivers # diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile index 24a9133..ca2fbaf 100644 --- a/drivers/usb/phy/Makefile +++ b/drivers/usb/phy/Makefile @@ -3,6 +3,7 @@ # obj-$(CONFIG_USB_PHY) += phy.o obj-$(CONFIG_OF) += of.o +obj-$(CONFIG_USB_OTG_WAKEUPSOURCE) += otg-wakeupsource.o # transceiver drivers, keep the list sorted diff --git a/drivers/usb/phy/otg-wakeupsource.c b/drivers/usb/phy/otg-wakeupsource.c new file mode 100644 index 0000000..00d3359 --- /dev/null +++ b/drivers/usb/phy/otg-wakeupsource.c @@ -0,0 +1,134 @@ +/* + * otg-wakeupsource.c + * + * Copyright (C) 2011 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +static void otgws_handle_event(struct usb_phy *otgws_xceiv, unsigned long event) +{ + unsigned long irqflags; + + spin_lock_irqsave(&otgws_xceiv->otgws_slock, irqflags); + + switch (event) { + case USB_EVENT_VBUS: + case USB_EVENT_ENUMERATED: + __pm_stay_awake(&otgws_xceiv->wsource); + break; + + case USB_EVENT_NONE: + case USB_EVENT_ID: + case USB_EVENT_CHARGER: + __pm_wakeup_event(&otgws_xceiv->wsource, + msecs_to_jiffies(TEMPORARY_HOLD_TIME)); + break; + + default: + break; + } + + spin_unlock_irqrestore(&otgws_xceiv->otgws_slock, irqflags); +} + +static int otgws_otg_usb2_notifications(struct notifier_block *nb, + unsigned long event, void *unused) +{ + static struct usb_phy *otgws_xceiv; + + otgws_xceiv = usb_get_phy(USB_PHY_TYPE_USB2); + + if (IS_ERR(otgws_xceiv)) { + pr_err("%s: No OTG transceiver found\n", __func__); + return PTR_ERR(otgws_xceiv); + } + + otgws_handle_event(otgws_xceiv, event); + + return NOTIFY_OK; +} + +static int otgws_otg_usb3_notifications(struct notifier_block *nb, + unsigned long event, void *unused) +{ + static struct usb_phy *otgws_xceiv; + + otgws_xceiv = usb_get_phy(USB_PHY_TYPE_USB3); + + if (IS_ERR(otgws_xceiv)) { + pr_err("%s: No OTG transceiver found\n", __func__); + return PTR_ERR(otgws_xceiv); + } + + otgws_handle_event(otgws_xceiv, event); + + return NOTIFY_OK; +} + +static int otg_wakeupsource_init(void) +{ + int ret_usb2; + int ret_usb3; + char wsource_name_usb2[40]; + char wsource_name_usb3[40]; + static struct usb_phy *otgws_xceiv_usb2; + static struct usb_phy *otgws_xceiv_usb3; + + otgws_xceiv_usb2 = usb_get_phy(USB_PHY_TYPE_USB2); + otgws_xceiv_usb3 = usb_get_phy(USB_PHY_TYPE_USB3); + + if (IS_ERR(otgws_xceiv_usb2) && IS_ERR(otgws_xceiv_usb3)) { + pr_err("%s: No OTG transceiver found\n", __func__); + return PTR_ERR(otgws_xceiv_usb2); + } + + spin_lock_init(&otgws_xceiv_usb2->otgws_slock); + spin_lock_init(&otgws_xceiv_usb3->otgws_slock); + + snprintf(wsource_name_usb2, sizeof(wsource_name_usb2), "vbus-%s", + dev_name(otgws_xceiv_usb2->dev)); + wakeup_source_init(&otgws_xceiv_usb2->wsource, wsource_name_usb2); + + snprintf(wsource_name_usb3, sizeof(wsource_name_usb3), "vbus-%s", + dev_name(otgws_xceiv_usb3->dev)); + wakeup_source_init(&otgws_xceiv_usb3->wsource, wsource_name_usb3); + + otgws_xceiv_usb2->otgws_nb.notifier_call = otgws_otg_usb2_notifications; + ret_usb2 = usb_register_notifier(otgws_xceiv_usb2, + &otgws_xceiv_usb2->otgws_nb); + + otgws_xceiv_usb3->otgws_nb.notifier_call = otgws_otg_usb3_notifications; + ret_usb3 = usb_register_notifier(otgws_xceiv_usb3, + &otgws_xceiv_usb3->otgws_nb); + + if (ret_usb2 && ret_usb3) { + pr_err("%s: usb_register_notifier on transceiver failed\n", + __func__); + wakeup_source_trash(&otgws_xceiv_usb2->wsource); + wakeup_source_trash(&otgws_xceiv_usb3->wsource); + otgws_xceiv_usb2 = NULL; + otgws_xceiv_usb3 = NULL; + return ret_usb2 | ret_usb3; + } + + return 0; +} + +late_initcall(otg_wakeupsource_init); diff --git a/include/linux/usb/phy.h b/include/linux/usb/phy.h index 353053a..dd64e2e 100644 --- a/include/linux/usb/phy.h +++ b/include/linux/usb/phy.h @@ -12,6 +12,8 @@ #include #include +#define TEMPORARY_HOLD_TIME 2000 + enum usb_phy_interface { USBPHY_INTERFACE_MODE_UNKNOWN, USBPHY_INTERFACE_MODE_UTMI, @@ -88,6 +90,12 @@ struct usb_phy { /* for notification of usb_phy_events */ struct atomic_notifier_head notifier; + struct notifier_block otgws_nb; + + /* wakeup source */ + struct wakeup_source wsource; + + spinlock_t otgws_slock; /* to pass extra port status to the root hub */ u16 port_status;