From cd36afbdb786c5ee8b2cdd319a85029c89d95e0f Mon Sep 17 00:00:00 2001 From: Liangliang Lu Date: Fri, 13 Jan 2017 11:36:21 +0800 Subject: [PATCH] usb: gadget: f_diag: allocate diag USB channel when not found Currently usb function instance driver depends on diag char driver to create the channel (using usb_diag_open api). Failing to create channel can result in enumeration failure. Avoid this dependency by creating diag channel from function instance if not available. Same channel will be reused when diag char driver creates/opens the channel. Change-Id: I11debd0189d81542762af22b3d203728d2266a42 Signed-off-by: Liangliang Lu --- drivers/usb/gadget/function/f_diag.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/drivers/usb/gadget/function/f_diag.c b/drivers/usb/gadget/function/f_diag.c index fe428e8bb781..da02ad557d34 100644 --- a/drivers/usb/gadget/function/f_diag.c +++ b/drivers/usb/gadget/function/f_diag.c @@ -352,9 +352,11 @@ struct usb_diag_ch *usb_diag_open(const char *name, void *priv, ch->priv = priv; ch->notify = notify; - spin_lock_irqsave(&ch_lock, flags); - list_add_tail(&ch->list, &usb_diag_ch_list); - spin_unlock_irqrestore(&ch_lock, flags); + if (!found) { + spin_lock_irqsave(&ch_lock, flags); + list_add_tail(&ch->list, &usb_diag_ch_list); + spin_unlock_irqrestore(&ch_lock, flags); + } return ch; } @@ -828,6 +830,7 @@ static struct diag_context *diag_context_init(const char *name) struct diag_context *dev; struct usb_diag_ch *_ch; int found = 0; + unsigned long flags; pr_debug("%s\n", __func__); @@ -837,9 +840,19 @@ static struct diag_context *diag_context_init(const char *name) break; } } + if (!found) { - pr_err("%s: unable to get diag usb channel\n", __func__); - return ERR_PTR(-ENODEV); + pr_warn("%s: unable to get diag usb channel\n", __func__); + + _ch = kzalloc(sizeof(*_ch), GFP_KERNEL); + if (_ch == NULL) + return ERR_PTR(-ENOMEM); + + _ch->name = name; + + spin_lock_irqsave(&ch_lock, flags); + list_add_tail(&_ch->list, &usb_diag_ch_list); + spin_unlock_irqrestore(&ch_lock, flags); } dev = kzalloc(sizeof(*dev), GFP_KERNEL);