USB driver fixes for 6.9-rc7
Here are some small USB driver fixes for reported problems for 6.9-rc7. Included in here are: - usb core fixes for found issues - typec driver fixes for reported problems - usb gadget driver fixes for reported problems - xhci build fixes - dwc3 driver fixes for reported issues All of these have been in linux-next this past week with no reported problems. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCZjdEhQ8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+ylZ0wCgpMcwSdBww3xH3JHwYjukeW8EPKYAn3N3CBb+ s/e/cETFHgg8RpWq38Sy =/6D3 -----END PGP SIGNATURE----- Merge tag 'usb-6.9-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb Pull USB driver fixes from Greg KH: "Here are some small USB driver fixes for reported problems for 6.9-rc7. Included in here are: - usb core fixes for found issues - typec driver fixes for reported problems - usb gadget driver fixes for reported problems - xhci build fixes - dwc3 driver fixes for reported issues All of these have been in linux-next this past week with no reported problems" * tag 'usb-6.9-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: usb: typec: tcpm: Check for port partner validity before consuming it usb: typec: tcpm: enforce ready state when queueing alt mode vdm usb: typec: tcpm: unregister existing source caps before re-registration usb: typec: tcpm: clear pd_event queue in PORT_RESET usb: typec: tcpm: queue correct sop type in tcpm_queue_vdm_unlocked usb: Fix regression caused by invalid ep0 maxpacket in virtual SuperSpeed device usb: ohci: Prevent missed ohci interrupts usb: typec: qcom-pmic: fix pdphy start() error handling usb: typec: qcom-pmic: fix use-after-free on late probe errors usb: gadget: f_fs: Fix a race condition when processing setup packets. USB: core: Fix access violation during port device removal usb: dwc3: core: Prevent phy suspend during init usb: xhci-plat: Don't include xhci.h usb: gadget: uvc: use correct buffer size when parsing configfs lists usb: gadget: composite: fix OS descriptors w_value logic usb: gadget: f_fs: Fix race between aio_cancel() and AIO request complete
This commit is contained in:
commit
3c15237018
@ -5110,9 +5110,10 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
|
|||||||
}
|
}
|
||||||
if (usb_endpoint_maxp(&udev->ep0.desc) == i) {
|
if (usb_endpoint_maxp(&udev->ep0.desc) == i) {
|
||||||
; /* Initial ep0 maxpacket guess is right */
|
; /* Initial ep0 maxpacket guess is right */
|
||||||
} else if ((udev->speed == USB_SPEED_FULL ||
|
} else if (((udev->speed == USB_SPEED_FULL ||
|
||||||
udev->speed == USB_SPEED_HIGH) &&
|
udev->speed == USB_SPEED_HIGH) &&
|
||||||
(i == 8 || i == 16 || i == 32 || i == 64)) {
|
(i == 8 || i == 16 || i == 32 || i == 64)) ||
|
||||||
|
(udev->speed >= USB_SPEED_SUPER && i > 0)) {
|
||||||
/* Initial guess is wrong; use the descriptor's value */
|
/* Initial guess is wrong; use the descriptor's value */
|
||||||
if (udev->speed == USB_SPEED_FULL)
|
if (udev->speed == USB_SPEED_FULL)
|
||||||
dev_dbg(&udev->dev, "ep0 maxpacket = %d\n", i);
|
dev_dbg(&udev->dev, "ep0 maxpacket = %d\n", i);
|
||||||
|
@ -51,13 +51,15 @@ static ssize_t disable_show(struct device *dev,
|
|||||||
struct usb_port *port_dev = to_usb_port(dev);
|
struct usb_port *port_dev = to_usb_port(dev);
|
||||||
struct usb_device *hdev = to_usb_device(dev->parent->parent);
|
struct usb_device *hdev = to_usb_device(dev->parent->parent);
|
||||||
struct usb_hub *hub = usb_hub_to_struct_hub(hdev);
|
struct usb_hub *hub = usb_hub_to_struct_hub(hdev);
|
||||||
struct usb_interface *intf = to_usb_interface(hub->intfdev);
|
struct usb_interface *intf = to_usb_interface(dev->parent);
|
||||||
int port1 = port_dev->portnum;
|
int port1 = port_dev->portnum;
|
||||||
u16 portstatus, unused;
|
u16 portstatus, unused;
|
||||||
bool disabled;
|
bool disabled;
|
||||||
int rc;
|
int rc;
|
||||||
struct kernfs_node *kn;
|
struct kernfs_node *kn;
|
||||||
|
|
||||||
|
if (!hub)
|
||||||
|
return -ENODEV;
|
||||||
hub_get(hub);
|
hub_get(hub);
|
||||||
rc = usb_autopm_get_interface(intf);
|
rc = usb_autopm_get_interface(intf);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
@ -101,12 +103,14 @@ static ssize_t disable_store(struct device *dev, struct device_attribute *attr,
|
|||||||
struct usb_port *port_dev = to_usb_port(dev);
|
struct usb_port *port_dev = to_usb_port(dev);
|
||||||
struct usb_device *hdev = to_usb_device(dev->parent->parent);
|
struct usb_device *hdev = to_usb_device(dev->parent->parent);
|
||||||
struct usb_hub *hub = usb_hub_to_struct_hub(hdev);
|
struct usb_hub *hub = usb_hub_to_struct_hub(hdev);
|
||||||
struct usb_interface *intf = to_usb_interface(hub->intfdev);
|
struct usb_interface *intf = to_usb_interface(dev->parent);
|
||||||
int port1 = port_dev->portnum;
|
int port1 = port_dev->portnum;
|
||||||
bool disabled;
|
bool disabled;
|
||||||
int rc;
|
int rc;
|
||||||
struct kernfs_node *kn;
|
struct kernfs_node *kn;
|
||||||
|
|
||||||
|
if (!hub)
|
||||||
|
return -ENODEV;
|
||||||
rc = kstrtobool(buf, &disabled);
|
rc = kstrtobool(buf, &disabled);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -104,6 +104,27 @@ static int dwc3_get_dr_mode(struct dwc3 *dwc)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dwc3_enable_susphy(struct dwc3 *dwc, bool enable)
|
||||||
|
{
|
||||||
|
u32 reg;
|
||||||
|
|
||||||
|
reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
|
||||||
|
if (enable && !dwc->dis_u3_susphy_quirk)
|
||||||
|
reg |= DWC3_GUSB3PIPECTL_SUSPHY;
|
||||||
|
else
|
||||||
|
reg &= ~DWC3_GUSB3PIPECTL_SUSPHY;
|
||||||
|
|
||||||
|
dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
|
||||||
|
|
||||||
|
reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
|
||||||
|
if (enable && !dwc->dis_u2_susphy_quirk)
|
||||||
|
reg |= DWC3_GUSB2PHYCFG_SUSPHY;
|
||||||
|
else
|
||||||
|
reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
|
||||||
|
|
||||||
|
dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
|
||||||
|
}
|
||||||
|
|
||||||
void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode)
|
void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode)
|
||||||
{
|
{
|
||||||
u32 reg;
|
u32 reg;
|
||||||
@ -585,11 +606,8 @@ static int dwc3_core_ulpi_init(struct dwc3 *dwc)
|
|||||||
*/
|
*/
|
||||||
static int dwc3_phy_setup(struct dwc3 *dwc)
|
static int dwc3_phy_setup(struct dwc3 *dwc)
|
||||||
{
|
{
|
||||||
unsigned int hw_mode;
|
|
||||||
u32 reg;
|
u32 reg;
|
||||||
|
|
||||||
hw_mode = DWC3_GHWPARAMS0_MODE(dwc->hwparams.hwparams0);
|
|
||||||
|
|
||||||
reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
|
reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -599,20 +617,15 @@ static int dwc3_phy_setup(struct dwc3 *dwc)
|
|||||||
reg &= ~DWC3_GUSB3PIPECTL_UX_EXIT_PX;
|
reg &= ~DWC3_GUSB3PIPECTL_UX_EXIT_PX;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Above 1.94a, it is recommended to set DWC3_GUSB3PIPECTL_SUSPHY
|
* Above DWC_usb3.0 1.94a, it is recommended to set
|
||||||
* to '0' during coreConsultant configuration. So default value
|
* DWC3_GUSB3PIPECTL_SUSPHY to '0' during coreConsultant configuration.
|
||||||
* will be '0' when the core is reset. Application needs to set it
|
* So default value will be '0' when the core is reset. Application
|
||||||
* to '1' after the core initialization is completed.
|
* needs to set it to '1' after the core initialization is completed.
|
||||||
|
*
|
||||||
|
* Similarly for DRD controllers, GUSB3PIPECTL.SUSPENDENABLE must be
|
||||||
|
* cleared after power-on reset, and it can be set after core
|
||||||
|
* initialization.
|
||||||
*/
|
*/
|
||||||
if (!DWC3_VER_IS_WITHIN(DWC3, ANY, 194A))
|
|
||||||
reg |= DWC3_GUSB3PIPECTL_SUSPHY;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* For DRD controllers, GUSB3PIPECTL.SUSPENDENABLE must be cleared after
|
|
||||||
* power-on reset, and it can be set after core initialization, which is
|
|
||||||
* after device soft-reset during initialization.
|
|
||||||
*/
|
|
||||||
if (hw_mode == DWC3_GHWPARAMS0_MODE_DRD)
|
|
||||||
reg &= ~DWC3_GUSB3PIPECTL_SUSPHY;
|
reg &= ~DWC3_GUSB3PIPECTL_SUSPHY;
|
||||||
|
|
||||||
if (dwc->u2ss_inp3_quirk)
|
if (dwc->u2ss_inp3_quirk)
|
||||||
@ -639,9 +652,6 @@ static int dwc3_phy_setup(struct dwc3 *dwc)
|
|||||||
if (dwc->tx_de_emphasis_quirk)
|
if (dwc->tx_de_emphasis_quirk)
|
||||||
reg |= DWC3_GUSB3PIPECTL_TX_DEEPH(dwc->tx_de_emphasis);
|
reg |= DWC3_GUSB3PIPECTL_TX_DEEPH(dwc->tx_de_emphasis);
|
||||||
|
|
||||||
if (dwc->dis_u3_susphy_quirk)
|
|
||||||
reg &= ~DWC3_GUSB3PIPECTL_SUSPHY;
|
|
||||||
|
|
||||||
if (dwc->dis_del_phy_power_chg_quirk)
|
if (dwc->dis_del_phy_power_chg_quirk)
|
||||||
reg &= ~DWC3_GUSB3PIPECTL_DEPOCHANGE;
|
reg &= ~DWC3_GUSB3PIPECTL_DEPOCHANGE;
|
||||||
|
|
||||||
@ -689,23 +699,14 @@ static int dwc3_phy_setup(struct dwc3 *dwc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Above 1.94a, it is recommended to set DWC3_GUSB2PHYCFG_SUSPHY to
|
* Above DWC_usb3.0 1.94a, it is recommended to set
|
||||||
* '0' during coreConsultant configuration. So default value will
|
* DWC3_GUSB2PHYCFG_SUSPHY to '0' during coreConsultant configuration.
|
||||||
* be '0' when the core is reset. Application needs to set it to
|
* So default value will be '0' when the core is reset. Application
|
||||||
* '1' after the core initialization is completed.
|
* needs to set it to '1' after the core initialization is completed.
|
||||||
|
*
|
||||||
|
* Similarly for DRD controllers, GUSB2PHYCFG.SUSPHY must be cleared
|
||||||
|
* after power-on reset, and it can be set after core initialization.
|
||||||
*/
|
*/
|
||||||
if (!DWC3_VER_IS_WITHIN(DWC3, ANY, 194A))
|
|
||||||
reg |= DWC3_GUSB2PHYCFG_SUSPHY;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* For DRD controllers, GUSB2PHYCFG.SUSPHY must be cleared after
|
|
||||||
* power-on reset, and it can be set after core initialization, which is
|
|
||||||
* after device soft-reset during initialization.
|
|
||||||
*/
|
|
||||||
if (hw_mode == DWC3_GHWPARAMS0_MODE_DRD)
|
|
||||||
reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
|
|
||||||
|
|
||||||
if (dwc->dis_u2_susphy_quirk)
|
|
||||||
reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
|
reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
|
||||||
|
|
||||||
if (dwc->dis_enblslpm_quirk)
|
if (dwc->dis_enblslpm_quirk)
|
||||||
@ -1227,21 +1228,6 @@ static int dwc3_core_init(struct dwc3 *dwc)
|
|||||||
if (ret)
|
if (ret)
|
||||||
goto err_exit_phy;
|
goto err_exit_phy;
|
||||||
|
|
||||||
if (hw_mode == DWC3_GHWPARAMS0_MODE_DRD &&
|
|
||||||
!DWC3_VER_IS_WITHIN(DWC3, ANY, 194A)) {
|
|
||||||
if (!dwc->dis_u3_susphy_quirk) {
|
|
||||||
reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
|
|
||||||
reg |= DWC3_GUSB3PIPECTL_SUSPHY;
|
|
||||||
dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!dwc->dis_u2_susphy_quirk) {
|
|
||||||
reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
|
|
||||||
reg |= DWC3_GUSB2PHYCFG_SUSPHY;
|
|
||||||
dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dwc3_core_setup_global_control(dwc);
|
dwc3_core_setup_global_control(dwc);
|
||||||
dwc3_core_num_eps(dwc);
|
dwc3_core_num_eps(dwc);
|
||||||
|
|
||||||
|
@ -1580,6 +1580,7 @@ int dwc3_event_buffers_setup(struct dwc3 *dwc);
|
|||||||
void dwc3_event_buffers_cleanup(struct dwc3 *dwc);
|
void dwc3_event_buffers_cleanup(struct dwc3 *dwc);
|
||||||
|
|
||||||
int dwc3_core_soft_reset(struct dwc3 *dwc);
|
int dwc3_core_soft_reset(struct dwc3 *dwc);
|
||||||
|
void dwc3_enable_susphy(struct dwc3 *dwc, bool enable);
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_USB_DWC3_HOST) || IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)
|
#if IS_ENABLED(CONFIG_USB_DWC3_HOST) || IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)
|
||||||
int dwc3_host_init(struct dwc3 *dwc);
|
int dwc3_host_init(struct dwc3 *dwc);
|
||||||
|
@ -2924,6 +2924,7 @@ static int __dwc3_gadget_start(struct dwc3 *dwc)
|
|||||||
dwc3_ep0_out_start(dwc);
|
dwc3_ep0_out_start(dwc);
|
||||||
|
|
||||||
dwc3_gadget_enable_irq(dwc);
|
dwc3_gadget_enable_irq(dwc);
|
||||||
|
dwc3_enable_susphy(dwc, true);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -4690,6 +4691,7 @@ void dwc3_gadget_exit(struct dwc3 *dwc)
|
|||||||
if (!dwc->gadget)
|
if (!dwc->gadget)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
dwc3_enable_susphy(dwc, false);
|
||||||
usb_del_gadget(dwc->gadget);
|
usb_del_gadget(dwc->gadget);
|
||||||
dwc3_gadget_free_endpoints(dwc);
|
dwc3_gadget_free_endpoints(dwc);
|
||||||
usb_put_gadget(dwc->gadget);
|
usb_put_gadget(dwc->gadget);
|
||||||
|
@ -10,10 +10,13 @@
|
|||||||
#include <linux/irq.h>
|
#include <linux/irq.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/usb.h>
|
||||||
|
#include <linux/usb/hcd.h>
|
||||||
|
|
||||||
#include "../host/xhci-port.h"
|
#include "../host/xhci-port.h"
|
||||||
#include "../host/xhci-ext-caps.h"
|
#include "../host/xhci-ext-caps.h"
|
||||||
#include "../host/xhci-caps.h"
|
#include "../host/xhci-caps.h"
|
||||||
|
#include "../host/xhci-plat.h"
|
||||||
#include "core.h"
|
#include "core.h"
|
||||||
|
|
||||||
#define XHCI_HCSPARAMS1 0x4
|
#define XHCI_HCSPARAMS1 0x4
|
||||||
@ -57,6 +60,24 @@ static void dwc3_power_off_all_roothub_ports(struct dwc3 *dwc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void dwc3_xhci_plat_start(struct usb_hcd *hcd)
|
||||||
|
{
|
||||||
|
struct platform_device *pdev;
|
||||||
|
struct dwc3 *dwc;
|
||||||
|
|
||||||
|
if (!usb_hcd_is_primary_hcd(hcd))
|
||||||
|
return;
|
||||||
|
|
||||||
|
pdev = to_platform_device(hcd->self.controller);
|
||||||
|
dwc = dev_get_drvdata(pdev->dev.parent);
|
||||||
|
|
||||||
|
dwc3_enable_susphy(dwc, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct xhci_plat_priv dwc3_xhci_plat_quirk = {
|
||||||
|
.plat_start = dwc3_xhci_plat_start,
|
||||||
|
};
|
||||||
|
|
||||||
static void dwc3_host_fill_xhci_irq_res(struct dwc3 *dwc,
|
static void dwc3_host_fill_xhci_irq_res(struct dwc3 *dwc,
|
||||||
int irq, char *name)
|
int irq, char *name)
|
||||||
{
|
{
|
||||||
@ -167,6 +188,11 @@ int dwc3_host_init(struct dwc3 *dwc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = platform_device_add_data(xhci, &dwc3_xhci_plat_quirk,
|
||||||
|
sizeof(struct xhci_plat_priv));
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
|
||||||
ret = platform_device_add(xhci);
|
ret = platform_device_add(xhci);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(dwc->dev, "failed to register xHCI device\n");
|
dev_err(dwc->dev, "failed to register xHCI device\n");
|
||||||
@ -192,6 +218,7 @@ void dwc3_host_exit(struct dwc3 *dwc)
|
|||||||
if (dwc->sys_wakeup)
|
if (dwc->sys_wakeup)
|
||||||
device_init_wakeup(&dwc->xhci->dev, false);
|
device_init_wakeup(&dwc->xhci->dev, false);
|
||||||
|
|
||||||
|
dwc3_enable_susphy(dwc, false);
|
||||||
platform_device_unregister(dwc->xhci);
|
platform_device_unregister(dwc->xhci);
|
||||||
dwc->xhci = NULL;
|
dwc->xhci = NULL;
|
||||||
}
|
}
|
||||||
|
@ -2112,7 +2112,7 @@ unknown:
|
|||||||
buf[5] = 0x01;
|
buf[5] = 0x01;
|
||||||
switch (ctrl->bRequestType & USB_RECIP_MASK) {
|
switch (ctrl->bRequestType & USB_RECIP_MASK) {
|
||||||
case USB_RECIP_DEVICE:
|
case USB_RECIP_DEVICE:
|
||||||
if (w_index != 0x4 || (w_value >> 8))
|
if (w_index != 0x4 || (w_value & 0xff))
|
||||||
break;
|
break;
|
||||||
buf[6] = w_index;
|
buf[6] = w_index;
|
||||||
/* Number of ext compat interfaces */
|
/* Number of ext compat interfaces */
|
||||||
@ -2128,9 +2128,9 @@ unknown:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case USB_RECIP_INTERFACE:
|
case USB_RECIP_INTERFACE:
|
||||||
if (w_index != 0x5 || (w_value >> 8))
|
if (w_index != 0x5 || (w_value & 0xff))
|
||||||
break;
|
break;
|
||||||
interface = w_value & 0xFF;
|
interface = w_value >> 8;
|
||||||
if (interface >= MAX_CONFIG_INTERFACES ||
|
if (interface >= MAX_CONFIG_INTERFACES ||
|
||||||
!os_desc_cfg->interface[interface])
|
!os_desc_cfg->interface[interface])
|
||||||
break;
|
break;
|
||||||
|
@ -852,6 +852,7 @@ static void ffs_user_copy_worker(struct work_struct *work)
|
|||||||
work);
|
work);
|
||||||
int ret = io_data->status;
|
int ret = io_data->status;
|
||||||
bool kiocb_has_eventfd = io_data->kiocb->ki_flags & IOCB_EVENTFD;
|
bool kiocb_has_eventfd = io_data->kiocb->ki_flags & IOCB_EVENTFD;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
if (io_data->read && ret > 0) {
|
if (io_data->read && ret > 0) {
|
||||||
kthread_use_mm(io_data->mm);
|
kthread_use_mm(io_data->mm);
|
||||||
@ -864,6 +865,11 @@ static void ffs_user_copy_worker(struct work_struct *work)
|
|||||||
if (io_data->ffs->ffs_eventfd && !kiocb_has_eventfd)
|
if (io_data->ffs->ffs_eventfd && !kiocb_has_eventfd)
|
||||||
eventfd_signal(io_data->ffs->ffs_eventfd);
|
eventfd_signal(io_data->ffs->ffs_eventfd);
|
||||||
|
|
||||||
|
spin_lock_irqsave(&io_data->ffs->eps_lock, flags);
|
||||||
|
usb_ep_free_request(io_data->ep, io_data->req);
|
||||||
|
io_data->req = NULL;
|
||||||
|
spin_unlock_irqrestore(&io_data->ffs->eps_lock, flags);
|
||||||
|
|
||||||
if (io_data->read)
|
if (io_data->read)
|
||||||
kfree(io_data->to_free);
|
kfree(io_data->to_free);
|
||||||
ffs_free_buffer(io_data);
|
ffs_free_buffer(io_data);
|
||||||
@ -877,7 +883,6 @@ static void ffs_epfile_async_io_complete(struct usb_ep *_ep,
|
|||||||
struct ffs_data *ffs = io_data->ffs;
|
struct ffs_data *ffs = io_data->ffs;
|
||||||
|
|
||||||
io_data->status = req->status ? req->status : req->actual;
|
io_data->status = req->status ? req->status : req->actual;
|
||||||
usb_ep_free_request(_ep, req);
|
|
||||||
|
|
||||||
INIT_WORK(&io_data->work, ffs_user_copy_worker);
|
INIT_WORK(&io_data->work, ffs_user_copy_worker);
|
||||||
queue_work(ffs->io_completion_wq, &io_data->work);
|
queue_work(ffs->io_completion_wq, &io_data->work);
|
||||||
@ -3806,7 +3811,7 @@ static int ffs_func_setup(struct usb_function *f,
|
|||||||
__ffs_event_add(ffs, FUNCTIONFS_SETUP);
|
__ffs_event_add(ffs, FUNCTIONFS_SETUP);
|
||||||
spin_unlock_irqrestore(&ffs->ev.waitq.lock, flags);
|
spin_unlock_irqrestore(&ffs->ev.waitq.lock, flags);
|
||||||
|
|
||||||
return creq->wLength == 0 ? USB_GADGET_DELAYED_STATUS : 0;
|
return ffs->ev.setup.wLength == 0 ? USB_GADGET_DELAYED_STATUS : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ffs_func_req_match(struct usb_function *f,
|
static bool ffs_func_req_match(struct usb_function *f,
|
||||||
|
@ -92,10 +92,10 @@ static int __uvcg_iter_item_entries(const char *page, size_t len,
|
|||||||
|
|
||||||
while (pg - page < len) {
|
while (pg - page < len) {
|
||||||
i = 0;
|
i = 0;
|
||||||
while (i < sizeof(buf) && (pg - page < len) &&
|
while (i < bufsize && (pg - page < len) &&
|
||||||
*pg != '\0' && *pg != '\n')
|
*pg != '\0' && *pg != '\n')
|
||||||
buf[i++] = *pg++;
|
buf[i++] = *pg++;
|
||||||
if (i == sizeof(buf)) {
|
if (i == bufsize) {
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto out_free_buf;
|
goto out_free_buf;
|
||||||
}
|
}
|
||||||
|
@ -888,6 +888,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
|
|||||||
/* Check for an all 1's result which is a typical consequence
|
/* Check for an all 1's result which is a typical consequence
|
||||||
* of dead, unclocked, or unplugged (CardBus...) devices
|
* of dead, unclocked, or unplugged (CardBus...) devices
|
||||||
*/
|
*/
|
||||||
|
again:
|
||||||
if (ints == ~(u32)0) {
|
if (ints == ~(u32)0) {
|
||||||
ohci->rh_state = OHCI_RH_HALTED;
|
ohci->rh_state = OHCI_RH_HALTED;
|
||||||
ohci_dbg (ohci, "device removed!\n");
|
ohci_dbg (ohci, "device removed!\n");
|
||||||
@ -982,6 +983,13 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
|
|||||||
}
|
}
|
||||||
spin_unlock(&ohci->lock);
|
spin_unlock(&ohci->lock);
|
||||||
|
|
||||||
|
/* repeat until all enabled interrupts are handled */
|
||||||
|
if (ohci->rh_state != OHCI_RH_HALTED) {
|
||||||
|
ints = ohci_readl(ohci, ®s->intrstatus);
|
||||||
|
if (ints && (ints & ohci_readl(ohci, ®s->intrenable)))
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,9 @@
|
|||||||
#ifndef _XHCI_PLAT_H
|
#ifndef _XHCI_PLAT_H
|
||||||
#define _XHCI_PLAT_H
|
#define _XHCI_PLAT_H
|
||||||
|
|
||||||
#include "xhci.h" /* for hcd_to_xhci() */
|
struct device;
|
||||||
|
struct platform_device;
|
||||||
|
struct usb_hcd;
|
||||||
|
|
||||||
struct xhci_plat_priv {
|
struct xhci_plat_priv {
|
||||||
const char *firmware_name;
|
const char *firmware_name;
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/usb/rzv2m_usb3drd.h>
|
#include <linux/usb/rzv2m_usb3drd.h>
|
||||||
|
#include "xhci.h"
|
||||||
#include "xhci-plat.h"
|
#include "xhci-plat.h"
|
||||||
#include "xhci-rzv2m.h"
|
#include "xhci-rzv2m.h"
|
||||||
|
|
||||||
|
@ -104,14 +104,18 @@ static int qcom_pmic_typec_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
ret = tcpm->port_start(tcpm, tcpm->tcpm_port);
|
ret = tcpm->port_start(tcpm, tcpm->tcpm_port);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto fwnode_remove;
|
goto port_unregister;
|
||||||
|
|
||||||
ret = tcpm->pdphy_start(tcpm, tcpm->tcpm_port);
|
ret = tcpm->pdphy_start(tcpm, tcpm->tcpm_port);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto fwnode_remove;
|
goto port_stop;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
port_stop:
|
||||||
|
tcpm->port_stop(tcpm);
|
||||||
|
port_unregister:
|
||||||
|
tcpm_unregister_port(tcpm->tcpm_port);
|
||||||
fwnode_remove:
|
fwnode_remove:
|
||||||
fwnode_remove_software_node(tcpm->tcpc.fwnode);
|
fwnode_remove_software_node(tcpm->tcpc.fwnode);
|
||||||
|
|
||||||
|
@ -475,10 +475,8 @@ static int qcom_pmic_typec_pdphy_enable(struct pmic_typec_pdphy *pmic_typec_pdph
|
|||||||
|
|
||||||
qcom_pmic_typec_pdphy_reset_off(pmic_typec_pdphy);
|
qcom_pmic_typec_pdphy_reset_off(pmic_typec_pdphy);
|
||||||
done:
|
done:
|
||||||
if (ret) {
|
if (ret)
|
||||||
regulator_disable(pmic_typec_pdphy->vdd_pdphy);
|
|
||||||
dev_err(dev, "pdphy_enable fail %d\n", ret);
|
dev_err(dev, "pdphy_enable fail %d\n", ret);
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -524,12 +522,17 @@ static int qcom_pmic_typec_pdphy_start(struct pmic_typec *tcpm,
|
|||||||
|
|
||||||
ret = pmic_typec_pdphy_reset(pmic_typec_pdphy);
|
ret = pmic_typec_pdphy_reset(pmic_typec_pdphy);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
goto err_disable_vdd_pdhy;
|
||||||
|
|
||||||
for (i = 0; i < pmic_typec_pdphy->nr_irqs; i++)
|
for (i = 0; i < pmic_typec_pdphy->nr_irqs; i++)
|
||||||
enable_irq(pmic_typec_pdphy->irq_data[i].irq);
|
enable_irq(pmic_typec_pdphy->irq_data[i].irq);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
err_disable_vdd_pdhy:
|
||||||
|
regulator_disable(pmic_typec_pdphy->vdd_pdphy);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void qcom_pmic_typec_pdphy_stop(struct pmic_typec *tcpm)
|
static void qcom_pmic_typec_pdphy_stop(struct pmic_typec *tcpm)
|
||||||
|
@ -1564,8 +1564,12 @@ static void tcpm_queue_vdm(struct tcpm_port *port, const u32 header,
|
|||||||
static void tcpm_queue_vdm_unlocked(struct tcpm_port *port, const u32 header,
|
static void tcpm_queue_vdm_unlocked(struct tcpm_port *port, const u32 header,
|
||||||
const u32 *data, int cnt, enum tcpm_transmit_type tx_sop_type)
|
const u32 *data, int cnt, enum tcpm_transmit_type tx_sop_type)
|
||||||
{
|
{
|
||||||
|
if (port->state != SRC_READY && port->state != SNK_READY &&
|
||||||
|
port->state != SRC_VDM_IDENTITY_REQUEST)
|
||||||
|
return;
|
||||||
|
|
||||||
mutex_lock(&port->lock);
|
mutex_lock(&port->lock);
|
||||||
tcpm_queue_vdm(port, header, data, cnt, TCPC_TX_SOP);
|
tcpm_queue_vdm(port, header, data, cnt, tx_sop_type);
|
||||||
mutex_unlock(&port->lock);
|
mutex_unlock(&port->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1580,6 +1584,7 @@ static void svdm_consume_identity(struct tcpm_port *port, const u32 *p, int cnt)
|
|||||||
port->partner_ident.cert_stat = p[VDO_INDEX_CSTAT];
|
port->partner_ident.cert_stat = p[VDO_INDEX_CSTAT];
|
||||||
port->partner_ident.product = product;
|
port->partner_ident.product = product;
|
||||||
|
|
||||||
|
if (port->partner)
|
||||||
typec_partner_set_identity(port->partner);
|
typec_partner_set_identity(port->partner);
|
||||||
|
|
||||||
tcpm_log(port, "Identity: %04x:%04x.%04x",
|
tcpm_log(port, "Identity: %04x:%04x.%04x",
|
||||||
@ -1742,6 +1747,9 @@ static void tcpm_register_partner_altmodes(struct tcpm_port *port)
|
|||||||
struct typec_altmode *altmode;
|
struct typec_altmode *altmode;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
if (!port->partner)
|
||||||
|
return;
|
||||||
|
|
||||||
for (i = 0; i < modep->altmodes; i++) {
|
for (i = 0; i < modep->altmodes; i++) {
|
||||||
altmode = typec_partner_register_altmode(port->partner,
|
altmode = typec_partner_register_altmode(port->partner,
|
||||||
&modep->altmode_desc[i]);
|
&modep->altmode_desc[i]);
|
||||||
@ -2996,7 +3004,7 @@ static int tcpm_register_source_caps(struct tcpm_port *port)
|
|||||||
{
|
{
|
||||||
struct usb_power_delivery_desc desc = { port->negotiated_rev };
|
struct usb_power_delivery_desc desc = { port->negotiated_rev };
|
||||||
struct usb_power_delivery_capabilities_desc caps = { };
|
struct usb_power_delivery_capabilities_desc caps = { };
|
||||||
struct usb_power_delivery_capabilities *cap;
|
struct usb_power_delivery_capabilities *cap = port->partner_source_caps;
|
||||||
|
|
||||||
if (!port->partner_pd)
|
if (!port->partner_pd)
|
||||||
port->partner_pd = usb_power_delivery_register(NULL, &desc);
|
port->partner_pd = usb_power_delivery_register(NULL, &desc);
|
||||||
@ -3006,6 +3014,9 @@ static int tcpm_register_source_caps(struct tcpm_port *port)
|
|||||||
memcpy(caps.pdo, port->source_caps, sizeof(u32) * port->nr_source_caps);
|
memcpy(caps.pdo, port->source_caps, sizeof(u32) * port->nr_source_caps);
|
||||||
caps.role = TYPEC_SOURCE;
|
caps.role = TYPEC_SOURCE;
|
||||||
|
|
||||||
|
if (cap)
|
||||||
|
usb_power_delivery_unregister_capabilities(cap);
|
||||||
|
|
||||||
cap = usb_power_delivery_register_capabilities(port->partner_pd, &caps);
|
cap = usb_power_delivery_register_capabilities(port->partner_pd, &caps);
|
||||||
if (IS_ERR(cap))
|
if (IS_ERR(cap))
|
||||||
return PTR_ERR(cap);
|
return PTR_ERR(cap);
|
||||||
@ -4231,7 +4242,10 @@ static int tcpm_init_vconn(struct tcpm_port *port)
|
|||||||
|
|
||||||
static void tcpm_typec_connect(struct tcpm_port *port)
|
static void tcpm_typec_connect(struct tcpm_port *port)
|
||||||
{
|
{
|
||||||
|
struct typec_partner *partner;
|
||||||
|
|
||||||
if (!port->connected) {
|
if (!port->connected) {
|
||||||
|
port->connected = true;
|
||||||
/* Make sure we don't report stale identity information */
|
/* Make sure we don't report stale identity information */
|
||||||
memset(&port->partner_ident, 0, sizeof(port->partner_ident));
|
memset(&port->partner_ident, 0, sizeof(port->partner_ident));
|
||||||
port->partner_desc.usb_pd = port->pd_capable;
|
port->partner_desc.usb_pd = port->pd_capable;
|
||||||
@ -4241,9 +4255,13 @@ static void tcpm_typec_connect(struct tcpm_port *port)
|
|||||||
port->partner_desc.accessory = TYPEC_ACCESSORY_AUDIO;
|
port->partner_desc.accessory = TYPEC_ACCESSORY_AUDIO;
|
||||||
else
|
else
|
||||||
port->partner_desc.accessory = TYPEC_ACCESSORY_NONE;
|
port->partner_desc.accessory = TYPEC_ACCESSORY_NONE;
|
||||||
port->partner = typec_register_partner(port->typec_port,
|
partner = typec_register_partner(port->typec_port, &port->partner_desc);
|
||||||
&port->partner_desc);
|
if (IS_ERR(partner)) {
|
||||||
port->connected = true;
|
dev_err(port->dev, "Failed to register partner (%ld)\n", PTR_ERR(partner));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
port->partner = partner;
|
||||||
typec_partner_set_usb_power_delivery(port->partner, port->partner_pd);
|
typec_partner_set_usb_power_delivery(port->partner, port->partner_pd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4323,9 +4341,11 @@ static void tcpm_typec_disconnect(struct tcpm_port *port)
|
|||||||
port->plug_prime = NULL;
|
port->plug_prime = NULL;
|
||||||
port->cable = NULL;
|
port->cable = NULL;
|
||||||
if (port->connected) {
|
if (port->connected) {
|
||||||
|
if (port->partner) {
|
||||||
typec_partner_set_usb_power_delivery(port->partner, NULL);
|
typec_partner_set_usb_power_delivery(port->partner, NULL);
|
||||||
typec_unregister_partner(port->partner);
|
typec_unregister_partner(port->partner);
|
||||||
port->partner = NULL;
|
port->partner = NULL;
|
||||||
|
}
|
||||||
port->connected = false;
|
port->connected = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4549,6 +4569,9 @@ static enum typec_cc_status tcpm_pwr_opmode_to_rp(enum typec_pwr_opmode opmode)
|
|||||||
|
|
||||||
static void tcpm_set_initial_svdm_version(struct tcpm_port *port)
|
static void tcpm_set_initial_svdm_version(struct tcpm_port *port)
|
||||||
{
|
{
|
||||||
|
if (!port->partner)
|
||||||
|
return;
|
||||||
|
|
||||||
switch (port->negotiated_rev) {
|
switch (port->negotiated_rev) {
|
||||||
case PD_REV30:
|
case PD_REV30:
|
||||||
break;
|
break;
|
||||||
@ -5605,6 +5628,7 @@ static void run_state_machine(struct tcpm_port *port)
|
|||||||
break;
|
break;
|
||||||
case PORT_RESET:
|
case PORT_RESET:
|
||||||
tcpm_reset_port(port);
|
tcpm_reset_port(port);
|
||||||
|
port->pd_events = 0;
|
||||||
if (port->self_powered)
|
if (port->self_powered)
|
||||||
tcpm_set_cc(port, TYPEC_CC_OPEN);
|
tcpm_set_cc(port, TYPEC_CC_OPEN);
|
||||||
else
|
else
|
||||||
|
Loading…
x
Reference in New Issue
Block a user