From patchwork Tue Sep 2 11:47:08 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: 36451 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-oi0-f72.google.com (mail-oi0-f72.google.com [209.85.218.72]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 0A029203BE for ; Tue, 2 Sep 2014 11:49:16 +0000 (UTC) Received: by mail-oi0-f72.google.com with SMTP id e131sf33070786oig.3 for ; Tue, 02 Sep 2014 04:49:15 -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=yZBcU4LpU1p9ea2yIDBDGtckZTxPxUqGDkSgqNbhJAY=; b=kJ/+smjYrdKoA+a8sPm5jOKIO4/0VYdizVCsFQ3JZHF1Cd2afJ7gG99jBddyxYBAPu kGzOyI5DqnEqUToP+yJtMJd7bKzW88skaiF/tNo2ZY61xoohHxHuw1yGQ1vcL0rUUlQA LW121OyVxmCaRgDjq1F+d62MJtv7/AGazAJSYKcbJ0fKMh2xC/kkw3dQFS+ph0VkWs0J 2G40XGcH5Iwy97XSOd/lzTR4BRZS3EkqqqDI9dgOBiXCoyC34h50Le5bN3j7bmU8J4mJ rrO4OW18WUoYOVs+50SVCPgZdP6Ep6ITXf14piVwPCNWsCD4BxynfDwGSv9SqDtblUgh mdFA== X-Gm-Message-State: ALoCoQloNtQNDz4EIGjVdfe2k9aZEFZkX0RoWk/8I9LH+dgyng0NHonxRX3Ef1jG/ChFSj458Idi X-Received: by 10.182.66.68 with SMTP id d4mr18465638obt.39.1409658555632; Tue, 02 Sep 2014 04:49:15 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.23.201 with SMTP id 67ls2383980qgp.45.gmail; Tue, 02 Sep 2014 04:49:15 -0700 (PDT) X-Received: by 10.221.68.66 with SMTP id xx2mr30048522vcb.1.1409658555510; Tue, 02 Sep 2014 04:49:15 -0700 (PDT) Received: from mail-vc0-f181.google.com (mail-vc0-f181.google.com [209.85.220.181]) by mx.google.com with ESMTPS id ub6si2139716vcb.35.2014.09.02.04.49.15 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 02 Sep 2014 04:49:15 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.181 as permitted sender) client-ip=209.85.220.181; Received: by mail-vc0-f181.google.com with SMTP id ij19so6764366vcb.40 for ; Tue, 02 Sep 2014 04:49:15 -0700 (PDT) X-Received: by 10.52.168.134 with SMTP id zw6mr1100340vdb.37.1409658555356; Tue, 02 Sep 2014 04:49:15 -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.221.45.67 with SMTP id uj3csp514267vcb; Tue, 2 Sep 2014 04:49:14 -0700 (PDT) X-Received: by 10.68.117.238 with SMTP id kh14mr46566139pbb.55.1409658554484; Tue, 02 Sep 2014 04:49:14 -0700 (PDT) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id rc1si5647993pdb.82.2014.09.02.04.49.13 for ; Tue, 02 Sep 2014 04:49:14 -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 S1753490AbaIBLtL (ORCPT + 25 others); Tue, 2 Sep 2014 07:49:11 -0400 Received: from mail-pd0-f177.google.com ([209.85.192.177]:60810 "EHLO mail-pd0-f177.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753363AbaIBLtI (ORCPT ); Tue, 2 Sep 2014 07:49:08 -0400 Received: by mail-pd0-f177.google.com with SMTP id r10so8421622pdi.36 for ; Tue, 02 Sep 2014 04:49:07 -0700 (PDT) X-Received: by 10.68.132.10 with SMTP id oq10mr19120431pbb.132.1409658546448; Tue, 02 Sep 2014 04:49:06 -0700 (PDT) Received: from c-krapar-linux.qualcomm.com ([202.46.23.54]) by mx.google.com with ESMTPSA id ke2sm3706388pbc.90.2014.09.02.04.49.02 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Tue, 02 Sep 2014 04:49:05 -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 , =?UTF-8?q?Arve=20Hj=F8nnev=E5g?= , Benoit Goby , Kiran Raparthy Subject: [RFC v2 1/2] usb: phy: Hold wakeupsource when USB is enumerated in peripheral mode Date: Tue, 2 Sep 2014 17:17:08 +0530 Message-Id: <1409658428-12281-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.220.181 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). Disabled by default, can enable with: echo Y > /sys/module/otg_wakeupsource/parameters/enabled 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: Arve Hjřnnevĺg Cc: Benoit Goby Signed-off-by: Todd Poynor [kiran: Added context to commit message. 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). changed to "disabled by default" from "enable by default". sys entry(module param) field modified to otg_wakeupsource. included Todd's refactoring logic. Introduced get_phy_hook to handle otgws_xceiv per-PHY. otgws_nb moved to otg_wakeupsource_init function. wakeupsource handling implemeted per-PHY(in phy core). modified Kconfig help text] Signed-off-by: Kiran Raparthy --- drivers/usb/phy/Kconfig | 8 +++ drivers/usb/phy/Makefile | 1 + drivers/usb/phy/otg-wakeupsource.c | 140 +++++++++++++++++++++++++++++++++++++ drivers/usb/phy/phy.c | 42 +++++++++++ include/linux/usb/phy.h | 8 +++ 5 files changed, 199 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..fca2010 --- /dev/null +++ b/drivers/usb/phy/otg-wakeupsource.c @@ -0,0 +1,140 @@ +/* + * 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 + +bool enabled = false; + +static DEFINE_SPINLOCK(otgws_spinlock); +static struct usb_phy *get_phy_hook(void); + +static void otgws_handle_event(struct usb_phy *otgws_xceiv, unsigned long event) +{ + unsigned long irqflags; + + spin_lock_irqsave(&otgws_spinlock, irqflags); + + if (!enabled) { + usb_drop_wsource(otgws_xceiv); + spin_unlock_irqrestore(&otgws_spinlock, irqflags); + return; + } + + switch (event) { + case USB_EVENT_VBUS: + case USB_EVENT_ENUMERATED: + usb_grab_wsource(otgws_xceiv); + break; + + case USB_EVENT_NONE: + case USB_EVENT_ID: + case USB_EVENT_CHARGER: + usb_drop_wsource(otgws_xceiv); + break; + + default: + break; + } + + spin_unlock_irqrestore(&otgws_spinlock, irqflags); +} +static struct usb_phy *get_phy_hook(void) +{ + struct usb_phy *phy; + + phy = usb_get_phy(USB_PHY_TYPE_USB2); + + if (IS_ERR(phy)) { + pr_err("%s: No OTG transceiver found\n", __func__); + return NULL; + } + + return phy; +} +static int otgws_otg_notifications(struct notifier_block *nb, + unsigned long event, void *unused) +{ + static struct usb_phy *otgws_xceiv; + + otgws_xceiv = get_phy_hook(); + + if (otgws_xceiv) + otgws_handle_event(otgws_xceiv, event); + + return NOTIFY_OK; +} + +static int set_enabled(const char *val, const struct kernel_param *kp) +{ + int rv = param_set_bool(val, kp); + static struct usb_phy *otgws_xceiv; + + if (rv) + return rv; + + otgws_xceiv = get_phy_hook(); + + if (otgws_xceiv) + otgws_handle_event(otgws_xceiv, otgws_xceiv->last_event); + + return 0; +} + +static struct kernel_param_ops enabled_param_ops = { + .set = set_enabled, + .get = param_get_bool, +}; + +module_param_cb(enabled, &enabled_param_ops, &enabled, 0644); +MODULE_PARM_DESC(enabled, "Hold wakeupsource when VBUS present"); + +static int __init otg_wakeupsource_init(void) +{ + int ret; + char wsource_name[40]; + static struct notifier_block otgws_nb; + static struct usb_phy *otgws_xceiv; + + otgws_xceiv = get_phy_hook(); + + if (NULL == otgws_xceiv) + return PTR_ERR(otgws_xceiv); + + snprintf(wsource_name, sizeof(wsource_name), "vbus-%s", + dev_name(otgws_xceiv->dev)); + usb_wsource_init(otgws_xceiv, wsource_name); + + otgws_nb.notifier_call = otgws_otg_notifications; + ret = usb_register_notifier(otgws_xceiv, &otgws_nb); + + if (ret) { + pr_err("%s: usb_register_notifier on transceiver %s failed\n", + __func__, dev_name(otgws_xceiv->dev)); + usb_wsource_trash(otgws_xceiv); + otgws_xceiv = NULL; + return ret; + } + + return 0; +} + +late_initcall(otg_wakeupsource_init); diff --git a/drivers/usb/phy/phy.c b/drivers/usb/phy/phy.c index 36b6bce..659b1e8 100644 --- a/drivers/usb/phy/phy.c +++ b/drivers/usb/phy/phy.c @@ -441,3 +441,45 @@ int usb_bind_phy(const char *dev_name, u8 index, return 0; } EXPORT_SYMBOL_GPL(usb_bind_phy); + +/** + * usb_wsource_init - Initialize wakeupsource + * @usb_phy: the phy returned by usb_get_phy() + * @phy_dev_name: the device name of the phy + */ +void usb_wsource_init(struct usb_phy *x, char *phy_dev_name) +{ + wakeup_source_init(&x->wsource, phy_dev_name); +} +EXPORT_SYMBOL_GPL(usb_wsource_init); + +/** + * usb_wsource_trash - Trash wakeupsource + * @usb_phy: the phy returned by usb_get_phy() + */ +void usb_wsource_trash(struct usb_phy *x) +{ + wakeup_source_trash(&x->wsource); + +} +EXPORT_SYMBOL_GPL(usb_wsource_trash); + +/** + * usb_grab_wsource - grab wakeupsource + * @usb_phy: the phy returned by usb_get_phy() + */ +void usb_grab_wsource(struct usb_phy *x) +{ + __pm_stay_awake(&x->wsource); +} +EXPORT_SYMBOL_GPL(usb_grab_wsource); + +/** + * usb_drop_wsource - drop wakeupsource + * @usb_phy: the phy returned by usb_get_phy() + */ +void usb_drop_wsource(struct usb_phy *x) +{ + __pm_relax(&x->wsource); +} +EXPORT_SYMBOL_GPL(usb_drop_wsource); diff --git a/include/linux/usb/phy.h b/include/linux/usb/phy.h index 353053a..6c680e6 100644 --- a/include/linux/usb/phy.h +++ b/include/linux/usb/phy.h @@ -11,6 +11,7 @@ #include #include +#include enum usb_phy_interface { USBPHY_INTERFACE_MODE_UNKNOWN, @@ -89,6 +90,9 @@ struct usb_phy { /* for notification of usb_phy_events */ struct atomic_notifier_head notifier; + /* wakeup source */ + struct wakeup_source wsource; + /* to pass extra port status to the root hub */ u16 port_status; u16 port_change; @@ -210,6 +214,10 @@ extern void usb_put_phy(struct usb_phy *); extern void devm_usb_put_phy(struct device *dev, struct usb_phy *x); extern int usb_bind_phy(const char *dev_name, u8 index, const char *phy_dev_name); +void usb_wsource_init(struct usb_phy *x, char *phy_dev_name); +void usb_wsource_trash(struct usb_phy *x); +void usb_grab_wsource(struct usb_phy *x); +void usb_drop_wsource(struct usb_phy *x); #else static inline struct usb_phy *usb_get_phy(enum usb_phy_type type) {