Re: [PATCH] USB: gadgetfs: Fix crash caused by inadequate synchronization

2017-09-22 Thread Greg KH
On Thu, Sep 21, 2017 at 01:23:58PM -0400, Alan Stern wrote:
> The gadgetfs driver (drivers/usb/gadget/legacy/inode.c) was written
> before the UDC and composite frameworks were adopted; it is a legacy
> driver.  As such, it expects that once bound to a UDC controller, it
> will not be unbound until it unregisters itself.
> 
> However, the UDC framework does unbind function drivers while they are
> still registered.  When this happens, it can cause the gadgetfs driver
> to misbehave or crash.  For example, userspace can cause a crash by
> opening the device file and doing an ioctl call before setting up a
> configuration (found by Andrey Konovalov using the syzkaller fuzzer).
> 
> This patch adds checks and synchronization to prevent these bad
> behaviors.  It adds a udc_usage counter that the driver increments at
> times when it is using a gadget interface without holding the private
> spinlock.  The unbind routine waits for this counter to go to 0 before
> returning, thereby ensuring that the UDC is no longer in use.
> 
> The patch also adds a check in the dev_ioctl() routine to make sure
> the driver is bound to a UDC before dereferencing the gadget pointer,
> and it makes destroy_ep_files() synchronize with the endpoint I/O
> routines, to prevent the user from accessing an endpoint data
> structure after it has been removed.
> 
> Signed-off-by: Alan Stern 
> Reported-by: Andrey Konovalov 
> Tested-by: Andrey Konovalov 
> CC: 

Felipe, any objection for me taking this, and the other gadget driver
fixes that Alan just sent out, directly in my tree?

thanks,

greg k-h
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: usb/storage/uas: slab-out-of-bounds in uas_probe

2017-09-22 Thread Greg Kroah-Hartman
On Thu, Sep 21, 2017 at 03:04:05PM -0400, Alan Stern wrote:
> On Thu, 21 Sep 2017, Andrey Konovalov wrote:
> 
> > On Thu, Sep 21, 2017 at 6:10 PM, Greg Kroah-Hartman
> >  wrote:
> > > On Thu, Sep 21, 2017 at 05:39:05PM +0200, Andrey Konovalov wrote:
> > >> Hi!
> > >>
> > >> I've got the following report while fuzzing the kernel with syzkaller.
> > >>
> > >> On commit ebb2c2437d8008d46796902ff390653822af6cc4 (Sep 18).
> > >>
> > >> The issue occurs when we iterate over interface altsettings, but I
> > >> don't see the driver doing anything wrong. I might be missing
> > >> something, or this might be an issue in USB core altsettings parsing.
> > >
> > >
> > > Any chance you happen to have the descriptors that you were feeding into
> > > the kernel at this crash?  That might help in figuring out what "went
> > > wrong".
> > 
> > Here's the data that I feed into dummy_udc:
> > 
> > 00 00 00 00 09 02 12 00 01 34 05 80 07 09 04 6e
> > 09 00 08 06 62 00 12 01 05 00 cb f7 71 83 04 00
> > 05 00 ab f6 07 81 08 01
> > 
> > Also attaching a C reproducer (requires dummy_hcd and gadgetfs) and my 
> > .config.
> 
> Why do your reproducers use an mmap'ed array for their data instead of 
> a plain old statically allocated array?
> 
> Anyway, this turns out to be a genuine (and subtle!) bug in the uas
> driver.  The uas_find_uas_alt_setting() routine in uas-detect.h returns
> a bAlternateSetting value, but then the uas_use_uas_driver() routine
> uses this value as an index to the altsetting array -- which it isn't.  
> 
> Normally this doesn't cause any problems because the the entries in the
> array have bAlternateSetting values 0, 1, etc., so the value is equal
> to the index.  But in your fuzzed case, that wasn't true.
> 
> The patch below fixes this bug, by returning a pointer to the 
> alt-setting entry instead of either the value or the index.  Pointers 
> are less subject to misinterpretation.

Ugh, messy, nice catch and fix, I'll go queue it up now, thanks for
resolving this.

greg k-h
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: usb/storage/uas: slab-out-of-bounds in uas_probe

2017-09-22 Thread Greg Kroah-Hartman
On Fri, Sep 22, 2017 at 09:58:15AM +0200, Greg Kroah-Hartman wrote:
> On Thu, Sep 21, 2017 at 03:04:05PM -0400, Alan Stern wrote:
> > On Thu, 21 Sep 2017, Andrey Konovalov wrote:
> > 
> > > On Thu, Sep 21, 2017 at 6:10 PM, Greg Kroah-Hartman
> > >  wrote:
> > > > On Thu, Sep 21, 2017 at 05:39:05PM +0200, Andrey Konovalov wrote:
> > > >> Hi!
> > > >>
> > > >> I've got the following report while fuzzing the kernel with syzkaller.
> > > >>
> > > >> On commit ebb2c2437d8008d46796902ff390653822af6cc4 (Sep 18).
> > > >>
> > > >> The issue occurs when we iterate over interface altsettings, but I
> > > >> don't see the driver doing anything wrong. I might be missing
> > > >> something, or this might be an issue in USB core altsettings parsing.
> > > >
> > > >
> > > > Any chance you happen to have the descriptors that you were feeding into
> > > > the kernel at this crash?  That might help in figuring out what "went
> > > > wrong".
> > > 
> > > Here's the data that I feed into dummy_udc:
> > > 
> > > 00 00 00 00 09 02 12 00 01 34 05 80 07 09 04 6e
> > > 09 00 08 06 62 00 12 01 05 00 cb f7 71 83 04 00
> > > 05 00 ab f6 07 81 08 01
> > > 
> > > Also attaching a C reproducer (requires dummy_hcd and gadgetfs) and my 
> > > .config.
> > 
> > Why do your reproducers use an mmap'ed array for their data instead of 
> > a plain old statically allocated array?
> > 
> > Anyway, this turns out to be a genuine (and subtle!) bug in the uas
> > driver.  The uas_find_uas_alt_setting() routine in uas-detect.h returns
> > a bAlternateSetting value, but then the uas_use_uas_driver() routine
> > uses this value as an index to the altsetting array -- which it isn't.  
> > 
> > Normally this doesn't cause any problems because the the entries in the
> > array have bAlternateSetting values 0, 1, etc., so the value is equal
> > to the index.  But in your fuzzed case, that wasn't true.
> > 
> > The patch below fixes this bug, by returning a pointer to the 
> > alt-setting entry instead of either the value or the index.  Pointers 
> > are less subject to misinterpretation.
> 
> Ugh, messy, nice catch and fix, I'll go queue it up now, thanks for
> resolving this.

Oops, no, you didn't send this as a "real" patch yet, I'll wait :)
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 1/2] ARM: dts: exynos: Add dwc3 SUSPHY quirk

2017-09-22 Thread Andrzej Pietrasiewicz

Hi,

W dniu 19.09.2017 o 20:10, Robin Murphy pisze:

On 19/09/17 18:40, Krzysztof Kozlowski wrote:

On Mon, Sep 18, 2017 at 12:02:13PM +0200, Andrzej Pietrasiewicz wrote:

Odroid XU4 board does not enumerate SuperSpeed devices.
This patch makes exynos5 series chips use USB SUSPHY quirk,
which solves the problem.

Signed-off-by: Andrzej Pietrasiewicz 
---
  arch/arm/boot/dts/exynos54xx.dtsi | 2 ++
  1 file changed, 2 insertions(+)


Makes sense to me... was it tested also on XU3 and XU?


Well, it at least doesn't make USB3 on my XU any more or less broken
than it was before ;) (both ports still report an over-current condition
even with nothing plugged in - I suspect there's probably still some
pinctrl/regulator stuff missing)

Robin.


Similar with XU3: nothing is any more or less broken with this patch
compared to the situation without the patch.

Andrzej
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 0/9] use setup_timer() helper function.

2017-09-22 Thread Allen Pais
This series uses setup_timer() helper function. The series
addresses the files under drivers/usb/*.

Allen Pais (9):
  drivers: usb: hcd: use setup_timer() helper.
  drivers: usb: phy: omap: use setup_timer() helper.
  usb: gadget: udc: m66592: use setup_timer() helper.
  usb: gadget: udc: pxa25x_udc: use setup_timer() helper.
  drivers: usb: atm: cxacru: use setup_timer() helper.
  usb: gadget: udc: r8a66597: use setup_timer() helper.
  drivers: usb: speedtch: use setup_timer() helper.
  usb: gadget: udc: dummy_hcd: use setup_timer() helper.
  usb: gadget: udc: snps_udc_core: use setup_timer() helper.

 drivers/usb/atm/cxacru.c   |  4 +---
 drivers/usb/atm/speedtch.c | 11 ---
 drivers/usb/core/hcd.c |  4 +---
 drivers/usb/gadget/udc/dummy_hcd.c |  8 ++--
 drivers/usb/gadget/udc/m66592-udc.c|  4 +---
 drivers/usb/gadget/udc/pxa25x_udc.c|  4 +---
 drivers/usb/gadget/udc/r8a66597-udc.c  |  4 +---
 drivers/usb/gadget/udc/snps_udc_core.c |  8 ++--
 drivers/usb/phy/phy-isp1301-omap.c |  4 +---
 9 files changed, 14 insertions(+), 37 deletions(-)

-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/9] drivers: usb: hcd: use setup_timer() helper.

2017-09-22 Thread Allen Pais
   Use setup_timer function instead of initializing timer with the
   function and data fields.

Signed-off-by: Allen Pais 
---
 drivers/usb/core/hcd.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 75ad671..67aa3d0 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -2558,9 +2558,7 @@ struct usb_hcd *__usb_create_hcd(const struct hc_driver 
*driver,
hcd->self.bus_name = bus_name;
hcd->self.uses_dma = (sysdev->dma_mask != NULL);
 
-   init_timer(&hcd->rh_timer);
-   hcd->rh_timer.function = rh_timer_func;
-   hcd->rh_timer.data = (unsigned long) hcd;
+   setup_timer(&hcd->rh_timer, rh_timer_func, (unsigned long)hcd);
 #ifdef CONFIG_PM
INIT_WORK(&hcd->wakeup_work, hcd_resume_work);
 #endif
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/9] drivers: usb: phy: omap: use setup_timer() helper.

2017-09-22 Thread Allen Pais
   Use setup_timer function instead of initializing timer with the
   function and data fields.

Signed-off-by: Allen Pais 
---
 drivers/usb/phy/phy-isp1301-omap.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/usb/phy/phy-isp1301-omap.c 
b/drivers/usb/phy/phy-isp1301-omap.c
index c6052c8..5630840 100644
--- a/drivers/usb/phy/phy-isp1301-omap.c
+++ b/drivers/usb/phy/phy-isp1301-omap.c
@@ -1507,9 +1507,7 @@ isp1301_probe(struct i2c_client *i2c, const struct 
i2c_device_id *id)
}
 
INIT_WORK(&isp->work, isp1301_work);
-   init_timer(&isp->timer);
-   isp->timer.function = isp1301_timer;
-   isp->timer.data = (unsigned long) isp;
+   setup_timer(&isp->timer, isp1301_timer, (unsigned long)isp);
 
i2c_set_clientdata(i2c, isp);
isp->client = i2c;
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 5/9] drivers: usb: atm: cxacru: use setup_timer() helper.

2017-09-22 Thread Allen Pais
   Use setup_timer function instead of initializing timer with the
   function and data fields.

Signed-off-by: Allen Pais 
---
 drivers/usb/atm/cxacru.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c
index 5160a4a..600a670 100644
--- a/drivers/usb/atm/cxacru.c
+++ b/drivers/usb/atm/cxacru.c
@@ -570,10 +570,8 @@ static int cxacru_start_wait_urb(struct urb *urb, struct 
completion *done,
 {
struct timer_list timer;
 
-   init_timer(&timer);
+   setup_timer(&timer, cxacru_timeout_kill, (unsigned long)urb);
timer.expires = jiffies + msecs_to_jiffies(CMD_TIMEOUT);
-   timer.data = (unsigned long) urb;
-   timer.function = cxacru_timeout_kill;
add_timer(&timer);
wait_for_completion(done);
del_timer_sync(&timer);
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 4/9] usb: gadget: udc: pxa25x_udc: use setup_timer() helper.

2017-09-22 Thread Allen Pais
   Use setup_timer function instead of initializing timer with the
   function and data fields.

Signed-off-by: Allen Pais 
---
 drivers/usb/gadget/udc/pxa25x_udc.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/usb/gadget/udc/pxa25x_udc.c 
b/drivers/usb/gadget/udc/pxa25x_udc.c
index a238da9..974b778 100644
--- a/drivers/usb/gadget/udc/pxa25x_udc.c
+++ b/drivers/usb/gadget/udc/pxa25x_udc.c
@@ -2417,9 +2417,7 @@ static int pxa25x_udc_probe(struct platform_device *pdev)
gpio_direction_output(dev->mach->gpio_pullup, 0);
}
 
-   init_timer(&dev->timer);
-   dev->timer.function = udc_watchdog;
-   dev->timer.data = (unsigned long) dev;
+   setup_timer(&dev->timer, udc_watchdog, (unsigned long)dev);
 
the_controller = dev;
platform_set_drvdata(pdev, dev);
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 6/9] usb: gadget: udc: r8a66597: use setup_timer() helper.

2017-09-22 Thread Allen Pais
   Use setup_timer function instead of initializing timer with the
   function and data fields.

Signed-off-by: Allen Pais 
---
 drivers/usb/gadget/udc/r8a66597-udc.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/usb/gadget/udc/r8a66597-udc.c 
b/drivers/usb/gadget/udc/r8a66597-udc.c
index 118ad70..bb844b9 100644
--- a/drivers/usb/gadget/udc/r8a66597-udc.c
+++ b/drivers/usb/gadget/udc/r8a66597-udc.c
@@ -1877,9 +1877,7 @@ static int r8a66597_probe(struct platform_device *pdev)
r8a66597->gadget.max_speed = USB_SPEED_HIGH;
r8a66597->gadget.name = udc_name;
 
-   init_timer(&r8a66597->timer);
-   r8a66597->timer.function = r8a66597_timer;
-   r8a66597->timer.data = (unsigned long)r8a66597;
+   setup_timer(&r8a66597->timer, r8a66597_timer, (unsigned long)r8a66597);
r8a66597->reg = reg;
 
if (r8a66597->pdata->on_chip) {
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 8/9] usb: gadget: udc: dummy_hcd: use setup_timer() helper.

2017-09-22 Thread Allen Pais
   Use setup_timer function instead of initializing timer with the
   function and data fields.

Signed-off-by: Allen Pais 
---
 drivers/usb/gadget/udc/dummy_hcd.c | 8 ++--
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/gadget/udc/dummy_hcd.c 
b/drivers/usb/gadget/udc/dummy_hcd.c
index a030d79..c9ac44d 100644
--- a/drivers/usb/gadget/udc/dummy_hcd.c
+++ b/drivers/usb/gadget/udc/dummy_hcd.c
@@ -2389,9 +2389,7 @@ static DEVICE_ATTR_RO(urbs);
 
 static int dummy_start_ss(struct dummy_hcd *dum_hcd)
 {
-   init_timer(&dum_hcd->timer);
-   dum_hcd->timer.function = dummy_timer;
-   dum_hcd->timer.data = (unsigned long)dum_hcd;
+   setup_timer(&dum_hcd->timer, dummy_timer, (unsigned long)dum_hcd);
dum_hcd->rh_state = DUMMY_RH_RUNNING;
dum_hcd->stream_en_ep = 0;
INIT_LIST_HEAD(&dum_hcd->urbp_list);
@@ -2420,9 +2418,7 @@ static int dummy_start(struct usb_hcd *hcd)
return dummy_start_ss(dum_hcd);
 
spin_lock_init(&dum_hcd->dum->lock);
-   init_timer(&dum_hcd->timer);
-   dum_hcd->timer.function = dummy_timer;
-   dum_hcd->timer.data = (unsigned long)dum_hcd;
+   setup_timer(&dum_hcd->timer, dummy_timer, (unsigned long)dum_hcd);
dum_hcd->rh_state = DUMMY_RH_RUNNING;
 
INIT_LIST_HEAD(&dum_hcd->urbp_list);
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 9/9] usb: gadget: udc: snps_udc_core: use setup_timer() helper.

2017-09-22 Thread Allen Pais
   Use setup_timer function instead of initializing timer with the
   function and data fields.

Signed-off-by: Allen Pais 
---
 drivers/usb/gadget/udc/snps_udc_core.c | 8 ++--
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/gadget/udc/snps_udc_core.c 
b/drivers/usb/gadget/udc/snps_udc_core.c
index 38a165d..47df99d 100644
--- a/drivers/usb/gadget/udc/snps_udc_core.c
+++ b/drivers/usb/gadget/udc/snps_udc_core.c
@@ -3207,13 +3207,9 @@ int udc_probe(struct udc *dev)
goto finished;
 
/* timer init */
-   init_timer(&udc_timer);
-   udc_timer.function = udc_timer_function;
-   udc_timer.data = 1;
+   setup_timer(&udc_timer, udc_timer_function, 1);
/* timer pollstall init */
-   init_timer(&udc_pollstall_timer);
-   udc_pollstall_timer.function = udc_pollstall_timer_function;
-   udc_pollstall_timer.data = 1;
+   setup_timer(&udc_pollstall_timer, udc_pollstall_timer_function, 1);
 
/* set SD */
reg = readl(&dev->regs->ctl);
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 7/9] drivers: usb: speedtch: use setup_timer() helper.

2017-09-22 Thread Allen Pais
   Use setup_timer function instead of initializing timer with the
   function and data fields.

Signed-off-by: Allen Pais 
---
 drivers/usb/atm/speedtch.c | 11 ---
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c
index 3676adb..091db9b 100644
--- a/drivers/usb/atm/speedtch.c
+++ b/drivers/usb/atm/speedtch.c
@@ -874,16 +874,13 @@ static int speedtch_bind(struct usbatm_data *usbatm,
usbatm->flags |= (use_isoc ? UDSL_USE_ISOC : 0);
 
INIT_WORK(&instance->status_check_work, speedtch_check_status);
-   init_timer(&instance->status_check_timer);
-
-   instance->status_check_timer.function = speedtch_status_poll;
-   instance->status_check_timer.data = (unsigned long)instance;
+   setup_timer(&instance->status_check_timer, speedtch_status_poll,
+   (unsigned long)instance);
instance->last_status = 0xff;
instance->poll_delay = MIN_POLL_DELAY;
 
-   init_timer(&instance->resubmit_timer);
-   instance->resubmit_timer.function = speedtch_resubmit_int;
-   instance->resubmit_timer.data = (unsigned long)instance;
+   setup_timer(&instance->resubmit_timer, speedtch_resubmit_int,
+   (unsigned long)instance);
 
instance->int_urb = usb_alloc_urb(0, GFP_KERNEL);
 
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 3/9] usb: gadget: udc: m66592: use setup_timer() helper.

2017-09-22 Thread Allen Pais
   Use setup_timer function instead of initializing timer with the
   function and data fields.

Signed-off-by: Allen Pais 
---
 drivers/usb/gadget/udc/m66592-udc.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/usb/gadget/udc/m66592-udc.c 
b/drivers/usb/gadget/udc/m66592-udc.c
index 46ce7bc..3b8dbed 100644
--- a/drivers/usb/gadget/udc/m66592-udc.c
+++ b/drivers/usb/gadget/udc/m66592-udc.c
@@ -1592,9 +1592,7 @@ static int m66592_probe(struct platform_device *pdev)
m66592->gadget.max_speed = USB_SPEED_HIGH;
m66592->gadget.name = udc_name;
 
-   init_timer(&m66592->timer);
-   m66592->timer.function = m66592_timer;
-   m66592->timer.data = (unsigned long)m66592;
+   setup_timer(&m66592->timer, m66592_timer, (unsigned long)m66592);
m66592->reg = reg;
 
ret = request_irq(ires->start, m66592_irq, IRQF_SHARED,
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] USB: gadgetfs: Fix crash caused by inadequate synchronization

2017-09-22 Thread Felipe Balbi

Hi,

Greg KH  writes:
> On Thu, Sep 21, 2017 at 01:23:58PM -0400, Alan Stern wrote:
>> The gadgetfs driver (drivers/usb/gadget/legacy/inode.c) was written
>> before the UDC and composite frameworks were adopted; it is a legacy
>> driver.  As such, it expects that once bound to a UDC controller, it
>> will not be unbound until it unregisters itself.
>> 
>> However, the UDC framework does unbind function drivers while they are
>> still registered.  When this happens, it can cause the gadgetfs driver
>> to misbehave or crash.  For example, userspace can cause a crash by
>> opening the device file and doing an ioctl call before setting up a
>> configuration (found by Andrey Konovalov using the syzkaller fuzzer).
>> 
>> This patch adds checks and synchronization to prevent these bad
>> behaviors.  It adds a udc_usage counter that the driver increments at
>> times when it is using a gadget interface without holding the private
>> spinlock.  The unbind routine waits for this counter to go to 0 before
>> returning, thereby ensuring that the UDC is no longer in use.
>> 
>> The patch also adds a check in the dev_ioctl() routine to make sure
>> the driver is bound to a UDC before dereferencing the gadget pointer,
>> and it makes destroy_ep_files() synchronize with the endpoint I/O
>> routines, to prevent the user from accessing an endpoint data
>> structure after it has been removed.
>> 
>> Signed-off-by: Alan Stern 
>> Reported-by: Andrey Konovalov 
>> Tested-by: Andrey Konovalov 
>> CC: 
>
> Felipe, any objection for me taking this, and the other gadget driver
> fixes that Alan just sent out, directly in my tree?

none whatsoever, for all of them:

Acked-by: Felipe Balbi 

I'll rebase my testing/fixes on top of your greg/usb-linus for the
remaining of the -rc cycle ;-)

-- 
balbi


signature.asc
Description: PGP signature


Re: [PATCH] USB: g_mass_storage: Fix deadlock when driver is unbound

2017-09-22 Thread Felipe Balbi
Alan Stern  writes:
> As a holdover from the old g_file_storage gadget, the g_mass_storage
> legacy gadget driver attempts to unregister itself when its main
> operating thread terminates (if it hasn't been unregistered already).
> This is not strictly necessary; it was never more than an attempt to
> have the gadget fail cleanly if something went wrong and the main
> thread was killed.
>
> However, now that the UDC core manages gadget drivers independently of
> UDC drivers, this scheme doesn't work any more.  A simple test:
>
>   modprobe dummy-hcd
>   modprobe g-mass-storage file=...
>   rmmod dummy-hcd
>
> ends up in a deadlock with the following backtrace:
>
>  sysrq: SysRq : Show Blocked State
>taskPC stack   pid father
>  file-storageD0  1130  2 0x
>  Call Trace:
>   __schedule+0x53e/0x58c
>   schedule+0x6e/0x77
>   schedule_preempt_disabled+0xd/0xf
>   __mutex_lock.isra.1+0x129/0x224
>   ? _raw_spin_unlock_irqrestore+0x12/0x14
>   __mutex_lock_slowpath+0x12/0x14
>   mutex_lock+0x28/0x2b
>   usb_gadget_unregister_driver+0x29/0x9b [udc_core]
>   usb_composite_unregister+0x10/0x12 [libcomposite]
>   msg_cleanup+0x1d/0x20 [g_mass_storage]
>   msg_thread_exits+0xd/0xdd7 [g_mass_storage]
>   fsg_main_thread+0x1395/0x13d6 [usb_f_mass_storage]
>   ? __schedule+0x573/0x58c
>   kthread+0xd9/0xdb
>   ? do_set_interface+0x25c/0x25c [usb_f_mass_storage]
>   ? init_completion+0x1e/0x1e
>   ret_from_fork+0x19/0x24
>  rmmod   D0  1155683 0x
>  Call Trace:
>   __schedule+0x53e/0x58c
>   schedule+0x6e/0x77
>   schedule_timeout+0x26/0xbc
>   ? __schedule+0x573/0x58c
>   do_wait_for_common+0xb3/0x128
>   ? usleep_range+0x81/0x81
>   ? wake_up_q+0x3f/0x3f
>   wait_for_common+0x2e/0x45
>   wait_for_completion+0x17/0x19
>   fsg_common_put+0x34/0x81 [usb_f_mass_storage]
>   fsg_free_inst+0x13/0x1e [usb_f_mass_storage]
>   usb_put_function_instance+0x1a/0x25 [libcomposite]
>   msg_unbind+0x2a/0x42 [g_mass_storage]
>   __composite_unbind+0x4a/0x6f [libcomposite]
>   composite_unbind+0x12/0x14 [libcomposite]
>   usb_gadget_remove_driver+0x4f/0x77 [udc_core]
>   usb_del_gadget_udc+0x52/0xcc [udc_core]
>   dummy_udc_remove+0x27/0x2c [dummy_hcd]
>   platform_drv_remove+0x1d/0x31
>   device_release_driver_internal+0xe9/0x16d
>   device_release_driver+0x11/0x13
>   bus_remove_device+0xd2/0xe2
>   device_del+0x19f/0x221
>   ? selinux_capable+0x22/0x27
>   platform_device_del+0x21/0x63
>   platform_device_unregister+0x10/0x1a
>   cleanup+0x20/0x817 [dummy_hcd]
>   SyS_delete_module+0x10c/0x197
>   ? fput+0xd/0xf
>   ? task_work_run+0x55/0x62
>   ? prepare_exit_to_usermode+0x65/0x75
>   do_fast_syscall_32+0x86/0xc3
>   entry_SYSENTER_32+0x4e/0x7c
>
> What happens is that removing the dummy-hcd driver causes the UDC core
> to unbind the gadget driver, which it does while holding the udc_lock
> mutex.  The unbind routine in g_mass_storage tells the main thread to
> exit and waits for it to terminate.
>
> But as mentioned above, when the main thread exits it tries to
> unregister the mass-storage function driver.  Via the composite
> framework this ends up calling usb_gadget_unregister_driver(), which
> tries to acquire the udc_lock mutex.  The result is deadlock.
>
> The simplest way to fix the problem is not to be so clever: The main
> thread doesn't have to unregister the function driver.  The side
> effects won't be so terrible; if the gadget is still attached to a USB
> host when the main thread is killed, it will appear to the host as
> though the gadget's firmware has crashed -- a reasonably accurate
> interpretation, and an all-too-common occurrence for USB mass-storage
> devices.
>
> In fact, the code to unregister the driver when the main thread exits
> is specific to g-mass-storage; it is not used when f-mass-storage is
> included as a function in a larger composite device.  Therefore the
> entire mechanism responsible for this (the fsg_operations structure
> with its ->thread_exits method, the fsg_common_set_ops() routine, and
> the msg_thread_exits() callback routine) can all be eliminated.  Even
> the msg_registered bitflag can be removed, because now the driver is
> unregistered in only one place rather than in two places.
>
> Signed-off-by: Alan Stern 
> CC: Michal Nazarewicz 
> CC: 

Acked-by: Felipe Balbi 

-- 
balbi


signature.asc
Description: PGP signature


Re: [PATCH] USB: gadgetfs: fix copy_to_user while holding spinlock

2017-09-22 Thread Felipe Balbi
Alan Stern  writes:

> The gadgetfs driver as a long-outstanding FIXME, regarding a call of
> copy_to_user() made while holding a spinlock.  This patch fixes the
> issue by dropping the spinlock and using the dev->udc_usage mechanism
> introduced by another recent patch to guard against status changes
> while the lock isn't held.
>
> Signed-off-by: Alan Stern 
> Reported-by: Andrey Konovalov 
> CC: 

Acked-by: Felipe Balbi 

-- 
balbi


signature.asc
Description: PGP signature


Re: [PATCH v2 3/9] clk: at91: pmc: Support backup for programmable clocks

2017-09-22 Thread Nicolas Ferre
On 15/09/2017 at 16:04, Romain Izard wrote:
> From: Romain Izard 
> 
> When an AT91 programmable clock is declared in the device tree, register
> it into the Power Management Controller driver. On entering suspend mode,
> the driver saves and restores the Programmable Clock registers to support
> the backup mode for these clocks.
> 
> Signed-off-by: Romain Izard 

Romain,

Some nitpicking and one comment. But on the overall patch, here is my:
Acked-by: Nicolas Ferre 

See below:

> ---
> Changes in v2:
> * register PCKs on clock startup
> 
>  drivers/clk/at91/clk-programmable.c |  2 ++
>  drivers/clk/at91/pmc.c  | 27 +++
>  drivers/clk/at91/pmc.h  |  2 ++
>  3 files changed, 31 insertions(+)
> 
> diff --git a/drivers/clk/at91/clk-programmable.c 
> b/drivers/clk/at91/clk-programmable.c
> index 85a449cf61e3..0e6aab1252fc 100644
> --- a/drivers/clk/at91/clk-programmable.c
> +++ b/drivers/clk/at91/clk-programmable.c
> @@ -204,6 +204,8 @@ at91_clk_register_programmable(struct regmap *regmap,
>   if (ret) {
>   kfree(prog);
>   hw = ERR_PTR(ret);

Nit: "else" not needed.

> + } else {
> + pmc_register_pck(id);
>   }
>  
>   return hw;
> diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c
> index 07dc2861ad3f..3910b7537152 100644
> --- a/drivers/clk/at91/pmc.c
> +++ b/drivers/clk/at91/pmc.c
> @@ -22,6 +22,7 @@
>  #include "pmc.h"
>  
>  #define PMC_MAX_IDS 128
> +#define PMC_MAX_PCKS 8
>  
>  int of_at91_get_clk_range(struct device_node *np, const char *propname,
> struct clk_range *range)
> @@ -50,6 +51,7 @@ EXPORT_SYMBOL_GPL(of_at91_get_clk_range);
>  static struct regmap *pmcreg;
>  
>  static u8 registered_ids[PMC_MAX_IDS];
> +static u8 registered_pcks[PMC_MAX_PCKS];
>  
>  static struct
>  {
> @@ -66,8 +68,10 @@ static struct
>   u32 pcr[PMC_MAX_IDS];
>   u32 audio_pll0;
>   u32 audio_pll1;
> + u32 pckr[PMC_MAX_PCKS];
>  } pmc_cache;
>  
> +/* Clock ID 0 is invalid */

(read: so we can use the 0 value as an indicator that this place in the
table hasn't been filled, so unused)

>  void pmc_register_id(u8 id)
>  {
>   int i;
> @@ -82,6 +86,21 @@ void pmc_register_id(u8 id)
>   }
>  }
>  
> +/* Programmable Clock 0 is valid */

I understand the rationale behind these ^^ two comments, but I would
like that it's more explicit. Saying that you will store the pck id as
(id + 1) and that you would have to invert this operation while using
the stored id.
Maybe add a comment about this transformation to the struct definition
as well...


> +void pmc_register_pck(u8 pck)
> +{
> + int i;
> +
> + for (i = 0; i < PMC_MAX_PCKS; i++) {
> + if (registered_pcks[i] == 0) {
> + registered_pcks[i] = pck + 1;
> + break;
> + }
> + if (registered_pcks[i] == (pck + 1))
> + break;
> + }
> +}
> +
>  static int pmc_suspend(void)
>  {
>   int i;
> @@ -103,6 +122,10 @@ static int pmc_suspend(void)
>   regmap_read(pmcreg, AT91_PMC_PCR,
>   &pmc_cache.pcr[registered_ids[i]]);
>   }
> + for (i = 0; registered_pcks[i]; i++) {
> + u8 num = registered_pcks[i] - 1;

Nit: declaration are better made at the beginning of the function. This
lead to a checkpatch warning:
"WARNING: Missing a blank line after declarations"

> + regmap_read(pmcreg, AT91_PMC_PCKR(num), &pmc_cache.pckr[num]);
> + }
>  
>   return 0;
>  }
> @@ -143,6 +166,10 @@ static void pmc_resume(void)
>pmc_cache.pcr[registered_ids[i]] |
>AT91_PMC_PCR_CMD);
>   }
> + for (i = 0; registered_pcks[i]; i++) {
> + u8 num = registered_pcks[i] - 1;

Ditto

> + regmap_write(pmcreg, AT91_PMC_PCKR(num), pmc_cache.pckr[num]);
> + }
>  
>   if (pmc_cache.uckr & AT91_PMC_UPLLEN)
>   mask |= AT91_PMC_LOCKU;
> diff --git a/drivers/clk/at91/pmc.h b/drivers/clk/at91/pmc.h
> index 858e8ef7e8db..d22b1fa9ecdc 100644
> --- a/drivers/clk/at91/pmc.h
> +++ b/drivers/clk/at91/pmc.h
> @@ -31,8 +31,10 @@ int of_at91_get_clk_range(struct device_node *np, const 
> char *propname,
>  
>  #ifdef CONFIG_PM
>  void pmc_register_id(u8 id);
> +void pmc_register_pck(u8 pck);
>  #else
>  static inline void pmc_register_id(u8 id) {}
> +static inline void pmc_register_pck(u8 pck) {}
>  #endif
>  
>  #endif /* __PMC_H_ */
> 


-- 
Nicolas Ferre
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: usb/storage/uas: slab-out-of-bounds in uas_probe

2017-09-22 Thread Andrey Konovalov
On Thu, Sep 21, 2017 at 9:04 PM, Alan Stern  wrote:
> On Thu, 21 Sep 2017, Andrey Konovalov wrote:
>
>> On Thu, Sep 21, 2017 at 6:10 PM, Greg Kroah-Hartman
>>  wrote:
>> > On Thu, Sep 21, 2017 at 05:39:05PM +0200, Andrey Konovalov wrote:
>> >> Hi!
>> >>
>> >> I've got the following report while fuzzing the kernel with syzkaller.
>> >>
>> >> On commit ebb2c2437d8008d46796902ff390653822af6cc4 (Sep 18).
>> >>
>> >> The issue occurs when we iterate over interface altsettings, but I
>> >> don't see the driver doing anything wrong. I might be missing
>> >> something, or this might be an issue in USB core altsettings parsing.
>> >
>> >
>> > Any chance you happen to have the descriptors that you were feeding into
>> > the kernel at this crash?  That might help in figuring out what "went
>> > wrong".
>>
>> Here's the data that I feed into dummy_udc:
>>
>> 00 00 00 00 09 02 12 00 01 34 05 80 07 09 04 6e
>> 09 00 08 06 62 00 12 01 05 00 cb f7 71 83 04 00
>> 05 00 ab f6 07 81 08 01
>>
>> Also attaching a C reproducer (requires dummy_hcd and gadgetfs) and my 
>> .config.
>
> Why do your reproducers use an mmap'ed array for their data instead of
> a plain old statically allocated array?

That's just the way syzkaller generates reproducers, it uses mmap() to
allocate memory to feed into syscalls.

>
> Anyway, this turns out to be a genuine (and subtle!) bug in the uas
> driver.  The uas_find_uas_alt_setting() routine in uas-detect.h returns
> a bAlternateSetting value, but then the uas_use_uas_driver() routine
> uses this value as an index to the altsetting array -- which it isn't.
>
> Normally this doesn't cause any problems because the the entries in the
> array have bAlternateSetting values 0, 1, etc., so the value is equal
> to the index.  But in your fuzzed case, that wasn't true.
>
> The patch below fixes this bug, by returning a pointer to the
> alt-setting entry instead of either the value or the index.  Pointers
> are less subject to misinterpretation.

The patch helps, thanks!

Tested-by: Andrey Konovalov 

>
> Alan Stern
>
>
>
> Index: usb-4.x/drivers/usb/storage/uas-detect.h
> ===
> --- usb-4.x.orig/drivers/usb/storage/uas-detect.h
> +++ usb-4.x/drivers/usb/storage/uas-detect.h
> @@ -9,7 +9,8 @@ static int uas_is_interface(struct usb_h
> intf->desc.bInterfaceProtocol == USB_PR_UAS);
>  }
>
> -static int uas_find_uas_alt_setting(struct usb_interface *intf)
> +static struct usb_host_interface *uas_find_uas_alt_setting(
> +   struct usb_interface *intf)
>  {
> int i;
>
> @@ -17,10 +18,10 @@ static int uas_find_uas_alt_setting(stru
> struct usb_host_interface *alt = &intf->altsetting[i];
>
> if (uas_is_interface(alt))
> -   return alt->desc.bAlternateSetting;
> +   return alt;
> }
>
> -   return -ENODEV;
> +   return NULL;
>  }
>
>  static int uas_find_endpoints(struct usb_host_interface *alt,
> @@ -58,14 +59,14 @@ static int uas_use_uas_driver(struct usb
> struct usb_device *udev = interface_to_usbdev(intf);
> struct usb_hcd *hcd = bus_to_hcd(udev->bus);
> unsigned long flags = id->driver_info;
> -   int r, alt;
> -
> +   struct usb_host_interface *alt;
> +   int r;
>
> alt = uas_find_uas_alt_setting(intf);
> -   if (alt < 0)
> +   if (!alt)
> return 0;
>
> -   r = uas_find_endpoints(&intf->altsetting[alt], eps);
> +   r = uas_find_endpoints(alt, eps);
> if (r < 0)
> return 0;
>
> Index: usb-4.x/drivers/usb/storage/uas.c
> ===
> --- usb-4.x.orig/drivers/usb/storage/uas.c
> +++ usb-4.x/drivers/usb/storage/uas.c
> @@ -873,14 +873,14 @@ MODULE_DEVICE_TABLE(usb, uas_usb_ids);
>  static int uas_switch_interface(struct usb_device *udev,
> struct usb_interface *intf)
>  {
> -   int alt;
> +   struct usb_host_interface *alt;
>
> alt = uas_find_uas_alt_setting(intf);
> -   if (alt < 0)
> -   return alt;
> +   if (!alt)
> +   return -ENODEV;
>
> -   return usb_set_interface(udev,
> -   intf->altsetting[0].desc.bInterfaceNumber, alt);
> +   return usb_set_interface(udev, alt->desc.bInterfaceNumber,
> +   alt->desc.bAlternateSetting);
>  }
>
>  static int uas_configure_endpoints(struct uas_dev_info *devinfo)
>
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 1/9] clk: at91: pmc: Wait for clocks when resuming

2017-09-22 Thread Ludovic Desroches
On Fri, Sep 15, 2017 at 04:04:03PM +0200, Romain Izard wrote:
> Wait for the syncronization of all clocks when resuming, not only the
> UPLL clock. Do not use regmap_read_poll_timeout, as it will call BUG()
> when interrupts are masked, which is the case in here.
> 
> Signed-off-by: Romain Izard 
Acked-by: Ludovic Desroches 

I faced the same issue because of the use of regmap_read_poll_timeout
when timekeeping is not ready.


Ludovic

> ---
>  drivers/clk/at91/pmc.c | 24 
>  1 file changed, 16 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c
> index 775af473fe11..5c2b26de303e 100644
> --- a/drivers/clk/at91/pmc.c
> +++ b/drivers/clk/at91/pmc.c
> @@ -107,10 +107,20 @@ static int pmc_suspend(void)
>   return 0;
>  }
>  
> +static bool pmc_ready(unsigned int mask)
> +{
> + unsigned int status;
> +
> + regmap_read(pmcreg, AT91_PMC_SR, &status);
> +
> + return ((status & mask) == mask) ? 1 : 0;
> +}
> +
>  static void pmc_resume(void)
>  {
> - int i, ret = 0;
> + int i;
>   u32 tmp;
> + u32 mask = AT91_PMC_MCKRDY | AT91_PMC_LOCKA;
>  
>   regmap_read(pmcreg, AT91_PMC_MCKR, &tmp);
>   if (pmc_cache.mckr != tmp)
> @@ -134,13 +144,11 @@ static void pmc_resume(void)
>AT91_PMC_PCR_CMD);
>   }
>  
> - if (pmc_cache.uckr & AT91_PMC_UPLLEN) {
> - ret = regmap_read_poll_timeout(pmcreg, AT91_PMC_SR, tmp,
> -!(tmp & AT91_PMC_LOCKU),
> -10, 5000);
> - if (ret)
> - pr_crit("USB PLL didn't lock when resuming\n");
> - }
> + if (pmc_cache.uckr & AT91_PMC_UPLLEN)
> + mask |= AT91_PMC_LOCKU;
> +
> + while (!pmc_ready(mask))
> + cpu_relax();
>  }
>  
>  static struct syscore_ops pmc_syscore_ops = {
> -- 
> 2.11.0
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v1 01/10] clk: at91: pmc: Wait for clocks when resuming

2017-09-22 Thread Nicolas Ferre
On 14/09/2017 at 18:15, Romain Izard wrote:
> 2017-09-13 14:15 GMT+02:00 Nicolas Ferre :
>> On 08/09/2017 at 17:35, Romain Izard wrote:
>>> Wait for the syncronization of all clocks when resuming, not only the
>>> UPLL clock. Do not use regmap_read_poll_timeout, as it will call BUG()
>>> when interrupts are masked, which is the case in here.
>>>
>>> Signed-off-by: Romain Izard 
>>> ---
>>>  drivers/clk/at91/pmc.c | 24 
>>>  1 file changed, 16 insertions(+), 8 deletions(-)
>>>
>>> diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c
>>> index 775af473fe11..5c2b26de303e 100644
>>> --- a/drivers/clk/at91/pmc.c
>>> +++ b/drivers/clk/at91/pmc.c
>>> @@ -107,10 +107,20 @@ static int pmc_suspend(void)
>>>   return 0;
>>>  }
>>>
>>> +static bool pmc_ready(unsigned int mask)
>>> +{
>>> + unsigned int status;
>>> +
>>> + regmap_read(pmcreg, AT91_PMC_SR, &status);
>>> +
>>> + return ((status & mask) == mask) ? 1 : 0;
>>> +}
>>> +
>>>  static void pmc_resume(void)
>>>  {
>>> - int i, ret = 0;
>>> + int i;
>>>   u32 tmp;
>>> + u32 mask = AT91_PMC_MCKRDY | AT91_PMC_LOCKA;
>>>
>>>   regmap_read(pmcreg, AT91_PMC_MCKR, &tmp);
>>>   if (pmc_cache.mckr != tmp)
>>> @@ -134,13 +144,11 @@ static void pmc_resume(void)
>>>AT91_PMC_PCR_CMD);
>>>   }
>>>
>>> - if (pmc_cache.uckr & AT91_PMC_UPLLEN) {
>>> - ret = regmap_read_poll_timeout(pmcreg, AT91_PMC_SR, tmp,
>>> -!(tmp & AT91_PMC_LOCKU),
>>> -10, 5000);
>>> - if (ret)
>>> - pr_crit("USB PLL didn't lock when resuming\n");
>>> - }
>>> + if (pmc_cache.uckr & AT91_PMC_UPLLEN)
>>> + mask |= AT91_PMC_LOCKU;
>>> +
>>> + while (!pmc_ready(mask))
>>> + cpu_relax();
>>
>> Okay, but I would prefer to keep the timeout property in it. So we may
>> need to re-implement a timeout way-out here.
>>
> 
> We need to have a reference clock to measure the timeout delay. If we use
> the kernel's timekeeping, it relies on the clocks that we are configuring in
> this code. Moreover, my experience with the mainline code is that when
> something goes wrong, nothing will work. No oops or panic will be reported,
> the device will just stop working.
> 
> In my case, I had obvious failures (it just stopped working unless I removed
> USB wakeup or activated the console during suspend) but also very rare
> failures, that occurred in the bootloader. Those issues were detected when
> testing repeated suspend cycles for a night: the memory controller would
> never enter the self-refresh mode during the resume sequence.
> 
> This led me to question the bootloader's code first, and I set up 4 boards
> with the backup prototype code on v4.9 to verify that it was stable on
> suspend. I've reached 1.5 million sleep cycles over 3 weeks without
> failure, so this hinted towards the difference between the prototype and the
> backup code provided for v4.12 (which contained the patch that got in
> v4.13). Once I integrated this patch, I've run the v4.12 code for 2 weeks
> without issue as well.
> 
> In the end, I don't want to touch this code if I do not have to, as checking
> that it does not regress is really cumbersome.

The timeout was more for PLL like the one use for USB. I didn't want to
block only for USB PLL failure (which is kind of hypothetical, I admit).
Anyway, I understand your arguments and taking into account the
extensive tests that you've run, I agree with your approach. I'm adding
my Ack to the v2.

Thanks for having take the time to describe your debugging session: it's
valuable information for everybody.

Best regards,
-- 
Nicolas Ferre
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 1/9] clk: at91: pmc: Wait for clocks when resuming

2017-09-22 Thread Nicolas Ferre
On 15/09/2017 at 16:04, Romain Izard wrote:
> Wait for the syncronization of all clocks when resuming, not only the
> UPLL clock. Do not use regmap_read_poll_timeout, as it will call BUG()
> when interrupts are masked, which is the case in here.
> 
> Signed-off-by: Romain Izard 

And here is my:
Acked-by: Nicolas Ferre 

> ---
>  drivers/clk/at91/pmc.c | 24 
>  1 file changed, 16 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c
> index 775af473fe11..5c2b26de303e 100644
> --- a/drivers/clk/at91/pmc.c
> +++ b/drivers/clk/at91/pmc.c
> @@ -107,10 +107,20 @@ static int pmc_suspend(void)
>   return 0;
>  }
>  
> +static bool pmc_ready(unsigned int mask)
> +{
> + unsigned int status;
> +
> + regmap_read(pmcreg, AT91_PMC_SR, &status);
> +
> + return ((status & mask) == mask) ? 1 : 0;
> +}
> +
>  static void pmc_resume(void)
>  {
> - int i, ret = 0;
> + int i;
>   u32 tmp;
> + u32 mask = AT91_PMC_MCKRDY | AT91_PMC_LOCKA;
>  
>   regmap_read(pmcreg, AT91_PMC_MCKR, &tmp);
>   if (pmc_cache.mckr != tmp)
> @@ -134,13 +144,11 @@ static void pmc_resume(void)
>AT91_PMC_PCR_CMD);
>   }
>  
> - if (pmc_cache.uckr & AT91_PMC_UPLLEN) {
> - ret = regmap_read_poll_timeout(pmcreg, AT91_PMC_SR, tmp,
> -!(tmp & AT91_PMC_LOCKU),
> -10, 5000);
> - if (ret)
> - pr_crit("USB PLL didn't lock when resuming\n");
> - }
> + if (pmc_cache.uckr & AT91_PMC_UPLLEN)
> + mask |= AT91_PMC_LOCKU;
> +
> + while (!pmc_ready(mask))
> + cpu_relax();
>  }
>  
>  static struct syscore_ops pmc_syscore_ops = {
> 


-- 
Nicolas Ferre
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 6/9] ehci-atmel: Power down during suspend is normal

2017-09-22 Thread Nicolas Ferre
On 15/09/2017 at 16:04, Romain Izard wrote:
> When an Atmel SoC is suspended with the backup mode, the USB bus will be
> powered down. As this is expected, do not return an error to the driver
> core when ehci_resume detects it.
> 
> Signed-off-by: Romain Izard 
> ---
>  drivers/usb/host/ehci-atmel.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c
> index 7440722bfbf0..2a8b9bdc0e57 100644
> --- a/drivers/usb/host/ehci-atmel.c
> +++ b/drivers/usb/host/ehci-atmel.c
> @@ -205,7 +205,8 @@ static int __maybe_unused ehci_atmel_drv_resume(struct 
> device *dev)
>   struct atmel_ehci_priv *atmel_ehci = hcd_to_atmel_ehci_priv(hcd);
>  
>   atmel_start_clock(atmel_ehci);
> - return ehci_resume(hcd, false);
> + ehci_resume(hcd, false);
> + return 0;

Ok, I agree with that as the underlying function takes care about the
controller, in any case (even for !B+S-R case). So we don't have any
added value to propagate this information.

Acked-by: Nicolas Ferre 

>  }
>  
>  #ifdef CONFIG_OF
> 


-- 
Nicolas Ferre
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 7/9] pwm: atmel-tcb: Support backup mode

2017-09-22 Thread Nicolas Ferre
On 15/09/2017 at 16:04, Romain Izard wrote:
> Save and restore registers for the PWM on suspend and resume, which
> makes hibernation and backup modes possible.
> 
> Signed-off-by: Romain Izard 

Seems good to me:
Acked-by: Nicolas Ferre 

> ---
>  drivers/pwm/pwm-atmel-tcb.c | 63 
> +++--
>  1 file changed, 61 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/pwm/pwm-atmel-tcb.c b/drivers/pwm/pwm-atmel-tcb.c
> index 75db585a2a94..acd3ce8ecf3f 100644
> --- a/drivers/pwm/pwm-atmel-tcb.c
> +++ b/drivers/pwm/pwm-atmel-tcb.c
> @@ -37,11 +37,20 @@ struct atmel_tcb_pwm_device {
>   unsigned period;/* PWM period expressed in clk cycles */
>  };
>  
> +struct atmel_tcb_channel {
> + u32 enabled;
> + u32 cmr;
> + u32 ra;
> + u32 rb;
> + u32 rc;
> +};
> +
>  struct atmel_tcb_pwm_chip {
>   struct pwm_chip chip;
>   spinlock_t lock;
>   struct atmel_tc *tc;
>   struct atmel_tcb_pwm_device *pwms[NPWM];
> + struct atmel_tcb_channel bkup[NPWM / 2];
>  };
>  
>  static inline struct atmel_tcb_pwm_chip *to_tcb_chip(struct pwm_chip *chip)
> @@ -175,12 +184,15 @@ static void atmel_tcb_pwm_disable(struct pwm_chip 
> *chip, struct pwm_device *pwm)
>* Use software trigger to apply the new setting.
>* If both PWM devices in this group are disabled we stop the clock.
>*/
> - if (!(cmr & (ATMEL_TC_ACPC | ATMEL_TC_BCPC)))
> + if (!(cmr & (ATMEL_TC_ACPC | ATMEL_TC_BCPC))) {
>   __raw_writel(ATMEL_TC_SWTRG | ATMEL_TC_CLKDIS,
>regs + ATMEL_TC_REG(group, CCR));
> - else
> + tcbpwmc->bkup[group].enabled = 1;
> + } else {
>   __raw_writel(ATMEL_TC_SWTRG, regs +
>ATMEL_TC_REG(group, CCR));
> + tcbpwmc->bkup[group].enabled = 0;
> + }
>  
>   spin_unlock(&tcbpwmc->lock);
>  }
> @@ -263,6 +275,7 @@ static int atmel_tcb_pwm_enable(struct pwm_chip *chip, 
> struct pwm_device *pwm)
>   /* Use software trigger to apply the new setting */
>   __raw_writel(ATMEL_TC_CLKEN | ATMEL_TC_SWTRG,
>regs + ATMEL_TC_REG(group, CCR));
> + tcbpwmc->bkup[group].enabled = 1;
>   spin_unlock(&tcbpwmc->lock);
>   return 0;
>  }
> @@ -445,10 +458,56 @@ static const struct of_device_id atmel_tcb_pwm_dt_ids[] 
> = {
>  };
>  MODULE_DEVICE_TABLE(of, atmel_tcb_pwm_dt_ids);
>  
> +#ifdef CONFIG_PM_SLEEP
> +static int atmel_tcb_pwm_suspend(struct device *dev)
> +{
> + struct platform_device *pdev = to_platform_device(dev);
> + struct atmel_tcb_pwm_chip *tcbpwm = platform_get_drvdata(pdev);
> + void __iomem *base = tcbpwm->tc->regs;
> + int i;
> +
> + for (i = 0; i < (NPWM / 2); i++) {
> + struct atmel_tcb_channel *chan = &tcbpwm->bkup[i];
> +
> + chan->cmr = readl(base + ATMEL_TC_REG(i, CMR));
> + chan->ra = readl(base + ATMEL_TC_REG(i, RA));
> + chan->rb = readl(base + ATMEL_TC_REG(i, RB));
> + chan->rc = readl(base + ATMEL_TC_REG(i, RC));
> + }
> + return 0;
> +}
> +
> +static int atmel_tcb_pwm_resume(struct device *dev)
> +{
> + struct platform_device *pdev = to_platform_device(dev);
> + struct atmel_tcb_pwm_chip *tcbpwm = platform_get_drvdata(pdev);
> + void __iomem *base = tcbpwm->tc->regs;
> + int i;
> +
> + for (i = 0; i < (NPWM / 2); i++) {
> + struct atmel_tcb_channel *chan = &tcbpwm->bkup[i];
> +
> + writel(chan->cmr, base + ATMEL_TC_REG(i, CMR));
> + writel(chan->ra, base + ATMEL_TC_REG(i, RA));
> + writel(chan->rb, base + ATMEL_TC_REG(i, RB));
> + writel(chan->rc, base + ATMEL_TC_REG(i, RC));
> + if (chan->enabled) {
> + writel(ATMEL_TC_CLKEN | ATMEL_TC_SWTRG,
> + base + ATMEL_TC_REG(i, CCR));
> + }
> + }
> + return 0;
> +}
> +#endif
> +
> +static SIMPLE_DEV_PM_OPS(atmel_tcb_pwm_pm_ops, atmel_tcb_pwm_suspend,
> +  atmel_tcb_pwm_resume);
> +
>  static struct platform_driver atmel_tcb_pwm_driver = {
>   .driver = {
>   .name = "atmel-tcb-pwm",
>   .of_match_table = atmel_tcb_pwm_dt_ids,
> + .pm = &atmel_tcb_pwm_pm_ops,
>   },
>   .probe = atmel_tcb_pwm_probe,
>   .remove = atmel_tcb_pwm_remove,
> 


-- 
Nicolas Ferre
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


usb/media/zr364xx: GPF in zr364xx_vidioc_querycap/strlcpy

2017-09-22 Thread Andrey Konovalov
Hi!

I've got the following report while fuzzing the kernel with syzkaller.

On commit ebb2c2437d8008d46796902ff390653822af6cc4 (Sep 18).

usb 1-1: new full-speed USB device number 2 using dummy_hcd
gadgetfs: connected
gadgetfs: disconnected
gadgetfs: connected
usb 1-1: config 225 has an invalid interface number: 1 but max is 0
usb 1-1: config 225 has no interface number 0
usb 1-1: config 225 interface 1 altsetting 0 endpoint 0x5 has invalid
maxpacket 2047, setting to 64
usb 1-1: config 225 interface 1 altsetting 0 has an invalid endpoint
with address 0xF5, skipping
usb 1-1: config 225 interface 1 altsetting 0 endpoint 0x8A has invalid
maxpacket 2047, setting to 64
usb 1-1: config 225 interface 1 altsetting 0 endpoint 0x81 has an
invalid bInterval 0, changing to 10
usb 1-1: config 225 interface 1 altsetting 0 endpoint 0x81 has invalid
maxpacket 1025, setting to 64
usb 1-1: config 225 interface 1 altsetting 0 has an invalid endpoint
with address 0xF7, skipping
usb 1-1: config 225 interface 1 altsetting 0 has an invalid endpoint
with address 0xB8, skipping
usb 1-1: New USB device found, idVendor=041e, idProduct=4024
usb 1-1: New USB device strings: Mfr=0, Product=0, SerialNumber=1
usb 1-1: SerialNumber: a
gadgetfs: configuration #225
zr364xx 1-1:225.1: Zoran 364xx compatible webcam plugged
zr364xx 1-1:225.1: model 041e:4024 detected
usb 1-1: 320x240 mode selected
usb 1-1: Zoran 364xx controlling device video0
kasan: CONFIG_KASAN_INLINE enabled
kasan: GPF could be caused by NULL-ptr deref or user memory access
general protection fault:  [#1] PREEMPT SMP KASAN
Modules linked in:
CPU: 0 PID: 4306 Comm: v4l_id Not tainted 4.14.0-rc1-42261-ga67ef73a6f27 #225
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
task: 88006a27e300 task.stack: 880067f7
RIP: 0010:strlcpy+0x21/0x120 lib/string.c:140
RSP: 0018:880067f777a0 EFLAGS: 00010286
RAX: dc00 RBX: 880067f77c00 RCX: 
RDX: 0020 RSI:  RDI: 880067f77c10
RBP: 880067f777c8 R08: ed000cfeef82 R09: ed000cfeef82
R10: 0002 R11: ed000cfeef81 R12: 880067f77c10
R13: 880063034400 R14: 8000 R15: 880063193180
FS:  7f5561fe8700() GS:88006c80() knlGS:
CS:  0010 DS:  ES:  CR0: 80050033
CR2: 7f5561b16110 CR3: 6b00c000 CR4: 06f0
Call Trace:
 zr364xx_vidioc_querycap+0xb8/0x220 drivers/media/usb/zr364xx/zr364xx.c:709
 v4l_querycap+0x134/0x370 drivers/media/v4l2-core/v4l2-ioctl.c:1008
 __video_do_ioctl+0x9c6/0xa80 drivers/media/v4l2-core/v4l2-ioctl.c:2750
 video_usercopy+0x4ea/0x1580 drivers/media/v4l2-core/v4l2-ioctl.c:2926
 video_ioctl2+0x31/0x40 drivers/media/v4l2-core/v4l2-ioctl.c:2968
 v4l2_ioctl+0x1c5/0x310 drivers/media/v4l2-core/v4l2-dev.c:360
 vfs_ioctl fs/ioctl.c:45
 do_vfs_ioctl+0x1c4/0x15c0 fs/ioctl.c:685
 SYSC_ioctl fs/ioctl.c:700
 SyS_ioctl+0x94/0xc0 fs/ioctl.c:691
 entry_SYSCALL_64_fastpath+0x23/0xc2 arch/x86/entry/entry_64.S:202
RIP: 0033:0x7f5561b1b347
RSP: 002b:7ffd403d19a8 EFLAGS: 0202 ORIG_RAX: 0010
RAX: ffda RBX: 7ffd403d1b00 RCX: 7f5561b1b347
RDX: 7ffd403d19b0 RSI: 80685600 RDI: 0003
RBP: 00400884 R08:  R09: 
R10:  R11: 0202 R12: 0003
R13: 7ffd403d1b00 R14:  R15: 
Code: 8b 45 f0 e9 64 ff ff ff 66 90 48 b8 00 00 00 00 00 fc ff df 55
48 89 f1 48 89 e5 48 c1 e9 03 41 55 41 54 49 89 fc 53 48 83 ec 10 <0f>
b6 04 01 48 89 f1 83 e1 07 38 c8 7f 08 84 c0 0f 85 9d 00 00
RIP: strlcpy+0x21/0x120 RSP: 880067f777a0
---[ end trace 23c9876972269088 ]---
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 08/11] staging: typec: tcpm: Set mux to device mode when configured as such

2017-09-22 Thread Hans de Goede

Hi,

On 09/11/2017 12:56 AM, Guenter Roeck wrote:

On 09/05/2017 09:42 AM, Hans de Goede wrote:

Setting the mux to TYPEC_MUX_NONE, TCPC_USB_SWITCH_DISCONNECT when the
data-role is device is not correct. Plenty of devices support operating
as USB device through a (separate) USB device controller.

So this commit instead splits out TYPEC_MUX_USB into TYPEC_MUX_USB_HOST
and TYPEC_MUX_USB_DEVICE and makes tcpm_set_roles() set the mux
accordingly.

Likewise TCPC_MUX_DP gets renamed to TCPC_MUX_DP_SRC to make clear that
this is for configuring the Type-C port as a Display Port source, not a
sink.

Last this commit makes tcpm_reset_port() to set the mux to
TYPEC_MUX_NONE, TCPC_USB_SWITCH_DISCONNECT so that it does not and up
staying in host (and with this commit also device) mode after a detach.


This sentence is hard to understand.


Ok, changed to:

"Last this commit makes tcpm_reset_port() call tcpm_mux_set(port,
TYPEC_MUX_NONE, TCPC_USB_SWITCH_DISCONNECT) so that the mux does _not_
stay in its last mode after a detach."

For v3 of this patchset.




Signed-off-by: Hans de Goede 


Otherwise

Reviewed-by: Guenter Roeck 


And added your Reviewed-by.

Thanks & Regards,

Hans








---
  drivers/staging/typec/tcpm.c |  7 ---
  drivers/staging/typec/tcpm.h | 22 ++
  2 files changed, 18 insertions(+), 11 deletions(-)

diff --git a/drivers/staging/typec/tcpm.c b/drivers/staging/typec/tcpm.c
index 8af62e74d54c..ffe7e26d4ed3 100644
--- a/drivers/staging/typec/tcpm.c
+++ b/drivers/staging/typec/tcpm.c
@@ -752,11 +752,11 @@ static int tcpm_set_roles(struct tcpm_port *port, bool 
attached,
  int ret;
  if (data == TYPEC_HOST)
-    ret = tcpm_mux_set(port, TYPEC_MUX_USB,
+    ret = tcpm_mux_set(port, TYPEC_MUX_USB_HOST,
 TCPC_USB_SWITCH_CONNECT);
  else
-    ret = tcpm_mux_set(port, TYPEC_MUX_NONE,
-   TCPC_USB_SWITCH_DISCONNECT);
+    ret = tcpm_mux_set(port, TYPEC_MUX_USB_DEVICE,
+   TCPC_USB_SWITCH_CONNECT);
  if (ret < 0)
  return ret;
@@ -2025,6 +2025,7 @@ static void tcpm_reset_port(struct tcpm_port *port)
  tcpm_init_vconn(port);
  tcpm_set_current_limit(port, 0, 0);
  tcpm_set_polarity(port, TYPEC_POLARITY_CC1);
+    tcpm_mux_set(port, TYPEC_MUX_NONE, TCPC_USB_SWITCH_DISCONNECT);
  tcpm_set_attached_state(port, false);
  port->try_src_count = 0;
  port->try_snk_count = 0;
diff --git a/drivers/staging/typec/tcpm.h b/drivers/staging/typec/tcpm.h
index 7e9a6b7b5cd6..f662eed48c86 100644
--- a/drivers/staging/typec/tcpm.h
+++ b/drivers/staging/typec/tcpm.h
@@ -83,17 +83,23 @@ enum tcpc_usb_switch {
  };
  /* Mux state attributes */
-#define TCPC_MUX_USB_ENABLED    BIT(0)    /* USB enabled */
-#define TCPC_MUX_DP_ENABLED    BIT(1)    /* DP enabled */
-#define TCPC_MUX_POLARITY_INVERTED    BIT(2)    /* Polarity inverted */
+#define TCPC_MUX_USB_DEVICE_ENABLED    BIT(0)    /* USB device enabled */
+#define TCPC_MUX_USB_HOST_ENABLED    BIT(1)    /* USB host enabled */
+#define TCPC_MUX_DP_SRC_ENABLED    BIT(2)    /* DP enabled */
+#define TCPC_MUX_POLARITY_INVERTED    BIT(3)    /* Polarity inverted */
  /* Mux modes, decoded to attributes */
  enum tcpc_mux_mode {
-    TYPEC_MUX_NONE    = 0,    /* Open switch */
-    TYPEC_MUX_USB    = TCPC_MUX_USB_ENABLED,    /* USB only */
-    TYPEC_MUX_DP    = TCPC_MUX_DP_ENABLED,    /* DP only */
-    TYPEC_MUX_DOCK    = TCPC_MUX_USB_ENABLED |    /* Both USB and DP */
-  TCPC_MUX_DP_ENABLED,
+    /* Open switch */
+    TYPEC_MUX_NONE = 0,
+    /* USB device only */
+    TYPEC_MUX_USB_DEVICE = TCPC_MUX_USB_DEVICE_ENABLED,
+    /* USB host only */
+    TYPEC_MUX_USB_HOST = TCPC_MUX_USB_HOST_ENABLED,
+    /* DP source only */
+    TYPEC_MUX_DP = TCPC_MUX_DP_SRC_ENABLED,
+    /* Both USB host and DP source */
+    TYPEC_MUX_DOCK = TCPC_MUX_USB_HOST_ENABLED | TCPC_MUX_DP_SRC_ENABLED,
  };
  struct tcpc_mux_dev {




--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: usb/storage/uas: slab-out-of-bounds in uas_probe

2017-09-22 Thread Alan Stern
On Fri, 22 Sep 2017, Greg Kroah-Hartman wrote:

> On Fri, Sep 22, 2017 at 09:58:15AM +0200, Greg Kroah-Hartman wrote:
> > On Thu, Sep 21, 2017 at 03:04:05PM -0400, Alan Stern wrote:
> > > On Thu, 21 Sep 2017, Andrey Konovalov wrote:
> > > 
> > > > On Thu, Sep 21, 2017 at 6:10 PM, Greg Kroah-Hartman
> > > >  wrote:
> > > > > On Thu, Sep 21, 2017 at 05:39:05PM +0200, Andrey Konovalov wrote:
> > > > >> Hi!
> > > > >>
> > > > >> I've got the following report while fuzzing the kernel with 
> > > > >> syzkaller.
> > > > >>
> > > > >> On commit ebb2c2437d8008d46796902ff390653822af6cc4 (Sep 18).
> > > > >>
> > > > >> The issue occurs when we iterate over interface altsettings, but I
> > > > >> don't see the driver doing anything wrong. I might be missing
> > > > >> something, or this might be an issue in USB core altsettings parsing.
> > > > >
> > > > >
> > > > > Any chance you happen to have the descriptors that you were feeding 
> > > > > into
> > > > > the kernel at this crash?  That might help in figuring out what "went
> > > > > wrong".
> > > > 
> > > > Here's the data that I feed into dummy_udc:
> > > > 
> > > > 00 00 00 00 09 02 12 00 01 34 05 80 07 09 04 6e
> > > > 09 00 08 06 62 00 12 01 05 00 cb f7 71 83 04 00
> > > > 05 00 ab f6 07 81 08 01
> > > > 
> > > > Also attaching a C reproducer (requires dummy_hcd and gadgetfs) and my 
> > > > .config.
> > > 
> > > Why do your reproducers use an mmap'ed array for their data instead of 
> > > a plain old statically allocated array?
> > > 
> > > Anyway, this turns out to be a genuine (and subtle!) bug in the uas
> > > driver.  The uas_find_uas_alt_setting() routine in uas-detect.h returns
> > > a bAlternateSetting value, but then the uas_use_uas_driver() routine
> > > uses this value as an index to the altsetting array -- which it isn't.  
> > > 
> > > Normally this doesn't cause any problems because the the entries in the
> > > array have bAlternateSetting values 0, 1, etc., so the value is equal
> > > to the index.  But in your fuzzed case, that wasn't true.
> > > 
> > > The patch below fixes this bug, by returning a pointer to the 
> > > alt-setting entry instead of either the value or the index.  Pointers 
> > > are less subject to misinterpretation.
> > 
> > Ugh, messy, nice catch and fix, I'll go queue it up now, thanks for
> > resolving this.
> 
> Oops, no, you didn't send this as a "real" patch yet, I'll wait :)

I was waiting for Andrey to verify that the problem was really gone.  
I'll submit it officially later today.

On Fri, 22 Sep 2017, Felipe Balbi wrote:

> > Felipe, any objection for me taking this, and the other gadget driver
> > fixes that Alan just sent out, directly in my tree?
>
> none whatsoever, for all of them:

There's still more to come.  I've got four patches for dummy-hcd just 
about ready to send.  :-)

Alan Stern

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: ASM1153 detected as ASM1051 and breaking UAS

2017-09-22 Thread Massimo Burcheri
On Tue, 2017-09-19 at 10:00 +0200, Oliver Neukum wrote:

> > "In order to use UAS that must be enabled in the firmware as well. On that
> > device it is not enabled and the official product id wouldn't help there
> > either."
> > 
> > What does that mean? Did I purchase a UAS capable hardware with the wrong
> 
> Yes. That is what they told you. With a bit of sugar coating.
> 
> If they provide a tool for updating the firmware and updating the firmware
> is supported. Which may be the case or not. Only the vendor can tell you.

Heureka!
Before buying a new case with a UAS capable bridge I tried flashing some unknown
firmware.
I searched for "ASM1153 firmware" and found
http://www.station-drivers.com/index.php?option=com_remository&Itemid=353&func=fileinfo&id=2842&lang=en
I fired up some VirtualBox with extensions to be able to flash that USB3 device.
Flashing worked, however ReLink failed.

Now plugging to Linux I finally see holy land:
[kernel] scsi host9: uas
[kernel] usb 4-1: Product: USB3-SATA-UASP1

Opening with cryptsetup showed
[kernel] device-mapper: table: 254:4: adding target device sdf caused an 
alignment inconsistency: physical_block_size=4096, logical_block_size=512, 
alignment_offset=0, start=2097152

But reading works fine.

However the new descriptor of my device now looks like:

Bus 004 Device 007: ID 174c:55aa ASMedia Technology Inc. ASM1051E SATA 6Gb/s 
bridge, ASM1053E SATA 6Gb/s bridge, ASM1153 SATA 3Gb/s bridge
Device Descriptor:
  bLength18
  bDescriptorType 1
  bcdUSB   3.00
  bDeviceClass0 
  bDeviceSubClass 0 
  bDeviceProtocol 0 
  bMaxPacketSize0 9
  idVendor   0x174c ASMedia Technology Inc.
  idProduct  0x55aa ASM1051E SATA 6Gb/s bridge, ASM1053E SATA 6Gb/s 
bridge, ASM1153 SATA 3Gb/s bridge
  bcdDevice1.00
  iManufacturer   2 Plugable
  iProduct3 USB3-SATA-UASP1
  iSerial 1 123456789012
  bNumConfigurations  1
  Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength  121
bNumInterfaces  1
bConfigurationValue 1
iConfiguration  0 
bmAttributes 0xc0
  Self Powered
MaxPower0mA
Interface Descriptor:
  bLength 9
  bDescriptorType 4
  bInterfaceNumber0
  bAlternateSetting   0
  bNumEndpoints   2
  bInterfaceClass 8 Mass Storage
  bInterfaceSubClass  6 SCSI
  bInterfaceProtocol 80 Bulk-Only


I wondered the InterfaceClass is still "Mass Storage" but now the uas module has
taken over.

Best regards,
Massimo

signature.asc
Description: This is a digitally signed message part


Re: [PATCH 9/9 v2] usb: usb251xb: Use GPIO descriptor consumer interface

2017-09-22 Thread Serge Semin
On Thu, Sep 21, 2017 at 05:07:14PM +0200, Greg KH  
wrote:
> On Thu, Sep 21, 2017 at 05:51:29PM +0300, Serge Semin wrote:
> > On Thu, Sep 21, 2017 at 10:23:38AM +0200, Greg KH 
> >  wrote:
> > > On Sat, Sep 16, 2017 at 01:42:20PM +0300, Serge Semin wrote:
> > > > diff --git a/drivers/usb/misc/usb251xb.c b/drivers/usb/misc/usb251xb.c
> > > > index 71994b883..c2dd9742f 100644
> > > > --- a/drivers/usb/misc/usb251xb.c
> > > > +++ b/drivers/usb/misc/usb251xb.c
> > > > @@ -3,6 +3,7 @@
> > > >   * Configuration via SMBus.
> > > >   *
> > > >   * Copyright (c) 2017 SKIDATA AG
> > > > + * Copyright (c) 2017 T-platforms
> > > 
> > > Again, no, please consult with your corporate lawyers why this isn't ok.
> > > 
> > > greg k-h
> > 
> > I still can't see why this isn't right. We submitted the patchset. It is not
> > that big and still it isn't just two lines. As I've seen all over the 
> > kernel, It is
> > a common practice to have multiple copyrights in kernel files. We are not 
> > claiming
> > the copyright to the whole file, but to the contribution only. I got a 
> > consent to
> > contribute when I was employed by the company. What's wrong with that? 
> > Shall I
> > send the patchset from my corporate e-mail then?
> 
> Well, yes, I need some way to properly identify that this corporation
> did do the changes.  I said that before, I don't know why you ignored
> that.
> 
> And yes, multiple copyrights are just fine, but again, please talk to
> your corporate lawyer about why these changes don't seem to warrant that
> "mark".  If they do think that they do warrant that, great, I will be
> glad to discuss that with them, off-list if needed.
> 
> For even more fun, try discussing with your lawyers about why copyright
> marks like this don't even mean anything anymore, and haven't for 20+
> years now (can't remember the actual date...)  But that's a different
> topic, and one not really relevant here.
> 
> thanks,
> 
> greg k-h

Alright then. We'll remove the Copyright mark and I'll resend the patchset
from my corporate e-mail. Hope it will solve this issue.
Could you review the rest of the patchset?

Regards,
-Sergey

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] USB: uas: fix bug in handling of alternate settings

2017-09-22 Thread Alan Stern
The uas driver has a subtle bug in the way it handles alternate
settings.  The uas_find_uas_alt_setting() routine returns an
altsetting value (the bAlternateSetting number in the descriptor), but
uas_use_uas_driver() then treats that value as an index to the
intf->altsetting array, which it isn't.

Normally this doesn't cause any problems because the various
alternate settings have bAlternateSetting values 0, 1, 2, ..., so the
value is equal to the index in the array.  But this is not guaranteed,
and Andrey Konovalov used the syzkaller fuzzer with KASAN to get a
slab-out-of-bounds error by violating this assumption.

This patch fixes the bug by making uas_find_uas_alt_setting() return a
pointer to the altsetting entry rather than either the value or the
index.  Pointers are less subject to misinterpretation.

Signed-off-by: Alan Stern 
Reported-by: Andrey Konovalov 
Tested-by: Andrey Konovalov 
CC: Oliver Neukum 
CC: 

---


[as1845]


 drivers/usb/storage/uas-detect.h |   15 ---
 drivers/usb/storage/uas.c|   10 +-
 2 files changed, 13 insertions(+), 12 deletions(-)

Index: usb-4.x/drivers/usb/storage/uas-detect.h
===
--- usb-4.x.orig/drivers/usb/storage/uas-detect.h
+++ usb-4.x/drivers/usb/storage/uas-detect.h
@@ -9,7 +9,8 @@ static int uas_is_interface(struct usb_h
intf->desc.bInterfaceProtocol == USB_PR_UAS);
 }
 
-static int uas_find_uas_alt_setting(struct usb_interface *intf)
+static struct usb_host_interface *uas_find_uas_alt_setting(
+   struct usb_interface *intf)
 {
int i;
 
@@ -17,10 +18,10 @@ static int uas_find_uas_alt_setting(stru
struct usb_host_interface *alt = &intf->altsetting[i];
 
if (uas_is_interface(alt))
-   return alt->desc.bAlternateSetting;
+   return alt;
}
 
-   return -ENODEV;
+   return NULL;
 }
 
 static int uas_find_endpoints(struct usb_host_interface *alt,
@@ -58,14 +59,14 @@ static int uas_use_uas_driver(struct usb
struct usb_device *udev = interface_to_usbdev(intf);
struct usb_hcd *hcd = bus_to_hcd(udev->bus);
unsigned long flags = id->driver_info;
-   int r, alt;
-
+   struct usb_host_interface *alt;
+   int r;
 
alt = uas_find_uas_alt_setting(intf);
-   if (alt < 0)
+   if (!alt)
return 0;
 
-   r = uas_find_endpoints(&intf->altsetting[alt], eps);
+   r = uas_find_endpoints(alt, eps);
if (r < 0)
return 0;
 
Index: usb-4.x/drivers/usb/storage/uas.c
===
--- usb-4.x.orig/drivers/usb/storage/uas.c
+++ usb-4.x/drivers/usb/storage/uas.c
@@ -873,14 +873,14 @@ MODULE_DEVICE_TABLE(usb, uas_usb_ids);
 static int uas_switch_interface(struct usb_device *udev,
struct usb_interface *intf)
 {
-   int alt;
+   struct usb_host_interface *alt;
 
alt = uas_find_uas_alt_setting(intf);
-   if (alt < 0)
-   return alt;
+   if (!alt)
+   return -ENODEV;
 
-   return usb_set_interface(udev,
-   intf->altsetting[0].desc.bInterfaceNumber, alt);
+   return usb_set_interface(udev, alt->desc.bInterfaceNumber,
+   alt->desc.bAlternateSetting);
 }
 
 static int uas_configure_endpoints(struct uas_dev_info *devinfo)

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 9/9 v2] usb: usb251xb: Use GPIO descriptor consumer interface

2017-09-22 Thread Greg KH
On Fri, Sep 22, 2017 at 06:26:54PM +0300, Serge Semin wrote:
> On Thu, Sep 21, 2017 at 05:07:14PM +0200, Greg KH 
>  wrote:
> > On Thu, Sep 21, 2017 at 05:51:29PM +0300, Serge Semin wrote:
> > > On Thu, Sep 21, 2017 at 10:23:38AM +0200, Greg KH 
> > >  wrote:
> > > > On Sat, Sep 16, 2017 at 01:42:20PM +0300, Serge Semin wrote:
> > > > > diff --git a/drivers/usb/misc/usb251xb.c b/drivers/usb/misc/usb251xb.c
> > > > > index 71994b883..c2dd9742f 100644
> > > > > --- a/drivers/usb/misc/usb251xb.c
> > > > > +++ b/drivers/usb/misc/usb251xb.c
> > > > > @@ -3,6 +3,7 @@
> > > > >   * Configuration via SMBus.
> > > > >   *
> > > > >   * Copyright (c) 2017 SKIDATA AG
> > > > > + * Copyright (c) 2017 T-platforms
> > > > 
> > > > Again, no, please consult with your corporate lawyers why this isn't ok.
> > > > 
> > > > greg k-h
> > > 
> > > I still can't see why this isn't right. We submitted the patchset. It is 
> > > not
> > > that big and still it isn't just two lines. As I've seen all over the 
> > > kernel, It is
> > > a common practice to have multiple copyrights in kernel files. We are not 
> > > claiming
> > > the copyright to the whole file, but to the contribution only. I got a 
> > > consent to
> > > contribute when I was employed by the company. What's wrong with that? 
> > > Shall I
> > > send the patchset from my corporate e-mail then?
> > 
> > Well, yes, I need some way to properly identify that this corporation
> > did do the changes.  I said that before, I don't know why you ignored
> > that.
> > 
> > And yes, multiple copyrights are just fine, but again, please talk to
> > your corporate lawyer about why these changes don't seem to warrant that
> > "mark".  If they do think that they do warrant that, great, I will be
> > glad to discuss that with them, off-list if needed.
> > 
> > For even more fun, try discussing with your lawyers about why copyright
> > marks like this don't even mean anything anymore, and haven't for 20+
> > years now (can't remember the actual date...)  But that's a different
> > topic, and one not really relevant here.
> > 
> > thanks,
> > 
> > greg k-h
> 
> Alright then. We'll remove the Copyright mark and I'll resend the patchset
> from my corporate e-mail. Hope it will solve this issue.
> Could you review the rest of the patchset?

I'll wait for the resend, as Rob already pointed out issues, so it is
long-gone from my patchqueue.

thanks,

greg k-h
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Fibocom L831-EAU and cdc_mbim

2017-09-22 Thread Andreas Böhler
On 19/09/17 17:38, Bjørn Mork wrote:
> Andreas Böhler  writes:
> 
>> On 19/09/17 14:25, Bjørn Mork wrote:
>>> Bjørn Mork  writes:
>>>
>>> Maybe we should simply ignore stalls completely?  They should not happen
>>> with any real WDM device anyway.
>>>
>>> What happens if you e.g. change the if-test here:
>>>
>>> /*
>>>  * only set a new error if there is no previous error.
>>>  * Errors are only cleared during read/open
>>>  */
>>> if (desc->rerr  == 0)
>>> desc->rerr = status;
>>>
>>>
>>> to
>>>
>>> if (desc->rerr  == 0 && status != -EPIPE)
>>
>> Well, this looks very promising: Although the error messages persist
>> every now and then, the device now works!
>>
>> I'll make the new module the default and I'll test it more thouroughly
>> during the next few days.

As promised I made the new module the default and tested it for a few
days. Although the error messages persist, I did not notice any negative
side effects. In fact, it also fixes a problem where mbim-proxy was at
100% load.

Two other users also reported success [1], so I'm looking forward to
having it fixed in the default kernel tree. In the meantime, I'll keep
the module patched using DKMS.

Thanks again for your help,

Andreas

[1] https://bugs.freedesktop.org/show_bug.cgi?id=100938
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH][for 4.14] xhci: allow TRACE to work with EVENT ring dequeue

2017-09-22 Thread Adam Wallis
inc_deq() currently bails earlier for EVENT rings than the common return
point of the function, due to the fact that EVENT rings do not have
link TRBs. The unfortunate side effect of this is that the very useful
trace_xhci_inc_deq() function is not called/usable for EVENT ring
debug.

This patch provides a refactor by removing the multiple return exit
points into a single return which additionally allows for all rings to
use the trace function.

Signed-off-by: Adam Wallis 
---
 drivers/usb/host/xhci-ring.c | 33 -
 1 file changed, 16 insertions(+), 17 deletions(-)

diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index a944365..10afd50 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -171,25 +171,24 @@ static void inc_deq(struct xhci_hcd *xhci, struct 
xhci_ring *ring)
if (ring->type == TYPE_EVENT) {
if (!last_trb_on_seg(ring->deq_seg, ring->dequeue)) {
ring->dequeue++;
-   return;
+   } else {
+   if (last_trb_on_ring(ring, ring->deq_seg,
+   ring->dequeue))
+   ring->cycle_state ^= 1;
+   ring->deq_seg = ring->deq_seg->next;
+   ring->dequeue = ring->deq_seg->trbs;
+   }
+   } else {
+   /* All other rings have link trbs */
+   if (!trb_is_link(ring->dequeue)) {
+   ring->dequeue++;
+   ring->num_trbs_free++;
+   }
+   while (trb_is_link(ring->dequeue)) {
+   ring->deq_seg = ring->deq_seg->next;
+   ring->dequeue = ring->deq_seg->trbs;
}
-   if (last_trb_on_ring(ring, ring->deq_seg, ring->dequeue))
-   ring->cycle_state ^= 1;
-   ring->deq_seg = ring->deq_seg->next;
-   ring->dequeue = ring->deq_seg->trbs;
-   return;
-   }
-
-   /* All other rings have link trbs */
-   if (!trb_is_link(ring->dequeue)) {
-   ring->dequeue++;
-   ring->num_trbs_free++;
-   }
-   while (trb_is_link(ring->dequeue)) {
-   ring->deq_seg = ring->deq_seg->next;
-   ring->dequeue = ring->deq_seg->trbs;
}
-
trace_xhci_inc_deq(ring);
 
return;
-- 
Qualcomm Datacenter Technologies as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Fibocom L831-EAU and cdc_mbim

2017-09-22 Thread Bjørn Mork
Andreas Böhler  writes:

> As promised I made the new module the default and tested it for a few
> days. Although the error messages persist, I did not notice any negative
> side effects. In fact, it also fixes a problem where mbim-proxy was at
> 100% load.
>
> Two other users also reported success [1], so I'm looking forward to
> having it fixed in the default kernel tree. In the meantime, I'll keep
> the module patched using DKMS.

Sounds good.  Ideally we should also get it tested with lots of other
devices.  But the only way I know of to make that happen is by pushing
the patch into mainline and stable kernels. I'll do some minimal testing
myself for a while and then submit.

Thanks for your patience.  I know this issue has been around for way too
long already.



Bjørn
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3 14/14] platform/x86: intel_cht_int33fe: Add mux mappings for the Type-C port

2017-09-22 Thread Hans de Goede
We need to add mappings for the mux subsys to be able to find the
muxes for the fusb302 driver to be able to control the PI3USB30532
Type-C mux and the device/host mux integrated in the CHT SoC.

Signed-off-by: Hans de Goede 
Acked-by: Andy Shevchenko 
---
 drivers/platform/x86/Kconfig |  1 +
 drivers/platform/x86/intel_cht_int33fe.c | 23 +++
 2 files changed, 24 insertions(+)

diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 312d2472b8b3..830ff8d0a1eb 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -794,6 +794,7 @@ config ACPI_CMPC
 config INTEL_CHT_INT33FE
tristate "Intel Cherry Trail ACPI INT33FE Driver"
depends on X86 && ACPI && I2C && REGULATOR
+   select MULTIPLEXER
---help---
  This driver add support for the INT33FE ACPI device found on
  some Intel Cherry Trail devices.
diff --git a/drivers/platform/x86/intel_cht_int33fe.c 
b/drivers/platform/x86/intel_cht_int33fe.c
index b2925d996613..89ba510dac78 100644
--- a/drivers/platform/x86/intel_cht_int33fe.c
+++ b/drivers/platform/x86/intel_cht_int33fe.c
@@ -24,6 +24,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -35,6 +36,19 @@ struct cht_int33fe_data {
struct i2c_client *pi3usb30532;
 };
 
+static struct mux_lookup cht_int33fe_mux_lookup[] = {
+   {
+   .provider = "i2c-pi3usb30532",
+   .dev_id   = "i2c-fusb302",
+   .mux_name = "type-c-mode-mux",
+   },
+   {
+   .provider = "intel_cht_usb_mux",
+   .dev_id   = "i2c-fusb302",
+   .mux_name = "usb-role-mux",
+   },
+};
+
 /*
  * Grrr I severly dislike buggy BIOS-es. At least one BIOS enumerates
  * the max17047 both through the INT33FE ACPI device (it is right there
@@ -177,6 +191,9 @@ static int cht_int33fe_probe(struct i2c_client *client)
board_info.properties = fusb302_props;
board_info.irq = fusb302_irq;
 
+   mux_add_table(cht_int33fe_mux_lookup,
+ ARRAY_SIZE(cht_int33fe_mux_lookup));
+
data->fusb302 = i2c_acpi_new_device(dev, 2, &board_info);
if (!data->fusb302)
goto out_unregister_max17047;
@@ -200,6 +217,9 @@ static int cht_int33fe_probe(struct i2c_client *client)
if (data->max17047)
i2c_unregister_device(data->max17047);
 
+   mux_remove_table(cht_int33fe_mux_lookup,
+ ARRAY_SIZE(cht_int33fe_mux_lookup));
+
return -EPROBE_DEFER; /* Wait for the i2c-adapter to load */
 }
 
@@ -212,6 +232,9 @@ static int cht_int33fe_remove(struct i2c_client *i2c)
if (data->max17047)
i2c_unregister_device(data->max17047);
 
+   mux_remove_table(cht_int33fe_mux_lookup,
+ ARRAY_SIZE(cht_int33fe_mux_lookup));
+
return 0;
 }
 
-- 
2.14.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3 13/14] staging: typec: fusb302: Hook up mux support using tcpc_gen_mux support

2017-09-22 Thread Hans de Goede
Add mux support to the fusb302 driver, call devm_tcpc_gen_mux_create()
to let the generic tcpc_mux_dev code create a tcpc_mux_dev for us.

Also document the mux-names used by the generic tcpc_mux_dev code in
our devicetree bindings.

Cc: Rob Herring 
Cc: Mark Rutland 
Cc: devicet...@vger.kernel.org
Signed-off-by: Hans de Goede 
---
Changes in v3:
-Drop devicetree bindings documentation, since this is only used with
 device-properties set by platform code on X86/ACPI now, we don't need
 bindings yet
---
 drivers/usb/typec/fusb302/fusb302.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/typec/fusb302/fusb302.c 
b/drivers/usb/typec/fusb302/fusb302.c
index e790b67d4953..10415d6b2292 100644
--- a/drivers/usb/typec/fusb302/fusb302.c
+++ b/drivers/usb/typec/fusb302/fusb302.c
@@ -1259,7 +1259,6 @@ static void init_tcpc_dev(struct tcpc_dev 
*fusb302_tcpc_dev)
fusb302_tcpc_dev->set_roles = tcpm_set_roles;
fusb302_tcpc_dev->start_drp_toggling = tcpm_start_drp_toggling;
fusb302_tcpc_dev->pd_transmit = tcpm_pd_transmit;
-   fusb302_tcpc_dev->mux = NULL;
 }
 
 static const char * const cc_polarity_name[] = {
@@ -1817,6 +1816,10 @@ static int fusb302_probe(struct i2c_client *client,
return -EPROBE_DEFER;
}
 
+   chip->tcpc_dev.mux = devm_tcpc_gen_mux_create(dev);
+   if (IS_ERR(chip->tcpc_dev.mux))
+   return PTR_ERR(chip->tcpc_dev.mux);
+
cfg.drv_data = chip;
chip->psy = devm_power_supply_register(dev, &fusb302_psy_desc, &cfg);
if (IS_ERR(chip->psy)) {
-- 
2.14.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3 12/14] staging: typec: Add Generic TCPC mux driver using the mux subsys

2017-09-22 Thread Hans de Goede
So far the mux functionality of the tcpm code has not been hooked up
in any tcpc drivers. This commit adds a generic TCPC mux driver using
the mux subsys, which tcpc drivers can use to provide mux functionality
in cases where an external my is used.

Signed-off-by: Hans de Goede 
---
Changes in v3:
-Use new devm_mux_control_get_optional()
-Simplify tcpc_gen_mux_set as we now no longer need to worry about the muxes
 being present
-Adjust for updated MUX_TYPEC_* defines
---
 drivers/usb/typec/Makefile   |   2 +-
 drivers/usb/typec/tcpc_gen_mux.c | 122 +++
 include/linux/usb/tcpm.h |   2 +
 3 files changed, 125 insertions(+), 1 deletion(-)
 create mode 100644 drivers/usb/typec/tcpc_gen_mux.c

diff --git a/drivers/usb/typec/Makefile b/drivers/usb/typec/Makefile
index b77688ce1f16..95a7d9c4527b 100644
--- a/drivers/usb/typec/Makefile
+++ b/drivers/usb/typec/Makefile
@@ -1,5 +1,5 @@
 obj-$(CONFIG_TYPEC)+= typec.o
-obj-$(CONFIG_TYPEC_TCPM)   += tcpm.o
+obj-$(CONFIG_TYPEC_TCPM)   += tcpm.o tcpc_gen_mux.o
 obj-y  += fusb302/
 obj-$(CONFIG_TYPEC_WCOVE)  += typec_wcove.o
 obj-$(CONFIG_TYPEC_UCSI)   += ucsi/
diff --git a/drivers/usb/typec/tcpc_gen_mux.c b/drivers/usb/typec/tcpc_gen_mux.c
new file mode 100644
index ..ea40b52ef6a6
--- /dev/null
+++ b/drivers/usb/typec/tcpc_gen_mux.c
@@ -0,0 +1,122 @@
+/*
+ * Generic TCPC mux driver using the mux subsys
+ *
+ * Copyright (c) 2017 Hans de Goede 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation, or (at your option)
+ * any later version.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct tcpc_gen_mux_data {
+   struct tcpc_mux_dev mux;
+   struct device *dev;
+   struct mux_control *type_c_mode_mux; /* Type-C cross switch / mux */
+   struct mux_control *usb_role_mux;/* USB Device / Host mode mux */
+   bool muxes_set;
+};
+
+static int tcpc_gen_mux_set(struct tcpc_mux_dev *mux_dev,
+   enum tcpc_mux_mode mux_mode,
+   enum tcpc_usb_switch usb_config,
+   enum typec_cc_polarity polarity)
+{
+   struct tcpc_gen_mux_data *data =
+   container_of(mux_dev, struct tcpc_gen_mux_data, mux);
+   unsigned int typec_state = MUX_TYPEC_USB;
+   unsigned int usb_state = MUX_USB_DEVICE;
+   int ret;
+
+   /* Put the muxes back in their open (idle) state */
+   if (data->muxes_set) {
+   mux_control_deselect(data->type_c_mode_mux);
+   mux_control_deselect(data->usb_role_mux);
+   data->muxes_set = false;
+   }
+
+   switch (mux_mode) {
+   case TYPEC_MUX_NONE:
+   /* Muxes are in their open state, done. */
+   return 0;
+   case TYPEC_MUX_USB_DEVICE:
+   typec_state = MUX_TYPEC_USB;
+   usb_state = MUX_USB_DEVICE;
+   break;
+   case TYPEC_MUX_USB_HOST:
+   typec_state = MUX_TYPEC_USB;
+   usb_state = MUX_USB_HOST;
+   break;
+   case TYPEC_MUX_DP:
+   typec_state = MUX_TYPEC_DP;
+   break;
+   case TYPEC_MUX_DOCK:
+   typec_state = MUX_TYPEC_USB_AND_DP;
+   usb_state = MUX_USB_HOST;
+   break;
+   }
+
+   if (polarity)
+   typec_state |= MUX_TYPEC_POLARITY_INV;
+
+   ret = mux_control_select(data->type_c_mode_mux, typec_state);
+   if (ret) {
+   dev_err(data->dev, "Error setting Type-C mode mux: %d\n", ret);
+   return ret;
+   }
+
+   ret = mux_control_select(data->usb_role_mux, usb_state);
+   if (ret) {
+   dev_err(data->dev, "Error setting USB role mux: %d\n", ret);
+   mux_control_deselect(data->type_c_mode_mux);
+   return ret;
+   }
+
+   data->muxes_set = true;
+   return 0;
+}
+
+struct tcpc_mux_dev *devm_tcpc_gen_mux_create(struct device *dev)
+{
+   struct tcpc_gen_mux_data *data;
+   int ret;
+
+   data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+   if (!data)
+   return ERR_PTR(-ENOMEM);
+
+   /* The use of either mux is optional */
+   data->type_c_mode_mux =
+   devm_mux_control_get_optional(dev, "type-c-mode-mux");
+   if (IS_ERR(data->type_c_mode_mux)) {
+   ret = PTR_ERR(data->type_c_mode_mux);
+   if (ret != -EPROBE_DEFER)
+   dev_err(dev, "Error getting Type-C mux: %d\n", ret);
+   return ERR_PTR(-ret);
+   }
+
+   data->usb_role_mux = devm_mux_control_get_optional(dev, "usb-role-mux");
+   if (IS_ERR(data->usb_role_mux)) {
+   ret = PTR_ERR(data->usb_role_mux);
+   if (ret != -EPR

[PATCH v3 11/14] staging: typec: tcpm: Set mux to device mode when configured as such

2017-09-22 Thread Hans de Goede
Setting the mux to TYPEC_MUX_NONE, TCPC_USB_SWITCH_DISCONNECT when the
data-role is device is not correct. Plenty of devices support operating
as USB device through a (separate) USB device controller.

So this commit instead splits out TYPEC_MUX_USB into TYPEC_MUX_USB_HOST
and TYPEC_MUX_USB_DEVICE and makes tcpm_set_roles() set the mux
accordingly.

Likewise TCPC_MUX_DP gets renamed to TCPC_MUX_DP_SRC to make clear that
this is for configuring the Type-C port as a Display Port source, not a
sink.

Last this commit makes tcpm_reset_port() call tcpm_mux_set(port,
TYPEC_MUX_NONE, TCPC_USB_SWITCH_DISCONNECT) so that the mux does _not_
stay in its last mode after a detach.

Signed-off-by: Hans de Goede 
Reviewed-by: Guenter Roeck 
---
Changes in v3:
-Improve / reword last paragraph of the commit message
-Add Guenter's Reviewed-by
---
 drivers/usb/typec/tcpm.c |  7 ---
 include/linux/usb/tcpm.h | 22 ++
 2 files changed, 18 insertions(+), 11 deletions(-)

diff --git a/drivers/usb/typec/tcpm.c b/drivers/usb/typec/tcpm.c
index f557c479fdc2..e104c218cb4a 100644
--- a/drivers/usb/typec/tcpm.c
+++ b/drivers/usb/typec/tcpm.c
@@ -751,11 +751,11 @@ static int tcpm_set_roles(struct tcpm_port *port, bool 
attached,
int ret;
 
if (data == TYPEC_HOST)
-   ret = tcpm_mux_set(port, TYPEC_MUX_USB,
+   ret = tcpm_mux_set(port, TYPEC_MUX_USB_HOST,
   TCPC_USB_SWITCH_CONNECT);
else
-   ret = tcpm_mux_set(port, TYPEC_MUX_NONE,
-  TCPC_USB_SWITCH_DISCONNECT);
+   ret = tcpm_mux_set(port, TYPEC_MUX_USB_DEVICE,
+  TCPC_USB_SWITCH_CONNECT);
if (ret < 0)
return ret;
 
@@ -1995,6 +1995,7 @@ static void tcpm_reset_port(struct tcpm_port *port)
tcpm_init_vconn(port);
tcpm_set_current_limit(port, 0, 0);
tcpm_set_polarity(port, TYPEC_POLARITY_CC1);
+   tcpm_mux_set(port, TYPEC_MUX_NONE, TCPC_USB_SWITCH_DISCONNECT);
tcpm_set_attached_state(port, false);
port->try_src_count = 0;
port->try_snk_count = 0;
diff --git a/include/linux/usb/tcpm.h b/include/linux/usb/tcpm.h
index 073197f0d2bb..bc76389ee257 100644
--- a/include/linux/usb/tcpm.h
+++ b/include/linux/usb/tcpm.h
@@ -103,17 +103,23 @@ enum tcpc_usb_switch {
 };
 
 /* Mux state attributes */
-#define TCPC_MUX_USB_ENABLED   BIT(0)  /* USB enabled */
-#define TCPC_MUX_DP_ENABLEDBIT(1)  /* DP enabled */
-#define TCPC_MUX_POLARITY_INVERTED BIT(2)  /* Polarity inverted */
+#define TCPC_MUX_USB_DEVICE_ENABLEDBIT(0)  /* USB device enabled */
+#define TCPC_MUX_USB_HOST_ENABLED  BIT(1)  /* USB host enabled */
+#define TCPC_MUX_DP_SRC_ENABLEDBIT(2)  /* DP enabled */
+#define TCPC_MUX_POLARITY_INVERTED BIT(3)  /* Polarity inverted */
 
 /* Mux modes, decoded to attributes */
 enum tcpc_mux_mode {
-   TYPEC_MUX_NONE  = 0,/* Open switch */
-   TYPEC_MUX_USB   = TCPC_MUX_USB_ENABLED, /* USB only */
-   TYPEC_MUX_DP= TCPC_MUX_DP_ENABLED,  /* DP only */
-   TYPEC_MUX_DOCK  = TCPC_MUX_USB_ENABLED |/* Both USB and DP */
- TCPC_MUX_DP_ENABLED,
+   /* Open switch */
+   TYPEC_MUX_NONE = 0,
+   /* USB device only */
+   TYPEC_MUX_USB_DEVICE = TCPC_MUX_USB_DEVICE_ENABLED,
+   /* USB host only */
+   TYPEC_MUX_USB_HOST = TCPC_MUX_USB_HOST_ENABLED,
+   /* DP source only */
+   TYPEC_MUX_DP = TCPC_MUX_DP_SRC_ENABLED,
+   /* Both USB host and DP source */
+   TYPEC_MUX_DOCK = TCPC_MUX_USB_HOST_ENABLED | TCPC_MUX_DP_SRC_ENABLED,
 };
 
 struct tcpc_mux_dev {
-- 
2.14.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3 10/14] extcon: intel-int3496: Add support for controlling the USB-role mux

2017-09-22 Thread Hans de Goede
Cherry Trail SoCs have a built-in USB-role mux for switching between
the host and device controllers, rather then using an external mux
controller by a GPIO.

There is a driver using the mux-subsys to control this mux, this
commit adds support to the intel-int3496 driver to get a mux_controller
handle for the mux and set the mux through the mux-subsys rather then
through a GPIO.

Signed-off-by: Hans de Goede 
---
Changes in v2:
-Drop || COMPILE_TEST from Kconfig depends on, as we will now fail to
 compile on !X86
-Minor code style tweaks
---
 drivers/extcon/Kconfig|  3 +-
 drivers/extcon/extcon-intel-int3496.c | 59 +++
 2 files changed, 61 insertions(+), 1 deletion(-)

diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig
index a7bca4207f44..168f9d710ea0 100644
--- a/drivers/extcon/Kconfig
+++ b/drivers/extcon/Kconfig
@@ -44,7 +44,8 @@ config EXTCON_GPIO
 
 config EXTCON_INTEL_INT3496
tristate "Intel INT3496 ACPI device extcon driver"
-   depends on GPIOLIB && ACPI && (X86 || COMPILE_TEST)
+   depends on GPIOLIB && ACPI && X86
+   select MULTIPLEXER
help
  Say Y here to enable extcon support for USB OTG ports controlled by
  an Intel INT3496 ACPI device.
diff --git a/drivers/extcon/extcon-intel-int3496.c 
b/drivers/extcon/extcon-intel-int3496.c
index 1a45e745717d..3c8e17449c12 100644
--- a/drivers/extcon/extcon-intel-int3496.c
+++ b/drivers/extcon/extcon-intel-int3496.c
@@ -23,8 +23,13 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 
+#include 
+#include 
+
 #define INT3496_GPIO_USB_ID0
 #define INT3496_GPIO_VBUS_EN   1
 #define INT3496_GPIO_USB_MUX   2
@@ -37,6 +42,8 @@ struct int3496_data {
struct gpio_desc *gpio_usb_id;
struct gpio_desc *gpio_vbus_en;
struct gpio_desc *gpio_usb_mux;
+   struct mux_control *usb_mux;
+   bool usb_mux_set;
int usb_id_irq;
 };
 
@@ -56,11 +63,32 @@ static const struct acpi_gpio_mapping 
acpi_int3496_default_gpios[] = {
{ },
 };
 
+static struct mux_lookup acpi_int3496_cht_mux_lookup[] = {
+   {
+   .provider = "intel_cht_usb_mux",
+   .dev_id   = "INT3496:00",
+   .mux_name = "usb-role-mux",
+   },
+};
+
+#define ICPU(model){ X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, }
+
+static const struct x86_cpu_id cht_cpu_ids[] = {
+   ICPU(INTEL_FAM6_ATOM_AIRMONT),  /* Braswell, Cherry Trail */
+   {}
+};
+
+static bool int3496_soc_has_mux(void)
+{
+   return x86_match_cpu(cht_cpu_ids);
+}
+
 static void int3496_do_usb_id(struct work_struct *work)
 {
struct int3496_data *data =
container_of(work, struct int3496_data, work.work);
int id = gpiod_get_value_cansleep(data->gpio_usb_id);
+   int ret;
 
/* id == 1: PERIPHERAL, id == 0: HOST */
dev_dbg(data->dev, "Connected %s cable\n", id ? "PERIPHERAL" : "HOST");
@@ -72,6 +100,22 @@ static void int3496_do_usb_id(struct work_struct *work)
if (!IS_ERR(data->gpio_usb_mux))
gpiod_direction_output(data->gpio_usb_mux, id);
 
+   if (data->usb_mux) {
+   /*
+* The mux framework expects multiple competing users, we must
+* release our previous setting before applying the new one.
+*/
+   if (data->usb_mux_set)
+   mux_control_deselect(data->usb_mux);
+
+   ret = mux_control_select(data->usb_mux,
+id ? MUX_USB_DEVICE : MUX_USB_HOST);
+   if (ret)
+   dev_err(data->dev, "Error setting mux: %d\n", ret);
+
+   data->usb_mux_set = ret == 0;
+   }
+
if (!IS_ERR(data->gpio_vbus_en))
gpiod_direction_output(data->gpio_vbus_en, !id);
 
@@ -107,6 +151,21 @@ static int int3496_probe(struct platform_device *pdev)
data->dev = dev;
INIT_DELAYED_WORK(&data->work, int3496_do_usb_id);
 
+   if (int3496_soc_has_mux()) {
+   mux_add_table(acpi_int3496_cht_mux_lookup,
+ ARRAY_SIZE(acpi_int3496_cht_mux_lookup));
+   data->usb_mux = devm_mux_control_get(dev, "usb-role-mux");
+   /* Doing this here keeps our error handling clean. */
+   mux_remove_table(acpi_int3496_cht_mux_lookup,
+ARRAY_SIZE(acpi_int3496_cht_mux_lookup));
+   if (IS_ERR(data->usb_mux)) {
+   ret = PTR_ERR(data->usb_mux);
+   if (ret != -EPROBE_DEFER)
+   dev_err(dev, "can't get mux: %d\n", ret);
+   return ret;
+   }
+   }
+
data->gpio_usb_id = devm_gpiod_get(dev, "id", GPIOD_IN);
if (IS_ERR(data->gpio_usb_id)) {
ret = PTR_ERR(data->gpio_usb_id);
-- 
2.14.1

--
To unsubscribe from this list: send the li

[PATCH v3 09/14] mux: Add Pericom PI3USB30532 Type-C mux driver

2017-09-22 Thread Hans de Goede
Add a driver for the Pericom PI3USB30532 Type-C cross switch /
mux chip found on some devices with a Type-C port.

Signed-off-by: Hans de Goede 
---
Changes in v2:
-Adjust for new MUX_TYPEC_foo state defines
-Add MAINTAINERS entry
-Various code-style fixes

Changes in v3:
-Use new init_as_is mux flag
-Adjust for updated MUX_TYPEC_* defines
---
 MAINTAINERS   |  5 +++
 drivers/mux/Kconfig   | 10 ++
 drivers/mux/Makefile  |  2 ++
 drivers/mux/pi3usb30532.c | 92 +++
 4 files changed, 109 insertions(+)
 create mode 100644 drivers/mux/pi3usb30532.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 6cfa0e5f2d2b..5c844fd3a23c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9181,6 +9181,11 @@ M:   Hans de Goede 
 S: Maintained
 F: drivers/mux/intel-cht-usb-mux.c
 
+MULTIPLEXER SUBSYSTEM PI3USB30532 DRIVER
+M: Hans de Goede 
+S: Maintained
+F: drivers/mux/pi3usb30532.c
+
 MULTISOUND SOUND DRIVER
 M: Andrew Veliath 
 S: Maintained
diff --git a/drivers/mux/Kconfig b/drivers/mux/Kconfig
index ebc04ae7ff30..f94660229d20 100644
--- a/drivers/mux/Kconfig
+++ b/drivers/mux/Kconfig
@@ -58,4 +58,14 @@ config MUX_MMIO
  To compile the driver as a module, choose M here: the module will
  be called mux-mmio.
 
+config MUX_PI3USB30532
+   tristate "Pericom PI3USB30532 Type-C cross switch driver"
+   depends on I2C
+   help
+ This driver adds support for the Pericom PI3USB30532 Type-C cross
+ switch / mux chip found on some devices with a Type-C port.
+
+ To compile the driver as a module, choose M here: the module will
+ be called mux-pi3usb30532.
+
 endmenu
diff --git a/drivers/mux/Makefile b/drivers/mux/Makefile
index 6cf41be2754f..df381c219708 100644
--- a/drivers/mux/Makefile
+++ b/drivers/mux/Makefile
@@ -7,9 +7,11 @@ mux-adg792a-objs   := adg792a.o
 mux-gpio-objs  := gpio.o
 mux-intel-cht-usb-mux-objs := intel-cht-usb-mux.o
 mux-mmio-objs  := mmio.o
+mux-pi3usb30532-objs   := pi3usb30532.o
 
 obj-$(CONFIG_MULTIPLEXER)  += mux-core.o
 obj-$(CONFIG_MUX_ADG792A)  += mux-adg792a.o
 obj-$(CONFIG_MUX_GPIO) += mux-gpio.o
 obj-$(CONFIG_MUX_INTEL_CHT_USB_MUX)+= mux-intel-cht-usb-mux.o
 obj-$(CONFIG_MUX_MMIO) += mux-mmio.o
+obj-$(CONFIG_MUX_PI3USB30532)  += mux-pi3usb30532.o
diff --git a/drivers/mux/pi3usb30532.c b/drivers/mux/pi3usb30532.c
new file mode 100644
index ..13c7c4ec0047
--- /dev/null
+++ b/drivers/mux/pi3usb30532.c
@@ -0,0 +1,92 @@
+/*
+ * Pericom PI3USB30532 Type-C cross switch / mux driver
+ *
+ * Copyright (c) 2017 Hans de Goede 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation, or (at your option)
+ * any later version.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define PI3USB30532_CONF   0x00
+
+#define PI3USB30532_CONF_OPEN  0x00
+#define PI3USB30532_CONF_SWAP  0x01
+#define PI3USB30532_CONF_4LANE_DP  0x02
+#define PI3USB30532_CONF_USB3  0x04
+#define PI3USB30532_CONF_USB3_AND_2LANE_DP 0x06
+
+static int pi3usb30532_set_mux(struct mux_control *mux, int state)
+{
+   struct i2c_client *i2c = to_i2c_client(mux->chip->dev.parent);
+   u8 conf = PI3USB30532_CONF_OPEN;
+
+   if (state == MUX_IDLE_DISCONNECT)
+   return i2c_smbus_write_byte_data(i2c, PI3USB30532_CONF, conf);
+
+   switch (state & ~MUX_TYPEC_POLARITY_INV) {
+   case MUX_TYPEC_USB:
+   conf = PI3USB30532_CONF_USB3;
+   break;
+   case MUX_TYPEC_USB_AND_DP:
+   conf = PI3USB30532_CONF_USB3_AND_2LANE_DP;
+   break;
+   case MUX_TYPEC_DP:
+   conf = PI3USB30532_CONF_4LANE_DP;
+   break;
+   }
+
+   if (state & MUX_TYPEC_POLARITY_INV)
+   conf |= PI3USB30532_CONF_SWAP;
+
+   return i2c_smbus_write_byte_data(i2c, PI3USB30532_CONF, conf);
+}
+
+static const struct mux_control_ops pi3usb30532_ops = {
+   .set = pi3usb30532_set_mux,
+};
+
+static int pi3usb30532_probe(struct i2c_client *client)
+{
+   struct device *dev = &client->dev;
+   struct mux_chip *mux_chip;
+
+   mux_chip = devm_mux_chip_alloc(dev, 1, 0);
+   if (IS_ERR(mux_chip))
+   return PTR_ERR(mux_chip);
+
+   mux_chip->ops = &pi3usb30532_ops;
+   mux_chip->mux[0].idle_state = MUX_IDLE_DISCONNECT;
+   /* Keep initial state as is, for e.g. booting from an USB disk */
+   mux_chip->mux[0].init_as_is = true;
+   mux_chip->mux[0].states = MUX_TYPEC_STATES;
+
+   return devm_mux_chip_register(dev, mux_chip);
+}
+
+static const struct i2c_device_id pi3usb30532_table[] = {
+   { "pi

[PATCH v3 08/14] mux: Add Intel Cherrytrail USB mux driver

2017-09-22 Thread Hans de Goede
Intel Cherrytrail SoCs have an internal USB mux for muxing the otg-port
USB data lines between the xHCI host controller and the dwc3 gadget
controller. On some Cherrytrail systems this mux is controlled through
AML code reacting on a GPIO IRQ connected to the USB OTG id pin (through
an _AIE ACPI method) so things just work.

But on other Cherrytrail systems we need to control the mux ourselves
this driver exports the mux through the mux subsys, so that other drivers
can control it if necessary.

This driver also updates the vbus-valid reporting to the dwc3 gadget
controller, as this uses the same registers as the mux. This is needed
for gadget/device mode to work properly (even on systems which control
the mux from their AML code).

Note this depends on the xhci driver registering a platform device
named "intel_cht_usb_mux", which has an IOMEM resource 0 which points
to the Intel Vendor Defined XHCI extended capabilities region.

Signed-off-by: Hans de Goede 
---
Changes in v2:
-Complete rewrite as a stand-alone platform-driver rather then as a phy
 driver, since this is just a mux, not a phy

Changes in v3:
-Make this a mux subsys driver instead of listening to USB_HOST extcon
 cable events and responding to those

Changes in v4 (of patch, v2 of new mux based series):
-Rename C-file to use - in name
-Add MAINTAINERS entry
-Various code-style fixes

Changes in v3 of new mux based series:
-Various code-style fixes
-Use new init_as_is mux flag
---
 MAINTAINERS |   5 +
 drivers/mux/Kconfig |  11 ++
 drivers/mux/Makefile|  10 +-
 drivers/mux/intel-cht-usb-mux.c | 251 
 4 files changed, 273 insertions(+), 4 deletions(-)
 create mode 100644 drivers/mux/intel-cht-usb-mux.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 04e7a5b9d6bd..6cfa0e5f2d2b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9176,6 +9176,11 @@ F:   include/linux/dt-bindings/mux/
 F: include/linux/mux/
 F: drivers/mux/
 
+MULTIPLEXER SUBSYSTEM INTEL CHT USB MUX DRIVER
+M: Hans de Goede 
+S: Maintained
+F: drivers/mux/intel-cht-usb-mux.c
+
 MULTISOUND SOUND DRIVER
 M: Andrew Veliath 
 S: Maintained
diff --git a/drivers/mux/Kconfig b/drivers/mux/Kconfig
index 19e4e904c9bf..ebc04ae7ff30 100644
--- a/drivers/mux/Kconfig
+++ b/drivers/mux/Kconfig
@@ -34,6 +34,17 @@ config MUX_GPIO
  To compile the driver as a module, choose M here: the module will
  be called mux-gpio.
 
+config MUX_INTEL_CHT_USB_MUX
+   tristate "Intel Cherrytrail USB Multiplexer"
+   depends on ACPI && X86 && EXTCON
+   help
+ This driver adds support for the internal USB mux for muxing the OTG
+ USB data lines between the xHCI host controller and the dwc3 gadget
+ controller found on Intel Cherrytrail SoCs.
+
+ To compile the driver as a module, choose M here: the module will
+ be called mux-intel-cht-usb-mux.
+
 config MUX_MMIO
tristate "MMIO register bitfield-controlled Multiplexer"
depends on (OF && MFD_SYSCON) || COMPILE_TEST
diff --git a/drivers/mux/Makefile b/drivers/mux/Makefile
index 0e1e59760e3f..6cf41be2754f 100644
--- a/drivers/mux/Makefile
+++ b/drivers/mux/Makefile
@@ -5,9 +5,11 @@
 mux-core-objs  := core.o
 mux-adg792a-objs   := adg792a.o
 mux-gpio-objs  := gpio.o
+mux-intel-cht-usb-mux-objs := intel-cht-usb-mux.o
 mux-mmio-objs  := mmio.o
 
-obj-$(CONFIG_MULTIPLEXER)  += mux-core.o
-obj-$(CONFIG_MUX_ADG792A)  += mux-adg792a.o
-obj-$(CONFIG_MUX_GPIO) += mux-gpio.o
-obj-$(CONFIG_MUX_MMIO) += mux-mmio.o
+obj-$(CONFIG_MULTIPLEXER)  += mux-core.o
+obj-$(CONFIG_MUX_ADG792A)  += mux-adg792a.o
+obj-$(CONFIG_MUX_GPIO) += mux-gpio.o
+obj-$(CONFIG_MUX_INTEL_CHT_USB_MUX)+= mux-intel-cht-usb-mux.o
+obj-$(CONFIG_MUX_MMIO) += mux-mmio.o
diff --git a/drivers/mux/intel-cht-usb-mux.c b/drivers/mux/intel-cht-usb-mux.c
new file mode 100644
index ..726facefd479
--- /dev/null
+++ b/drivers/mux/intel-cht-usb-mux.c
@@ -0,0 +1,251 @@
+/*
+ * Intel Cherrytrail USB OTG MUX driver
+ *
+ * Copyright (c) 2016-2017 Hans de Goede 
+ *
+ * Loosely based on android x86 kernel code which is:
+ *
+ * Copyright (C) 2014 Intel Corp.
+ *
+ * Author: Wu, Hao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation, or (at your option)
+ * any later version.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/* register definition */
+#define DUAL_ROLE_CFG0 0x68
+#define SW_VBUS_VALID  (1 << 24)
+#define SW_IDPIN_EN(1 << 21)
+#define SW_IDPIN   (1 << 20)
+
+#define DUAL_ROL

[PATCH v3 07/14] xhci: Add Intel cherrytrail extended cap / otg phy mux handling

2017-09-22 Thread Hans de Goede
The Intel cherrytrail xhci controller has an extended cap mmio-range
which contains registers to control the muxing to the xhci (host mode)
or the dwc3 (device mode) and vbus-detection for the otg usb-phy.

Having a mux driver included in the xhci code (or under drivers/usb/host)
is not desirable. So this commit adds a simple handler for this extended
capability, which creates a platform device with the caps mmio region as
resource, this allows us to write a separate platform mux driver for the
mux.

Note this commit adds a call to the new xhci_ext_cap_init() function
to xhci_pci_probe(), it is added here because xhci_ext_cap_init() must
be called only once. If in the future we also want to handle ext-caps
on non pci XHCI HCDs from xhci_ext_cap_init() a call to it should also
be added to other bus probe paths.

Signed-off-by: Hans de Goede 
---
Changes in v2:
-Check xHCI controller PCI device-id instead of only checking for the
 Intel Extended capability ID, as the Extended capability ID is used on
 other model Intel xHCI controllers too

Changes in v3:
-Add a new generic xhci_ext_cap_init() function and handle the new
 XHCI_INTEL_CHT_USB_MUX quirk there.
---
 drivers/usb/host/Makefile|  2 +-
 drivers/usb/host/xhci-ext-caps.c | 88 
 drivers/usb/host/xhci-ext-caps.h |  2 +
 drivers/usb/host/xhci-pci.c  |  5 +++
 drivers/usb/host/xhci.h  |  2 +
 5 files changed, 98 insertions(+), 1 deletion(-)
 create mode 100644 drivers/usb/host/xhci-ext-caps.c

diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index cf2691fffcc0..59329a9cf392 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -10,7 +10,7 @@ fhci-y += fhci-mem.o fhci-tds.o fhci-sched.o
 
 fhci-$(CONFIG_FHCI_DEBUG) += fhci-dbg.o
 
-xhci-hcd-y := xhci.o xhci-mem.o
+xhci-hcd-y := xhci.o xhci-mem.o xhci-ext-caps.o
 xhci-hcd-y += xhci-ring.o xhci-hub.o xhci-dbg.o
 xhci-hcd-y += xhci-trace.o
 ifneq ($(CONFIG_USB_XHCI_MTK), )
diff --git a/drivers/usb/host/xhci-ext-caps.c b/drivers/usb/host/xhci-ext-caps.c
new file mode 100644
index ..8bc4787afdd0
--- /dev/null
+++ b/drivers/usb/host/xhci-ext-caps.c
@@ -0,0 +1,88 @@
+/*
+ * XHCI extended capability handling
+ *
+ * Copyright (c) 2017 Hans de Goede 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include 
+#include "xhci.h"
+
+static void xhci_intel_unregister_pdev(void *arg)
+{
+   platform_device_unregister(arg);
+}
+
+static int xhci_create_intel_cht_mux_pdev(struct xhci_hcd *xhci, u32 
cap_offset)
+{
+   struct usb_hcd *hcd = xhci_to_hcd(xhci);
+   struct device *dev = hcd->self.controller;
+   struct platform_device *pdev;
+   struct resource res = { 0, };
+   int ret;
+
+   pdev = platform_device_alloc("intel_cht_usb_mux", PLATFORM_DEVID_NONE);
+   if (!pdev) {
+   xhci_err(xhci, "couldn't allocate intel_cht_usb_mux pdev\n");
+   return -ENOMEM;
+   }
+
+   res.start = hcd->rsrc_start + cap_offset;
+   res.end   = res.start + 0x3ff;
+   res.name  = "intel_cht_usb_mux";
+   res.flags = IORESOURCE_MEM;
+
+   ret = platform_device_add_resources(pdev, &res, 1);
+   if (ret) {
+   dev_err(dev, "couldn't add resources to intel_cht_usb_mux 
pdev\n");
+   platform_device_put(pdev);
+   return ret;
+   }
+
+   pdev->dev.parent = dev;
+
+   ret = platform_device_add(pdev);
+   if (ret) {
+   dev_err(dev, "couldn't register intel_cht_usb_mux pdev\n");
+   platform_device_put(pdev);
+   return ret;
+   }
+
+   ret = devm_add_action_or_reset(dev, xhci_intel_unregister_pdev, pdev);
+   if (ret) {
+   dev_err(dev, "couldn't add unregister action for 
intel_cht_usb_mux pdev\n");
+   return ret;
+   }
+
+   return 0;
+}
+
+int xhci_ext_cap_init(struct xhci_hcd *xhci)
+{
+   void __iomem *base = &xhci->cap_regs->hc_capbase;
+   u32 cap_offset, val;
+   int ret;
+
+   cap_offset = xhci_find_next_ext_cap(base, 0, 0);
+
+   while (cap_offset) {
+   val = readl(base + cap_offset);
+
+   switch (XHCI_EXT_CAPS_ID(val)) {
+   case XHCI_EXT_CAPS_VENDOR_INTEL:
+   if (xhci->quirks & XHCI_INTEL_CHT_USB_MUX) {
+   ret = xhci_create_intel_cht_mux_pdev(
+   xhci, cap_offset);
+   if (ret)
+   return ret;
+   }
+   break;
+   }
+   cap_offset = xhci_find_next_ext_cap(base, cap_offset, 0);
+   }
+
+   return 0;
+}
diff --git a/drivers/usb/host/xhci-ext-caps.h b/drivers/usb/host/

[PATCH v3 05/14] mux: core: Add usb.h header with MUX_USB_* and and MUX_TYPEC_* state constants

2017-09-22 Thread Hans de Goede
Add MUX_USB_* and MUX_TYPEC_* state constant defines, which can be used by
USB device/host, resp. Type-C polarity/role/altmode mux drivers and
consumers to ensure that they agree on the meaning of the
mux_control_select() state argument.

Signed-off-by: Hans de Goede 
---
Changes in v2:
-Start numbering of defines at 0 not 1
-Use a new usb.h header, rather then adding these to consumer.h
-Add separate MUX_USB_* and MUX_TYPEC_* defines

Changes in v3:
-Simplify MUX_TYPEC_* states, drop having separate USB HOST / DEVICE states
---
 include/linux/mux/usb.h | 31 +++
 1 file changed, 31 insertions(+)
 create mode 100644 include/linux/mux/usb.h

diff --git a/include/linux/mux/usb.h b/include/linux/mux/usb.h
new file mode 100644
index ..2fec06846e14
--- /dev/null
+++ b/include/linux/mux/usb.h
@@ -0,0 +1,31 @@
+/*
+ * mux/usb.h - definitions for USB multiplexers
+ *
+ * Copyright (C) 2017 Hans de Goede 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef _LINUX_MUX_USB_H
+#define _LINUX_MUX_USB_H
+
+/* Mux state values for USB device/host role muxes */
+#define MUX_USB_DEVICE (0) /* USB device mode */
+#define MUX_USB_HOST   (1) /* USB host mode */
+#define MUX_USB_STATES (2)
+
+/*
+ * Mux state values for Type-C polarity/role/altmode muxes.
+ *
+ * MUX_TYPEC_POLARITY_INV may be or-ed together with any other mux-state as
+ * inverted-polarity (Type-C plugged in upside down) can happen with any
+ * other mux-state.
+ */
+#define MUX_TYPEC_POLARITY_INV BIT(0)   /* Polarity inverted bit */
+#define MUX_TYPEC_USB  (0 << 1) /* USB only mode */
+#define MUX_TYPEC_USB_AND_DP   (1 << 1) /* USB host + 2 lanes DP */
+#define MUX_TYPEC_DP   (2 << 1) /* 4 lanes Display Port */
+#define MUX_TYPEC_STATES   (3 << 1)
+
+#endif /* _LINUX_MUX_TYPEC_H */
-- 
2.14.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3 04/14] mux: core: Add support for getting a mux controller on a non DT platform

2017-09-22 Thread Hans de Goede
On non DT platforms we cannot get the mux_chip by pnode. Other subsystems
(regulator, clock, pwm) have the same problem and solve this by allowing
platform / board-setup code to add entries to a lookup table and then use
this table to look things up.

This commit adds support for getting a mux controller on a non DT platform
following this pattern. It is based on a simplified version of the pwm
subsys lookup code, the dev_id and mux_name parts of a lookup table entry
are mandatory in the mux-core implementation.

Signed-off-by: Hans de Goede 
---
Changes in v2:
-Fixup some kerneldoc comments, add kerneldoc comment to structs
-Minor code-style tweaks
---
 drivers/mux/core.c   | 93 +++-
 include/linux/mux/consumer.h | 19 +
 2 files changed, 111 insertions(+), 1 deletion(-)

diff --git a/drivers/mux/core.c b/drivers/mux/core.c
index 8c0a4c83cdc5..c9afc79196f0 100644
--- a/drivers/mux/core.c
+++ b/drivers/mux/core.c
@@ -24,6 +24,9 @@
 #include 
 #include 
 
+static DEFINE_MUTEX(mux_lookup_lock);
+static LIST_HEAD(mux_lookup_list);
+
 /*
  * The idle-as-is "state" is not an actual state that may be selected, it
  * only implies that the state should not be changed. So, use that state
@@ -423,6 +426,23 @@ int mux_control_deselect(struct mux_control *mux)
 }
 EXPORT_SYMBOL_GPL(mux_control_deselect);
 
+static int parent_name_match(struct device *dev, const void *data)
+{
+   const char *parent_name = dev_name(dev->parent);
+   const char *name = data;
+
+   return strcmp(parent_name, name) == 0;
+}
+
+static struct mux_chip *mux_chip_get_by_name(const char *name)
+{
+   struct device *dev;
+
+   dev = class_find_device(&mux_class, NULL, name, parent_name_match);
+
+   return dev ? to_mux_chip(dev) : NULL;
+}
+
 static int of_dev_node_match(struct device *dev, const void *data)
 {
return dev->of_node == data;
@@ -503,12 +523,83 @@ of_mux_control_get(struct device *dev, const char 
*mux_name, bool optional)
 static struct mux_control *
 __mux_control_get(struct device *dev, const char *mux_name, bool optional)
 {
+   struct mux_lookup *m, *chosen = NULL;
+   const char *dev_id = dev_name(dev);
+   struct mux_chip *mux_chip;
+
/* look up via DT first */
if (IS_ENABLED(CONFIG_OF) && dev->of_node)
return of_mux_control_get(dev, mux_name, optional);
 
-   return optional ? NULL : ERR_PTR(-ENODEV);
+   /*
+* For non DT we look up the provider in the static table typically
+* provided by board setup code.
+*
+* If a match is found, the provider mux chip is looked up by name
+* and a mux-control is requested using the table provided index.
+*/
+   mutex_lock(&mux_lookup_lock);
+   list_for_each_entry(m, &mux_lookup_list, list) {
+   if (WARN_ON(!m->dev_id || !m->mux_name || !m->provider))
+   continue;
+
+   if (!strcmp(m->dev_id, dev_id) &&
+   !strcmp(m->mux_name, mux_name))
+   {
+   chosen = m;
+   break;
+   }
+   }
+   mutex_unlock(&mux_lookup_lock);
+
+   if (!chosen)
+   return optional ? NULL : ERR_PTR(-ENODEV);
+
+   mux_chip = mux_chip_get_by_name(chosen->provider);
+   if (!mux_chip)
+   return ERR_PTR(-EPROBE_DEFER);
+
+   if (chosen->index >= mux_chip->controllers) {
+   dev_err(dev, "Mux lookup table index out of bounds %u >= %u\n",
+   chosen->index, mux_chip->controllers);
+   put_device(&mux_chip->dev);
+   return ERR_PTR(-EINVAL);
+   }
+
+   return &mux_chip->mux[chosen->index];
+}
+
+/**
+ * mux_add_table() - Register consumer to mux-controller mappings
+ * @table: array of mappings to register
+ * @num: number of mappings in table
+ */
+void mux_add_table(struct mux_lookup *table, size_t num)
+{
+   mutex_lock(&mux_lookup_lock);
+
+   for (; num--; table++)
+   list_add_tail(&table->list, &mux_lookup_list);
+
+   mutex_unlock(&mux_lookup_lock);
+}
+EXPORT_SYMBOL_GPL(mux_add_table);
+
+/**
+ * mux_remove_table() - Unregister consumer to mux-controller mappings
+ * @table: array of mappings to unregister
+ * @num: number of mappings in table
+ */
+void mux_remove_table(struct mux_lookup *table, size_t num)
+{
+   mutex_lock(&mux_lookup_lock);
+
+   for (; num--; table++)
+   list_del(&table->list);
+
+   mutex_unlock(&mux_lookup_lock);
 }
+EXPORT_SYMBOL_GPL(mux_remove_table);
 
 /**
  * mux_control_get() - Get the mux-control for a device.
diff --git a/include/linux/mux/consumer.h b/include/linux/mux/consumer.h
index fc98547bf494..eaa6d239c4f5 100644
--- a/include/linux/mux/consumer.h
+++ b/include/linux/mux/consumer.h
@@ -18,6 +18,25 @@
 struct device;
 struct mux_control;
 
+/**
+ * struct mux_lookup - Mux consumer to mux-control

[PATCH v3 03/14] mux: core: Add of_mux_control_get helper function

2017-09-22 Thread Hans de Goede
Currently the mux_control_get implementation only deals with getting
mux controllers on DT platforms. This commit renames the current
implementation to of_mux_control_get to reflect this and makes
mux_control_get a wrapper around of_mux_control_get.

This is a preparation patch for adding support for getting muxes on
non DT platforms.

Signed-off-by: Hans de Goede 
---
 drivers/mux/core.c | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/drivers/mux/core.c b/drivers/mux/core.c
index d0ad56abca2a..8c0a4c83cdc5 100644
--- a/drivers/mux/core.c
+++ b/drivers/mux/core.c
@@ -439,7 +439,7 @@ static struct mux_chip *of_find_mux_chip_by_node(struct 
device_node *np)
 }
 
 static struct mux_control *
-__mux_control_get(struct device *dev, const char *mux_name, bool optional)
+of_mux_control_get(struct device *dev, const char *mux_name, bool optional)
 {
struct device_node *np = dev->of_node;
struct of_phandle_args args;
@@ -500,6 +500,16 @@ __mux_control_get(struct device *dev, const char 
*mux_name, bool optional)
return &mux_chip->mux[controller];
 }
 
+static struct mux_control *
+__mux_control_get(struct device *dev, const char *mux_name, bool optional)
+{
+   /* look up via DT first */
+   if (IS_ENABLED(CONFIG_OF) && dev->of_node)
+   return of_mux_control_get(dev, mux_name, optional);
+
+   return optional ? NULL : ERR_PTR(-ENODEV);
+}
+
 /**
  * mux_control_get() - Get the mux-control for a device.
  * @dev: The device that needs a mux-control.
-- 
2.14.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3 01/14] mux: core: Add mux_control_get_optional() API

2017-09-22 Thread Hans de Goede
From: Stephen Boyd 

Sometimes drivers only use muxes under certain scenarios. For
example, the chipidea usb controller may be connected to a usb
switch on some platforms, and connected directly to a usb port on
others. The driver won't know one way or the other though, so add
a mux_control_get_optional() API that allows the driver to
differentiate errors getting the mux from there not being a mux
for the driver to use at all.

Signed-off-by: Stephen Boyd 
Signed-off-by: Hans de Goede 
---
 Documentation/driver-model/devres.txt |   1 +
 drivers/mux/core.c| 104 +++---
 include/linux/mux/consumer.h  |   4 ++
 3 files changed, 89 insertions(+), 20 deletions(-)

diff --git a/Documentation/driver-model/devres.txt 
b/Documentation/driver-model/devres.txt
index 69f08c0f23a8..5e41f3ac8a05 100644
--- a/Documentation/driver-model/devres.txt
+++ b/Documentation/driver-model/devres.txt
@@ -343,6 +343,7 @@ MUX
   devm_mux_chip_alloc()
   devm_mux_chip_register()
   devm_mux_control_get()
+  devm_mux_control_get_optional()
 
 PER-CPU MEM
   devm_alloc_percpu()
diff --git a/drivers/mux/core.c b/drivers/mux/core.c
index 6e5cf9d9cd99..244bceb17877 100644
--- a/drivers/mux/core.c
+++ b/drivers/mux/core.c
@@ -289,6 +289,9 @@ EXPORT_SYMBOL_GPL(devm_mux_chip_register);
  */
 unsigned int mux_control_states(struct mux_control *mux)
 {
+   if (!mux)
+   return 0;
+
return mux->states;
 }
 EXPORT_SYMBOL_GPL(mux_control_states);
@@ -338,6 +341,9 @@ int mux_control_select(struct mux_control *mux, unsigned 
int state)
 {
int ret;
 
+   if (!mux)
+   return 0;
+
ret = down_killable(&mux->lock);
if (ret < 0)
return ret;
@@ -370,6 +376,9 @@ int mux_control_try_select(struct mux_control *mux, 
unsigned int state)
 {
int ret;
 
+   if (!mux)
+   return 0;
+
if (down_trylock(&mux->lock))
return -EBUSY;
 
@@ -398,6 +407,9 @@ int mux_control_deselect(struct mux_control *mux)
 {
int ret = 0;
 
+   if (!mux)
+   return 0;
+
if (mux->idle_state != MUX_IDLE_AS_IS &&
mux->idle_state != mux->cached_state)
ret = mux_control_set(mux, mux->idle_state);
@@ -423,14 +435,8 @@ static struct mux_chip *of_find_mux_chip_by_node(struct 
device_node *np)
return dev ? to_mux_chip(dev) : NULL;
 }
 
-/**
- * mux_control_get() - Get the mux-control for a device.
- * @dev: The device that needs a mux-control.
- * @mux_name: The name identifying the mux-control.
- *
- * Return: A pointer to the mux-control, or an ERR_PTR with a negative errno.
- */
-struct mux_control *mux_control_get(struct device *dev, const char *mux_name)
+static struct mux_control *
+__mux_control_get(struct device *dev, const char *mux_name, bool optional)
 {
struct device_node *np = dev->of_node;
struct of_phandle_args args;
@@ -442,16 +448,22 @@ struct mux_control *mux_control_get(struct device *dev, 
const char *mux_name)
if (mux_name) {
index = of_property_match_string(np, "mux-control-names",
 mux_name);
+   if ((index == -EINVAL || index == -ENODATA) && optional)
+   return NULL;
if (index < 0) {
dev_err(dev, "mux controller '%s' not found\n",
mux_name);
return ERR_PTR(index);
}
+   /* OF does point to a mux, so it's no longer optional */
+   optional = false;
}
 
ret = of_parse_phandle_with_args(np,
 "mux-controls", "#mux-control-cells",
 index, &args);
+   if (ret == -ENOENT && optional)
+   return NULL;
if (ret) {
dev_err(dev, "%pOF: failed to get mux-control %s(%i)\n",
np, mux_name ?: "", index);
@@ -484,8 +496,35 @@ struct mux_control *mux_control_get(struct device *dev, 
const char *mux_name)
 
return &mux_chip->mux[controller];
 }
+
+/**
+ * mux_control_get() - Get the mux-control for a device.
+ * @dev: The device that needs a mux-control.
+ * @mux_name: The name identifying the mux-control.
+ *
+ * Return: A pointer to the mux-control, or an ERR_PTR with a negative errno.
+ */
+struct mux_control *mux_control_get(struct device *dev, const char *mux_name)
+{
+   return __mux_control_get(dev, mux_name, false);
+}
 EXPORT_SYMBOL_GPL(mux_control_get);
 
+/**
+ * mux_control_get_optional() - Get the optional mux-control for a device.
+ * @dev: The device that needs a mux-control.
+ * @mux_name: The name identifying the mux-control.
+ *
+ * Return: NULL if no mux with the provided name is found, a pointer to
+ * the named mux-control or an ERR_PTR with a negative errno.
+ */
+struct mux_control *
+mux_control_get_op

[PATCH v3 02/14] mux: core: Add explicit hook to leave the mux as-is on init/registration

2017-09-22 Thread Hans de Goede
From: Peter Rosin 

A board may need a mux controller to stay as-is for a while longer, e.g.
if setting the normally preferred idle state destroys booting.

The mechanism provided here is not perfect in two ways.
1. As soon as the mux controller is registered, some mux consumer can
   access it and set a state that destroys booting all the same.
2. The mux controller might linger in a state that is not the
   preferred idle state indefinitely, if no mux consumer ever selects
   and then deselects the mux.

Signed-off-by: Hans de Goede 
---
 drivers/mux/core.c | 3 +++
 include/linux/mux/driver.h | 4 
 2 files changed, 7 insertions(+)

diff --git a/drivers/mux/core.c b/drivers/mux/core.c
index 244bceb17877..d0ad56abca2a 100644
--- a/drivers/mux/core.c
+++ b/drivers/mux/core.c
@@ -155,6 +155,9 @@ int mux_chip_register(struct mux_chip *mux_chip)
for (i = 0; i < mux_chip->controllers; ++i) {
struct mux_control *mux = &mux_chip->mux[i];
 
+   if (mux->init_as_is)
+   continue;
+
if (mux->idle_state == mux->cached_state)
continue;
 
diff --git a/include/linux/mux/driver.h b/include/linux/mux/driver.h
index 35c3579c3304..21cf6041a962 100644
--- a/include/linux/mux/driver.h
+++ b/include/linux/mux/driver.h
@@ -36,6 +36,9 @@ struct mux_control_ops {
  * @states:The number of mux controller states.
  * @idle_state:The mux controller state to use when inactive, 
or one
  * of MUX_IDLE_AS_IS and MUX_IDLE_DISCONNECT.
+ * @init_as_is:Set to true to have the core leave the mux 
controller
+ * state as-is until first selection. If @idle_state is
+ * MUX_IDLE_AS_IS, @init_as_is is irrelevant.
  *
  * Mux drivers may only change @states and @idle_state, and may only do so
  * between allocation and registration of the mux controller. Specifically,
@@ -50,6 +53,7 @@ struct mux_control {
 
unsigned int states;
int idle_state;
+   bool init_as_is;
 };
 
 /**
-- 
2.14.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3 06/14] xhci: Add option to get next extended capability in list by passing id = 0

2017-09-22 Thread Hans de Goede
From: Mathias Nyman 

Modify xhci_find_next_ext_cap(base, offset, id) to return the next
capability offset if 0 is passed for id. Otherwise it will behave as
previously and return the offset of the next capability with matching id

capability id 0 is not used by xhci (reserved)

This is useful when we want to loop through all capabilities.

Signed-off-by: Mathias Nyman 
Signed-off-by: Hans de Goede 
---
 drivers/usb/host/xhci-ext-caps.h | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/host/xhci-ext-caps.h b/drivers/usb/host/xhci-ext-caps.h
index 28deea584884..c1b404224839 100644
--- a/drivers/usb/host/xhci-ext-caps.h
+++ b/drivers/usb/host/xhci-ext-caps.h
@@ -96,7 +96,8 @@
  * @base   PCI MMIO registers base address.
  * @start  address at which to start looking, (0 or HCC_PARAMS to start at
  * beginning of list)
- * @id Extended capability ID to search for.
+ * @id Extended capability ID to search for, or 0 for the next
+ * capability
  *
  * Returns the offset of the next matching extended capability structure.
  * Some capabilities can occur several times, e.g., the XHCI_EXT_CAPS_PROTOCOL,
@@ -122,7 +123,7 @@ static inline int xhci_find_next_ext_cap(void __iomem 
*base, u32 start, int id)
val = readl(base + offset);
if (val == ~0)
return 0;
-   if (XHCI_EXT_CAPS_ID(val) == id && offset != start)
+   if (offset != start && (id == 0 || XHCI_EXT_CAPS_ID(val) == id))
return offset;
 
next = XHCI_EXT_CAPS_NEXT(val);
-- 
2.14.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] r8152: add Linksys USB3GIGV1 id

2017-09-22 Thread Grant Grundler
This Linksys dongle by default comes up in cdc_ether mode.
This patch allows r8152 to claim the device:
   Bus 002 Device 002: ID 13b1:0041 Linksys

Signed-off-by: Grant Grundler 
---
 drivers/net/usb/r8152.c | 2 ++
 1 file changed, 2 insertions(+)

This was tested on chromeos-3.14, chromeos-3.18, and chromeos-4.4 kernels
with a mix of ARM/x86-64 systems.

diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index ceb78e2ea4f0..941ece08ba78 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -613,6 +613,7 @@ enum rtl8152_flags {
 #define VENDOR_ID_MICROSOFT0x045e
 #define VENDOR_ID_SAMSUNG  0x04e8
 #define VENDOR_ID_LENOVO   0x17ef
+#define VENDOR_ID_LINKSYS  0x13b1
 #define VENDOR_ID_NVIDIA   0x0955
 
 #define MCU_TYPE_PLA   0x0100
@@ -5316,6 +5317,7 @@ static const struct usb_device_id rtl8152_table[] = {
{REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x7205)},
{REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x720c)},
{REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x7214)},
+   {REALTEK_USB_DEVICE(VENDOR_ID_LINKSYS, 0x0041)},
{REALTEK_USB_DEVICE(VENDOR_ID_NVIDIA,  0x09ff)},
{}
 };
-- 
2.14.1.821.g8fa685d3b7-goog

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2][for 4.14] xhci: allow TRACE to work with EVENT ring dequeue

2017-09-22 Thread Adam Wallis
inc_deq() currently bails earlier for EVENT rings than the common return
point of the function, due to the fact that EVENT rings do not have
link TRBs. The unfortunate side effect of this is that the very useful
trace_xhci_inc_deq() function is not called/usable for EVENT ring
debug.

This patch provides a refactor by removing the multiple return exit
points into a single return which additionally allows for all rings to
use the trace function.

Signed-off-by: Adam Wallis 
---
Changes in v2: undo accidental line removal at end of patch

 drivers/usb/host/xhci-ring.c | 32 
 1 file changed, 16 insertions(+), 16 deletions(-)

diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index a944365..3960ba9 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -171,23 +171,23 @@ static void inc_deq(struct xhci_hcd *xhci, struct 
xhci_ring *ring)
if (ring->type == TYPE_EVENT) {
if (!last_trb_on_seg(ring->deq_seg, ring->dequeue)) {
ring->dequeue++;
-   return;
+   } else {
+   if (last_trb_on_ring(ring, ring->deq_seg,
+   ring->dequeue))
+   ring->cycle_state ^= 1;
+   ring->deq_seg = ring->deq_seg->next;
+   ring->dequeue = ring->deq_seg->trbs;
+   }
+   } else {
+   /* All other rings have link trbs */
+   if (!trb_is_link(ring->dequeue)) {
+   ring->dequeue++;
+   ring->num_trbs_free++;
+   }
+   while (trb_is_link(ring->dequeue)) {
+   ring->deq_seg = ring->deq_seg->next;
+   ring->dequeue = ring->deq_seg->trbs;
}
-   if (last_trb_on_ring(ring, ring->deq_seg, ring->dequeue))
-   ring->cycle_state ^= 1;
-   ring->deq_seg = ring->deq_seg->next;
-   ring->dequeue = ring->deq_seg->trbs;
-   return;
-   }
-
-   /* All other rings have link trbs */
-   if (!trb_is_link(ring->dequeue)) {
-   ring->dequeue++;
-   ring->num_trbs_free++;
-   }
-   while (trb_is_link(ring->dequeue)) {
-   ring->deq_seg = ring->deq_seg->next;
-   ring->dequeue = ring->deq_seg->trbs;
}
 
trace_xhci_inc_deq(ring);
-- 
Qualcomm Datacenter Technologies as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] USB: cdc-wdm: ignore -EPIPE from GetEncapsulatedResponse

2017-09-22 Thread Bjørn Mork
The driver will forward errors to userspace after turning most of them
into -EIO. But all status codes are not equal. The -EPIPE (stall) in
particular can be seen more as a result of normal USB signaling than
an actual error. The state is automatically cleared by the USB core
without intervention from either driver or userspace.

And most devices and firmwares will never trigger a stall as a result
of GetEncapsulatedResponse. This is in fact a requirement for CDC WDM
devices. Quoting from section 7.1 of the CDC WMC spec revision 1.1:

  The function shall not return STALL in response to
  GetEncapsulatedResponse.

But this driver is also handling GetEncapsulatedResponse on behalf of
the qmi_wwan and cdc_mbim drivers. Unfortunately the relevant specs
are not as clear wrt stall. So some QMI and MBIM devices *will*
occasionally stall, causing the GetEncapsulatedResponse to return an
-EPIPE status. Translating this into -EIO for userspace has proven to
be harmful. Treating it as an empty read is safer, making the driver
behave as if the device was conforming to the CDC WDM spec.

There have been numerous reports of issues related to -EPIPE errors
from some newer CDC MBIM devices in particular, like for example the
Fibocom L831-EAU.  Testing on this device has shown that the issues
go away if we simply ignore the -EPIPE status.  Similar handling of
-EPIPE is already known from e.g. usb_get_string()

The -EPIPE log message is still kept to let us track devices with this
unexpected behaviour, hoping that it attracts attention from firmware
developers.

Cc: 
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=100938
Reported-and-tested-by: Christian Ehrig 

Reported-and-tested-by: Patrick Chilton 
Reported-and-tested-by: Andreas Böhler 
Signed-off-by: Bjørn Mork 
---
The fallout of this problem has been reported by a number of people
for a long time.  Many more than those being listed above. Apologies
to all who didn't get the appropriate credit.  Sorry, I am lousy with
paper work and lost track of you all.

Hoping the fix will make up for it...


Bjørn

 drivers/usb/class/cdc-wdm.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
index 0b845e550fbd..9f001659807a 100644
--- a/drivers/usb/class/cdc-wdm.c
+++ b/drivers/usb/class/cdc-wdm.c
@@ -194,8 +194,10 @@ static void wdm_in_callback(struct urb *urb)
/*
 * only set a new error if there is no previous error.
 * Errors are only cleared during read/open
+* Avoid propagating -EPIPE (stall) to userspace since it is
+* better handled as an empty read
 */
-   if (desc->rerr  == 0)
+   if (desc->rerr == 0 && status != -EPIPE)
desc->rerr = status;
 
if (length + desc->length > desc->wMaxCommand) {
-- 
2.11.0

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/2] USB: devio: Don't corrupt user memory

2017-09-22 Thread Dan Carpenter
The user buffer has "uurb->buffer_length" bytes.  If the kernel has more
information than that, we should truncate it instead of writing past
the end of the user's buffer.  I added a WARN_ONCE() to help the user
debug the issue.

Reported-by: Alan Stern 
Signed-off-by: Dan Carpenter 

diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 318bb3b96687..4664e543cf2f 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -1571,7 +1576,11 @@ static int proc_do_submiturb(struct usb_dev_state *ps, 
struct usbdevfs_urb *uurb
totlen += isopkt[u].length;
}
u *= sizeof(struct usb_iso_packet_descriptor);
-   uurb->buffer_length = totlen;
+   if (totlen <= uurb->buffer_length)
+   uurb->buffer_length = totlen;
+   else
+   WARN_ONCE(1, "uurb->buffer_length is too short %d vs 
%d",
+ totlen, uurb->buffer_length);
break;
 
default:
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 1/2] USB: devio: Prevent integer overflow in proc_do_submiturb()

2017-09-22 Thread Dan Carpenter
There used to be an integer overflow check in proc_do_submiturb() but
we removed it.  It turns out that it's still required.  The
uurb->buffer_length variable is a signed integer and it's controlled by
the user.  It can lead to an integer overflow when we do:

num_sgs = DIV_ROUND_UP(uurb->buffer_length, USB_SG_SIZE);

If we strip away the macro then that line looks like this:

num_sgs = (uurb->buffer_length + USB_SG_SIZE - 1) / USB_SG_SIZE;
   ^
It's the first addition which can overflow.

Fixes: 1129d270cbfb ("USB: Increase usbfs transfer limit")
Signed-off-by: Dan Carpenter 
---
v2: Cast the ->buffer_length to unsigned int which is more readable than
relying on type promotion.

diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 318bb3b96687..4664e543cf2f 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -140,6 +140,9 @@ module_param(usbfs_memory_mb, uint, 0644);
 MODULE_PARM_DESC(usbfs_memory_mb,
"maximum MB allowed for usbfs buffers (0 = no limit)");
 
+/* Hard limit, necessary to avoid arithmetic overflow */
+#define USBFS_XFER_MAX (UINT_MAX / 2 - 100)
+
 static atomic64_t usbfs_memory_usage;  /* Total memory currently allocated */
 
 /* Check whether it's okay to allocate more memory for a transfer */
@@ -1460,6 +1463,8 @@ static int proc_do_submiturb(struct usb_dev_state *ps, 
struct usbdevfs_urb *uurb
USBDEVFS_URB_ZERO_PACKET |
USBDEVFS_URB_NO_INTERRUPT))
return -EINVAL;
+   if ((unsigned int)uurb->buffer_length >= USBFS_XFER_MAX)
+   return -EINVAL;
if (uurb->buffer_length > 0 && !uurb->buffer)
return -EINVAL;
if (!(uurb->type == USBDEVFS_URB_TYPE_CONTROL &&
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 1/2] USB: devio: Prevent integer overflow in proc_do_submiturb()

2017-09-22 Thread Alan Stern
On Fri, 22 Sep 2017, Dan Carpenter wrote:

> There used to be an integer overflow check in proc_do_submiturb() but
> we removed it.  It turns out that it's still required.  The
> uurb->buffer_length variable is a signed integer and it's controlled by
> the user.  It can lead to an integer overflow when we do:
> 
>   num_sgs = DIV_ROUND_UP(uurb->buffer_length, USB_SG_SIZE);
> 
> If we strip away the macro then that line looks like this:
> 
>   num_sgs = (uurb->buffer_length + USB_SG_SIZE - 1) / USB_SG_SIZE;
>^
> It's the first addition which can overflow.
> 
> Fixes: 1129d270cbfb ("USB: Increase usbfs transfer limit")
> Signed-off-by: Dan Carpenter 
> ---
> v2: Cast the ->buffer_length to unsigned int which is more readable than
> relying on type promotion.

For both 1/2 and 2/2:

Acked-by: Alan Stern 

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html